VillagerTradeLimiter/src/com/pretzel/dev/villagertradelimiter/data/CustomRecipe.java

127 lines
5.8 KiB
Java

package com.pretzel.dev.villagertradelimiter.data;
import com.pretzel.dev.villagertradelimiter.VillagerTradeLimiter;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Villager;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.MerchantRecipe;
import java.time.Instant;
import java.util.Date;
public class CustomRecipe {
private final VillagerTradeLimiter instance;
private final OfflinePlayer player;
private final MerchantRecipe original;
private final MerchantRecipe adjusted;
private final String type;
public CustomRecipe(final VillagerTradeLimiter instance, final OfflinePlayer player, final Villager villager, final MerchantRecipe original) {
this.instance = instance;
this.player = player;
this.original = original;
this.type = instance.getGroupManager().getType(player, original);
ItemStack item1 = instance.getGroupManager().getItem1(player, type);
ItemStack item2 = instance.getGroupManager().getItem2(player, type);
ItemStack result = instance.getGroupManager().getResult(player, type);
this.adjusted = new MerchantRecipe(result == null ? original.getResult() : result, original.getUses(), original.getMaxUses(), original.hasExperienceReward(), original.getVillagerExperience(), getPriceMultiplier(), getDemand(), original.getSpecialPrice());
this.adjusted.setMaxUses(getMaxUses(villager));
this.adjusted.addIngredient(item1 == null ? original.getIngredients().get(0) : item1);
this.adjusted.addIngredient(item2 == null ? original.getIngredients().get(1) : item2);
}
/**
* @param villager The villager
* @return The current maximum number of times a player can make a trade before the villager restocks
*/
private int getMaxUses(final Villager villager) {
int maxUses = instance.getGroupManager().getMaxUses(player, type);
boolean disabled = instance.getGroupManager().getDisabled(player, type);
//Disables the trade if the player has an active cooldown for the trade
final PlayerData playerData = instance.getPlayerData().get(player.getUniqueId());
final PlayerData villagerData = instance.getPlayerData().get(villager.getUniqueId());
if(playerData != null && type != null) {
if(isOnCooldown(playerData, instance.getGroupManager().getCooldown(player, type))) disabled = true;
if(isOnCooldown(villagerData, instance.getSettings().getRestock())) disabled = true;
}
if(maxUses < 0) maxUses = original.getMaxUses();
if(original.getUses() >= maxUses) disabled = true;
if(disabled) maxUses = 0;
return maxUses;
}
private boolean isOnCooldown(final PlayerData data, final String cooldownStr) {
if(cooldownStr.startsWith("0")) return false;
if(!data.getTradingCooldowns().containsKey(type)) return false;
final Date now = Date.from(Instant.now());
final Date lastTrade = Cooldown.parseTime(data.getTradingCooldowns().get(type));
long cooldown = Cooldown.parseCooldown(cooldownStr);
if(lastTrade != null && (now.getTime() >= lastTrade.getTime() + cooldown*1000L)) {
data.getTradingCooldowns().remove(type);
adjusted.setUses(0);
return false;
}
return true;
}
/** @return The current value of the price multiplier for the given recipe */
private float getPriceMultiplier() {
float priceMultiplier = (float)instance.getGroupManager().getPriceMultiplier(player, type);
if(priceMultiplier < 0) return original.getPriceMultiplier();
return priceMultiplier;
}
/** @return The current value of the demand for the given recipe */
private int getDemand() {
int maxDemand = instance.getGroupManager().getMaxDemand(player, type);
if(maxDemand < 0) return original.getDemand();
return Math.min(original.getDemand(), maxDemand);
}
/** @return The initial price of a recipe/trade, before any discounts are applied */
private int getBasePrice() {
ItemStack item = instance.getGroupManager().getItem1(player, type);
if(item == null) return original.getIngredients().get(0).getAmount();
return Math.min(Math.max(item.getAmount(), 1), item.getMaxStackSize());
}
/**
* @param totalReputation The total reputation for the player and villager
* @param hotvDiscount The total discount from the Hero of the Village effect
* @return The total discount for the recipe, which is added to the base price to get the final price
*/
public int getDiscount(int totalReputation, double hotvDiscount) {
//Calculates the total discount
int basePrice = getBasePrice();
int demand = getDemand();
double priceMultiplier = getPriceMultiplier();
int discount = -(int)(totalReputation * priceMultiplier) - (int)(hotvDiscount * basePrice) + Math.max(0, (int)(demand * priceMultiplier * basePrice));
double maxDiscount = instance.getGroupManager().getMaxDiscount(player, type);
if(maxDiscount >= 0.0 && maxDiscount <= 1.0) {
//Change the discount to the smaller MaxDiscount
if(basePrice + discount < basePrice * (1.0 - maxDiscount)) {
discount = -(int)(basePrice * maxDiscount);
}
} else if(maxDiscount > 1.0) {
//Change the discount to the larger MaxDiscount (increases discount 100%)
//TODO: Allow for better fine-tuning
discount = (int)(discount * maxDiscount);
}
return discount;
}
public void reset() {
original.setDemand(adjusted.getDemand());
original.setUses(adjusted.getUses());
}
public MerchantRecipe getOriginal() { return this.original; }
public MerchantRecipe getAdjusted() { return this.adjusted; }
}