127 lines
5.8 KiB
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; }
|
|
}
|