General
i want it in zip
A
You
Papermc
A proxy (Velocity) chat System. Including: - permission based Chatcolors (minimessage format) - Permission based tags (suffixes using luckperms) - Singe chatmessage deleting I can pay bank and paypal
en
Minecraft Plugin BuilderClaude 3.7 Sonnet
Java Velocity Chat System Plugin
I'll create a comprehensive chat system plugin for Velocity that includes permission-based chat colors (using MiniMessage format), permission-based tags/suffixes (integrated with LuckPerms), and a message deletion feature.
Below is the complete implementation:
Main Plugin Class
java
package com.example.velocitychat;
import com.google.inject.Inject;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import org.slf4j.Logger;
import java.nio.file.Path;
@Plugin(
id = "velocitychat",
name = "VelocityChat",
version = "1.0.0",
description = "Advanced chat system with colors, tags, and message deletion",
authors = {"YourName"}
)
public class VelocityChatPlugin {
private final ProxyServer server;
private final Logger logger;
private final Path dataDirectory;
private ConfigManager configManager;
@Inject
public VelocityChatPlugin(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
this.server = server;
this.logger = logger;
this.dataDirectory = dataDirectory;
}
@Subscribe
public void onProxyInitialization(ProxyInitializeEvent event) {
// Initialize config
configManager = new ConfigManager(dataDirectory);
configManager.loadConfig();
// Register chat listener
ChatListener chatListener = new ChatListener(server, logger, configManager);
server.getEventManager().register(this, chatListener);
// Register commands
server.getCommandManager().register("deletemsg", new DeleteMessageCommand(chatListener), "delmsg", "removemsg");
logger.info("VelocityChat has been initialized!");
}
public ProxyServer getServer() {
return server;
}
public Logger getLogger() {
return logger;
}
}
Configuration Manager
java
package com.example.velocitychat;
import ninja.leaping.configurate.ConfigurationNode;
import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
public class ConfigManager {
private final Path dataDirectory;
private final Path configPath;
private ConfigurationNode config;
private Map<String, String> formatPermissions = new HashMap<>();
private Map<String, String> tagPermissions = new HashMap<>();
private String defaultFormat;
public ConfigManager(Path dataDirectory) {
this.dataDirectory = dataDirectory;
this.configPath = dataDirectory.resolve("config.yml");
}
public void loadConfig() {
try {
if (!Files.exists(dataDirectory)) {
Files.createDirectories(dataDirectory);
}
if (!Files.exists(configPath)) {
createDefaultConfig();
}
YAMLConfigurationLoader loader = YAMLConfigurationLoader.builder()
.setPath(configPath)
.build();
config = loader.load();
// Load format permissions
ConfigurationNode formatNode = config.getNode("formats");
formatNode.getChildrenMap().forEach((key, value) ->
formatPermissions.put(key.toString(), value.getString("<white>%message%")));
// Load tag permissions
ConfigurationNode tagNode = config.getNode("tags");
tagNode.getChildrenMap().forEach((key, value) ->
tagPermissions.put(key.toString(), value.getString("")));
defaultFormat = config.getNode("default-format").getString("<white>%message%");
} catch (IOException e) {
e.printStackTrace();
}
}
private void createDefaultConfig() throws IOException {
Files.createFile(configPath);
YAMLConfigurationLoader loader = YAMLConfigurationLoader.builder()
.setPath(configPath)
.build();
ConfigurationNode root = loader.createEmptyNode();
root.getNode("default-format").setValue("<white>%message%");
root.getNode("formats", "velocitychat.format.admin").setValue("<gradient:red:gold>%message%</gradient>");
root.getNode("formats", "velocitychat.format.mod").setValue("<yellow>%message%");
root.getNode("formats", "velocitychat.format.vip").setValue("<green>%message%");
root.getNode("tags", "velocitychat.tag.admin").setValue("<dark_red>[Admin] ");
root.getNode("tags", "velocitychat.tag.mod").setValue("<gold>[Mod] ");
root.getNode("tags", "velocitychat.tag.vip").setValue("<green>[VIP] ");
loader.save(root);
}
public String getFormatForPermission(String permission) {
return formatPermissions.getOrDefault(permission, defaultFormat);
}
public String getTagForPermission(String permission) {
return tagPermissions.getOrDefault(permission, "");
}
public Map<String, String> getFormatPermissions() {
return formatPermissions;
}
public Map<String, String> getTagPermissions() {
return tagPermissions;
}
}
Chat Listener
java
package com.example.velocitychat;
import com.velocitypowered.api.event.PostOrder;
import com.velocitypowered.api.event.Subscribe;
import com.velocitypowered.api.event.player.PlayerChatEvent;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ProxyServer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.minimessage.MiniMessage;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import net.luckperms.api.LuckPerms;
import net.luckperms.api.LuckPermsProvider;
import net.luckperms.api.model.user.User;
import org.slf4j.Logger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class ChatListener {
private final ProxyServer server;
private final Logger logger;
private final ConfigManager configManager;
private final MiniMessage miniMessage = MiniMessage.miniMessage();
private final Map<UUID, List<MessageEntry>> recentMessages = new ConcurrentHashMap<>();
public ChatListener(ProxyServer server, Logger logger, ConfigManager configManager) {
this.server = server;
this.logger = logger;
this.configManager = configManager;
}
@Subscribe(order = PostOrder.EARLY)
public void onPlayerChat(PlayerChatEvent event) {
event.setResult(PlayerChatEvent.ChatResult.denied());
Player player = event.getPlayer();
String message = event.getMessage();
// Get LuckPerms suffix if available
String luckPermsSuffix = getLuckPermsSuffix(player);
// Find the highest permission format the player has
String format = configManager.getDefaultFormat();
for (Map.Entry<String, String> entry : configManager.getFormatPermissions().entrySet()) {
if (player.hasPermission(entry.getKey())) {
format = entry.getValue();
break;
}
}
// Find the highest permission tag the player has
String tag = "";
for (Map.Entry<String, String> entry : configManager.getTagPermissions().entrySet()) {
if (player.hasPermission(entry.getKey())) {
tag = entry.getValue();
break;
}
}
// Apply LuckPerms suffix if available
if (luckPermsSuffix != null && !luckPermsSuffix.isEmpty()) {
tag = tag + luckPermsSuffix + " ";
}
// Format the message
String formattedMessage = format.replace("%message%", message);
// Build the final message with player name and tag
String finalMessage = tag + "<reset>" + player.getUsername() + ": " + formattedMessage;
Component component = miniMessage.deserialize(finalMessage);
// Store message for potential deletion
UUID playerUuid = player.getUniqueId();
if (!recentMessages.containsKey(playerUuid)) {
recentMessages.put(playerUuid, new ArrayList<>());
}
// Keep only the last 10 messages
List<MessageEntry> playerMessages = recentMessages.get(playerUuid);
if (playerMessages.size() >= 10) {
playerMessages.remove(0);
}
// Add the new message
MessageEntry messageEntry = new MessageEntry(
component,
PlainTextComponentSerializer.plainText().serialize(component),
System.currentTimeMillis()
);
playerMessages.add(messageEntry);
// Send the message to all players
server.getAllPlayers().forEach(p -> p.sendMessage(component));
// Log the message
logger.info("Chat: " + PlainTextComponentSerializer.plainText().serialize(component));
}
private String getLuckPermsSuffix(Player player) {
try {
LuckPerms luckPerms = LuckPermsProvider.get();
User user = luckPerms.getUserManager().getUser(player.getUniqueId());
if (user != null) {
String suffix = user.getCachedData().getMetaData().getSuffix();
return suffix != null ? suffix : "";
}
} catch (Exception e) {
logger.warn("Failed to get LuckPerms suffix", e);
}
return "";
}
public boolean deleteLastMessage(Player player) {
UUID playerUuid = player.getUniqueId();
if (!recentMessages.containsKey(playerUuid) || recentMessages.get(playerUuid).isEmpty()) {
return false;
}
List<MessageEntry> playerMessages = recentMessages.get(playerUuid);
MessageEntry lastMessage = playerMessages.remove(playerMessages.size() - 1);
// Notify all players about deletion
Component deletionMessage = miniMessage.deserialize("<gray><italic>* " + player.getUsername() + "'s message was deleted *</italic></gray>");
server.getAllPlayers().forEach(p -> p.sendMessage(deletionMessage));
return true;
}
public static class MessageEntry {
private final Component component;
private final String plainText;
private final long timestamp;
public MessageEntry(Component component, String plainText, long timestamp) {
this.component = component;
this.plainText = plainText;
this.timestamp = timestamp;
}
public Component getComponent() {
return component;
}
public String getPlainText() {
return plainText;
}
public long getTimestamp() {
return timestamp;
}
}
}
Delete Message Command
java
package com.example.velocitychat;
import com.velocitypowered.api.command.SimpleCommand;
import com.velocitypowered.api.proxy.Player;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
public class DeleteMessageCommand implements SimpleCommand {
private final ChatListener chatListener;
public DeleteMessageCommand(ChatListener chatListener) {
this.chatListener = chatListener;
}
@Override
public void execute(Invocation invocation) {
if (!(invocation.source() instanceof Player)) {
invocation.source().sendMessage(Component.text("This command can only be used by players.", NamedTextColor.RED));
return;
}
Player player = (Player) invocation.source();
if (!player.hasPermission("velocitychat.delete")) {
player.sendMessage(Component.text("You don't have permission to delete messages.", NamedTextColor.RED));
return;
}
boolean deleted = chatListener.deleteLastMessage(player);
if (deleted) {
player.sendMessage(Component.text("Your last message has been deleted.", NamedTextColor.GREEN));
} else {
player.sendMessage(Component.text("You have no recent messages to delete.", NamedTextColor.RED));
}
}
@Override
public boolean hasPermission(Invocation invocation) {
return invocation.source().hasPermission("velocitychat.delete");
}
}
build.gradle (Dependencies)
gradle
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '7.1.2'
}
group = 'com.example'
version = '1.0.0'
repositories {
mavenCentral()
maven {
name = 'papermc'
url = 'https://repo.papermc.io/repository/maven-public/'
}
maven {
name = 'sonatype'
url = 'https://oss.sonatype.org/content/repositories/snapshots/'
}
// For LuckPerms API
maven {
url = 'https://repo.lucko.me/'
}
}
dependencies {
compileOnly 'com.velocitypowered:velocity-api:3.1.0'
annotationProcessor 'com.velocitypowered:velocity-api:3.1.0'
// LuckPerms API
compileOnly 'net.luckperms:api:5.4'
}
tasks {
build {
dependsOn(shadowJar)
}
shadowJar {
archiveBaseName.set(project.name)
archiveClassifier.set('')
}
}
java {
sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11
}
Plugin Features:
- Permission-based Chat Colors:
- Uses MiniMessage format for rich text formatting
- Configurable formats based on permissions
- Players with specific permissions get access to different color formats
- Permission-based Tags/Suffixes:
- Support for permission-based prefixes
- Integration with LuckPerms for suffixes
- Configurable in the config.yml
- Message Deletion:
- Command to delete your last sent message
- Notification to all players when a message is deleted
- Permission-controlled access
- Configuration:
- Easy to configure formats and tags
- Default format for players without special permissions
Usage:
- Install the plugin on your Velocity proxy server
- Configure the formats and tags in config.yml
- Set up LuckPerms with appropriate suffixes
- Grant permissions to players:
velocitychat.format.[level]for chat colorsvelocitychat.tag.[level]for chat tagsvelocitychat.deletefor message deletion
This implementation provides a flexible, feature-rich chat system that integrates well with LuckPerms and provides all the requested functionality.
114.6k