Merge pull request #19 from CraftingStore/feature/CRAF-111/virtual-currency

Add virtual currency.
This commit is contained in:
thijs_a authored and GitHub committed 2021-08-02 23:40:05 +02:00
commit 01f809de73
41 files changed
+817 -75

No files matched your search

+4
View File
@@ -56,6 +56,10 @@
<pattern>org.apache.commons.codec</pattern>
<shadedPattern>net.craftingstore.libraries.apache.commons.codec</shadedPattern>
</relocation>
<relocation>
<pattern>org.apache.commons.text</pattern>
<shadedPattern>net.craftingstore.libraries.apache.commons.text</shadedPattern>
</relocation>
<relocation>
<pattern>org.json</pattern>
<shadedPattern>net.craftingstore.libraries.json</shadedPattern>
+10
View File
@@ -49,6 +49,10 @@
<url>https://repo.codemc.org/repository/maven-public</url>
</repository>
<!-- PlaceholderRAPI end -->
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>
@@ -80,5 +84,11 @@
<artifactId>XSeries</artifactId>
<version>7.9.1.1</version>
</dependency>
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
@@ -39,4 +39,9 @@ public class BukkitPluginConfiguration implements PluginConfiguration {
public int getTimeBetweenCommands() {
return plugin.getConfig().getInt("time-between-commands", 200);
}
@Override
public String getNotEnoughBalanceMessage() {
return plugin.getConfig().getString("not-enough-balance-message", "&4You do not have enough in-game money in your account! You can also buy this package on the website:");
}
}
@@ -4,6 +4,7 @@ import net.craftingstore.bukkit.commands.BuyCommand;
import net.craftingstore.bukkit.commands.CraftingStoreCommand;
import net.craftingstore.bukkit.config.Config;
import net.craftingstore.bukkit.hooks.PlaceholderAPIHook;
import net.craftingstore.bukkit.hooks.VaultHook;
import net.craftingstore.bukkit.listeners.InventoryListener;
import net.craftingstore.bukkit.listeners.AdminJoinListener;
import net.craftingstore.bukkit.listeners.PendingDonationJoinListener;
@@ -18,6 +19,7 @@ public class CraftingStoreBukkit extends JavaPlugin {
private CraftingStore craftingStore;
private Config config;
private String prefix = ChatColor.GRAY + "[" + ChatColor.RED + "CraftingStore" + ChatColor.GRAY + "] " + ChatColor.WHITE;
private VaultHook vaultHook;
@Override
public void onEnable() {
@@ -38,6 +40,16 @@ public class CraftingStoreBukkit extends JavaPlugin {
new PlaceholderAPIHook(craftingStore);
craftingStore.getLogger().info("Hooked with PlaceholderAPI");
}
// Vault hook
if (Bukkit.getPluginManager().isPluginEnabled("Vault")) {
this.vaultHook = new VaultHook(this);
if (this.vaultHook.register()) {
craftingStore.getLogger().info("Hooked with Vault");
} else {
craftingStore.getLogger().info("There was a problem hooking with Vault");
this.vaultHook = null;
}
}
}
@Override
@@ -62,4 +74,12 @@ public class CraftingStoreBukkit extends JavaPlugin {
public String getPrefix() {
return prefix;
}
public VaultHook getVaultHook() {
return vaultHook;
}
public boolean isHookedWithVault() {
return vaultHook != null;
}
}
@@ -3,6 +3,7 @@ package net.craftingstore.bukkit.commands;
import net.craftingstore.bukkit.CraftingStoreBukkit;
import net.craftingstore.bukkit.inventory.InventoryBuilder;
import net.craftingstore.core.exceptions.CraftingStoreApiException;
import net.craftingstore.core.models.api.ApiInventory;
import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
@@ -34,8 +35,10 @@ public class BuyCommand implements CommandExecutor {
Bukkit.getScheduler().runTaskAsynchronously(instance, () -> {
try {
InventoryBuilder builder = new InventoryBuilder(this.instance);
CraftingStoreInventory gui = instance.getCraftingStore().getApi().getGUI().get();
Inventory inventory = builder.buildInventory(gui);
ApiInventory gui = instance.getCraftingStore().getApi().getGUI().get();
Inventory inventory = builder.buildInventory(
new CraftingStoreInventory(gui.getTitle(), gui.getContent(), gui.getSize())
);
Bukkit.getScheduler().runTask(instance, () -> {
if (p.isOnline()) {
p.openInventory(inventory);
@@ -0,0 +1,27 @@
package net.craftingstore.bukkit.hooks;
import net.craftingstore.bukkit.CraftingStoreBukkit;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.plugin.RegisteredServiceProvider;
public class VaultHook {
private final CraftingStoreBukkit instance;
private Economy economy;
public VaultHook(CraftingStoreBukkit instance) {
this.instance = instance;
}
public boolean register() {
RegisteredServiceProvider<Economy> rsp = instance.getServer().getServicesManager().getRegistration(Economy.class);
if (rsp == null) {
return false;
}
this.economy = rsp.getProvider();
return true;
}
public Economy getEconomy() {
return economy;
}
}
@@ -0,0 +1,79 @@
package net.craftingstore.bukkit.inventory;
import net.craftingstore.bukkit.CraftingStoreBukkit;
import net.craftingstore.bukkit.util.ChatColorUtil;
import net.craftingstore.core.exceptions.CraftingStoreApiException;
import net.craftingstore.core.models.api.ApiInventory;
import net.craftingstore.core.models.api.ApiPackageInformation;
import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
import net.craftingstore.core.models.api.inventory.InventoryItem;
import net.craftingstore.core.models.api.inventory.InventoryItemIcon;
import net.craftingstore.core.models.api.inventory.InventoryItemType;
import net.craftingstore.core.models.api.inventory.types.InventoryItemBuyablePackage;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
public class BuyInventoryBuilder {
private final CraftingStoreBukkit instance;
private final InventoryBuilder inventoryBuilder;
public BuyInventoryBuilder(CraftingStoreBukkit instance, InventoryBuilder inventoryBuilder) {
this.instance = instance;
this.inventoryBuilder = inventoryBuilder;
}
public Inventory build(Player p, InventoryItemBuyablePackage item, CraftingStoreInventoryHolder holder) throws CraftingStoreApiException, ExecutionException, InterruptedException {
ApiInventory buyMenu = this.instance.getCraftingStore().getApi().getGUI().get().getBuyMenu();
CraftingStoreInventory craftingStoreInventory = new CraftingStoreInventory(buyMenu.getTitle(), buyMenu.getContent(), buyMenu.getSize());
String ip = p.getAddress().getAddress().getHostAddress();
ApiPackageInformation packageInformation = this.instance.getCraftingStore().getApi().getPackageInformation(
p.getName(),
p.getUniqueId(),
ip,
item.getPackageId()
).get();
if (!packageInformation.isAllowedToBuy()) {
p.sendMessage(ChatColorUtil.translate(packageInformation.getMessage()));
p.closeInventory();
return null;
}
if (packageInformation.getPrice() != item.getPrice()) {
p.sendMessage(this.instance.getPrefix() + "There was a problem with the payment data. Please try again later.");
p.closeInventory();
return null;
}
Map placeholders = new HashMap<>();
placeholders.put("package_name", item.getName());
placeholders.put("package_price_ingame", packageInformation.getPrice());
return this.inventoryBuilder.buildInventory(
craftingStoreInventory,
new BuyMenuInventoryHolder(craftingStoreInventory, holder, item),
placeholders
);
}
public Inventory buildLoadInventory() {
InventoryItemIcon icon = new InventoryItemIcon("LIGHT_BLUE_STAINED_GLASS_PANE", 1, 0, null);
InventoryItem[] content = new InventoryItem[9];
for (int i = 0; i < 9; i++) {
content[i] = new InventoryItem("Loading...", null, InventoryItemType.NULL, icon, i);
}
CraftingStoreInventory craftingStoreInventory = new CraftingStoreInventory(
"Loading...",
content,
9
);
return this.inventoryBuilder.buildInventory(
craftingStoreInventory,
new CraftingStoreInventoryHolder(craftingStoreInventory, null)
);
}
}
@@ -0,0 +1,22 @@
package net.craftingstore.bukkit.inventory;
import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
import net.craftingstore.core.models.api.inventory.types.InventoryItemBuyablePackage;
public class BuyMenuInventoryHolder extends CraftingStoreInventoryHolder {
private final InventoryItemBuyablePackage itemBuyablePackage;
public BuyMenuInventoryHolder(
CraftingStoreInventory csInventory,
CraftingStoreInventoryHolder parentInventory,
InventoryItemBuyablePackage itemBuyablePackage
) {
super(csInventory, parentInventory);
this.itemBuyablePackage = itemBuyablePackage;
}
public InventoryItemBuyablePackage getItemBuyablePackage() {
return itemBuyablePackage;
}
}
@@ -5,12 +5,15 @@ import net.craftingstore.bukkit.util.ChatColorUtil;
import net.craftingstore.bukkit.util.VersionUtil;
import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
import net.craftingstore.core.models.api.inventory.InventoryItem;
import org.apache.commons.text.StringSubstitutor;
import org.bukkit.Bukkit;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;
public class InventoryBuilder {
@@ -24,24 +27,31 @@ public class InventoryBuilder {
}
public Inventory buildInventory(CraftingStoreInventory csInventory) {
return buildInventory(csInventory, null);
return buildInventory(csInventory, new CraftingStoreInventoryHolder(csInventory, null));
}
public Inventory buildInventory(CraftingStoreInventory csInventory, CraftingStoreInventoryHolder parent) {
public Inventory buildInventory(CraftingStoreInventory csInventory, CraftingStoreInventoryHolder holder) {
return buildInventory(csInventory, holder, new HashMap<>());
}
public Inventory buildInventory(CraftingStoreInventory csInventory, CraftingStoreInventoryHolder holder, Map<String, ?> placeholders) {
String title = csInventory.getTitle();
if (title == null || title.isEmpty()) {
title = "CraftingStore";
}
title = ChatColorUtil.translate(title);
Inventory inventory = Bukkit.createInventory(new CraftingStoreInventoryHolder(csInventory, parent), csInventory.getSize(), title);
StringSubstitutor stringSubstitutor = new StringSubstitutor(placeholders, "{", "}");
title = ChatColorUtil.translate(stringSubstitutor.replace(title));
Inventory inventory = Bukkit.createInventory(holder, csInventory.getSize(), title);
for (InventoryItem inventoryItem : csInventory.getContent()) {
ItemStack itemStack = this.inventoryItemBuilder.getItemStack(inventoryItem.getIcon().getMaterial(), inventoryItem.getIcon().getAmount());
ItemMeta meta = itemStack.getItemMeta();
if (meta != null) {
meta.setDisplayName(ChatColorUtil.translate(inventoryItem.getName()));
meta.setDisplayName(ChatColorUtil.translate(stringSubstitutor.replace(inventoryItem.getName())));
if (inventoryItem.getDescription() != null && inventoryItem.getDescription().length != 0) {
meta.setLore(Arrays.stream(inventoryItem.getDescription())
.map(stringSubstitutor::replace)
.map(ChatColorUtil::translate)
.collect(Collectors.toList())
);
@@ -18,7 +18,11 @@ public class BackButtonHandler implements InventoryItemHandler<InventoryItemBack
@Override
public void handle(Player p, InventoryItemBackButton item, CraftingStoreInventoryHolder holder) {
if (holder.getParentInventory() != null) {
Inventory inventory = builder.buildInventory(holder.getParentInventory().getCsInventory(), holder.getParentInventory().getParentInventory());
CraftingStoreInventoryHolder parentInventory = holder.getParentInventory();
Inventory inventory = builder.buildInventory(
parentInventory.getCsInventory(),
new CraftingStoreInventoryHolder(parentInventory.getCsInventory(), parentInventory.getParentInventory())
);
p.openInventory(inventory);
}
}
@@ -0,0 +1,139 @@
package net.craftingstore.bukkit.inventory.handlers;
import net.craftingstore.bukkit.CraftingStoreBukkit;
import net.craftingstore.bukkit.inventory.BuyInventoryBuilder;
import net.craftingstore.bukkit.inventory.BuyMenuInventoryHolder;
import net.craftingstore.bukkit.inventory.CraftingStoreInventoryHolder;
import net.craftingstore.bukkit.inventory.InventoryItemHandler;
import net.craftingstore.bukkit.util.ChatColorUtil;
import net.craftingstore.core.models.api.ApiPackageInformation;
import net.craftingstore.core.models.api.inventory.types.InventoryItemBuyButton;
import net.craftingstore.core.models.api.inventory.types.InventoryItemBuyablePackage;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
public class BuyButtonHandler implements InventoryItemHandler<InventoryItemBuyButton> {
private final CraftingStoreBukkit instance;
private final BuyInventoryBuilder buyInventoryBuilder;
public BuyButtonHandler(CraftingStoreBukkit instance, BuyInventoryBuilder buyInventoryBuilder) {
this.instance = instance;
this.buyInventoryBuilder = buyInventoryBuilder;
}
@Override
public void handle(Player p, InventoryItemBuyButton item, CraftingStoreInventoryHolder holder) {
if (!(holder instanceof BuyMenuInventoryHolder)) {
throw new RuntimeException("BuyButtonHandler only works in a buy menu");
}
InventoryItemBuyablePackage itemBuyablePackage = ((BuyMenuInventoryHolder) holder).getItemBuyablePackage();
InventoryItemBuyButton.InventoryItemBuyButtonAction action = item.getAction();
if (action.equals(InventoryItemBuyButton.InventoryItemBuyButtonAction.ONLINE)) {
for (String message : itemBuyablePackage.getMessages()) {
p.sendMessage(ChatColorUtil.translate(message));
}
p.closeInventory();
return;
}
if (action.equals(InventoryItemBuyButton.InventoryItemBuyButtonAction.IN_GAME)) {
Inventory loading = this.buyInventoryBuilder.buildLoadInventory();
p.openInventory(loading);
Bukkit.getScheduler().runTaskAsynchronously(this.instance, () -> {
try {
String ip = p.getAddress().getAddress().getHostAddress();
ApiPackageInformation packageInformation = this.instance.getCraftingStore().getApi().getPackageInformation(
p.getName(),
p.getUniqueId(),
ip,
itemBuyablePackage.getPackageId()
).get();
if (!packageInformation.isAllowedToBuy()) {
p.sendMessage(ChatColorUtil.translate(packageInformation.getMessage()));
for (String message : itemBuyablePackage.getMessages()) {
p.sendMessage(ChatColorUtil.translate(message));
}
closeInventory(p);
return;
}
if (packageInformation.getPrice() != itemBuyablePackage.getPrice()) {
p.sendMessage(this.instance.getPrefix() + "There was a problem with the payment data. Please try again later.");
closeInventory(p);
return;
}
if (!this.instance.getVaultHook().getEconomy().has(p, packageInformation.getPrice())) {
p.sendMessage(ChatColorUtil.translate(
this.instance.getCraftingStore().getImplementation().getConfiguration().getNotEnoughBalanceMessage()
));
closeInventory(p);
return;
}
EconomyResponse response = this.instance.getVaultHook().getEconomy().withdrawPlayer(
p,
packageInformation.getPrice()
);
if (!response.transactionSuccess()) {
p.sendMessage(this.instance.getPrefix() + "There was a problem with the transaction. Please try again later");
closeInventory(p);
return;
}
try {
boolean success = this.instance.getCraftingStore().getApi().createPayment(
p.getName(),
packageInformation.getPrice(),
new int[]{itemBuyablePackage.getPackageId()}
).get();
if (success) {
p.sendMessage(ChatColorUtil.translate(itemBuyablePackage.getSuccessMessage()));
closeInventory(p);
return;
}
throw new RuntimeException("Failed to create a transaction at CraftingStore. Giving money back.");
} catch (Exception exception) {
exception.printStackTrace();
this.instance.getCraftingStore().getLogger().error(String.format(
"Unable to create a transaction for player %s with package %s and cost %s. Giving the player's money back...",
p.getName(),
itemBuyablePackage.getPackageId(),
packageInformation.getPrice()
));
EconomyResponse rollbackResponse = this.instance.getVaultHook().getEconomy().depositPlayer(
p,
packageInformation.getPrice()
);
if (!rollbackResponse.transactionSuccess()) {
p.sendMessage(this.instance.getPrefix() + "There was a problem with the transaction, and we were unable to give you back your money. Please contact an administrator");
this.instance.getCraftingStore().getLogger().error(String.format(
"Unable to give the player's money back. Player: %s, cost: %s.",
p.getName(),
packageInformation.getPrice()
));
closeInventory(p);
return;
}
p.sendMessage(this.instance.getPrefix() + "A problem occurred while creating your payment. Your money has been given back. Please try again later");
closeInventory(p);
}
} catch (Exception exception) {
exception.printStackTrace();
closeInventory(p);
p.sendMessage(this.instance.getPrefix() + "A problem occurred. Please try again later.");
}
});
}
}
private void closeInventory(Player p) {
Bukkit.getScheduler().runTask(instance, () -> {
if (p.isOnline()) {
p.closeInventory();
}
});
}
}
@@ -0,0 +1,57 @@
package net.craftingstore.bukkit.inventory.handlers;
import net.craftingstore.bukkit.CraftingStoreBukkit;
import net.craftingstore.bukkit.inventory.*;
import net.craftingstore.bukkit.util.ChatColorUtil;
import net.craftingstore.core.models.api.inventory.types.InventoryItemBuyablePackage;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.inventory.Inventory;
public class BuyablePackageHandler implements InventoryItemHandler<InventoryItemBuyablePackage> {
private final CraftingStoreBukkit instance;
private final BuyInventoryBuilder buyInventoryBuilder;
public BuyablePackageHandler(CraftingStoreBukkit instance, BuyInventoryBuilder buyInventoryBuilder) {
this.instance = instance;
this.buyInventoryBuilder = buyInventoryBuilder;
}
@Override
public void handle(Player p, InventoryItemBuyablePackage item, CraftingStoreInventoryHolder holder) {
if (!this.instance.isHookedWithVault()) {
p.sendMessage(instance.getPrefix() + "CraftingStore is not hooked with Vault!");
p.closeInventory();
return;
}
if (!this.instance.getVaultHook().getEconomy().has(p, item.getPrice())) {
p.sendMessage(ChatColorUtil.translate(
this.instance.getCraftingStore().getImplementation().getConfiguration().getNotEnoughBalanceMessage()
));
for (String message : item.getMessages()) {
p.sendMessage(ChatColorUtil.translate(message));
}
p.closeInventory();
return;
}
Inventory loading = this.buyInventoryBuilder.buildLoadInventory();
p.openInventory(loading);
Bukkit.getScheduler().runTaskAsynchronously(this.instance, () -> {
try {
Inventory inventory = this.buyInventoryBuilder.build(p, item, holder);
if (inventory != null) {
Bukkit.getScheduler().runTask(instance, () -> {
if (p.isOnline()) {
p.openInventory(inventory);
}
});
}
} catch (Exception exception) {
exception.printStackTrace();
}
});
}
}
@@ -19,7 +19,7 @@ public class CategoryItemHandler implements InventoryItemHandler<InventoryItemCa
@Override
public void handle(Player p, InventoryItemCategory category, CraftingStoreInventoryHolder holder) {
CraftingStoreInventory csInventory = new CraftingStoreInventory(category.getTitle(), category.getContent(), category.getSize());
Inventory inventory = builder.buildInventory(csInventory, holder);
Inventory inventory = builder.buildInventory(csInventory, new CraftingStoreInventoryHolder(csInventory, holder));
p.openInventory(inventory);
}
}
@@ -1,41 +1,40 @@
package net.craftingstore.bukkit.listeners;
import net.craftingstore.bukkit.CraftingStoreBukkit;
import net.craftingstore.bukkit.inventory.BuyInventoryBuilder;
import net.craftingstore.bukkit.inventory.CraftingStoreInventoryHolder;
import net.craftingstore.bukkit.inventory.InventoryBuilder;
import net.craftingstore.bukkit.inventory.InventoryItemHandler;
import net.craftingstore.bukkit.inventory.handlers.BackButtonHandler;
import net.craftingstore.bukkit.inventory.handlers.CategoryItemHandler;
import net.craftingstore.bukkit.inventory.handlers.CloseButtonHandler;
import net.craftingstore.bukkit.inventory.handlers.MessageButtonHandler;
import net.craftingstore.bukkit.inventory.handlers.*;
import net.craftingstore.core.models.api.inventory.*;
import net.craftingstore.core.models.api.inventory.types.InventoryItemBackButton;
import net.craftingstore.core.models.api.inventory.types.InventoryItemCategory;
import net.craftingstore.core.models.api.inventory.types.InventoryItemCloseButton;
import net.craftingstore.core.models.api.inventory.types.InventoryItemMessage;
import org.bukkit.ChatColor;
import net.craftingstore.core.models.api.inventory.types.*;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.inventory.Inventory;
import java.util.HashMap;
public class InventoryListener implements Listener {
private HashMap<Class<? extends InventoryItem>, InventoryItemHandler> handlers = new HashMap<>();
private final HashMap<Class<? extends InventoryItem>, InventoryItemHandler> handlers = new HashMap<>();
private CraftingStoreBukkit instance;
private InventoryBuilder inventoryBuilder;
private final CraftingStoreBukkit instance;
private final InventoryBuilder inventoryBuilder;
public InventoryListener(CraftingStoreBukkit instance) {
this.instance = instance;
this.inventoryBuilder = new InventoryBuilder(instance);
BuyInventoryBuilder buyInventoryBuilder = new BuyInventoryBuilder(instance, this.inventoryBuilder);
this.handlers.put(InventoryItemBackButton.class, new BackButtonHandler(this.inventoryBuilder));
this.handlers.put(InventoryItemCategory.class, new CategoryItemHandler(this.inventoryBuilder));
this.handlers.put(InventoryItemCloseButton.class, new CloseButtonHandler());
this.handlers.put(InventoryItemMessage.class, new MessageButtonHandler());
this.handlers.put(InventoryItemBuyablePackage.class, new BuyablePackageHandler(
instance,
buyInventoryBuilder
));
this.handlers.put(InventoryItemBuyButton.class, new BuyButtonHandler(instance, buyInventoryBuilder));
}
@EventHandler
+1 -1
View File
@@ -3,7 +3,7 @@ main: net.craftingstore.bukkit.CraftingStoreBukkit
version: ${craftingstore-version}
authors: [Tim_kwakman, thijs_a]
prefix: CraftingStore
softdepend: [PlaceholderAPI]
softdepend: [PlaceholderAPI, Vault]
api-version: "1.13"
commands:
craftingstore:
@@ -39,4 +39,9 @@ public class BungeePluginConfiguration implements PluginConfiguration {
public int getTimeBetweenCommands() {
return plugin.getConfig().getInt("time-between-commands", 200);
}
@Override
public String getNotEnoughBalanceMessage() {
return null;
}
}
+5
View File
@@ -59,5 +59,10 @@
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.9</version>
</dependency>
</dependencies>
</project>
@@ -1,14 +1,11 @@
package net.craftingstore.core;
import net.craftingstore.core.exceptions.CraftingStoreApiException;
import net.craftingstore.core.models.api.ApiCategory;
import net.craftingstore.core.models.api.ApiPayment;
import net.craftingstore.core.models.api.ApiTopDonator;
import net.craftingstore.core.models.api.Root;
import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
import net.craftingstore.core.models.api.*;
import net.craftingstore.core.models.api.misc.CraftingStoreInformation;
import net.craftingstore.core.models.donation.Donation;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@@ -20,7 +17,7 @@ public abstract class CraftingStoreAPI {
public abstract Future<CraftingStoreInformation> getInformation() throws CraftingStoreApiException;
public abstract Future<Root> checkKey() throws CraftingStoreApiException;
public abstract Future<Root<?>> checkKey() throws CraftingStoreApiException;
public abstract Future<Donation[]> getDonationQueue() throws CraftingStoreApiException;
@@ -28,12 +25,23 @@ public abstract class CraftingStoreAPI {
public abstract Future<ApiPayment[]> getPayments() throws CraftingStoreApiException;
public abstract Future<ApiCategory[]> getCategories() throws CraftingStoreApiException;
public abstract Future<CraftingStoreInventory> getGUI() throws CraftingStoreApiException;
public abstract Future<ApiInventory> getGUI() throws CraftingStoreApiException;
public abstract Future<ApiTopDonator[]> getTopDonators() throws CraftingStoreApiException;
public abstract Future<ApiPackageInformation> getPackageInformation(
String inGameName,
UUID uuid,
String ip,
int packageId
) throws CraftingStoreApiException;
public abstract Future<Boolean> createPayment(
String inGameName,
int price,
int[] packages
) throws CraftingStoreApiException;
public String getToken() {
return this.token;
}
@@ -12,4 +12,6 @@ public interface PluginConfiguration {
boolean isBuyCommandEnabled();
int getTimeBetweenCommands();
String getNotEnoughBalanceMessage();
}
@@ -8,11 +8,13 @@ import net.craftingstore.core.exceptions.CraftingStoreApiException;
import net.craftingstore.core.http.util.InformationAdapter;
import net.craftingstore.core.http.util.InventoryAdapter;
import net.craftingstore.core.http.util.JsonResponseHandler;
import net.craftingstore.core.http.util.JsonResponseHandlerV7;
import net.craftingstore.core.models.api.*;
import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
import net.craftingstore.core.models.api.inventory.InventoryItem;
import net.craftingstore.core.models.api.misc.CraftingStoreInformation;
import net.craftingstore.core.models.api.provider.ProviderInformation;
import net.craftingstore.core.models.api.request.PackageInformationRequest;
import net.craftingstore.core.models.api.request.PaymentCreateRequest;
import net.craftingstore.core.models.donation.Donation;
import net.craftingstore.core.models.donation.DonationPackage;
import net.craftingstore.core.models.donation.DonationPlayer;
@@ -24,6 +26,8 @@ import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
@@ -35,6 +39,7 @@ import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Future;
public class CraftingStoreAPIImpl extends CraftingStoreAPI {
@@ -64,7 +69,7 @@ public class CraftingStoreAPIImpl extends CraftingStoreAPI {
public Future<CraftingStoreInformation> getInformation() throws CraftingStoreApiException {
return executor.submit(() -> {
try {
HttpPost request = post("info");
HttpPost request = post("v4/info");
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("version", instance.getImplementation().getConfiguration().getVersion()));
params.add(new BasicNameValuePair("platform", instance.getImplementation().getConfiguration().getPlatform()));
@@ -76,10 +81,10 @@ public class CraftingStoreAPIImpl extends CraftingStoreAPI {
});
}
public Future<Root> checkKey() throws CraftingStoreApiException {
public Future<Root<?>> checkKey() throws CraftingStoreApiException {
return executor.submit(() -> {
try {
return httpClient.execute(get("validateToken"), new JsonResponseHandler<>(gson, Root.class));
return httpClient.execute(get("v4/validateToken"), new JsonResponseHandler<>(gson, Root.class));
} catch (IOException e) {
throw new CraftingStoreApiException("Check Key call failed", e);
}
@@ -89,7 +94,7 @@ public class CraftingStoreAPIImpl extends CraftingStoreAPI {
public Future<Donation[]> getDonationQueue() throws CraftingStoreApiException {
return executor.submit(() -> {
try {
ApiDonation[] apiDonations = httpClient.execute(get("queue"), new JsonResponseHandler<>(gson, ApiDonation[].class));
ApiDonation[] apiDonations = httpClient.execute(get("v4/queue"), new JsonResponseHandler<>(gson, ApiDonation[].class));
return Arrays.stream(apiDonations).map(apiDonation -> {
DonationPlayer player = new DonationPlayer(apiDonation.getMcName(), apiDonation.getUuid(), apiDonation.getRequireOnline());
DonationPackage donationPackage = new DonationPackage(apiDonation.getPackageName(), apiDonation.getPackagePriceCents());
@@ -111,7 +116,7 @@ public class CraftingStoreAPIImpl extends CraftingStoreAPI {
public void completeDonations(int[] ids) throws CraftingStoreApiException {
executor.submit(() -> {
try {
HttpPost request = post("queue/markComplete");
HttpPost request = post("v4/queue/markComplete");
List<NameValuePair> params = new ArrayList<>();
params.add(new BasicNameValuePair("removeIds", gson.toJson(ids)));
request.setEntity(new UrlEncodedFormEntity(params));
@@ -127,28 +132,17 @@ public class CraftingStoreAPIImpl extends CraftingStoreAPI {
public Future<ApiPayment[]> getPayments() throws CraftingStoreApiException {
return executor.submit(() -> {
try {
return httpClient.execute(get("buyers/recent"), new JsonResponseHandler<>(gson, ApiPayment[].class));
return httpClient.execute(get("v4/buyers/recent"), new JsonResponseHandler<>(gson, ApiPayment[].class));
} catch (IOException e) {
throw new CraftingStoreApiException("Payments call failed", e);
}
});
}
@Deprecated
public Future<ApiCategory[]> getCategories() throws CraftingStoreApiException {
public Future<ApiInventory> getGUI() throws CraftingStoreApiException {
return executor.submit(() -> {
try {
return httpClient.execute(get("plugin/inventory"), new JsonResponseHandler<>(gson, ApiCategory[].class));
} catch (IOException e) {
throw new CraftingStoreApiException("Categories call failed", e);
}
});
}
public Future<CraftingStoreInventory> getGUI() throws CraftingStoreApiException {
return executor.submit(() -> {
try {
return httpClient.execute(get("plugin/gui"), new JsonResponseHandler<>(gson, CraftingStoreInventory.class));
return httpClient.execute(get("v4/plugin/gui"), new JsonResponseHandler<>(gson, ApiInventory.class));
} catch (IOException e) {
throw new CraftingStoreApiException("Inventory call failed", e);
}
@@ -158,13 +152,65 @@ public class CraftingStoreAPIImpl extends CraftingStoreAPI {
public Future<ApiTopDonator[]> getTopDonators() throws CraftingStoreApiException {
return executor.submit(() -> {
try {
return httpClient.execute(get("buyers/top"), new JsonResponseHandler<>(gson, ApiTopDonator[].class));
return httpClient.execute(get("v4/buyers/top"), new JsonResponseHandler<>(gson, ApiTopDonator[].class));
} catch (IOException e) {
throw new CraftingStoreApiException("Top Donators call failed", e);
}
});
}
public Future<ApiPackageInformation> getPackageInformation(
String inGameName,
UUID uuid,
String ip,
int packageId
) throws CraftingStoreApiException {
return executor.submit(() -> {
try {
HttpPost request = post("v7/package/ingame/information");
PackageInformationRequest packageInformationRequest = new PackageInformationRequest(
inGameName,
uuid.toString(),
ip,
packageId
);
request.setEntity(new StringEntity(gson.toJson(packageInformationRequest), ContentType.APPLICATION_JSON));
return httpClient.execute(request, new JsonResponseHandlerV7<>(gson, ApiPackageInformation.class));
} catch (IOException e) {
throw new CraftingStoreApiException("Get package information call failed", e);
}
});
}
public Future<Boolean> createPayment(
String inGameName,
int price,
int[] packages
) throws CraftingStoreApiException {
return executor.submit(() -> {
try {
HttpPost request = post("v7/payments");
PaymentCreateRequest paymentCreateRequest = new PaymentCreateRequest(
inGameName,
"Paid with in-game currency",
"ingame",
price,
null,
true,
packages
);
request.setEntity(new StringEntity(gson.toJson(paymentCreateRequest), ContentType.APPLICATION_JSON));
HttpResponse response = httpClient.execute(request);
EntityUtils.consumeQuietly(response.getEntity());
return true;
} catch (IOException e) {
instance.getLogger().error("Payment create call failed");
e.printStackTrace();
return false;
}
});
}
private HttpGet get(String endpoint) {
HttpGet request = new HttpGet(BASE_URL + endpoint);
request.setConfig(RequestConfig.custom()
@@ -2,9 +2,9 @@ package net.craftingstore.core.http;
import net.craftingstore.core.CraftingStore;
import net.craftingstore.core.exceptions.CraftingStoreApiException;
import net.craftingstore.core.models.api.ApiInventory;
import net.craftingstore.core.models.api.ApiPayment;
import net.craftingstore.core.models.api.ApiTopDonator;
import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
import java.util.HashMap;
import java.util.concurrent.ExecutionException;
@@ -12,20 +12,20 @@ import java.util.concurrent.Future;
public class CraftingStoreCachedAPI extends CraftingStoreAPIImpl {
private HashMap<String, Object> cache = new HashMap<>();
private final HashMap<String, Object> cache = new HashMap<>();
public CraftingStoreCachedAPI(CraftingStore instance) {
super(instance);
}
@Override
public Future<CraftingStoreInventory> getGUI() throws CraftingStoreApiException {
public Future<ApiInventory> getGUI() throws CraftingStoreApiException {
return executor.submit(() -> {
String key = "plugin/inventory";
if (!cache.containsKey(key)) {
cache.put(key, super.getGUI().get());
}
return (CraftingStoreInventory) cache.get(key);
return (ApiInventory) cache.get(key);
});
}
@@ -13,7 +13,7 @@ public class InventoryAdapter implements JsonDeserializer<InventoryItem> {
JsonPrimitive prim = (JsonPrimitive) jsonObject.get("type");
InventoryItemType itemType = InventoryItemType.valueOf(prim.getAsString());
Class klass = itemType.getActualClass();
Class<? extends InventoryItem> klass = itemType.getActualClass();
return context.deserialize(jsonObject, klass);
}
}
@@ -0,0 +1,45 @@
package net.craftingstore.core.http.util;
import com.google.gson.Gson;
import net.craftingstore.core.models.api.RootV7;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.util.EntityUtils;
import java.io.IOException;
public class JsonResponseHandlerV7<T> implements ResponseHandler<T> {
private Gson gson;
private Class<T> aClass;
public JsonResponseHandlerV7(Gson gson, Class<T> aClass) {
this.gson = gson;
this.aClass = aClass;
}
public T handleResponse(HttpResponse response) throws IOException {
StatusLine statusLine = response.getStatusLine();
HttpEntity entity = response.getEntity();
if (statusLine.getStatusCode() >= 300) {
throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
}
if (entity == null) {
throw new ClientProtocolException("Response contains no content");
}
String value = EntityUtils.toString(entity);
if (aClass == RootV7.class) {
return gson.fromJson(value, aClass);
}
RootV7<T> result = gson.fromJson(value, new GenericOf<>(RootV7.class, aClass));
return result.getData();
}
}
@@ -0,0 +1,26 @@
package net.craftingstore.core.models.api;
import net.craftingstore.core.models.api.inventory.InventoryItem;
public class ApiInventory {
private String title;
private InventoryItem[] content;
private int size;
private ApiInventory buyMenu;
public String getTitle() {
return title;
}
public InventoryItem[] getContent() {
return content;
}
public int getSize() {
return size;
}
public ApiInventory getBuyMenu() {
return buyMenu;
}
}
@@ -0,0 +1,19 @@
package net.craftingstore.core.models.api;
public class ApiPackageInformation {
private boolean mayBuy;
private int price;
private String message;
public boolean isAllowedToBuy() {
return mayBuy;
}
public int getPrice() {
return price;
}
public String getMessage() {
return message;
}
}
@@ -0,0 +1,17 @@
package net.craftingstore.core.models.api;
public class RootV7<T> {
private T data;
private boolean success;
private String message;
public T getData() {
return data;
}
public boolean isSuccess() {
return success;
}
}
@@ -1,11 +1,23 @@
package net.craftingstore.core.models.api.inventory;
public class InventoryItem {
private String name;
private String[] description;
private InventoryItemType type;
private InventoryItemIcon icon;
private int index;
protected String name;
protected String[] description;
protected InventoryItemType type;
protected InventoryItemIcon icon;
protected int index;
public InventoryItem() {
}
public InventoryItem(String name, String[] description, InventoryItemType type, InventoryItemIcon icon, int index) {
this.name = name;
this.description = description;
this.type = type;
this.icon = icon;
this.index = index;
}
public String getName() {
return name;
@@ -6,6 +6,16 @@ public class InventoryItemIcon {
private int customModelData;
private InventoryItemEnhancement[] enhancements;
public InventoryItemIcon() {
}
public InventoryItemIcon(String material, Integer amount, int customModelData, InventoryItemEnhancement[] enhancements) {
this.material = material;
this.amount = amount;
this.customModelData = customModelData;
this.enhancements = enhancements;
}
public String getMaterial() {
return material;
}
@@ -1,23 +1,24 @@
package net.craftingstore.core.models.api.inventory;
import net.craftingstore.core.models.api.inventory.types.InventoryItemBackButton;
import net.craftingstore.core.models.api.inventory.types.InventoryItemCategory;
import net.craftingstore.core.models.api.inventory.types.InventoryItemCloseButton;
import net.craftingstore.core.models.api.inventory.types.InventoryItemMessage;
import net.craftingstore.core.models.api.inventory.types.*;
public enum InventoryItemType {
NULL(null),
CATEGORY(InventoryItemCategory.class),
MESSAGE(InventoryItemMessage.class),
BACK(InventoryItemBackButton.class),
CLOSE(InventoryItemCloseButton.class);
CLOSE(InventoryItemCloseButton.class),
BUYABLE_PACKAGE(InventoryItemBuyablePackage.class),
BUY_DETAILS(InventoryItemBuyDetails.class),
BUY_BUTTON(InventoryItemBuyButton.class);
private Class c;
private final Class<? extends InventoryItem> c;
InventoryItemType(Class c) {
InventoryItemType(Class<? extends InventoryItem> c) {
this.c = c;
}
public Class getActualClass() {
public Class<? extends InventoryItem> getActualClass() {
return c;
}
}
@@ -1,6 +1,19 @@
package net.craftingstore.core.models.api.inventory.types;
import net.craftingstore.core.models.api.inventory.InventoryItem;
import net.craftingstore.core.models.api.inventory.InventoryItemIcon;
import net.craftingstore.core.models.api.inventory.InventoryItemType;
public class InventoryItemBackButton extends InventoryItem {
public InventoryItemBackButton() {}
public InventoryItemBackButton(
String name,
String[] description,
InventoryItemIcon icon,
int index
) {
super(name, description, InventoryItemType.BACK, icon, index);
}
}
@@ -0,0 +1,29 @@
package net.craftingstore.core.models.api.inventory.types;
import net.craftingstore.core.models.api.inventory.InventoryItem;
import net.craftingstore.core.models.api.inventory.InventoryItemIcon;
import net.craftingstore.core.models.api.inventory.InventoryItemType;
public class InventoryItemBuyButton extends InventoryItem {
private final InventoryItemBuyButtonAction action;
public InventoryItemBuyButton(
String name,
String[] description,
InventoryItemIcon icon,
int index,
InventoryItemBuyButtonAction action
) {
super(name, description, InventoryItemType.BUY_BUTTON, icon, index);
this.action = action;
}
public InventoryItemBuyButtonAction getAction() {
return action;
}
public enum InventoryItemBuyButtonAction {
IN_GAME,
ONLINE,
}
}
@@ -0,0 +1,19 @@
package net.craftingstore.core.models.api.inventory.types;
import net.craftingstore.core.models.api.inventory.InventoryItem;
import net.craftingstore.core.models.api.inventory.InventoryItemIcon;
import net.craftingstore.core.models.api.inventory.InventoryItemType;
public class InventoryItemBuyDetails extends InventoryItem {
public InventoryItemBuyDetails() {}
public InventoryItemBuyDetails(
String name,
String[] description,
InventoryItemIcon icon,
int index
) {
super(name, description, InventoryItemType.BUY_DETAILS, icon, index);
}
}
@@ -0,0 +1,30 @@
package net.craftingstore.core.models.api.inventory.types;
import net.craftingstore.core.models.api.inventory.InventoryItem;
public class InventoryItemBuyablePackage extends InventoryItem {
private int price;
private int packageId;
private String[] messages;
private String successMessage;
public InventoryItemBuyablePackage() {
}
public int getPrice() {
return price;
}
public int getPackageId() {
return packageId;
}
public String[] getMessages() {
return messages;
}
public String getSuccessMessage() {
return successMessage;
}
}
@@ -1,11 +1,29 @@
package net.craftingstore.core.models.api.inventory.types;
import net.craftingstore.core.models.api.inventory.InventoryItem;
import net.craftingstore.core.models.api.inventory.InventoryItemIcon;
import net.craftingstore.core.models.api.inventory.InventoryItemType;
public class InventoryItemMessage extends InventoryItem {
private String[] messages;
private boolean close;
public InventoryItemMessage() {
}
public InventoryItemMessage(
String name,
String[] description,
InventoryItemIcon icon,
int index,
String[] messages,
boolean close
) {
super(name, description, InventoryItemType.MESSAGE, icon, index);
this.messages = messages;
this.close = close;
}
public String[] getMessages() {
return messages;
}
@@ -0,0 +1,17 @@
package net.craftingstore.core.models.api.request;
import java.io.Serializable;
public class PackageInformationRequest implements Serializable {
String inGameName;
String uuid;
String ip;
int packageId;
public PackageInformationRequest(String inGameName, String uuid, String ip, int packageId) {
this.inGameName = inGameName;
this.uuid = uuid;
this.ip = ip;
this.packageId = packageId;
}
}
@@ -0,0 +1,29 @@
package net.craftingstore.core.models.api.request;
public class PaymentCreateRequest {
String inGameName;
String notes;
String gateway;
int inGamePricePaid;
Integer pricePaid;
boolean executeCommands;
int[] packages;
public PaymentCreateRequest(
String inGameName,
String notes,
String gateway,
int inGamePricePaid,
Integer pricePaid,
boolean executeCommands,
int[] packages
) {
this.inGameName = inGameName;
this.notes = notes;
this.gateway = gateway;
this.inGamePricePaid = inGamePricePaid;
this.pricePaid = pricePaid;
this.executeCommands = executeCommands;
this.packages = packages;
}
}
@@ -36,7 +36,7 @@ public class SocketProvider extends CraftingStoreProvider {
}
}
// Wait some time on SocketIO
Thread.sleep(150);
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
+1 -1
View File
@@ -11,7 +11,7 @@
<properties>
<revision>${craftingstore-version}-RELEASE</revision>
<craftingstore-version>2.7.0</craftingstore-version>
<craftingstore-version>2.8.0</craftingstore-version>
</properties>
<build>
@@ -48,4 +48,9 @@ public class SpongePluginConfiguration implements PluginConfiguration {
public int getTimeBetweenCommands() {
return craftingStoreSponge.getConfigWrapper().getConfig().getNode("time-between-commands").getInt(200);
}
@Override
public String getNotEnoughBalanceMessage() {
return null;
}
}
@@ -3,6 +3,7 @@ package net.craftingstore.sponge.commands;
import com.google.inject.Inject;
import net.craftingstore.core.CraftingStore;
import net.craftingstore.core.exceptions.CraftingStoreApiException;
import net.craftingstore.core.models.api.ApiInventory;
import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
import net.craftingstore.sponge.CraftingStoreSponge;
import net.craftingstore.sponge.inventory.InventoryBuilder;
@@ -43,8 +44,9 @@ public class BuyCommand implements CommandExecutor {
game.getScheduler().createTaskBuilder()
.execute(() -> {
try {
CraftingStoreInventory gui = craftingStore.getApi().getGUI().get();
Inventory inventory = this.inventoryBuilder.buildInventory(gui);
ApiInventory gui = craftingStore.getApi().getGUI().get();
CraftingStoreInventory craftingStoreInventory = new CraftingStoreInventory(gui.getTitle(), gui.getContent(), gui.getSize());
Inventory inventory = this.inventoryBuilder.buildInventory(craftingStoreInventory);
game.getScheduler().createTaskBuilder()
.execute(() -> {
if (p.isOnline()) {
@@ -53,4 +53,9 @@ public class VelocityPluginConfiguration implements PluginConfiguration {
}
throw new RuntimeException("Invalid integer value in time-between-commands");
}
@Override
public String getNotEnoughBalanceMessage() {
return null;
}
}