Version 1.3.0:

* Added per-world disabled trading
* Added per-item disabled trading
This commit is contained in:
PretzelJohn 2021-09-16 01:35:21 -04:00
parent 960fd1c535
commit 589efcbfdb
9 changed files with 75 additions and 29 deletions

View File

@ -63,7 +63,13 @@
</tr>
<tr>
<td><code>DisableTrading:</code></td>
<td>Set this to true if you want to completely disable ALL villager trading.</td>
<td>Whether to disable all villager trading for all worlds, some worlds, or no worlds. Options:
<ul>
<li>Add world names for worlds that you want to completely disable ALL villager trading.</li>
<li>Set to true to disable trading in all worlds.</li>
<li>Set to false or [] to disable this feature.</li>
</ul>
</td>
</tr>
<tr>
<td><code>MaxHeroLevel:</code></td>
@ -106,13 +112,17 @@
<td><code>&lt;item_name&gt;:</code></td>
<td>Override the global settings by adding as many of these as you need. Enchanted books must follow the format of <code>name_level</code> (mending_1). All other items must follow the format of <code>item_name</code> (stone_bricks).</td>
</tr>
<tr>
<td><code>.Disabled:</code></td>
<td>Disables any trade that contains the item (true/false)</td>
</tr>
<tr>
<td><code>.MaxDiscount:</code></td>
<td>Sets the maximum discount for this item</td>
<td>Sets the maximum discount for this item (-1.0, or between 0.0 to 1.0)</td>
</tr>
<tr>
<td><code>.MaxDemand:</code></td>
<td>Sets the maximum demand for this item</td>
<td>Sets the maximum demand for this item (-1, or 0+)</td>
</tr>
</table>
</li>

View File

@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>com.pretzel.dev</groupId>
<artifactId>VillagerTradeLimiter</artifactId>
<version>1.2.1</version>
<version>1.3.0</version>
<properties>
<java.version>1.8</java.version>

View File

