Added price system

This commit is contained in:
Auxilor
2022-10-23 16:40:52 +01:00
parent 9588d49788
commit ee13de31f4
10 changed files with 354 additions and 1 deletions

View File

@@ -0,0 +1,26 @@
package com.willfp.eco.core.price;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* A price that a player should pay.
*/
public interface Price {
/**
* Get if the player can afford the price.
*
* @param player The player.
* @return If the player can afford.
*/
boolean canAfford(@NotNull Player player);
/**
* Make the player pay the price.
* <p>
* Only run this if the player can afford the price.
*
* @param player The player.
*/
void pay(@NotNull Player player);
}

View File

@@ -0,0 +1,27 @@
package com.willfp.eco.core.price;
import org.jetbrains.annotations.NotNull;
import java.util.List;
/**
* Create prices.
*/
public interface PriceFactory {
/**
* Get the names (how the price looks in lookup strings).
* <p>
* For example, for XP Levels this would be 'l', 'xpl', 'levels', etc.
*
* @return The allowed names.
*/
@NotNull List<String> getNames();
/**
* Create the price.
*
* @param value The value.
* @return The price.
*/
@NotNull Price create(double value);
}

View File

@@ -0,0 +1,84 @@
package com.willfp.eco.core.price;
import com.willfp.eco.core.items.Items;
import com.willfp.eco.core.items.TestableItem;
import com.willfp.eco.core.price.impl.PriceEconomy;
import com.willfp.eco.core.price.impl.PriceFree;
import com.willfp.eco.core.price.impl.PriceItem;
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* Class to manage prices.
*/
public final class Prices {
/**
* All factories.
*/
private static final Map<String, PriceFactory> FACTORIES = new ConcurrentHashMap<>();
/**
* Register a new price factory.
*
* @param factory The factory.
*/
public static void registerPriceFactory(@NotNull final PriceFactory factory) {
for (String name : factory.getNames()) {
FACTORIES.put(name.toLowerCase(), factory);
}
}
/**
* Lookup a price from a string.
* <p>
* A price string should look like {@code 5000}, {@code 2000 levels},
* {@code 200 g_souls}, {@code 200 pots of gold}, etc.
*
* @param key The key.
* @return The price, or {@link PriceFree} if invalid.
*/
@NotNull
public static Price lookup(@NotNull final String key) {
String[] split = key.split(" ");
if (split.length == 0) {
return new PriceFree();
}
double value;
try {
value = Double.parseDouble(split[0]);
} catch (NumberFormatException e) {
value = 0.0;
}
if (split.length == 1) {
return new PriceEconomy(value);
}
String name = String.join(" ", Arrays.copyOfRange(split, 1, split.length));
PriceFactory factory = FACTORIES.get(name.toLowerCase());
if (factory == null) {
TestableItem item = Items.lookup(name.toLowerCase());
if (item instanceof EmptyTestableItem) {
return new PriceFree();
}
return new PriceItem((int) Math.round(value), item);
}
return factory.create(value);
}
private Prices() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
}

View File

@@ -0,0 +1,35 @@
package com.willfp.eco.core.price.impl;
import com.willfp.eco.core.integrations.economy.EconomyManager;
import com.willfp.eco.core.price.Price;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Economy-based price (for Vault, Treasury, etc.)
*/
public final class PriceEconomy implements Price {
/**
* The value of the price.
*/
private final double value;
/**
* Create a new economy-based price.
*
* @param value The value.
*/
public PriceEconomy(final double value) {
this.value = value;
}
@Override
public boolean canAfford(@NotNull Player player) {
return EconomyManager.getBalance(player) >= value;
}
@Override
public void pay(@NotNull Player player) {
EconomyManager.removeMoney(player, value);
}
}

View File

@@ -0,0 +1,27 @@
package com.willfp.eco.core.price.impl;
import com.willfp.eco.core.price.Price;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
/**
* Free (default) price.
*/
public final class PriceFree implements Price {
/**
* Create a new free price.
*/
public PriceFree() {
}
@Override
public boolean canAfford(@NotNull Player player) {
return true;
}
@Override
public void pay(@NotNull Player player) {
// Do nothing.
}
}

View File

