Skip to content
Open
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
18 changes: 17 additions & 1 deletion src/main/java/com/yourorg/servershop/commands/AdminCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.yourorg.servershop.ServerShopPlugin;
import com.yourorg.servershop.importer.ShopImporter;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.*;

import java.io.File;
Expand All @@ -18,6 +19,7 @@ public boolean handle(CommandSender sender, String[] args) {
case "category": return handleCategory(sender, slice(args, 2));
case "import": return handleImport(sender);
case "reload": plugin.reloadConfig(); plugin.catalog().reload(); sender.sendMessage(plugin.prefixed("Reloaded.")); return true;
case "resetprice": return handleResetPrice(sender, slice(args, 2));
default: help(sender); return true;
}
}
Expand Down Expand Up @@ -68,7 +70,21 @@ private boolean handleCategory(CommandSender sender, String[] args) {
helpCategory(sender); return true;
}

private boolean handleResetPrice(CommandSender sender, String[] args) {
if (args.length < 1) { sender.sendMessage(plugin.prefixed("/shop admin resetprice <material|all>")); return true; }
if (args[0].equalsIgnoreCase("all")) {
plugin.dynamic().resetAll();
sender.sendMessage(plugin.prefixed("Reset all prices."));
return true;
}
Material m = Util.parseMaterial(args[0]);
if (m == null) { sender.sendMessage(plugin.prefixed("Unknown material.")); return true; }
plugin.dynamic().reset(m);
sender.sendMessage(plugin.prefixed("Reset price for "+m.name()));
return true;
}

private static String[] slice(String[] a, int from) { String[] b = new String[Math.max(0, a.length-from)]; System.arraycopy(a, from, b, 0, b.length); return b; }
private void help(CommandSender s) { s.sendMessage(plugin.prefixed("/shop admin category <list|setmult|toggle> ... | import | reload")); }
private void help(CommandSender s) { s.sendMessage(plugin.prefixed("/shop admin category <list|setmult|toggle> ... | import | reload | resetprice <mat|all>")); }
private void helpCategory(CommandSender s) { s.sendMessage(plugin.prefixed("/shop admin category list | setmult <cat> <x> | toggle <cat> <on|off>")); }
}
58 changes: 56 additions & 2 deletions src/main/java/com/yourorg/servershop/commands/ShopCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.bukkit.command.*;
import org.bukkit.entity.Player;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

Expand All @@ -25,6 +26,8 @@ public final class ShopCommand implements TabExecutor {
if (args[0].equalsIgnoreCase("search")) return search(sender, args);
if (args[0].equalsIgnoreCase("price")) return price(sender, args);
if (args[0].equalsIgnoreCase("buy")) return buy(sender, args);
if (args[0].equalsIgnoreCase("debug")) return debug(sender, args);
if (args[0].equalsIgnoreCase("snapshot")) return snapshot(sender, args);
sender.sendMessage(plugin.prefixed("Unknown subcommand."));
return true;
}
Expand Down Expand Up @@ -80,13 +83,53 @@ private boolean buy(CommandSender sender, String[] args) {
return true;
}

private boolean debug(CommandSender sender, String[] args) {
if (!sender.hasPermission("servershop.admin")) { sender.sendMessage(plugin.prefixed("No permission.")); return true; }
if (args.length < 2 || !args[1].equalsIgnoreCase("price") || args.length < 3) {
sender.sendMessage(plugin.prefixed("/shop debug price <material>"));
return true;
}
Material mat = Util.parseMaterial(args[2]);
if (mat == null) { sender.sendMessage(plugin.prefixed("Unknown material.")); return true; }
Optional<ItemEntry> opt = plugin.catalog().get(mat);
if (opt.isEmpty() || !opt.get().canBuy()) { sender.sendMessage(plugin.prefixed("Not for sale.")); return true; }
double base = opt.get().buyPrice();
double dyn = plugin.dynamic().multiplier(mat);
double weekly = plugin.weekly().isWeekly(mat) ? plugin.getConfig().getDouble("weekly.discount", 0.80) : 1.0;
String cat = plugin.catalog().categoryOf(mat);
double catMult = plugin.categorySettings().multiplier(cat);
double finalPrice = plugin.shop().priceBuy(mat);
sender.sendMessage(plugin.prefixed(mat.name()+": base "+fmt(base)+" x dyn "+fmt(dyn)+" x weekly "+fmt(weekly)+" x cat "+fmt(catMult)+" = "+fmt(finalPrice)));
return true;
}

private boolean snapshot(CommandSender sender, String[] args) {
if (!sender.hasPermission("servershop.admin")) { sender.sendMessage(plugin.prefixed("No permission.")); return true; }
if (args.length < 2) { sender.sendMessage(plugin.prefixed("/shop snapshot <save|load>")); return true; }
File f = new File(plugin.getDataFolder(), "price-snapshot.yml");
try {
if (args[1].equalsIgnoreCase("save")) {
plugin.dynamic().saveSnapshot(f);
sender.sendMessage(plugin.prefixed("Snapshot saved."));
} else if (args[1].equalsIgnoreCase("load")) {
plugin.dynamic().loadSnapshot(f);
sender.sendMessage(plugin.prefixed("Snapshot loaded."));
} else {
sender.sendMessage(plugin.prefixed("/shop snapshot <save|load>"));
}
} catch (Exception e) {
sender.sendMessage(plugin.prefixed("Snapshot failed: "+e.getMessage()));
}
return true;
}