@ -54,10 +54,10 @@ public class VillagerTradeLimiter extends JavaPlugin {
//Registers plugin commands
private void registerCommands() {
final String reloaded = Util.replaceColors("&eVillagerTradeLimiter &ahas been reloaded!");
final CommandBase vtl = new CommandBase("villagertradelimiter", "villagertradelimiter.use", p -> this.help(p));
vtl.addSub(new CommandBase("reload", "villagertradelimiter.reload", p -> {
final CommandBase vtl = new CommandBase("villagertradelimiter", "villagertradelimiter.use", (p,args) -> this.help(p));
vtl.addSub(new CommandBase("reload", "villagertradelimiter.reload", (p,args) -> {
loadSettings();
if(p != null) p.sendMessage(reloaded);
Util.sendMsg(reloaded, p);
}));
this.getCommand("villagertradelimiter").setExecutor(vtl);
this.getCommand("villagertradelimiter").setTabCompleter(vtl);

View File

@ -1,5 +1,5 @@
package com.pretzel.dev.villagertradelimiter.lib;
public interface Callback<T> {
void call(T result);
void call(T result, String[] args);
}

View File

@ -1,5 +1,6 @@
package com.pretzel.dev.villagertradelimiter.lib;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@ -32,8 +33,8 @@ public class CommandBase implements CommandExecutor, TabCompleter {
final Player player = (sender instanceof Player ? (Player)sender : null);
if(player != null && !player.hasPermission(this.permission) && !this.permission.isEmpty()) return false;
if(args.length == 0) {
this.callback.call(player);
if(args.length == 0 || (args.length == 1 && subs.size() == 0)) {
this.callback.call(player, args);
return true;
}
@ -54,6 +55,7 @@ public class CommandBase implements CommandExecutor, TabCompleter {
final List<String> list = new ArrayList<>();
if(args.length == 0) return null;
if(args.length == 1) {
if(subs.size() == 0) return getPlayerList();
for(CommandBase cmd : subs)
if(player.hasPermission(cmd.getPermission()))
list.add(cmd.getName());
@ -73,6 +75,13 @@ public class CommandBase implements CommandExecutor, TabCompleter {
return res;
}
private static List<String> getPlayerList() {
final List<String> players = new ArrayList<>();
for(Player p : Bukkit.getOnlinePlayers())
players.add(p.getName());
return players;
}
public String getName() { return this.name; }
public String getPermission() { return this.permission; }
}

View File

@ -29,7 +29,7 @@ public class ConfigUpdater {
}
public FileConfiguration updateConfig(File file, String prefix) {
final FileConfiguration cfg = (FileConfiguration)YamlConfiguration.loadConfiguration(file);
final FileConfiguration cfg = YamlConfiguration.loadConfiguration(file);
if(this.isUpdated()) return cfg;
Util.consoleMsg(prefix+"Updating config.yml...");
@ -49,14 +49,13 @@ public class ConfigUpdater {
}
out += line+"\n";
boolean found = false;
for(int j = 0; j < cfgActive.length; j++) {
String line2 = cfgActive[j];
if(line2.startsWith(" ") && !line2.replace(" ", "").isEmpty()) {
out += line2+"\n";
for(String line2 : cfgActive) {
if (line2.startsWith(" ") && !line2.replace(" ", "").isEmpty()) {
out += line2 + "\n";
found = true;
}
}
if(found == false) {
if(!found) {
while(i < cfgDefault.length-1) {
i++;
String line2 = cfgDefault[i];
@ -68,7 +67,7 @@ public class ConfigUpdater {
}
}
Util.writeFile(file, out+"\n");
return (FileConfiguration)YamlConfiguration.loadConfiguration(file);
return YamlConfiguration.loadConfiguration(file);
}
public boolean isUpdated() {

View File

@ -19,10 +19,11 @@ import org.bukkit.inventory.meta.EnchantmentStorageMeta;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;
import java.util.ArrayList;
import java.util.List;
public class PlayerListener implements Listener {
private static final Material[] MATERIALS = new Material[] { Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, Material.BELL, Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, Material.SHIELD, Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, Material.FILLED_MAP, Material.FISHING_ROD, Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS, Material.LEATHER_HORSE_ARMOR, Material.SADDLE, Material.ENCHANTED_BOOK, Material.STONE_AXE, Material.STONE_SHOVEL, Material.STONE_PICKAXE, Material.STONE_HOE, Material.IRON_AXE, Material.IRON_SHOVEL, Material.IRON_PICKAXE, Material.DIAMOND_AXE, Material.DIAMOND_SHOVEL, Material.DIAMOND_PICKAXE, Material.DIAMOND_HOE, Material.IRON_SWORD, Material.DIAMOND_SWORD };
private static final Material[] MATERIALS = new Material[] { Material.IRON_HELMET, Material.IRON_CHESTPLATE, Material.IRON_LEGGINGS, Material.IRON_BOOTS, Material.BELL, Material.CHAINMAIL_HELMET, Material.CHAINMAIL_CHESTPLATE, Material.CHAINMAIL_LEGGINGS, Material.CHAINMAIL_BOOTS, Material.SHIELD, Material.DIAMOND_HELMET, Material.DIAMOND_CHESTPLATE, Material.DIAMOND_LEGGINGS, Material.DIAMOND_BOOTS, Material.FILLED_MAP, Material.FISHING_ROD, Material.LEATHER_HELMET, Material.LEATHER_CHESTPLATE, Material.LEATHER_LEGGINGS, Material.LEATHER_BOOTS, Material.LEATHER_HORSE_ARMOR, Material.SADDLE, Material.ENCHANTED_BOOK, Material.STONE_AXE, Material.STONE_SHOVEL, Material.STONE_PICKAXE, Material.STONE_HOE, Material.IRON_AXE, Material.IRON_SHOVEL, Material.IRON_PICKAXE, Material.DIAMOND_AXE, Material.DIAMOND_SHOVEL, Material.DIAMOND_PICKAXE, Material.DIAMOND_HOE, Material.IRON_SWORD, Material.DIAMOND_SWORD, Material.NETHERITE_AXE, Material.NETHERITE_HOE, Material.NETHERITE_PICKAXE, Material.NETHERITE_SHOVEL, Material.NETHERITE_SWORD, Material.NETHERITE_HELMET, Material.NETHERITE_CHESTPLATE, Material.NETHERITE_LEGGINGS, Material.NETHERITE_BOOTS };
private final VillagerTradeLimiter instance;
private final NMS nms;
@ -39,10 +40,22 @@ public class PlayerListener implements Listener {
if(Util.isNPC(villager)) return; //Skips NPCs
if(villager.getProfession() == Villager.Profession.NONE || villager.getProfession() == Villager.Profession.NITWIT) return; //Skips non-trading villagers
if(villager.getRecipeCount() == 0) return; //Skips non-trading villagers
//DisableTrading feature
if(instance.getCfg().isBoolean("DisableTrading")) {
if(instance.getCfg().getBoolean("DisableTrading", false)) {
event.setCancelled(true);
return;
}
} else {
List<String> disabledWorlds = instance.getCfg().getStringList("DisableTrading");
for(String world : disabledWorlds) {
if(event.getPlayer().getWorld().getName().equals(world)) {
event.setCancelled(true);
return;
}
}
}
final Player player = event.getPlayer();
if(Util.isNPC(player)) return; //Skips NPCs
@ -51,6 +64,7 @@ public class PlayerListener implements Listener {
this.maxDemand(villager);
}
//Hero of the Village effect limiter feature
private void hotv(final Player player) {
final PotionEffectType effect = PotionEffectType.HERO_OF_THE_VILLAGE;
if(!player.hasPotionEffect(effect)) return; //Skips when player doesn't have HotV
@ -66,6 +80,7 @@ public class PlayerListener implements Listener {
}
}
//MaxDiscount feature - limits the lowest discounted price to a % of the base price
private void maxDiscount(final Villager villager, final Player player) {
final List<MerchantRecipe> recipes = villager.getRecipes();
int a = 0, b = 0, c = 0, d = 0, e = 0;
@ -92,16 +107,20 @@ public class PlayerListener implements Listener {
}
}
final ConfigurationSection overrides = instance.getCfg().getConfigurationSection("Overrides");
final ArrayList<MerchantRecipe> finalRecipes = new ArrayList<>();
for (final MerchantRecipe recipe : recipes) {
final int x = recipe.getIngredients().get(0).getAmount();
final float p0 = this.getPriceMultiplier(recipe);
final int w = 5 * a + b + c - d - 5 * e;
final float y = x - p0 * w;
boolean disabled = false;
double maxDiscount = instance.getCfg().getDouble("MaxDiscount", 0.3);
if(overrides != null) {
for (final String k : overrides.getKeys(false)) {
for(final String k : overrides.getKeys(false)) {
final ConfigurationSection item = this.getItem(recipe, k);
if (item != null) {
if(item != null) {
disabled = item.getBoolean("Disabled", false);
maxDiscount = item.getDouble("MaxDiscount", maxDiscount);
break;
}
@ -116,9 +135,13 @@ public class PlayerListener implements Listener {
} else {
recipe.setPriceMultiplier(p0);
}
if(!disabled) finalRecipes.add(recipe);
}
villager.setRecipes(finalRecipes);
Bukkit.getScheduler().runTaskLater(instance, () -> villager.setRecipes(recipes), 0);
}
//MaxDemand feature - limits demand-based price increases
private void maxDemand(final Villager villager) {
List<MerchantRecipe> recipes = villager.getRecipes();
final NBTContainer vnbt = new NBTContainer(this.nms, villager);
@ -147,6 +170,7 @@ public class PlayerListener implements Listener {
vnbt.saveTag(villager, vtag);
}
//Returns the price multiplier for a given trade
private float getPriceMultiplier(final MerchantRecipe recipe) {
float p = 0.05f;
final Material type = recipe.getResult().getType();
@ -159,6 +183,7 @@ public class PlayerListener implements Listener {
return p;
}
//Returns the configured settings for a trade
private ConfigurationSection getItem(final MerchantRecipe recipe, final String k) {
final ConfigurationSection item = instance.getCfg().getConfigurationSection("Overrides."+k);
if(item == null) return null;
@ -176,6 +201,7 @@ public class PlayerListener implements Listener {
if(recipe.getResult().getType() != Material.ENCHANTED_BOOK) return null;
final EnchantmentStorageMeta meta = (EnchantmentStorageMeta)recipe.getResult().getItemMeta();
final Enchantment enchantment = EnchantmentWrapper.getByKey(NamespacedKey.minecraft(k.substring(0, k.lastIndexOf("_"))));
if(meta == null || enchantment == null) return null;
if(meta.hasStoredEnchant(enchantment) && meta.getStoredEnchantLevel(enchantment) == level) return item;
return null;
} catch(NumberFormatException e) {

View File

@ -1,6 +1,6 @@
#---------------------------------------------------------------------------------#
# VTL ~ VillagerTradeLimiter #
# Version: 1.2.1 #
# Version: 1.3.0 #
# By: PretzelJohn #
#---------------------------------------------------------------------------------#
@ -9,8 +9,10 @@
# This helps me keep track of what server versions are being used. Please leave this set to true.
bStats: true
# Set this to true if you want to completely disable ALL villager trading.
DisableTrading: false
# Add world names for worlds that you want to completely disable ALL villager trading. Set to [] to disable this feature.
DisableTrading:
- world_nether
- world_the_end
# The maximum level of the "Hero of the Village" (HotV) effect that a player can have. This limits HotV price decreases.
# * Set to -1 to disable this feature and keep vanilla behavior.
@ -34,7 +36,7 @@ MaxDemand: -1
# To enable, add items below!
# * Enchanted books must follow the format: enchantment_name_level (ex: mending_1)
# * All other items must follow the format: item_name (ex: stone_bricks)
# For each item you add, you can override MaxDiscount and/or MaxDemand.
# For each item you add, you can disable the trade (set Disabled: true), or override MaxDiscount and/or MaxDemand.
Overrides:
mending_1:
MaxDiscount: 0.1
@ -47,4 +49,4 @@ Overrides:
clock:
MaxDemand: 12
paper:
MaxDiscount: 0.1
Disabled: true

View File

@ -1,7 +1,7 @@
name: VillagerTradeLimiter
author: PretzelJohn
main: com.pretzel.dev.villagertradelimiter.VillagerTradeLimiter
version: 1.2.1
version: 1.3.0
api-version: 1.14
commands: