Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions src/main/java/com/yourname/sellplugin/SellPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import com.yourname.sellplugin.listener.WorthPacketListener;
import com.yourname.sellplugin.listener.WorthRefreshListener;
import com.yourname.sellplugin.manager.ConfigManager;
import com.yourname.sellplugin.manager.DailyBonusManager;
import com.yourname.sellplugin.manager.ConfigMigrator;
import com.yourname.sellplugin.manager.MultiplierManager;
import com.yourname.sellplugin.manager.PriceManager;
import com.yourname.sellplugin.manager.SellManager;
Expand All @@ -25,21 +25,20 @@ public class SellPlugin extends JavaPlugin {
private ConfigManager configManager;
private PriceManager priceManager;
private MultiplierManager multiplierManager;
private DailyBonusManager dailyBonusManager;
private SellManager sellManager;
private WorthVisibilityManager worthVisibilityManager;
private WorthPacketListener worthPacketListener;

@Override
public void onEnable() {
saveDefaultConfig();
new ConfigMigrator(this).migrate();
configManager = new ConfigManager(this);

priceManager = new PriceManager(this);
priceManager.loadPrices();

multiplierManager = new MultiplierManager(this);
dailyBonusManager = new DailyBonusManager(this);
sellManager = new SellManager(this);
worthVisibilityManager = new WorthVisibilityManager(this);

Expand Down Expand Up @@ -86,7 +85,6 @@ public void onDisable() {
public ConfigManager getConfigManager() { return configManager; }
public PriceManager getPriceManager() { return priceManager; }
public MultiplierManager getMultiplierManager() { return multiplierManager; }
public DailyBonusManager getDailyBonusManager() { return dailyBonusManager; }
public SellManager getSellManager() { return sellManager; }
public WorthVisibilityManager getWorthVisibilityManager() { return worthVisibilityManager; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
return true;
}

if (!plugin.getConfigManager().isProgressGuiEnabled()) {
player.sendMessage(plugin.getConfigManager().getText("feature-disabled", "&cThis feature is currently disabled."));
return true;
}

if (!player.hasPermission("sellplugin.use")) {
player.sendMessage(plugin.getConfigManager().getMessage("no-permission"));
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ public boolean onCommand(CommandSender sender, Command command, String label, St
return true;
}

if (!plugin.getConfigManager().isTopSellEnabled()) {
player.sendMessage(plugin.getConfigManager().getText("feature-disabled", "&cThis feature is currently disabled."));
return true;
}

if (!player.hasPermission("sellplugin.topsell")) {
player.sendMessage(plugin.getConfigManager().getMessage("no-permission"));
return true;
Expand Down
17 changes: 5 additions & 12 deletions src/main/java/com/yourname/sellplugin/gui/CategoryItemsGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,6 @@ private ItemStack buildItemDisplay(String itemKey) {
PriceManager pm = plugin.getPriceManager();
double base = pm.getPrice(itemKey);
String itemCategory = pm.getCategory(itemKey);
double earned = plugin.getMultiplierManager().getMultiplier(player, itemCategory);
double daily = plugin.getDailyBonusManager().getDailyBonus(itemCategory);
double effectiveMultiplier = plugin.getMultiplierManager().getEffectiveMultiplier(player, itemCategory);
double effective = base * effectiveMultiplier;

Expand All @@ -178,14 +176,8 @@ private ItemStack buildItemDisplay(String itemKey) {
lore.add(ChatColor.DARK_GRAY + "━━━━━━━━━━━━━━━━━━━━━");
lore.add(ChatColor.GRAY + " ▸ " + ChatColor.WHITE + "Base: "
+ ChatColor.GREEN + "$" + NumberFormatter.format(base));
if (daily > 0) {
lore.add(ChatColor.GRAY + " ▸ " + ChatColor.WHITE + "Mult: "
+ ChatColor.AQUA + String.format("%.2fx", earned)
+ ChatColor.GOLD + " (+" + String.format("%.2fx", daily) + " today)");
} else {
lore.add(ChatColor.GRAY + " ▸ " + ChatColor.WHITE + "Mult: "
+ ChatColor.AQUA + String.format("%.2fx", effectiveMultiplier));
}
lore.add(ChatColor.GRAY + " ▸ " + ChatColor.WHITE + "Mult: "
+ ChatColor.AQUA + String.format("%.2fx", effectiveMultiplier));
lore.add(ChatColor.GRAY + " ▸ " + ChatColor.WHITE + "Price: "
+ ChatColor.GREEN + "$" + NumberFormatter.format(effective));
lore.add(ChatColor.DARK_GRAY + "━━━━━━━━━━━━━━━━━━━━━");
Expand All @@ -210,7 +202,7 @@ private ItemStack resolveItemStack(String itemKey) {
if (itemKey.contains(":")) {
String[] parts = itemKey.split(":", 2);
Material mat = Material.matchMaterial(parts[0]);
if (mat == null) return new ItemStack(Material.BARRIER);
if (mat == null || mat.isAir() || !mat.isItem()) return new ItemStack(Material.BARRIER);

ItemStack item = new ItemStack(mat);
ItemMeta meta = item.getItemMeta();
Expand All @@ -226,7 +218,8 @@ private ItemStack resolveItemStack(String itemKey) {
return item;
}
Material mat = Material.matchMaterial(itemKey);
return new ItemStack(mat != null ? mat : Material.BARRIER);
if (mat == null || mat.isAir() || !mat.isItem()) return new ItemStack(Material.BARRIER);
return new ItemStack(mat);
}

// ── Item clicked ─────────────────────────────────────────────────────────
Expand Down
17 changes: 0 additions & 17 deletions src/main/java/com/yourname/sellplugin/gui/CategoryProgressGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,25 +112,8 @@ private void populate() {
// ── Snake path ──────────────────────────────────────────────────────
double mult = plugin.getMultiplierManager().getMultiplier(player, categoryId);
double moneyEarned = plugin.getMultiplierManager().getMoneyEarned(player, categoryId);
double dailyBonus = plugin.getDailyBonusManager().getDailyBonus(categoryId);
buildSnakePath(mult, moneyEarned);

// ── Daily bonus indicator (slot 4, top centre) ─────────────────────
if (dailyBonus > 0) {
String separator = cfg.getText("lore-separator", "&8━━━━━━━━━━━━━━━━━━━");
List<String> boostLore = new ArrayList<>();
boostLore.add(separator);
boostLore.add(ChatColor.GRAY + " ▸ " + SmallCaps.convert(cfg.getText("category-progress.daily-boost-bonus-label", "bonus: "))
+ ChatColor.YELLOW + "+" + String.format("%.2f", dailyBonus) + "x");
boostLore.add(ChatColor.GRAY + " ▸ " + SmallCaps.convert(cfg.getText("category-progress.daily-boost-effective-label", "effective: "))
+ ChatColor.GREEN + String.format("%.2fx", mult + dailyBonus));
boostLore.add(separator);
boostLore.add(ChatColor.GRAY + SmallCaps.convert(cfg.getText("category-progress.daily-boost-resets", "resets at midnight.")));
inv.setItem(4, makeItem(Material.BLAZE_POWDER,
SmallCaps.convert(cfg.getText("category-progress.daily-boost-title", "&6&l\uD83D\uDD25 Daily Boost Active!")),
boostLore));
}

// ── Back button (bottom-right) ──────────────────────────────────────
List<String> backLore = cfg.getIconLore("back",
Collections.singletonList(ChatColor.GRAY + " ▸ " + SmallCaps.convert(cfg.getText("category-progress.back-lore", "return to the main menu."))));
Expand Down
17 changes: 13 additions & 4 deletions src/main/java/com/yourname/sellplugin/gui/GUIListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,18 @@ public void onDrag(InventoryDragEvent e) {

// ShopMainGUI: allow drags in the item-placement area (0-44),
// cancel if any slot touches the protected bottom row (45-53).
if (holder instanceof ShopMainGUI) {
if (holder instanceof ShopMainGUI shopGUI) {
for (int slot : e.getRawSlots()) {
if (slot >= ShopMainGUI.BOTTOM_ROW_START && slot <= 53) {
e.setCancelled(true);
return;
}
}
// Allow the drag, then refresh the sell button so the value updates.
Player dragger = (e.getWhoClicked() instanceof Player p) ? p : null;
if (dragger != null) {
Scheduler.runEntityLater(plugin, dragger, shopGUI::refreshSellButton, 1L);
}
return; // allow the drag
}

Expand Down Expand Up @@ -71,8 +76,12 @@ public void onClick(InventoryClickEvent e) {
if (holder instanceof ShopMainGUI shopGUI) {
Inventory clicked = e.getClickedInventory();

// Click in player inventory (bottom) – allow freely
// Click in player inventory (bottom) – allow freely, but a
// shift-click / number-key / move-to-other-inventory action can push
// an item up into the shop area without the top inventory being the
// clicked one. Schedule a sell-button refresh so the value updates.
if (clicked != null && clicked.equals(player.getInventory())) {
Scheduler.runEntityLater(plugin, player, shopGUI::refreshSellButton, 1L);
return;
}

Expand Down Expand Up @@ -318,7 +327,7 @@ private void sellGuiItems(Player player, ShopMainGUI shopGUI) {
String cat = pl.getPriceManager().getCategory(key);
double mult = pl.getMultiplierManager().getEffectiveMultiplier(player, cat);
int amount = item.getAmount();
double earned = base * mult * amount;
double earned = pl.getSellManager().enchantedUnitPrice(item, base) * mult * amount;
totalEarned += earned;
totalItems += amount;
categoryEarnings.merge(cat, earned, Double::sum);
Expand Down Expand Up @@ -392,7 +401,7 @@ public void onClose(InventoryCloseEvent e) {
String cat = pl.getPriceManager().getCategory(key);
double mult = pl.getMultiplierManager().getEffectiveMultiplier(player, cat);
int amount = item.getAmount();
double earned = base * mult * amount;
double earned = pl.getSellManager().enchantedUnitPrice(item, base) * mult * amount;
totalEarned += earned;
totalItems += amount;
categoryEarnings.merge(cat, earned, Double::sum);
Expand Down
6 changes: 1 addition & 5 deletions src/main/java/com/yourname/sellplugin/gui/SellAllGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,8 @@ private void populate(Player player) {
if (raw.contains("{multipliers}")) {
for (String cat : categories) {
double m = plugin.getMultiplierManager().getEffectiveMultiplier(player, cat);
double daily = plugin.getDailyBonusManager().getDailyBonus(cat);
String suffix = daily > 0
? ChatColor.GOLD + " (\uD83D\uDD25 +" + String.format("%.2f", daily) + "x)"
: "";
lore.add(ChatColor.translateAlternateColorCodes('&',
"&e \u25b6 &f" + cat + ": &a" + NumberFormatter.format(m) + "x" + suffix));
"&e \u25b6 &f" + cat + ": &a" + NumberFormatter.format(m) + "x"));
}
} else {
lore.add(ChatColor.translateAlternateColorCodes('&', raw));
Expand Down
7 changes: 1 addition & 6 deletions src/main/java/com/yourname/sellplugin/gui/SellMultiGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,14 @@ private ItemStack buildMultiplierIcon(String catId) {
ConfigManager cfg = plugin.getConfigManager();

double multiplier = plugin.getMultiplierManager().getMultiplier(player, catId);
double dailyBonus = plugin.getDailyBonusManager().getDailyBonus(catId);
double effective = multiplier + dailyBonus;
double effective = multiplier;

String separator = cfg.getText("lore-separator", "&8━━━━━━━━━━━━━━━━━━━");

List<String> lore = new ArrayList<>();
lore.add(separator);
lore.add(ChatColor.GRAY + " ▸ " + SmallCaps.convert(cfg.getText("sellmulti.earned-label", "earned: "))
+ ChatColor.AQUA + String.format("%.2fx", multiplier));
if (dailyBonus > 0) {
lore.add(ChatColor.GOLD + " ▸ \uD83D\uDD25 " + SmallCaps.convert(cfg.getText("sellmulti.daily-boost-label", "daily boost: "))
+ ChatColor.YELLOW + "+" + String.format("%.2f", dailyBonus) + "x");
}
lore.add(ChatColor.GRAY + " ▸ " + SmallCaps.convert(cfg.getText("sellmulti.effective-label", "effective: "))
+ ChatColor.GREEN + String.format("%.2fx", effective));
lore.add(separator);
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/com/yourname/sellplugin/gui/WorthGUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ private ItemStack resolveItemStack(String itemKey) {
if (itemKey.contains(":")) {
String[] parts = itemKey.split(":", 2);
Material mat = Material.matchMaterial(parts[0]);
if (mat == null) return new ItemStack(Material.BARRIER);
if (mat == null || mat.isAir() || !mat.isItem()) return new ItemStack(Material.BARRIER);

ItemStack item = new ItemStack(mat);
ItemMeta meta = item.getItemMeta();
Expand All @@ -224,7 +224,8 @@ private ItemStack resolveItemStack(String itemKey) {
return item;
}
Material mat = Material.matchMaterial(itemKey);
return new ItemStack(mat != null ? mat : Material.BARRIER);
if (mat == null || mat.isAir() || !mat.isItem()) return new ItemStack(Material.BARRIER);
return new ItemStack(mat);
}

/** Cycle to the next filter category. */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.yourname.sellplugin.gui.ShopMainGUI;
import com.yourname.sellplugin.gui.TopSellGUI;
import com.yourname.sellplugin.util.NumberFormatter;
import org.bukkit.GameMode;
import org.bukkit.block.DoubleChest;
import org.bukkit.entity.Player;
import org.bukkit.event.inventory.InventoryType;
Expand Down Expand Up @@ -61,14 +62,44 @@ public void register() {
public void onPacketSending(PacketEvent event) {
Player viewer = event.getPlayer();
if (viewer == null) return;
if (!WorthPacketListener.this.plugin.getWorthVisibilityManager()
.isVisible(viewer.getUniqueId())) return;
if (!shouldDecorate(viewer)) return;
if (!worthAllowedFor(viewer)) return;

Inventory top = viewer.getOpenInventory().getTopInventory();
InventoryHolder holder = top.getHolder();
boolean pluginGui = isPluginGui(holder);
int topSize = top.getSize();

// Window id: 0 = the player's own inventory, negative = cursor /
// direct player-slot set, positive = an open container window.
int windowId = 0;
boolean windowKnown = false;
try {
windowId = event.getPacket().getIntegers().read(0);
windowKnown = true;
} catch (Exception ignored) {}
boolean ownInventory = windowKnown && windowId <= 0;

if (event.getPacketType() == PacketType.Play.Server.SET_SLOT) {
if (event.getPacket().getItemModifier().size() <= 0) return;

boolean decorate;
if (ownInventory) {
// Player's own inventory / cursor item: always follow it,
// even while a custom GUI is open, so a held item keeps its
// worth line.
decorate = true;
} else if (pluginGui) {
// Only the mirrored player-inventory portion of a plugin
// GUI gets decorated; the GUI's own slots never do.
int slot = readSetSlotIndex(event);
decorate = slot >= topSize;
} else {
decorate = shouldDecorate(viewer);
}
if (!decorate) return;

ItemStack item = event.getPacket().getItemModifier().read(0);
ItemStack updated = addWorthLore(event.getPlayer(), item);
ItemStack updated = addWorthLore(viewer, item);
if (updated != item) {
event.getPacket().getItemModifier().write(0, updated);
}
Expand All @@ -79,12 +110,30 @@ public void onPacketSending(PacketEvent event) {
List<ItemStack> items = event.getPacket().getItemListModifier().read(0);
if (items == null || items.isEmpty()) return;

// Index of the first slot in this packet that belongs to the
// player's own inventory (everything from here on is decorated).
int playerStart;
if (ownInventory) {
playerStart = 0;
} else if (pluginGui) {
playerStart = topSize;
} else if (shouldDecorate(viewer)) {
playerStart = 0;
} else {
return;
}

boolean changed = false;
List<ItemStack> updatedItems = new ArrayList<>(items.size());
for (ItemStack item : items) {
ItemStack updated = addWorthLore(event.getPlayer(), item);
updatedItems.add(updated);
changed |= updated != item;
for (int i = 0; i < items.size(); i++) {
ItemStack item = items.get(i);
if (i >= playerStart) {
ItemStack updated = addWorthLore(viewer, item);
updatedItems.add(updated);
changed |= updated != item;
} else {
updatedItems.add(item);
}
}

if (changed) {
Expand Down Expand Up @@ -225,6 +274,36 @@ private boolean isBlank(String line) {
return true;
}

/**
* Whether the worth line may be injected for this viewer at all. Respects the
* per-player visibility toggle and hides the line from creative-mode players
* (whose clients echo lore back to the server, baking it into real items)
* unless explicitly enabled via {@code worth.show-in-creative}.
*/
private boolean worthAllowedFor(Player viewer) {
if (!plugin.getConfigManager().isWorthEnabled()) return false;
if (!plugin.getWorthVisibilityManager().isVisible(viewer.getUniqueId())) return false;
if (viewer.getGameMode() == GameMode.CREATIVE
&& !plugin.getConfigManager().isWorthShownInCreative()) return false;
return true;
}

/** Reads the slot index from a SET_SLOT packet, or -1 if it can't be read. */
private int readSetSlotIndex(PacketEvent event) {
try {
if (event.getPacket().getShorts().size() > 0) {
return event.getPacket().getShorts().read(0);
}
} catch (Exception ignored) {}
try {
// Some mappings expose the slot as the 3rd integer (windowId, stateId, slot).
if (event.getPacket().getIntegers().size() > 2) {
return event.getPacket().getIntegers().read(2);
}
} catch (Exception ignored) {}
return -1;
}

private boolean shouldDecorate(Player player) {
Inventory topInventory = player.getOpenInventory().getTopInventory();
InventoryHolder holder = topInventory.getHolder();
Expand Down
Loading
Loading