@@ -0,0 +1,77 @@
package com.willfp.eco.core.price.impl;
import com.willfp.eco.core.items.TestableItem;
import com.willfp.eco.core.price.Price;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
/**
* Item-based price.
*/
public final class PriceItem implements Price {
/**
* The amount of items.
*/
private final int amountToRemove;
/**
* The item.
*/
private final TestableItem item;
/**
* Create a new economy-based price.
*
* @param amount The amount.
*/
public PriceItem(final int amount,
@NotNull final TestableItem item) {
this.amountToRemove = Math.max(0, amount);
this.item = item;
}
@Override
public boolean canAfford(@NotNull Player player) {
if (amountToRemove == 0) {
return true;
}
int count = 0;
for (ItemStack itemStack : player.getInventory().getContents()) {
if (item.matches(itemStack)) {
count += itemStack.getAmount();
}
}
return count >= amountToRemove;
}
@Override
public void pay(@NotNull Player player) {
int count = 0;
for (ItemStack itemStack : player.getInventory().getContents()) {
if (count >= amountToRemove) {
break;
}
if (item.matches(itemStack)) {
int itemAmount = itemStack.getAmount();
if (itemAmount > amountToRemove) {
itemStack.setAmount(itemAmount - amountToRemove);
}
if (itemAmount <= amountToRemove) {
itemStack.setAmount(0);
itemStack.setType(Material.AIR);
}
count += itemAmount;
}
}
}
}

View File

@@ -0,0 +1,14 @@
package com.willfp.eco.internal.price
import com.willfp.eco.core.price.Price
import com.willfp.eco.core.price.PriceFactory
import com.willfp.eco.core.price.impl.PriceEconomy
object PriceFactoryEconomy : PriceFactory {
override fun getNames() = listOf(
"coins",
"$"
)
override fun create(value: Double): Price = PriceEconomy(value)
}

View File

@@ -0,0 +1,26 @@
package com.willfp.eco.internal.price
import com.willfp.eco.core.price.Price
import com.willfp.eco.core.price.PriceFactory
import org.bukkit.entity.Player
import kotlin.math.roundToInt
object PriceFactoryXP : PriceFactory {
override fun getNames() = listOf(
"xp",
"exp",
"experience"
)
override fun create(value: Double): Price = PriceXP(value.roundToInt())
private class PriceXP(
private val xp: Int
) : Price {
override fun canAfford(player: Player) = player.totalExperience >= xp
override fun pay(player: Player) {
player.totalExperience -= xp
}
}
}

View File

@@ -0,0 +1,29 @@
package com.willfp.eco.internal.price
import com.willfp.eco.core.price.Price
import com.willfp.eco.core.price.PriceFactory
import org.bukkit.entity.Player
import kotlin.math.roundToInt
object PriceFactoryXPLevels : PriceFactory {
override fun getNames() = listOf(
"levels",
"xp levels",
"exp levels",
"l",
"xpl",
"expl"
)
override fun create(value: Double): Price = PriceXPLevel(value.roundToInt())
private class PriceXPLevel(
private val levels: Int
) : Price {
override fun canAfford(player: Player) = player.level >= levels
override fun pay(player: Player) {
player.level -= levels
}
}
}

View File

@@ -17,6 +17,7 @@ import com.willfp.eco.core.integrations.mcmmo.McmmoManager
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
import com.willfp.eco.core.integrations.shop.ShopManager
import com.willfp.eco.core.items.Items
import com.willfp.eco.core.price.Prices
import com.willfp.eco.internal.entities.EntityArgParserAdult
import com.willfp.eco.internal.entities.EntityArgParserAttackDamage
import com.willfp.eco.internal.entities.EntityArgParserAttackSpeed
@@ -45,11 +46,14 @@ import com.willfp.eco.internal.items.ArgParserTexture
import com.willfp.eco.internal.items.ArgParserUnbreakable
import com.willfp.eco.internal.lookup.SegmentParserGroup
import com.willfp.eco.internal.lookup.SegmentParserUseIfPresent
import com.willfp.eco.internal.price.PriceFactoryEconomy
import com.willfp.eco.internal.price.PriceFactoryXP
import com.willfp.eco.internal.price.PriceFactoryXPLevels
import com.willfp.eco.internal.spigot.arrows.ArrowDataListener
import com.willfp.eco.internal.spigot.data.DataListener
import com.willfp.eco.internal.spigot.data.DataYml
import com.willfp.eco.internal.spigot.data.ProfileHandler
import com.willfp.eco.internal.spigot.data.PlayerBlockListener
import com.willfp.eco.internal.spigot.data.ProfileHandler
import com.willfp.eco.internal.spigot.data.storage.ProfileSaver
import com.willfp.eco.internal.spigot.display.PacketAutoRecipe
import com.willfp.eco.internal.spigot.display.PacketChat
@@ -161,6 +165,10 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
Entities.registerArgParser(EntityArgParserSilent)
Entities.registerArgParser(EntityArgParserEquipment)
Prices.registerPriceFactory(PriceFactoryEconomy)
Prices.registerPriceFactory(PriceFactoryXPLevels)
Prices.registerPriceFactory(PriceFactoryXP)
CraftingRecipeListener.registerListener(ComplexInComplex)
CraftingRecipeListener.registerListener(ComplexInVanilla)