private String msg(String key) { return plugin.getConfig().getString("messages." + key, key); }

@Override public java.util.List<String> onTabComplete(CommandSender sender, Command cmd, String alias, String[] args) {
java.util.List<String> out = new java.util.ArrayList<>();
if (args.length == 1) { suggest(out, args[0], "price","buy","search","admin"); return out; }
if (args.length == 1) { suggest(out, args[0], "price","buy","search","admin","debug","snapshot"); return out; }
if (args[0].equalsIgnoreCase("admin")) {
if (args.length == 2) { suggest(out, args[1], "category","import","reload"); return out; }
if (args.length == 2) { suggest(out, args[1], "category","import","reload","resetprice"); return out; }
if (args[1].equalsIgnoreCase("category")) {
if (args.length == 3) { suggest(out, args[2], "list","setmult","toggle"); return out; }
if (args[2].equalsIgnoreCase("setmult")) {
Expand All @@ -97,13 +140,22 @@ private boolean buy(CommandSender sender, String[] args) {
if (args.length == 4) { suggestCats(out, args[3]); return out; }
if (args.length == 5) { suggest(out, args[4], "on","off"); return out; }
}
} else if (args[1].equalsIgnoreCase("resetprice")) {
if (args.length == 3) { suggestMats(out, args[2]); suggest(out, args[2], "all"); return out; }
}
return out;
}
if (args[0].equalsIgnoreCase("price") || args[0].equalsIgnoreCase("buy")) {
if (args.length == 2) { suggestMats(out, args[1]); return out; }
if (args[0].equalsIgnoreCase("buy") && args.length == 3) { suggest(out, args[2], "1","16","64"); return out; }
}
if (args[0].equalsIgnoreCase("debug")) {
if (args.length == 2) { suggest(out, args[1], "price"); return out; }
if (args.length == 3 && args[1].equalsIgnoreCase("price")) { suggestMats(out, args[2]); return out; }
}
if (args[0].equalsIgnoreCase("snapshot")) {
if (args.length == 2) { suggest(out, args[1], "save","load"); return out; }
}
if (args[0].equalsIgnoreCase("search")) { return out; }
return out;
}
Expand All @@ -126,4 +178,6 @@ private void suggestMats(java.util.List<String> out, String token) {
if (out.size() >= 50) break;
}
}

private static String fmt(double v) { return String.format("%.2f", v); }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
import com.yourorg.servershop.ServerShopPlugin;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.configuration.file.YamlConfiguration;

import java.io.File;

public final class DynamicPricingManager {
private final ServerShopPlugin plugin;
Expand Down Expand Up @@ -90,6 +93,47 @@ public synchronized void adjustOnSell(Material m, int qty) {
saveLater(m, st);
}

public synchronized double multiplier(Material m) { return currentMultiplier(m); }

public synchronized void reset(Material m) {
PriceState st = new PriceState(initMult, System.currentTimeMillis());
map.put(m, st);
saveLater(m, st);
}

public synchronized void resetAll() {
long now = System.currentTimeMillis();
map.replaceAll((k, v) -> new PriceState(initMult, now));
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
try { storage.saveAll(new java.util.EnumMap<>(map)); } catch (Exception e) { plugin.getLogger().warning("Failed to save prices: "+e.getMessage()); }
});
}

public synchronized void saveSnapshot(File file) throws java.io.IOException {
YamlConfiguration y = new YamlConfiguration();
for (var e : map.entrySet()) {
y.set(e.getKey().name()+".multiplier", e.getValue().multiplier);
y.set(e.getKey().name()+".lastUpdateMs", e.getValue().lastUpdateMs);
}
y.save(file);
}

public synchronized void loadSnapshot(File file) throws java.io.IOException {
map.clear();
YamlConfiguration y = YamlConfiguration.loadConfiguration(file);
long now = System.currentTimeMillis();
for (String k : y.getKeys(false)) {
Material m = Material.matchMaterial(k);
if (m == null) continue;
double mult = y.getDouble(k+".multiplier", initMult);
long last = y.getLong(k+".lastUpdateMs", now);
map.put(m, new PriceState(mult, last));
}
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
try { storage.saveAll(new java.util.EnumMap<>(map)); } catch (Exception e) { plugin.getLogger().warning("Failed to save prices: "+e.getMessage()); }
});
}

private void saveLater(Material m, PriceState st) {
Bukkit.getScheduler().runTaskAsynchronously(plugin, () -> {
try { storage.save(m, st); } catch (Exception e) { plugin.getLogger().warning("Failed to save price: "+e.getMessage()); }
Expand Down
Loading