Port to Paper 26.2 (2.0.0)

Snapshot of the 26.2 port published on Modrinth as 2.0.0 on 2026-08-06.
Built against paper-api 26.2.build.100-stable on Java 25. The changes had
only lived in the working tree on HPDebian (/root/mc-26.2/repos); this
commit records them as they were shipped. Details are in the 2.0.0 section
of the Modrinth changelog.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-30 16:35:33 +01:00
parent bc6e2296c6
commit cfc2efc9a5
91 changed files with 378 additions and 1293 deletions
+7 -7
View File
@@ -18,13 +18,13 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<source>21</source>
<target>21</target>
<source>25</source>
<target>25</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<version>3.6.2</version>
<executions>
<execution>
<phase>package</phase>
@@ -72,7 +72,7 @@
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.21.1-R0.1-SNAPSHOT</version>
<version>26.2.build.100-stable</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -83,9 +83,9 @@
</dependency>
</dependencies>
<properties>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.source>21</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<paper.version>1.21.1-R0.1-SNAPSHOT</paper.version>
<paper.version>26.2.build.100-stable</paper.version>
<maven.compiler.target>25</maven.compiler.target>
<maven.compiler.source>25</maven.compiler.source>
</properties>
</project>
+7 -7
View File
@@ -13,10 +13,10 @@
<description>A comprehensive player-to-player marketplace plugin with sales, auctions, and negotiations</description>
<properties>
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.source>25</maven.compiler.source>
<maven.compiler.target>25</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<paper.version>1.21.1-R0.1-SNAPSHOT</paper.version>
<paper.version>26.2.build.100-stable</paper.version>
</properties>
<repositories>
@@ -37,7 +37,7 @@
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>${paper.version}</version>
<version>26.2.build.100-stable</version>
<scope>provided</scope>
</dependency>
@@ -72,15 +72,15 @@
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<source>21</source>
<target>21</target>
<source>25</source>
<target>25</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.5.1</version>
<version>3.6.2</version>
<executions>
<execution>
<phase>package</phase>
@@ -120,7 +120,10 @@ public class BrowseMarketGui implements MarketGui {
var msgManager = plugin.getMessageManager();
ItemStack display = listing.getItem().clone();
display.setAmount(listing.getAmount());
// Display only: a count above the max stack size makes the stack resolve to
// empty since 26.1, so the icon would render as nothing. The real amount is
// in the lore.
display.setAmount(Math.min(listing.getAmount(), Math.max(1, display.getMaxStackSize())));
// Calculate time remaining
String expires;
@@ -382,8 +382,7 @@ public class CreateAuctionGui implements MarketGui {
// Creation failed AFTER we removed the items - give them back so nothing is lost.
ItemStack refund = auctionItem.clone();
refund.setAmount(amount);
ItemStack leftover = InventoryUtil.giveItem(player, refund);
if (leftover != null) {
for (ItemStack leftover : InventoryUtil.giveItemSplit(player, refund)) {
plugin.getClaimService().addClaimItem(player.getUniqueId(), leftover,
pt.henrique.communityMarket.model.ClaimItem.ClaimReason.ADMIN_RETURN,
"Auction creation failed");
@@ -327,8 +327,7 @@ public class CreateListingGui implements MarketGui {
// Creation failed AFTER we removed the items - give them back so nothing is lost.
ItemStack refund = listItem.clone();
refund.setAmount(amount);
ItemStack leftover = InventoryUtil.giveItem(player, refund);
if (leftover != null) {
for (ItemStack leftover : InventoryUtil.giveItemSplit(player, refund)) {
plugin.getClaimService().addClaimItem(player.getUniqueId(), leftover,
pt.henrique.communityMarket.model.ClaimItem.ClaimReason.ADMIN_RETURN,
"Listing creation failed");
@@ -80,7 +80,10 @@ public class MyListingsGui implements MarketGui {
var msgManager = plugin.getMessageManager();
ItemStack display = listing.getItem().clone();
display.setAmount(listing.getAmount());
// Display only: a count above the max stack size makes the stack resolve to
// empty since 26.1, so the icon would render as nothing. The real amount is
// in the lore.
display.setAmount(Math.min(listing.getAmount(), Math.max(1, display.getMaxStackSize())));
String expires;
if (listing.getExpiresAt() != null) {
@@ -112,9 +112,10 @@ public class QuantitySelectGui implements MarketGui {
)
.build());
// Item preview
// Item preview. Clamped: a count above the max stack size renders as an
// empty slot since 26.1. The chosen quantity is shown in the lore.
ItemStack displayItem = selectedItem.clone();
displayItem.setAmount(currentQuantity);
displayItem.setAmount(Math.min(currentQuantity, Math.max(1, displayItem.getMaxStackSize())));
inventory.setItem(ITEM_DISPLAY_SLOT, new ItemBuilder(displayItem)
.addLore(java.util.List.of(
"",
@@ -211,7 +212,7 @@ public class QuantitySelectGui implements MarketGui {
// Update item display amount
ItemStack displayItem = selectedItem.clone();
displayItem.setAmount(Math.min(currentQuantity, 64));
displayItem.setAmount(Math.min(currentQuantity, Math.max(1, displayItem.getMaxStackSize())));
inventory.setItem(ITEM_DISPLAY_SLOT, new ItemBuilder(displayItem)
.addLore(java.util.List.of(
"",
@@ -53,7 +53,9 @@ public class AuctionService {
return CompletableFuture.completedFuture(-1);
}
if (plugin.getConfigManager().isMaterialBlacklisted(item.getType())) {
// Last gate before persistence: applies the blacklist to the payload too,
// so a banned material cannot enter the market inside a container.
if (!plugin.getTransactionService().validateItem(item).isValid()) {
return CompletableFuture.completedFuture(-1);
}
@@ -77,9 +77,10 @@ public class ClaimService {
// Give item to player on main thread
Bukkit.getScheduler().runTask(plugin, () -> {
ItemStack leftover = InventoryUtil.giveItem(player, claimItem.getItem());
if (leftover != null) {
// This shouldn't happen since we checked space, but just in case
// Every leftover stack is re-stored, not just the first:
// an item stored before the split fix can be several
// stacks wide and must not lose the tail.
for (ItemStack leftover : InventoryUtil.giveItemSplit(player, claimItem.getItem())) {
plugin.getDatabaseManager().addClaimItem(new ClaimItem(
player.getUniqueId(),
leftover,
@@ -118,8 +119,7 @@ public class ClaimService {
ItemStack itemToGive = item.getItem();
ClaimItem source = item;
Bukkit.getScheduler().runTask(plugin, () -> {
ItemStack leftover = InventoryUtil.giveItem(player, itemToGive);
if (leftover != null) {
for (ItemStack leftover : InventoryUtil.giveItemSplit(player, itemToGive)) {
// Inventory filled up mid-claim: put the remainder back into
// claim storage instead of silently destroying the items.
plugin.getDatabaseManager().addClaimItem(new ClaimItem(
@@ -52,7 +52,9 @@ public class ListingService {
return CompletableFuture.completedFuture(-1);
}
if (plugin.getConfigManager().isMaterialBlacklisted(item.getType())) {
// Last gate before persistence: applies the blacklist to the payload too,
// so a banned material cannot enter the market inside a container.
if (!plugin.getTransactionService().validateItem(item).isValid()) {
return CompletableFuture.completedFuture(-1);
}
@@ -229,17 +231,19 @@ public class ListingService {
Bukkit.getScheduler().runTask(plugin, () -> {
ItemStack item = listing.getItem().clone();
item.setAmount(listing.getAmount());
ItemStack leftover = InventoryUtil.giveItem(buyer, item);
java.util.List<ItemStack> leftovers = InventoryUtil.giveItemSplit(buyer, item);
if (leftover != null) {
// Couldn't fit in inventory, add to claim storage
ClaimItem claimItem = new ClaimItem(
buyer.getUniqueId(),
leftover,
ClaimItem.ClaimReason.PURCHASE_FULL_INVENTORY,
"Listing #" + listingId
);
plugin.getDatabaseManager().addClaimItem(claimItem);
if (!leftovers.isEmpty()) {
// Couldn't fit in inventory, add to claim storage.
// Every leftover stack is stored, not just the first.
for (ItemStack leftover : leftovers) {
plugin.getDatabaseManager().addClaimItem(new ClaimItem(
buyer.getUniqueId(),
leftover,
ClaimItem.ClaimReason.PURCHASE_FULL_INVENTORY,
"Listing #" + listingId
));
}
buyer.sendMessage(plugin.getMessageManager().getPrefixed("messages.claim-inventory-full"));
}
});
@@ -3,6 +3,7 @@ package pt.henrique.communityMarket.service;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import pt.henrique.communityMarket.CommunityMarket;
import pt.henrique.communityMarket.util.ContainerItemUtil;
import java.util.concurrent.CompletableFuture;
@@ -22,6 +23,11 @@ public class TransactionService {
/**
* Validates an item before it can be listed or auctioned.
* Checks material blacklist, keywords in name/lore, and other restrictions.
* <p>
* Prices here are set by the seller and the item is transferred intact, so a
* loaded container is not refused. What is refused is a banned material or a
* banned lore keyword hidden inside a shulker box, a bundle, a sulfur cube
* bucket or a crossbow, so every rule is applied to the payload as well.
*
* @param item The item to validate
* @return ValidationResult with success status and error message if applicable
@@ -31,6 +37,23 @@ public class TransactionService {
return new ValidationResult(false, "invalid-item");
}
ValidationResult own = validateSingleStack(item);
if (!own.isValid()) return own;
for (ItemStack nested : ContainerItemUtil.flattenPayload(item)) {
ValidationResult inner = validateSingleStack(nested);
if (!inner.isValid()) return inner;
}
return new ValidationResult(true, null);
}
/** Applies the blacklist rules to one stack, ignoring anything it contains. */
private ValidationResult validateSingleStack(ItemStack item) {
if (item == null || item.getType().isAir()) {
return new ValidationResult(true, null);
}
// Check material blacklist
if (plugin.getConfigManager().isMaterialBlacklisted(item.getType())) {
return new ValidationResult(false, "blacklisted-item");
@@ -0,0 +1,227 @@
package pt.henrique.communityMarket.util;
import io.papermc.paper.datacomponent.DataComponentTypes;
import io.papermc.paper.datacomponent.item.BundleContents;
import io.papermc.paper.datacomponent.item.ChargedProjectiles;
import io.papermc.paper.datacomponent.item.ItemContainerContents;
import io.papermc.paper.datacomponent.item.SulfurCubeContent;
import org.bukkit.block.ShulkerBox;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.BlockStateMeta;
import org.bukkit.inventory.meta.BundleMeta;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
/**
* Single answer to "does this stack contain other stacks, and if so which ones".
* <p>
* As of 26.2 an {@link ItemStack} can carry other stacks in four distinct ways,
* none of which share an API:
* <ol>
* <li>Shulker boxes and other block-entity items: {@link BlockStateMeta} whose
* block state is a container, or the {@code minecraft:container} component.</li>
* <li>Bundles: {@link BundleMeta#getItems()} / {@code minecraft:bundle_contents}.</li>
* <li>{@code SULFUR_CUBE_BUCKET}: {@code minecraft:sulfur_cube_content}, reached
* through {@link SulfurCubeContent#absorbedItem()}. Neither a
* {@link BlockStateMeta} nor a {@link BundleMeta}.</li>
* <li>Crossbows: {@code minecraft:charged_projectiles}.</li>
* </ol>
* The server's own {@code ItemStack.validateComponents} recurses into
* {@code CONTAINER}, {@code BUNDLE_CONTENTS} and {@code CHARGED_PROJECTILES} but
* <b>not</b> {@code SULFUR_CUBE_CONTENT}, so a sulfur cube bucket payload is never
* sanitised by the server. Every pricing, selling, listing and anti-dupe check must
* go through {@link #payloadOf(ItemStack)} rather than testing for a shulker box.
* <p>
* The shulker-box read/rewrite helpers below stay shulker-specific: they back the
* three-option shulker sell flow, which needs the 27-slot inventory shape. Buckets,
* bundles and crossbows have no such shape and are never opened, only refused.
*/
public final class ContainerItemUtil {
/** Number of slots inside a shulker box. */
public static final int SHULKER_SIZE = 27;
/**
* Levels of nesting inspected by {@link #flattenPayload(ItemStack)}.
* Vanilla forbids shulker-in-shulker, so one level is enough today; the cap
* exists so a datapack or plugin that deepens the nesting cannot walk past
* the guard, and so a malformed cyclic payload cannot loop forever.
*/
public static final int MAX_NESTING_DEPTH = 3;
private ContainerItemUtil() {}
// ══════════════════════════════════════════════════════════════
// General nesting
// ══════════════════════════════════════════════════════════════
/**
* Returns the stacks held directly inside this one, across all four nesting
* classes. Empty when the stack holds nothing or is not a container.
* The returned stacks are the live snapshots handed back by the API; callers
* that keep them should clone.
*/
public static List<ItemStack> payloadOf(ItemStack stack) {
if (stack == null || stack.getType().isAir()) return List.of();
List<ItemStack> out = new ArrayList<>();
// getItemMeta() clones, and this runs once per inventory slot in the sell
// scans, so the meta routes are gated on the type name first. The component
// checks below are cheap map lookups and cover everything the gate misses,
// including block-entity items that are not shulker boxes.
String typeName = stack.getType().name();
if (typeName.endsWith("SHULKER_BOX")) {
if (stack.getItemMeta() instanceof BlockStateMeta bsm
&& bsm.getBlockState() instanceof ShulkerBox box) {
addNonEmpty(out, box.getInventory().getContents());
}
} else if (typeName.endsWith("BUNDLE")) {
if (stack.getItemMeta() instanceof BundleMeta bundle) {
addNonEmpty(out, bundle.getItems());
}
}
if (out.isEmpty() && stack.hasData(DataComponentTypes.CONTAINER)) {
ItemContainerContents container = stack.getData(DataComponentTypes.CONTAINER);
if (container != null) addNonEmpty(out, container.contents());
}
if (out.isEmpty() && stack.hasData(DataComponentTypes.BUNDLE_CONTENTS)) {
BundleContents bundle = stack.getData(DataComponentTypes.BUNDLE_CONTENTS);
if (bundle != null) addNonEmpty(out, bundle.contents());
}
if (stack.hasData(DataComponentTypes.SULFUR_CUBE_CONTENT)) {
SulfurCubeContent cube = stack.getData(DataComponentTypes.SULFUR_CUBE_CONTENT);
if (cube != null) addNonEmpty(out, List.of(cube.absorbedItem()));
}
if (stack.hasData(DataComponentTypes.CHARGED_PROJECTILES)) {
ChargedProjectiles charged = stack.getData(DataComponentTypes.CHARGED_PROJECTILES);
if (charged != null) addNonEmpty(out, charged.projectiles());
}
return out;
}
/**
* True when this stack carries other stacks. Such items are refused by every
* server-shop path: their payload has no price and would be destroyed with the
* container, and a container priced as empty is a value-laundering route.
*/
public static boolean isNestingItemWithContents(ItemStack stack) {
return !payloadOf(stack).isEmpty();
}
/**
* Every stack reachable from this one, breadth-first, down to
* {@link #MAX_NESTING_DEPTH} levels. The stack itself is not included.
* Used by the blacklist checks, which must see a banned material or a banned
* lore keyword wherever it is hidden.
*/
public static List<ItemStack> flattenPayload(ItemStack stack) {
List<ItemStack> out = new ArrayList<>();
Deque<ItemStack> frontier = new ArrayDeque<>(payloadOf(stack));
int depth = 0;
while (!frontier.isEmpty() && depth < MAX_NESTING_DEPTH) {
int levelSize = frontier.size();
for (int i = 0; i < levelSize; i++) {
ItemStack current = frontier.poll();
if (current == null) continue;
out.add(current);
if (depth + 1 < MAX_NESTING_DEPTH) frontier.addAll(payloadOf(current));
}
depth++;
}
return out;
}
/** Total number of items (summed amounts) held inside this stack, one level deep. */
public static int countTotalItems(ItemStack stack) {
int total = 0;
for (ItemStack c : payloadOf(stack)) total += c.getAmount();
return total;
}
/** Number of occupied slots inside this stack, one level deep. */
public static int countNonEmptySlots(ItemStack stack) {
return payloadOf(stack).size();
}
// ══════════════════════════════════════════════════════════════
// Shulker boxes: read and rewrite
// ══════════════════════════════════════════════════════════════
/** @return true if the stack is any shulker box (all 16 colors + uncolored). */
public static boolean isShulkerBox(ItemStack stack) {
return stack != null && !stack.getType().isAir()
&& stack.getType().name().endsWith("SHULKER_BOX");
}
/**
* Returns the shulker's internal contents as a detached snapshot array.
* {@code getBlockState()} returns a copy, so reading never mutates the original
* item. Returns an empty array if the stack is not a shulker box.
*/
public static ItemStack[] getContents(ItemStack shulker) {
if (!isShulkerBox(shulker)) return new ItemStack[0];
if (!(shulker.getItemMeta() instanceof BlockStateMeta bsm)) return new ItemStack[0];
if (!(bsm.getBlockState() instanceof ShulkerBox box)) return new ItemStack[0];
return box.getInventory().getContents();
}
/** @return true if the shulker box contains at least one item. */
public static boolean hasContents(ItemStack shulker) {
for (ItemStack c : getContents(shulker)) {
if (c != null && !c.getType().isAir()) return true;
}
return false;
}
/** Returns a clone of the shulker with its internal inventory emptied. */
public static ItemStack emptiedClone(ItemStack shulker) {
ItemStack clone = shulker.clone();
if (clone.getItemMeta() instanceof BlockStateMeta bsm
&& bsm.getBlockState() instanceof ShulkerBox box) {
box.getInventory().clear();
bsm.setBlockState(box);
clone.setItemMeta(bsm);
}
return clone;
}
/**
* Returns a clone of the shulker whose internal contents are replaced by the
* given array (length must be at most {@link #SHULKER_SIZE}; shorter arrays
* clear the remaining slots).
*/
public static ItemStack withContents(ItemStack shulker, ItemStack[] newContents) {
ItemStack clone = shulker.clone();
if (clone.getItemMeta() instanceof BlockStateMeta bsm
&& bsm.getBlockState() instanceof ShulkerBox box) {
box.getInventory().setContents(newContents);
bsm.setBlockState(box);
clone.setItemMeta(bsm);
}
return clone;
}
// ══════════════════════════════════════════════════════════════
// Helpers
// ══════════════════════════════════════════════════════════════
private static void addNonEmpty(List<ItemStack> out, ItemStack[] items) {
if (items == null) return;
for (ItemStack i : items) {
if (i != null && !i.getType().isAir()) out.add(i);
}
}
private static void addNonEmpty(List<ItemStack> out, List<ItemStack> items) {
if (items == null) return;
for (ItemStack i : items) {
if (i != null && !i.getType().isAir()) out.add(i);
}
}
}
@@ -6,6 +6,7 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import pt.henrique.communityMarket.CommunityMarket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -51,24 +52,73 @@ public class InventoryUtil {
}
/**
* Gives an item to a player, returning any items that couldn't fit
* Splits a stack into legally-sized stacks.
* <p>
* Since 26.1 an {@link ItemStack} whose count exceeds its max stack size is
* treated as empty by the server, so a "give 320 dirt" shortcut built as one
* stack hands the player nothing. Anything that multiplies a quantity into a
* single stack must route through this first. The input amount is used as the
* total; the returned stacks are clones.
*
* @return one or more stacks, each within its max stack size; empty for air
*/
public static List<ItemStack> splitIntoLegalStacks(ItemStack item) {
if (item == null || item.getType().isAir() || item.getAmount() <= 0) {
return List.of();
}
int maxStack = Math.max(1, item.getMaxStackSize());
if (item.getAmount() <= maxStack) {
return List.of(item.clone());
}
List<ItemStack> out = new ArrayList<>();
for (int left = item.getAmount(); left > 0; left -= maxStack) {
ItemStack part = item.clone();
part.setAmount(Math.min(left, maxStack));
out.add(part);
}
return out;
}
/** @return true when the stack's count is within its max stack size. */
public static boolean isLegalStack(ItemStack item) {
return item == null || item.getType().isAir()
|| item.getAmount() <= Math.max(1, item.getMaxStackSize());
}
/**
* Gives an item to a player, returning any items that couldn't fit.
* The item is split into legal stacks first, so an oversized input is handed
* over in full instead of resolving to nothing.
*
* @param player The player
* @param item The item to give
* @return Items that couldn't fit, or null if all items were added
*/
public static ItemStack giveItem(Player player, ItemStack item) {
if (item == null || item.getType().isAir()) {
return null;
List<ItemStack> leftovers = giveItemSplit(player, item);
return leftovers.isEmpty() ? null : leftovers.get(0);
}
/**
* Gives an item to a player as legal stacks.
*
* @return every stack that did not fit, each within its max stack size
*/
public static List<ItemStack> giveItemSplit(Player player, ItemStack item) {
List<ItemStack> parts = splitIntoLegalStacks(item);
if (parts.isEmpty()) {
return List.of();
}
HashMap<Integer, ItemStack> leftover = player.getInventory().addItem(item.clone());
HashMap<Integer, ItemStack> leftover =
player.getInventory().addItem(parts.toArray(new ItemStack[0]));
if (leftover.isEmpty()) {
return null;
return List.of();
}
return leftover.values().iterator().next();
return new ArrayList<>(leftover.values());
}
/**
@@ -87,7 +137,12 @@ public class InventoryUtil {
ItemStack toRemove = item.clone();
toRemove.setAmount(amount);
HashMap<Integer, ItemStack> notRemoved = player.getInventory().removeItem(toRemove);
// Split first: an over-full stack is treated as empty since 26.1, so a
// single oversized removal request could take nothing while reporting
// success.
List<ItemStack> parts = splitIntoLegalStacks(toRemove);
HashMap<Integer, ItemStack> notRemoved =
player.getInventory().removeItem(parts.toArray(new ItemStack[0]));
return notRemoved.isEmpty();
}
@@ -38,8 +38,20 @@ public class ItemBuilder {
/**
* Creates a new ItemBuilder from an existing ItemStack
*/
/**
* Wraps an existing stack as a GUI icon.
* <p>
* The count is clamped to the item's max stack size. Builder output only ever
* goes into plugin GUI inventories, never to a player, and since 26.1 an
* over-full stack resolves to empty, which would render the icon as a blank
* slot. Real quantities are shown in the lore.
*/
public ItemBuilder(ItemStack item) {
this.item = item.clone();
int maxStack = Math.max(1, this.item.getMaxStackSize());
if (this.item.getAmount() > maxStack) {
this.item.setAmount(maxStack);
}
this.meta = this.item.getItemMeta();
}
@@ -115,7 +127,7 @@ public class ItemBuilder {
* Sets the item amount
*/
public ItemBuilder amount(int amount) {
item.setAmount(Math.min(64, Math.max(1, amount)));
item.setAmount(Math.min(Math.max(1, item.getMaxStackSize()), Math.max(1, amount)));
return this;
}
+1 -1
View File
@@ -1,7 +1,7 @@
name: CommunityMarket
version: '${project.version}'
main: pt.henrique.communityMarket.CommunityMarket
api-version: '1.21'
api-version: "26.2"
description: A GUI-only marketplace plugin for fixed-price listings and auctions
author: Henrique
website: https://github.com/henriquescrrrr/carrageis-communitymarket
-152
View File
@@ -1,152 +0,0 @@
# ============================================
# CommunityMarket Configuration
# A GUI-only marketplace plugin
# ============================================
# Language setting (available: en_US, pt_PT)
language: en_US
# Database Configuration
database:
# Type: sqlite or mysql
type: sqlite
sqlite:
file: database.db
mysql:
host: localhost
port: 3306
database: communitymarket
username: root
password: ""
pool:
maximum-pool-size: 10
minimum-idle: 2
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
# Economy Settings
economy:
# Currency display format (uses Java DecimalFormat)
currency-format: "$#,##0.00"
currency-symbol: "$"
taxes:
# Tax percentage for fixed-price market sales (seller pays)
market-tax: 5.0
# Tax percentage for auction sales (seller pays)
auction-tax: 7.5
# Fixed-Price Market Settings
market:
# Maximum active listings per player
max-listings-per-player: 20
# Cooldown between creating listings (seconds, 0 = disabled)
listing-cooldown: 0
# Default listing duration in hours
default-duration-hours: 168
# Available durations for players to choose (in hours)
available-durations:
- 24
- 72
- 168
- 336
# Price limits
min-price: 1.0
max-price: 1000000000.0
# Auction Settings
auction:
# Maximum active auctions per player
max-auctions-per-player: 10
# Duration limits (hours)
min-duration-hours: 1
max-duration-hours: 168
default-duration-hours: 24
# Available durations for players to choose (in hours)
available-durations:
- 1
- 6
- 12
- 24
- 48
- 72
- 168
# Price limits for starting bid
min-start-price: 1.0
max-start-price: 1000000000.0
# Minimum bid increment (percentage of current bid)
min-bid-increment-percent: 5.0
# Minimum absolute bid increment
min-bid-increment-absolute: 1.0
# Anti-snipe protection
anti-snipe:
enabled: true
# If bid placed within this many seconds of end, extend auction
trigger-seconds: 30
# How many seconds to extend
extension-seconds: 30
# Maximum number of extensions (0 = unlimited)
max-extensions: 10
# Item Blacklist
blacklist:
# Materials that cannot be listed/auctioned
materials:
- BARRIER
- COMMAND_BLOCK
- CHAIN_COMMAND_BLOCK
- REPEATING_COMMAND_BLOCK
- COMMAND_BLOCK_MINECART
- STRUCTURE_BLOCK
- STRUCTURE_VOID
- JIGSAW
- DEBUG_STICK
- KNOWLEDGE_BOOK
- SPAWNER
- BEDROCK
# Items with these keywords in their name/lore are blocked
keywords:
- "admin"
- "illegal"
- "exploit"
# GUI Settings
gui:
# Items displayed per page in browse views
items-per-page: 45
# Whether to show the Help button in the main menu
# Set to false to hide it (slot will be filled with glass)
show-help-button: true
# Sound effects (use Bukkit Sound enum names)
sounds:
click: UI_BUTTON_CLICK
success: ENTITY_PLAYER_LEVELUP
error: ENTITY_VILLAGER_NO
purchase: ENTITY_EXPERIENCE_ORB_PICKUP
# Notification Settings
notifications:
# Notify seller when their item sells
notify-on-sale: true
# Notify bidder when they are outbid
notify-on-outbid: true
# Notify winner when they win an auction
notify-on-win: true
# Notify seller when their listing expires
notify-on-expire: true
# Performance Settings
performance:
# How often to cache listings/auctions (seconds)
cache-duration: 30
# How often to check for ended auctions (seconds)
auction-check-interval: 5
# How often to check for expired listings (minutes)
expired-check-interval: 5
-448
View File
@@ -1,448 +0,0 @@
# ============================================
# CommunityMarket Language File - English (US)
# ============================================
# General
prefix: "&8[&6Market&8] &r"
# General Messages
messages:
no-permission: "&cYou don't have permission to do that."
player-only: "&cThis command can only be used by players."
reload-success: "&aConfiguration reloaded successfully!"
economy-not-found: "&cNo economy plugin found! Market disabled."
# Listing Messages
listing-created: "&aListing created successfully! ID: #{id}"
listing-cancelled: "&aListing cancelled. Item returned to claim storage."
listing-expired: "&eYour listing #{id} has expired. Item moved to claim storage."
listing-purchased: "&aYou purchased {item} x{amount} for {price}!"
listing-sold: "&aYour {item} x{amount} was sold to {buyer} for {price}!"
listing-limit-reached: "&cYou've reached the maximum number of listings ({max})."
listing-cooldown: "&cPlease wait {time} before creating another listing."
listing-not-found: "&cListing not found or no longer available."
listing-own-item: "&cYou cannot buy your own listing."
listing-insufficient-funds: "&cYou don't have enough money. Required: {price}"
# Auction Messages
auction-created: "&aAuction created successfully! ID: #{id}"
auction-cancelled: "&aAuction cancelled. Item returned to claim storage."
auction-ended-winner: "&aCongratulations! You won the auction for {item}! Paid: {price}"
auction-ended-seller: "&aYour auction for {item} ended! Winner: {winner}, Earned: {price}"
auction-ended-no-bids: "&eYour auction for {item} ended with no bids. Item moved to claim storage."
auction-limit-reached: "&cYou've reached the maximum number of auctions ({max})."
auction-not-found: "&cAuction not found or no longer available."
auction-own-item: "&cYou cannot bid on your own auction."
auction-bid-placed: "&aYou placed a bid of {amount} on {item}!"
auction-outbid: "&eYou've been outbid on {item}! New bid: {amount} by {bidder}"
auction-bid-too-low: "&cBid too low! Minimum bid: {min}"
auction-insufficient-funds: "&cYou don't have enough money. Required: {price}"
auction-buyout: "&aYou bought out the auction for {item} for {price}!"
auction-extended: "&eAuction extended by {seconds}s due to anti-snipe protection."
# Claim Messages
claim-success: "&aItem claimed successfully!"
claim-empty: "&eYou have no items to claim."
claim-inventory-full: "&cYour inventory is full! Please make space."
claim-all-success: "&aClaimed {count} items!"
# Earnings Messages
earnings-withdrawn: "&aWithdrew {amount}! New balance: {balance}"
earnings-empty: "&eYou have no pending earnings."
earnings-balance: "&aYour pending earnings: {amount}"
# Item Validation
invalid-item: "&cPlease select a valid item."
item-no-longer-available: "&cThe selected item is no longer in your inventory."
item-changed: "&cThe selected item has changed. Please select again."
quantity-changed: "&cThe available quantity has changed. Please verify and try again."
blacklisted-item: "&cThis item type is not allowed on the market."
blacklisted-content: "&cThis item contains blacklisted content."
invalid-price: "&cInvalid price. Range: {min} - {max}"
invalid-amount: "&cInvalid amount."
invalid-duration: "&cInvalid duration."
# Admin Messages
admin-listing-removed: "&aListing #{id} removed by admin."
admin-auction-cancelled: "&aAuction #{id} cancelled by admin."
admin-reload: "&aConfiguration reloaded."
# GUI Titles (support color codes)
gui-titles:
main-menu: "&8&lCommunity Market"
browse-market: "&8&lBrowse Market &7(Page {page})"
browse-auctions: "&8&lBrowse Auctions &7(Page {page})"
create-listing: "&8&lCreate Listing"
create-auction: "&8&lCreate Auction"
select-item-listing: "&8&lSelect Item to Sell"
select-item-auction: "&8&lSelect Item to Auction"
quantity-select: "&8&lSelect Quantity"
my-listings: "&8&lMy Listings"
my-auctions: "&8&lMy Auctions"
claim-items: "&8&lClaim Items"
earnings: "&8&lEarnings"
confirm-purchase: "&8&lConfirm Purchase"
confirm-bid: "&8&lConfirm Bid"
confirm-cancel: "&8&lConfirm Cancellation"
number-input: "&8&lEnter Amount"
admin-panel: "&8&lAdmin Panel"
admin-listings: "&8&lAll Listings"
admin-auctions: "&8&lAll Auctions"
listing-details: "&8&lListing Details"
auction-details: "&8&lAuction Details"
filter-menu: "&8&lFilter Options"
sort-menu: "&8&lSort Options"
duration-select: "&8&lSelect Duration"
help: "&8&lHelp"
# Button Names
buttons:
# Main Menu
browse-market: "&aBrowse Market"
browse-auctions: "&6Browse Auctions"
create-listing: "&eCreate Listing"
create-auction: "&eCreate Auction"
my-listings: "&bMy Listings"
my-auctions: "&bMy Auctions"
claim-items: "&dClaim Items"
earnings: "&aEarnings"
help: "&fHelp"
admin: "&cAdmin Panel"
# Navigation
next-page: "&aNext Page →"
previous-page: "&a← Previous Page"
back: "&cBack"
close: "&cClose"
# Actions
confirm: "&aConfirm"
cancel: "&cCancel"
buy: "&aBuy Now"
bid: "&6Place Bid"
buyout: "&eBuyout"
claim: "&aClaim"
claim-all: "&aClaim All"
withdraw: "&aWithdraw All"
remove: "&cRemove Listing"
cancel-auction: "&cCancel Auction"
# Number Input
add-1: "&a+1"
add-10: "&a+10"
add-100: "&a+100"
add-1000: "&a+1,000"
subtract-1: "&c-1"
subtract-10: "&c-10"
subtract-100: "&c-100"
subtract-1000: "&c-1,000"
set-min: "&eSet Min"
set-max: "&eSet Max"
custom-amount: "&bCustom Amount"
# Filters & Sort
filter: "&eFilter"
sort: "&eSort"
search: "&eSearch"
clear-filter: "&cClear Filters"
# Duration
duration-1h: "&e1 Hour"
duration-6h: "&e6 Hours"
duration-12h: "&e12 Hours"
duration-24h: "&e24 Hours"
duration-48h: "&e48 Hours"
duration-72h: "&e3 Days"
duration-168h: "&e7 Days"
duration-336h: "&e14 Days"
# Admin
admin-view-listings: "&aView All Listings"
admin-view-auctions: "&6View All Auctions"
admin-reload: "&eReload Config"
# Button Lore (descriptions)
lore:
browse-market:
- "&7Browse all fixed-price"
- "&7listings from players."
- ""
- "&eClick to browse!"
browse-auctions:
- "&7Browse all active auctions"
- "&7and place bids."
- ""
- "&eClick to browse!"
create-listing:
- "&7Sell items at a fixed price."
- "&7Tax: &f{tax}%"
- ""
- "&eClick to create!"
create-auction:
- "&7Auction items to the"
- "&7highest bidder."
- "&7Tax: &f{tax}%"
- ""
- "&eClick to create!"
my-listings:
- "&7View and manage your"
- "&7active listings."
- ""
- "&7Active: &f{count}/{max}"
- ""
- "&eClick to view!"
my-auctions:
- "&7View and manage your"
- "&7active auctions."
- ""
- "&7Active: &f{count}/{max}"
- ""
- "&eClick to view!"
claim-items:
- "&7Claim items from expired"
- "&7listings or won auctions."
- ""
- "&7Pending: &f{count}"
- ""
- "&eClick to claim!"
earnings:
- "&7View and withdraw your"
- "&7pending earnings from sales."
- ""
- "&7Pending: &a{amount}"
- ""
- "&eClick to view!"
help:
- "&7Learn how to use the"
- "&7Community Market."
- ""
- "&eClick for help!"
admin:
- "&cAdmin Panel"
- "&7Manage listings and auctions."
- ""
- "&eClick to open!"
# Listing Info
listing-info:
- "&7Seller: &f{seller}"
- "&7Price: &a{price}"
- "&7Amount: &f{amount}"
- "&7Expires: &f{expires}"
- ""
- "&eLeft-click to buy!"
# Auction Info
auction-info:
- "&7Seller: &f{seller}"
- "&7Starting bid: &a{start_price}"
- "&7Current bid: &a{current_bid}"
- "&7Bidder: &f{bidder}"
- "&7Bids: &f{bid_count}"
- "&7Ends: &f{ends}"
- ""
- "&eLeft-click to bid!"
- "&eRight-click to buyout!"
# My Listing Info
my-listing-info:
- "&7Price: &a{price}"
- "&7Amount: &f{amount}"
- "&7Created: &f{created}"
- "&7Expires: &f{expires}"
- ""
- "&cClick to cancel"
# My Auction Info
my-auction-info:
- "&7Starting bid: &a{start_price}"
- "&7Current bid: &a{current_bid}"
- "&7Bidder: &f{bidder}"
- "&7Bids: &f{bid_count}"
- "&7Ends: &f{ends}"
- ""
- "&cClick to cancel (if no bids)"
# Confirm Purchase
confirm-purchase-info:
- "&7You are purchasing:"
- "&f{item} x{amount}"
- ""
- "&7Price: &a{price}"
- "&7Tax: &e{tax}"
- "&7Total: &a{total}"
- ""
- "&aClick to confirm!"
# Confirm Bid
confirm-bid-info:
- "&7You are bidding on:"
- "&f{item}"
- ""
- "&7Your bid: &a{bid}"
- "&7Current high: &e{current}"
- ""
- "&aClick to confirm!"
# Claim Item
claim-item-info:
- "&7Reason: &f{reason}"
- "&7From: &f{source}"
- "&7Date: &f{date}"
- ""
- "&eClick to claim!"
# Earnings Info
earnings-info:
- "&7Your pending earnings"
- "&7from market sales."
- ""
- "&7Total: &a{amount}"
- ""
- "&aClick to withdraw!"
# Number Input Info
current-value:
- "&7Current: &a{value}"
# Filter Options
filters:
all: "&fAll Items"
weapons: "&cWeapons"
armor: "&bArmor"
tools: "&eTools"
blocks: "&7Blocks"
food: "&6Food"
potions: "&dPotions"
materials: "&aMaterials"
enchanted: "&5Enchanted Items"
misc: "&8Miscellaneous"
# Sort Options
sort:
newest: "&aNewest First"
oldest: "&eOldest First"
price-low: "&aPrice: Low to High"
price-high: "&cPrice: High to Low"
ending-soon: "&6Ending Soon"
most-bids: "&bMost Bids"
# Time Formats
time:
expired: "&cExpired"
days: "{d}d"
hours: "{h}h"
minutes: "{m}m"
seconds: "{s}s"
# Quantity Selector GUI
quantity-select:
title: "&6&lSelect Quantity"
info-line-1: "&7Choose how many items"
info-line-2: "&7you want to sell."
available: "&7Available: &f{amount}"
selected: "&7Selected: &f{amount}"
quantity-label: "Quantity"
minimum: "&7Minimum: &f{amount}"
maximum: "&7Maximum: &f{amount}"
use-buttons: "&eUse buttons to adjust"
click-adjust: "&7Click: &e{amount}"
set-minimum: "&6Set Minimum"
set-maximum: "&6Set Maximum"
set-to: "&7Set to: &f{amount}"
back-lore: "&7Return to item selection"
confirm-lore: "&7Quantity: &a{amount}"
# Item Selection GUI
item-selection:
info-title: "&fSelect an Item"
info-lore-listing: "&7Click on an item from your|&7inventory to create a &eListing&7."
info-lore-auction: "&7Click on an item from your|&7inventory to create a &6Auction&7."
blacklisted-note: "&7Blacklisted items are shown in red."
click-to-select: "&a► Click to select"
blocked-title: "&c{material}"
blocked-lore-1: "&7This item cannot be listed."
blocked-lore-2: "&cBlacklisted or invalid."
back-lore: "&7Return to main menu"
# Create Listing GUI
create-listing:
info-title: "&6&lCreate Listing"
info-lore-1: "&7Set a price and duration"
info-lore-2: "&7for your listing."
tax-info: "&7Tax: &f{tax}%"
item-lore: "&7Quantity: &f{amount}|&eThis item will be listed"
price-title: "&6Price: {price}"
price-tax: "&7Tax ({percent}%): &c{amount}"
price-earnings: "&7You receive: &a{amount}"
price-click: "&eClick to change price"
duration-title: "&eDuration: {duration}"
duration-lore: "&7Listing expires after this time"
duration-click: "&eClick to change duration"
back-lore: "&7Return to item selection"
confirm-item: "&7Item: &f{item} x{amount}"
confirm-price: "&7Price: &a{price}"
confirm-earnings: "&7You receive: &a{amount}"
confirm-duration: "&7Duration: &e{duration}"
confirm-click: "&aClick to create listing!"
# Create Auction GUI
create-auction:
info-title: "&6&lCreate Auction"
info-lore-1: "&7Set starting price, optional buyout,"
info-lore-2: "&7and duration for your auction."
tax-info: "&7Tax on sale: &f{tax}%"
item-lore: "&7Quantity: &f{amount}|&eThis item will be auctioned"
start-price-title: "&6Starting Price: {price}"
start-price-lore-1: "&7Minimum bid to start"
start-price-lore-2: "&7the auction."
start-price-click: "&eClick to change"
buyout-title-set: "&bBuyout: {price}"
buyout-title-unset: "&bBuyout: &7Not set"
buyout-lore-set-1: "&7Instant purchase price."
buyout-lore-set-2: "&eLeft-click to change"
buyout-lore-set-3: "&cRight-click to remove"
buyout-lore-unset-1: "&7Optional instant purchase"
buyout-lore-unset-2: "&7price for your auction."
buyout-lore-unset-click: "&eClick to set buyout price"
duration-title: "&eDuration: {duration}"
duration-lore: "&7Auction ends after this time."
duration-click: "&eClick to change duration"
back-lore: "&7Return to item selection"
confirm-item: "&7Item: &f{item} x{amount}"
confirm-start: "&7Start: &a{price}"
confirm-buyout: "&7Buyout: &b{price}"
confirm-buyout-none: "&7Buyout: &7None"
confirm-duration: "&7Duration: &e{duration}"
confirm-click: "&aClick to create auction!"
# Number Input GUI
number-input:
display-title: "&6&l{value}"
minimum: "&7Minimum: &f{value}"
maximum: "&7Maximum: &f{value}"
use-buttons: "&eUse buttons to adjust"
click-adjust: "&7Click: &e{amount}"
shift-click: "&7Shift-click: &e{amount}"
set-minimum: "&6Set Minimum"
set-maximum: "&6Set Maximum"
set-to: "&7Set to: &f{value}"
cancel-lore: "&7Cancel and go back"
confirm-lore: "&7Confirm: &a{value}"
# Help Content
help:
title: "&6&lCommunity Market Help"
content:
- "&eBrowse Market &7- View and buy fixed-price listings"
- "&eBrowse Auctions &7- View and bid on auctions"
- "&eCreate Listing &7- Sell items at a fixed price"
- "&eCreate Auction &7- Auction items to highest bidder"
- "&eMy Listings &7- Manage your active listings"
- "&eMy Auctions &7- Manage your active auctions"
- "&eClaim Items &7- Collect unsold/won items"
- "&eEarnings &7- Withdraw money from sales"
- ""
- "&7&oTip: All actions are done through GUIs!"
- "&7&oJust click on buttons to navigate."
-448
View File
@@ -1,448 +0,0 @@
# ============================================
# CommunityMarket Ficheiro de Idioma - Português (Portugal)
# ============================================
# Geral
prefix: "&8[&6Mercado&8] &r"
# Mensagens Gerais
messages:
no-permission: "&cNão tens permissão para fazer isso."
player-only: "&cEste comando só pode ser usado por jogadores."
reload-success: "&aConfiguração recarregada com sucesso!"
economy-not-found: "&cNenhum plugin de economia encontrado! Mercado desativado."
# Mensagens de Anúncios
listing-created: "&aAnúncio criado com sucesso! ID: #{id}"
listing-cancelled: "&aAnúncio cancelado. Item devolvido ao armazém."
listing-expired: "&eO teu anúncio #{id} expirou. Item movido para o armazém."
listing-purchased: "&aCompraste {item} x{amount} por {price}!"
listing-sold: "&aO teu {item} x{amount} foi vendido a {buyer} por {price}!"
listing-limit-reached: "&cAtingiste o número máximo de anúncios ({max})."
listing-cooldown: "&cPor favor aguarda {time} antes de criar outro anúncio."
listing-not-found: "&cAnúncio não encontrado ou já não está disponível."
listing-own-item: "&cNão podes comprar o teu próprio anúncio."
listing-insufficient-funds: "&cNão tens dinheiro suficiente. Necessário: {price}"
# Mensagens de Leilões
auction-created: "&aLeilão criado com sucesso! ID: #{id}"
auction-cancelled: "&aLeilão cancelado. Item devolvido ao armazém."
auction-ended-winner: "&aParabéns! Ganhaste o leilão por {item}! Pagaste: {price}"
auction-ended-seller: "&aO teu leilão por {item} terminou! Vencedor: {winner}, Ganhaste: {price}"
auction-ended-no-bids: "&eO teu leilão por {item} terminou sem licitações. Item movido para o armazém."
auction-limit-reached: "&cAtingiste o número máximo de leilões ({max})."
auction-not-found: "&cLeilão não encontrado ou já não está disponível."
auction-own-item: "&cNão podes licitar no teu próprio leilão."
auction-bid-placed: "&aFizeste uma licitação de {amount} em {item}!"
auction-outbid: "&eForam feitas licitações superiores à tua em {item}! Nova licitação: {amount} por {bidder}"
auction-bid-too-low: "&cLicitação muito baixa! Mínimo: {min}"
auction-insufficient-funds: "&cNão tens dinheiro suficiente. Necessário: {price}"
auction-buyout: "&aCompraste o leilão de {item} por {price}!"
auction-extended: "&eLeilão prolongado por {seconds}s devido à proteção anti-snipe."
# Mensagens de Reclamação
claim-success: "&aItem reclamado com sucesso!"
claim-empty: "&eNão tens itens para reclamar."
claim-inventory-full: "&cO teu inventário está cheio! Por favor liberta espaço."
claim-all-success: "&aReclamaste {count} itens!"
# Mensagens de Ganhos
earnings-withdrawn: "&aLevantaste {amount}! Novo saldo: {balance}"
earnings-empty: "&eNão tens ganhos pendentes."
earnings-balance: "&aOs teus ganhos pendentes: {amount}"
# Validação de Itens
invalid-item: "&cPor favor seleciona um item válido."
item-no-longer-available: "&cO item selecionado já não está no teu inventário."
item-changed: "&cO item selecionado foi alterado. Por favor seleciona novamente."
quantity-changed: "&cA quantidade disponível foi alterada. Por favor verifica e tenta novamente."
blacklisted-item: "&cEste tipo de item não é permitido no mercado."
blacklisted-content: "&cEste item contém conteúdo bloqueado."
invalid-price: "&cPreço inválido. Intervalo: {min} - {max}"
invalid-amount: "&cQuantidade inválida."
invalid-duration: "&cDuração inválida."
# Mensagens de Admin
admin-listing-removed: "&aAnúncio #{id} removido pelo admin."
admin-auction-cancelled: "&aLeilão #{id} cancelado pelo admin."
admin-reload: "&aConfiguração recarregada."
# Títulos GUI (suportam códigos de cor)
gui-titles:
main-menu: "&8&lMercado Comunitário"
browse-market: "&8&lExplorar Mercado &7(Página {page})"
browse-auctions: "&8&lExplorar Leilões &7(Página {page})"
create-listing: "&8&lCriar Anúncio"
create-auction: "&8&lCriar Leilão"
select-item-listing: "&8&lSelecionar Item para Vender"
select-item-auction: "&8&lSelecionar Item para Leilão"
quantity-select: "&8&lSelecionar Quantidade"
my-listings: "&8&lOs Meus Anúncios"
my-auctions: "&8&lOs Meus Leilões"
claim-items: "&8&lReclamar Itens"
earnings: "&8&lGanhos"
confirm-purchase: "&8&lConfirmar Compra"
confirm-bid: "&8&lConfirmar Licitação"
confirm-cancel: "&8&lConfirmar Cancelamento"
number-input: "&8&lIntroduzir Valor"
admin-panel: "&8&lPainel de Admin"
admin-listings: "&8&lTodos os Anúncios"
admin-auctions: "&8&lTodos os Leilões"
listing-details: "&8&lDetalhes do Anúncio"
auction-details: "&8&lDetalhes do Leilão"
filter-menu: "&8&lOpções de Filtro"
sort-menu: "&8&lOpções de Ordenação"
duration-select: "&8&lSelecionar Duração"
help: "&8&lAjuda"
# Nomes dos Botões
buttons:
# Menu Principal
browse-market: "&aExplorar Mercado"
browse-auctions: "&6Explorar Leilões"
create-listing: "&eCriar Anúncio"
create-auction: "&eCriar Leilão"
my-listings: "&bOs Meus Anúncios"
my-auctions: "&bOs Meus Leilões"
claim-items: "&dReclamar Itens"
earnings: "&aGanhos"
help: "&fAjuda"
admin: "&cPainel de Admin"
# Navegação
next-page: "&aPágina Seguinte →"
previous-page: "&a← Página Anterior"
back: "&cVoltar"
close: "&cFechar"
# Ações
confirm: "&aConfirmar"
cancel: "&cCancelar"
buy: "&aComprar Agora"
bid: "&6Fazer Licitação"
buyout: "&eCompra Imediata"
claim: "&aReclamar"
claim-all: "&aReclamar Tudo"
withdraw: "&aLevantar Tudo"
remove: "&cRemover Anúncio"
cancel-auction: "&cCancelar Leilão"
# Entrada Numérica
add-1: "&a+1"
add-10: "&a+10"
add-100: "&a+100"
add-1000: "&a+1.000"
subtract-1: "&c-1"
subtract-10: "&c-10"
subtract-100: "&c-100"
subtract-1000: "&c-1.000"
set-min: "&eDefinir Mín"
set-max: "&eDefinir Máx"
custom-amount: "&bValor Personalizado"
# Filtros e Ordenação
filter: "&eFiltro"
sort: "&eOrdenar"
search: "&ePesquisar"
clear-filter: "&cLimpar Filtros"
# Duração
duration-1h: "&e1 Hora"
duration-6h: "&e6 Horas"
duration-12h: "&e12 Horas"
duration-24h: "&e24 Horas"
duration-48h: "&e48 Horas"
duration-72h: "&e3 Dias"
duration-168h: "&e7 Dias"
duration-336h: "&e14 Dias"
# Admin
admin-view-listings: "&aVer Todos os Anúncios"
admin-view-auctions: "&6Ver Todos os Leilões"
admin-reload: "&eRecarregar Config"
# Lore dos Botões (descrições)
lore:
browse-market:
- "&7Explora todos os anúncios"
- "&7de preço fixo dos jogadores."
- ""
- "&eClica para explorar!"
browse-auctions:
- "&7Explora todos os leilões ativos"
- "&7e faz licitações."
- ""
- "&eClica para explorar!"
create-listing:
- "&7Vende itens a um preço fixo."
- "&7Taxa: &f{tax}%"
- ""
- "&eClica para criar!"
create-auction:
- "&7Leiloa itens ao"
- "&7maior licitador."
- "&7Taxa: &f{tax}%"
- ""
- "&eClica para criar!"
my-listings:
- "&7Vê e gere os teus"
- "&7anúncios ativos."
- ""
- "&7Ativos: &f{count}/{max}"
- ""
- "&eClica para ver!"
my-auctions:
- "&7Vê e gere os teus"
- "&7leilões ativos."
- ""
- "&7Ativos: &f{count}/{max}"
- ""
- "&eClica para ver!"
claim-items:
- "&7Reclama itens de anúncios"
- "&7expirados ou leilões ganhos."
- ""
- "&7Pendentes: &f{count}"
- ""
- "&eClica para reclamar!"
earnings:
- "&7Vê e levanta os teus"
- "&7ganhos pendentes das vendas."
- ""
- "&7Pendente: &a{amount}"
- ""
- "&eClica para ver!"
help:
- "&7Aprende a usar o"
- "&7Mercado Comunitário."
- ""
- "&eClica para ajuda!"
admin:
- "&cPainel de Admin"
- "&7Gere anúncios e leilões."
- ""
- "&eClica para abrir!"
# Info do Anúncio
listing-info:
- "&7Vendedor: &f{seller}"
- "&7Preço: &a{price}"
- "&7Quantidade: &f{amount}"
- "&7Expira: &f{expires}"
- ""
- "&eClique esquerdo para comprar!"
# Info do Leilão
auction-info:
- "&7Vendedor: &f{seller}"
- "&7Licitação inicial: &a{start_price}"
- "&7Licitação atual: &a{current_bid}"
- "&7Licitador: &f{bidder}"
- "&7Licitações: &f{bid_count}"
- "&7Termina: &f{ends}"
- ""
- "&eClique esquerdo para licitar!"
- "&eClique direito para compra imediata!"
# Info do Meu Anúncio
my-listing-info:
- "&7Preço: &a{price}"
- "&7Quantidade: &f{amount}"
- "&7Criado: &f{created}"
- "&7Expira: &f{expires}"
- ""
- "&cClica para cancelar"
# Info do Meu Leilão
my-auction-info:
- "&7Licitação inicial: &a{start_price}"
- "&7Licitação atual: &a{current_bid}"
- "&7Licitador: &f{bidder}"
- "&7Licitações: &f{bid_count}"
- "&7Termina: &f{ends}"
- ""
- "&cClica para cancelar (sem licitações)"
# Confirmar Compra
confirm-purchase-info:
- "&7Estás a comprar:"
- "&f{item} x{amount}"
- ""
- "&7Preço: &a{price}"
- "&7Taxa: &e{tax}"
- "&7Total: &a{total}"
- ""
- "&aClica para confirmar!"
# Confirmar Licitação
confirm-bid-info:
- "&7Estás a licitar em:"
- "&f{item}"
- ""
- "&7A tua licitação: &a{bid}"
- "&7Atual mais alta: &e{current}"
- ""
- "&aClica para confirmar!"
# Reclamar Item
claim-item-info:
- "&7Razão: &f{reason}"
- "&7De: &f{source}"
- "&7Data: &f{date}"
- ""
- "&eClica para reclamar!"
# Info de Ganhos
earnings-info:
- "&7Os teus ganhos pendentes"
- "&7das vendas no mercado."
- ""
- "&7Total: &a{amount}"
- ""
- "&aClica para levantar!"
# Info de Entrada Numérica
current-value:
- "&7Atual: &a{value}"
# Opções de Filtro
filters:
all: "&fTodos os Itens"
weapons: "&cArmas"
armor: "&bArmadura"
tools: "&eFerramentas"
blocks: "&7Blocos"
food: "&6Comida"
potions: "&dPoções"
materials: "&aMateriais"
enchanted: "&5Itens Encantados"
misc: "&8Diversos"
# Opções de Ordenação
sort:
newest: "&aMais Recente"
oldest: "&eMais Antigo"
price-low: "&aPreço: Menor para Maior"
price-high: "&cPreço: Maior para Menor"
ending-soon: "&6A Terminar Em Breve"
most-bids: "&bMais Licitações"
# Formatos de Tempo
time:
expired: "&cExpirado"
days: "{d}d"
hours: "{h}h"
minutes: "{m}m"
seconds: "{s}s"
# GUI de Seleção de Quantidade
quantity-select:
title: "&6&lSelecionar Quantidade"
info-line-1: "&7Escolhe quantos itens"
info-line-2: "&7queres vender."
available: "&7Disponível: &f{amount}"
selected: "&7Selecionado: &f{amount}"
quantity-label: "Quantidade"
minimum: "&7Mínimo: &f{amount}"
maximum: "&7Máximo: &f{amount}"
use-buttons: "&eUsa os botões para ajustar"
click-adjust: "&7Clica: &e{amount}"
set-minimum: "&6Definir Mínimo"
set-maximum: "&6Definir Máximo"
set-to: "&7Definir para: &f{amount}"
back-lore: "&7Voltar à seleção de item"
confirm-lore: "&7Quantidade: &a{amount}"
# GUI de Seleção de Item
item-selection:
info-title: "&fSelecionar um Item"
info-lore-listing: "&7Clica num item do teu|&7inventário para criar um &eAnúncio&7."
info-lore-auction: "&7Clica num item do teu|&7inventário para criar um &6Leilão&7."
blacklisted-note: "&7Itens bloqueados aparecem a vermelho."
click-to-select: "&a► Clica para selecionar"
blocked-title: "&c{material}"
blocked-lore-1: "&7Este item não pode ser listado."
blocked-lore-2: "&cBloqueado ou inválido."
back-lore: "&7Voltar ao menu principal"
# GUI de Criar Anúncio
create-listing:
info-title: "&6&lCriar Anúncio"
info-lore-1: "&7Define um preço e duração"
info-lore-2: "&7para o teu anúncio."
tax-info: "&7Taxa: &f{tax}%"
item-lore: "&7Quantidade: &f{amount}|&eEste item será listado"
price-title: "&6Preço: {price}"
price-tax: "&7Taxa ({percent}%): &c{amount}"
price-earnings: "&7Recebes: &a{amount}"
price-click: "&eClica para alterar preço"
duration-title: "&eDuração: {duration}"
duration-lore: "&7O anúncio expira após este tempo"
duration-click: "&eClica para alterar duração"
back-lore: "&7Voltar à seleção de item"
confirm-item: "&7Item: &f{item} x{amount}"
confirm-price: "&7Preço: &a{price}"
confirm-earnings: "&7Recebes: &a{amount}"
confirm-duration: "&7Duração: &e{duration}"
confirm-click: "&aClica para criar anúncio!"
# GUI de Criar Leilão
create-auction:
info-title: "&6&lCriar Leilão"
info-lore-1: "&7Define preço inicial, compra imediata opcional,"
info-lore-2: "&7e duração para o teu leilão."
tax-info: "&7Taxa na venda: &f{tax}%"
item-lore: "&7Quantidade: &f{amount}|&eEste item será leiloado"
start-price-title: "&6Preço Inicial: {price}"
start-price-lore-1: "&7Licitação mínima para iniciar"
start-price-lore-2: "&7o leilão."
start-price-click: "&eClica para alterar"
buyout-title-set: "&bCompra Imediata: {price}"
buyout-title-unset: "&bCompra Imediata: &7Não definido"
buyout-lore-set-1: "&7Preço de compra instantânea."
buyout-lore-set-2: "&eClique esquerdo para alterar"
buyout-lore-set-3: "&cClique direito para remover"
buyout-lore-unset-1: "&7Preço opcional de compra"
buyout-lore-unset-2: "&7instantânea para o teu leilão."
buyout-lore-unset-click: "&eClica para definir preço de compra imediata"
duration-title: "&eDuração: {duration}"
duration-lore: "&7O leilão termina após este tempo."
duration-click: "&eClica para alterar duração"
back-lore: "&7Voltar à seleção de item"
confirm-item: "&7Item: &f{item} x{amount}"
confirm-start: "&7Início: &a{price}"
confirm-buyout: "&7Compra Imediata: &b{price}"
confirm-buyout-none: "&7Compra Imediata: &7Nenhum"
confirm-duration: "&7Duração: &e{duration}"
confirm-click: "&aClica para criar leilão!"
# GUI de Entrada Numérica
number-input:
display-title: "&6&l{value}"
minimum: "&7Mínimo: &f{value}"
maximum: "&7Máximo: &f{value}"
use-buttons: "&eUsa os botões para ajustar"
click-adjust: "&7Clica: &e{amount}"
shift-click: "&7Shift-clica: &e{amount}"
set-minimum: "&6Definir Mínimo"
set-maximum: "&6Definir Máximo"
set-to: "&7Definir para: &f{value}"
cancel-lore: "&7Cancelar e voltar"
confirm-lore: "&7Confirmar: &a{value}"
# Conteúdo de Ajuda
help:
title: "&6&lAjuda do Mercado Comunitário"
content:
- "&eExplorar Mercado &7- Ver e comprar anúncios de preço fixo"
- "&eExplorar Leilões &7- Ver e licitar em leilões"
- "&eCriar Anúncio &7- Vender itens a um preço fixo"
- "&eCriar Leilão &7- Leiloar itens ao maior licitador"
- "&eOs Meus Anúncios &7- Gerir os teus anúncios ativos"
- "&eOs Meus Leilões &7- Gerir os teus leilões ativos"
- "&eReclamar Itens &7- Recolher itens não vendidos/ganhos"
- "&eGanhos &7- Levantar dinheiro das vendas"
- ""
- "&7&oDica: Todas as ações são feitas através de GUIs!"
- "&7&oBasta clicar nos botões para navegar."
-83
View File
@@ -1,83 +0,0 @@
name: CommunityMarket
version: '1.0.0'
main: pt.henrique.communityMarket.CommunityMarket
api-version: '1.21'
description: A GUI-only marketplace plugin for fixed-price listings and auctions
author: Henrique
website: https://github.com/henrique/CommunityMarket
# Soft dependencies - plugin will detect and use these if available
softdepend:
- Vault
- Essentials
load: POSTWORLD
commands:
market:
description: Opens the Community Market main menu
usage: /<command>
aliases: [cmarket]
permission: communitymarket.use
permissions:
communitymarket.*:
description: Grants all CommunityMarket permissions
default: op
children:
communitymarket.use: true
communitymarket.sell: true
communitymarket.auction: true
communitymarket.buy: true
communitymarket.bid: true
communitymarket.claim: true
communitymarket.withdraw: true
communitymarket.admin: true
communitymarket.use:
description: Allows access to the market GUI
default: true
communitymarket.sell:
description: Allows creating fixed-price listings
default: true
communitymarket.auction:
description: Allows creating auctions
default: true
communitymarket.buy:
description: Allows purchasing from the market
default: true
communitymarket.bid:
description: Allows bidding on auctions
default: true
communitymarket.claim:
description: Allows claiming items from storage
default: true
communitymarket.withdraw:
description: Allows withdrawing earnings
default: true
communitymarket.admin:
description: Allows access to admin functions
default: op
children:
communitymarket.admin.viewall: true
communitymarket.admin.remove: true
communitymarket.admin.reload: true
communitymarket.admin.viewall:
description: Allows viewing all listings/auctions
default: op
communitymarket.admin.remove:
description: Allows removing any listing or auction
default: op
communitymarket.admin.reload:
description: Allows reloading configuration
default: op
Binary file not shown.
-3
View File
@@ -1,3 +0,0 @@
artifactId=communitymarket
groupId=pt.henrique
version=1.0.0
@@ -1,67 +0,0 @@
pt/henrique/communityMarket/economy/EconomyManager.class
pt/henrique/communityMarket/util/TextUtil.class
pt/henrique/communityMarket/config/MessageManager.class
pt/henrique/communityMarket/model/PendingEarnings.class
pt/henrique/communityMarket/gui/AdminGui$AdminListingsGui.class
pt/henrique/communityMarket/model/Auction.class
pt/henrique/communityMarket/listener/PlayerListener.class
pt/henrique/communityMarket/economy/EconomyManager$EconomyAdapter.class
pt/henrique/communityMarket/gui/MarketGui.class
pt/henrique/communityMarket/service/AuctionService.class
pt/henrique/communityMarket/util/ItemSerializer.class
pt/henrique/communityMarket/service/EarningsService$WithdrawResult.class
pt/henrique/communityMarket/gui/MainMenuGui.class
pt/henrique/communityMarket/service/ListingService.class
pt/henrique/communityMarket/gui/ConfirmationGui.class
pt/henrique/communityMarket/gui/HelpGui.class
pt/henrique/communityMarket/db/DatabaseManager.class
pt/henrique/communityMarket/gui/QuantitySelectGui$QuantityCallback.class
pt/henrique/communityMarket/service/TransactionService.class
pt/henrique/communityMarket/task/AuctionTask.class
pt/henrique/communityMarket/model/Bid.class
pt/henrique/communityMarket/service/ClaimService.class
pt/henrique/communityMarket/task/ExpiredListingTask.class
pt/henrique/communityMarket/gui/NumberInputGui$NumberInputCallback.class
pt/henrique/communityMarket/service/ClaimService$ClaimResult.class
pt/henrique/communityMarket/gui/MyAuctionsGui.class
pt/henrique/communityMarket/CommunityMarket.class
pt/henrique/communityMarket/gui/ConfirmationGui$ConfirmCallback.class
pt/henrique/communityMarket/model/ClaimItem$ClaimReason.class
pt/henrique/communityMarket/gui/BrowseMarketGui.class
pt/henrique/communityMarket/model/Auction$AuctionStatus.class
pt/henrique/communityMarket/util/SoundUtil.class
pt/henrique/communityMarket/gui/BrowseMarketGui$1.class
pt/henrique/communityMarket/gui/CreateAuctionGui.class
pt/henrique/communityMarket/gui/QuantitySelectGui.class
pt/henrique/communityMarket/util/InventoryUtil.class
pt/henrique/communityMarket/gui/AdminGui$AdminAuctionsGui.class
pt/henrique/communityMarket/command/MarketCommand.class
pt/henrique/communityMarket/listener/GuiListener$1.class
pt/henrique/communityMarket/service/AuctionService$BidResult.class
pt/henrique/communityMarket/gui/CreateListingGui.class
pt/henrique/communityMarket/model/ClaimItem.class
pt/henrique/communityMarket/gui/ClaimGui$1.class
pt/henrique/communityMarket/util/ItemBuilder.class
pt/henrique/communityMarket/gui/NumberInputGui.class
pt/henrique/communityMarket/gui/AdminGui.class
pt/henrique/communityMarket/gui/BrowseAuctionsGui.class
pt/henrique/communityMarket/gui/ItemSelectionGui$SelectionMode.class
pt/henrique/communityMarket/service/TransactionService$TransactionResult.class
pt/henrique/communityMarket/service/EarningsService.class
pt/henrique/communityMarket/service/TransactionService$ValidationResult.class
pt/henrique/communityMarket/gui/BrowseAuctionsGui$1.class
pt/henrique/communityMarket/model/Listing.class
pt/henrique/communityMarket/service/AuctionService$CancelResult.class
pt/henrique/communityMarket/gui/GuiManager.class
pt/henrique/communityMarket/economy/EconomyManager$VaultAdapter.class
pt/henrique/communityMarket/gui/ClaimGui.class
pt/henrique/communityMarket/economy/EconomyManager$EssentialsAdapter.class
pt/henrique/communityMarket/service/ListingService$PurchaseResult.class
pt/henrique/communityMarket/gui/EarningsGui.class
pt/henrique/communityMarket/config/ConfigManager.class
pt/henrique/communityMarket/gui/MarketGui$GuiType.class
pt/henrique/communityMarket/util/InventoryUtil$ItemCategory.class
pt/henrique/communityMarket/gui/MyListingsGui.class
pt/henrique/communityMarket/gui/ItemSelectionGui.class
pt/henrique/communityMarket/model/Listing$ListingStatus.class
pt/henrique/communityMarket/listener/GuiListener.class
@@ -1,42 +0,0 @@
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/CommunityMarket.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/command/MarketCommand.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/config/ConfigManager.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/config/MessageManager.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/db/DatabaseManager.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/economy/EconomyManager.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/AdminGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/BrowseAuctionsGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/BrowseMarketGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/ClaimGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/ConfirmationGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/CreateAuctionGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/CreateListingGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/EarningsGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/GuiManager.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/HelpGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/ItemSelectionGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/MainMenuGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/MarketGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/MyAuctionsGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/MyListingsGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/NumberInputGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/gui/QuantitySelectGui.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/listener/GuiListener.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/listener/PlayerListener.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/model/Auction.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/model/Bid.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/model/ClaimItem.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/model/Listing.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/model/PendingEarnings.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/service/AuctionService.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/service/ClaimService.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/service/EarningsService.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/service/ListingService.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/service/TransactionService.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/task/AuctionTask.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/task/ExpiredListingTask.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/util/InventoryUtil.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/util/ItemBuilder.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/util/ItemSerializer.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/util/SoundUtil.java
/root/mc-plugins-audit/repos/communitymarket/src/main/java/pt/henrique/communityMarket/util/TextUtil.java
Binary file not shown.