flan/common/src/main/java/io/github/flemmli97/flan/config/BuySellHandler.java
2023-05-06 15:58:42 +02:00

219 lines
9.1 KiB
Java

package io.github.flemmli97.flan.config;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import io.github.flemmli97.flan.claim.PermHelper;
import io.github.flemmli97.flan.platform.integration.currency.CommandCurrency;
import io.github.flemmli97.flan.player.PlayerClaimData;
import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.Ingredient;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class BuySellHandler {
private static int[] xpCalc;
private Type buyType = Type.MONEY;
private Type sellType = Type.MONEY;
private float buyAmount = -1;
private float sellAmount = -1;
private Ingredient ingredient = Ingredient.EMPTY;
public boolean buy(ServerPlayer player, int blocks, Consumer<Component> message) {
if (this.buyAmount == -1) {
message.accept(PermHelper.simpleColoredText(ConfigHandler.langManager.get("buyDisabled"), ChatFormatting.DARK_RED));
return false;
}
PlayerClaimData data = PlayerClaimData.get(player);
if (ConfigHandler.config.maxBuyBlocks >= 0 && data.getAdditionalClaims() + blocks > ConfigHandler.config.maxBuyBlocks) {
message.accept(PermHelper.simpleColoredText(ConfigHandler.langManager.get("buyLimit"), ChatFormatting.DARK_RED));
return false;
}
switch (this.buyType) {
case MONEY -> {
return CommandCurrency.INSTANCE.buyClaimBlocks(player, blocks, this.buyAmount, message);
}
case ITEM -> {
int deduct = Mth.ceil(blocks * this.buyAmount);
List<ItemStack> matching = new ArrayList<>();
int i = 0;
for (ItemStack stack : player.getInventory().items) {
if (this.ingredient.test(stack)) {
if (stack.isDamageableItem()) {
if (stack.getDamageValue() != 0) {
continue;
}
}
//Ignore "special" items
if (!this.isJustRenamedItem(stack)) {
continue;
}
matching.add(stack);
i += stack.getCount();
}
}
if (i < deduct) {
message.accept(PermHelper.simpleColoredText(ConfigHandler.langManager.get("buyFailItem"), ChatFormatting.DARK_RED));
return false;
}
i = deduct;
for (ItemStack stack : matching) {
if (i > stack.getCount()) {
int count = stack.getCount();
stack.setCount(0);
i -= count;
} else {
stack.shrink(i);
break;
}
}
data.setAdditionalClaims(data.getAdditionalClaims() + blocks);
message.accept(PermHelper.simpleColoredText(String.format(ConfigHandler.langManager.get("buySuccessItem"), blocks, deduct)));
return true;
}
case XP -> {
int deduct = Mth.ceil(blocks * this.buyAmount);
if (deduct < totalXpPointsForLevel(player.experienceLevel) + player.experienceProgress * xpForLevel(player.experienceLevel + 1)) {
player.giveExperiencePoints(-deduct);
data.setAdditionalClaims(data.getAdditionalClaims() + blocks);
message.accept(PermHelper.simpleColoredText(String.format(ConfigHandler.langManager.get("buySuccessXP"), blocks, deduct)));
return true;
}
message.accept(PermHelper.simpleColoredText(ConfigHandler.langManager.get("buyFailXP"), ChatFormatting.DARK_RED));
return false;
}
}
return false;
}
public boolean sell(ServerPlayer player, int blocks, Consumer<Component> message) {
if (this.sellAmount == -1) {
message.accept(PermHelper.simpleColoredText(ConfigHandler.langManager.get("sellDisabled"), ChatFormatting.DARK_RED));
return false;
}
PlayerClaimData data = PlayerClaimData.get(player);
if (data.getAdditionalClaims() - Math.max(0, data.usedClaimBlocks() - data.getClaimBlocks()) < blocks) {
message.accept(PermHelper.simpleColoredText(ConfigHandler.langManager.get("sellFail"), ChatFormatting.DARK_RED));
return false;
}
switch (this.sellType) {
case MONEY -> {
return CommandCurrency.INSTANCE.sellClaimBlocks(player, blocks, this.sellAmount, message);
}
case ITEM -> {
ItemStack[] stacks = this.ingredient.getItems();
if (this.ingredient.isEmpty()) {
return false;
}
int amount = Mth.floor(blocks * this.sellAmount);
ItemStack stack = stacks[0];
while (amount > 0) {
ItemStack toGive = stack.copy();
if (amount > 64) {
toGive.setCount(64);
amount -= 64;
} else {
toGive.setCount(amount);
amount = 0;
}
boolean bl = player.getInventory().add(toGive);
if (!bl || !toGive.isEmpty()) {
ItemEntity itemEntity = player.drop(toGive, false);
if (itemEntity != null) {
itemEntity.setNoPickUpDelay();
itemEntity.setTarget(player.getUUID());
}
}
}
data.setAdditionalClaims(data.getAdditionalClaims() - blocks);
message.accept(Component.translatable(ConfigHandler.langManager.get("sellSuccessItem"), blocks, amount, Component.translatable(stack.getDescriptionId()).withStyle(ChatFormatting.AQUA)));
return true;
}
case XP -> {
int amount = Mth.floor(blocks * this.buyAmount);
player.giveExperiencePoints(amount);
data.setAdditionalClaims(data.getAdditionalClaims() - blocks);
message.accept(PermHelper.simpleColoredText(String.format(ConfigHandler.langManager.get("sellSuccessXP"), blocks, amount)));
return false;
}
}
return false;
}
private boolean isJustRenamedItem(ItemStack stack) {
if (!stack.hasTag())
return true;
if (stack.getTag().getAllKeys()
.stream().allMatch(s -> s.equals("Damage") || s.equals("RepairCost") || s.equals("display"))) {
CompoundTag tag = stack.getTag().getCompound("display");
return tag.contains("Name") && tag.size() == 1;
}
return true;
}
private static int totalXpPointsForLevel(int level) {
if (xpCalc == null || level > xpCalc.length) {
xpCalc = new int[level + 50];
xpCalc[0] = 0;
for (int i = 1; i < xpCalc.length; i++) {
xpCalc[i] = xpForLevel(i) + xpCalc[i - 1];
}
}
return xpCalc[level];
}
/**
* See {@link Player#getXpNeededForNextLevel()}
*/
private static int xpForLevel(int level) {
level -= 1;
if (level >= 30) {
return 112 + (level - 30) * 9;
}
if (level >= 15) {
return 37 + (level - 15) * 5;
}
return 7 + level * 2;
}
public JsonObject toJson() {
JsonObject obj = new JsonObject();
obj.addProperty("buyType", this.buyType.toString());
obj.addProperty("sellType", this.sellType.toString());
obj.addProperty("buyValue", this.buyAmount);
obj.addProperty("sellValue", this.sellAmount);
obj.add("ingredient", this.ingredient.toJson());
return obj;
}
public void fromJson(JsonObject object) {
this.buyType = Type.valueOf(ConfigHandler.fromJson(object, "buyType", this.buyType.toString()));
this.sellType = Type.valueOf(ConfigHandler.fromJson(object, "sellType", this.sellType.toString()));
this.buyAmount = object.has("buyValue") ? object.get("buyValue").getAsFloat() : this.buyAmount;
this.sellAmount = object.has("sellValue") ? object.get("sellValue").getAsFloat() : this.sellAmount;
try {
this.ingredient = object.has("ingredient") ? Ingredient.fromJson(object.get("ingredient")) : Ingredient.EMPTY;
} catch (JsonParseException e) {
this.ingredient = Ingredient.EMPTY;
}
}
enum Type {
MONEY,
ITEM,
XP
}
}