Compare commits

..
34 Commits
Author SHA1 Message Date
dadus33 fff868cf25 Changed version string. 2016-10-23 16:37:15 +03:00
LongLiveVladerius@gmail.com 51b91b3c3d Merge remote-tracking branch 'origin/master' 2016-10-23 16:36:08 +03:00
LongLiveVladerius@gmail.com a20ed832f4 Fixed error when using item names with dollar sign or backslash. 2016-10-23 16:36:02 +03:00
dadus33 4ebbdc1c64 Updated README.MD 2016-10-19 18:26:24 +03:00
LongLiveVladerius@gmail.com f0eb998f23 Merge remote-tracking branch 'origin/master' 2016-10-19 18:19:56 +03:00
dadus33 f1590c5098 Added travis. 2016-10-19 18:19:50 +03:00
dadus33 30aeb8882b Updated README.MD 2016-10-19 18:14:27 +03:00
dadus33 8b2803d752 Merge pull request #1 from Shynixn/master
Changed custom config handling to bukkit.
2016-10-19 18:07:15 +03:00
Shynixn 6d2c5907c1 Changed custom config handling to bukkit. 2016-10-18 17:26:45 +02:00
dadus33 a5a81f2360 Fixed config bug. 2016-10-17 19:15:42 +03:00
LongLiveVladerius@gmail.com f14a1660b5 Added compatibility with 1.7.X. Fixed DeluxeChat's and possibly other plugins' bugs by changing listener priority to LOWEST. 2016-10-14 18:05:47 +03:00
dadus33 f07f3edc3b Added compatibility with 1.7.X. Fixed DeluxeChat's and possibly other plugins' bugs by changing listener priority to LOWEST. 2016-10-14 15:21:52 +03:00
dadus33 c18118f846 Fixed console message bug. Added log4j. 2016-10-12 18:41:32 +03:00
LongLiveVladerius@gmail.com f1e6291e76 Fixed Item not displaying to user who sent it (using commands). Added commands feature. 2016-10-10 22:55:38 +03:00
LongLiveVladerius@gmail.com 97d28fe0f0 Updated way of getting player from packet and fixed translations. 2016-10-09 19:41:50 +03:00
LongLiveVladerius@gmail.com 7093fa2761 Updated config version. 2016-10-09 19:40:03 +03:00
LongLiveVladerius@gmail.com ce68890877 Updated config version. 2016-10-09 00:01:19 +03:00
dadus33 3a71045feb Updated config version. 2016-10-08 22:53:37 +03:00
LongLiveVladerius@gmail.com 4db713d93b Merge remote-tracking branch 'origin/master' 2016-10-08 22:49:37 +03:00
dadus33 910179326a Fixed translations feature. Added Metrics. 2016-10-08 22:49:32 +03:00
LongLiveVladerius@gmail.com 856c6decb2 Merge remote-tracking branch 'origin/master' 2016-10-08 22:45:13 +03:00
dadus33 d4c8b36ac6 Fixed translations feature. Added Metrics. 2016-10-08 22:45:08 +03:00
dadus33 0318246403 Fixed translations feature. Added Metrics. 2016-10-08 22:43:30 +03:00
LongLiveVladerius@gmail.com b38e62b138 Merge remote-tracking branch 'origin/master' 2016-10-08 20:16:06 +03:00
dadus33 bd62322adf Fixed bugged display of items (seemed to be random) 2016-10-08 20:15:45 +03:00
LongLiveVladerius@gmail.com 803b49c2ac Fixed bugged display of items (seemed to be random) 2016-10-08 20:11:19 +03:00
LongLiveVladerius@gmail.com 68c749c9d2 Fixed item display-name not showing in chat. 2016-10-07 17:01:36 +03:00
LongLiveVladerius@gmail.com 27def17f8a Attempt to fix messages sending different for each player. 2016-10-06 07:48:16 +03:00
dadus33 2b27cbbf64 Fixed parser not searching deep enough 2016-10-05 14:27:53 +03:00
dadus33 39a5fdb611 Added cooldown settings to config 2016-10-04 21:27:58 +03:00
LongLiveVladerius@gmail.com 7e961dc8ee Removed .idea 2016-10-04 21:09:17 +03:00
dadus33 ccbe90f7ee Create .gitignore 2016-10-04 20:54:52 +03:00
dadus33 ce6da93c57 Initial commit. 2016-10-04 18:49:59 +03:00
dadus33 2e8379dec9 Initial commit 2016-09-30 18:45:28 +03:00
82 changed files with 1060 additions and 7238 deletions

No files matched your search

