yep
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.yourname</groupId>
|
||||
<artifactId>DirtTrades</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>DirtTrades</name>
|
||||
|
||||
<properties>
|
||||
<java.version>21</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<maven.compiler.release>21</maven.compiler.release>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>papermc-repo</id>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.21.1-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.13.0</version>
|
||||
<configuration>
|
||||
<release>21</release>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.yourname.dirttrades;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class DirtTradesPlugin extends JavaPlugin {
|
||||
|
||||
private TradeManager tradeManager;
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
saveDefaultConfig();
|
||||
|
||||
this.tradeManager = new TradeManager(this);
|
||||
|
||||
TradeCommand tradeCommand = new TradeCommand(this, tradeManager);
|
||||
getCommand("trade").setExecutor(tradeCommand);
|
||||
getCommand("trade").setTabCompleter(tradeCommand);
|
||||
|
||||
Bukkit.getPluginManager().registerEvents(new TradeListener(this, tradeManager), this);
|
||||
|
||||
getLogger().info("DirtTrades enabled.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
if (tradeManager != null) {
|
||||
tradeManager.shutdown();
|
||||
}
|
||||
|
||||
getLogger().info("DirtTrades disabled.");
|
||||
}
|
||||
|
||||
public TradeManager getTradeManager() {
|
||||
return tradeManager;
|
||||
}
|
||||
|
||||
public void reloadPlugin() {
|
||||
reloadConfig();
|
||||
if (tradeManager != null) {
|
||||
tradeManager.reload();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.yourname.dirttrades;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TradeCommand implements CommandExecutor, TabCompleter {
|
||||
|
||||
private final DirtTradesPlugin plugin;
|
||||
private final TradeManager tradeManager;
|
||||
|
||||
public TradeCommand(DirtTradesPlugin plugin, TradeManager tradeManager) {
|
||||
this.plugin = plugin;
|
||||
this.tradeManager = tradeManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
|
||||
if (!(sender instanceof Player player)) {
|
||||
if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
|
||||
if (!sender.hasPermission("dirttrades.reload") && !sender.hasPermission("dirttrades.admin")) {
|
||||
sender.sendMessage(tradeManager.msg("no-permission"));
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.reloadPlugin();
|
||||
sender.sendMessage(tradeManager.msg("config-reloaded"));
|
||||
return true;
|
||||
}
|
||||
|
||||
sender.sendMessage(tradeManager.msg("player-only"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!player.hasPermission("dirttrades.use") && !player.hasPermission("dirttrades.admin")) {
|
||||
player.sendMessage(tradeManager.msg("no-permission"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (args.length == 0) {
|
||||
player.sendMessage(tradeManager.msg("usage"));
|
||||
return true;
|
||||
}
|
||||
|
||||
String sub = args[0];
|
||||
|
||||
if (sub.equalsIgnoreCase("accept")) {
|
||||
tradeManager.acceptRequest(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sub.equalsIgnoreCase("deny")) {
|
||||
tradeManager.denyRequest(player);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (sub.equalsIgnoreCase("reload")) {
|
||||
if (!player.hasPermission("dirttrades.reload") && !player.hasPermission("dirttrades.admin")) {
|
||||
player.sendMessage(tradeManager.msg("no-permission"));
|
||||
return true;
|
||||
}
|
||||
|
||||
plugin.reloadPlugin();
|
||||
player.sendMessage(tradeManager.msg("config-reloaded"));
|
||||
return true;
|
||||
}
|
||||
|
||||
Player target = Bukkit.getPlayerExact(sub);
|
||||
if (target == null || !target.isOnline()) {
|
||||
player.sendMessage(tradeManager.msg("player-not-found"));
|
||||
return true;
|
||||
}
|
||||
|
||||
tradeManager.sendTradeRequest(player, target);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
|
||||
if (args.length == 1) {
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add("accept");
|
||||
options.add("deny");
|
||||
if (sender.hasPermission("dirttrades.reload") || sender.hasPermission("dirttrades.admin")) {
|
||||
options.add("reload");
|
||||
}
|
||||
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
options.add(player.getName());
|
||||
}
|
||||
|
||||
String input = args[0].toLowerCase();
|
||||
List<String> matches = new ArrayList<>();
|
||||
for (String option : options) {
|
||||
if (option.toLowerCase().startsWith(input)) {
|
||||
matches.add(option);
|
||||
}
|
||||
}
|
||||
Collections.sort(matches);
|
||||
return matches;
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
package com.yourname.dirttrades;
|
||||
|
||||
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.inventory.InventoryAction;
|
||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.player.PlayerMoveEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TradeListener implements Listener {
|
||||
|
||||
private final DirtTradesPlugin plugin;
|
||||
private final TradeManager manager;
|
||||
private final Set<UUID> closingPlayers = new HashSet<>();
|
||||
private BukkitTask rangeTask;
|
||||
|
||||
public TradeListener(DirtTradesPlugin plugin, TradeManager manager) {
|
||||
this.plugin = plugin;
|
||||
this.manager = manager;
|
||||
startRangeTask();
|
||||
}
|
||||
|
||||
private void startRangeTask() {
|
||||
rangeTask = Bukkit.getScheduler().runTaskTimer(plugin, () -> {
|
||||
Set<TradeSession> checked = new HashSet<>();
|
||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||
TradeSession session = manager.getSession(player);
|
||||
if (session == null || checked.contains(session)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
checked.add(session);
|
||||
if (session.shouldCancelForDistance()) {
|
||||
manager.cancelTrade(session, null, false);
|
||||
|
||||
Player p1 = Bukkit.getPlayer(session.getPlayer1());
|
||||
Player p2 = Bukkit.getPlayer(session.getPlayer2());
|
||||
|
||||
if (p1 != null && p1.isOnline()) {
|
||||
p1.sendMessage(manager.msg("too-far"));
|
||||
}
|
||||
if (p2 != null && p2.isOnline()) {
|
||||
p2.sendMessage(manager.msg("too-far"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 20L, 20L);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onInventoryClick(InventoryClickEvent event) {
|
||||
if (!(event.getWhoClicked() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TradeSession session = manager.getSession(player);
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Inventory top = event.getView().getTopInventory();
|
||||
if (!top.equals(session.getInventory())) {
|
||||
return;
|
||||
}
|
||||
|
||||
int rawSlot = event.getRawSlot();
|
||||
|
||||
if (rawSlot < top.getSize()) {
|
||||
if (session.isOfferSlot(player, rawSlot)) {
|
||||
session.resetAccepts();
|
||||
return;
|
||||
}
|
||||
|
||||
if (session.isAnyButtonSlot(rawSlot)) {
|
||||
event.setCancelled(true);
|
||||
session.handleButtonClick(player, rawSlot);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
InventoryAction action = event.getAction();
|
||||
switch (action) {
|
||||
case MOVE_TO_OTHER_INVENTORY -> event.setCancelled(true);
|
||||
default -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onInventoryClose(InventoryCloseEvent event) {
|
||||
if (!(event.getPlayer() instanceof Player player)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TradeSession session = manager.getSession(player);
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!event.getInventory().equals(session.getInventory())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (session.isClosing()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (closingPlayers.contains(player.getUniqueId())) {
|
||||
return;
|
||||
}
|
||||
|
||||
closingPlayers.add(player.getUniqueId());
|
||||
Bukkit.getScheduler().runTask(plugin, () -> {
|
||||
try {
|
||||
TradeSession latest = manager.getSession(player);
|
||||
if (latest != null && latest == session && !latest.isClosing()) {
|
||||
manager.cancelTrade(latest, player.getUniqueId(), false);
|
||||
}
|
||||
} finally {
|
||||
closingPlayers.remove(player.getUniqueId());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onQuit(PlayerQuitEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
TradeSession session = manager.getSession(player);
|
||||
if (session != null) {
|
||||
manager.cancelTrade(session, player.getUniqueId(), true);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public void onMove(PlayerMoveEvent event) {
|
||||
if (!plugin.getConfig().getBoolean("settings.close-on-move-out-of-range", false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getTo() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.getFrom().getBlockX() == event.getTo().getBlockX()
|
||||
&& event.getFrom().getBlockY() == event.getTo().getBlockY()
|
||||
&& event.getFrom().getBlockZ() == event.getTo().getBlockZ()) {
|
||||
return;
|
||||
}
|
||||
|
||||
TradeSession session = manager.getSession(event.getPlayer());
|
||||
if (session == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (session.shouldCancelForDistance()) {
|
||||
manager.cancelTrade(session, event.getPlayer().getUniqueId(), false);
|
||||
|
||||
Player p1 = Bukkit.getPlayer(session.getPlayer1());
|
||||
Player p2 = Bukkit.getPlayer(session.getPlayer2());
|
||||
|
||||
if (p1 != null && p1.isOnline()) {
|
||||
p1.sendMessage(manager.msg("too-far"));
|
||||
}
|
||||
if (p2 != null && p2.isOnline()) {
|
||||
p2.sendMessage(manager.msg("too-far"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,406 @@
|
||||
package com.yourname.dirttrades;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemFlag;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.scheduler.BukkitTask;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class TradeManager {
|
||||
|
||||
private final DirtTradesPlugin plugin;
|
||||
|
||||
private final Map<UUID, TradeRequest> pendingRequests = new HashMap<>();
|
||||
private final Map<UUID, TradeSession> activeTrades = new HashMap<>();
|
||||
|
||||
public TradeManager(DirtTradesPlugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
for (TradeRequest request : new ArrayList<>(pendingRequests.values())) {
|
||||
if (request.expireTask != null) {
|
||||
request.expireTask.cancel();
|
||||
}
|
||||
}
|
||||
pendingRequests.clear();
|
||||
|
||||
for (TradeSession session : new HashSet<>(activeTrades.values())) {
|
||||
cancelTrade(session, null, true);
|
||||
}
|
||||
|
||||
activeTrades.clear();
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
reload();
|
||||
}
|
||||
|
||||
public void sendTradeRequest(Player sender, Player target) {
|
||||
if (plugin.getConfig().getBoolean("settings.prevent-self-trade", true)
|
||||
&& sender.getUniqueId().equals(target.getUniqueId())) {
|
||||
sender.sendMessage(msg("cannot-trade-self"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!target.hasPermission("dirttrades.use") && !target.hasPermission("dirttrades.admin")) {
|
||||
sender.sendMessage(msg("target-no-permission"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.getConfig().getBoolean("settings.block-creative-mode-trading", true)) {
|
||||
if (sender.getGameMode() == GameMode.CREATIVE || target.getGameMode() == GameMode.CREATIVE) {
|
||||
sender.sendMessage(msg("creative-blocked"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasPendingRequestBetween(sender.getUniqueId(), target.getUniqueId())) {
|
||||
sender.sendMessage(msg("already-in-trade"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isBusy(sender.getUniqueId()) || isBusy(target.getUniqueId())) {
|
||||
sender.sendMessage(msg("already-in-trade"));
|
||||
return;
|
||||
}
|
||||
|
||||
TradeRequest existing = pendingRequests.remove(target.getUniqueId());
|
||||
if (existing != null && existing.expireTask != null) {
|
||||
existing.expireTask.cancel();
|
||||
}
|
||||
|
||||
int expireSeconds = plugin.getConfig().getInt("settings.request-expire-seconds", 30);
|
||||
TradeRequest request = new TradeRequest(sender.getUniqueId(), target.getUniqueId());
|
||||
|
||||
request.expireTask = Bukkit.getScheduler().runTaskLater(plugin, () -> {
|
||||
TradeRequest current = pendingRequests.get(target.getUniqueId());
|
||||
if (current != null && current.sender.equals(sender.getUniqueId())) {
|
||||
pendingRequests.remove(target.getUniqueId());
|
||||
|
||||
Player onlineSender = Bukkit.getPlayer(sender.getUniqueId());
|
||||
Player onlineTarget = Bukkit.getPlayer(target.getUniqueId());
|
||||
|
||||
if (onlineSender != null && onlineSender.isOnline()) {
|
||||
onlineSender.sendMessage(msg("request-expired-sender")
|
||||
.replace("%target%", target.getName()));
|
||||
}
|
||||
if (onlineTarget != null && onlineTarget.isOnline()) {
|
||||
onlineTarget.sendMessage(msg("request-expired-target")
|
||||
.replace("%sender%", sender.getName()));
|
||||
}
|
||||
}
|
||||
}, expireSeconds * 20L);
|
||||
|
||||
pendingRequests.put(target.getUniqueId(), request);
|
||||
|
||||
sender.sendMessage(msg("request-sent").replace("%target%", target.getName()));
|
||||
target.sendMessage(msg("request-received").replace("%sender%", sender.getName()));
|
||||
target.sendMessage(msg("request-received-hover"));
|
||||
|
||||
playSound(sender, Sound.UI_BUTTON_CLICK);
|
||||
playSound(target, Sound.UI_BUTTON_CLICK);
|
||||
}
|
||||
|
||||
public void acceptRequest(Player target) {
|
||||
TradeRequest request = pendingRequests.remove(target.getUniqueId());
|
||||
if (request == null) {
|
||||
target.sendMessage(msg("no-pending-request"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.expireTask != null) {
|
||||
request.expireTask.cancel();
|
||||
}
|
||||
|
||||
Player sender = Bukkit.getPlayer(request.sender);
|
||||
if (sender == null || !sender.isOnline()) {
|
||||
target.sendMessage(msg("player-not-found"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.getConfig().getBoolean("settings.block-creative-mode-trading", true)) {
|
||||
if (sender.getGameMode() == GameMode.CREATIVE || target.getGameMode() == GameMode.CREATIVE) {
|
||||
target.sendMessage(msg("creative-blocked"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isBusy(sender.getUniqueId()) || isBusy(target.getUniqueId())) {
|
||||
target.sendMessage(msg("already-in-trade"));
|
||||
return;
|
||||
}
|
||||
|
||||
target.sendMessage(msg("request-accepted").replace("%sender%", sender.getName()));
|
||||
sender.sendMessage(msg("trade-started").replace("%player%", target.getName()));
|
||||
target.sendMessage(msg("trade-started").replace("%player%", sender.getName()));
|
||||
|
||||
startTrade(sender, target);
|
||||
}
|
||||
|
||||
public void denyRequest(Player target) {
|
||||
TradeRequest request = pendingRequests.remove(target.getUniqueId());
|
||||
if (request == null) {
|
||||
target.sendMessage(msg("no-pending-request"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.expireTask != null) {
|
||||
request.expireTask.cancel();
|
||||
}
|
||||
|
||||
Player sender = Bukkit.getPlayer(request.sender);
|
||||
target.sendMessage(msg("request-denied").replace("%sender%", sender != null ? sender.getName() : "Unknown"));
|
||||
|
||||
if (sender != null && sender.isOnline()) {
|
||||
sender.sendMessage(msg("request-denied-sender").replace("%target%", target.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
public void startTrade(Player player1, Player player2) {
|
||||
TradeSession session = new TradeSession(plugin, this, player1.getUniqueId(), player2.getUniqueId());
|
||||
activeTrades.put(player1.getUniqueId(), session);
|
||||
activeTrades.put(player2.getUniqueId(), session);
|
||||
session.open();
|
||||
}
|
||||
|
||||
public boolean isBusy(UUID uuid) {
|
||||
if (activeTrades.containsKey(uuid)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (TradeRequest request : pendingRequests.values()) {
|
||||
if (request.sender.equals(uuid) || request.target.equals(uuid)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasPendingRequestBetween(UUID a, UUID b) {
|
||||
for (TradeRequest request : pendingRequests.values()) {
|
||||
if ((request.sender.equals(a) && request.target.equals(b))
|
||||
|| (request.sender.equals(b) && request.target.equals(a))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public TradeSession getSession(Player player) {
|
||||
return activeTrades.get(player.getUniqueId());
|
||||
}
|
||||
|
||||
public void removeSession(TradeSession session) {
|
||||
activeTrades.remove(session.getPlayer1());
|
||||
activeTrades.remove(session.getPlayer2());
|
||||
}
|
||||
|
||||
public void cancelTrade(TradeSession session, UUID cancelledBy, boolean silent) {
|
||||
session.returnItemsToOwners();
|
||||
removeSession(session);
|
||||
|
||||
Player p1 = Bukkit.getPlayer(session.getPlayer1());
|
||||
Player p2 = Bukkit.getPlayer(session.getPlayer2());
|
||||
|
||||
clearActionBar(p1);
|
||||
clearActionBar(p2);
|
||||
|
||||
if (p1 != null && p1.isOnline() && p1.getOpenInventory().getTopInventory().equals(session.getInventory())) {
|
||||
p1.closeInventory();
|
||||
}
|
||||
if (p2 != null && p2.isOnline() && p2.getOpenInventory().getTopInventory().equals(session.getInventory())) {
|
||||
p2.closeInventory();
|
||||
}
|
||||
|
||||
if (!silent) {
|
||||
if (p1 != null && p1.isOnline()) {
|
||||
if (cancelledBy != null && cancelledBy.equals(p1.getUniqueId())) {
|
||||
p1.sendMessage(msg("trade-cancelled"));
|
||||
} else {
|
||||
p1.sendMessage(msg("trade-cancelled-other"));
|
||||
}
|
||||
}
|
||||
|
||||
if (p2 != null && p2.isOnline()) {
|
||||
if (cancelledBy != null && cancelledBy.equals(p2.getUniqueId())) {
|
||||
p2.sendMessage(msg("trade-cancelled"));
|
||||
} else {
|
||||
p2.sendMessage(msg("trade-cancelled-other"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void completeTrade(TradeSession session) {
|
||||
Player p1 = Bukkit.getPlayer(session.getPlayer1());
|
||||
Player p2 = Bukkit.getPlayer(session.getPlayer2());
|
||||
|
||||
if (p1 == null || p2 == null) {
|
||||
cancelTrade(session, null, true);
|
||||
return;
|
||||
}
|
||||
|
||||
List<ItemStack> p1Items = session.collectPlayer1Items();
|
||||
List<ItemStack> p2Items = session.collectPlayer2Items();
|
||||
|
||||
giveItems(p1, p2Items);
|
||||
giveItems(p2, p1Items);
|
||||
|
||||
removeSession(session);
|
||||
|
||||
clearActionBar(p1);
|
||||
clearActionBar(p2);
|
||||
|
||||
if (p1.getOpenInventory().getTopInventory().equals(session.getInventory())) {
|
||||
p1.closeInventory();
|
||||
}
|
||||
if (p2.getOpenInventory().getTopInventory().equals(session.getInventory())) {
|
||||
p2.closeInventory();
|
||||
}
|
||||
|
||||
p1.sendMessage(msg("trade-completed"));
|
||||
p2.sendMessage(msg("trade-completed"));
|
||||
|
||||
playSound(p1, Sound.ENTITY_PLAYER_LEVELUP);
|
||||
playSound(p2, Sound.ENTITY_PLAYER_LEVELUP);
|
||||
}
|
||||
|
||||
private void giveItems(Player player, List<ItemStack> items) {
|
||||
boolean droppedAny = false;
|
||||
|
||||
for (ItemStack item : items) {
|
||||
if (item == null || item.getType().isAir()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
HashMap<Integer, ItemStack> leftover = player.getInventory().addItem(item);
|
||||
if (!leftover.isEmpty()) {
|
||||
for (ItemStack left : leftover.values()) {
|
||||
if (plugin.getConfig().getBoolean("settings.drop-items-if-inventory-full", true)) {
|
||||
player.getWorld().dropItemNaturally(player.getLocation(), left);
|
||||
droppedAny = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (droppedAny) {
|
||||
player.sendMessage(msg("inventory-full-drop"));
|
||||
}
|
||||
}
|
||||
|
||||
public void sendWaitingActionBars(TradeSession session, boolean player1Accepted, boolean player2Accepted) {
|
||||
if (!plugin.getConfig().getBoolean("settings.actionbar-enabled", true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Player p1 = Bukkit.getPlayer(session.getPlayer1());
|
||||
Player p2 = Bukkit.getPlayer(session.getPlayer2());
|
||||
|
||||
if (p1 == null || p2 == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (player1Accepted && !player2Accepted) {
|
||||
sendActionBar(p1, rawMessage("actionbar-waiting-self"));
|
||||
sendActionBar(p2, rawMessage("actionbar-waiting-other"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!player1Accepted && player2Accepted) {
|
||||
sendActionBar(p2, rawMessage("actionbar-waiting-self"));
|
||||
sendActionBar(p1, rawMessage("actionbar-waiting-other"));
|
||||
return;
|
||||
}
|
||||
|
||||
clearActionBar(p1);
|
||||
clearActionBar(p2);
|
||||
}
|
||||
|
||||
public void clearActionBar(Player player) {
|
||||
if (player == null || !player.isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.sendActionBar(Component.text(color(plugin.getConfig().getString("messages.actionbar-cleared", ""))));
|
||||
}
|
||||
|
||||
public void sendActionBar(Player player, String message) {
|
||||
if (player == null || !player.isOnline()) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.sendActionBar(Component.text(color(message)));
|
||||
}
|
||||
|
||||
public String rawMessage(String path) {
|
||||
return plugin.getConfig().getString("messages." + path, "");
|
||||
}
|
||||
|
||||
public String msg(String path) {
|
||||
String prefix = color(plugin.getConfig().getString("messages.prefix", "&6[DirtTrades] &r"));
|
||||
String text = color(plugin.getConfig().getString("messages." + path, "&cMissing message: " + path));
|
||||
return prefix + text;
|
||||
}
|
||||
|
||||
public String color(String text) {
|
||||
return text == null ? "" : text.replace("&", "§");
|
||||
}
|
||||
|
||||
public ItemStack createConfiguredItem(String path) {
|
||||
ConfigurationSection section = plugin.getConfig().getConfigurationSection("items." + path);
|
||||
if (section == null) {
|
||||
return new ItemStack(Material.BARRIER);
|
||||
}
|
||||
|
||||
Material material = Material.matchMaterial(section.getString("material", "BARRIER"));
|
||||
if (material == null) {
|
||||
material = Material.BARRIER;
|
||||
}
|
||||
|
||||
ItemStack item = new ItemStack(material);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (meta != null) {
|
||||
meta.displayName(Component.text(color(section.getString("name", path))));
|
||||
List<String> loreLines = section.getStringList("lore");
|
||||
if (!loreLines.isEmpty()) {
|
||||
List<Component> lore = new ArrayList<>();
|
||||
for (String line : loreLines) {
|
||||
lore.add(Component.text(color(line)));
|
||||
}
|
||||
meta.lore(lore);
|
||||
}
|
||||
meta.addItemFlags(ItemFlag.HIDE_ATTRIBUTES);
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
public void playSound(Player player, Sound sound) {
|
||||
if (plugin.getConfig().getBoolean("settings.sound-enabled", true)) {
|
||||
player.playSound(player.getLocation(), sound, 1f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
private static class TradeRequest {
|
||||
private final UUID sender;
|
||||
private final UUID target;
|
||||
private BukkitTask expireTask;
|
||||
|
||||
private TradeRequest(UUID sender, UUID target) {
|
||||
this.sender = sender;
|
||||
this.target = target;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,252 @@
|
||||
package com.yourname.dirttrades;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class TradeSession {
|
||||
|
||||
private final DirtTradesPlugin plugin;
|
||||
private final TradeManager manager;
|
||||
private final UUID player1;
|
||||
private final UUID player2;
|
||||
private final Inventory inventory;
|
||||
|
||||
private boolean player1Accepted = false;
|
||||
private boolean player2Accepted = false;
|
||||
private boolean closing = false;
|
||||
|
||||
public TradeSession(DirtTradesPlugin plugin, TradeManager manager, UUID player1, UUID player2) {
|
||||
this.plugin = plugin;
|
||||
this.manager = manager;
|
||||
this.player1 = player1;
|
||||
this.player2 = player2;
|
||||
|
||||
String p1Name = Bukkit.getOfflinePlayer(player1).getName();
|
||||
String p2Name = Bukkit.getOfflinePlayer(player2).getName();
|
||||
String title = manager.color(plugin.getConfig().getString("gui.title", "&8Trade: %player1% &7<-> &f%player2%"))
|
||||
.replace("%player1%", p1Name == null ? "Player1" : p1Name)
|
||||
.replace("%player2%", p2Name == null ? "Player2" : p2Name);
|
||||
|
||||
int size = plugin.getConfig().getInt("gui.size", 54);
|
||||
this.inventory = Bukkit.createInventory(null, size, Component.text(title));
|
||||
|
||||
refreshButtons();
|
||||
}
|
||||
|
||||
public void open() {
|
||||
Player p1 = Bukkit.getPlayer(player1);
|
||||
Player p2 = Bukkit.getPlayer(player2);
|
||||
|
||||
if (p1 == null || p2 == null) {
|
||||
manager.cancelTrade(this, null, true);
|
||||
return;
|
||||
}
|
||||
|
||||
refreshButtons();
|
||||
p1.openInventory(inventory);
|
||||
p2.openInventory(inventory);
|
||||
manager.clearActionBar(p1);
|
||||
manager.clearActionBar(p2);
|
||||
}
|
||||
|
||||
public Inventory getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public UUID getPlayer1() {
|
||||
return player1;
|
||||
}
|
||||
|
||||
public UUID getPlayer2() {
|
||||
return player2;
|
||||
}
|
||||
|
||||
public boolean isClosing() {
|
||||
return closing;
|
||||
}
|
||||
|
||||
public boolean isPlayer1(Player player) {
|
||||
return player.getUniqueId().equals(player1);
|
||||
}
|
||||
|
||||
public boolean isPlayer2(Player player) {
|
||||
return player.getUniqueId().equals(player2);
|
||||
}
|
||||
|
||||
public boolean isOfferSlot(Player player, int slot) {
|
||||
if (isPlayer1(player)) {
|
||||
return plugin.getConfig().getIntegerList("gui.player1-slots").contains(slot);
|
||||
}
|
||||
if (isPlayer2(player)) {
|
||||
return plugin.getConfig().getIntegerList("gui.player2-slots").contains(slot);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isAnyButtonSlot(int slot) {
|
||||
return slot == plugin.getConfig().getInt("gui.accept-slot", 22)
|
||||
|| slot == plugin.getConfig().getInt("gui.decline-slot", 31);
|
||||
}
|
||||
|
||||
public void handleButtonClick(Player player, int slot) {
|
||||
int acceptSlot = plugin.getConfig().getInt("gui.accept-slot", 22);
|
||||
int declineSlot = plugin.getConfig().getInt("gui.decline-slot", 31);
|
||||
|
||||
if (slot == acceptSlot) {
|
||||
if (isPlayer1(player)) {
|
||||
player1Accepted = true;
|
||||
} else if (isPlayer2(player)) {
|
||||
player2Accepted = true;
|
||||
}
|
||||
|
||||
manager.playSound(player, Sound.UI_BUTTON_CLICK);
|
||||
refreshButtons();
|
||||
manager.sendWaitingActionBars(this, player1Accepted, player2Accepted);
|
||||
tryComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
if (slot == declineSlot) {
|
||||
manager.cancelTrade(this, player.getUniqueId(), false);
|
||||
}
|
||||
}
|
||||
|
||||
public void resetAccepts() {
|
||||
if (!player1Accepted && !player2Accepted) {
|
||||
return;
|
||||
}
|
||||
|
||||
player1Accepted = false;
|
||||
player2Accepted = false;
|
||||
refreshButtons();
|
||||
manager.sendWaitingActionBars(this, player1Accepted, player2Accepted);
|
||||
}
|
||||
|
||||
private void tryComplete() {
|
||||
if (player1Accepted && player2Accepted) {
|
||||
closing = true;
|
||||
manager.completeTrade(this);
|
||||
}
|
||||
}
|
||||
|
||||
public void refreshButtons() {
|
||||
for (int slot : plugin.getConfig().getIntegerList("gui.divider-slots")) {
|
||||
inventory.setItem(slot, manager.createConfiguredItem("divider"));
|
||||
}
|
||||
|
||||
int acceptSlot = plugin.getConfig().getInt("gui.accept-slot", 22);
|
||||
int declineSlot = plugin.getConfig().getInt("gui.decline-slot", 31);
|
||||
|
||||
if (player1Accepted || player2Accepted) {
|
||||
inventory.setItem(acceptSlot, manager.createConfiguredItem("accepted"));
|
||||
} else {
|
||||
inventory.setItem(acceptSlot, manager.createConfiguredItem("accept"));
|
||||
}
|
||||
|
||||
inventory.setItem(declineSlot, manager.createConfiguredItem("decline"));
|
||||
}
|
||||
|
||||
public void returnItemsToOwners() {
|
||||
List<ItemStack> p1Items = collectPlayer1Items();
|
||||
List<ItemStack> p2Items = collectPlayer2Items();
|
||||
|
||||
Player p1 = Bukkit.getPlayer(player1);
|
||||
Player p2 = Bukkit.getPlayer(player2);
|
||||
|
||||
if (p1 != null && p1.isOnline()) {
|
||||
giveBack(p1, p1Items);
|
||||
}
|
||||
|
||||
if (p2 != null && p2.isOnline()) {
|
||||
giveBack(p2, p2Items);
|
||||
}
|
||||
|
||||
clearOfferSlots();
|
||||
}
|
||||
|
||||
private void giveBack(Player player, List<ItemStack> items) {
|
||||
boolean droppedAny = false;
|
||||
|
||||
for (ItemStack item : items) {
|
||||
if (item == null || item.getType().isAir()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var leftover = player.getInventory().addItem(item);
|
||||
if (!leftover.isEmpty()) {
|
||||
for (ItemStack left : leftover.values()) {
|
||||
if (plugin.getConfig().getBoolean("settings.drop-items-if-inventory-full", true)) {
|
||||
player.getWorld().dropItemNaturally(player.getLocation(), left);
|
||||
droppedAny = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (droppedAny) {
|
||||
player.sendMessage(manager.msg("inventory-full-drop"));
|
||||
}
|
||||
}
|
||||
|
||||
public List<ItemStack> collectPlayer1Items() {
|
||||
List<ItemStack> items = new ArrayList<>();
|
||||
for (int slot : plugin.getConfig().getIntegerList("gui.player1-slots")) {
|
||||
ItemStack item = inventory.getItem(slot);
|
||||
if (item != null && !item.getType().isAir()) {
|
||||
items.add(item.clone());
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
public List<ItemStack> collectPlayer2Items() {
|
||||
List<ItemStack> items = new ArrayList<>();
|
||||
for (int slot : plugin.getConfig().getIntegerList("gui.player2-slots")) {
|
||||
ItemStack item = inventory.getItem(slot);
|
||||
if (item != null && !item.getType().isAir()) {
|
||||
items.add(item.clone());
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
public void clearOfferSlots() {
|
||||
for (int slot : plugin.getConfig().getIntegerList("gui.player1-slots")) {
|
||||
inventory.setItem(slot, new ItemStack(Material.AIR));
|
||||
}
|
||||
for (int slot : plugin.getConfig().getIntegerList("gui.player2-slots")) {
|
||||
inventory.setItem(slot, new ItemStack(Material.AIR));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldCancelForDistance() {
|
||||
if (!plugin.getConfig().getBoolean("settings.close-on-move-out-of-range", false)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Player p1 = Bukkit.getPlayer(player1);
|
||||
Player p2 = Bukkit.getPlayer(player2);
|
||||
if (p1 == null || p2 == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!p1.getWorld().equals(p2.getWorld())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Location l1 = p1.getLocation();
|
||||
Location l2 = p2.getLocation();
|
||||
double max = plugin.getConfig().getDouble("settings.max-trade-distance", 10.0);
|
||||
return l1.distanceSquared(l2) > (max * max);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
settings:
|
||||
request-expire-seconds: 30
|
||||
prevent-self-trade: true
|
||||
block-creative-mode-trading: true
|
||||
close-on-move-out-of-range: false
|
||||
max-trade-distance: 10.0
|
||||
drop-items-if-inventory-full: true
|
||||
sound-enabled: true
|
||||
actionbar-enabled: true
|
||||
|
||||
gui:
|
||||
title: "&8Dirt Trade: %player1% &7<-> &f%player2%"
|
||||
size: 54
|
||||
|
||||
divider-slots:
|
||||
- 4
|
||||
- 13
|
||||
- 40
|
||||
- 49
|
||||
|
||||
player1-slots:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 9
|
||||
- 10
|
||||
- 11
|
||||
- 12
|
||||
- 18
|
||||
- 19
|
||||
- 20
|
||||
- 21
|
||||
- 27
|
||||
- 28
|
||||
- 29
|
||||
- 30
|
||||
- 36
|
||||
- 37
|
||||
- 38
|
||||
- 39
|
||||
- 45
|
||||
- 46
|
||||
- 47
|
||||
- 48
|
||||
|
||||
player2-slots:
|
||||
- 5
|
||||
- 6
|
||||
- 7
|
||||
- 8
|
||||
- 14
|
||||
- 15
|
||||
- 16
|
||||
- 17
|
||||
- 23
|
||||
- 24
|
||||
- 25
|
||||
- 26
|
||||
- 32
|
||||
- 33
|
||||
- 34
|
||||
- 35
|
||||
- 41
|
||||
- 42
|
||||
- 43
|
||||
- 44
|
||||
- 50
|
||||
- 51
|
||||
- 52
|
||||
- 53
|
||||
|
||||
accept-slot: 22
|
||||
decline-slot: 31
|
||||
|
||||
items:
|
||||
divider:
|
||||
material: BLACK_STAINED_GLASS_PANE
|
||||
name: "&0"
|
||||
lore: []
|
||||
|
||||
accept:
|
||||
material: LIME_CONCRETE
|
||||
name: "&aAccept Trade"
|
||||
lore:
|
||||
- "&7Click to accept."
|
||||
- "&7If items change, accept resets."
|
||||
|
||||
accepted:
|
||||
material: GREEN_CONCRETE
|
||||
name: "&aAccepted"
|
||||
lore:
|
||||
- "&7Waiting for the other player..."
|
||||
|
||||
decline:
|
||||
material: RED_CONCRETE
|
||||
name: "&cDecline Trade"
|
||||
lore:
|
||||
- "&7Click to cancel this trade."
|
||||
|
||||
messages:
|
||||
prefix: "&6[DirtTrades] &r"
|
||||
|
||||
no-permission: "&cYou do not have permission."
|
||||
player-only: "&cOnly players can use this command."
|
||||
usage: "&eUsage: /trade <player|accept|deny|reload>"
|
||||
player-not-found: "&cThat player is not online."
|
||||
cannot-trade-self: "&cYou cannot trade with yourself."
|
||||
target-no-permission: "&cThat player cannot use trades."
|
||||
already-in-trade: "&cYou or that player is already in a trade."
|
||||
request-sent: "&aTrade request sent to &e%target%&a."
|
||||
request-received: "&e%sender% &ahas sent you a trade request."
|
||||
request-received-hover: "&7Use &f/trade accept &7or &f/trade deny"
|
||||
no-pending-request: "&cYou have no pending trade request."
|
||||
request-accepted: "&aYou accepted the trade request from &e%sender%&a."
|
||||
request-denied: "&cYou denied the trade request from &e%sender%&c."
|
||||
request-denied-sender: "&c%target% denied your trade request."
|
||||
request-expired-sender: "&cYour trade request to &e%target% &cexpired."
|
||||
request-expired-target: "&cThe trade request from &e%sender% &cexpired."
|
||||
trade-started: "&aTrade started with &e%player%&a."
|
||||
trade-cancelled: "&cTrade cancelled."
|
||||
trade-cancelled-other: "&cThe trade was cancelled by the other player."
|
||||
trade-completed: "&aTrade completed successfully."
|
||||
inventory-full-drop: "&eYour inventory was full, so some items were dropped."
|
||||
config-reloaded: "&aDirtTrades config reloaded."
|
||||
creative-blocked: "&cYou cannot trade while in creative mode."
|
||||
too-far: "&cTrade cancelled because a player moved too far away."
|
||||
|
||||
actionbar-waiting-self: "&aYou accepted &7- waiting for the other player..."
|
||||
actionbar-waiting-other: "&eOther player accepted &7- click accept to finish."
|
||||
actionbar-cleared: ""
|
||||
@@ -0,0 +1,25 @@
|
||||
name: DirtTrades
|
||||
version: 1.0-SNAPSHOT
|
||||
main: com.yourname.dirttrades.DirtTradesPlugin
|
||||
api-version: '1.21'
|
||||
|
||||
commands:
|
||||
trade:
|
||||
description: Main trade command
|
||||
usage: /trade <player|accept|deny|reload>
|
||||
aliases: [dtrade, trades]
|
||||
|
||||
permissions:
|
||||
dirttrades.use:
|
||||
description: Allows using trade commands
|
||||
default: true
|
||||
|
||||
dirttrades.reload:
|
||||
description: Allows reloading the plugin config
|
||||
default: op
|
||||
|
||||
dirttrades.admin:
|
||||
description: Admin access to DirtTrades
|
||||
default: op
|
||||
children:
|
||||
dirttrades.reload: true
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,131 @@
|
||||
settings:
|
||||
request-expire-seconds: 30
|
||||
prevent-self-trade: true
|
||||
block-creative-mode-trading: true
|
||||
close-on-move-out-of-range: false
|
||||
max-trade-distance: 10.0
|
||||
drop-items-if-inventory-full: true
|
||||
sound-enabled: true
|
||||
actionbar-enabled: true
|
||||
|
||||
gui:
|
||||
title: "&8Dirt Trade: %player1% &7<-> &f%player2%"
|
||||
size: 54
|
||||
|
||||
divider-slots:
|
||||
- 4
|
||||
- 13
|
||||
- 40
|
||||
- 49
|
||||
|
||||
player1-slots:
|
||||
- 0
|
||||
- 1
|
||||
- 2
|
||||
- 3
|
||||
- 9
|
||||
- 10
|
||||
- 11
|
||||
- 12
|
||||
- 18
|
||||
- 19
|
||||
- 20
|
||||
- 21
|
||||
- 27
|
||||
- 28
|
||||
- 29
|
||||
- 30
|
||||
- 36
|
||||
- 37
|
||||
- 38
|
||||
- 39
|
||||
- 45
|
||||
- 46
|
||||
- 47
|
||||
- 48
|
||||
|
||||
player2-slots:
|
||||
- 5
|
||||
- 6
|
||||
- 7
|
||||
- 8
|
||||
- 14
|
||||
- 15
|
||||
- 16
|
||||
- 17
|
||||
- 23
|
||||
- 24
|
||||
- 25
|
||||
- 26
|
||||
- 32
|
||||
- 33
|
||||
- 34
|
||||
- 35
|
||||
- 41
|
||||
- 42
|
||||
- 43
|
||||
- 44
|
||||
- 50
|
||||
- 51
|
||||
- 52
|
||||
- 53
|
||||
|
||||
accept-slot: 22
|
||||
decline-slot: 31
|
||||
|
||||
items:
|
||||
divider:
|
||||
material: BLACK_STAINED_GLASS_PANE
|
||||
name: "&0"
|
||||
lore: []
|
||||
|
||||
accept:
|
||||
material: LIME_CONCRETE
|
||||
name: "&aAccept Trade"
|
||||
lore:
|
||||
- "&7Click to accept."
|
||||
- "&7If items change, accept resets."
|
||||
|
||||
accepted:
|
||||
material: GREEN_CONCRETE
|
||||
name: "&aAccepted"
|
||||
lore:
|
||||
- "&7Waiting for the other player..."
|
||||
|
||||
decline:
|
||||
material: RED_CONCRETE
|
||||
name: "&cDecline Trade"
|
||||
lore:
|
||||
- "&7Click to cancel this trade."
|
||||
|
||||
messages:
|
||||
prefix: "&6[DirtTrades] &r"
|
||||
|
||||
no-permission: "&cYou do not have permission."
|
||||
player-only: "&cOnly players can use this command."
|
||||
usage: "&eUsage: /trade <player|accept|deny|reload>"
|
||||
player-not-found: "&cThat player is not online."
|
||||
cannot-trade-self: "&cYou cannot trade with yourself."
|
||||
target-no-permission: "&cThat player cannot use trades."
|
||||
already-in-trade: "&cYou or that player is already in a trade."
|
||||
request-sent: "&aTrade request sent to &e%target%&a."
|
||||
request-received: "&e%sender% &ahas sent you a trade request."
|
||||
request-received-hover: "&7Use &f/trade accept &7or &f/trade deny"
|
||||
no-pending-request: "&cYou have no pending trade request."
|
||||
request-accepted: "&aYou accepted the trade request from &e%sender%&a."
|
||||
request-denied: "&cYou denied the trade request from &e%sender%&c."
|
||||
request-denied-sender: "&c%target% denied your trade request."
|
||||
request-expired-sender: "&cYour trade request to &e%target% &cexpired."
|
||||
request-expired-target: "&cThe trade request from &e%sender% &cexpired."
|
||||
trade-started: "&aTrade started with &e%player%&a."
|
||||
trade-cancelled: "&cTrade cancelled."
|
||||
trade-cancelled-other: "&cThe trade was cancelled by the other player."
|
||||
trade-completed: "&aTrade completed successfully."
|
||||
inventory-full-drop: "&eYour inventory was full, so some items were dropped."
|
||||
config-reloaded: "&aDirtTrades config reloaded."
|
||||
creative-blocked: "&cYou cannot trade while in creative mode."
|
||||
too-far: "&cTrade cancelled because a player moved too far away."
|
||||
|
||||
actionbar-waiting-self: "&aYou accepted &7- waiting for the other player..."
|
||||
actionbar-waiting-other: "&eOther player accepted &7- click accept to finish."
|
||||
actionbar-cleared: ""
|
||||
@@ -0,0 +1,25 @@
|
||||
name: DirtTrades
|
||||
version: 1.0-SNAPSHOT
|
||||
main: com.yourname.dirttrades.DirtTradesPlugin
|
||||
api-version: '1.21'
|
||||
|
||||
commands:
|
||||
trade:
|
||||
description: Main trade command
|
||||
usage: /trade <player|accept|deny|reload>
|
||||
aliases: [dtrade, trades]
|
||||
|
||||
permissions:
|
||||
dirttrades.use:
|
||||
description: Allows using trade commands
|
||||
default: true
|
||||
|
||||
dirttrades.reload:
|
||||
description: Allows reloading the plugin config
|
||||
default: op
|
||||
|
||||
dirttrades.admin:
|
||||
description: Admin access to DirtTrades
|
||||
default: op
|
||||
children:
|
||||
dirttrades.reload: true
|
||||
@@ -0,0 +1,5 @@
|
||||
#Generated by Maven
|
||||
#Sun Jun 14 15:02:31 EDT 2026
|
||||
artifactId=DirtTrades
|
||||
groupId=com.yourname
|
||||
version=1.0-SNAPSHOT
|
||||
@@ -0,0 +1,7 @@
|
||||
com/yourname/dirttrades/TradeListener$1.class
|
||||
com/yourname/dirttrades/TradeCommand.class
|
||||
com/yourname/dirttrades/TradeListener.class
|
||||
com/yourname/dirttrades/DirtTradesPlugin.class
|
||||
com/yourname/dirttrades/TradeManager$TradeRequest.class
|
||||
com/yourname/dirttrades/TradeManager.class
|
||||
com/yourname/dirttrades/TradeSession.class
|
||||
@@ -0,0 +1,5 @@
|
||||
/home/bitnix/Desktop/DirtTrades/src/main/java/com/yourname/dirttrades/DirtTradesPlugin.java
|
||||
/home/bitnix/Desktop/DirtTrades/src/main/java/com/yourname/dirttrades/TradeCommand.java
|
||||
/home/bitnix/Desktop/DirtTrades/src/main/java/com/yourname/dirttrades/TradeListener.java
|
||||
/home/bitnix/Desktop/DirtTrades/src/main/java/com/yourname/dirttrades/TradeManager.java
|
||||
/home/bitnix/Desktop/DirtTrades/src/main/java/com/yourname/dirttrades/TradeSession.java
|
||||
Reference in New Issue
Block a user