-30
View File
@@ -1,30 +0,0 @@
name: Build v2 for PR
on:
pull_request:
branches: [ v2 ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
name: Checkout repo
- name: Set up JDK 17 (LTS)
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'
cache: maven
- name: Build with Maven
run: mvn install --file pom.xml
- uses: actions/upload-artifact@v2
name: Upload Artifact
with:
name: ChatItem.jar
path: target/ChatItem-*.jar
-36
View File
@@ -1,36 +0,0 @@
name: Build v2
on:
push:
branches: [ v2 ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
name: Checkout repo
- name: Set up JDK 17 (LTS)
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'adopt'
cache: maven
- name: Build with Maven
run: mvn install --file pom.xml
- uses: actions/upload-artifact@v2
name: Upload Artifact
with:
name: ChatItem.jar
path: target/ChatItem-*.jar
- name: Send file README.md to discord channel
uses: sinshutu/upload-to-discord@master
env:
DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }}
with:
args: target/ChatItem-*.jar
-5
View File
@@ -1,9 +1,4 @@
.idea/
src/test/
bin/
target/
*.iml
dependency-reduced-pom.xml
.classpath
.project
.settings/
+1 -2
View File
@@ -1,2 +1 @@
language: java
script: "mvn clean package -DskipTests"
language: java
+1 -1
View File
@@ -1,4 +1,4 @@
# ChatItem [![Build Status](https://travis-ci.org/dadus33/ChatItem.svg?branch=master)](https://travis-ci.org/dadus33/ChatItem) [![Help Chat](https://img.shields.io/badge/chat-on_discord-7289da.svg)](https://discord.gg/eQJbVJt)
# ChatItem [![Build Status](https://travis-ci.org/dadus33/ChatItem.svg?branch=master)](https://travis-ci.org/dadus33/ChatItem)
The official repository of the ChatItem Spigot/Bukkit plugin.
# Building
Building this is simple as we use Maven.
+42 -147
View File
@@ -5,159 +5,72 @@
<modelVersion>4.0.0</modelVersion>
<groupId>me.dadus33</groupId>
<artifactId>chatitem</artifactId>
<version>2.4.2</version>
<artifactId>ChatItem</artifactId>
<version>1.2.0</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<repositories>
<repository>
<id>Bungeecord</id>
<url>https://repo.md-5.net/content/groups/public/</url>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
<repository>
<id>sonatype</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<id>dmulloy2-repo</id>
<url>http://repo.dmulloy2.net/content/groups/public/</url>
</repository>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>lang-utils-repo</id>
<url>https://raw.github.com/MascusJeoraly/LanguageUtils/mvn-repo/</url>
</repository>
<repository>
<id>protocollib-repo</id>
<url>https://repo.dmulloy2.net/nexus/repository/public/</url>
<id>Plugin Metrics</id>
<url>http://repo.mcstats.org/content/repositories/public</url>
</repository>
<repository>
<id>viaversion-repo</id>
<url>https://repo.viaversion.com</url>
</repository>
<repository>
<id>elikill-repo</id>
<url>https://repo.eliapp.fr:8081/repository/internal/</url>
</repository>
<repository>
<id>dv8tion</id>
<url>https://m2.dv8tion.net/releases</url>
</repository>
<repository>
<id>Scarsz-Nexus</id>
<url>https://nexus.scarsz.me/content/groups/public/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.17-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>minecraft-server</artifactId>
<version>1.7.10</version>
<type>jar</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.17.2</version>
<version>1.10-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.17.2</version>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>1.10-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>3.6.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.meowj</groupId>
<artifactId>LangUtils</artifactId>
<version>1.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.comphenix.protocol</groupId>
<artifactId>ProtocolLib</artifactId>
<version>5.0.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>us.myles</groupId>
<artifactId>viaversion</artifactId>
<version>3.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.shevchik</groupId>
<artifactId>ProtocolSupport</artifactId>
<version>1.18.2-1-dev</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.53.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.github.GeyserMC</groupId>
<artifactId>opennbt</artifactId>
<version>1.4</version>
<version>2.7</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>dev.majek</groupId>
<artifactId>HexNicks</artifactId>
<version>2.2.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-api</artifactId>
<version>4.11.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>adventure-platform-bungeecord</artifactId>
<version>4.1.0</version>
<groupId>org.mcstats.bukkit</groupId>
<artifactId>metrics-lite</artifactId>
<version>R8-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.discordsrv</groupId>
<artifactId>discordsrv</artifactId>
<version>1.25.1</version>
<scope>provided</scope>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>com.willfp</groupId>
<artifactId>EcoEnchants</artifactId>
<version>8.57.2</version>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<finalName>ChatItem-${project.version}</finalName>
<directory>./target</directory>
<resources>
<resource>
@@ -170,20 +83,29 @@
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<outputDirectory>${dir}</outputDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0</version>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
@@ -191,44 +113,17 @@
<goal>shade</goal>
</goals>
<configuration>
<minimizeJar>true</minimizeJar>
<relocations>
<relocation>
<pattern>com.google.gson</pattern>
<shadedPattern>me.dadus33.libs.gson</shadedPattern>
</relocation>
<relocation>
<pattern>net.kyori.adventure.text.serializer.bungeecord</pattern>
<shadedPattern>me.dadus33.libs.kyori.serializer.bungeecord</shadedPattern>
<shadedPattern>me.dadus33.gson</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>*</artifact>
<excludes>
<exclude>net.kyori:examination-api:**</exclude>
<exclude>net.kyori:examination-string:**</exclude>
<exclude>net.kyori:adventure-platform-api:**</exclude>
<exclude>net.kyori:adventure-text-serializer-legacy:**</exclude>
<exclude>net.kyori:adventure-text-serializer-gson:**</exclude>
<exclude>net.kyori:adventure-platform-facet:**</exclude>
<exclude>net.kyori:adventure-nbt:**</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<outputDirectory>${export_dir}</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
</project>
+78 -160
View File
@@ -1,199 +1,117 @@
package me.dadus33.chatitem;
import com.google.common.base.Strings;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v2.ChatListenerChatManager;
import me.dadus33.chatitem.commands.CIReloadCommand;
import me.dadus33.chatitem.commands.ChatItemCommand;
import com.comphenix.protocol.AsynchronousManager;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.async.AsyncListenerHandler;
import com.comphenix.protocol.events.ListenerPriority;
import me.dadus33.chatitem.commands.CIReload;
import me.dadus33.chatitem.filters.Log4jFilter;
import me.dadus33.chatitem.itemnamer.NamerManager;
import me.dadus33.chatitem.listeners.InventoryListener;
import me.dadus33.chatitem.listeners.JoinListener;
import me.dadus33.chatitem.playernamer.PlayerNamerManager;
import me.dadus33.chatitem.utils.SemVer;
import me.dadus33.chatitem.json.JSONManipulator;
import me.dadus33.chatitem.json.JSONManipulatorCurrent;
import me.dadus33.chatitem.listeners.ChatEventListener;
import me.dadus33.chatitem.listeners.ChatPacketListener;
import me.dadus33.chatitem.utils.General;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
import me.dadus33.chatitem.utils.Version;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandExecutor;
import org.bukkit.Server;
import org.bukkit.command.CommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import org.mcstats.MetricsLite;
import java.util.*;
import java.io.IOException;
import java.util.logging.Level;
public class ChatItem extends JavaPlugin {
public final static int CFG_VER = 13;
public static boolean discordSrvSupport = false, ecoEnchantsSupport = false, hasNewVersion = false;
public final static int CFG_VER = 4;
private static ChatItem instance;
private final String brandChannelName = Version.getVersion().isNewerOrEquals(Version.V1_13) ? "minecraft:brand" : "MC|Brand";
private final List<ChatManager> chatManager = new ArrayList<>();
private ChatEventListener chatEventListener;
private Log4jFilter filter;
private Storage storage;
private ProtocolManager pm;
private ChatPacketListener listener;
private static JSONManipulator manip;
public static boolean post17 = false;
public static void reload(CommandSender sender) {
ChatItem pl = getInstance();
if (pl.getConfig().getKeys(false).isEmpty())
pl.saveDefaultConfig();
pl.reloadConfig();
String oldChatManager = pl.storage.MANAGER;
pl.storage = new Storage(pl.getConfig());
pl.chooseManagers();
pl.filter.setStorage(pl.storage);
if (!pl.storage.RELOAD_MESSAGE.isEmpty())
sender.sendMessage(pl.storage.RELOAD_MESSAGE);
if (!oldChatManager.equalsIgnoreCase(pl.storage.MANAGER))
sender.sendMessage(ChatColor.GOLD + "Changing the manager with command reloading CAN produce issue. It's mostly suggested to restart after finding the better manager for you.");
ChatItem obj = getInstance();
obj.pm = ProtocolLibrary.getProtocolManager();
obj.saveDefaultConfig();
obj.reloadConfig();
obj.storage = new Storage(obj.getConfig());
General.init(obj.storage);
General.checkConfigVersion();
obj.listener.setStorage(obj.storage);
obj.chatEventListener.setStorage(obj.storage);
obj.filter.setStorage(obj.storage);
if (!obj.storage.RELOAD_MESSAGE.isEmpty())
sender.sendMessage(obj.storage.RELOAD_MESSAGE);
}
public static ChatItem getInstance() {
return instance;
}
public static void debug(String msg) {
if (getInstance().getStorage().DEBUG)
getInstance().getLogger().info("[Debug] " + msg.replace(ChatManager.SEPARATOR, 'S'));
}
private void chooseManagers() {
this.chatManager.forEach((cm) -> cm.unload(this));
this.chatManager.clear();
PluginManager pm = getServer().getPluginManager();
String managerName = getStorage().MANAGER;
switch (managerName.toLowerCase(Locale.ROOT)) {
case "both":
this.chatManager.add(new PacketEditingChatManager(this));
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
break;
case "auto":
if (getPluginThatRequirePacket().stream().map(pm::getPlugin).anyMatch(Objects::nonNull) && Version.getVersion().isNewerThan(Version.V1_7))
this.chatManager.add(new PacketEditingChatManager(this));
else
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager automatically chosen: " + getVisualChatManagers());
break;
case "packet":
this.chatManager.add(new PacketEditingChatManager(this));
getLogger().info("Manager chosen: " + getVisualChatManagers());
break;
case "chat":
this.chatManager.add(new ChatListenerChatManager(this));
getLogger().info("Manager chosen: " + getVisualChatManagers());
break;
default:
getLogger().severe("----- WARN -----");
getLogger().severe("Failed to find manager: " + managerName + ".");
getLogger().severe("Please reset your config and/or check wiki for more information");
getLogger().severe("Using default manager: chat.");
getLogger().severe("----- WARN -----");
this.chatManager.add(new ChatListenerChatManager(this));
break;
}
this.chatManager.forEach((cm) -> cm.load(this, getStorage()));
NamerManager.load(this);
PlayerNamerManager.load(this);
}
private List<String> getPluginThatRequirePacket() {
return Arrays.asList("DeluxeChat", "HexNicks", "VentureChat");
}
@Override
public void onEnable() {
//Save the instance (we're basically a singleton)
instance = this;
getLogger().info("Detected server version: " + Version.getVersion().name().toLowerCase());
//Load config
pm = ProtocolLibrary.getProtocolManager();
saveDefaultConfig();
storage = new Storage(getConfig());
General.init(storage);
General.checkConfigVersion();
listener = new ChatPacketListener(this, ListenerPriority.HIGHEST, storage, PacketType.Play.Server.CHAT);
AsynchronousManager am = pm.getAsynchronousManager();
AsyncListenerHandler packetListenerAsyncThread = am.registerAsyncHandler(listener);
packetListenerAsyncThread.start();
CIReload rld = new CIReload();
Bukkit.getPluginCommand("cireload").setExecutor(rld);
chatEventListener = new ChatEventListener(storage);
Bukkit.getPluginManager().registerEvents(chatEventListener, this);
if(isMc18OrLater()) {
post17 = true;
}
manip = new JSONManipulatorCurrent();
//Commands
loadCommand(getCommand("cireload"), new CIReloadCommand());
loadCommand(getCommand("chatitem"), new ChatItemCommand());
// events
PluginManager pm = getServer().getPluginManager();
pm.registerEvents(new JoinListener(), this);
pm.registerEvents(new InventoryListener(), this);
chooseManagers();
//Initialize Log4J filter (remove ugly console messages)
try {
MetricsLite metrics = new MetricsLite(this);
metrics.start();
} catch (IOException e) {
getLogger().log(Level.WARNING, ChatColor.RED + "Couldn't start metrics!");
}
filter = new Log4jFilter(storage);
}
StringJoiner plugins = new StringJoiner(", ");
if (pm.getPlugin("DiscordSRV") != null) {
discordSrvSupport = true;
plugins.add("DiscordSRV");
}
if (pm.getPlugin("EcoEnchants") != null) {
ecoEnchantsSupport = true;
plugins.add("EcoEnchants");
}
if(plugins.length() > 0)
getLogger().info("Load " + plugins.toString() + " support.");
public void onDisable() {
instance = null;
post17 = false;
}
getServer().getMessenger().registerIncomingPluginChannel(this, brandChannelName, (chan, p, msg) -> {
String client = new String(msg).substring(1);
ChatItem.debug("Detected client " + client + " for " + p.getName());
ItemPlayer.getPlayer(p).setClientName(client);
});
if (storage.CHECK_UPDATE) {
getServer().getScheduler().runTaskAsynchronously(this, () -> {
String urlName = "https://api.spigotmc.org/legacy/update.php?resource=19064";
String content = Utils.getFromURL(urlName);
if (Strings.isNullOrEmpty(content))
return;
SemVer currentVersion = SemVer.parse(getDescription().getVersion());
if (currentVersion == null)
return;
SemVer latestVersion = SemVer.parse(content);
if (latestVersion != null && latestVersion.isNewerThan(currentVersion)) {
hasNewVersion = !content.equalsIgnoreCase(getDescription().getVersion());
if (hasNewVersion) {
getLogger().info(storage.JOIN_UPDATE_MESSAGE);
}
}
});
private boolean isMc18OrLater(){
switch(getVersion(Bukkit.getServer())){
case "v1_8_R1": return true;
case "v1_8_R2": return true;
case "v1_8_R3": return true;
case "v1_9_R1": return true;
case "v1_9_R2": return true;
case "v1_10_R1": return true;
case "v1_10_R2": return true;
default: return false;
}
}
public void loadCommand(PluginCommand cmd, Object obj) {
if (obj instanceof CommandExecutor)
cmd.setExecutor((CommandExecutor) obj);
if (obj instanceof TabCompleter)
cmd.setTabCompleter((TabCompleter) obj);
private static String getVersion(Server server) {
final String packageName = server.getClass().getPackage().getName();
return packageName.substring(packageName.lastIndexOf('.') + 1);
}
public Storage getStorage() {
return storage;
}
public List<ChatManager> getChatManager() {
return chatManager;
}
public String getVisualChatManagers() {
StringJoiner sj = new StringJoiner(", ");
for (ChatManager cm : chatManager) {
sj.add(cm.getName() + " (" + cm.getId() + ")");
}
return sj.toString();
}
public boolean isHasNewVersion() {
return hasNewVersion;
public static JSONManipulator getManipulator(){
return manip;
}
}
@@ -1,83 +0,0 @@
package me.dadus33.chatitem;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playerversion.PlayerVersionManager;
import me.dadus33.chatitem.utils.Version;
public class ItemPlayer {
private static final ConcurrentHashMap<UUID, ItemPlayer> PLAYERS = new ConcurrentHashMap<>();
public static ItemPlayer getPlayer(Player p) {
return PLAYERS.computeIfAbsent(p.getUniqueId(), ItemPlayer::new);
}
public static ItemPlayer getPlayer(UUID uuid) {
return PLAYERS.computeIfAbsent(uuid, ItemPlayer::new);
}
private final UUID uuid;
private int protocolVersion = 0;
private Version version = null;
private String clientName = "unknow";
public ItemPlayer(UUID uuid) {
this.uuid = uuid;
Player p = Bukkit.getPlayer(uuid);
if(p != null)
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(p));
}
public UUID getUUID() {
return uuid;
}
public Player getPlayer() {
return Bukkit.getPlayer(uuid);
}
public String getClientName() {
return clientName;
}
public void setClientName(String clientName) {
this.clientName = clientName;
}
public int getProtocolVersion() {
if(protocolVersion == 0)
setProtocolVersion(PlayerVersionManager.getPlayerVersionAdapter().getProtocolVersion(getPlayer()));
return protocolVersion;
}
public void setProtocolVersion(int protocolVersion) {
this.protocolVersion = protocolVersion;
if(version == Version.getVersion()) {// if is default
version = Version.getVersion(protocolVersion);
ChatItem.debug("Detected version " + version.name() + " (protocol: " + protocolVersion + ")");
}
}
public Version getVersion() {
if(version == null)
setVersion(PlayerVersionManager.getPlayerVersionAdapter().getPlayerVersion(getPlayer()));
return version;
}
public void setVersion(Version version) {
this.version = version;
if(protocolVersion == 0)
this.protocolVersion = version.MAX_VER;
}
public boolean isBuggedClient() {
return getVersion().equals(Version.V1_7) && getClientName().toLowerCase().contains("lunarclient");
}
@Override
public String toString() {
return "ItemPlayer[uuid=" + uuid + ",name=" + (getPlayer() != null ? getPlayer().getName() : "-") + ",version=" + version.name() + ",protocol=" + protocolVersion + ",client=" + clientName + "]";
}
}
@@ -1,245 +0,0 @@
package me.dadus33.chatitem.chatmanager;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.hook.EcoEnchantsSupport;
import me.dadus33.chatitem.itemnamer.NamerManager;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Storage;
public abstract class ChatManager {
public final static HashMap<UUID, Long> COOLDOWNS = new HashMap<>();
public final static HashMap<UUID, Long> LAST_INFO_MESSAGE = new HashMap<>();
public final static String NAME = "{name}";
public final static String AMOUNT = "{amount}";
public final static String TIMES = "{times}";
public final static String LEFT = "{remaining}";
public final static char SEPARATOR = ((char) 0x0007);
public final static String SEPARATOR_STR = "\\u0007";
protected Storage s;
public ChatManager() {
}
public abstract String getName();
public abstract String getId();
public Storage getStorage() {
return s;
}
public void load(ChatItem pl, Storage s) {
this.s = s;
}
public abstract void unload(ChatItem pl);
/**
* Get the item in hand as usable one.<br>
* Will include, in lore, all informations from other plugins.
*
* @param p the player
* @return the usable item
*/
public static ItemStack getUsableItem(Player p) {
ItemStack item = HandItem.getBetterItem(p).clone();
if(ChatItem.ecoEnchantsSupport) {
List<String> addLore = EcoEnchantsSupport.getLores(item);
if(!addLore.isEmpty()) {
ItemMeta meta = item.getItemMeta();
List<String> lores = meta.hasLore() ? meta.getLore() : new ArrayList<>();
for(int i = 0; i < addLore.size(); i++)
lores.add(i, addLore.get(i));
meta.setLore(lores);
item.setItemMeta(meta);
}
}
return item;
}
/**
* Get the name of item according to player & config<br>
* Prefer use {@link #getNameOfItem(Player, ItemStack, Storage)} if you want take in count the empty item
*
* @param p the player
* @param item the item
* @param c the config
* @return the name of item
*/
public static String styleItem(Player p, ItemStack item, Storage c) {
String replacer = c.NAME_FORMAT;
String amount = c.AMOUNT_FORMAT;
boolean dname = item.hasItemMeta() && item.getItemMeta().hasDisplayName();
if (item.getAmount() == 1) {
if (c.FORCE_ADD_AMOUNT) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(item.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
if (dname) {
String trp = item.getItemMeta().getDisplayName();
if (c.COLOR_IF_ALREADY_COLORED) {
replacer = replacer.replace(NAME, ChatColor.stripColor(trp));
} else {
replacer = replacer.replace(NAME, trp);
}
} else {
replacer = replacer.replace(NAME, NamerManager.getName(p, item, c));
}
return replacer;
}
/**
* Get the name of item according to player & config
*
* @param p the player
* @param item the item
* @param c the config
* @return the name of item or hand
*/
public static String getNameOfItem(Player p, ItemStack item, Storage c) {
if(ItemUtils.isEmpty(item)) {
if(c.HAND_DISABLED)
return c.PLACEHOLDERS.get(0);
else
return c.HAND_NAME;
}
String replacer = c.NAME_FORMAT;
String amount = c.AMOUNT_FORMAT;
boolean dname = item.hasItemMeta() && item.getItemMeta().hasDisplayName();
if (item.getAmount() == 1) {
if (c.FORCE_ADD_AMOUNT) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(item.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
if (dname) {
String trp = item.getItemMeta().getDisplayName();
if (c.COLOR_IF_ALREADY_COLORED) {
replacer = replacer.replace(NAME, ChatColor.stripColor(trp));
} else {
replacer = replacer.replace(NAME, trp);
}
} else {
replacer = replacer.replace(NAME, NamerManager.getName(p, item, c));
}
return replacer;
}
public static String calculateTime(long seconds) {
Storage c = ChatItem.getInstance().getStorage();
if (seconds < 60) {
return seconds + c.SECONDS;
}
if (seconds < 3600) {
StringBuilder builder = new StringBuilder();
int minutes = (int) seconds / 60;
builder.append(minutes).append(c.MINUTES);
int secs = (int) seconds - minutes * 60;
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
}
return builder.toString();
}
StringBuilder builder = new StringBuilder();
int hours = (int) seconds / 3600;
builder.append(hours).append(c.HOURS);
int minutes = (int) (seconds / 60) - (hours * 60);
if (minutes != 0) {
builder.append(" ").append(minutes).append(c.MINUTES);
}
int secs = (int) (seconds - ((seconds / 60) * 60));
if (secs != 0) {
builder.append(" ").append(secs).append(c.SECONDS);
}
return builder.toString();
}
public static boolean canShowItem(Player p, ItemStack item, Cancellable e) {
Storage c = ChatItem.getInstance().getStorage();
if (c.PERMISSION_ENABLED && !p.hasPermission(c.PERMISSION_NAME)) {
if (!c.LET_MESSAGE_THROUGH) {
e.setCancelled(true);
}
if (!c.NO_PERMISSION_MESSAGE.isEmpty() && c.SHOW_NO_PERM_NORMAL) {
sendIfNeed(p, c.NO_PERMISSION_MESSAGE);
}
return false;
}
if (item.getType().equals(Material.AIR)) {
if (c.DENY_IF_NO_ITEM) {
e.setCancelled(true);
if (!c.DENY_MESSAGE.isEmpty())
sendIfNeed(p, c.DENY_MESSAGE);
return false;
}
if (c.HAND_DISABLED) {
return false;
}
}
if (c.COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
if (COOLDOWNS.containsKey(p.getUniqueId())) {
long start = COOLDOWNS.get(p.getUniqueId());
long current = System.currentTimeMillis() / 1000;
long elapsed = current - start;
if (elapsed >= c.COOLDOWN) {
COOLDOWNS.remove(p.getUniqueId());
} else {
if (!c.LET_MESSAGE_THROUGH) {
e.setCancelled(true);
}
if (!c.COOLDOWN_MESSAGE.isEmpty()) {
long left = (start + c.COOLDOWN) - current;
sendIfNeed(p, c.COOLDOWN_MESSAGE.replace(LEFT, ChatManager.calculateTime(left)));
}
ChatItem.debug("Cooldown");
return false;
}
}
}
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis()); // prevent showing item then send cooldown error message
return true;
}
private static void sendIfNeed(Player p, String msg) {
Long time = LAST_INFO_MESSAGE.remove(p.getUniqueId());
if(time != null) {
long diff = System.currentTimeMillis() - time;
if(diff < 100)
return; // don't show message
}
p.sendMessage(msg);
LAST_INFO_MESSAGE.put(p.getUniqueId(), System.currentTimeMillis());
}
public static void clear(Player p) {
COOLDOWNS.remove(p.getUniqueId());
LAST_INFO_MESSAGE.remove(p.getUniqueId());
}
}
@@ -1,22 +0,0 @@
package me.dadus33.chatitem.chatmanager;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Version;
public class HandItem {
@SuppressWarnings("deprecation")
public static ItemStack getBetterItem(Player p) {
if(Version.getVersion().isNewerOrEquals(Version.V1_9)) {
ItemStack main = p.getInventory().getItemInMainHand();
if(!ItemUtils.isEmpty(main))
return main;
ItemStack off = p.getInventory().getItemInOffHand();
return ItemUtils.isEmpty(off) ? main : off;
}
return p.getItemInHand();
}
}
@@ -1,69 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.json.JSONManipulatorCurrent;
import me.dadus33.chatitem.chatmanager.v1.listeners.ChatEventListener;
import me.dadus33.chatitem.chatmanager.v1.listeners.ChatPacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacketManager;
import me.dadus33.chatitem.utils.Storage;
public class PacketEditingChatManager extends ChatManager {
private final JSONManipulatorCurrent jsonManipulator;
private boolean baseComponentAvailable = true;
private final ChatItemPacketManager packetManager;
private final ChatEventListener chatEventListener;
private final ChatPacketManager chatPacketManager;
public PacketEditingChatManager(ChatItem pl) {
jsonManipulator = new JSONManipulatorCurrent();
packetManager = new ChatItemPacketManager(pl);
chatEventListener = new ChatEventListener(this);
chatPacketManager = new ChatPacketManager(this);
//Check for existence of BaseComponent class (only on spigot)
try {
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
} catch (ClassNotFoundException e) {
baseComponentAvailable = false;
}
}
@Override
public String getName() {
return "PacketEditing";
}
@Override
public String getId() {
return "packet";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
Bukkit.getPluginManager().registerEvents(chatEventListener, pl);
packetManager.getPacketManager().addHandler(chatPacketManager);
}
@Override
public void unload(ChatItem pl) {
HandlerList.unregisterAll(chatEventListener);
packetManager.getPacketManager().removeHandler(chatPacketManager);
packetManager.getPacketManager().stop();
}
public JSONManipulatorCurrent getManipulator(){
return jsonManipulator;
}
public boolean supportsChatComponentApi(){
return baseComponentAvailable;
}
}
@@ -1,14 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
public interface IBaseComponentGetter {
default boolean hasConditions() {
return true;
}
String getBaseComponentAsJSON(ChatItemPacket packet);
void writeJson(ChatItemPacket packet, String json);
}
@@ -1,162 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.stream.Collectors;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.ReflectionUtils;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.chat.ComponentSerializer;
public class AdventureComponentGetter implements IBaseComponentGetter {
private boolean useExtra = false;
@Override
public boolean hasConditions() {
try {
for (String cl : Arrays.asList("net.kyori.adventure.text.Component",
"net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer"))
Class.forName(cl);
} catch (ClassNotFoundException e) { // can't support this, adventure comp not found
return false;
}
return true;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Component comp = packet.getContent().getSpecificModifier(Component.class).readSafely(0);
if(comp == null) {
ChatItem.debug("The component is null.");
return null;
}
String json = ComponentSerializer.toString(BungeeComponentSerializer.legacy().serialize(comp).clone());
ChatItem.debug("AdventureJSON : " + json.replace(ChatManager.SEPARATOR, 'S'));
JsonObject jsonObj = JsonParser.parseString(json).getAsJsonObject();
if(jsonObj.has("with")) {
JsonObject next = new JsonObject();
next.add("extra", jsonObj.get("with"));
return next.toString();
}
useExtra = true;
return json;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
/*JsonObject next = new JsonObject();
next.addProperty("translate", "chat.type.text");
if(useExtra)
next.add("with", fixParsedArray(JsonParser.parseString(json).getAsJsonObject().getAsJsonArray("extra")));
else
next.add("extra", fixParsedArray(JsonParser.parseString(json).getAsJsonObject().getAsJsonArray("extra")));*/
JsonElement globalElement = JsonParser.parseString(json);
JsonArray extraArray = fixParsedArray(globalElement.getAsJsonObject().getAsJsonArray("extra"));
String localJson;
if(useExtra) {
globalElement.getAsJsonObject().add("extra", extraArray);
localJson = globalElement.toString();
} else {
JsonObject next = new JsonObject();
next.addProperty("translate", "chat.type.text");
next.add("with", extraArray);
localJson = next.toString();
}
ChatItem.debug("Adventure Json: " + json);
try {
Class<?> packetClass = packet.getPacket().getClass();
if(packetClass.getSimpleName().equalsIgnoreCase("PacketPlayOutChat")) {
Field componentField = ReflectionUtils.getFirstFieldWith(packetClass, Component.class);
if(componentField != null) {
componentField.setAccessible(true);
componentField.set(packet.getPacket(), BungeeComponentSerializer.legacy().deserialize(ComponentSerializer.parse(localJson)));
} else {
throw new UnsupportedOperationException("The packet PacketPlayOutChat doesn't have Kyori's field. It has: " + Arrays.asList(packetClass.getDeclaredFields()).stream().map(f -> f.getName() + ": " + f.getType().getName()).collect(Collectors.toList()));
}
} else if(packetClass.getSimpleName().equalsIgnoreCase("CliendboundSystemChatPacket")) {
packet.setPacket(packetClass.getConstructor(Component.class, String.class, int.class).newInstance(BungeeComponentSerializer.legacy().deserialize(ComponentSerializer.parse(localJson)), null, 1));
} else {
throw new UnsupportedOperationException("The packet " + packetClass.getSimpleName() + " insupported by the AdventureGetter. Please report this.");
}
} catch (Exception e) {
e.printStackTrace();
}
}
public JsonArray fixParsedArray(JsonArray arr) {
JsonArray next = new JsonArray();
for(JsonElement e : arr) {
if(e.isJsonArray()) {
JsonObject obj = null;
JsonArray extra = new JsonArray();
for(JsonElement element : e.getAsJsonArray()) {
JsonElement fixed = checkElement(element);
if(obj == null && fixed.isJsonObject()) {
obj = fixed.getAsJsonObject();
} else {
extra.add(fixed);
}
}
if(obj != null && extra.size() > 0) {
obj.add("extra", extra);
}
next.add(obj);
} else
next.add(checkElement(e));
}
return next;
}
private JsonElement checkElement(JsonElement e) {
if(e.isJsonObject()) {
JsonObject o = e.getAsJsonObject();
if(o.has("hoverEvent")) {// only hover event
JsonObject hoverObject = o.getAsJsonObject("hoverEvent");
if(hoverObject.get("action").getAsString().equalsIgnoreCase("show_item") && hoverObject.has("value")) {// if it's item to fix
String val = hoverObject.get("value").getAsString();
// now, we should fix the value
val = val.replaceAll("\\\"", "\"");
ChatItem.debug("Fixed json: " + ("{" + val.substring(1, val.length() - 1) + "}"));
hoverObject.remove("value");
JsonElement tagElement = JsonParser.parseString("{" + val.substring(1, val.length() - 1) + "}");
tagElement.getAsJsonObject().remove("tag");
/*if(tagElement.getAsJsonObject().has("tag")) {
JsonElement tag = tagElement.getAsJsonObject().get("tag");
if(tag.isJsonObject()) {
JsonObject tagObj = tag.getAsJsonObject();
tagObj.entrySet().forEach(entry -> {
ChatItem.debug("Tag json: " + entry.getKey() + " > " + entry.getValue());
JsonElement value = entry.getValue();
String sval = value.getAsString();
if(Utils.isInteger(sval)) {
if(Utils.isByte(sval))
tagObj.addProperty(entry.getKey(), sval + "b");
else if(Utils.isShort(sval))
tagObj.addProperty(entry.getKey(), sval + "s");
else if(Utils.isLong(sval))
tagObj.addProperty(entry.getKey(), sval + "l");
else
tagObj.addProperty(entry.getKey(), value + "i");
}
});
}
}*/
hoverObject.add("contents", tagElement);
o.add("hoverEvent", hoverObject);
}
}
}
return e;
}
}
@@ -1,26 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.Version;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
public class BaseComponentGetter implements IBaseComponentGetter {
@Override
public boolean hasConditions() {
return Version.getVersion().isNewerOrEquals(Version.V1_8);
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
BaseComponent[] comps = packet.getContent().getSpecificModifier(BaseComponent[].class).readSafely(0);
return comps == null ? null : ComponentSerializer.toString(comps);
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
packet.getContent().getSpecificModifier(BaseComponent[].class).write(0, ComponentSerializer.parse(json));
}
}
@@ -1,36 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.PacketUtils;
public class ComponentGetter implements IBaseComponentGetter {
@Override
public boolean hasConditions() {
return PacketUtils.COMPONENT_CLASS != null;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
Object chatBaseComp = packet.getContent().getSpecificModifier(PacketUtils.COMPONENT_CLASS).readSafely(0);
if (chatBaseComp != null) {
try {
return PacketUtils.CHAT_SERIALIZER.getMethod("a", PacketUtils.COMPONENT_CLASS)
.invoke(null, packet.getPacket()).toString();
} catch (Exception exc) {
exc.printStackTrace();
}
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.getContent().getChatComponents().write(0, PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,55 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import java.lang.reflect.Method;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.utils.PacketUtils;
public class IChatBaseComponentGetter implements IBaseComponentGetter {
private Method serializerGetJson;
public IChatBaseComponentGetter() {
try {
for (Method m : PacketUtils.CHAT_SERIALIZER.getDeclaredMethods()) {
if (m.getParameterCount() == 1 && m.getParameterTypes()[0].equals(PacketUtils.COMPONENT_CLASS)
&& m.getReturnType().equals(String.class)) {
serializerGetJson = m;
break;
}
}
if (serializerGetJson == null)
ChatItem.getInstance().getLogger().warning(
"Failed to find JSON serializer in class: " + PacketUtils.CHAT_SERIALIZER.getCanonicalName());
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
public boolean hasConditions() {
return serializerGetJson != null;
}
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
try {
Object obj = packet.getContent().getChatComponents().readSafely(0);
return obj == null ? null : (String) serializerGetJson.invoke(null, obj);
} catch (Exception exc) {
exc.printStackTrace();
}
return null;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.getContent().getChatComponents().write(0, PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,44 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.basecomp.hook;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import net.kyori.adventure.text.Component;
public class StringComponentGetter implements IBaseComponentGetter{
@Override
public String getBaseComponentAsJSON(ChatItemPacket packet) {
String json = packet.getContent().getStrings().readSafely(0);
if(json != null && json.startsWith("[") && json.endsWith("]")) { // if used as array instead of json obj
JsonArray extra = new JsonArray();
for(JsonElement element : JsonParser.parseString(json).getAsJsonArray()) {
if(element.isJsonObject()) { // ignore this
extra.add(element);
} else {
ChatItem.debug("Ignoring element " + element);
}
}
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("text", "");
jsonObject.add("extra", extra);
json = jsonObject.toString();
}
return json;
}
@Override
public void writeJson(ChatItemPacket packet, String json) {
try {
packet.setPacket(packet.getPacket().getClass().getConstructor(Component.class, String.class, int.class).newInstance(null, json, 1));
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,249 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.json;
import static me.dadus33.chatitem.utils.PacketUtils.getNmsClass;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Pattern;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.Reflect;
import me.dadus33.chatitem.utils.Version;
@SuppressWarnings({ "unchecked" })
public class JSONManipulatorCurrent {
private static final Class<?> CRAFT_ITEM_STACK_CLASS = PacketUtils.getObcClass("inventory.CraftItemStack");
private static final Class<?> NMS_ITEM_STACK_CLASS = getNmsClass("ItemStack", "world.item.");
private static final Method AS_NMS_COPY = Reflect.getMethod(CRAFT_ITEM_STACK_CLASS, "asNMSCopy", ItemStack.class);
private static final Class<?> NBT_TAG_COMPOUND = getNmsClass("NBTTagCompound", "nbt.");
private static final Method SAVE_NMS_ITEM_STACK_METHOD = Reflect.getMethod(NMS_ITEM_STACK_CLASS, NBT_TAG_COMPOUND,
NBT_TAG_COMPOUND);
private static final Field MAP = Reflect.getField(NBT_TAG_COMPOUND, "map", "x");
private static final ConcurrentHashMap<Map.Entry<Version, ItemStack>, JsonObject> STACKS = new ConcurrentHashMap<>();
private Version protocolVersion;
private JsonObject itemTooltip;
private JsonArray classicTooltip;
public String parse(String json, String placeholder, ItemStack item, String replacement, int protocol)
throws Exception {
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
JsonArray array = obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray();
final AbstractMap.SimpleEntry<Version, ItemStack> p = new AbstractMap.SimpleEntry<>(
protocolVersion = Version.getVersion(protocol), item);
if ((itemTooltip = STACKS.get(p)) == null) {
JsonArray use = Translator.toJson(replacement); // We get the json representation of the old color
// formatting method
// There's no public clone method for JSONObjects so we need to parse them every
// time
JsonObject hover = JsonParser.parseString("{\"action\":\"show_item\", \"value\": \"\"}").getAsJsonObject();
String jsonRep = stringifyItem(this, item, protocolVersion);// stringifyItem(item); // Get the JSON
// representation of the item (well, not really
// JSON, but
// rather a string representation of NBT data)
hover.addProperty("value", jsonRep);
JsonObject wrapper = new JsonObject(); // Create a wrapper object for the whole array
wrapper.addProperty("text", ""); // The text field is compulsory, even if it's empty
wrapper.add("extra", use);
wrapper.add("hoverEvent", hover);
itemTooltip = wrapper; // Save the tooltip for later use when we encounter a placeholder
STACKS.put(p, itemTooltip); // Save it in the cache too so when parsing other packets with the same item
// (and client version) we no longer have to create it again
// We remove it later when no longer needed to save memory
Bukkit.getScheduler().runTaskLaterAsynchronously(ChatItem.getInstance(), () -> STACKS.remove(p), 100L);
}
obj.add("extra", parseArray(placeholder, array, itemTooltip));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
public String parseEmpty(String json, String placeholder, String repl, List<String> tooltip, Player sender) {
JsonObject obj = JsonParser.parseString(json).getAsJsonObject();
JsonArray array = obj.has("extra") ? obj.getAsJsonArray("extra") : new JsonArray();
JsonArray use = Translator
.toJson(repl.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
JsonObject hover = JsonParser.parseString("{\"action\":\"show_text\", \"value\": \"\"}").getAsJsonObject();
StringBuilder oneLineTooltip = new StringBuilder("");
int index = 0;
for (String m : tooltip) {
oneLineTooltip
.append(m.replace("{name}", sender.getName()).replace("{display-name}", sender.getDisplayName()));
++index;
if (index != tooltip.size()) {
oneLineTooltip.append('\n');
}
}
hover.add("value", new JsonPrimitive(oneLineTooltip.toString()));
if (!tooltip.isEmpty()) {
for (JsonElement ob : use)
ob.getAsJsonObject().add("hoverEvent", hover);
classicTooltip = use;
}
obj.add("extra", parseArray(placeholder, array, classicTooltip));
if (!obj.has("text")) {
obj.addProperty("text", "");
}
return obj.toString();
}
private JsonArray parseArray(String placeholder, JsonArray arr, JsonElement tooltip) {
JsonArray replacer = new JsonArray();
for (int i = 0; i < arr.size(); ++i) {
if (arr.get(i).isJsonNull()) {
continue;
} else if (arr.get(i).isJsonObject()) {
addParsedJsonObjectToArray(arr.get(i).getAsJsonObject(), placeholder, replacer, tooltip);
} else if (arr.get(i).isJsonArray()) {
JsonArray jar = arr.get(i).getAsJsonArray();
if (jar.size() != 0) {
jar = parseArray(placeholder, arr.get(i).getAsJsonArray(), tooltip);
replacer.set(i, jar);
}
} else {
addParsedStringToArray(arr.get(i).getAsString(), placeholder, replacer, arr.get(i), tooltip);
}
}
return replacer;
}
private void addParsedJsonObjectToArray(JsonObject o, String placeholder, JsonArray rep, JsonElement tooltip) {
JsonElement text = o.get("text");
if (text == null) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
if (jar.size() != 0) {
o.add("extra", parseArray(placeholder, jar, tooltip));
} else {
o.remove("extra");
}
}
return;
} else {
if (text.getAsString().isEmpty()) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
if (jar.size() != 0) {
o.add("extra", parseArray(placeholder, jar, tooltip));
} else {
o.remove("extra");
}
}
}
}
addParsedStringToArray(text.getAsString(), placeholder, rep, o, tooltip);
}
private void addParsedStringToArray(String msg, String placeholder, JsonArray rep, JsonElement o, JsonElement tooltip) {
boolean isLast = msg.endsWith(placeholder);
if (isLast) {
msg = msg.concat(".");
}
String[] splits = msg.split(Pattern.quote(placeholder));
if (splits.length != 1) {
for (int j = 0; j < splits.length; ++j) {
boolean endDot = (j == splits.length - 1) && isLast;
if (!splits[j].isEmpty() && !endDot) {
String st = o.toString();
JsonElement element = JsonParser.parseString(st);
if(element.isJsonObject()) {
JsonObject fix = element.getAsJsonObject();
fix.addProperty("text", splits[j]);
rep.add(fix);
} else
rep.add(new JsonPrimitive(splits[j]));
}
if (j != splits.length - 1) {
rep.add(tooltip);
}
}
} else {
rep.add(o);
}
}
@SuppressWarnings({ "deprecation" })
public static String stringifyItem(JSONManipulatorCurrent j, ItemStack is, Version protocolVersion)
throws Exception {
Object nmsStack = JSONManipulatorCurrent.AS_NMS_COPY.invoke(null, is);
Object nmsTag = JSONManipulatorCurrent.NBT_TAG_COMPOUND.newInstance();
JSONManipulatorCurrent.SAVE_NMS_ITEM_STACK_METHOD.invoke(nmsStack, nmsTag);
HashMap<String, String> tagMap = new HashMap<>();
Map<String, Object> nmsMap = (Map<String, Object>) JSONManipulatorCurrent.MAP.get(nmsTag);
String id = nmsMap.get("id").toString().replace("\"", "");
Object realTag = nmsMap.get("tag");
if (JSONManipulatorCurrent.NBT_TAG_COMPOUND.isInstance(realTag)) { // We need to make sure this is indeed an
// NBTTagCompound
Map<String, Object> realMap = (Map<String, Object>) JSONManipulatorCurrent.MAP.get(realTag);
Set<Map.Entry<String, Object>> entrySet = realMap.entrySet();
for (Map.Entry<String, Object> entry : entrySet) {
tagMap.put(entry.getKey(), entry.getValue().toString());
}
}
// TODO check for ID remapping
// ItemRewriter.remapIds(Version.getVersion().MAX_VER, protocolVersion.MAX_VER,
// is);
StringBuilder sb = new StringBuilder("{id:");
if (protocolVersion.equals(Version.V1_7))
sb.append(id).append(","); // Append the id
else
sb.append("\"").append(id).append("\"").append(","); // Append the id
sb.append("Count:").append(is.getAmount()).append("b"); // Append the amount
if (!tagMap.containsKey("Damage")) { // for new versions
sb.append(",Damage:").append(is.getDurability()).append("s"); // Append the durability data
}
if (tagMap.isEmpty()) {
sb.append("}");
return sb.toString();
}
Set<Map.Entry<String, String>> entrySet = tagMap.entrySet();
boolean first = true;
sb.append(",tag:{"); // Start of the tag
for (Map.Entry<String, String> entry : entrySet) {
if (!first)
sb.append(",");
first = false;
if (!entry.getKey().isEmpty())
sb.append(entry.getKey()).append(":");
sb.append(cleanStr(entry.getValue()));
}
sb.append("}}"); // End of tag and end of item
return sb.toString();
}
private static String cleanStr(String s) {
return s.startsWith("'") && s.endsWith("'") ? s.substring(1, s.length() - 1) : s;
}
}
@@ -1,134 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.json;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import org.bukkit.ChatColor;
//Based on DarkSeraphim's system, but using Gson and supporting some more edge cases
public class Translator {
private static final String STYLES = "klmnor"; //All style codes
public static JsonArray toJson(String old){
if(old.lastIndexOf(ChatColor.COLOR_CHAR) == -1){
JsonArray arr = new JsonArray();
JsonObject obj = new JsonObject();
obj.addProperty("text", old);
arr.add(obj);
return arr;
}
boolean startsWithCode = old.startsWith(Character.toString(ChatColor.COLOR_CHAR));
JsonArray message = new JsonArray();
String[] parts = old.split(Character.toString(ChatColor.COLOR_CHAR));
JsonObject next = null; //refers to the object we created before (in time) but next in the message, as we're going from end to start
for(int i = parts.length-1; i >= 0; --i){ //We go in reverse order
String part = parts[i];
if(part.isEmpty()){
continue;
}
if(i == 0 && !startsWithCode){
JsonObject toAdd = new JsonObject();
toAdd.addProperty("text", part);
message.add(toAdd);
break;
}
char code = Character.toLowerCase(part.charAt(0));
if(!isColorOrStyle(code)){
if(next != null){
String text = next.get("text").getAsString();
text = ChatColor.COLOR_CHAR + part + text;
next.addProperty("text", text);
}else{
JsonObject added = new JsonObject();
added.addProperty("text", ChatColor.COLOR_CHAR + part);
message.add(added);
next = added;
}
continue;
}
if(part.length() == 1){ //If it's just format and no text, we try to format the next element, if it wasn't formatted already (and it's not null)
if(next == null){
continue;
}
if(isStyle(code)){
next.addProperty(getStyleName(code), true);
}else{ //it's a color
if(isAlreadyColored(next)){
continue;
}
next.addProperty("color", getColorName(code));
}
continue;
}
//Last possibility that remains is that we have a normal color/format + text situation
JsonObject added = new JsonObject();
added.addProperty("text", part.substring(1));
if(isStyle(code)){
added.addProperty(getStyleName(code), true);
message.add(added);
next = added;
continue;
}
//else it can only be a color
added.addProperty("color", getColorName(code));
//also try to color the next element if not colored already
if(next != null){
if(!isAlreadyColored(next)){
next.addProperty("color", getColorName(code));
}
}
message.add(added);
next = added;
}
int i = message.size()-1;
JsonArray orderedMessage = new JsonArray();//This is where we'll store the reverted message (in proper order for being sent to the client)
//First we have to copy all elements
for(JsonElement el : message){
orderedMessage.add(el);
}
for(JsonElement element : message){
JsonObject obj = (JsonObject) element;
orderedMessage.set(i, obj); //And then we add the object to the properly ordered array
--i;
}
return orderedMessage;
}
private static String getColorName(char code){
return ChatColor.getByChar(code).name().toLowerCase();
}
private static String getStyleName(char code){
switch(code){
case 'k': return "obfuscated";
case 'l': return "bold";
case 'm': return "strikethrough";
case 'n': return "underlined";
case 'o': return "italic";
case 'r': return "reset";
default: return null; //Should never happen. Made it return null to throw errors if a new format pops up and it really happens
}
}
private static boolean isColorOrStyle(char code){
return ChatColor.getByChar(code) != null;
}
private static boolean isStyle(char c){
return STYLES.indexOf(c) != -1;
}
private static boolean isAlreadyColored(JsonObject obj){
return obj.has("color");
}
}
@@ -1,162 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.listeners;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR;
import java.util.StringJoiner;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
public class ChatEventListener implements Listener {
private final PacketEditingChatManager manage;
public ChatEventListener(PacketEditingChatManager manage) {
this.manage = manage;
}
public Storage getStorage() {
return this.manage.getStorage();
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST) // We need to have lowest priority in order
// to get to the event before DeluxeChat or
// other plugins do
public void onChat(AsyncPlayerChatEvent e) {
if (e.getMessage().indexOf(SEPARATOR) != -1) { // If the BELL character is found, we have to remove it
String msg = e.getMessage().replace(Character.toString(SEPARATOR), "");
ChatItem.debug("Already bell in message: " + e.getMessage());
e.setMessage(msg);
}
boolean found = false;
final String oldMsg = e.getMessage();
for (String rep : getStorage().PLACEHOLDERS)
if (oldMsg.contains(rep)) {
found = true;
break;
}
if (!found) {
ChatItem.debug("(v1) not found placeholders in: " + e.getMessage());
return;
}
Player p = e.getPlayer();
ItemStack item = ChatManager.getUsableItem(p);
if(!ChatManager.canShowItem(p, item, e))
return;
String s = e.getMessage(), firstPlaceholder = getStorage().PLACEHOLDERS.get(0);
for (String placeholder : getStorage().PLACEHOLDERS) {
s = s.replace(placeholder, firstPlaceholder);
}
if (Utils.countMatches(s, firstPlaceholder) > getStorage().LIMIT) {
e.setCancelled(true);
if (getStorage().LIMIT_MESSAGE.isEmpty()) {
return;
}
p.sendMessage(getStorage().LIMIT_MESSAGE);
return;
}
ChatItem.debug("(v1) Set placeholder: " + e.getMessage());
try {
StringJoiner msg = new StringJoiner(" ");
for(String part : s.split(" ")) {
if(part.equalsIgnoreCase(firstPlaceholder)) {
msg.add(firstPlaceholder + SEPARATOR + p.getName());
} else {
msg.add(part);
}
}
e.setMessage(msg.toString());
e.setFormat(e.getFormat().replace(oldMsg, e.getMessage())); // set own message for plugin that already put the message into the format
ChatItem.debug("Message: " + e.getMessage().replace(SEPARATOR, 'S') + ", format: " + e.getFormat());
} catch (Exception exc) {
exc.printStackTrace();
}
if (getStorage().COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
ChatManager.COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onCommand(final PlayerCommandPreprocessEvent e) {
if (e.getMessage().indexOf(SEPARATOR) != -1) { // If the BELL character is found, we have to remove it
String msg = e.getMessage().replace(Character.toString(SEPARATOR), "");
e.setMessage(msg);
}
String commandString = e.getMessage().split(" ")[0].replaceAll("^/+", ""); // First part of the command, without
// leading slashes and without
// arguments
Command cmd = Bukkit.getPluginCommand(commandString);
if (cmd == null) { // not a plugin command
if (!getStorage().ALLOWED_DEFAULT_COMMANDS.contains(commandString)) {
return;
}
} else {
if (!getStorage().ALLOWED_PLUGIN_COMMANDS.contains(cmd)) {
return;
}
}
Player p = e.getPlayer();
boolean found = false;
for (String rep : getStorage().PLACEHOLDERS) {
if (e.getMessage().contains(rep)) {
found = true;
break;
}
}
if (!found) {
return;
}
ItemStack item = ChatManager.getUsableItem(p);
if(!ChatManager.canShowItem(p, item, e))
return;
String s = e.getMessage(), firstPlaceholder = getStorage().PLACEHOLDERS.get(0);
for (String placeholder : getStorage().PLACEHOLDERS) {
s = s.replace(placeholder, firstPlaceholder);
}
if (Utils.countMatches(s, firstPlaceholder) > getStorage().LIMIT) {
e.setCancelled(true);
if (getStorage().LIMIT_MESSAGE.isEmpty()) {
return;
}
p.sendMessage(getStorage().LIMIT_MESSAGE);
return;
}
ChatItem.debug("(v1) Set placeholder: " + e.getMessage());
try {
StringJoiner msg = new StringJoiner(" ");
for(String part : s.split(" ")) {
if(part.equalsIgnoreCase(firstPlaceholder)) {
msg.add(firstPlaceholder + SEPARATOR + p.getName());
} else {
msg.add(part);
}
}
e.setMessage(msg.toString());
} catch (Exception exc) {
exc.printStackTrace();
}
if (getStorage().COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
ChatManager.COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
}
}
}
@@ -1,297 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.listeners;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR;
import static me.dadus33.chatitem.chatmanager.ChatManager.SEPARATOR_STR;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.ShulkerBox;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.BookMeta;
import org.bukkit.inventory.meta.ItemMeta;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.chatmanager.v1.PacketEditingChatManager;
import me.dadus33.chatitem.chatmanager.v1.basecomp.IBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.AdventureComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.BaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.ComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.IChatBaseComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.basecomp.hook.StringComponentGetter;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketHandler;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.itemnamer.NamerManager;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
import me.dadus33.chatitem.utils.Version;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.chat.ComponentSerializer;
public class ChatPacketManager extends PacketHandler {
private Object lastSentPacket = null;
private Method serializerGetJson;
private PacketEditingChatManager manager;
private final List<IBaseComponentGetter> baseComponentGetter = new ArrayList<>();
public ChatPacketManager(PacketEditingChatManager manager) {
this.manager = manager;
try {
for (Method m : PacketUtils.CHAT_SERIALIZER.getDeclaredMethods()) {
if (m.getParameterCount() == 1 && m.getParameterTypes()[0].equals(PacketUtils.COMPONENT_CLASS)
&& m.getReturnType().equals(String.class)) {
serializerGetJson = m;
break;
}
}
if (serializerGetJson == null)
ChatItem.getInstance().getLogger().warning(
"Failed to find JSON serializer in class: " + PacketUtils.CHAT_SERIALIZER.getCanonicalName());
} catch (Exception e) {
e.printStackTrace();
}
for(IBaseComponentGetter getter : Arrays.asList(new IChatBaseComponentGetter(), new BaseComponentGetter(), new ComponentGetter(), new AdventureComponentGetter(), new StringComponentGetter())) {
if(getter.hasConditions())
baseComponentGetter.add(getter);
}
ChatItem.getInstance().getLogger().info("Loaded " + baseComponentGetter.size() + " getter for base components.");
ChatItem.debug("BaseComponentGetters: " + String.join(", ", baseComponentGetter.stream().map(IBaseComponentGetter::getClass).map(Class::getSimpleName).collect(Collectors.toList())));
}
@Override
public void onSend(ChatItemPacket e) {
if (!e.hasPlayer() || !e.getPacketType().equals(PacketType.Server.CHAT))
return;
if (lastSentPacket != null && lastSentPacket == e.getPacket())
return; // prevent infinite loop
PacketContent packet = e.getContent();
Version version = Version.getVersion();
String json = "{}";
IBaseComponentGetter choosedGetter = null;
if (version.isNewerOrEquals(Version.V1_19)) {
if(packet.getIntegers().readSafely(0, 0) != 1)
return;
choosedGetter = new StringComponentGetter();
json = choosedGetter.getBaseComponentAsJSON(e); // if null, will be re-checked so anyway
} else if (version.isNewerOrEquals(Version.V1_12)) {
// only if action bar messages are supported in this version of minecraft
try {
if (((Enum<?>) packet
.getSpecificModifier(PacketUtils.getNmsClass("ChatMessageType", "network.chat.")).read(0))
.name().equals("GAME_INFO")) {
return; // It means it's an actionbar message, and we ain't intercepting those
}
} catch (Exception exc) {
exc.printStackTrace();
}
} else if (version.isNewerOrEquals(Version.V1_8) && packet.getBytes().readSafely(0) == (byte) 2) {
return; // It means it's an actionbar message, and we ain't intercepting those
}
if(json == null || choosedGetter == null) {
for(IBaseComponentGetter getters : baseComponentGetter) {
String tmpJson = getters.getBaseComponentAsJSON(e);
if(tmpJson != null) {
json = tmpJson;
choosedGetter = getters;
break;
}
}
}
boolean found = false;
for (String rep : getStorage().PLACEHOLDERS) {
if (json.contains(rep)) {
found = true;
break;
}
}
if (!found) {
ChatItem.debug("No placeholders founded in " + json);
ChatItem.debug("String: " + packet.getStrings().getContent());
try {
Class<?> c = Class.forName("net.kyori.adventure.text.Component");
ChatItem.debug("Component: " + packet.getSpecificModifier(c).getContent());
} catch (ClassNotFoundException exc) {
ChatItem.debug("Can't find Kyori's component");
} catch(Exception exc) {
exc.printStackTrace();
}
return; // then it's just a normal message without placeholders, so we leave it alone
}
ChatItem.debug("Found " + json + " with " + choosedGetter.getClass().getName());
Object toReplace = null;
if (json.lastIndexOf(SEPARATOR) != -1)
toReplace = SEPARATOR;
if (json.lastIndexOf(SEPARATOR_STR) != -1)
toReplace = SEPARATOR_STR;
if (toReplace == null) { // if the message doesn't contain the BELL separator
ChatItem.debug("Not containing bell " + json);
return;
}
IBaseComponentGetter fchoosedGetter = choosedGetter;
String fjson = json, toReplaceStr = toReplace.toString();
e.setCancelled(true); // We cancel the packet as we're going to resend it anyways (ignoring listeners
// this time)
Bukkit.getScheduler().runTaskAsynchronously(ChatItem.getInstance(), () -> {
Player p = e.getPlayer();
int topIndex = -1;
String name = null;
for (Player pl : Bukkit.getOnlinePlayers()) {
String pname = toReplaceStr + pl.getName();
if (!fjson.contains(pname)) {
continue;
}
int index = fjson.lastIndexOf(pname) + pname.length();
if (index > topIndex) {
topIndex = index;
name = pname.replace(toReplaceStr, "");
}
}
if (name == null) { // something went really bad, so we run away and hide (AKA the player left or is
// on another server)
ChatItem.debug("Name null for " + fjson);
return;
}
Player itemPlayer = Bukkit.getPlayer(name);
StringBuilder builder = new StringBuilder(fjson);
builder.replace(topIndex - (name.length() + 6), topIndex, ""); // we remove both the name and the separator
// from the json string
String localJson = fjson.replace(toReplaceStr + itemPlayer.getName(), "");// builder.toString();
String message = null;
try {
ItemStack item = ChatManager.getUsableItem(itemPlayer);
if (!ItemUtils.isEmpty(item)) {
ItemStack copy = item.clone();
if (ItemPlayer.getPlayer(p).isBuggedClient()) {
String act = getStorage().BUGGED_CLIENT_ACTION;
List<String> tooltip;// = act.equalsIgnoreCase("nothing") ? new ArrayList<>() : null;
if (act.equalsIgnoreCase("tooltip"))
tooltip = getStorage().BUGGED_CLIENTS_TOOLTIP;
else if (act.equalsIgnoreCase("item"))
tooltip = getMaxLinesFromItem(p, copy);
else if (act.equalsIgnoreCase("show_both")) {
tooltip = getMaxLinesFromItem(p, copy);
tooltip.addAll(getStorage().BUGGED_CLIENTS_TOOLTIP);
} else
tooltip = new ArrayList<>();
message = manager.getManipulator().parseEmpty(localJson, getStorage().PLACEHOLDERS.get(0),
ChatManager.styleItem(p, copy, getStorage()), tooltip, itemPlayer);
if (!manager.supportsChatComponentApi()) {
ChatItem.debug("Use basic for 1.7 lunar");
packet.getChatComponents().write(0, jsonToChatComponent(message));
} else {
ChatItem.debug("Use baseComponent for 1.7 lunar");
packet.getSpecificModifier(BaseComponent[].class).write(0,
ComponentSerializer.parse(message));
}
lastSentPacket = e.getPacket();
PacketUtils.sendPacket(p, lastSentPacket);
return;
}
if (copy.getType().name().contains("_BOOK")) { // filtering written books
BookMeta bm = (BookMeta) copy.getItemMeta();
bm.setPages(Collections.emptyList());
copy.setItemMeta(bm);
} else {
if (copy.getType().name().contains("SHULKER_BOX")) { // if it's shulker
if (copy.hasItemMeta()) {
BlockStateMeta bsm = (BlockStateMeta) copy.getItemMeta();
if (bsm.hasBlockState()) {
ShulkerBox sb = (ShulkerBox) bsm.getBlockState();
for (ItemStack itemInv : sb.getInventory()) {
stripData(itemInv);
}
bsm.setBlockState(sb);
}
copy.setItemMeta(bsm);
}
}
}
message = manager.getManipulator().parse(localJson, getStorage().PLACEHOLDERS.get(0), copy,
ChatManager.styleItem(p, copy, getStorage()), ItemPlayer.getPlayer(itemPlayer).getProtocolVersion());
} else {
if (!getStorage().HAND_DISABLED) {
message = manager.getManipulator().parseEmpty(localJson, getStorage().PLACEHOLDERS.get(0),
getStorage().HAND_NAME, getStorage().HAND_TOOLTIP, itemPlayer);
}
}
} catch (Exception e1) {
e1.printStackTrace();
}
if (message != null) {
ChatItem.debug("(v1) Writing message: " + message);
fchoosedGetter.writeJson(e, message);
}
lastSentPacket = e.getPacket();
PacketUtils.sendPacket(p, lastSentPacket);
});
}
private Object jsonToChatComponent(String json) {
try {
return PacketUtils.CHAT_SERIALIZER.getMethod("a", String.class).invoke(null, json);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private void stripData(ItemStack i) {
if (i == null) {
return;
}
if (i.getType().equals(Material.AIR)) {
return;
}
if (!i.hasItemMeta()) {
return;
}
ItemMeta im = Bukkit.getItemFactory().getItemMeta(i.getType());
ItemMeta original = i.getItemMeta();
if (original.hasDisplayName()) {
im.setDisplayName(original.getDisplayName());
}
i.setItemMeta(im);
}
public Storage getStorage() {
return manager.getStorage();
}
private List<String> getMaxLinesFromItem(Player p, ItemStack item) {
List<String> lines = new ArrayList<>();
if (item.hasItemMeta()) {
ItemMeta meta = item.getItemMeta();
lines.add(meta.hasDisplayName() ? meta.getDisplayName()
: NamerManager.getName(p, item, getStorage()));
if (meta.hasEnchants()) {
meta.getEnchants().forEach((enchant, lvl) -> {
lines.add(ChatColor.RESET + Utils.getEnchantName(enchant) + " " + Utils.toRoman(lvl));
});
}
if (meta.hasLore())
lines.addAll(meta.getLore());
} else {
lines.add(NamerManager.getName(p, item, getStorage()));
}
return lines;
}
}
@@ -1,33 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.listeners;
import org.bukkit.Bukkit;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.playerversion.hooks.DefaultVersionHook;
import me.dadus33.chatitem.utils.Version;
public class HandshakeListener extends PacketAdapter {
public HandshakeListener(ChatItem pl) {
super(pl, ListenerPriority.MONITOR, PacketType.Handshake.Client.SET_PROTOCOL);
}
@Override
public void onPacketReceiving(final PacketEvent e){
if(e.isPlayerTemporary() || e.getPlayer() == null)
return;
PacketType.Protocol p = e.getPacket().getProtocols().read(0);
if(p == PacketType.Protocol.STATUS || p == PacketType.Protocol.LEGACY){
return;
}
final int version = e.getPacket().getIntegers().readSafely(0);
//Delay the mapping to make sure the true address of the player was received when using bungeecord or other types of proxies
Bukkit.getScheduler().scheduleSyncDelayedTask(getPlugin(), () ->
DefaultVersionHook.PROTOCOL_PER_ADDRESS.put(Version.stringifyAdress(e.getPlayer().getAddress()), version), 10L);
}
}
@@ -1,57 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import org.bukkit.entity.Player;
public class ChatItemPacket {
protected final Player player;
protected Object packet;
protected PacketType type;
protected boolean cancel = false;
public ChatItemPacket(PacketType type, Object packet, Player player) {
this.player = player;
this.packet = packet;
this.type = type;
}
public Player getPlayer() {
return player;
}
public boolean hasPlayer() {
return player != null;
}
public String getPlayername() {
return getPlayer().getName();
}
public Object getPacket() {
return packet;
}
public void setPacket(Object packet) {
this.packet = packet;
}
public String getPacketName() {
return packet.getClass().getSimpleName();
}
public PacketType getPacketType() {
return type;
}
public boolean isCancelled() {
return cancel;
}
public void setCancelled(boolean cancel) {
this.cancel = cancel;
}
public PacketContent getContent() {
return new PacketContent(this);
}
}
@@ -1,50 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.protocollib.ProtocollibPacketManager;
public class ChatItemPacketManager {
private PacketManager packetManager;
public ChatItemPacketManager(ChatItem pl) {
Plugin protocolLibPlugin = Bukkit.getPluginManager().getPlugin("ProtocolLib");
if (protocolLibPlugin != null) {
String version = protocolLibPlugin.getDescription().getVersion();
if(version.contains("5.0.0-SNAPSHOT")) {
pl.getLogger().warning("ProtocolLib have been detected, but actually, snapshot have issues with chat packet. More informations here: https://github.com/dmulloy2/ProtocolLib/issues/1670.");
packetManager = new CustomPacketManager(pl);
} else if(checkProtocollibConditions()) {
pl.getLogger().info("The plugin ProtocolLib has been detected. Loading Protocollib support ...");
packetManager = new ProtocollibPacketManager(pl);
} else {
pl.getLogger().warning("The plugin ProtocolLib has been detected but you have an old or too new version, so we cannot use it.");
pl.getLogger().warning("Fallback to default Packet system ...");
packetManager = new CustomPacketManager(pl);
}
} else {
pl.getLogger().info("Loading own packet system.");
packetManager = new CustomPacketManager(pl);
}
}
public PacketManager getPacketManager() {
return packetManager;
}
private boolean checkProtocollibConditions() {
for(String searchedClass : Arrays.asList("com.comphenix.protocol.injector.server.TemporaryPlayer", "com.comphenix.protocol.injector.temporary.TemporaryPlayer")) { // class since 4.4.0 until 4.8.0, then the new one
try {
Class.forName(searchedClass);
return true; // class found
} catch (ClassNotFoundException e) {}
}
return false;
}
}
@@ -1,213 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Objects;
import java.util.stream.Collectors;
import me.dadus33.chatitem.utils.PacketUtils;
public class PacketContent {
private final ChatItemPacket packet;
private final Object obj;
/**
* Create a PacketContent to easily read and write value in it
*
* @param packet the Negativity's packet
*/
public PacketContent(ChatItemPacket packet) {
this.packet = packet;
this.obj = packet.getPacket();
}
/**
* Create a PacketContent to easily read and write to the specified object
*
* @param obj the object that will be read or edit
*/
public PacketContent(Object obj) {
this.packet = null;
this.obj = obj;
}
public ChatItemPacket getPacket() {
return packet;
}
public <T> ContentModifier<T> getSpecificModifier(T type){
return new ContentModifier<T>(obj, type.getClass());
}
public <T> ContentModifier<T> getSpecificModifier(Class<T> clazz){
return new ContentModifier<T>(obj, clazz);
}
public ContentModifier<String> getStrings(){
return new ContentModifier<String>(obj, String.class);
}
public ContentModifier<Byte> getBytes(){
return new ContentModifier<Byte>(obj, byte.class);
}
public ContentModifier<Boolean> getBooleans(){
return new ContentModifier<Boolean>(obj, boolean.class);
}
public ContentModifier<Integer> getIntegers(){
return new ContentModifier<Integer>(obj, int.class);
}
public ContentModifier<byte[]> getByteArrays(){
return new ContentModifier<byte[]>(obj, byte[].class);
}
@SuppressWarnings("unchecked")
public ContentModifier<Object> getChatComponents() {
return (ContentModifier<Object>) getSpecificModifier(PacketUtils.COMPONENT_CLASS);
}
public static class ContentModifier<T> {
private Object obj;
private HashMap<Field, T> content = new HashMap<>();
@SuppressWarnings("unchecked")
public ContentModifier(Object obj, Class<?> clazz) {
this.obj = obj;
for(Field f : obj.getClass().getDeclaredFields()) {
try {
if(f.getType().isAssignableFrom(clazz)) {
f.setAccessible(true);
content.put(f, (T) f.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
}
if(!obj.getClass().getSuperclass().equals(Object.class)) {
for(Field f : obj.getClass().getSuperclass().getDeclaredFields()) {
try {
if(f.getType().isAssignableFrom(clazz)) {
f.setAccessible(true);
content.put(f, (T) f.get(obj));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* Get the size of the Map of content
*
* @return the number of content
*/
public int size() {
return content.size();
}
/**
* Get the value of the field which is named by the given one
*
* @param fieldName the name of the needed field
* @return the value of the field
*/
public T read(String fieldName) {
for(Field field : content.keySet())
if(field.getName().equalsIgnoreCase(fieldName))
return content.get(field);
return null;
}
/**
* Get the value of the field which is named by the given one
*
* @param fieldName the name of the needed field
* @param defaultValue the returned value if there is no value
* @return the value of the field
*/
public T read(String fieldName, T defaultValue) {
for(Field field : content.keySet())
if(field.getName().equalsIgnoreCase(fieldName))
return content.get(field);
return defaultValue;
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @return the requested value.
*
* @throws NoSuchElementException if the value doesn't exist
*/
public T read(int i) {
return content.values().stream().filter(Objects::nonNull).collect(Collectors.toList()).get(i);
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @return the requested value, or null if it doesn't exist.
*/
public T readSafely(int i) {
return readSafely(i, null);
}
/**
* Read the specified value.
*
* @param i the number of the value to get getted. Start at 0.
* @param defaultValue the value which is return if the key doesn't exist
* @return the requested value.
*/
public T readSafely(int i, T defaultValue) {
List<T> vals = content.values().stream().filter(Objects::nonNull).collect(Collectors.toList());
return vals.size() <= i ? defaultValue : vals.get(i);
}
/**
* Set the value in the specified object.
*
* @param i the key of the value to set
* @param value the new value which will be set
*/
public void write(int i, T value) {
Field key = content.keySet().toArray(new Field[] {})[i];
if(key == null) {
new NoSuchFieldException("Not enough value in " + obj.getClass() + ".").printStackTrace();
} else {
content.put(key, value);
try {
key.setAccessible(true);
/*if(Modifier.isFinal(key.getModifiers())) {
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(key, key.getModifiers() & ~Modifier.FINAL);
}*/
key.set(obj, value);
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Get field which her value
*
* @return all content
*/
public HashMap<Field, T> getContent(){
return content;
}
}
}
@@ -1,7 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
public abstract class PacketHandler {
public void onReceive(ChatItemPacket packet) {}
public void onSend(ChatItemPacket packet) {}
}
@@ -1,25 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.util.ArrayList;
import org.bukkit.entity.Player;
public abstract class PacketManager {
public void addPlayer(Player p) {}
public void removePlayer(Player p) {}
public abstract void stop();
private final ArrayList<PacketHandler> handlers = new ArrayList<>();
public boolean addHandler(PacketHandler handler) {
return !handlers.add(handler);
}
public boolean removeHandler(PacketHandler handler) {
return handlers.remove(handler);
}
public void notifyHandlersSent(ChatItemPacket packet) {
handlers.forEach((handler) -> handler.onSend(packet));
}
}
@@ -1,106 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public interface PacketType {
String name();
String getPacketName();
String getFullName();
List<String> getAlias();
public static List<PacketType> values() {
List<PacketType> list = new ArrayList<>();
list.addAll(Arrays.asList(Server.values()));
list.addAll(Arrays.asList(Handshake.values()));
return list;
}
static final String SERVER_PREFIX = "PacketPlayOut", HANDSHAKE_PREFIX = "PacketHandshaking";
public static PacketType getType(String packetName) {
if(packetName.startsWith(SERVER_PREFIX)) {
return getPacketTypeFor(packetName, Server.values(), Server.UNSET);
} else if(packetName.startsWith(HANDSHAKE_PREFIX)) {
return getPacketTypeFor(packetName, Handshake.values(), Handshake.UNSET);
} else {
for(PacketType types : values()) {
if(types.getFullName().equalsIgnoreCase(packetName) || types.getAlias().contains(packetName))
return types;
}
return null;
}
}
static PacketType getPacketTypeFor(String packetName, PacketType[] types, PacketType unset) {
for(PacketType packet : types)
if(packet.getFullName().equalsIgnoreCase(packetName) || packet.getPacketName().equalsIgnoreCase(packetName) || packet.getAlias().contains(packetName))
return packet;
return unset;
}
public static enum Server implements PacketType {
CHAT("Chat", "ClientboundPlayerChatPacket", "ClientboundSystemChatPacket"),
UNSET("Unset");
private final String packetName, fullName;
private List<String> alias = new ArrayList<>();
private Server(String packetName, String... alias) {
this.packetName = packetName;
this.fullName = SERVER_PREFIX + packetName;
for(String al : alias)
this.alias.add(al);
}
@Override
public String getPacketName() {
return packetName;
}
@Override
public String getFullName() {
return fullName;
}
@Override
public List<String> getAlias() {
return alias;
}
}
public static enum Handshake implements PacketType {
IS_SET_PROTOCOL("InSetProtocol"),
UNSET("Unset");
private final String packetName, fullName;
private List<String> alias = new ArrayList<>();
private Handshake(String packetName, String... alias) {
this.packetName = packetName;
for(String al : alias)
this.alias.add(HANDSHAKE_PREFIX + al);
this.fullName = HANDSHAKE_PREFIX + packetName;
}
@Override
public String getPacketName() {
return packetName;
}
@Override
public String getFullName() {
return fullName;
}
@Override
public List<String> getAlias() {
return alias;
}
}
}
@@ -1,92 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom;
import java.util.HashMap;
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.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.plugin.Plugin;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.ChannelAbstract;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.INC2Channel;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.INCChannel;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.channel.NMUChannel;
import me.dadus33.chatitem.utils.Utils;
import me.dadus33.chatitem.utils.Version;
public class CustomPacketManager extends PacketManager implements Listener {
private ChannelAbstract channel;
private Plugin pl;
public HashMap<Object, Integer> protocolVersionPerChannel = new HashMap<>();
private boolean isStarted = false;
public CustomPacketManager(Plugin pl) {
this.pl = pl;
Version version = Version.getVersion();
if (version.isNewerOrEquals(Version.V1_17))
channel = new INC2Channel(this);
else if (version.equals(Version.V1_7))
channel = new NMUChannel(this);
else
channel = new INCChannel(this);
pl.getServer().getPluginManager().registerEvents(this, pl);
// we wait the start server
Bukkit.getScheduler().runTaskLater(pl, () -> {
isStarted = true;
for(Player p : Utils.getOnlinePlayers())
addPlayer(p);
}, 20);
}
public Plugin getPlugin() {
return pl;
}
@EventHandler
public void onJoin(PlayerJoinEvent e) {
addPlayer(e.getPlayer());
}
@EventHandler
public void onQuit(PlayerQuitEvent e) {
removePlayer(e.getPlayer());
}
@Override
public void addPlayer(Player p) {
if(isStarted)
channel.addPlayer(p);
}
@Override
public void removePlayer(Player p) {
channel.removePlayer(p);
}
@Override
public void stop() {
for(Player player : Utils.getOnlinePlayers())
removePlayer(player);
if(channel.getAddChannelExecutor() != null)
channel.getAddChannelExecutor().shutdownNow();
if(channel.getRemoveChannelExecutor() != null)
channel.getRemoveChannelExecutor().shutdownNow();
}
public ChatItemPacket onPacketSent(PacketType type, Player sender, Object packet) {
if(type == null) {
return null;
}
ChatItemPacket customPacket = new ChatItemPacket(type, packet, sender);
notifyHandlersSent(customPacket);
return customPacket;
}
}
@@ -1,86 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.ItemPlayer;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
public abstract class ChannelAbstract {
private ExecutorService addChannelExecutor, removeChannelExecutor;
static final String KEY_HANDSHAKE = "packet_handshake_chatitem", KEY_HANDLER_SERVER = "packet_handler", KEY_SERVER = "packet_server_chatitem";
private CustomPacketManager customPacketManager;
private HashSet<UUID> players = new HashSet<>();
protected ChannelAbstract(CustomPacketManager customPacketManager) {
this.customPacketManager = customPacketManager;
}
public CustomPacketManager getPacketManager() {
return customPacketManager;
}
public ExecutorService getAddChannelExecutor() {
return addChannelExecutor;
}
public ExecutorService getOrCreateAddChannelExecutor() {
if(addChannelExecutor == null || addChannelExecutor.isTerminated())
addChannelExecutor = Executors.newSingleThreadExecutor();
return addChannelExecutor;
}
public ExecutorService getRemoveChannelExecutor() {
return removeChannelExecutor;
}
public ExecutorService getOrCreateRemoveChannelExecutor() {
if(removeChannelExecutor == null || removeChannelExecutor.isTerminated())
removeChannelExecutor = Executors.newSingleThreadExecutor();
return removeChannelExecutor;
}
public void addPlayer(Player p) {
if(players.add(p.getUniqueId())) {
addChannel(p, p.getUniqueId().toString());
try {
Integer protocol = customPacketManager.protocolVersionPerChannel.remove(getChannel(p));
if(protocol != null)
ItemPlayer.getPlayer(p).setProtocolVersion(protocol);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void removePlayer(Player p) {
if(players.remove(p.getUniqueId()))
removeChannel(p, p.getUniqueId().toString());
}
public void removeAllPlayers() {
new ArrayList<>(players).forEach((uuid) -> {
Player p = Bukkit.getPlayer(uuid);
if(p != null) // player don't left
removeChannel(Bukkit.getPlayer(uuid), uuid.toString());
});
players.clear();
}
protected abstract void stopPipelines();
public abstract void addChannel(Player player, String endChannelName);
public abstract void removeChannel(Player player, String endChannelName);
public abstract Object getChannel(Player p) throws Exception;
}
@@ -1,83 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
public class ChannelInboundHandler extends ChannelInboundHandlerAdapter {
private CustomPacketManager packetManager;
private List<ChannelPipeline> pipelines = new ArrayList<>();
public ChannelInboundHandler(CustomPacketManager packetManager) {
this.packetManager = packetManager;
}
public void clean() {
pipelines.forEach(ChannelPipeline::removeFirst);
pipelines.clear();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ctx.fireChannelRead(msg);
ChannelPipeline pipe = ((Channel) msg).pipeline();
pipelines.add(pipe);
pipe.addFirst(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
try {
channel.eventLoop().submit(() -> {
try {
ChannelHandler interceptor = channel.pipeline().get(ChannelAbstract.KEY_HANDSHAKE);
// Inject our packet interceptor
if (interceptor == null) {
interceptor = new ChannelHandlerHandshakeReceive(channel);
channel.pipeline().addBefore("packet_handler", ChannelAbstract.KEY_HANDSHAKE, interceptor);
}
return interceptor;
} catch (IllegalArgumentException e) {
// Try again
return channel.pipeline().get(ChannelAbstract.KEY_HANDSHAKE);
}
});
} catch (Exception e) {
packetManager.getPlugin().getLogger().log(Level.SEVERE, "Cannot inject incoming channel " + channel, e);
}
}
});
}
public class ChannelHandlerHandshakeReceive extends ChannelInboundHandlerAdapter {
private Channel channel;
public ChannelHandlerHandshakeReceive(Channel channel) {
this.channel = channel;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object packet) {
try {
PacketType packetType = PacketType.getType(packet.getClass().getSimpleName());
if(packetType != null && packetType == PacketType.Handshake.IS_SET_PROTOCOL) {
packetManager.protocolVersionPerChannel.put(channel, new PacketContent(packet).getIntegers().readSafely(0, 0));
}
super.channelRead(ctx, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@@ -1,110 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import static me.dadus33.chatitem.utils.PacketUtils.getPlayerConnection;
import java.util.List;
import java.util.NoSuchElementException;
import org.bukkit.entity.Player;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Version;
public class INC2Channel extends ChannelAbstract {
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
@SuppressWarnings("unchecked")
public INC2Channel(CustomPacketManager customPacketManager) {
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
try {
Object mcServer = ReflectionUtils.callMethod(PacketUtils.getCraftServer(), Version.getVersion().equals(Version.V1_17) ? "getServer" : "b");
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "server.network."));
((List<ChannelFuture>) ReflectionUtils.getObject(co, "f")).forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void stopPipelines() {
pipeline.remove(boundHandler);
boundHandler.clean();
}
@Override
public void addChannel(final Player player, String endChannelName) {
getOrCreateAddChannelExecutor().execute(() -> {
if(!player.isOnline())
return;
try {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
} catch (IllegalArgumentException e) {
if(e.getMessage().contains("Duplicate handler")) {
removeChannel(player, endChannelName);
addChannel(player, endChannelName);
} else
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void removeChannel(Player player, String endChannelName) {
getOrCreateRemoveChannelExecutor().execute(() -> {
try {
final Channel channel = getChannel(player);
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
channel.pipeline().remove(KEY_SERVER + endChannelName);
} catch (Exception e) {
ChatItem.getInstance().getLogger().warning("Failed to remove channel for " + player.getName() + ". Reason: " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
}
});
}
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = ReflectionUtils.getObject(getPlayerConnection(p), Version.getVersion().isNewerOrEquals(Version.V1_19) ? "b" : "a");
return ReflectionUtils.getFirstWith(playerConnection, playerConnection.getClass(), Channel.class);//(Channel) networkManager.getClass().getDeclaredField("channel").get(networkManager);
}
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
private final Player owner;
public ChannelHandlerSent(Player player) {
this.owner = player;
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
}
@@ -1,123 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import static me.dadus33.chatitem.utils.PacketUtils.getPlayerConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
import org.bukkit.entity.Player;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.ChannelPromise;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
@SuppressWarnings("unchecked")
public class INCChannel extends ChannelAbstract {
private final ChannelInboundHandler boundHandler;
private ChannelPipeline pipeline;
public INCChannel(CustomPacketManager customPacketManager) {
super(customPacketManager);
boundHandler = new ChannelInboundHandler(customPacketManager);
getFuturChannel().forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler);
});
}
public List<ChannelFuture> getFuturChannel() {
try {
Object dedicatedSrv = PacketUtils.getCraftServer();
Object mcServer = dedicatedSrv.getClass().getMethod("getServer").invoke(dedicatedSrv);
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "network."));
try {
return (List<ChannelFuture>) ReflectionUtils.getPrivateField(co, "g");
} catch (NoSuchFieldException e) {
return (List<ChannelFuture>) ReflectionUtils.getPrivateField(co, "listeningChannels");
}
} catch (Exception e) {
e.printStackTrace();
return new ArrayList<>();
}
}
@Override
protected void stopPipelines() {
pipeline.remove(boundHandler);
boundHandler.clean();
}
@Override
public void addChannel(final Player player, String endChannelName) {
getOrCreateAddChannelExecutor().execute(() -> {
if(!player.isOnline())
return;
try {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
} catch (IllegalArgumentException e) {
if(e.getMessage().contains("Duplicate handler")) {
removeChannel(player, endChannelName);
addChannel(player, endChannelName);
} else
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void removeChannel(Player player, String endChannelName) {
getOrCreateRemoveChannelExecutor().execute(() -> {
try {
final Channel channel = getChannel(player);
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
channel.pipeline().remove(KEY_SERVER + endChannelName);
} catch (Exception e) {
ChatItem.getInstance().getLogger().warning("Failed to remove channel for " + player.getName() + ". Reason: " + e.getMessage() + " (" + e.getStackTrace()[0].toString() + ")");
}
});
}
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = getPlayerConnection(p);
Object networkManager = playerConnection.getClass().getField("networkManager").get(playerConnection);
return new PacketContent(networkManager).getSpecificModifier(Channel.class).readSafely(0);//(Channel) networkManager.getClass().getDeclaredField("channel").get(networkManager);
}
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
private final Player owner;
public ChannelHandlerSent(Player player) {
this.owner = player;
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
}
@@ -1,167 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets.custom.channel;
import static me.dadus33.chatitem.utils.PacketUtils.getPlayerConnection;
import java.lang.reflect.Field;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.logging.Level;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketContent;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
import me.dadus33.chatitem.chatmanager.v1.packets.custom.CustomPacketManager;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import net.minecraft.util.io.netty.channel.Channel;
import net.minecraft.util.io.netty.channel.ChannelFuture;
import net.minecraft.util.io.netty.channel.ChannelHandler;
import net.minecraft.util.io.netty.channel.ChannelHandlerContext;
import net.minecraft.util.io.netty.channel.ChannelInboundHandlerAdapter;
import net.minecraft.util.io.netty.channel.ChannelInitializer;
import net.minecraft.util.io.netty.channel.ChannelOutboundHandlerAdapter;
import net.minecraft.util.io.netty.channel.ChannelPipeline;
import net.minecraft.util.io.netty.channel.ChannelPromise;
public class NMUChannel extends ChannelAbstract {
private ChannelInboundHandlerAdapter boundHandler;
private ChannelPipeline pipeline;
public NMUChannel(CustomPacketManager customPacketManager) {
super(customPacketManager);
try {
Object dedicatedSrv = PacketUtils.getCraftServer();
Object mcServer = dedicatedSrv.getClass().getMethod("getServer").invoke(dedicatedSrv);
Object co = ReflectionUtils.getFirstWith(mcServer, PacketUtils.getNmsClass("MinecraftServer", "server."), PacketUtils.getNmsClass("ServerConnection", "network."));
@SuppressWarnings("unchecked")
List<ChannelFuture> g = (List<ChannelFuture>) ReflectionUtils.getObject(co, "g", "e");
g.forEach((channelFuture) -> {
pipeline = channelFuture.channel().pipeline();
pipeline.addFirst(boundHandler = new ChannelInboundHandlerAdapter() {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
((Channel) msg).pipeline().addFirst(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel channel) {
try {
channel.eventLoop().submit(() -> {
try {
ChannelHandler interceptor = channel.pipeline().get(KEY_HANDSHAKE);
// Inject our packet interceptor
if (interceptor == null) {
interceptor = new ChannelHandlerHandshakeReceive(channel);
channel.pipeline().addBefore("packet_handler", KEY_HANDSHAKE, interceptor);
}
return interceptor;
} catch (IllegalArgumentException e) {
// Try again
return channel.pipeline().get(KEY_HANDSHAKE);
}
});
} catch (Exception e) {
getPacketManager().getPlugin().getLogger().log(Level.SEVERE, "Cannot inject incomming channel " + channel, e);
}
}
});
ctx.fireChannelRead(msg);
}
});
});
} catch (Exception e) {
e.printStackTrace();
}
}
@Override
protected void stopPipelines() {
pipeline.remove(boundHandler);
}
@Override
public void addChannel(final Player player, String endChannelName) {
getOrCreateAddChannelExecutor().execute(() -> {
try {
Channel channel = getChannel(player);
// Managing outgoing packet (to the player)
channel.pipeline().addAfter(KEY_HANDLER_SERVER, KEY_SERVER + endChannelName, new ChannelHandlerSent(player));
} catch (NoSuchElementException e) {
// appear when the player's channel isn't accessible because of reload.
getPacketManager().getPlugin().getLogger().warning("Please, don't use reload, this can produce some problem. Currently, " + player.getName() + " isn't fully checked because of that. More details: " + e.getMessage() + " (NoSuchElementException)");
} catch (IllegalArgumentException e) {
if(e.getMessage().contains("Duplicate")) {
removeChannel(player, endChannelName);
addChannel(player, endChannelName);
} else
getPacketManager().getPlugin().getLogger().severe("Error while loading Packet channel. " + e.getMessage() + ". Please, prefer restart than reload.");
} catch (Exception e) {
e.printStackTrace();
}
});
}
@Override
public void removeChannel(Player player, String endChannelName) {
getOrCreateRemoveChannelExecutor().execute(() -> {
try {
final Channel channel = getChannel(player);
if(channel.pipeline().get(KEY_SERVER + endChannelName) != null)
channel.pipeline().remove(KEY_SERVER + endChannelName);
} catch (Exception e) {}
});
}
@Override
public Channel getChannel(Player p) throws Exception {
Object playerConnection = getPlayerConnection(p);
Object networkManager = playerConnection.getClass().getField("networkManager").get(playerConnection);
for (Field field : networkManager.getClass().getDeclaredFields())
if (field.getType().equals(Channel.class)) {
field.setAccessible(true);
return (Channel) field.get(networkManager);
}
return null;
}
private class ChannelHandlerSent extends ChannelOutboundHandlerAdapter {
private final Player owner;
public ChannelHandlerSent(Player player) {
this.owner = player;
}
@Override
public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception {
ChatItemPacket nextPacket = getPacketManager().onPacketSent(PacketType.getType(packet.getClass().getSimpleName()), owner, packet);
if(nextPacket != null && nextPacket.isCancelled())
return;
super.write(ctx, nextPacket == null ? packet : nextPacket.getPacket(), promise);
}
}
private class ChannelHandlerHandshakeReceive extends ChannelInboundHandlerAdapter {
private final Channel channel;
public ChannelHandlerHandshakeReceive(Channel channel) {
this.channel = channel;
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object packet) {
try {
PacketType packetType = PacketType.getType(packet.getClass().getSimpleName());
if(packetType != null && packetType == PacketType.Handshake.IS_SET_PROTOCOL) {
getPacketManager().protocolVersionPerChannel.put(channel, new PacketContent(packet).getIntegers().readSafely(1, 0));
}
super.channelRead(ctx, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@@ -1,64 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.packets.protocollib;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.entity.Player;
import com.comphenix.protocol.PacketType.Play;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.ProtocolManager;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketEvent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.v1.listeners.HandshakeListener;
import me.dadus33.chatitem.chatmanager.v1.packets.ChatItemPacket;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketManager;
import me.dadus33.chatitem.chatmanager.v1.packets.PacketType;
public class ProtocollibPacketManager extends PacketManager {
private final ProtocolManager protocolManager;
public ProtocollibPacketManager(ChatItem pl) {
protocolManager = ProtocolLibrary.getProtocolManager();
List<com.comphenix.protocol.PacketType> list = new ArrayList<>();
list.add(Play.Server.CHAT);
try {
list.add((com.comphenix.protocol.PacketType) Play.Server.class.getDeclaredField("SYSTEM_CHAT").get(null));
} catch (Exception e) {
// ignore because using old version
}
protocolManager.addPacketListener(new PacketAdapter(pl, ListenerPriority.LOWEST, list) {
@Override
public void onPacketSending(PacketEvent e) {
Player p = e.getPlayer();
if (p == null || e.isPlayerTemporary())
return;
ChatItemPacket packet = onPacketSent(PacketType.getType(e.getPacket().getHandle().getClass().getSimpleName()), p, e.getPacket().getHandle());
if(packet == null) {
ChatItem.debug("Can't find packet: " + e.getPacket().getHandle().getClass().getName());
return;
}
if(!e.isCancelled())
e.setCancelled(packet.isCancelled());
}
});
protocolManager.addPacketListener(new HandshakeListener(pl));
}
@Override
public void stop() {
protocolManager.removePacketListeners(ChatItem.getInstance());
}
public ChatItemPacket onPacketSent(PacketType type, Player sender, Object packet) {
if(type == null)
return null;
ChatItemPacket customPacket = new ChatItemPacket(type, packet, sender);
notifyHandlersSent(customPacket);
return customPacket;
}
}
@@ -1,44 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
@Deprecated
public class Item {
private String id;
private byte amount;
private short data;
private CompoundTag tag;
public CompoundTag getTag(){
return tag;
}
public void setTag(CompoundTag newTag){
this.tag = newTag;
}
public void setId(String newId){
this.id = newId;
}
public void setData(short newData){
data = newData;
}
public String getId(){
return id;
}
public short getData(){
return data;
}
public void setAmount(byte newAmount){
this.amount = newAmount;
}
public byte getAmount(){
return amount;
}
}
@@ -1,50 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import static me.dadus33.chatitem.utils.Version.V1_10;
import static me.dadus33.chatitem.utils.Version.V1_11;
import static me.dadus33.chatitem.utils.Version.V1_8;
import static me.dadus33.chatitem.utils.Version.V1_9;
import org.bukkit.inventory.ItemStack;
@Deprecated
public class ItemRewriter {
public static String remapIds(int server, int player, ItemStack is) {
Item item = new Item();
item.setAmount((byte)is.getAmount());
//item.setData(is.getDurability());
//item.setId(id);
//item.setTag(tag);
if (areIdsCompatible(server, player)) {
return item.getId();
}
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER) || (player >= V1_9.MIN_VER && server <= V1_8.MAX_VER)) {
if ((server >= V1_9.MIN_VER && player <= V1_8.MAX_VER)) {
ItemRewriter_1_9_TO_1_8.reversedToClient(item);
} else
ItemRewriter_1_9_TO_1_8.toClient(item);
}
if ((server <= V1_10.MAX_VER && player >= V1_11.MIN_VER)
|| (player <= V1_10.MAX_VER && server >= V1_11.MIN_VER)) {
if (server <= V1_10.MAX_VER && player >= V1_11.MIN_VER) {
ItemRewriter_1_11_TO_1_10.toClient(item);
} else {
ItemRewriter_1_11_TO_1_10.reverseToClient(item);
}
}
return item.getId();
}
public static boolean areIdsCompatible(int version1, int version2) {
if ((version1 >= V1_9.MIN_VER && version2 <= V1_8.MAX_VER)
|| (version2 >= V1_9.MIN_VER && version1 <= V1_8.MAX_VER)) {
return false;
}
if ((version1 <= V1_10.MAX_VER && version2 >= V1_11.MIN_VER)
|| (version1 <= V1_10.MAX_VER && version2 >= V1_11.MIN_VER)) {
return false;
}
return true;
}
}
@@ -1,132 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
/**
* Thanks to the developers of ViaVersion for this!
*/
@Deprecated
public class ItemRewriter_1_11_TO_1_10 {
private static BiMap<String, String> oldToNewNames = HashBiMap.create();
static {
oldToNewNames.put("AreaEffectCloud", "minecraft:area_effect_cloud");
oldToNewNames.put("ArmorStand", "minecraft:armor_stand");
oldToNewNames.put("Arrow", "minecraft:arrow");
oldToNewNames.put("Bat", "minecraft:bat");
oldToNewNames.put("Blaze", "minecraft:blaze");
oldToNewNames.put("Boat", "minecraft:boat");
oldToNewNames.put("CaveSpider", "minecraft:cave_spider");
oldToNewNames.put("Chicken", "minecraft:chicken");
oldToNewNames.put("Cow", "minecraft:cow");
oldToNewNames.put("Creeper", "minecraft:creeper");
oldToNewNames.put("Donkey", "minecraft:donkey");
oldToNewNames.put("DragonFireball", "minecraft:dragon_fireball");
oldToNewNames.put("ElderGuardian", "minecraft:elder_guardian");
oldToNewNames.put("EnderCrystal", "minecraft:ender_crystal");
oldToNewNames.put("EnderDragon", "minecraft:ender_dragon");
oldToNewNames.put("Enderman", "minecraft:enderman");
oldToNewNames.put("Endermite", "minecraft:endermite");
oldToNewNames.put("EntityHorse", "minecraft:horse");
oldToNewNames.put("EyeOfEnderSignal", "minecraft:eye_of_ender_signal");
oldToNewNames.put("FallingSand", "minecraft:falling_block");
oldToNewNames.put("Fireball", "minecraft:fireball");
oldToNewNames.put("FireworksRocketEntity", "minecraft:fireworks_rocket");
oldToNewNames.put("Ghast", "minecraft:ghast");
oldToNewNames.put("Giant", "minecraft:giant");
oldToNewNames.put("Guardian", "minecraft:guardian");
oldToNewNames.put("Husk", "minecraft:husk");
oldToNewNames.put("Item", "minecraft:item");
oldToNewNames.put("ItemFrame", "minecraft:item_frame");
oldToNewNames.put("LavaSlime", "minecraft:magma_cube");
oldToNewNames.put("LeashKnot", "minecraft:leash_knot");
oldToNewNames.put("MinecartChest", "minecraft:chest_minecart");
oldToNewNames.put("MinecartCommandBlock", "minecraft:commandblock_minecart");
oldToNewNames.put("MinecartFurnace", "minecraft:furnace_minecart");
oldToNewNames.put("MinecartHopper", "minecraft:hopper_minecart");
oldToNewNames.put("MinecartRideable", "minecraft:minecart");
oldToNewNames.put("MinecartSpawner", "minecraft:spawner_minecart");
oldToNewNames.put("MinecartTNT", "minecraft:tnt_minecart");
oldToNewNames.put("Mule", "minecraft:mule");
oldToNewNames.put("MushroomCow", "minecraft:mooshroom");
oldToNewNames.put("Ozelot", "minecraft:ocelot");
oldToNewNames.put("Painting", "minecraft:painting");
oldToNewNames.put("Pig", "minecraft:pig");
oldToNewNames.put("PigZombie", "minecraft:zombie_pigman");
oldToNewNames.put("PolarBear", "minecraft:polar_bear");
oldToNewNames.put("PrimedTnt", "minecraft:tnt");
oldToNewNames.put("Rabbit", "minecraft:rabbit");
oldToNewNames.put("Sheep", "minecraft:sheep");
oldToNewNames.put("Shulker", "minecraft:shulker");
oldToNewNames.put("ShulkerBullet", "minecraft:shulker_bullet");
oldToNewNames.put("Silverfish", "minecraft:silverfish");
oldToNewNames.put("Skeleton", "minecraft:skeleton");
oldToNewNames.put("SkeletonHorse", "minecraft:skeleton_horse");
oldToNewNames.put("Slime", "minecraft:slime");
oldToNewNames.put("SmallFireball", "minecraft:small_fireball");
oldToNewNames.put("Snowball", "minecraft:snowball");
oldToNewNames.put("SnowMan", "minecraft:snowman");
oldToNewNames.put("SpectralArrow", "minecraft:spectral_arrow");
oldToNewNames.put("Spider", "minecraft:spider");
oldToNewNames.put("Squid", "minecraft:squid");
oldToNewNames.put("Stray", "minecraft:stray");
oldToNewNames.put("ThrownEgg", "minecraft:egg");
oldToNewNames.put("ThrownEnderpearl", "minecraft:ender_pearl");
oldToNewNames.put("ThrownExpBottle", "minecraft:xp_bottle");
oldToNewNames.put("ThrownPotion", "minecraft:potion");
oldToNewNames.put("Villager", "minecraft:villager");
oldToNewNames.put("VillagerGolem", "minecraft:villager_golem");
oldToNewNames.put("Witch", "minecraft:witch");
oldToNewNames.put("WitherBoss", "minecraft:wither");
oldToNewNames.put("WitherSkeleton", "minecraft:wither_skeleton");
oldToNewNames.put("WitherSkull", "minecraft:wither_skull");
oldToNewNames.put("Wolf", "minecraft:wolf");
oldToNewNames.put("XPOrb", "minecraft:xp_orb");
oldToNewNames.put("Zombie", "minecraft:zombie");
oldToNewNames.put("ZombieHorse", "minecraft:zombie_horse");
oldToNewNames.put("ZombieVillager", "minecraft:zombie_villager");
}
static void toClient(Item item) {
if (hasEntityTag(item)) {
CompoundTag entityTag = item.getTag().get("EntityTag");
if (entityTag.get("id") instanceof StringTag) {
StringTag id = entityTag.get("id");
if (oldToNewNames.containsKey(id.getValue())) {
id.setValue(oldToNewNames.get(id.getValue()));
}
}
}
}
static void reverseToClient(Item item) {
if (hasEntityTag(item)) {
CompoundTag entityTag = item.getTag().get("EntityTag");
if (entityTag.get("id") instanceof StringTag) {
StringTag id = entityTag.get("id");
if (oldToNewNames.containsKey(id.getValue())) {
id.setValue(oldToNewNames.get(id.getValue()));
}
}
}
}
private static boolean hasEntityTag(Item item) {
if (item != null && item.getId().equals("minecraft:spawn_egg")) { // Monster Egg
CompoundTag tag = item.getTag();
if (tag != null && tag.contains("EntityTag") && tag.get("EntityTag") instanceof CompoundTag) {
if (((CompoundTag) tag.get("EntityTag")).get("id") instanceof StringTag) {
return true;
}
}
}
return false;
}
}
@@ -1,342 +0,0 @@
package me.dadus33.chatitem.chatmanager.v1.utils;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import java.util.HashMap;
import java.util.Map;
/**
* Thanks to the developers of ViaVersion for this!
*/
@Deprecated
public class ItemRewriter_1_9_TO_1_8 {
private static final Map<String, Integer> ENTTIY_NAME_TO_ID = new HashMap<>();
private static final Map<Integer, String> ENTTIY_ID_TO_NAME = new HashMap<>();
private static final Map<String, Integer> POTION_NAME_TO_ID = new HashMap<>();
private static final Map<Integer, String> POTION_ID_TO_NAME = new HashMap<>();
private static final Map<Integer, Integer> POTION_INDEX = new HashMap<>();
static {
/* Entities */
registerEntity(1, "Item");
registerEntity(2, "XPOrb");
registerEntity(7, "ThrownEgg");
registerEntity(8, "LeashKnot");
registerEntity(9, "Painting");
registerEntity(10, "Arrow");
registerEntity(11, "Snowball");
registerEntity(12, "Fireball");
registerEntity(13, "SmallFireball");
registerEntity(14, "ThrownEnderpearl");
registerEntity(15, "EyeOfEnderSignal");
registerEntity(16, "ThrownPotion");
registerEntity(17, "ThrownExpBottle");
registerEntity(18, "ItemFrame");
registerEntity(19, "WitherSkull");
registerEntity(20, "PrimedTnt");
registerEntity(21, "FallingSand");
registerEntity(22, "FireworksRocketEntity");
registerEntity(30, "ArmorStand");
registerEntity(40, "MinecartCommandBlock");
registerEntity(41, "Boat");
registerEntity(42, "MinecartRideable");
registerEntity(43, "MinecartChest");
registerEntity(44, "MinecartFurnace");
registerEntity(45, "MinecartTNT");
registerEntity(46, "MinecartHopper");
registerEntity(47, "MinecartSpawner");
registerEntity(48, "Mob");
registerEntity(49, "Monster");
registerEntity(50, "Creeper");
registerEntity(51, "Skeleton");
registerEntity(52, "Spider");
registerEntity(53, "Giant");
registerEntity(54, "Zombie");
registerEntity(55, "Slime");
registerEntity(56, "Ghast");
registerEntity(57, "PigZombie");
registerEntity(58, "Enderman");
registerEntity(59, "CaveSpider");
registerEntity(60, "Silverfish");
registerEntity(61, "Blaze");
registerEntity(62, "LavaSlime");
registerEntity(63, "EnderDragon");
registerEntity(64, "WitherBoss");
registerEntity(65, "Bat");
registerEntity(66, "Witch");
registerEntity(67, "Endermite");
registerEntity(68, "Guardian");
registerEntity(90, "Pig");
registerEntity(91, "Sheep");
registerEntity(92, "Cow");
registerEntity(93, "Chicken");
registerEntity(94, "Squid");
registerEntity(95, "Wolf");
registerEntity(96, "MushroomCow");
registerEntity(97, "SnowMan");
registerEntity(98, "Ozelot");
registerEntity(99, "VillagerGolem");
registerEntity(100, "EntityHorse");
registerEntity(101, "Rabbit");
registerEntity(120, "Villager");
registerEntity(200, "EnderCrystal");
/* Potions */
registerPotion(-1, "empty");
registerPotion(0, "water");
registerPotion(64, "mundane");
registerPotion(32, "thick");
registerPotion(16, "awkward");
registerPotion(8198, "night_vision");
registerPotion(8262, "long_night_vision");
registerPotion(8206, "invisibility");
registerPotion(8270, "long_invisibility");
registerPotion(8203, "leaping");
registerPotion(8267, "long_leaping");
registerPotion(8235, "strong_leaping");
registerPotion(8195, "fire_resistance");
registerPotion(8259, "long_fire_resistance");
registerPotion(8194, "swiftness");
registerPotion(8258, "long_swiftness");
registerPotion(8226, "strong_swiftness");
registerPotion(8202, "slowness");
registerPotion(8266, "long_slowness");
registerPotion(8205, "water_breathing");
registerPotion(8269, "long_water_breathing");
registerPotion(8261, "healing");
registerPotion(8229, "strong_healing");
registerPotion(8204, "harming");
registerPotion(8236, "strong_harming");
registerPotion(8196, "poison");
registerPotion(8260, "long_poison");
registerPotion(8228, "strong_poison");
registerPotion(8193, "regeneration");
registerPotion(8257, "long_regeneration");
registerPotion(8225, "strong_regeneration");
registerPotion(8201, "strength");
registerPotion(8265, "long_strength");
registerPotion(8233, "strong_strength");
registerPotion(8200, "weakness");
registerPotion(8264, "long_weakness");
}
static void toClient(Item item) {
if (item != null) {
if (item.getId().equals("minecraft:spawn_egg") && item.getData() != 0) { // Monster Egg
CompoundTag tag = item.getTag();
if (tag == null) {
tag = new CompoundTag("tag");
}
CompoundTag entityTag = new CompoundTag("EntityTag");
if (ENTTIY_ID_TO_NAME.containsKey((int) item.getData())) {
StringTag id = new StringTag("id", ENTTIY_ID_TO_NAME.get((int) item.getData()));
entityTag.put(id);
tag.put(entityTag);
}
item.setTag(tag);
item.setData((short) 0);
}
if (item.getId().equals("minecraft:potion")) { // Potion
CompoundTag tag = item.getTag();
if (tag == null) {
tag = new CompoundTag("tag");
}
if (item.getData() >= 16384) {
item.setId("minecraft:splash_potion"); // splash id
item.setData((short) (item.getData() - 8192));
}
String name = potionNameFromDamage(item.getData());
StringTag potion = new StringTag("Potion", "minecraft:" + name);
tag.put(potion);
item.setTag(tag);
item.setData((short) 0);
}
}
}
static void reversedToClient(Item item) {
if (item != null) {
if (item.getId().equals("minecraft:spawn_egg") && item.getData() == 0) { // Monster Egg
CompoundTag tag = item.getTag();
int data = 0;
if(tag != null) {
if (tag.get("EntityTag") instanceof CompoundTag) {
CompoundTag entityTag = tag.get("EntityTag");
if (entityTag.get("id") instanceof StringTag) {
StringTag id = entityTag.get("id");
if (ENTTIY_NAME_TO_ID.containsKey(id.getValue()))
data = ENTTIY_NAME_TO_ID.get(id.getValue());
}
tag.remove("EntityTag");
}
}
item.setTag(tag);
item.setData((short) data);
}
if (item.getId().equals("minecraft:potion")) { // Potion
CompoundTag tag = item.getTag();
int data = 0;
if(tag != null) {
if (tag.get("Potion") instanceof StringTag) {
StringTag potion = tag.get("Potion");
String potionName = potion.getValue().replace("minecraft:", "");
if (POTION_NAME_TO_ID.containsKey(potionName)) {
data = POTION_NAME_TO_ID.get(potionName);
}
tag.remove("Potion");
}
}
item.setTag(tag);
item.setData((short) data);
}
// Splash potion
if (item.getId().equals("minecraft:splash_potion")) {
CompoundTag tag = item.getTag();
int data = 0;
item.setId("minecraft:potion"); // Potion
if(tag != null) {
if (tag.get("Potion") instanceof StringTag) {
StringTag potion = tag.get("Potion");
String potionName = potion.getValue().replace("minecraft:", "");
if (POTION_NAME_TO_ID.containsKey(potionName)) {
data = POTION_NAME_TO_ID.get(potionName) + 8192;
}
tag.remove("Potion");
}
}
item.setTag(tag);
item.setData((short) data);
}
}
}
private static String potionNameFromDamage(short damage) {
String cached = POTION_ID_TO_NAME.get((int) damage);
if (cached != null) {
return cached;
}
if (damage == 0) {
return "water";
}
int effect = damage & 0xF;
int name = damage & 0x3F;
boolean enhanced = (damage & 0x20) > 0;
boolean extended = (damage & 0x40) > 0;
boolean canEnhance = true;
boolean canExtend = true;
String id;
switch (effect) {
case 1:
id = "regeneration";
break;
case 2:
id = "swiftness";
break;
case 3:
id = "fire_resistance";
canEnhance = false;
break;
case 4:
id = "poison";
break;
case 5:
id = "healing";
canExtend = false;
break;
case 6:
id = "night_vision";
canEnhance = false;
break;
case 8:
id = "weakness";
canEnhance = false;
break;
case 9:
id = "strength";
break;
case 10:
id = "slowness";
canEnhance = false;
break;
case 11:
id = "leaping";
break;
case 12:
id = "harming";
canExtend = false;
break;
case 13:
id = "water_breathing";
canEnhance = false;
break;
case 14:
id = "invisibility";
canEnhance = false;
break;
default:
canEnhance = false;
canExtend = false;
switch (name) {
case 0:
id = "mundane";
break;
case 16:
id = "awkward";
break;
case 32:
id = "thick";
break;
default:
id = "empty";
}
}
if (effect > 0) {
if (canEnhance && enhanced) {
id = "strong_" + id;
} else if (canExtend && extended) {
id = "long_" + id;
}
}
return id;
}
private static void registerEntity(Integer id, String name) {
ENTTIY_ID_TO_NAME.put(id, name);
ENTTIY_NAME_TO_ID.put(name, id);
}
private static void registerPotion(Integer id, String name) {
POTION_INDEX.put(id, POTION_ID_TO_NAME.size());
POTION_ID_TO_NAME.put(id, name);
POTION_NAME_TO_ID.put(name, id);
}
}
@@ -1,293 +0,0 @@
package me.dadus33.chatitem.chatmanager.v2;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.hook.DiscordSrvSupport;
import me.dadus33.chatitem.playernamer.PlayerNamerManager;
import me.dadus33.chatitem.utils.ColorManager;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.PacketUtils;
import me.dadus33.chatitem.utils.ReflectionUtils;
import me.dadus33.chatitem.utils.Storage;
import me.dadus33.chatitem.utils.Utils;
import net.md_5.bungee.api.ChatColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.HoverEvent.Action;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
@SuppressWarnings("deprecation")
public class ChatListener implements Listener {
private ChatListenerChatManager manage;
private Method saveMethod;
private boolean shouldUseAppendMethod = false;
public ChatListener(ChatListenerChatManager manage) {
this.manage = manage;
try {
Class<?> nbtTag = PacketUtils.getNmsClass("NBTTagCompound", "nbt.");
Class<?> itemClass = PacketUtils.getNmsClass("ItemStack", "world.item.");
for (Method m : itemClass.getDeclaredMethods()) {
if (m.getParameterTypes().length == 1) {
if (m.getParameterTypes()[0].equals(nbtTag) && m.getReturnType().equals(nbtTag)) {
saveMethod = m;
}
}
}
try {
ComponentBuilder.class.getDeclaredMethod("append", BaseComponent[].class);
shouldUseAppendMethod = true;
} catch (Exception e) {
shouldUseAppendMethod = false;
}
} catch (Exception e) {
}
Logger log = ChatItem.getInstance().getLogger();
String appendMethodMsg = shouldUseAppendMethod ? "Use ComponentBuilder's method."
: "Use own ComponentBuilder append method.";
if (saveMethod == null)
log.info("Failed to find save method. Using default system. " + appendMethodMsg);
else
log.info("Save method founded: " + saveMethod.getName() + ". " + appendMethodMsg);
}
public Storage getStorage() {
return manage.getStorage();
}
@EventHandler(priority = EventPriority.MONITOR)
public void onChat(AsyncPlayerChatEvent e) {
Storage c = getStorage();
if (e.isCancelled()) {
if (ChatItem.getInstance().getChatManager().size() == 1) { // only chat
String msg = e.getMessage().toLowerCase();
for (String rep : c.PLACEHOLDERS) {
if (msg.contains(rep)) {
ChatItem.debug(
"You choose 'chat' manager but it seems to don't be the good choice. More informations here: https://github.com/dadus33-plugins/ChatItem/wiki");
return;
}
}
}
ChatItem.debug("Chat cancelled for " + e.getPlayer().getName());
return;
}
Player p = e.getPlayer();
boolean hasv1 = false;
String placeholder = null;
for (String rep : c.PLACEHOLDERS) {
// v1 try to manage it, but the message have not been changed by another plugin
if (e.getMessage().contains(rep + ChatManager.SEPARATOR + p.getName())) {
hasv1 = true;
ChatItem.debug("Found v1 placeholders in v2");
placeholder = rep;
break;
}
if (e.getMessage().contains(rep)) {
placeholder = rep;
break;
}
}
if (placeholder == null) { // if not found
ChatItem.debug("(v2) Can't found placeholder in: " + e.getMessage() + " > " + PlayerNamerManager.getPlayerNamer().getName(p));
return;
}
ItemStack item = ChatManager.getUsableItem(p);
if(!ChatManager.canShowItem(p, item, e))
return;
e.setCancelled(true);
String format = e.getFormat();
String msg, defMsg = e.getMessage();
for (String rep : c.PLACEHOLDERS) {
if (hasv1) // remove v1 char
defMsg = defMsg.replace(rep + ChatManager.SEPARATOR + p.getName(), String.valueOf(ChatManager.SEPARATOR));
else
defMsg = defMsg.replace(rep, String.valueOf(ChatManager.SEPARATOR));
}
if (Utils.countMatches(defMsg, String.valueOf(ChatManager.SEPARATOR)) > getStorage().LIMIT) {
e.setCancelled(true);
if (getStorage().LIMIT_MESSAGE.isEmpty()) {
return;
}
p.sendMessage(getStorage().LIMIT_MESSAGE);
return;
}
if (format.contains("%1$s") || format.contains("%2$s")) {
msg = (format.contains("%2$s") ? String.format(format, p.getDisplayName(), defMsg)
: String.format(format, p.getDisplayName()));
} else {
msg = format.replace(e.getMessage(), defMsg);
}
String itemName = ChatManager.getNameOfItem(p, item, c);
String loggedMessage = msg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName())
.replace("{display-name}", p.getDisplayName());
Bukkit.getConsoleSender().sendMessage(loggedMessage); // show in log
if (ChatItem.discordSrvSupport)
DiscordSrvSupport.sendChatMessage(p, defMsg.replace(ChatManager.SEPARATOR + "", itemName).replace("{name}", p.getName())
.replace("{display-name}", p.getDisplayName()));
ChatItem.debug("Msg: " + msg.replace(ChatColor.COLOR_CHAR, '&') + ", format: " + format);
e.getRecipients().forEach((pl) -> showItem(pl, p, item, msg));
if (c.COOLDOWN > 0 && !p.hasPermission("chatitem.ignore-cooldown")) {
ChatManager.COOLDOWNS.put(p.getUniqueId(), System.currentTimeMillis() / 1000);
}
}
private void showItem(Player to, Player origin, ItemStack item, String msg) {
ComponentBuilder builder = new ComponentBuilder("");
ChatColor color = ChatColor.WHITE;
String colorCode = "", text = "";
boolean waiting = false;
for (char args : msg.toCharArray()) {
if (args == '§') { // begin of color
if (colorCode.isEmpty() && !text.isEmpty()) { // text before this char
ChatItem.debug("Append " + text);
appendToComponentBuilder(builder, new ComponentBuilder(text).color(color).create());
text = "";
}
waiting = true; // waiting for color code
} else if (waiting) { // if waiting for code and valid str
// if it's hexademical value and with enough space for full color
waiting = false;
if(args == 'r' && colorCode.isEmpty()) {
color = ChatColor.RESET;
continue;
}
if(args == 'x' && !colorCode.isEmpty()) {
text += ColorManager.getColorString(colorCode);
colorCode = "x";
} else
colorCode += args; // a color by itself
} else {
waiting = false;
if(!colorCode.isEmpty()) {
if(colorCode.startsWith("x") && colorCode.length() >= 7) {
if(colorCode.length() == 7)
color = ColorManager.getColor(colorCode);
else {
color = ColorManager.getColor(colorCode.substring(0, 7)); // only the hex code
ChatItem.debug("Adding color for " + colorCode.substring(7, colorCode.length()) + " (in " + colorCode + ")");
text += ColorManager.getColorString(colorCode.substring(7, colorCode.length()));
}
} else if(colorCode.length() == 1) // if only one color code
color = ColorManager.getColor(colorCode);
else
text += ColorManager.getColorString(colorCode);
colorCode = "";
}
if (args == ChatManager.SEPARATOR) {
// here put the item
appendToComponentBuilder(builder, new ComponentBuilder(text).color(color).create());
addItem(builder, to, origin, item);
text = "";
} else {
// basic text, not waiting for code after '§'
text += args;
}
}
}
if(!text.isEmpty())
appendToComponentBuilder(builder, new ComponentBuilder(text).color(color).create());
to.spigot().sendMessage(builder.create());
}
/**
* Converts an {@link org.bukkit.inventory.ItemStack} to a Json string for
* sending with {@link net.md_5.bungee.api.chat.BaseComponent}'s.
*
* @param itemStack the item to convert
* @return the Json string representation of the item
*/
public String convertItemStackToJson(ItemStack itemStack) {
try {
Class<?> nbtTag = PacketUtils.getNmsClass("NBTTagCompound", "nbt.");
Class<?> craftItemClass = PacketUtils.getObcClass("inventory.CraftItemStack");
Object nmsNbtTagCompoundObj = nbtTag.getConstructor().newInstance();
if (saveMethod == null) {
Object nmsItemStackObj = craftItemClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, itemStack);
return nmsItemStackObj.getClass().getMethod("save", nbtTag)
.invoke(nmsItemStackObj, nmsNbtTagCompoundObj).toString();
} else {
Object nmsItemStackObj = craftItemClass.getMethod("asNMSCopy", ItemStack.class).invoke(null, itemStack);
return saveMethod.invoke(nmsItemStackObj, nmsNbtTagCompoundObj).toString();
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public void addItem(ComponentBuilder builder, Player to, Player origin, ItemStack item) {
if (!ItemUtils.isEmpty(item)) {
ComponentBuilder itemComponent = new ComponentBuilder(ChatManager.styleItem(to, item, getStorage()));
String itemJson = convertItemStackToJson(item);
itemComponent.event(new HoverEvent(Action.SHOW_ITEM, new ComponentBuilder(itemJson).create()));
appendToComponentBuilder(builder, itemComponent.create());
} else {
String handName = getStorage().HAND_NAME;
ComponentBuilder handComp = new ComponentBuilder("");
ComponentBuilder handTooltip = new ComponentBuilder("");
int stay = getStorage().HAND_TOOLTIP.size();
for (String line : getStorage().HAND_TOOLTIP) {
stay--;
handTooltip.append(
line.replace("{name}", origin.getName()).replace("{display-name}", origin.getDisplayName()));
if (stay > 0)
handTooltip.append("\n");
}
handComp.event(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(handTooltip.create())));
if (handName.contains("{name}")) {
String[] splitted = handName.split("\\{name\\}");
for (int i = 0; i < (splitted.length - 1); i++) {
handComp.append(splitted[i]);
appendToComponentBuilder(handComp, PlayerNamerManager.getPlayerNamer().getName(origin));
}
handComp.append(splitted[splitted.length - 1]);
} else
handComp.append(handName.replace("{display-name}", origin.getDisplayName()));
appendToComponentBuilder(builder, handComp.create());
}
}
@SuppressWarnings("unchecked")
public void appendToComponentBuilder(ComponentBuilder builder, BaseComponent[] comps) {
if (shouldUseAppendMethod) {
try {
builder.append(comps);
} catch (Exception e) {
ChatItem.getInstance().getLogger().severe(
"This should NEVER append. The ComponentBuilder#append(BaseComponent[]) was found but it's NOT. Using own next time.");
shouldUseAppendMethod = false;
}
} else {
try {
Field currentField = ReflectionUtils.getField(builder, "current");
List<BaseComponent> parts = (List<BaseComponent>) ReflectionUtils.getObject(builder, "parts");
parts.add(new TextComponent((TextComponent) currentField.get(builder)));
parts.addAll(Arrays.asList(comps));
currentField.set(builder, new TextComponent(""));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@@ -1,51 +0,0 @@
package me.dadus33.chatitem.chatmanager.v2;
import org.bukkit.Bukkit;
import org.bukkit.event.HandlerList;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.utils.Storage;
public class ChatListenerChatManager extends ChatManager {
private final ChatListener chatListener;
private boolean baseComponentAvailable = true;
public ChatListenerChatManager(ChatItem pl) {
chatListener = new ChatListener(this);
//Check for existence of BaseComponent class (only on spigot)
try {
Class.forName("net.md_5.bungee.api.chat.BaseComponent");
} catch (ClassNotFoundException e) {
baseComponentAvailable = false;
}
}
@Override
public String getName() {
return "ChatListener";
}
@Override
public String getId() {
return "chat";
}
@Override
public void load(ChatItem pl, Storage s) {
super.load(pl, s);
Bukkit.getPluginManager().registerEvents(chatListener, pl);
}
@Override
public void unload(ChatItem pl) {
HandlerList.unregisterAll(chatListener);
}
public boolean supportsChatComponentApi(){
return baseComponentAvailable;
}
}
@@ -1,16 +1,18 @@
package me.dadus33.chatitem.commands;
import me.dadus33.chatitem.ChatItem;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import me.dadus33.chatitem.ChatItem;
public class CIReloadCommand implements CommandExecutor {
/**
* Created by Vlad on 30.09.2016.
*/
public class CIReload implements CommandExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
ChatItem.reload(sender);
ChatItem.reload(sender);
return false;
}
}
@@ -1,72 +0,0 @@
package me.dadus33.chatitem.commands;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.listeners.InventoryListener;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.Storage;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
public class ChatItemCommand implements CommandExecutor, TabExecutor {
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) {
Messages.sendMessage(sender, "only-players");
return false;
}
Player p = (Player) sender;
if (args.length == 0) {
Messages.sendMessage(p, "chatitem-cmd.help");
} else if (args[0].equalsIgnoreCase("admin")) {
InventoryListener.open(p);
} else if (args[0].equalsIgnoreCase("reload")) {
ChatItem.reload(sender);
} else if (args[0].equalsIgnoreCase("link") || args[0].equalsIgnoreCase("links")) {
ConfigurationSection config = ChatItem.getInstance().getConfig()
.getConfigurationSection("messages.chatitem-cmd.links");
TextComponent text = new TextComponent(Storage.color(config.getString("begin")));
for (String key : config.getConfigurationSection("list").getKeys(false)) {
ConfigurationSection linkConfig = config.getConfigurationSection("list." + key);
TextComponent linkComp = new TextComponent(Storage.color(linkConfig.getString("message")));
String hover = Storage.color(linkConfig.getString("hover"));
if (hover != null)
linkComp.setHoverEvent(
new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(new ComponentBuilder(hover).create())));
String link = linkConfig.getString("link");
if (link != null)
linkComp.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, link));
text.addExtra(linkComp);
}
p.spigot().sendMessage(text);
} else {
Messages.sendMessage(p, "chatitem-cmd.help");
}
return false;
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] arg) {
List<String> list = new ArrayList<>();
String prefix = arg[arg.length - 1].toLowerCase(Locale.ROOT);
for (String s : Arrays.asList("help", "admin", "reload", "link"))
if (prefix.isEmpty() || s.startsWith(prefix))
list.add(s);
return list.isEmpty() ? null : list;
}
}
@@ -1,7 +1,6 @@
package me.dadus33.chatitem.filters;
import static org.apache.logging.log4j.core.Filter.Result.NEUTRAL;
import me.dadus33.chatitem.utils.Storage;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Marker;
@@ -12,70 +11,92 @@ import org.apache.logging.log4j.message.Message;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.chatmanager.ChatManager;
import me.dadus33.chatitem.utils.Storage;
import java.util.concurrent.CopyOnWriteArrayList;
import static org.apache.logging.log4j.core.Filter.Result.NEUTRAL;
public class Log4jFilter implements Filter {
private Storage c;
private boolean stopped;
private final static CopyOnWriteArrayList<String> ls = new CopyOnWriteArrayList<>();
public Storage c;
public Log4jFilter(Storage st) {
c = st;
((Logger) LogManager.getRootLogger()).addFilter(this);
}
public Log4jFilter(Storage st){
c = st;
((Logger) LogManager.getRootLogger()).addFilter(this);
}
@Override
public Result getOnMismatch() {
return NEUTRAL;
}
@Override
public Result getOnMatch() {
return NEUTRAL;
}
@Override
public Result getOnMismatch() {
return NEUTRAL;
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String s, Object... objects) {
return checkMessage(s);
}
@Override
public Result getOnMatch() {
return NEUTRAL;
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Object o, Throwable throwable) {
return checkMessage(((Message) o).getFormattedMessage());
}
@Override
public Result filter(Logger logger, Level level, Marker marker, String s, Object... objects) {
return checkMessage(s);
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Message message, Throwable throwable) {
return checkMessage(message.getFormattedMessage());
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Object o, Throwable throwable) {
return checkMessage(((Message)o).getFormattedMessage());
}
@Override
public Result filter(LogEvent logEvent) {
return checkMessage(logEvent.getMessage().getFormattedMessage());
}
@Override
public Result filter(Logger logger, Level level, Marker marker, Message message, Throwable throwable) {
return checkMessage(message.getFormattedMessage());
}
public void stop() {
// seems to be required
}
@Override
public Result filter(LogEvent logEvent) {
return checkMessage(logEvent.getMessage().getFormattedMessage());
}
private Result checkMessage(String msg) {
if (msg == null) {
return Result.NEUTRAL;
}
for (String placeholder : c.PLACEHOLDERS) {
if (msg.contains(placeholder)) {
for (Player p : Bukkit.getOnlinePlayers()) {
if (msg.contains(ChatManager.SEPARATOR + p.getName())) {
return Result.DENY;
}
}
@Override
public void start() {
stopped = false;
}
}
}
return Result.NEUTRAL;
}
@Override
public void stop() {
stopped = true;
}
public void setStorage(Storage nst) {
this.c = nst;
}
@Override
public boolean isStarted() {
return !this.stopped;
}
@Override
public boolean isStopped() {
return this.stopped;
}
private Result checkMessage(String msg){
for(String placeholder : c.PLACEHOLDERS){
if(msg.contains(placeholder)){
ls.add(msg);
for(Player p : Bukkit.getOnlinePlayers()){
msg = msg.replaceAll("\\p{C}", "");
if(msg.endsWith(p.getName()) || msg.lastIndexOf(p.getName())+2+p.getName().length()>=msg.length()){
return Result.DENY;
}
}
}
}
return Result.NEUTRAL;
}
public void setStorage(Storage nst){
this.c = nst;
}
}
@@ -1,16 +0,0 @@
package me.dadus33.chatitem.hook;
import org.bukkit.entity.Player;
import github.scarsz.discordsrv.DiscordSRV;
public class DiscordSrvSupport {
public static void sendChatMessage(Player p, String message) {
DiscordSRV pl = DiscordSRV.getPlugin();
if (DiscordSRV.config().getBooleanElse("UseModernPaperChatEvent", false) && pl.isModernChatEventAvailable()) {
return;
}
pl.processChatMessage(p, message, pl.getOptionalChannel("global"), false);
}
}
@@ -1,21 +0,0 @@
package me.dadus33.chatitem.hook;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.inventory.ItemStack;
import com.willfp.ecoenchants.display.EnchantmentCache;
import com.willfp.ecoenchants.enchantments.util.EnchantChecks;
public class EcoEnchantsSupport {
public static List<String> getLores(ItemStack item) {
List<String> lores = new ArrayList<>();
EnchantChecks.getEnchantsOnItem(item).forEach((en, lvl) -> {
lores.add(EnchantmentCache.getEntry(en).getNameWithLevel(lvl));
});
return lores;
}
}
@@ -1,54 +0,0 @@
package me.dadus33.chatitem.itemnamer;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.utils.Storage;
public interface INamer {
/**
* Get priority of this namer.<br>
* Get first name that is not null, with this order:
* - MAJOR
*
*
* @return priority
*/
Priority getPriority();
/**
* Get the name of the item thanks to this namer.
*
* @param item the item to get the name
* @param storage the actual config
* @return the name or null if can't find a name
*/
String getName(Player p, ItemStack item, Storage storage);
enum Priority {
MAJOR(4),
IMPORTANT(3),
MEDIUM(2),
SMALL(1),
MINOR(0);
private final int priority;
Priority(int priority) {
this.priority = priority;
}
public int getPriority() {
return priority;
}
public static List<Priority> getOrderedPriorities() {
return Arrays.stream(values()).sorted((p1, p2) -> p2.getPriority() - p1.getPriority()).collect(Collectors.toList());
}
}
}
@@ -1,76 +0,0 @@
package me.dadus33.chatitem.itemnamer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringJoiner;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.PluginManager;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.itemnamer.INamer.Priority;
import me.dadus33.chatitem.itemnamer.hook.ChatItemTranslationNamer;
import me.dadus33.chatitem.itemnamer.hook.DefaultNamer;
import me.dadus33.chatitem.itemnamer.hook.ItemDisplayNamer;
import me.dadus33.chatitem.itemnamer.hook.LangUtilsNamer;
import me.dadus33.chatitem.utils.Storage;
public class NamerManager {
private static final HashMap<Priority, List<INamer>> NAMER_PER_PRIORITY = new HashMap<>();
public static void load(ChatItem pl) {
NAMER_PER_PRIORITY.clear();
StringJoiner sj = new StringJoiner(", ");
PluginManager pm = Bukkit.getPluginManager();
if(pm.getPlugin("LangUtils") != null) {
addNamer(new LangUtilsNamer());
sj.add("LangUtils");
}
if(sj.length() > 0)
pl.getLogger().info("Loaded namer for plugin " + sj.toString() + ".");
addNamer(new ChatItemTranslationNamer());
addNamer(new ItemDisplayNamer());
addNamer(new DefaultNamer());
}
/**
* Add namer according to his {@link INamer#getPriority()}'s value
*
* @param namer the namer to add
*/
public static void addNamer(INamer namer) {
List<INamer> namers = getOrCreate(namer.getPriority());
namers.add(namer);
}
private static List<INamer> getOrCreate(Priority p){
return NAMER_PER_PRIORITY.computeIfAbsent(p, (a) -> new ArrayList<>());
}
/**
* Get the name of this item, according to this storage.
*
* @param item
* @param storage
* @return the name (should NOT return null)
*/
public static String getName(Player p, ItemStack item, Storage storage) {
for(Priority pr : Priority.getOrderedPriorities()) {
List<INamer> allNamers = NAMER_PER_PRIORITY.get(pr);
if(allNamers == null || allNamers.isEmpty())
continue;
for(INamer namer : allNamers) {
String tmpName = namer.getName(p, item, storage);
if(tmpName != null)
return tmpName;
}
}
return null; // this should NEVER append
}
}
@@ -1,29 +0,0 @@
package me.dadus33.chatitem.itemnamer.hook;
import java.util.HashMap;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.itemnamer.INamer;
import me.dadus33.chatitem.utils.Storage;
public class ChatItemTranslationNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.SMALL;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
HashMap<Short, String> translationSection = storage.TRANSLATIONS.get(item.getType().name());
if (translationSection != null) {
@SuppressWarnings("deprecation")
String translated = translationSection.get(item.getDurability());
return translated;
}
return null;
}
}
@@ -1,23 +0,0 @@
package me.dadus33.chatitem.itemnamer.hook;
import org.apache.commons.lang.WordUtils;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.itemnamer.INamer;
import me.dadus33.chatitem.utils.Storage;
public class DefaultNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.MINOR;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
Material m = item.getType();
return m.equals(Material.TNT) ? "TNT" : WordUtils.capitalize(m.name().replaceAll("_", " ").toLowerCase());
}
}
@@ -1,26 +0,0 @@
package me.dadus33.chatitem.itemnamer.hook;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.itemnamer.INamer;
import me.dadus33.chatitem.utils.Storage;
public class ItemDisplayNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.MEDIUM;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
if(item.hasItemMeta() && item.getItemMeta().hasDisplayName()) {
String name = item.getItemMeta().getDisplayName();
return storage.COLOR_IF_ALREADY_COLORED ? ChatColor.stripColor(name) : name;
}
return null;
}
}
@@ -1,23 +0,0 @@
package me.dadus33.chatitem.itemnamer.hook;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import com.meowj.langutils.lang.LanguageHelper;
import me.dadus33.chatitem.itemnamer.INamer;
import me.dadus33.chatitem.utils.Storage;
public class LangUtilsNamer implements INamer {
@Override
public Priority getPriority() {
return Priority.IMPORTANT;
}
@Override
public String getName(Player p, ItemStack item, Storage storage) {
return LanguageHelper.getItemName(item, p);
}
}
@@ -0,0 +1,10 @@
package me.dadus33.chatitem.json;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
public interface JSONManipulator {
String parse(String json, String[] replacements, ItemStack item, String repl) throws InvocationTargetException, IllegalAccessException, InstantiationException;
}
@@ -0,0 +1,298 @@
package me.dadus33.chatitem.json;
import com.google.gson.*;
import me.dadus33.chatitem.utils.Reflect;
import org.bukkit.inventory.ItemStack;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.regex.Pattern;
public class JSONManipulatorCurrent implements JSONManipulator{
private static Class<?> craftItemStackClass = Reflect.getOBCClass("inventory.CraftItemStack");
private static Class<?> nmsItemStackClass = Reflect.getNMSClass("ItemStack");
private static Method asNMSCopy = Reflect.getMethod(craftItemStackClass, "asNMSCopy", ItemStack.class);
private static Class<?> nbtTagCompoundClass = Reflect.getNMSClass("NBTTagCompound");
private static Method saveNmsItemStackMethod = Reflect.getMethod(nmsItemStackClass, "save", nbtTagCompoundClass);
private static String[] replaces;
private static String rgx;
private static JsonArray toUse;
private static JsonParser parser = new JsonParser();
public String parse(String json, String[] replacements, ItemStack item, String repl) throws InvocationTargetException, IllegalAccessException, InstantiationException {
JsonObject obj = parser.parse(json).getAsJsonObject();
JsonArray array = obj.getAsJsonArray("extra");
replaces = replacements;
String regex = "";
for (int i = 0; i < replacements.length; ++i) {
if (replacements.length == 1) {
regex = Pattern.quote(replacements[0]);
break;
}
if (i == 0 || i + 1 == replacements.length) {
if (i == 0) {
regex = "(" + Pattern.quote(replacements[i]);
} else {
regex = regex.concat("|").concat(Pattern.quote(replacements[i])).concat(")");
}
continue;
}
regex = regex.concat("|").concat(Pattern.quote(replacements[i]));
}
rgx = regex;
JsonArray rep = new JsonArray();
repl = escapeBackslash(repl);
JsonArray use = parser.parse(Translator.toJSON(repl)).getAsJsonArray();
JsonObject hover = parser.parse("{\"action\":\"show_item\", \"value\": \"\"}").getAsJsonObject();
Object nmsStack = asNMSCopy.invoke(null, item);
Object tag = nbtTagCompoundClass.newInstance();
tag = saveNmsItemStackMethod.invoke(nmsStack, tag);
String jsonRep = escapeBackslash(tag.toString());
hover.addProperty("value", jsonRep);
for (JsonElement ob : use)
ob.getAsJsonObject().add("hoverEvent", hover);
toUse = use;
for (int i = 0; i < array.size(); ++i) {
if (array.get(i).isJsonObject()){
JsonObject o = array.get(i).getAsJsonObject();
boolean inside = false;
for (String replacement : replacements)
if (o.toString().contains(replacement)) {
if (inside) {
break;
}
inside = true;
}
JsonElement text = o.get("text");
if (text == null) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
jar = parseArray(jar);
o.add("extra", jar);
}
continue;
} else {
if (text.getAsString().isEmpty()) {
JsonElement el = o.get("extra");
if (el != null) {
JsonArray jar = el.getAsJsonArray();
jar = parseArray(jar);
o.add("extra", jar);
}
}
}
String msg = text.getAsString();
boolean isLast = false;
boolean done = false;
boolean fnd;
String[] splits;
for (String repls : replacements) {
if (done) {
break;
}
isLast = msg.endsWith(repls);
if (isLast) {
done = true;
msg = msg.concat(".");
}
}
splits = msg.split(regex);
fnd = splits.length != 1;
if (fnd)
for (int j = 0; j < splits.length; ++j) {
boolean endDot = (j == splits.length - 1) && isLast;
if (!splits[j].isEmpty() && !endDot) {
String st = o.toString();
JsonObject fix = parser.parse(st).getAsJsonObject();
fix.addProperty("text", splits[j]);
rep.add(fix);
}
if (j != splits.length - 1) {
rep.addAll(use);
}
}
if (!fnd) {
rep.add(o);
}
}else{
if(array.get(i).isJsonNull()){
continue;
}else{
if(array.get(i).isJsonArray()){
JsonArray jar = parseArray(array.get(i).getAsJsonArray());
rep.set(i, jar);
}else{
String msg = array.get(i).getAsString();
boolean isLast = false;
boolean done = false;
boolean fnd;
String[] splits;
for (String repls : replacements) {
if (done) {
break;
}
isLast = msg.endsWith(repls);
if (isLast) {
done = true;
msg = msg.concat(".");
}
}
splits = msg.split(regex);
fnd = splits.length != 1;
if (fnd)
for (int j = 0; j < splits.length; ++j) {
boolean endDot = (j == splits.length - 1) && isLast;
if (!splits[j].isEmpty() && !endDot) {
JsonElement fix = new JsonPrimitive(splits[j]);
rep.add(fix);
}
if (j != splits.length - 1) {
rep.addAll(use);
}
}
if (!fnd) {
rep.add(array.get(i));
}
}
}
}
}
obj.add("extra", rep);
return obj.toString();
}
private static JsonArray parseArray(JsonArray arr) {
JsonArray replacer = new JsonArray();
for (int i = 0; i < arr.size(); ++i) {
if (arr.get(i).isJsonObject()){
JsonObject o = arr.get(i).getAsJsonObject();
boolean inside = false;
for (String replacement : replaces)
if (o.toString().contains(replacement)) {
if (inside) {
break;
}
inside = true;
}
if (!inside) { //the placeholder we're looking for is not inside this element, so we continue searching
continue;
}
JsonElement text = o.get("text");
if (text == null) {
continue;
}
if (text.getAsString().isEmpty()) {
JsonElement el = o.get("extra");
if (el == null) {
continue;
}
JsonArray jar = el.getAsJsonArray();
jar = parseArray(jar);
o.add("extra", jar);
}
String msg = text.getAsString();
boolean isLast = false;
boolean done = false;
boolean fnd;
String[] splits;
for (String repls : replaces) {
if (done) {
break;
}
isLast = msg.endsWith(repls);
if (isLast) {
done = true;
msg = msg.concat(".");
}
}
splits = msg.split(rgx);
fnd = splits.length != 1;
if (fnd)
for (int j = 0; j < splits.length; ++j) {
boolean endDot = (j == splits.length - 1) && isLast;
if (!splits[j].isEmpty() && !endDot) {
String st = o.toString();
JsonObject fix = parser.parse(st).getAsJsonObject();
fix.addProperty("text", splits[j]);
replacer.add(fix);
}
if (j != splits.length - 1) {
replacer.addAll(toUse);
}
}
if (!fnd) {
replacer.add(o);
}
}else{
if(arr.get(i).isJsonNull()){
continue;
}else{
if(arr.get(i).isJsonArray()){
JsonArray jar = parseArray(arr.get(i).getAsJsonArray());
replacer.set(i, jar);
}else{
String msg = arr.get(i).getAsString();
boolean isLast = false;
boolean done = false;
boolean fnd;
String[] splits;
for (String repls : replaces) {
if (done) {
break;
}
isLast = msg.endsWith(repls);
if (isLast) {
done = true;
msg = msg.concat(".");
}
}
splits = msg.split(rgx);
fnd = splits.length != 1;
if (fnd)
for (int j = 0; j < splits.length; ++j) {
boolean endDot = (j == splits.length - 1) && isLast;
if (!splits[j].isEmpty() && !endDot) {
JsonElement fix = new JsonPrimitive(splits[j]);
replacer.add(fix);
}
if (j != splits.length - 1) {
replacer.addAll(toUse);
}
}
if (!fnd) {
replacer.add(arr.get(i));
}
}
}
}
}
return replacer;
}
private static String escapeBackslash(String json){
json = json.replace("\\", "\\\\");
return json;
}
}
@@ -0,0 +1,93 @@
package me.dadus33.chatitem.json;
import com.google.gson.JsonParser;
import org.bukkit.ChatColor;
/*
Many thanks to @DarkSeraphim for this!
I only modified his work to make it compatible with what I was building.
*/
public class Translator {
private static final StringBuilder BUILDER = new StringBuilder("");
private static final StringBuilder STYLE = new StringBuilder();
private static final JsonParser JSON_PARSER = new JsonParser();
static String toJSON(String message) {
if (message == null || message.isEmpty())
return null;
String[] parts = message.split(Character.toString(ChatColor.COLOR_CHAR));
boolean first = true;
String colour = null;
String format = null;
BUILDER.setLength(0);
BUILDER.append("[");
boolean ignoreFirst = !parts[0].isEmpty() && ChatColor.getByChar(parts[0].charAt(0)) != null;
for (String part : parts) {
if (part.isEmpty()) {
continue;
}
String newStyle = null;
if (!ignoreFirst) {
newStyle = getStyle(part.charAt(0));
} else {
ignoreFirst = false;
}
if (newStyle != null) {
part = part.substring(1);
if (newStyle.startsWith("\"c"))
colour = newStyle;
else
format = newStyle;
}
if (!part.isEmpty()) {
if (first)
first = false;
else {
BUILDER.append(", ");
}
BUILDER.append("{");
if (colour != null) {
BUILDER.append(colour);
colour = null;
}
if (format != null) {
BUILDER.append(format);
format = null;
}
BUILDER.append(String.format("\"text\":\"%s\"", part));
BUILDER.append("}");
}
}
BUILDER.append("]");
return BUILDER.toString();
}
private static String getStyle(char colour) {
if (STYLE.length() > 0)
STYLE.delete(0, STYLE.length());
switch (colour) {
case 'k':
return "\"obfuscated\": true,";
case 'l':
return "\"bold\": true,";
case 'm':
return "\"strikethrough\": true,";
case 'n':
return "\"underlined\": true,";
case 'o':
return "\"italic\": true,";
case 'r':
return "\"reset\": true,";
default:
break;
}
ChatColor cc = ChatColor.getByChar(colour);
if (cc == null)
return null;
return STYLE.append("\"color\":\"").append(cc.name().toLowerCase()).append("\", ").toString();
}
}
@@ -0,0 +1,93 @@
package me.dadus33.chatitem.listeners;
import me.dadus33.chatitem.utils.Storage;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
public class ChatEventListener implements Listener {
private Storage c;
public ChatEventListener(Storage storage) {
c = storage;
}
@SuppressWarnings("deprecation")
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onChat(AsyncPlayerChatEvent e) {
boolean found = false;
for (String rep : c.PLACEHOLDERS)
if (e.getMessage().contains(rep)) {
found = true;
break;
}
if (!found) {
return;
}
if (!e.getPlayer().hasPermission("chatitem.use")) {
e.setCancelled(true);
return;
}
if (e.getPlayer().getItemInHand().getType().equals(Material.AIR)) {
if (c.DENY_IF_NO_ITEM) {
e.setCancelled(true);
if (!c.DENY_MESSAGE.isEmpty())
e.getPlayer().sendMessage(c.DENY_MESSAGE);
return;
}
return;
}
String oldmsg = e.getMessage();
e.setMessage(e.getMessage().concat(e.getPlayer().getName()));
Bukkit.getConsoleSender().sendMessage(String.format(e.getFormat(), e.getPlayer().getDisplayName(), oldmsg));
}
@SuppressWarnings("deprecation")
@EventHandler(priority = EventPriority.NORMAL)
public void onCommand(PlayerCommandPreprocessEvent e){
Command cmd = Bukkit.getPluginCommand(e.getMessage().split(" ")[0].substring(1));
if(!c.ALLOWED_COMMANDS.contains(cmd)){
return;
}
boolean found = false;
for (String rep : c.PLACEHOLDERS)
if (e.getMessage().contains(rep)) {
found = true;
break;
}
if (!found) {
return;
}
if (!e.getPlayer().hasPermission("chatitem.use")) {
e.setCancelled(true);
return;
}
if (e.getPlayer().getItemInHand().getType().equals(Material.AIR)) {
if (c.DENY_IF_NO_ITEM) {
e.setCancelled(true);
if (!c.DENY_MESSAGE.isEmpty())
e.getPlayer().sendMessage(c.DENY_MESSAGE);
}
return;
}
e.setMessage(e.getMessage().concat(e.getPlayer().getName()));
}
public void setStorage(Storage st) {
c = st;
}
}
@@ -1,17 +0,0 @@
package me.dadus33.chatitem.listeners;
import java.util.HashMap;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
public class ChatItemAdminHolder implements InventoryHolder {
public final HashMap<Integer, String> keyBySlot = new HashMap<>();
@Override
public Inventory getInventory() {
return null;
}
}
@@ -0,0 +1,174 @@
package me.dadus33.chatitem.listeners;
import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.events.ListenerPriority;
import com.comphenix.protocol.events.PacketAdapter;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.events.PacketEvent;
import com.comphenix.protocol.wrappers.WrappedChatComponent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.utils.Storage;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
public class ChatPacketListener extends PacketAdapter {
private final static String NAME = "{name}";
private final static String AMOUNT = "{amount}";
private final static String TIMES = "{times}";
private ChatItem instance;
private Storage c;
public ChatPacketListener(Plugin plugin, ListenerPriority listenerPriority, Storage s, PacketType... types) {
super(plugin, listenerPriority, types);
this.instance = (ChatItem) plugin;
c = s;
}
private static String materialToName(Material m) {
if (m.equals(Material.TNT)) {
return "TNT";
}
String orig = m.toString().toLowerCase();
String[] splits = orig.split("_");
StringBuilder sb = new StringBuilder(orig.length());
int pos = 0;
for (String split : splits) {
sb.append(split);
int loc = sb.lastIndexOf(split);
char charLoc = sb.charAt(loc);
if (!(split.equalsIgnoreCase("of") || split.equalsIgnoreCase("and") ||
split.equalsIgnoreCase("with") || split.equalsIgnoreCase("on")))
sb.setCharAt(loc, Character.toUpperCase(charLoc));
if (pos != splits.length - 1)
sb.append(' ');
++pos;
}
return sb.toString();
}
@SuppressWarnings("deprecation")
@Override
public void onPacketSending(PacketEvent e) {
if(ChatItem.post17)
if (e.getPacket().getBytes().readSafely(0) == (byte) 2) {
return; //It means it's an actionbar message, and we ain't intercepting those
}
PacketContainer packet = e.getPacket();
String json = packet.getChatComponents().readSafely(0).getJson();
boolean found = false;
for (String rep : c.PLACEHOLDERS)
if (json.contains(rep)) {
found = true;
break;
}
if (!found) {
return; //then it's just a normal message without placeholders, so we leave it alone
}
int topIndex = -1;
String name = null;
for(Player p : Bukkit.getOnlinePlayers()){
String pname = p.getName();
if(!json.contains(pname)){
continue;
}
int index = json.lastIndexOf(pname)+pname.length();
if(index>topIndex){
topIndex = index;
name = pname;
}
}
if(name==null){ //something went really bad, so we run away and hide
return;
}
Player p = Bukkit.getPlayer(name);
StringBuilder buff = new StringBuilder(json);
buff.replace(topIndex-name.length(), topIndex, "");
json = buff.toString();
//STYLE BEGIN
ItemStack inHand = p.getItemInHand();
String replacer = c.NAME_FORMAT;
String amount = c.AMOUNT_FORMAT;
boolean dname = false;
if (!c.COLOR_IF_ALREADY_COLORED && inHand.hasItemMeta()) {
if (inHand.getItemMeta().hasDisplayName()) {
replacer = ChatColor.stripColor(replacer);
dname = true;
}
} else {
if (inHand.hasItemMeta()) {
if (inHand.getItemMeta().hasDisplayName()) {
dname = true;
}
}
}
if (inHand.getAmount() == 1) {
if (c.FORCE_ADD_AMOUNT) {
amount = amount.replace(TIMES, "1");
replacer = replacer.replace(AMOUNT, amount);
} else {
replacer = replacer.replace(AMOUNT, "");
}
} else {
amount = amount.replace(TIMES, String.valueOf(inHand.getAmount()));
replacer = replacer.replace(AMOUNT, amount);
}
if (dname) {
String trp = inHand.getItemMeta().getDisplayName();
replacer = replacer.replace(NAME, trp);
} else {
HashMap<Short, String> translationSection = c.TRANSLATIONS.get(inHand.getType().name());
if(translationSection==null){
String trp = materialToName(inHand.getType());
replacer = replacer.replace(NAME, trp);
}else {
String translated = translationSection.get(inHand.getDurability());
if (translated != null) {
replacer = replacer.replace(NAME, translated);
} else {
replacer = replacer.replace(NAME, materialToName(inHand.getType()));
}
}
}
//STYLE END
String[] reps = new String[c.PLACEHOLDERS.size()];
c.PLACEHOLDERS.toArray(reps);
String message = null;
try {
if(!p.getItemInHand().getType().equals(Material.AIR))
message = ChatItem.getManipulator().parse(json, reps, p.getItemInHand(), replacer);
} catch (InvocationTargetException | IllegalAccessException | InstantiationException e1) {
e1.printStackTrace();
}
if(message!=null)
packet.getChatComponents().writeSafely(0, WrappedChatComponent.fromJson(message));
else
e.setCancelled(true);
}
public void setStorage(Storage st) {
c = st;
}
}
@@ -1,117 +0,0 @@
package me.dadus33.chatitem.listeners;
import static me.dadus33.chatitem.utils.ItemUtils.createItem;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.utils.ItemUtils;
import me.dadus33.chatitem.utils.Messages;
import me.dadus33.chatitem.utils.Storage;
public class InventoryListener implements Listener {
@EventHandler
public void onClick(InventoryClickEvent e) {
if(e.getClickedInventory() == null || !(e.getWhoClicked() instanceof Player) || e.getCurrentItem() == null
|| !(e.getClickedInventory().getHolder() instanceof ChatItemAdminHolder))
return;
e.setCancelled(true);
Player p = (Player) e.getWhoClicked();
ItemStack item = e.getCurrentItem();
Material type = item.getType();
Storage c = ChatItem.getInstance().getStorage();
if(type.equals(ItemUtils.MATERIAL_CLOSE)) {
p.closeInventory();
} else if(type.equals(Material.PAPER)) {
ChatItemAdminHolder holder = (ChatItemAdminHolder) e.getClickedInventory().getHolder();
String key = holder.keyBySlot.get(e.getSlot());
if(key != null) {
setInConfig("manager", key);
p.closeInventory();
ChatItem.reload(p);
}
} else if(type.equals(ItemUtils.INK_SAC)) {
setInConfig("general.color-if-already-colored", c.COLOR_IF_ALREADY_COLORED = !c.COLOR_IF_ALREADY_COLORED);
open(p);
} else if(type.equals(Material.REDSTONE)) {
setInConfig("general.deny-if-no-item", c.DENY_IF_NO_ITEM = !c.DENY_IF_NO_ITEM);
open(p);
} else if(type.equals(Material.STICK)) {
setInConfig("general.hand.disabled", c.HAND_DISABLED = !c.HAND_DISABLED);
open(p);
} else if(type.equals(ItemUtils.FIREWORK_CHARGE)) {
setInConfig("debug", c.DEBUG = !c.DEBUG);
open(p);
} else if(type.equals(Material.IRON_DOOR)) {
if(e.getClick().equals(ClickType.RIGHT))
c.LIMIT--;
else if(e.getClick().equals(ClickType.LEFT))
c.LIMIT++;
setInConfig("general.limit-per-message", c.LIMIT);
open(p);
} else if(type.equals(Material.APPLE)) {
if(e.getClick().equals(ClickType.RIGHT))
c.COOLDOWN--;
else if(e.getClick().equals(ClickType.LEFT))
c.COOLDOWN++;
setInConfig("general.cooldown", c.COOLDOWN);
open(p);
}
}
private void setInConfig(String key, Object val) {
ChatItem pl = ChatItem.getInstance();
pl.getConfig().set(key, val);
pl.saveConfig();
}
public static void open(Player p) {
ChatItemAdminHolder holder = new ChatItemAdminHolder();
Storage c = ChatItem.getInstance().getStorage();
Inventory inv = Bukkit.createInventory(holder, 27, Messages.getMessage("admin-inv.name"));
for(int i = 0; i < inv.getSize(); i ++)
inv.setItem(i, createItem(ItemUtils.WHITE_STAINED_GLASS, "-"));
int slot = 0;
for(String manager : Arrays.asList("both", "auto", "packet", "chat")) {
holder.keyBySlot.put(slot, manager);
inv.setItem(slot++, getManagerItem(manager));
}
inv.setItem(slot + 1, getManagerItem("actual", "%manager%", Messages.getMessage("admin-inv.manager." + c.MANAGER + ".name")));
inv.setItem(8, getBoolChangeItem(ItemUtils.FIREWORK_CHARGE, "debug", c.DEBUG));
inv.setItem(18, getBoolChangeItem(ItemUtils.INK_SAC, "color-if-already-colored", c.COLOR_IF_ALREADY_COLORED));
inv.setItem(19, getBoolChangeItem(Material.REDSTONE, "deny-no-item", c.DENY_IF_NO_ITEM));
inv.setItem(20, getBoolChangeItem(Material.STICK, "hand-disabled", c.HAND_DISABLED));
inv.setItem(21, getAmountChangeItem(Material.IRON_DOOR, "limit-per-message", c.LIMIT));
inv.setItem(22, getAmountChangeItem(Material.APPLE, "cooldown", c.COOLDOWN));
inv.setItem(26, createItem(ItemUtils.MATERIAL_CLOSE, Messages.getMessage("admin-inv.close")));
p.openInventory(inv);
}
private static ItemStack getBoolChangeItem(Material type, String key, boolean b) {
return createItem(type, Messages.getMessage("admin-inv." + key, "%state%", Messages.getMessage(b ? "enabled" : "disabled")), Messages.getMessageList("admin-inv.bool-lore"));
}
private static ItemStack getAmountChangeItem(Material type, String key, int amount) {
return createItem(type, Messages.getMessage("admin-inv." + key, "%state%", amount), Messages.getMessageList("admin-inv.amount-lore"));
}
private static ItemStack getManagerItem(String manager, Object... placeholders) {
return createItem(Material.PAPER, Messages.getMessage("admin-inv.manager." + manager + ".name", placeholders),
Messages.getMessageList("admin-inv.manager." + manager + ".lore", placeholders));
}
}
@@ -1,37 +0,0 @@
package me.dadus33.chatitem.listeners;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.chatmanager.ChatManager;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
public class JoinListener implements Listener {
@EventHandler
public void onJoin(PlayerJoinEvent e) {
Player p = e.getPlayer();
if(!p.isOp())
return;
ChatItem pl = ChatItem.getInstance();
if(pl.isHasNewVersion()) {
TextComponent text = new TextComponent(pl.getStorage().JOIN_UPDATE_MESSAGE);
text.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(new ComponentBuilder(pl.getStorage().JOIN_UPDATE_HOVER).create())));
text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://www.spigotmc.org/resources/19064/"));
p.spigot().sendMessage(text);
}
}
@EventHandler
public void onLeft(PlayerQuitEvent e) {
ChatManager.clear(e.getPlayer());
}
}
@@ -1,11 +0,0 @@
package me.dadus33.chatitem.playernamer;
import org.bukkit.entity.Player;
import net.md_5.bungee.api.chat.BaseComponent;
public interface IPlayerNamer {
public BaseComponent[] getName(Player p);
}
@@ -1,27 +0,0 @@
package me.dadus33.chatitem.playernamer;
import org.bukkit.Bukkit;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.playernamer.hook.DefaultPlayerNamer;
import me.dadus33.chatitem.playernamer.hook.HexNicksPlayerNamer;
public class PlayerNamerManager {
private static IPlayerNamer playerNamer;
public static IPlayerNamer getPlayerNamer() {
return playerNamer;
}
public static void setPlayerNamer(IPlayerNamer playerNamer) {
PlayerNamerManager.playerNamer = playerNamer;
}
public static void load(ChatItem pl) {
if(Bukkit.getPluginManager().getPlugin("HexNicks") != null) {
setPlayerNamer(new HexNicksPlayerNamer());
pl.getLogger().info("Enable support for HexNicks plugin !");
} else {
setPlayerNamer(new DefaultPlayerNamer());
}
}
}
@@ -1,15 +0,0 @@
package me.dadus33.chatitem.playernamer.hook;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playernamer.IPlayerNamer;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ComponentBuilder;
public class DefaultPlayerNamer implements IPlayerNamer {
@Override
public BaseComponent[] getName(Player p) {
return new ComponentBuilder(p.getName()).create();
}
}
@@ -1,17 +0,0 @@
package me.dadus33.chatitem.playernamer.hook;
import org.bukkit.entity.Player;
import dev.majek.hexnicks.Nicks;
import me.dadus33.chatitem.playernamer.IPlayerNamer;
import net.kyori.adventure.text.serializer.bungeecord.BungeeComponentSerializer;
import net.md_5.bungee.api.chat.BaseComponent;
public class HexNicksPlayerNamer implements IPlayerNamer {
@Override
public BaseComponent[] getName(Player p) {
return BungeeComponentSerializer.get().serialize(Nicks.api().getStoredNick(p).join());
}
}
@@ -1,14 +0,0 @@
package me.dadus33.chatitem.playerversion;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.utils.Version;
public interface IPlayerVersion {
public int getProtocolVersion(Player p);
default Version getPlayerVersion(Player p) {
return Version.getVersion(getProtocolVersion(p), Version.getVersion());
}
}
@@ -1,29 +0,0 @@
package me.dadus33.chatitem.playerversion;
import me.dadus33.chatitem.ChatItem;
import me.dadus33.chatitem.playerversion.hooks.DefaultVersionHook;
import me.dadus33.chatitem.playerversion.hooks.ProtocolSupportHook;
import me.dadus33.chatitem.playerversion.hooks.ViaVersionHook;
import org.bukkit.Bukkit;
public class PlayerVersionManager {
private static final IPlayerVersion playerVersionAdapter;
static {
ChatItem pl = ChatItem.getInstance();
if (Bukkit.getPluginManager().getPlugin("ViaVersion") != null) {
playerVersionAdapter = new ViaVersionHook();
pl.getLogger().info("Loading ViaVersion support ...");
} else if (Bukkit.getPluginManager().getPlugin("ProtocolSupport") != null) {
playerVersionAdapter = new ProtocolSupportHook();
pl.getLogger().info("Loading ProtocolSupport support ...");
} else {
playerVersionAdapter = new DefaultVersionHook();
}
}
public static IPlayerVersion getPlayerVersionAdapter() {
return playerVersionAdapter;
}
}
@@ -1,18 +0,0 @@
package me.dadus33.chatitem.playerversion.hooks;
import java.util.HashMap;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playerversion.IPlayerVersion;
import me.dadus33.chatitem.utils.Version;
public class DefaultVersionHook implements IPlayerVersion {
public static final HashMap<String, Integer> PROTOCOL_PER_ADDRESS = new HashMap<>();
@Override
public int getProtocolVersion(Player p) {
return PROTOCOL_PER_ADDRESS.getOrDefault(Version.stringifyAdress(p.getAddress()), Version.getVersion().MAX_VER);
}
}
@@ -1,15 +0,0 @@
package me.dadus33.chatitem.playerversion.hooks;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playerversion.IPlayerVersion;
import protocolsupport.api.ProtocolSupportAPI;
public class ProtocolSupportHook implements IPlayerVersion {
@Override
public int getProtocolVersion(Player p) {
return ProtocolSupportAPI.getProtocolVersion(p).getId();
}
}
@@ -1,14 +0,0 @@
package me.dadus33.chatitem.playerversion.hooks;
import org.bukkit.entity.Player;
import me.dadus33.chatitem.playerversion.IPlayerVersion;
import us.myles.ViaVersion.api.Via;
public class ViaVersionHook implements IPlayerVersion {
@Override
public int getProtocolVersion(Player p) {
return Via.getAPI().getPlayerVersion(p.getUniqueId());
}
}
@@ -1,43 +0,0 @@
package me.dadus33.chatitem.utils;
import me.dadus33.chatitem.ChatItem;
import net.md_5.bungee.api.ChatColor;
public class ColorManager {
public static String getColorString(String input) {
if(input == null || input.isEmpty())
return "";
StringBuilder str = new StringBuilder();
if(Version.getVersion().isNewerOrEquals(Version.V1_16) && input.startsWith("x")) { // x mean it's an hex
ChatItem.debug("Removing char x at begin: " + input.substring(1));
input = input.substring(1);
if(input.length() >= 6) { // at least hex
str.append(ChatColor.of("#" + input.substring(0, 6))); // get first hex color code
ChatItem.debug("Str with hex: " + str);
if(input.length() > 6) // if as another color code
str.append(getColorString(input.substring(6))); // get color for after
return str.toString();
} else
ChatItem.debug("Low len: " + input.length());
}
// not hex
for(char c : input.toCharArray())
str.append(ChatColor.getByChar(c));
return str.toString();
}
public static ChatColor getColor(String input) {
if(input == null || input.isEmpty())
return ChatColor.RESET;
if(Version.getVersion().isNewerOrEquals(Version.V1_16) && input.startsWith("x")) { // x mean it's an hex
ChatItem.debug("Removing char x at begin: " + input.substring(1));
if(input.length() >= 7) { // at least hex, and 7 because we count the "x"
return ChatColor.of("#" + input.substring(1, 7)); // get first hex color code
} else
ChatItem.debug("Low len: " + input.length());
}
// not hex
return ChatColor.getByChar(input.charAt(0));
}
}
@@ -0,0 +1,25 @@
package me.dadus33.chatitem.utils;
import me.dadus33.chatitem.ChatItem;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import java.util.logging.Level;
public class General {
private static Storage c;
public static void checkConfigVersion() {
int latestVersion = ChatItem.CFG_VER;
if (latestVersion != c.CONFIG_VERSION) {
Bukkit.getLogger().log(Level.WARNING, ChatColor.RED + "ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
c.performOverwrite();
Bukkit.getLogger().log(Level.WARNING, ChatColor.RED + "Replacement complete!");
}
}
public static void init(Storage st) {
c = st;
}
}
@@ -1,92 +0,0 @@
package me.dadus33.chatitem.utils;
import java.util.Arrays;
import java.util.List;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class ItemUtils {
public static final Material MATERIAL_CLOSE = getMaterialWithCompatibility("BARRIER", "REDSTONE_BLOCK");
// items
public static final Material EMPTY_MAP = getMaterialWithCompatibility("EMPTY_MAP", "MAP");
public static final Material BOOK_AND_QUILL = getMaterialWithCompatibility("BOOK_AND_QUILL", "WRITTEN_BOOK");
public static final Material WEB = getMaterialWithCompatibility("WEB", "COBWEB");
public static final Material FIREBALL = getMaterialWithCompatibility("FIREBALL", "FIRE_CHARGE");
public static final Material INK_SAC = getMaterialWithCompatibility("INK_SAC", "INK_SACK", "DYE", "GRAY_DYE");
public static final Material FIREWORK_CHARGE = getMaterialWithCompatibility("FIREWORK_CHARGE", "FIRE_CHARGE");
public static final Material BIRCH_WOOD_STAIRS = getMaterialWithCompatibility("BIRCH_WOOD_STAIRS", "BIRCH_STAIRS");
// colored items
public static final Material GRAY_STAINED_GLASS_PANE = getMaterialWithCompatibility("STAINED_GLASS_PANE", "GRAY_STAINED_GLASS_PANE");
public static final Material WHITE_STAINED_GLASS = getMaterialWithCompatibility("STAINED_GLASS_PANE", "WHITE_STAINED_GLASS_PANE");
public static Material getMaterialWithCompatibility(String... tempMat) {
for(String s : tempMat) {
try {
Material m = (Material) Material.class.getField(s).get(Material.class);
if(m != null)
return m;
} catch (IllegalArgumentException | IllegalAccessException | SecurityException e2) {
e2.printStackTrace();
} catch (NoSuchFieldException e) {}
}
return null;
}
public static ItemStack createItem(Material m, String name, String... lore) {
return createItem(m, name, 1, lore);
}
public static ItemStack createItem(Material m, String name, int quantite, String... lore) {
ItemStack item = new ItemStack(m, quantite);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.setDisplayName(ChatColor.RESET + name);
meta.setLore(Arrays.asList(lore));
item.setItemMeta(meta);
return item;
}
public static ItemStack createItem(Material m, String name, List<String> lore) {
return createItem(m, name, 1, lore);
}
public static ItemStack createItem(Material m, String name, int quantite, List<String> lore) {
ItemStack item = new ItemStack(m, quantite);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.setDisplayName(ChatColor.RESET + name);
meta.setLore(lore);
item.setItemMeta(meta);
return item;
}
@SuppressWarnings("deprecation")
public static ItemStack createItem(Material m, String name, int amount, byte b, String... lore) {
ItemStack item = new ItemStack(m, amount, b);
ItemMeta meta = (ItemMeta) item.getItemMeta();
meta.setDisplayName(ChatColor.RESET + name);
meta.setLore(Arrays.asList(lore));
item.setItemMeta(meta);
return item;
}
public static ItemStack hideAttributes(ItemStack stack) {
if (Version.getVersion().isNewerThan(Version.V1_7)) {
ItemMeta meta = stack.getItemMeta();
// All ItemFlags are used to hide attributes, their javadoc says so too.
meta.addItemFlags(ItemFlag.values());
stack.setItemMeta(meta);
}
return stack;
}
public static boolean isEmpty(ItemStack item) {
return item == null || item.getType().equals(Material.AIR);
}
}
@@ -1,42 +0,0 @@
package me.dadus33.chatitem.utils;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.bukkit.command.CommandSender;
import me.dadus33.chatitem.ChatItem;
public class Messages {
public static void sendMessage(CommandSender p, String key, Object... placeholders) {
getMessageList(key, placeholders).forEach(p::sendMessage);
}
public static String getMessage(String key, Object... placeholders) {
return colorAndPlaceholders(ChatItem.getInstance().getConfig().getString("messages." + key, key), placeholders);
}
@SuppressWarnings("unchecked")
public static List<String> getMessageList(String key, Object... placeholders) {
Object obj = ChatItem.getInstance().getConfig().get("messages." + key);
if(obj == null)
return Arrays.asList(key);
if(obj instanceof List) {
return ((List<String>) obj).stream().map((s) -> colorAndPlaceholders(s, placeholders)).collect(Collectors.toList());
} else if(obj instanceof String)
return Arrays.asList(colorAndPlaceholders((String) obj, placeholders));
else
return Arrays.asList(colorAndPlaceholders(obj.toString(), placeholders));
}
private static String colorAndPlaceholders(String msg, Object... placeholders) {
if(msg == null)
return "";
for (int index = 0; index <= placeholders.length - 1; index += 2) {
msg = msg.replace(String.valueOf(placeholders[index]), String.valueOf(placeholders[index + 1]));
}
return Storage.color(msg);
}
}
@@ -1,173 +0,0 @@
package me.dadus33.chatitem.utils;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
public class PacketUtils {
public static final String VERSION = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",")
.split(",")[3];
public static final String NMS_PREFIX;
public static final String OBC_PREFIX;
public static final boolean IS_THERMOS;
public static final Class<?> CRAFT_PLAYER_CLASS, CRAFT_SERVER_CLASS, CHAT_SERIALIZER, COMPONENT_CLASS;
/**
* This Map is to reduce Reflection action which take more resources than just RAM action
*/
private static final Map<String, Class<?>> ALL_CLASS = Collections.synchronizedMap(new HashMap<String, Class<?>>());
static {
IS_THERMOS = isClassExist("thermos.Thermos");
NMS_PREFIX = Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? "net.minecraft." : "net.minecraft.server." + VERSION + ".";
OBC_PREFIX = "org.bukkit.craftbukkit." + VERSION + ".";
CRAFT_PLAYER_CLASS = getObcClass("entity.CraftPlayer");
CHAT_SERIALIZER = getNmsClass("IChatBaseComponent$ChatSerializer", "network.chat.", "ChatSerializer");
COMPONENT_CLASS = getNmsClass("IChatBaseComponent", "network.chat.");
CRAFT_SERVER_CLASS = getObcClass("CraftServer");
}
/**
* Get the Class in NMS, with a processing reducer
*
* @param name of the NMS class (in net.minecraft.server package ONLY, because it's NMS)
* @return clazz the searched class
*/
public static Class<?> getNmsClass(String name, String packagePrefix, String... alias){
return ALL_CLASS.computeIfAbsent(name, (a) -> {
String fullPrefix = NMS_PREFIX + (Version.getVersion().isNewerOrEquals(Version.V1_17) || IS_THERMOS ? packagePrefix : "");
try {
Class<?> clazz = Class.forName(fullPrefix + name);
if(clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if(alias.length == 0)
e.printStackTrace(); // no alias, print error
// else ignore and go check for alias
}
for(String className : alias) {
try {
Class<?> clazz = Class.forName(fullPrefix + className);
if(clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if(className == alias[alias.length - 1]) // if it's last alias, print error
e.printStackTrace();
}
}
return null;
});
}
/**
* Get the Class in NMS, with a processing reducer
*
* @param name of the NMS class (in net.minecraft.server package ONLY, because it's NMS)
* @return clazz the searched class
*/
public static Class<?> getObcClass(String name, String... alias){
return ALL_CLASS.computeIfAbsent(name, (a) -> {
try {
Class<?> clazz = Class.forName(OBC_PREFIX + name);
if(clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if(alias.length == 0)
e.printStackTrace(); // no alias, print error
// else ignore and go check for alias
}
for(String className : alias) {
try {
Class<?> clazz = Class.forName(OBC_PREFIX + className);
if(clazz != null)
return clazz;
} catch (ClassNotFoundException e) {
if(className == alias[alias.length - 1]) // if it's last alias, print error
e.printStackTrace();
}
}
return null;
});
}
/**
* Get NMS entity player of specified one
*
* @param p the player that we want the NMS entity player
* @return the entity player
*/
public static Object getEntityPlayer(Player p) {
try {
Object craftPlayer = CRAFT_PLAYER_CLASS.cast(p);
return craftPlayer.getClass().getMethod("getHandle").invoke(craftPlayer);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
public static boolean isClassExist(String name) {
try {
Class.forName(name);
return true;
} catch (Exception e) {
return false;
}
}
/**
* Get NMS player connection of specified player
*
* @param p Player of which we want to get the player connection
* @return the NMS player connection
*/
public static Object getPlayerConnection(Player p) {
try {
Object entityPlayer = getEntityPlayer(p);
if(Version.getVersion().isNewerOrEquals(Version.V1_17))
return entityPlayer.getClass().getField("b").get(entityPlayer);
else
return entityPlayer.getClass().getField("playerConnection").get(entityPlayer);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Get NMS entity player of specified one
*
* @param p the player that we want the NMS entity player
* @return the entity player
*/
public static Object getCraftServer() {
try {
Object craftServer = CRAFT_SERVER_CLASS.cast(Bukkit.getServer());
return craftServer.getClass().getMethod("getHandle").invoke(craftServer);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Send the packet to the specified player
*
* @param p which will receive the packet
* @param packet the packet to sent
*/
public static void sendPacket(Player p, Object packet) {
try {
Object playerConnection = getPlayerConnection(p);
playerConnection.getClass().getMethod(Version.getVersion().isNewerOrEquals(Version.V1_18) ? "a" : "sendPacket", getNmsClass("Packet", "network.protocol.")).invoke(playerConnection, packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@@ -1,13 +1,56 @@
package me.dadus33.chatitem.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import org.bukkit.Bukkit;
import me.dadus33.chatitem.ChatItem;
import java.lang.reflect.Method;
public class Reflect {
private static String versionString;
private static String getVersion() {
if (versionString == null) {
String name = Bukkit.getServer().getClass().getPackage().getName();
versionString = name.substring(name.lastIndexOf('.') + 1) + ".";
}
return versionString;
}
public static Class<?> getNMSClass(String nmsClassName) {
String clazzName = "net.minecraft.server." + getVersion() + nmsClassName;
Class<?> clazz;
try {
clazz = Class.forName(clazzName);
} catch (Throwable t) {
t.printStackTrace();
return null;
}
return clazz;
}
public static Class<?> getOBCClass(String obcClassName) {
String clazzName = "org.bukkit.craftbukkit." + getVersion() + obcClassName;
Class<?> clazz;
try {
clazz = Class.forName(clazzName);
} catch (Throwable t) {
t.printStackTrace();
return null;
}
return clazz;
}
public static Method getMethod(Class<?> clazz, String methodName, Class<?>... params) {
try {
return clazz.getMethod(methodName, params);
@@ -16,41 +59,5 @@ public class Reflect {
return null;
}
}
public static Method getMethod(Class<?> clazz, Class<?> returned, Class<?>... params) {
try {
for(Method m : clazz.getDeclaredMethods()) {
if(returned.equals(m.getReturnType()) && areParamsEquals(m.getParameterTypes(), params))
return m;
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static boolean areParamsEquals(Class<?>[] p1, Class<?>[] p2) {
if(p1.length != p2.length)
return false;
for(int i = 0; i < p1.length; i++) {
if(!p1[i].equals(p2[i]))
return false;
}
return true;
}
public static Field getField(Class<?> clazz, String... fieldNames){
for(String field : fieldNames) {
try{
Field f = clazz.getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (NoSuchFieldException e) {
// go to next
}
}
ChatItem.getInstance().getLogger().severe("Failed to find field: " + Arrays.asList(fieldNames) + " in class: " + clazz.getCanonicalName());
return null;
}
}
@@ -1,124 +0,0 @@
package me.dadus33.chatitem.utils;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import me.dadus33.chatitem.ChatItem;
public class ReflectionUtils {
public static Object getPrivateField(Object object, String field)
throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
Field objectField = object.getClass().getDeclaredField(field);
objectField.setAccessible(true);
return objectField.get(object);
}
public static void setField(Object src, String fieldName, Object value) {
try {
Field field = src.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(src, value);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Get the specified field name in the object source
*
* @param source where we will find the field
* @param field the name of the field
* @return the requested object of the field
*/
public static Object getObject(Object source, String... field) {
try {
for(String fieldName : field) {
try {
Field f = source.getClass().getDeclaredField(fieldName);
f.setAccessible(true);
return f.get(source);
} catch (NoSuchFieldException e) {
// ignore because going to next item
}
}
ChatItem.getInstance().getLogger().severe("Failed to find fields: " + String.join(", ", field) + " in " + source.getClass().getSimpleName());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Get the specified field name in the object source
*
* @param source where we will find the field
* @param field the name of the field
* @return the requested field
*/
public static Field getField(Object source, String field) {
try {
Field f = source.getClass().getDeclaredField(field);
f.setAccessible(true);
return f;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Call method. Return the method return.
*
* @param source the object where we want to run the method
* @param method the name of the method to call
* @return the return of the method called
*/
public static Object callMethod(Object source, String method) {
try {
return source.getClass().getDeclaredMethod(method).invoke(source);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* Get the first object which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
@SuppressWarnings("unchecked")
public static <T> T getFirstWith(Object from, Class<?> clazz, Class<T> searchingFor) throws Exception {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(searchingFor) && !Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
return (T) f.get(from);
}
}
return null;
}
/**
* Get the first field which have the searching for class type
*
* @param from the object where we will try to find the field
* @param clazz the class that have to define the field
* @param searchingFor the class of the required field
* @return the field (or null if not found)
* @throws Exception if something gone wrong
*/
public static Field getFirstFieldWith(Class<?> clazz, Class<?> searchingFor) throws Exception {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(searchingFor) && !Modifier.isStatic(f.getModifiers())) {
f.setAccessible(true);
return f;
}
}
return null;
}
}
@@ -1,208 +0,0 @@
package me.dadus33.chatitem.utils;
import java.util.Locale;
import java.util.Objects;
import javax.annotation.Nullable;
/**
* Represents the simplified SemVer schema Negativity uses for its plugin versions.
*/
public final class SemVer implements Comparable<SemVer> {
private final int major;
private final int minor;
private final int patch;
private final @Nullable Suffix suffix;
public SemVer(int major, int minor, int patch, @Nullable Suffix suffix) {
this.major = major;
this.minor = minor;
this.patch = patch;
this.suffix = suffix;
}
public boolean isNewerThan(SemVer other) {
return this.compareTo(other) > 0;
}
public boolean isOlderThan(SemVer other) {
return this.compareTo(other) < 0;
}
/**
* Slightly different from {@link #equals} in that this method will return
* true if the suffix has the same {@link Suffix#getWeight() weight}
* but not the same {@link Suffix#getText()} text
*/
public boolean isEquivalentTo(SemVer other) {
return this.compareTo(other) == 0;
}
public int getMajor() {
return major;
}
public int getMinor() {
return minor;
}
public int getPatch() {
return patch;
}
public @Nullable Suffix getSuffix() {
return suffix;
}
@Override
public int compareTo(SemVer o) {
int majorDelta = Integer.compare(this.major, o.major);
if (majorDelta != 0) {
return majorDelta;
}
int minorDelta = Integer.compare(this.minor, o.minor);
if (minorDelta != 0) {
return minorDelta;
}
int patchDelta = Integer.compare(this.patch, o.patch);
if (patchDelta != 0) {
return patchDelta;
}
if (this.suffix != null) {
return o.suffix != null ? this.suffix.compareTo(o.suffix) : -1;
}
if (o.suffix != null) {
return 1;
}
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
SemVer semVer = (SemVer) o;
return major == semVer.major && minor == semVer.minor && patch == semVer.patch && Objects.equals(suffix, semVer.suffix);
}
@Override
public int hashCode() {
return Objects.hash(major, minor, patch, suffix);
}
@Override
public String toString() {
return "SemVer{major=" + major + ", minor=" + minor + ", patch=" + patch + ", suffix=" + suffix + '}';
}
public String toFormattedString() {
if (suffix == null) {
if(patch > 0)
return major + "." + minor + (patch > 0 ? "." + patch : "");
}
return major + "." + minor + (patch > 0 ? "." + patch : "") + (suffix == null ? "" : "-" + suffix.getText());
}
public static @Nullable SemVer parse(String text) {
if (text == null || text.isEmpty()) {
return null;
}
String[] suffixSplit = text.split("-", 2);
Suffix suffix = null;
if (suffixSplit.length > 1) {
suffix = Suffix.of(suffixSplit[1]);
}
String[] parts = suffixSplit[0].split("\\.");
int major;
try {
major = Integer.parseInt(parts[0]);
} catch (NumberFormatException e) {
return null;
}
int minor = 0;
if (parts.length > 1) {
try {
minor = Integer.parseInt(parts[1]);
} catch (NumberFormatException ignore) {
}
}
int patch = 0;
if (parts.length > 2) {
try {
patch = Integer.parseInt(parts[2]);
} catch (NumberFormatException ignore) {
}
}
return new SemVer(major, minor, patch, suffix);
}
public static final class Suffix implements Comparable<Suffix> {
public static final Suffix SNAPSHOT = new Suffix(0, "SNAPSHOT");
public static final Suffix ALPHA = new Suffix(1, "ALPHA");
public static final Suffix BETA = new Suffix(2, "BETA");
public static final Suffix GAMMA = new Suffix(3, "GAMMA");
public static final Suffix DELTA = new Suffix(4, "DELTA");
private final int weight;
private final String text;
public Suffix(int weight, String text) {
this.weight = weight;
this.text = text;
}
public int getWeight() {
return weight;
}
public String getText() {
return text;
}
@Override
public int compareTo(Suffix o) {
return Integer.compare(this.weight, o.weight);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Suffix suffix = (Suffix) o;
return weight == suffix.weight && text.equals(suffix.text);
}
@Override
public int hashCode() {
return Objects.hash(weight, text);
}
@Override
public String toString() {
return "Suffix{weight=" + weight + ", text='" + text + "'}";
}
public static Suffix of(String text) {
String uppercaseText = text.toUpperCase(Locale.ROOT);
switch (uppercaseText) {
case "SNAPSHOT":
return SNAPSHOT;
case "ALPHA":
return ALPHA;
case "BETA":
return BETA;
case "GAMMA":
return GAMMA;
case "DELTA":
return DELTA;
default:
return new Suffix(-1, uppercaseText);
}
}
}
}
@@ -11,111 +11,70 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.logging.Level;
public class Storage {
public final HashMap<String, HashMap<Short, String>> TRANSLATIONS = new HashMap<>();
public final String HAND_NAME, NAME_FORMAT, AMOUNT_FORMAT, MANAGER, PERMISSION_NAME, BUGGED_CLIENT_ACTION;
public final String NO_PERMISSION_MESSAGE, DENY_MESSAGE, RELOAD_MESSAGE, COOLDOWN_MESSAGE, LIMIT_MESSAGE;
public final String SECONDS, MINUTES, HOURS;
public final String JOIN_UPDATE_MESSAGE, JOIN_UPDATE_HOVER;
public final List<Command> ALLOWED_PLUGIN_COMMANDS = new ArrayList<>();
public final List<String> ALLOWED_DEFAULT_COMMANDS = new ArrayList<>();
public final List<String> PLACEHOLDERS, HAND_TOOLTIP, BUGGED_CLIENTS_TOOLTIP;
public boolean COLOR_IF_ALREADY_COLORED, FORCE_ADD_AMOUNT, LET_MESSAGE_THROUGH, DENY_IF_NO_ITEM, DEBUG,
HAND_DISABLED, SHOW_NO_PERM_NORMAL, CHECK_UPDATE, SHOW_NO_PERM_COMMAND, PERMISSION_ENABLED;
public int CONFIG_VERSION, LIMIT, COOLDOWN;
private FileConfiguration conf;
public final List<String> PLACEHOLDERS;
public final String NAME_FORMAT;
public final String AMOUNT_FORMAT;
public final Boolean COLOR_IF_ALREADY_COLORED;
public final Boolean FORCE_ADD_AMOUNT;
public final Boolean DENY_IF_NO_ITEM;
public final String DENY_MESSAGE;
public final String RELOAD_MESSAGE;
final Integer CONFIG_VERSION;
public final List<Command> ALLOWED_COMMANDS = new ArrayList<>();
public Storage(FileConfiguration cnf) {
this.conf = cnf;
CONFIG_VERSION = conf.getInt("config-version", 13);
checkConfigVersion();
this.MANAGER = conf.getString("manager", "auto");
Set<String> keys = conf.getConfigurationSection("translations").getKeys(false);
public Storage(FileConfiguration conf) {
Set<String> keys = conf.getConfigurationSection("Translations").getKeys(false);
for (String key : keys) {
HashMap<Short, String> entry = new HashMap<>();
Set<String> subKeys = conf.getConfigurationSection("translations.".concat(key)).getKeys(false);
Set<String> subKeys = conf.getConfigurationSection("Translations.".concat(key)).getKeys(false);
for (String subKey : subKeys) {
entry.put(Short.parseShort(subKey),
color(conf.getString("translations.".concat(key).concat(".").concat(subKey))));
entry.put(Short.parseShort(subKey), color(conf.getString("Translations.".concat(key).concat(".")
.concat(subKey))));
}
TRANSLATIONS.put(key, entry);
}
DEBUG = conf.getBoolean("debug", false);
PLACEHOLDERS = ImmutableList.copyOf(conf.getStringList("general.placeholders"));
NAME_FORMAT = color(conf.getString("general.name-format", "&b&l&o{name} {amount}&r"));
AMOUNT_FORMAT = color(conf.getString("general.amount-format", "x{times}"));
COLOR_IF_ALREADY_COLORED = conf.getBoolean("general.color-if-already-colored", true);
LET_MESSAGE_THROUGH = conf.getBoolean("general.let-message-through", true);
FORCE_ADD_AMOUNT = conf.getBoolean("general.force-add-amount", true);
DENY_IF_NO_ITEM = conf.getBoolean("general.deny-if-no-item", false);
LIMIT = conf.getInt("general.limit", 8);
COOLDOWN = conf.getInt("general.cooldown", 60);
SHOW_NO_PERM_NORMAL = conf.getBoolean("general.show-no-permission-message.normal", true);
SHOW_NO_PERM_COMMAND = conf.getBoolean("general.show-no-permission-message.command", false);
PERMISSION_ENABLED = conf.getBoolean("general.permission.enabled", false);
PERMISSION_NAME = conf.getString("general.permission.name", "chatitem.use");
HAND_DISABLED = conf.getBoolean("general.hand.disabled", false);
HAND_NAME = color(conf.getString("general.hand.name", "&b&l&o{display-name}&b&l&o's hand"));
HAND_TOOLTIP = conf.getStringList("general.hand.tooltip").stream().map(Storage::color).collect(Collectors.toList());
BUGGED_CLIENT_ACTION = conf.getString("general.bugged_client.action", "show_both");
BUGGED_CLIENTS_TOOLTIP = conf.getStringList("general.bugged_client.tooltip").stream().map(Storage::color).collect(Collectors.toList());
CHECK_UPDATE = conf.getBoolean("general.check-update", true);
DENY_MESSAGE = color(conf.getString("messages.deny-message", "&c&lYou have no item in hand!"));
RELOAD_MESSAGE = color(conf.getString("messages.reload-success", "&b&lSuccessful reload!"));
NO_PERMISSION_MESSAGE = color(conf.getString("messages.no-permission",
"&c&lI'm sorry, but you are not allowed to use the placeholder in chat!"));
COOLDOWN_MESSAGE = color(conf.getString("messages.cooldown-message",
"&c&lYou can only use items in chat once a minute! You have {remaining} left!"));
JOIN_UPDATE_MESSAGE = color(conf.getString("messages.join-update.message",
"&cA new version of ChatItem is available. &aClick here to download."));
JOIN_UPDATE_HOVER = color(conf.getString("messages.join-update.hover", "&6Click to go to spigot page !"));
LIMIT_MESSAGE = color(conf.getString("messages.limit-message", "&c&lYou can only add 8 item placeholders per message!"));
SECONDS = color(conf.getString("messages.seconds", " seconds"));
MINUTES = color(conf.getString("messages.minutes", " minutes"));
HOURS = color(conf.getString("messages.hours", " hours"));
colorStringList(HAND_TOOLTIP);
final List<String> cmds = conf.getStringList("general.commands");
Bukkit.getScheduler().runTaskLaterAsynchronously(ChatItem.getInstance(), () -> {
for (String s : cmds) {
Command c = Bukkit.getPluginCommand(s);
if (c != null) {
ALLOWED_PLUGIN_COMMANDS.add(c);
} else {
ALLOWED_DEFAULT_COMMANDS.add(s);
CONFIG_VERSION = conf.getInt("config-version");
List<String> added = conf.getStringList("placeholders");
PLACEHOLDERS = ImmutableList.copyOf(added);
NAME_FORMAT = color(conf.getString("name-format"));
AMOUNT_FORMAT = color(conf.getString("amount-format"));
COLOR_IF_ALREADY_COLORED = conf.getBoolean("color-if-already-colored");
FORCE_ADD_AMOUNT = conf.getBoolean("force-add-amount");
DENY_IF_NO_ITEM = conf.getBoolean("deny-if-no-item");
DENY_MESSAGE = color(conf.getString("deny-message"));
RELOAD_MESSAGE = color(conf.getString("reload-success"));
final List<String> cmds = conf.getStringList("commands");
Bukkit.getScheduler().runTaskLaterAsynchronously(ChatItem.getInstance(), new Runnable() {
@Override
public void run() {
for(String s : cmds){
Command c = Bukkit.getPluginCommand(s);
if(c!=null) {
ALLOWED_COMMANDS.add(Bukkit.getPluginCommand(s));
}
else
ChatItem.getInstance().getLogger().log(Level.WARNING, ChatColor.RED.toString().concat("Unknown command ")
.concat(s).concat(" found in config! Ignoring occurrence..."));
}
}
}, 100L);
}
public static String color(String s) {
return s == null || s.isEmpty() ? s : ChatColor.translateAlternateColorCodes('&', s);
private static String color(String s) {
return ChatColor.translateAlternateColorCodes('&', s);
}
private static void colorStringList(List<String> input) {
for (int i = 0; i < input.size(); ++i) {
input.set(i, color(input.get(i)));
}
}
private void checkConfigVersion() {
int latestVersion = ChatItem.CFG_VER;
if (latestVersion != CONFIG_VERSION) {
ChatItem pl = ChatItem.getInstance();
pl.getLogger().warning(ChatColor.RED
+ "ChatItem detected an older or invalid configuration file. Replacing it with the default config...");
performOverwrite();
conf = pl.getConfig();
pl.getLogger().warning(ChatColor.RED + "Replacement complete!");
}
}
private void performOverwrite() {
void performOverwrite() {
ChatItem.getInstance().saveResource("config.yml", true);
}
@@ -1,177 +0,0 @@
package me.dadus33.chatitem.utils;
import me.dadus33.chatitem.ChatItem;
import org.bukkit.Bukkit;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.TreeMap;
public class Utils {
private final static TreeMap<Integer, String> ROMAN_KEYS = new TreeMap<>();
private final static HashMap<String, String> ENCHANTS_NAMES = new HashMap<>();
static {
ROMAN_KEYS.put(1000, "M");
ROMAN_KEYS.put(900, "CM");
ROMAN_KEYS.put(500, "D");
ROMAN_KEYS.put(400, "CD");
ROMAN_KEYS.put(100, "C");
ROMAN_KEYS.put(90, "XC");
ROMAN_KEYS.put(50, "L");
ROMAN_KEYS.put(40, "XL");
ROMAN_KEYS.put(10, "X");
ROMAN_KEYS.put(9, "IX");
ROMAN_KEYS.put(5, "V");
ROMAN_KEYS.put(4, "IV");
ROMAN_KEYS.put(1, "I");
ENCHANTS_NAMES.put("ARROW_DAMAGE", "Power");
ENCHANTS_NAMES.put("ARROW_FIRE", "Flame");
ENCHANTS_NAMES.put("ARROW_INFINITE", "Infinity");
ENCHANTS_NAMES.put("ARROW_KNOCKBACK", "Punch");
ENCHANTS_NAMES.put("BINDING_CURSE", "Curse of Binding");
ENCHANTS_NAMES.put("DAMAGE_ALL", "Sharpness");
ENCHANTS_NAMES.put("DAMAGE_ARTHROPODS", "Bane of Arthropods");
ENCHANTS_NAMES.put("DAMAGE_UNDEAD", "Smite");
ENCHANTS_NAMES.put("DEPTH_STRIDER", "Depth Strider");
ENCHANTS_NAMES.put("DIG_SPEED", "Efficiency");
ENCHANTS_NAMES.put("DURABILITY", "Unbreaking");
ENCHANTS_NAMES.put("FIRE_ASPECT", "Fire Aspect");
ENCHANTS_NAMES.put("FROST_WALKER", "Frost Walker");
ENCHANTS_NAMES.put("KNOCKBACK", "Knockback");
ENCHANTS_NAMES.put("LOOT_BONUS_BLOCKS", "Fortune");
ENCHANTS_NAMES.put("LOOT_BONUS_MOBS", "Looting");
ENCHANTS_NAMES.put("LUCK", "Luck of the Sea");
ENCHANTS_NAMES.put("LURE", "Lure");
ENCHANTS_NAMES.put("MENDING", "Mending");
ENCHANTS_NAMES.put("OXYGEN", "Respiration");
ENCHANTS_NAMES.put("PROTECTION_ENVIRONMENTAL ", "Protection");
ENCHANTS_NAMES.put("PROTECTION_EXPLOSIONS", "Blast Protection");
ENCHANTS_NAMES.put("PROTECTION_FALL", "Feather Falling");
ENCHANTS_NAMES.put("PROTECTION_FIRE", "Fire Protection");
ENCHANTS_NAMES.put("PROTECTION_PROJECTILE", "Projectile Protection");
ENCHANTS_NAMES.put("SILK_TOUCH", "Silk Touch");
ENCHANTS_NAMES.put("SWEEPING_EDGE", "Sweeping Edge");
ENCHANTS_NAMES.put("THORNS", "Thorns");
ENCHANTS_NAMES.put("VANISHING_CURSE", "Cure of Vanishing");
ENCHANTS_NAMES.put("WATER_WORKER", "Aqua Affinity");
}
public static List<Player> getOnlinePlayers() {
return new ArrayList<>(Bukkit.getOnlinePlayers());
}
public static String toRoman(int number) {
int l = ROMAN_KEYS.floorKey(number);
if (number == l) {
return ROMAN_KEYS.get(number);
}
return ROMAN_KEYS.get(l) + toRoman(number - l);
}
@SuppressWarnings("deprecation")
public static String getEnchantName(Enchantment enchant) {
String name = ENCHANTS_NAMES.get(enchant.getName());
if (name == null) {
ChatItem.getInstance().getLogger()
.warning("Unknown enchant " + enchant.getName() + ". Please report this to Elikill58.");
}
return name;
}
public static String getFromURL(String urlName) {
ChatItem pl = ChatItem.getInstance();
try {
URL url = new URL(urlName);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setUseCaches(true);
connection.setConnectTimeout(5000);
connection.setReadTimeout(5000);
connection.setRequestProperty("User-Agent", "ChatItem " + pl.getDescription().getVersion());
connection.setDoOutput(true);
connection.setRequestMethod("GET");
BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
StringBuilder content = new StringBuilder();
String input;
while ((input = br.readLine()) != null)
content.append(input);
br.close();
return content.toString();
} catch (SocketTimeoutException e) {
pl.getLogger().info("Failed to access to " + urlName + " (Reason: timed out).");
} catch (UnknownHostException | MalformedURLException e) {
pl.getLogger().info("Could not use the internet connection to check for update or send stats");
} catch (ConnectException e) {
pl.getLogger().warning("Cannot connect to " + urlName + " (Reason: " + e.getMessage() + ").");
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public static int indexOf(CharSequence s, CharSequence searched, int i) {
return s.toString().indexOf(searched.toString(), i);
}
public static boolean isEmpty(CharSequence s) {
return (s == null || s.length() == 0);
}
public static int countMatches(CharSequence str, CharSequence searched) {
if (isEmpty(str) || isEmpty(searched))
return 0;
byte b = 0;
int i = 0;
while ((i = indexOf(str, searched, i)) != -1) {
b++;
i += searched.length();
}
return b;
}
public static boolean isInteger(String s) {
try {
Integer.parseInt(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isByte(String s) {
try {
Byte.parseByte(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isShort(String s) {
try {
Short.parseShort(s);
return true;
} catch (Exception e) {
return false;
}
}
public static boolean isLong(String s) {
try {
Long.parseLong(s);
return true;
} catch (Exception e) {
return false;
}
}
}
@@ -1,91 +0,0 @@
package me.dadus33.chatitem.utils;
import java.net.InetSocketAddress;
import org.bukkit.Bukkit;
import me.dadus33.chatitem.ChatItem;
public enum Version {
// http://wiki.vg/Protocol_version_numbers
V1_7(0, 5, 0),
V1_8(6, 47, 1),
V1_9(49, 110, 2), // 1.9.X - Starts with 49 as 48 was an april fools update
V1_10(201, 210, 3), // 1.10.X - Starts with 201 because why not.
V1_11(301, 316, 4),
V1_12(317, 340, 5),
V1_13(341, 440, 6),
V1_14(100, 441, 500),
V1_15(100, 550, 578),
V1_16(100, 700, 754),
V1_17(100, 755, 756),
V1_18(100, 757, 758),
V1_19(100, 759, 1000),
HIGHER(Integer.MAX_VALUE, -1, Integer.MAX_VALUE);
// Latest version should always have the upper limit set to Integer.MAX_VALUE so
// I don't have to update the plugin for every minor protocol change
public final int MIN_VER;
public final int MAX_VER;
public final int index; // Represents how new the version is (0 - extremely old)
private static final Version SERVER_VERSION;
public static final String BUKKIT_VERSION;
static {
BUKKIT_VERSION = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
SERVER_VERSION = getVersionByName(BUKKIT_VERSION);
}
Version(int min, int max, int index) {
this.MIN_VER = min;
this.MAX_VER = max;
this.index = index;
}
public boolean isNewerOrEquals(Version other) {
return index >= other.index;
}
public boolean isNewerThan(Version other) {
return index > other.index;
}
public static Version getVersionByName(String name) {
for (Version v : Version.values())
if (name.toLowerCase().startsWith(v.name().toLowerCase()))
return v;
return HIGHER;
}
public static Version getVersion(int protocolVersion) {
for (Version ver : Version.values()) {
if (protocolVersion >= ver.MIN_VER && protocolVersion <= ver.MAX_VER) {
return ver;
}
}
return HIGHER;
}
public static Version getVersion(int protocolVersion, Version def) {
for (Version ver : Version.values()) {
if (protocolVersion >= ver.MIN_VER && protocolVersion <= ver.MAX_VER) {
return ver;
}
}
ChatItem.debug("Failed to find version for protocol " + protocolVersion);
return def;
}
public static Version getVersion() {
return SERVER_VERSION;
}
public static String stringifyAdress(InetSocketAddress address) {
String port = String.valueOf(address.getPort());
String ip = address.getAddress().getHostAddress();
return ip + ":" + port;
}
}
File diff suppressed because it is too large. Load diff
+3 -12
View File
@@ -1,26 +1,17 @@
name: ChatItem
main: me.dadus33.chatitem.ChatItem
version: ${project.version}
softdepend: [ViaVersion, ProtocolSupport, ProtocolLib, LangUtils, HexNicks, EcoEnchants, DiscordSRV]
authors: [dadus33, WOLFI3654, Elikill58]
api-version: 1.13
depend: [ProtocolLib]
author: dadus33
commands:
cireload:
description: Reload the ChatItem config.
aliases: [chatitemreload, citemreload, cir]
permission: chatitem.reload
chatitem:
description: See and edit ChatItem informations
permission: chatitem.reload
permissions:
chatitem.reload:
description: Allows reloading the config
default: op
chatitem.use:
description: Allows your messages to be parsed by the plugin
default: op
chatitem.ignore-cooldown:
description: Allows you to ignore cooldowns (if enabled)
default: op
default: true