├── .gitignore
├── LICENSE
├── assembly
└── pom.xml
├── bukkit
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── net
│ │ └── craftingstore
│ │ └── bukkit
│ │ ├── BukkitPluginConfiguration.java
│ │ ├── CraftingStoreBukkit.java
│ │ ├── CraftingStoreBukkitImpl.java
│ │ ├── commands
│ │ ├── BuyCommand.java
│ │ └── CraftingStoreCommand.java
│ │ ├── config
│ │ └── Config.java
│ │ ├── events
│ │ └── DonationReceivedEvent.java
│ │ ├── hooks
│ │ ├── PlaceholderAPIHook.java
│ │ └── VaultHook.java
│ │ ├── inventory
│ │ ├── BuyInventoryBuilder.java
│ │ ├── BuyMenuInventoryHolder.java
│ │ ├── CraftingStoreInventoryHolder.java
│ │ ├── InventoryBuilder.java
│ │ ├── InventoryItemBuilder.java
│ │ ├── InventoryItemHandler.java
│ │ └── handlers
│ │ │ ├── BackButtonHandler.java
│ │ │ ├── BuyButtonHandler.java
│ │ │ ├── BuyablePackageHandler.java
│ │ │ ├── CategoryItemHandler.java
│ │ │ ├── CloseButtonHandler.java
│ │ │ └── MessageButtonHandler.java
│ │ ├── listeners
│ │ ├── AdminJoinListener.java
│ │ ├── InventoryListener.java
│ │ └── PendingDonationJoinListener.java
│ │ └── util
│ │ ├── ChatColorUtil.java
│ │ ├── VersionUtil.java
│ │ └── XMaterial.java
│ └── resources
│ ├── config.yml
│ └── plugin.yml
├── bungee
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── net
│ │ └── craftingstore
│ │ └── bungee
│ │ ├── BungeePluginConfiguration.java
│ │ ├── CraftingStoreBungee.java
│ │ ├── CraftingStoreBungeeImpl.java
│ │ ├── commands
│ │ └── CraftingStoreCommand.java
│ │ ├── config
│ │ └── Config.java
│ │ ├── events
│ │ └── DonationReceivedEvent.java
│ │ └── listeners
│ │ ├── AdminJoinListener.java
│ │ └── PendingDonationJoinListener.java
│ └── resources
│ └── bungee.yml
├── core
├── pom.xml
└── src
│ └── main
│ └── java
│ └── net
│ └── craftingstore
│ └── core
│ ├── CraftingStore.java
│ ├── CraftingStoreAPI.java
│ ├── CraftingStorePlugin.java
│ ├── PluginConfiguration.java
│ ├── exceptions
│ └── CraftingStoreApiException.java
│ ├── http
│ ├── CraftingStoreAPIImpl.java
│ ├── CraftingStoreCachedAPI.java
│ └── util
│ │ ├── GenericOf.java
│ │ ├── InformationAdapter.java
│ │ ├── InventoryAdapter.java
│ │ ├── JsonResponseHandler.java
│ │ └── JsonResponseHandlerV7.java
│ ├── jobs
│ ├── ExecuteDonationsJob.java
│ └── ProcessPendingPaymentsJob.java
│ ├── logging
│ ├── CraftingStoreLogger.java
│ └── impl
│ │ └── JavaLogger.java
│ ├── models
│ ├── api
│ │ ├── ApiCategory.java
│ │ ├── ApiDonation.java
│ │ ├── ApiInventory.java
│ │ ├── ApiPackageInformation.java
│ │ ├── ApiPayment.java
│ │ ├── ApiTopDonator.java
│ │ ├── Root.java
│ │ ├── RootV7.java
│ │ ├── inventory
│ │ │ ├── CraftingStoreInventory.java
│ │ │ ├── InventoryItem.java
│ │ │ ├── InventoryItemEnhancement.java
│ │ │ ├── InventoryItemIcon.java
│ │ │ ├── InventoryItemType.java
│ │ │ └── types
│ │ │ │ ├── InventoryItemBackButton.java
│ │ │ │ ├── InventoryItemBuyButton.java
│ │ │ │ ├── InventoryItemBuyDetails.java
│ │ │ │ ├── InventoryItemBuyablePackage.java
│ │ │ │ ├── InventoryItemCategory.java
│ │ │ │ ├── InventoryItemCloseButton.java
│ │ │ │ └── InventoryItemMessage.java
│ │ ├── misc
│ │ │ ├── ApiKeyResult.java
│ │ │ ├── CraftingStoreInformation.java
│ │ │ └── UpdateInformation.java
│ │ ├── provider
│ │ │ ├── ProviderInformation.java
│ │ │ ├── ProviderType.java
│ │ │ └── SocketProviderInformation.java
│ │ └── request
│ │ │ ├── PackageInformationRequest.java
│ │ │ └── PaymentCreateRequest.java
│ └── donation
│ │ ├── Donation.java
│ │ ├── DonationPackage.java
│ │ └── DonationPlayer.java
│ ├── provider
│ ├── CraftingStoreProvider.java
│ ├── ProviderSelector.java
│ ├── ProviderStatus.java
│ └── SocketProvider.java
│ ├── runner
│ └── DonationRunner.java
│ ├── scheduler
│ ├── APICacheRenewer.java
│ ├── DonationChecker.java
│ ├── InformationUpdater.java
│ ├── InventoryRenewer.java
│ └── ProviderChecker.java
│ └── util
│ └── ArrayUtil.java
├── pom.xml
├── sponge
├── pom.xml
└── src
│ └── main
│ └── java
│ └── net
│ └── craftingstore
│ └── sponge
│ ├── CraftingStoreSponge.java
│ ├── CraftingStoreSpongeImpl.java
│ ├── SpongePluginConfiguration.java
│ ├── commands
│ ├── BuyCommand.java
│ └── CraftingStoreCommand.java
│ ├── config
│ └── Config.java
│ ├── events
│ └── DonationReceivedEvent.java
│ ├── inventory
│ ├── CraftingStoreInventoryProperty.java
│ ├── InventoryAttachment.java
│ ├── InventoryBuilder.java
│ ├── InventoryItemHandler.java
│ └── handlers
│ │ ├── BackButtonHandler.java
│ │ ├── CategoryItemHandler.java
│ │ ├── CloseButtonHandler.java
│ │ └── MessageButtonHandler.java
│ ├── listeners
│ ├── InventoryClickListener.java
│ └── PendingDonationJoinListener.java
│ ├── logging
│ └── Slf4jLogger.java
│ └── module
│ ├── ConfigModule.java
│ └── CraftingStoreModule.java
└── velocity
├── pom.xml
└── src
└── main
├── java
└── net
│ └── craftingstore
│ └── velocity
│ ├── CraftingStoreVelocity.java
│ ├── CraftingStoreVelocityImpl.java
│ ├── VelocityPluginConfiguration.java
│ ├── annotation
│ └── Prefix.java
│ ├── command
│ └── CraftingStoreCommand.java
│ ├── config
│ └── Config.java
│ ├── events
│ ├── DonationReceivedEvent.java
│ └── DonationResult.java
│ ├── listeners
│ └── PendingDonationJoinListener.java
│ ├── logging
│ └── Slf4jLogger.java
│ └── module
│ ├── ConfigModule.java
│ └── CraftingStoreModule.java
└── resources
└── config.json
/.gitignore:
--------------------------------------------------------------------------------
1 | ### Maven template
2 | target/
3 | pom.xml.tag
4 | pom.xml.releaseBackup
5 | pom.xml.versionsBackup
6 | pom.xml.next
7 | release.properties
8 | dependency-reduced-pom.xml
9 | buildNumber.properties
10 | .mvn/timing.properties
11 | .mvn/wrapper/maven-wrapper.jar
12 | .flattened-pom.xml
13 |
14 | # IntelliJ project files
15 | .idea
16 | *.iml
17 | out
18 | gen
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 CraftingStore.net
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/bukkit/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | net.craftingstore
9 | craftingstore
10 | ${revision}
11 |
12 |
13 | bukkit
14 |
15 |
16 |
17 | org.apache.maven.plugins
18 | maven-compiler-plugin
19 |
20 | 8
21 | 8
22 |
23 |
24 |
25 |
26 |
27 | src/main/resources
28 | true
29 |
30 |
31 |
32 |
33 |
34 |
35 | spigot-repo
36 | https://hub.spigotmc.org/nexus/content/repositories/snapshots/
37 |
38 |
39 |
40 | PlaceholderAPI
41 | https://repo.extendedclip.com/content/repositories/placeholderapi/
42 |
43 |
44 | razyr-dev
45 | https://rayzr.dev/repo/
46 |
47 |
48 | codemc
49 | https://repo.codemc.org/repository/maven-public
50 |
51 |
52 |
53 | jitpack.io
54 | https://jitpack.io
55 |
56 |
57 | papermc
58 | https://repo.papermc.io/repository/maven-public/
59 |
60 |
61 |
62 |
63 |
64 | net.craftingstore
65 | core
66 | ${project.version}
67 |
68 |
69 | io.papermc.paper
70 | paper-api
71 | 1.20.6-R0.1-SNAPSHOT
72 | provided
73 |
74 |
75 | net.md-5
76 | bungeecord-chat
77 | 1.20-R0.2
78 | provided
79 |
80 |
81 | me.clip
82 | placeholderapi
83 | 2.10.7
84 | provided
85 |
86 |
87 | com.github.cryptomorin
88 | XSeries
89 | 9.4.0
90 |
91 |
92 | com.github.MilkBowl
93 | VaultAPI
94 | 1.7
95 | provided
96 |
97 |
98 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/BukkitPluginConfiguration.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit;
2 |
3 | import net.craftingstore.core.PluginConfiguration;
4 |
5 | public class BukkitPluginConfiguration implements PluginConfiguration {
6 |
7 | private CraftingStoreBukkit plugin;
8 |
9 | BukkitPluginConfiguration(CraftingStoreBukkit plugin) {
10 | this.plugin = plugin;
11 | }
12 |
13 | @Override
14 | public String getName() {
15 | return "Bukkit";
16 | }
17 |
18 | @Override
19 | public String[] getMainCommands() {
20 | return new String[]{"craftingstore", "cs"};
21 | }
22 |
23 | @Override
24 | public String getVersion() {
25 | return plugin.getDescription().getVersion();
26 | }
27 |
28 | @Override
29 | public String getPlatform() {
30 | return plugin.getServer().getVersion();
31 | }
32 |
33 | @Override
34 | public boolean isBuyCommandEnabled() {
35 | return !plugin.getConfig().getBoolean("disable-buy-command", false);
36 | }
37 |
38 | @Override
39 | public int getTimeBetweenCommands() {
40 | return plugin.getConfig().getInt("time-between-commands", 200);
41 | }
42 |
43 | @Override
44 | public String getNotEnoughBalanceMessage() {
45 | 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:");
46 | }
47 |
48 | @Override
49 | public boolean isUsingAlternativeApi() {
50 | return plugin.getConfig().getBoolean("use-alternative-api", false);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/CraftingStoreBukkit.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit;
2 |
3 | import net.craftingstore.bukkit.commands.BuyCommand;
4 | import net.craftingstore.bukkit.commands.CraftingStoreCommand;
5 | import net.craftingstore.bukkit.config.Config;
6 | import net.craftingstore.bukkit.hooks.PlaceholderAPIHook;
7 | import net.craftingstore.bukkit.hooks.VaultHook;
8 | import net.craftingstore.bukkit.listeners.InventoryListener;
9 | import net.craftingstore.bukkit.listeners.AdminJoinListener;
10 | import net.craftingstore.bukkit.listeners.PendingDonationJoinListener;
11 | import net.craftingstore.bukkit.util.VersionUtil;
12 | import net.craftingstore.core.CraftingStore;
13 | import org.bukkit.Bukkit;
14 | import org.bukkit.ChatColor;
15 | import org.bukkit.configuration.file.FileConfiguration;
16 | import org.bukkit.plugin.java.JavaPlugin;
17 |
18 | public class CraftingStoreBukkit extends JavaPlugin {
19 |
20 | private CraftingStore craftingStore;
21 | private Config config;
22 | private String prefix = ChatColor.GRAY + "[" + ChatColor.RED + "CraftingStore" + ChatColor.GRAY + "] " + ChatColor.WHITE;
23 | private VaultHook vaultHook;
24 |
25 | @Override
26 | public void onEnable() {
27 | config = new Config("config.yml", this);
28 | this.craftingStore = new CraftingStore(new CraftingStoreBukkitImpl(this));
29 |
30 | this.getCommand("craftingstore").setExecutor(new CraftingStoreCommand(this));
31 | if (this.craftingStore.getImplementation().getConfiguration().isBuyCommandEnabled()) {
32 | this.getCommand("csbuy").setExecutor(new BuyCommand(this));
33 | }
34 |
35 | this.getServer().getPluginManager().registerEvents(new InventoryListener(this), this);
36 | this.getServer().getPluginManager().registerEvents(new AdminJoinListener(this), this);
37 | this.getServer().getPluginManager().registerEvents(new PendingDonationJoinListener(this), this);
38 |
39 | // PlaceholderAPI hook
40 | if (Bukkit.getPluginManager().isPluginEnabled("PlaceholderAPI")) {
41 | new PlaceholderAPIHook(craftingStore);
42 | craftingStore.getLogger().info("Hooked with PlaceholderAPI");
43 | }
44 | // Vault hook
45 | if (Bukkit.getPluginManager().isPluginEnabled("Vault")) {
46 | this.vaultHook = new VaultHook(this);
47 | if (this.vaultHook.register()) {
48 | craftingStore.getLogger().info("Hooked with Vault");
49 | } else {
50 | craftingStore.getLogger().info("There was a problem hooking with Vault");
51 | this.vaultHook = null;
52 | }
53 | }
54 | }
55 |
56 | @Override
57 | public void onDisable() {
58 | craftingStore.setEnabled(false);
59 | craftingStore.getLogger().debug("Shutdown complete");
60 | }
61 |
62 | public CraftingStore getCraftingStore() {
63 | return craftingStore;
64 | }
65 |
66 | @Override
67 | public FileConfiguration getConfig() {
68 | return this.config.getConfig();
69 | }
70 |
71 | public Config getConfigWrapper() {
72 | return this.config;
73 | }
74 |
75 | public String getPrefix() {
76 | return prefix;
77 | }
78 |
79 | public VaultHook getVaultHook() {
80 | return vaultHook;
81 | }
82 |
83 | public boolean isHookedWithVault() {
84 | return vaultHook != null;
85 | }
86 |
87 | public void runSyncTask(Runnable runnable) {
88 | if (VersionUtil.isFoliaSchedulerAvailable()) {
89 | this.getServer().getGlobalRegionScheduler().run(this, (task) -> runnable.run());
90 | } else {
91 | this.getServer().getScheduler().runTask(this, runnable);
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/CraftingStoreBukkitImpl.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit;
2 |
3 | import net.craftingstore.bukkit.events.DonationReceivedEvent;
4 | import net.craftingstore.bukkit.util.VersionUtil;
5 | import net.craftingstore.core.CraftingStorePlugin;
6 | import net.craftingstore.core.PluginConfiguration;
7 | import net.craftingstore.core.logging.CraftingStoreLogger;
8 | import net.craftingstore.core.logging.impl.JavaLogger;
9 | import net.craftingstore.core.models.donation.Donation;
10 | import org.bukkit.Bukkit;
11 | import org.bukkit.Server;
12 |
13 | import java.util.concurrent.TimeUnit;
14 |
15 |
16 | public class CraftingStoreBukkitImpl implements CraftingStorePlugin {
17 |
18 | private CraftingStoreBukkit bukkitPlugin;
19 | private JavaLogger logger;
20 | private PluginConfiguration pluginConfiguration;
21 |
22 | CraftingStoreBukkitImpl(CraftingStoreBukkit bukkitPlugin) {
23 | this.bukkitPlugin = bukkitPlugin;
24 | this.pluginConfiguration = new BukkitPluginConfiguration(bukkitPlugin);
25 | this.logger = new JavaLogger(bukkitPlugin.getLogger());
26 | this.logger.setDebugging(bukkitPlugin.getConfig().getBoolean("debug", false));
27 | }
28 |
29 | public boolean executeDonation(Donation donation) {
30 | if (donation.getPlayer().isRequiredOnline()) {
31 | if (Bukkit.getPlayerExact(donation.getPlayer().getUsername()) == null) {
32 | return false;
33 | }
34 | }
35 | Server server = this.bukkitPlugin.getServer();
36 |
37 | DonationReceivedEvent event = new DonationReceivedEvent(donation);
38 | server.getPluginManager().callEvent(event);
39 | if (event.isCancelled()) {
40 | return false;
41 | }
42 |
43 | this.bukkitPlugin.runSyncTask(() -> server.dispatchCommand(server.getConsoleSender(), donation.getCommand()));
44 | return true;
45 | }
46 |
47 | public CraftingStoreLogger getLogger() {
48 | return this.logger;
49 | }
50 |
51 | public void registerRunnable(Runnable runnable, int delay, int interval) {
52 | if (VersionUtil.isFoliaSchedulerAvailable()) {
53 | this.bukkitPlugin.getServer().getAsyncScheduler().runAtFixedRate(this.bukkitPlugin, task -> runnable.run(), delay, interval, TimeUnit.SECONDS);
54 | } else {
55 | this.bukkitPlugin.getServer().getScheduler().runTaskTimerAsynchronously(this.bukkitPlugin, runnable, delay * 20, interval * 20);
56 | }
57 | }
58 |
59 | public void runAsyncTask(Runnable runnable) {
60 | if (VersionUtil.isFoliaSchedulerAvailable()) {
61 | this.bukkitPlugin.getServer().getAsyncScheduler().runNow(this.bukkitPlugin, task -> runnable.run());
62 | } else {
63 | this.bukkitPlugin.getServer().getScheduler().runTaskAsynchronously(this.bukkitPlugin, runnable);
64 | }
65 | }
66 |
67 | public String getToken() {
68 | return bukkitPlugin.getConfig().getString("api-key");
69 | }
70 |
71 | @Override
72 | public PluginConfiguration getConfiguration() {
73 | return this.pluginConfiguration;
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/commands/BuyCommand.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.commands;
2 |
3 | import net.craftingstore.bukkit.CraftingStoreBukkit;
4 | import net.craftingstore.bukkit.inventory.InventoryBuilder;
5 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
6 | import net.craftingstore.core.models.api.ApiInventory;
7 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
8 | import org.bukkit.command.Command;
9 | import org.bukkit.command.CommandExecutor;
10 | import org.bukkit.command.CommandSender;
11 | import org.bukkit.entity.Player;
12 | import org.bukkit.inventory.Inventory;
13 |
14 | import java.util.concurrent.ExecutionException;
15 |
16 | public class BuyCommand implements CommandExecutor {
17 |
18 | private CraftingStoreBukkit instance;
19 |
20 | public BuyCommand(CraftingStoreBukkit instance) {
21 | this.instance = instance;
22 | }
23 |
24 | @Override
25 | public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
26 | if (!(sender instanceof Player)) {
27 | return false;
28 | }
29 | if (!this.instance.getCraftingStore().isEnabled()) {
30 | sender.sendMessage(instance.getPrefix() + "The plugin has not been set-up correctly. Please contact an administrator.");
31 | return false;
32 | }
33 | Player p = (Player) sender;
34 | this.instance.getCraftingStore().getImplementation().runAsyncTask(() -> {
35 | try {
36 | InventoryBuilder builder = new InventoryBuilder(this.instance);
37 | ApiInventory gui = instance.getCraftingStore().getApi().getGUI().get();
38 | Inventory inventory = builder.buildInventory(
39 | new CraftingStoreInventory(gui.getTitle(), gui.getContent(), gui.getSize())
40 | );
41 | this.instance.runSyncTask(() -> {
42 | if (p.isOnline()) {
43 | p.openInventory(inventory);
44 | }
45 | });
46 | } catch (CraftingStoreApiException | InterruptedException | ExecutionException e) {
47 | e.printStackTrace();
48 | }
49 | });
50 | return true;
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/commands/CraftingStoreCommand.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.commands;
2 |
3 | import net.craftingstore.bukkit.CraftingStoreBukkit;
4 | import org.bukkit.Bukkit;
5 | import org.bukkit.ChatColor;
6 | import org.bukkit.command.Command;
7 | import org.bukkit.command.CommandExecutor;
8 | import org.bukkit.command.CommandSender;
9 |
10 | import java.util.concurrent.ExecutionException;
11 |
12 | public class CraftingStoreCommand implements CommandExecutor {
13 |
14 | private CraftingStoreBukkit instance;
15 |
16 | public CraftingStoreCommand(CraftingStoreBukkit instance) {
17 | this.instance = instance;
18 | }
19 |
20 | @Override
21 | public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
22 | if (!sender.hasPermission(instance.getCraftingStore().ADMIN_PERMISSION)) {
23 | sender.sendMessage(instance.getPrefix() + "You don't have the required permission!");
24 | return false;
25 | }
26 | if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
27 | instance.getCraftingStore().reload();
28 | sender.sendMessage(instance.getPrefix() + "The plugin is reloading!");
29 | return true;
30 | }
31 | if (args.length == 2 && args[0].equalsIgnoreCase("key")) {
32 | instance.getConfig().set("api-key", args[1]);
33 | instance.getConfigWrapper().saveConfig();
34 | instance.getServer().getScheduler().runTaskAsynchronously(instance, () -> {
35 | try {
36 | if (instance.getCraftingStore().reload().get()) {
37 | sender.sendMessage(instance.getPrefix() + "The new API key has been set in the config, and the plugin has been reloaded.");
38 | } else {
39 | sender.sendMessage(instance.getPrefix() + "The API key is invalid. The plugin will not work until you set a valid API key.");
40 | }
41 | } catch (InterruptedException | ExecutionException e) {
42 | e.printStackTrace();
43 | }
44 | });
45 | return true;
46 | }
47 | if ((args.length == 1 || args.length == 2) && args[0].equalsIgnoreCase("debug")) {
48 | boolean isDebugging = this.instance.getCraftingStore().getLogger().isDebugging();
49 | if (args.length == 1) {
50 | sender.sendMessage(String.format(
51 | "%sDebug mode is currently %s.",
52 | this.instance.getPrefix(),
53 | isDebugging ? "enabled" : "disabled"
54 | ));
55 | return true;
56 | }
57 | String debugValue = args[1].toLowerCase();
58 | if (debugValue.equalsIgnoreCase("true")) {
59 | isDebugging = true;
60 | } else if (debugValue.equalsIgnoreCase("false")) {
61 | isDebugging = false;
62 | } else {
63 | sender.sendMessage(instance.getPrefix() + "Unknown debug value.");
64 | return true;
65 | }
66 | this.instance.getCraftingStore().getLogger().setDebugging(isDebugging);
67 | instance.getConfig().set("debug", isDebugging);
68 | instance.getConfigWrapper().saveConfig();
69 | sender.sendMessage(String.format(
70 | "%sDebug mode has been %s.",
71 | this.instance.getPrefix(),
72 | isDebugging ? "enabled" : "disabled"
73 | ));
74 | return true;
75 | }
76 |
77 | sender.sendMessage(ChatColor.GRAY + "" +ChatColor.STRIKETHROUGH + "-----------------------");
78 | sender.sendMessage(ChatColor.DARK_GRAY + ">" + ChatColor.GRAY + " /" + label + " reload" + ChatColor.DARK_GRAY + " -> " + ChatColor.GRAY + "Reload the config.");
79 | sender.sendMessage(ChatColor.DARK_GRAY + ">" + ChatColor.GRAY + " /" + label + " key " + ChatColor.DARK_GRAY + " -> " + ChatColor.GRAY + "Update the key.");
80 | sender.sendMessage(ChatColor.GRAY + "" +ChatColor.STRIKETHROUGH + "-----------------------");
81 | return true;
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/config/Config.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.config;
2 |
3 | import org.bukkit.configuration.file.FileConfiguration;
4 | import org.bukkit.configuration.file.YamlConfiguration;
5 | import org.bukkit.plugin.Plugin;
6 |
7 | import java.io.*;
8 | import java.nio.charset.StandardCharsets;
9 | import java.util.logging.Level;
10 |
11 | public class Config {
12 |
13 | private Plugin instance;
14 | private FileConfiguration config = null;
15 | private File configFile = null;
16 | private String filename;
17 |
18 | /**
19 | * Create a new instance of Config, specifying a file name and Plugin.
20 | *
21 | * @param filename the file name, including .yml
22 | * @param instance the instance
23 | */
24 | public Config(String filename, Plugin instance) {
25 | this.filename = filename;
26 | this.instance = instance;
27 |
28 | reload();
29 |
30 | File file = new File(instance.getDataFolder() + File.pathSeparator + filename);
31 | if (!file.exists()) {
32 | if (instance.getResource(filename) != null) {
33 | Reader defaultConfigFile = new InputStreamReader(instance.getResource(filename), StandardCharsets.UTF_8);
34 | YamlConfiguration defConfig = YamlConfiguration.loadConfiguration(defaultConfigFile);
35 | config.setDefaults(defConfig);
36 | config.options().copyDefaults(true);
37 | saveConfig();
38 | }
39 | }
40 | }
41 |
42 | /**
43 | * Reload the config.
44 | */
45 | public void reload() {
46 | if (configFile == null) {
47 | configFile = new File(instance.getDataFolder(), filename);
48 | }
49 | config = YamlConfiguration.loadConfiguration(configFile);
50 | }
51 |
52 | /**
53 | * Get the FileConfiguration associated with this Config.
54 | *
55 | * @return the FileConfiguration
56 | */
57 | public FileConfiguration getConfig() {
58 | if (configFile == null) {
59 | reload();
60 | }
61 | return config;
62 | }
63 |
64 | /**
65 | * Save all changes to the disk.
66 | */
67 | public void saveConfig() {
68 | if (config == null || configFile == null) {
69 | return;
70 | }
71 |
72 | try {
73 | getConfig().save(configFile);
74 | } catch (IOException e) {
75 | instance.getLogger().log(Level.SEVERE, "An error occurred while saving the config file " + filename + ".", e);
76 | }
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/events/DonationReceivedEvent.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.events;
2 |
3 | import net.craftingstore.core.models.donation.Donation;
4 | import org.bukkit.event.Cancellable;
5 | import org.bukkit.event.Event;
6 | import org.bukkit.event.HandlerList;
7 |
8 | import java.util.UUID;
9 |
10 | public class DonationReceivedEvent extends Event implements Cancellable {
11 |
12 | @Deprecated
13 | private String command;
14 | @Deprecated
15 | private String username;
16 | @Deprecated
17 | private UUID uuid;
18 | @Deprecated
19 | private String packageName;
20 | @Deprecated
21 | private int packagePrice;
22 | @Deprecated
23 | private int couponDiscount;
24 |
25 | private Donation donation;
26 |
27 | private boolean cancelled = false;
28 |
29 | @Deprecated
30 | public DonationReceivedEvent(String command, String username, UUID uuid, String packageName, int packagePrice, int couponDiscount) {
31 | super(true);
32 | this.command = command;
33 | this.username = username;
34 | this.uuid = uuid;
35 | this.packageName = packageName;
36 | this.packagePrice = packagePrice;
37 | this.couponDiscount = couponDiscount;
38 | }
39 |
40 | public DonationReceivedEvent(Donation donation) {
41 | super(true);
42 | this.command = donation.getCommand();
43 | this.username = donation.getPlayer().getUsername();
44 | this.uuid = donation.getPlayer().getUUID();
45 | this.packageName = donation.getPackage().getName();
46 | this.packagePrice = donation.getPackage().getPrice();
47 | this.couponDiscount = donation.getDiscount();
48 | this.donation = donation;
49 | }
50 |
51 | public Donation getDonation() {
52 | return this.donation;
53 | }
54 |
55 | @Deprecated
56 | public String getCommand() {
57 | return command;
58 | }
59 |
60 | @Deprecated
61 | public String getUsername() {
62 | return username;
63 | }
64 |
65 | @Deprecated
66 | public UUID getUuid() {
67 | return uuid;
68 | }
69 |
70 | @Deprecated
71 | public String getPackageName() {
72 | return packageName;
73 | }
74 |
75 | @Deprecated
76 | public int getPackagePrice() {
77 | return packagePrice;
78 | }
79 |
80 | @Deprecated
81 | public int getCouponDiscount() {
82 | return couponDiscount;
83 | }
84 |
85 | public boolean isCancelled() {
86 | return cancelled;
87 | }
88 |
89 | public void setCancelled(boolean cancelled) {
90 | this.cancelled = cancelled;
91 | }
92 |
93 | private static final HandlerList handlers = new HandlerList();
94 |
95 | public HandlerList getHandlers() {
96 | return handlers;
97 | }
98 |
99 | public static HandlerList getHandlerList() {
100 | return handlers;
101 | }
102 |
103 | }
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/hooks/PlaceholderAPIHook.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.hooks;
2 |
3 | import me.clip.placeholderapi.expansion.PlaceholderExpansion;
4 | import net.craftingstore.core.CraftingStore;
5 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
6 | import net.craftingstore.core.models.api.ApiPayment;
7 | import net.craftingstore.core.models.api.ApiTopDonator;
8 | import org.bukkit.OfflinePlayer;
9 |
10 | import java.util.concurrent.ExecutionException;
11 | import java.util.regex.Matcher;
12 | import java.util.regex.Pattern;
13 |
14 | public class PlaceholderAPIHook extends PlaceholderExpansion {
15 |
16 | private CraftingStore instance;
17 |
18 | public PlaceholderAPIHook(CraftingStore instance) {
19 | this.instance = instance;
20 | this.register(); // Documentation is missing so we are using this method.
21 | }
22 |
23 | @Override
24 | public String onRequest(OfflinePlayer player, String s) {
25 | try {
26 | if (s.startsWith("donator")) {
27 | return handleDonators(player, s);
28 | } else if (s.startsWith("payment")) {
29 | return handlePayments(player, s);
30 | }
31 | } catch (CraftingStoreApiException | ExecutionException | InterruptedException e) {
32 | e.printStackTrace();
33 | }
34 |
35 | return null;
36 | }
37 |
38 | private String handleDonators(OfflinePlayer player, String s) throws CraftingStoreApiException, ExecutionException, InterruptedException {
39 | ApiTopDonator[] topDonators = instance.getApi().getTopDonators().get();
40 | if (topDonators == null) {
41 | return ""; // Donators are not retrieved yet.
42 | } else if (s.equalsIgnoreCase("donator")) {
43 | StringBuilder builder = new StringBuilder();
44 | for (ApiTopDonator donator : topDonators) {
45 | builder.append(donator.getUsername()).append(": ").append(donator.getTotal()).append(", ");
46 | }
47 | builder.substring(0, builder.length() - 2); // Remove the last ', ' from the string
48 | return builder.toString();
49 | } else if (s.startsWith("donator_")) {
50 | Pattern pattern = Pattern.compile("donator_([1-5])");
51 | Matcher matcher = pattern.matcher(s);
52 | if (matcher.matches()) {
53 | int id = Integer.parseInt(matcher.group(1));
54 | if (topDonators.length >= id) {
55 | id--; // Zero based array
56 | ApiTopDonator donator = topDonators[id];
57 | return donator.getUsername() + ": " + donator.getTotal();
58 | }
59 | }
60 | }
61 | return "";
62 | }
63 |
64 | private String handlePayments(OfflinePlayer player, String s) throws CraftingStoreApiException, ExecutionException, InterruptedException {
65 | ApiPayment[] payments = instance.getApi().getPayments().get();
66 | if (payments == null || payments.length == 0) {
67 | return ""; // Recent payments are not retrieved yet or there are no payments.
68 | } else if (s.equalsIgnoreCase("payment")) {
69 | StringBuilder builder = new StringBuilder();
70 | for (ApiPayment payment : payments) {
71 | builder.append(payment.getUsername()).append(": ").append(payment.getPackageName()).append(", ");
72 | }
73 | builder.substring(0, builder.length() - 2); // Remove the last ', ' from the string
74 | return builder.toString();
75 | } else if (s.startsWith("payment_")) {
76 | Pattern pattern = Pattern.compile("payment_([1-5])");
77 | Matcher matcher = pattern.matcher(s);
78 | if (matcher.matches()) {
79 | int id = Integer.parseInt(matcher.group(1));
80 | if (payments.length >= id) {
81 | id--; // Zero based array
82 | ApiPayment payment = payments[id];
83 | return payment.getUsername() + ": " + payment.getPackageName();
84 | }
85 | }
86 | }
87 | return "";
88 | }
89 |
90 | @Override
91 | public String getIdentifier() {
92 | return "craftingstore";
93 | }
94 |
95 | @Override
96 | public String getAuthor() {
97 | return "CraftingStore";
98 | }
99 |
100 | @Override
101 | public String getVersion() {
102 | return this.instance.getImplementation().getConfiguration().getVersion();
103 | }
104 |
105 | @Override
106 | public boolean persist() {
107 | return true;
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/hooks/VaultHook.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.hooks;
2 |
3 | import net.craftingstore.bukkit.CraftingStoreBukkit;
4 | import net.milkbowl.vault.economy.Economy;
5 | import org.bukkit.plugin.RegisteredServiceProvider;
6 |
7 | public class VaultHook {
8 | private final CraftingStoreBukkit instance;
9 | private Economy economy;
10 |
11 | public VaultHook(CraftingStoreBukkit instance) {
12 | this.instance = instance;
13 | }
14 |
15 | public boolean register() {
16 | RegisteredServiceProvider rsp = instance.getServer().getServicesManager().getRegistration(Economy.class);
17 | if (rsp == null) {
18 | return false;
19 | }
20 | this.economy = rsp.getProvider();
21 | return true;
22 | }
23 |
24 | public Economy getEconomy() {
25 | return economy;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/BuyInventoryBuilder.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory;
2 |
3 | import net.craftingstore.bukkit.CraftingStoreBukkit;
4 | import net.craftingstore.bukkit.util.ChatColorUtil;
5 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
6 | import net.craftingstore.core.models.api.ApiInventory;
7 | import net.craftingstore.core.models.api.ApiPackageInformation;
8 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
9 | import net.craftingstore.core.models.api.inventory.InventoryItem;
10 | import net.craftingstore.core.models.api.inventory.InventoryItemIcon;
11 | import net.craftingstore.core.models.api.inventory.InventoryItemType;
12 | import net.craftingstore.core.models.api.inventory.types.InventoryItemBuyablePackage;
13 | import org.bukkit.entity.Player;
14 | import org.bukkit.inventory.Inventory;
15 |
16 | import java.util.HashMap;
17 | import java.util.Map;
18 | import java.util.concurrent.ExecutionException;
19 |
20 | public class BuyInventoryBuilder {
21 |
22 | private final CraftingStoreBukkit instance;
23 | private final InventoryBuilder inventoryBuilder;
24 |
25 | public BuyInventoryBuilder(CraftingStoreBukkit instance, InventoryBuilder inventoryBuilder) {
26 | this.instance = instance;
27 | this.inventoryBuilder = inventoryBuilder;
28 | }
29 |
30 | public Inventory build(Player p, InventoryItemBuyablePackage item, CraftingStoreInventoryHolder holder) throws CraftingStoreApiException, ExecutionException, InterruptedException {
31 | ApiInventory buyMenu = this.instance.getCraftingStore().getApi().getGUI().get().getBuyMenu();
32 | CraftingStoreInventory craftingStoreInventory = new CraftingStoreInventory(buyMenu.getTitle(), buyMenu.getContent(), buyMenu.getSize());
33 |
34 | String ip = p.getAddress().getAddress().getHostAddress();
35 | ApiPackageInformation packageInformation = this.instance.getCraftingStore().getApi().getPackageInformation(
36 | p.getName(),
37 | p.getUniqueId(),
38 | ip,
39 | item.getPackageId()
40 | ).get();
41 | if (!packageInformation.isAllowedToBuy()) {
42 | p.sendMessage(ChatColorUtil.translate(packageInformation.getMessage()));
43 | this.closeInventory(p);
44 | return null;
45 | }
46 | if (packageInformation.getPrice() != item.getPrice()) {
47 | p.sendMessage(this.instance.getPrefix() + "There was a problem with the payment data. Please try again later.");
48 | this.closeInventory(p);
49 | return null;
50 | }
51 |
52 | Map placeholders = new HashMap<>();
53 | placeholders.put("package_name", item.getName());
54 | placeholders.put("package_price_ingame", packageInformation.getPrice());
55 | return this.inventoryBuilder.buildInventory(
56 | craftingStoreInventory,
57 | new BuyMenuInventoryHolder(craftingStoreInventory, holder, item),
58 | placeholders
59 | );
60 | }
61 |
62 | public Inventory buildLoadInventory() {
63 | InventoryItemIcon icon = new InventoryItemIcon("LIGHT_BLUE_STAINED_GLASS_PANE", 1, 0, null);
64 | InventoryItem[] content = new InventoryItem[9];
65 | for (int i = 0; i < 9; i++) {
66 | content[i] = new InventoryItem("Loading...", null, InventoryItemType.NULL, icon, i);
67 | }
68 |
69 | CraftingStoreInventory craftingStoreInventory = new CraftingStoreInventory(
70 | "Loading...",
71 | content,
72 | 9
73 | );
74 | return this.inventoryBuilder.buildInventory(
75 | craftingStoreInventory,
76 | new CraftingStoreInventoryHolder(craftingStoreInventory, null)
77 | );
78 | }
79 |
80 | private void closeInventory(Player p) {
81 | this.instance.runSyncTask(() -> {
82 | if (p.isOnline()) {
83 | p.closeInventory();
84 | }
85 | });
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/BuyMenuInventoryHolder.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory;
2 |
3 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
4 | import net.craftingstore.core.models.api.inventory.types.InventoryItemBuyablePackage;
5 |
6 | public class BuyMenuInventoryHolder extends CraftingStoreInventoryHolder {
7 |
8 | private final InventoryItemBuyablePackage itemBuyablePackage;
9 |
10 | public BuyMenuInventoryHolder(
11 | CraftingStoreInventory csInventory,
12 | CraftingStoreInventoryHolder parentInventory,
13 | InventoryItemBuyablePackage itemBuyablePackage
14 | ) {
15 | super(csInventory, parentInventory);
16 | this.itemBuyablePackage = itemBuyablePackage;
17 | }
18 |
19 | public InventoryItemBuyablePackage getItemBuyablePackage() {
20 | return itemBuyablePackage;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/CraftingStoreInventoryHolder.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory;
2 |
3 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
4 | import org.bukkit.inventory.Inventory;
5 | import org.bukkit.inventory.InventoryHolder;
6 |
7 | public class CraftingStoreInventoryHolder implements InventoryHolder {
8 |
9 | private CraftingStoreInventory csInventory;
10 | private CraftingStoreInventoryHolder parentInventory;
11 |
12 | public CraftingStoreInventoryHolder(CraftingStoreInventory csInventory, CraftingStoreInventoryHolder parentInventory) {
13 | this.csInventory = csInventory;
14 | this.parentInventory = parentInventory;
15 | }
16 |
17 | @Override
18 | public Inventory getInventory() {
19 | return null;
20 | }
21 |
22 | public CraftingStoreInventory getCsInventory() {
23 | return csInventory;
24 | }
25 |
26 | public CraftingStoreInventoryHolder getParentInventory() {
27 | return parentInventory;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/InventoryBuilder.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory;
2 |
3 | import net.craftingstore.bukkit.CraftingStoreBukkit;
4 | import net.craftingstore.bukkit.util.ChatColorUtil;
5 | import net.craftingstore.bukkit.util.VersionUtil;
6 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
7 | import net.craftingstore.core.models.api.inventory.InventoryItem;
8 | import org.apache.commons.text.StringSubstitutor;
9 | import org.bukkit.Bukkit;
10 | import org.bukkit.inventory.Inventory;
11 | import org.bukkit.inventory.ItemStack;
12 | import org.bukkit.inventory.meta.ItemMeta;
13 |
14 | import java.util.Arrays;
15 | import java.util.HashMap;
16 | import java.util.Map;
17 | import java.util.stream.Collectors;
18 |
19 | public class InventoryBuilder {
20 |
21 | private final CraftingStoreBukkit instance;
22 | private final InventoryItemBuilder inventoryItemBuilder;
23 |
24 | public InventoryBuilder(CraftingStoreBukkit instance) {
25 | this.instance = instance;
26 | this.inventoryItemBuilder = new InventoryItemBuilder(instance);
27 | }
28 |
29 | public Inventory buildInventory(CraftingStoreInventory csInventory) {
30 | return buildInventory(csInventory, new CraftingStoreInventoryHolder(csInventory, null));
31 | }
32 |
33 | public Inventory buildInventory(CraftingStoreInventory csInventory, CraftingStoreInventoryHolder holder) {
34 | return buildInventory(csInventory, holder, new HashMap<>());
35 | }
36 |
37 | public Inventory buildInventory(CraftingStoreInventory csInventory, CraftingStoreInventoryHolder holder, Map placeholders) {
38 | String title = csInventory.getTitle();
39 | if (title == null || title.isEmpty()) {
40 | title = "CraftingStore";
41 | }
42 |
43 | StringSubstitutor stringSubstitutor = new StringSubstitutor(placeholders, "{", "}");
44 | title = ChatColorUtil.translate(stringSubstitutor.replace(title));
45 | Inventory inventory = Bukkit.createInventory(holder, csInventory.getSize(), title);
46 |
47 | for (InventoryItem inventoryItem : csInventory.getContent()) {
48 | ItemStack itemStack = this.inventoryItemBuilder.getItemStack(inventoryItem.getIcon().getMaterial(), inventoryItem.getIcon().getAmount());
49 | ItemMeta meta = itemStack.getItemMeta();
50 | if (meta != null) {
51 | meta.setDisplayName(ChatColorUtil.translate(stringSubstitutor.replace(inventoryItem.getName())));
52 | if (inventoryItem.getDescription() != null && inventoryItem.getDescription().length != 0) {
53 | meta.setLore(Arrays.stream(inventoryItem.getDescription())
54 | .map(stringSubstitutor::replace)
55 | .map(ChatColorUtil::translate)
56 | .collect(Collectors.toList())
57 | );
58 | }
59 | if (VersionUtil.isCustomModalDataAvailable() && inventoryItem.getIcon().getCustomModelData() != null) {
60 | meta.setCustomModelData(inventoryItem.getIcon().getCustomModelData());
61 | }
62 | itemStack.setItemMeta(meta);
63 | }
64 | inventory.setItem(inventoryItem.getIndex(), itemStack);
65 | }
66 |
67 | return inventory;
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/InventoryItemBuilder.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory;
2 |
3 | import com.cryptomorin.xseries.XMaterial;
4 | import net.craftingstore.bukkit.CraftingStoreBukkit;
5 | import net.craftingstore.bukkit.util.VersionUtil;
6 | import org.bukkit.Material;
7 | import org.bukkit.inventory.ItemStack;
8 |
9 | import java.util.Optional;
10 |
11 | public class InventoryItemBuilder {
12 |
13 | private CraftingStoreBukkit instance;
14 |
15 | public InventoryItemBuilder(CraftingStoreBukkit instance) {
16 | this.instance = instance;
17 | }
18 |
19 | public ItemStack getItemStack(String material, int amount) {
20 | ItemStack itemStack;
21 | if (VersionUtil.isGuavaAvailable()) {
22 | // 1.8+
23 | com.cryptomorin.xseries.XMaterial xMaterial;
24 | if (material == null) {
25 | xMaterial = com.cryptomorin.xseries.XMaterial.CHEST;
26 | } else {
27 | Optional xMaterialOptional = com.cryptomorin.xseries.XMaterial.matchXMaterial(material);
28 | if (!xMaterialOptional.isPresent()) {
29 | instance.getCraftingStore().getLogger().debug("Material " + material + " not found.");
30 | xMaterial = com.cryptomorin.xseries.XMaterial.CHEST;
31 | } else {
32 | xMaterial = xMaterialOptional.get();
33 | }
34 | }
35 | itemStack = xMaterial.parseItem();
36 | if (itemStack == null) {
37 | itemStack = new ItemStack(Material.CHEST);
38 | }
39 | itemStack.setAmount(amount);
40 | } else {
41 | // 1.7 support
42 | net.craftingstore.bukkit.util.XMaterial xMaterial;
43 | if (material == null) {
44 | xMaterial = net.craftingstore.bukkit.util.XMaterial.CHEST;
45 | } else {
46 | xMaterial = net.craftingstore.bukkit.util.XMaterial.fromString(material);
47 | if (xMaterial == null || xMaterial.parseMaterial() == null) {
48 | instance.getCraftingStore().getLogger().debug("Material " + material + " not found.");
49 | xMaterial = net.craftingstore.bukkit.util.XMaterial.CHEST;
50 | }
51 | }
52 | itemStack = xMaterial.parseItem(amount);
53 | }
54 | return itemStack;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/InventoryItemHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory;
2 |
3 | import net.craftingstore.core.models.api.inventory.InventoryItem;
4 | import org.bukkit.entity.Player;
5 |
6 | public interface InventoryItemHandler {
7 | void handle(Player p, T item, CraftingStoreInventoryHolder holder);
8 | }
9 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/handlers/BackButtonHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory.handlers;
2 |
3 | import net.craftingstore.bukkit.inventory.CraftingStoreInventoryHolder;
4 | import net.craftingstore.bukkit.inventory.InventoryBuilder;
5 | import net.craftingstore.bukkit.inventory.InventoryItemHandler;
6 | import net.craftingstore.core.models.api.inventory.types.InventoryItemBackButton;
7 | import org.bukkit.entity.Player;
8 | import org.bukkit.inventory.Inventory;
9 |
10 | public class BackButtonHandler implements InventoryItemHandler {
11 |
12 | private InventoryBuilder builder;
13 |
14 | public BackButtonHandler(InventoryBuilder builder) {
15 | this.builder = builder;
16 | }
17 |
18 | @Override
19 | public void handle(Player p, InventoryItemBackButton item, CraftingStoreInventoryHolder holder) {
20 | if (holder.getParentInventory() != null) {
21 | CraftingStoreInventoryHolder parentInventory = holder.getParentInventory();
22 | Inventory inventory = builder.buildInventory(
23 | parentInventory.getCsInventory(),
24 | new CraftingStoreInventoryHolder(parentInventory.getCsInventory(), parentInventory.getParentInventory())
25 | );
26 | p.openInventory(inventory);
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/handlers/BuyablePackageHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory.handlers;
2 |
3 | import net.craftingstore.bukkit.CraftingStoreBukkit;
4 | import net.craftingstore.bukkit.inventory.*;
5 | import net.craftingstore.bukkit.util.ChatColorUtil;
6 | import net.craftingstore.core.models.api.inventory.types.InventoryItemBuyablePackage;
7 | import org.bukkit.entity.Player;
8 | import org.bukkit.inventory.Inventory;
9 |
10 | public class BuyablePackageHandler implements InventoryItemHandler {
11 |
12 | private final CraftingStoreBukkit instance;
13 | private final BuyInventoryBuilder buyInventoryBuilder;
14 |
15 | public BuyablePackageHandler(CraftingStoreBukkit instance, BuyInventoryBuilder buyInventoryBuilder) {
16 | this.instance = instance;
17 | this.buyInventoryBuilder = buyInventoryBuilder;
18 | }
19 |
20 | @Override
21 | public void handle(Player p, InventoryItemBuyablePackage item, CraftingStoreInventoryHolder holder) {
22 | if (!this.instance.isHookedWithVault()) {
23 | p.sendMessage(instance.getPrefix() + "CraftingStore is not hooked with Vault!");
24 | p.closeInventory();
25 | return;
26 | }
27 |
28 | if (!this.instance.getVaultHook().getEconomy().has(p, item.getPrice())) {
29 | p.sendMessage(ChatColorUtil.translate(
30 | this.instance.getCraftingStore().getImplementation().getConfiguration().getNotEnoughBalanceMessage()
31 | ));
32 | for (String message : item.getMessages()) {
33 | p.sendMessage(ChatColorUtil.translate(message));
34 | }
35 | p.closeInventory();
36 | return;
37 | }
38 |
39 | Inventory loading = this.buyInventoryBuilder.buildLoadInventory();
40 | p.openInventory(loading);
41 | this.instance.getCraftingStore().getImplementation().runAsyncTask(() -> {
42 | try {
43 | Inventory inventory = this.buyInventoryBuilder.build(p, item, holder);
44 | if (inventory != null) {
45 | this.instance.runSyncTask(() -> {
46 | if (p.isOnline()) {
47 | p.openInventory(inventory);
48 | }
49 | });
50 | }
51 | } catch (Exception exception) {
52 | exception.printStackTrace();
53 | }
54 | });
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/handlers/CategoryItemHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory.handlers;
2 |
3 | import net.craftingstore.bukkit.inventory.CraftingStoreInventoryHolder;
4 | import net.craftingstore.bukkit.inventory.InventoryBuilder;
5 | import net.craftingstore.bukkit.inventory.InventoryItemHandler;
6 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
7 | import net.craftingstore.core.models.api.inventory.types.InventoryItemCategory;
8 | import org.bukkit.entity.Player;
9 | import org.bukkit.inventory.Inventory;
10 |
11 | public class CategoryItemHandler implements InventoryItemHandler {
12 |
13 | private InventoryBuilder builder;
14 |
15 | public CategoryItemHandler(InventoryBuilder builder) {
16 | this.builder = builder;
17 | }
18 |
19 | @Override
20 | public void handle(Player p, InventoryItemCategory category, CraftingStoreInventoryHolder holder) {
21 | CraftingStoreInventory csInventory = new CraftingStoreInventory(category.getTitle(), category.getContent(), category.getSize());
22 | Inventory inventory = builder.buildInventory(csInventory, new CraftingStoreInventoryHolder(csInventory, holder));
23 | p.openInventory(inventory);
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/handlers/CloseButtonHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory.handlers;
2 |
3 | import net.craftingstore.bukkit.inventory.CraftingStoreInventoryHolder;
4 | import net.craftingstore.bukkit.inventory.InventoryItemHandler;
5 | import net.craftingstore.core.models.api.inventory.types.InventoryItemCloseButton;
6 | import org.bukkit.entity.Player;
7 |
8 | public class CloseButtonHandler implements InventoryItemHandler {
9 | @Override
10 | public void handle(Player p, InventoryItemCloseButton item, CraftingStoreInventoryHolder holder) {
11 | p.closeInventory();
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/inventory/handlers/MessageButtonHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.inventory.handlers;
2 |
3 | import net.craftingstore.bukkit.inventory.CraftingStoreInventoryHolder;
4 | import net.craftingstore.bukkit.inventory.InventoryItemHandler;
5 | import net.craftingstore.bukkit.util.ChatColorUtil;
6 | import net.craftingstore.core.models.api.inventory.types.InventoryItemMessage;
7 | import org.bukkit.entity.Player;
8 |
9 | public class MessageButtonHandler implements InventoryItemHandler {
10 | @Override
11 | public void handle(Player p, InventoryItemMessage item, CraftingStoreInventoryHolder holder) {
12 | for (String message : item.getMessages()) {
13 | p.sendMessage(ChatColorUtil.translate(message));
14 | }
15 | if (item.shouldClose()) {
16 | p.closeInventory();
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/listeners/AdminJoinListener.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.listeners;
2 |
3 | import net.craftingstore.bukkit.CraftingStoreBukkit;
4 | import net.craftingstore.core.models.api.misc.CraftingStoreInformation;
5 | import net.craftingstore.core.models.api.misc.UpdateInformation;
6 | import org.bukkit.entity.Player;
7 | import org.bukkit.event.EventHandler;
8 | import org.bukkit.event.Listener;
9 | import org.bukkit.event.player.PlayerJoinEvent;
10 |
11 | public class AdminJoinListener implements Listener {
12 |
13 | private CraftingStoreBukkit instance;
14 |
15 | public AdminJoinListener(CraftingStoreBukkit instance) {
16 | this.instance = instance;
17 | }
18 |
19 | @EventHandler
20 | public void onPlayerJoin(PlayerJoinEvent e) {
21 | Player p = e.getPlayer();
22 | if (!p.hasPermission(instance.getCraftingStore().ADMIN_PERMISSION)) {
23 | return;
24 | }
25 | CraftingStoreInformation information = instance.getCraftingStore().getInformation();
26 | UpdateInformation update = null;
27 | if (information != null) {
28 | update = information.getUpdateInformation();
29 |
30 | // Update notification
31 | if (update != null) {
32 | p.sendMessage(instance.getPrefix() + update.getMessage());
33 | }
34 | }
35 |
36 | if (!instance.getCraftingStore().isEnabled()) {
37 | if (update != null && update.shouldDisable()) {
38 | p.sendMessage(instance.getPrefix() + "The CraftingStore plugin has been disabled because this is an outdated version. Please update the plugin.");
39 | } else {
40 | p.sendMessage(instance.getPrefix() + "The CraftingStore plugin has not been set-up correctly. Please set your API key using /craftingstore key .");
41 | }
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/listeners/InventoryListener.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.listeners;
2 |
3 | import net.craftingstore.bukkit.CraftingStoreBukkit;
4 | import net.craftingstore.bukkit.inventory.BuyInventoryBuilder;
5 | import net.craftingstore.bukkit.inventory.CraftingStoreInventoryHolder;
6 | import net.craftingstore.bukkit.inventory.InventoryBuilder;
7 | import net.craftingstore.bukkit.inventory.InventoryItemHandler;
8 | import net.craftingstore.bukkit.inventory.handlers.*;
9 | import net.craftingstore.core.models.api.inventory.*;
10 | import net.craftingstore.core.models.api.inventory.types.*;
11 | import org.bukkit.entity.Player;
12 | import org.bukkit.event.EventHandler;
13 | import org.bukkit.event.Listener;
14 | import org.bukkit.event.inventory.InventoryClickEvent;
15 |
16 | import java.util.HashMap;
17 |
18 | public class InventoryListener implements Listener {
19 |
20 | private final HashMap, InventoryItemHandler> handlers = new HashMap<>();
21 |
22 | private final CraftingStoreBukkit instance;
23 | private final InventoryBuilder inventoryBuilder;
24 |
25 | public InventoryListener(CraftingStoreBukkit instance) {
26 | this.instance = instance;
27 | this.inventoryBuilder = new InventoryBuilder(instance);
28 | BuyInventoryBuilder buyInventoryBuilder = new BuyInventoryBuilder(instance, this.inventoryBuilder);
29 | this.handlers.put(InventoryItemBackButton.class, new BackButtonHandler(this.inventoryBuilder));
30 | this.handlers.put(InventoryItemCategory.class, new CategoryItemHandler(this.inventoryBuilder));
31 | this.handlers.put(InventoryItemCloseButton.class, new CloseButtonHandler());
32 | this.handlers.put(InventoryItemMessage.class, new MessageButtonHandler());
33 | this.handlers.put(InventoryItemBuyablePackage.class, new BuyablePackageHandler(
34 | instance,
35 | buyInventoryBuilder
36 | ));
37 | this.handlers.put(InventoryItemBuyButton.class, new BuyButtonHandler(instance, buyInventoryBuilder));
38 | }
39 |
40 | @EventHandler
41 | public void onClick(InventoryClickEvent e) {
42 | // Fix "Negative, non outside slot -1" error.
43 | if (e.getRawSlot() < 0) {
44 | return;
45 | }
46 | if (e.getInventory() == null
47 | || e.getInventory().getHolder() == null
48 | || !(e.getInventory().getHolder() instanceof CraftingStoreInventoryHolder)) {
49 | return;
50 | }
51 | e.setCancelled(true);
52 | Player p = (Player) e.getWhoClicked();
53 | CraftingStoreInventoryHolder holder = (CraftingStoreInventoryHolder) e.getInventory().getHolder();
54 | InventoryItem item = holder.getCsInventory().getByIndex(e.getRawSlot());
55 | if (item == null) {
56 | return;
57 | }
58 |
59 | if (handlers.containsKey(item.getClass())) {
60 | handlers.get(item.getClass()).handle(p, item, holder);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/listeners/PendingDonationJoinListener.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.listeners;
2 |
3 | import net.craftingstore.bukkit.CraftingStoreBukkit;
4 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
5 | import net.craftingstore.core.jobs.ProcessPendingPaymentsJob;
6 | import org.bukkit.entity.Player;
7 | import org.bukkit.event.EventHandler;
8 | import org.bukkit.event.Listener;
9 | import org.bukkit.event.player.PlayerJoinEvent;
10 |
11 | public class PendingDonationJoinListener implements Listener {
12 |
13 | private final CraftingStoreBukkit instance;
14 |
15 | public PendingDonationJoinListener(CraftingStoreBukkit instance) {
16 | this.instance = instance;
17 | }
18 |
19 | @EventHandler
20 | public void onJoin(PlayerJoinEvent e) {
21 | Player p = e.getPlayer();
22 | String username = p.getName();
23 |
24 | instance.getCraftingStore().getImplementation().runAsyncTask(() -> {
25 | try {
26 | new ProcessPendingPaymentsJob(instance.getCraftingStore(), username);
27 | } catch (CraftingStoreApiException ex) {
28 | ex.printStackTrace();
29 | }
30 | });
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/util/ChatColorUtil.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.util;
2 |
3 | import java.util.regex.Matcher;
4 | import java.util.regex.Pattern;
5 |
6 | public class ChatColorUtil {
7 | private static final Pattern HEX_PATTERN = Pattern.compile("(\\w{5}[0-9a-f])", Pattern.CASE_INSENSITIVE);
8 |
9 | public static String translate(String textToTranslate) {
10 | if (VersionUtil.isHexAvailable()) {
11 | return translateHexCodes(textToTranslate);
12 | }
13 | return org.bukkit.ChatColor.translateAlternateColorCodes('&', textToTranslate);
14 | }
15 |
16 | private static String translateHexCodes(String textToTranslate) {
17 | Matcher matcher = HEX_PATTERN.matcher(textToTranslate);
18 | StringBuffer buffer = new StringBuffer();
19 |
20 | while (matcher.find()) {
21 | matcher.appendReplacement(buffer, net.md_5.bungee.api.ChatColor.of("#" + matcher.group(1)).toString());
22 | }
23 |
24 | return net.md_5.bungee.api.ChatColor.translateAlternateColorCodes('&', matcher.appendTail(buffer).toString());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/bukkit/src/main/java/net/craftingstore/bukkit/util/VersionUtil.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bukkit.util;
2 |
3 | public class VersionUtil {
4 | private static boolean hexAvailable = false;
5 | private static boolean customModalDataAvailable = false;
6 | private static boolean guavaAvailable = false;
7 | private static boolean foliaSchedulerAvailable = false;
8 |
9 | static {
10 | try {
11 | Class.forName("net.md_5.bungee.api.ChatColor").getMethod("of", String.class);
12 | hexAvailable = true;
13 | } catch (NoSuchMethodException | ClassNotFoundException ignored) {
14 | }
15 | try {
16 | Class.forName("org.bukkit.inventory.meta.ItemMeta").getMethod("hasCustomModelData");
17 | customModalDataAvailable = true;
18 | } catch (NoSuchMethodException | ClassNotFoundException ignored) {
19 | }
20 | try {
21 | Class.forName("com.google.common.cache.CacheBuilder").getMethod("build");
22 | guavaAvailable = true;
23 | } catch (NoSuchMethodException | ClassNotFoundException ignored) {
24 | }
25 | try {
26 | Class.forName("org.bukkit.Bukkit").getMethod("getAsyncScheduler");
27 | foliaSchedulerAvailable = true;
28 | } catch (NoSuchMethodException | ClassNotFoundException ignored) {
29 | }
30 | }
31 |
32 | public static boolean isHexAvailable() {
33 | return hexAvailable;
34 | }
35 |
36 | public static boolean isCustomModalDataAvailable() {
37 | return customModalDataAvailable;
38 | }
39 |
40 | public static boolean isGuavaAvailable() {
41 | return guavaAvailable;
42 | }
43 |
44 | public static boolean isFoliaSchedulerAvailable() {
45 | return foliaSchedulerAvailable;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/bukkit/src/main/resources/config.yml:
--------------------------------------------------------------------------------
1 | api-key: ''
2 | disable-buy-command: false
--------------------------------------------------------------------------------
/bukkit/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: CraftingStore
2 | main: net.craftingstore.bukkit.CraftingStoreBukkit
3 | version: ${craftingstore-version}
4 | authors: [Tim_kwakman, thijs_a]
5 | prefix: CraftingStore
6 | softdepend: [PlaceholderAPI, Vault]
7 | api-version: "1.13"
8 | folia-supported: true
9 | commands:
10 | craftingstore:
11 | description: CraftingStore command
12 | aliases: [cs]
13 | csbuy:
14 | description: Buy command
15 | aliases: [buy]
--------------------------------------------------------------------------------
/bungee/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | net.craftingstore
9 | craftingstore
10 | ${revision}
11 |
12 |
13 | bungee
14 |
15 |
16 |
17 |
18 | org.apache.maven.plugins
19 | maven-compiler-plugin
20 |
21 | 8
22 | 8
23 |
24 |
25 |
26 |
27 |
28 | src/main/resources
29 | true
30 |
31 |
32 |
33 |
34 |
35 |
36 | bungeecord-repo
37 | https://oss.sonatype.org/content/repositories/snapshots
38 |
39 |
40 |
41 |
42 |
43 | net.craftingstore
44 | core
45 | ${project.version}
46 |
47 |
48 | net.md-5
49 | bungeecord-api
50 | 1.10-SNAPSHOT
51 | provided
52 |
53 |
54 |
--------------------------------------------------------------------------------
/bungee/src/main/java/net/craftingstore/bungee/BungeePluginConfiguration.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bungee;
2 |
3 | import net.craftingstore.core.PluginConfiguration;
4 |
5 | public class BungeePluginConfiguration implements PluginConfiguration {
6 |
7 | private CraftingStoreBungee plugin;
8 |
9 | BungeePluginConfiguration(CraftingStoreBungee plugin) {
10 | this.plugin = plugin;
11 | }
12 |
13 | @Override
14 | public String getName() {
15 | return "BungeeCord";
16 | }
17 |
18 | @Override
19 | public String[] getMainCommands() {
20 | return new String[]{"csb"};
21 | }
22 |
23 | @Override
24 | public String getVersion() {
25 | return plugin.getDescription().getVersion();
26 | }
27 |
28 | @Override
29 | public String getPlatform() {
30 | return plugin.getProxy().getVersion();
31 | }
32 |
33 | @Override
34 | public boolean isBuyCommandEnabled() {
35 | return false;
36 | }
37 |
38 | @Override
39 | public int getTimeBetweenCommands() {
40 | return plugin.getConfig().getInt("time-between-commands", 200);
41 | }
42 |
43 | @Override
44 | public String getNotEnoughBalanceMessage() {
45 | return null;
46 | }
47 |
48 | @Override
49 | public boolean isUsingAlternativeApi() {
50 | return plugin.getConfig().getBoolean("use-alternative-api", false);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/bungee/src/main/java/net/craftingstore/bungee/CraftingStoreBungee.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bungee;
2 |
3 | import net.craftingstore.bungee.commands.CraftingStoreCommand;
4 | import net.craftingstore.bungee.config.Config;
5 | import net.craftingstore.bungee.listeners.AdminJoinListener;
6 | import net.craftingstore.bungee.listeners.PendingDonationJoinListener;
7 | import net.craftingstore.core.CraftingStore;
8 | import net.md_5.bungee.api.ChatColor;
9 | import net.md_5.bungee.api.plugin.Plugin;
10 | import net.md_5.bungee.config.Configuration;
11 |
12 | public class CraftingStoreBungee extends Plugin {
13 |
14 | private Config config;
15 | private CraftingStore craftingStore;
16 | private String prefix = ChatColor.GRAY + "[" + ChatColor.RED + "CraftingStore" + ChatColor.GRAY + "] " + ChatColor.WHITE;
17 |
18 | @Override
19 | public void onEnable() {
20 | config = new Config(this, "config.yml");
21 | this.craftingStore = new CraftingStore(new CraftingStoreBungeeImpl(this));
22 | getProxy().getPluginManager().registerCommand(this, new CraftingStoreCommand(this));
23 | getProxy().getPluginManager().registerListener(this, new AdminJoinListener(this));
24 | getProxy().getPluginManager().registerListener(this, new PendingDonationJoinListener(this));
25 | }
26 |
27 | @Override
28 | public void onDisable() {
29 | craftingStore.setEnabled(false);
30 | }
31 |
32 | public Configuration getConfig() {
33 | return config.getConfig();
34 | }
35 |
36 | public Config getConfigWrapper() {
37 | return config;
38 | }
39 |
40 | public CraftingStore getCraftingStore() {
41 | return craftingStore;
42 | }
43 |
44 | public String getPrefix() {
45 | return prefix;
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/bungee/src/main/java/net/craftingstore/bungee/CraftingStoreBungeeImpl.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bungee;
2 |
3 | import net.craftingstore.bungee.events.DonationReceivedEvent;
4 | import net.craftingstore.core.CraftingStorePlugin;
5 | import net.craftingstore.core.PluginConfiguration;
6 | import net.craftingstore.core.logging.CraftingStoreLogger;
7 | import net.craftingstore.core.logging.impl.JavaLogger;
8 | import net.craftingstore.core.models.donation.Donation;
9 | import net.md_5.bungee.api.ProxyServer;
10 | import net.md_5.bungee.api.connection.ProxiedPlayer;
11 |
12 | import java.util.concurrent.TimeUnit;
13 |
14 | public class CraftingStoreBungeeImpl implements CraftingStorePlugin {
15 |
16 | private CraftingStoreBungee bungeePlugin;
17 | private JavaLogger logger;
18 | private BungeePluginConfiguration configuration;
19 |
20 | CraftingStoreBungeeImpl(CraftingStoreBungee bungeePlugin) {
21 | this.bungeePlugin = bungeePlugin;
22 | this.configuration = new BungeePluginConfiguration(bungeePlugin);
23 | this.logger = new JavaLogger(bungeePlugin.getLogger());
24 | this.logger.setDebugging(bungeePlugin.getConfig().getBoolean("debug", false));
25 | }
26 |
27 | public boolean executeDonation(final Donation donation) {
28 | ProxyServer proxy = bungeePlugin.getProxy();
29 | if (donation.getPlayer().isRequiredOnline()) {
30 | ProxiedPlayer player = proxy.getPlayer(donation.getPlayer().getUsername());
31 | if (player == null || !player.isConnected()) {
32 | return false;
33 | }
34 | }
35 |
36 | DonationReceivedEvent event = new DonationReceivedEvent(donation);
37 | proxy.getPluginManager().callEvent(event);
38 | if (event.isCancelled()) {
39 | return false;
40 | }
41 |
42 | proxy.getScheduler().runAsync(bungeePlugin, () -> proxy.getPluginManager().dispatchCommand(proxy.getConsole(), donation.getCommand()));
43 | return true;
44 | }
45 |
46 | public CraftingStoreLogger getLogger() {
47 | return this.logger;
48 | }
49 |
50 | public void registerRunnable(Runnable runnable, int delay, int interval) {
51 | bungeePlugin.getProxy().getScheduler().schedule(bungeePlugin, runnable, delay, interval, TimeUnit.SECONDS);
52 | }
53 |
54 | public void runAsyncTask(Runnable runnable) {
55 | bungeePlugin.getProxy().getScheduler().runAsync(bungeePlugin, runnable);
56 | }
57 |
58 | public String getToken() {
59 | return bungeePlugin.getConfig().getString("api-key");
60 | }
61 |
62 | @Override
63 | public PluginConfiguration getConfiguration() {
64 | return this.configuration;
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/bungee/src/main/java/net/craftingstore/bungee/commands/CraftingStoreCommand.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bungee.commands;
2 |
3 | import net.craftingstore.bungee.CraftingStoreBungee;
4 | import net.md_5.bungee.api.ChatColor;
5 | import net.md_5.bungee.api.CommandSender;
6 | import net.md_5.bungee.api.chat.TextComponent;
7 | import net.md_5.bungee.api.plugin.Command;
8 |
9 | import java.util.concurrent.ExecutionException;
10 |
11 | public class CraftingStoreCommand extends Command {
12 |
13 | private CraftingStoreBungee instance;
14 |
15 | public CraftingStoreCommand(CraftingStoreBungee instance) {
16 | super("csb", instance.getCraftingStore().ADMIN_PERMISSION);
17 | this.instance = instance;
18 | }
19 |
20 | @Override
21 | public void execute(CommandSender sender, String[] args) {
22 | if (!sender.hasPermission(instance.getCraftingStore().ADMIN_PERMISSION)) {
23 | sender.sendMessage(new TextComponent(instance.getPrefix() + "You don't have the required permission!"));
24 | return;
25 | }
26 | if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
27 | instance.getCraftingStore().reload();
28 | sender.sendMessage(new TextComponent(instance.getPrefix() + "The plugin is reloading!"));
29 | return;
30 | }
31 | if (args.length == 2 && args[0].equalsIgnoreCase("key")) {
32 | instance.getConfig().set("api-key", args[1]);
33 | instance.getConfigWrapper().saveConfig();
34 | instance.getProxy().getScheduler().runAsync(instance, () -> {
35 | try {
36 | if (instance.getCraftingStore().reload().get()) {
37 | sender.sendMessage(new TextComponent(instance.getPrefix() + "The new API key has been set in the config, and the plugin has been reloaded."));
38 | } else {
39 | sender.sendMessage(new TextComponent(instance.getPrefix() + "The API key is invalid. The plugin will not work until you set a valid API key."));
40 | }
41 | } catch (InterruptedException | ExecutionException e) {
42 | e.printStackTrace();
43 | }
44 | });
45 | return;
46 | }
47 | if ((args.length == 1 || args.length == 2) && args[0].equalsIgnoreCase("debug")) {
48 | boolean isDebugging = this.instance.getCraftingStore().getLogger().isDebugging();
49 | if (args.length == 1) {
50 | sender.sendMessage(new TextComponent(String.format(
51 | "%sDebug mode is currently %s.",
52 | this.instance.getPrefix(),
53 | isDebugging ? "enabled" : "disabled"
54 | )));
55 | return;
56 | }
57 | String debugValue = args[1].toLowerCase();
58 | if (debugValue.equalsIgnoreCase("true")) {
59 | isDebugging = true;
60 | } else if (debugValue.equalsIgnoreCase("false")) {
61 | isDebugging = false;
62 | } else {
63 | sender.sendMessage(new TextComponent(instance.getPrefix() + "Unknown debug value."));
64 | return;
65 | }
66 | this.instance.getCraftingStore().getLogger().setDebugging(isDebugging);
67 | instance.getConfig().set("debug", isDebugging);
68 | instance.getConfigWrapper().saveConfig();
69 | sender.sendMessage(new TextComponent(String.format(
70 | "%sDebug mode has been %s.",
71 | this.instance.getPrefix(),
72 | isDebugging ? "enabled" : "disabled"
73 | )));
74 | return;
75 | }
76 |
77 | sender.sendMessage(new TextComponent(ChatColor.GRAY + "" + ChatColor.STRIKETHROUGH + "-----------------------"));
78 | sender.sendMessage(new TextComponent(ChatColor.DARK_GRAY + ">" + ChatColor.GRAY + " /csb reload" + ChatColor.DARK_GRAY + " -> " + ChatColor.GRAY + "Reload the config."));
79 | sender.sendMessage(new TextComponent(ChatColor.DARK_GRAY + ">" + ChatColor.GRAY + " /csb key " + ChatColor.DARK_GRAY + " -> " + ChatColor.GRAY + "Update the key."));
80 | sender.sendMessage(new TextComponent(ChatColor.GRAY + "" + ChatColor.STRIKETHROUGH + "-----------------------"));
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/bungee/src/main/java/net/craftingstore/bungee/config/Config.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bungee.config;
2 |
3 | import net.md_5.bungee.api.plugin.Plugin;
4 | import net.md_5.bungee.config.Configuration;
5 | import net.md_5.bungee.config.ConfigurationProvider;
6 | import net.md_5.bungee.config.YamlConfiguration;
7 |
8 | import java.io.File;
9 | import java.io.IOException;
10 | import java.io.InputStream;
11 | import java.nio.file.Files;
12 | import java.util.logging.Level;
13 |
14 | public class Config {
15 |
16 | private Plugin instance;
17 | private Configuration configuration;
18 | private String filename;
19 |
20 | public Config(Plugin instance, String filename) {
21 | this.instance = instance;
22 | this.filename = filename;
23 |
24 | instance.getDataFolder().mkdir();
25 |
26 | File file = new File(instance.getDataFolder(), filename);
27 | if (!file.exists()) {
28 | InputStream is = instance.getResourceAsStream(filename);
29 | if (is != null) {
30 | instance.getLogger().info("Copying default config file.");
31 | try {
32 | Files.copy(is, file.toPath());
33 | } catch (IOException e) {
34 | instance.getLogger().log(Level.SEVERE, "An error occurred while copying the default config file " + filename + ".", e);
35 | }
36 | } else {
37 | try {
38 | file.createNewFile();
39 | } catch (IOException e) {
40 | instance.getLogger().log(Level.SEVERE, "An error occurred while creating the config file " + filename + ".", e);
41 | }
42 | }
43 | }
44 |
45 | reload();
46 | }
47 |
48 | public void reload() {
49 | try {
50 | configuration = ConfigurationProvider.getProvider(YamlConfiguration.class).load(new File(instance.getDataFolder(), filename));
51 | } catch (IOException e) {
52 | instance.getLogger().log(Level.SEVERE, "An error occurred while loading the config file " + filename + ".", e);
53 | }
54 | }
55 |
56 | public Configuration getConfig() {
57 | if (configuration == null) {
58 | reload();
59 | }
60 | return configuration;
61 | }
62 |
63 | public void saveConfig() {
64 | try {
65 | ConfigurationProvider.getProvider(YamlConfiguration.class).save(configuration, new File(instance.getDataFolder(), filename));
66 | } catch (IOException e) {
67 | instance.getLogger().log(Level.SEVERE, "An error occured while saving the config file " + filename + ".", e);
68 | }
69 | }
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/bungee/src/main/java/net/craftingstore/bungee/events/DonationReceivedEvent.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bungee.events;
2 |
3 | import net.craftingstore.core.models.donation.Donation;
4 | import net.md_5.bungee.api.plugin.Cancellable;
5 | import net.md_5.bungee.api.plugin.Event;
6 |
7 | import java.util.UUID;
8 |
9 | public class DonationReceivedEvent extends Event implements Cancellable {
10 |
11 | @Deprecated
12 | private String command;
13 | @Deprecated
14 | private String username;
15 | @Deprecated
16 | private UUID uuid;
17 | @Deprecated
18 | private String packageName;
19 | @Deprecated
20 | private int packagePrice;
21 | @Deprecated
22 | private int couponDiscount;
23 |
24 | private Donation donation;
25 |
26 | private boolean cancelled = false;
27 |
28 | @Deprecated
29 | public DonationReceivedEvent(String command, String username, UUID uuid, String packageName, int packagePrice, int couponDiscount) {
30 | this.command = command;
31 | this.username = username;
32 | this.uuid = uuid;
33 | this.packageName = packageName;
34 | this.packagePrice = packagePrice;
35 | this.couponDiscount = couponDiscount;
36 | }
37 |
38 | public DonationReceivedEvent(Donation donation) {
39 | this.command = donation.getCommand();
40 | this.username = donation.getPlayer().getUsername();
41 | this.uuid = donation.getPlayer().getUUID();
42 | this.packageName = donation.getPackage().getName();
43 | this.packagePrice = donation.getPackage().getPrice();
44 | this.couponDiscount = donation.getDiscount();
45 | this.donation = donation;
46 | }
47 |
48 | public Donation getDonation() {
49 | return this.donation;
50 | }
51 |
52 | @Deprecated
53 | public String getCommand() {
54 | return command;
55 | }
56 |
57 | @Deprecated
58 | public String getUsername() {
59 | return username;
60 | }
61 |
62 | @Deprecated
63 | public UUID getUuid() {
64 | return uuid;
65 | }
66 |
67 | @Deprecated
68 | public String getPackageName() {
69 | return packageName;
70 | }
71 |
72 | @Deprecated
73 | public int getPackagePrice() {
74 | return packagePrice;
75 | }
76 |
77 | @Deprecated
78 | public int getCouponDiscount() {
79 | return couponDiscount;
80 | }
81 |
82 | public boolean isCancelled() {
83 | return cancelled;
84 | }
85 |
86 | public void setCancelled(boolean cancelled) {
87 | this.cancelled = cancelled;
88 | }
89 | }
--------------------------------------------------------------------------------
/bungee/src/main/java/net/craftingstore/bungee/listeners/AdminJoinListener.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bungee.listeners;
2 |
3 | import net.craftingstore.bungee.CraftingStoreBungee;
4 | import net.craftingstore.core.models.api.misc.CraftingStoreInformation;
5 | import net.craftingstore.core.models.api.misc.UpdateInformation;
6 | import net.md_5.bungee.api.chat.TextComponent;
7 | import net.md_5.bungee.api.connection.ProxiedPlayer;
8 | import net.md_5.bungee.api.event.PostLoginEvent;
9 | import net.md_5.bungee.api.plugin.Listener;
10 | import net.md_5.bungee.event.EventHandler;
11 |
12 | public class AdminJoinListener implements Listener {
13 |
14 | private CraftingStoreBungee instance;
15 |
16 | public AdminJoinListener(CraftingStoreBungee instance) {
17 | this.instance = instance;
18 | }
19 |
20 | @EventHandler
21 | public void onPostLogin(PostLoginEvent e) {
22 | ProxiedPlayer p = e.getPlayer();
23 | if (!p.hasPermission(instance.getCraftingStore().ADMIN_PERMISSION)) {
24 | return;
25 | }
26 | CraftingStoreInformation information = instance.getCraftingStore().getInformation();
27 | UpdateInformation update = null;
28 | if (information != null) {
29 | update = information.getUpdateInformation();
30 |
31 | // Update notification
32 | if (update != null) {
33 | p.sendMessage(new TextComponent(instance.getPrefix() + update.getMessage()));
34 | }
35 | }
36 |
37 | if (!instance.getCraftingStore().isEnabled()) {
38 | if (update != null && update.shouldDisable()) {
39 | p.sendMessage(new TextComponent(instance.getPrefix() + "The CraftingStore plugin has been disabled because this is an outdated version. Please update the plugin."));
40 | } else {
41 | p.sendMessage(new TextComponent(instance.getPrefix() + "The CraftingStore plugin has not been set-up correctly. Please set your API key using /csb key ."));
42 | }
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/bungee/src/main/java/net/craftingstore/bungee/listeners/PendingDonationJoinListener.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.bungee.listeners;
2 |
3 | import net.craftingstore.bungee.CraftingStoreBungee;
4 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
5 | import net.craftingstore.core.jobs.ProcessPendingPaymentsJob;
6 | import net.md_5.bungee.api.connection.ProxiedPlayer;
7 | import net.md_5.bungee.api.event.PostLoginEvent;
8 | import net.md_5.bungee.api.plugin.Listener;
9 | import net.md_5.bungee.event.EventHandler;
10 |
11 | public class PendingDonationJoinListener implements Listener {
12 |
13 | private final CraftingStoreBungee instance;
14 |
15 | public PendingDonationJoinListener(CraftingStoreBungee instance) {
16 | this.instance = instance;
17 | }
18 |
19 | @EventHandler
20 | public void onPostLogin(PostLoginEvent e) {
21 | ProxiedPlayer p = e.getPlayer();
22 | String username = p.getName();
23 | instance.getCraftingStore().getImplementation().runAsyncTask(() -> {
24 | try {
25 | new ProcessPendingPaymentsJob(instance.getCraftingStore(), username);
26 | } catch (CraftingStoreApiException ex) {
27 | ex.printStackTrace();
28 | }
29 | });
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/bungee/src/main/resources/bungee.yml:
--------------------------------------------------------------------------------
1 | name: CraftingStore
2 | main: net.craftingstore.bungee.CraftingStoreBungee
3 | version: ${craftingstore-version}
4 | author: thijs_a
5 | prefix: CraftingStore
--------------------------------------------------------------------------------
/core/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | net.craftingstore
9 | craftingstore
10 | ${revision}
11 |
12 |
13 | core
14 |
15 |
16 |
17 |
18 | org.apache.maven.plugins
19 | maven-compiler-plugin
20 |
21 | 8
22 | 8
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | jitpack.io
31 | https://jitpack.io
32 |
33 |
34 |
35 |
36 |
37 | com.google.code.gson
38 | gson
39 | 2.8.9
40 | provided
41 |
42 |
43 | com.github.thijsa
44 | socket.io-client-java
45 | 1.0.3
46 |
47 |
48 | org.apache.httpcomponents
49 | httpclient
50 | 4.5.13
51 |
52 |
53 | org.apache.commons
54 | commons-lang3
55 | 3.12.0
56 |
57 |
58 | commons-logging
59 | commons-logging
60 | 1.2
61 |
62 |
63 | org.apache.commons
64 | commons-text
65 | 1.10.0
66 |
67 |
68 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/CraftingStore.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core;
2 |
3 | import net.craftingstore.core.http.CraftingStoreCachedAPI;
4 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
5 | import net.craftingstore.core.jobs.ExecuteDonationsJob;
6 | import net.craftingstore.core.logging.CraftingStoreLogger;
7 | import net.craftingstore.core.models.api.Root;
8 | import net.craftingstore.core.models.api.misc.CraftingStoreInformation;
9 | import net.craftingstore.core.models.api.misc.UpdateInformation;
10 | import net.craftingstore.core.models.donation.Donation;
11 | import net.craftingstore.core.provider.ProviderSelector;
12 | import net.craftingstore.core.runner.DonationRunner;
13 | import net.craftingstore.core.scheduler.*;
14 |
15 | import java.util.ArrayList;
16 | import java.util.HashMap;
17 | import java.util.Map;
18 | import java.util.concurrent.ExecutionException;
19 | import java.util.concurrent.ExecutorService;
20 | import java.util.concurrent.Executors;
21 | import java.util.concurrent.Future;
22 |
23 | public class CraftingStore {
24 |
25 | private CraftingStorePlugin plugin;
26 | private CraftingStoreAPI api;
27 | private ProviderSelector selector;
28 | private CraftingStoreInformation information;
29 | private DonationRunner donationRunner;
30 | private boolean enabled = false;
31 | public final String ADMIN_PERMISSION = "craftingstore.admin";
32 | private ExecutorService executor = Executors.newSingleThreadExecutor();
33 | private Map pendingDonations;
34 |
35 | public CraftingStore(CraftingStorePlugin implementation) {
36 | this.plugin = implementation;
37 | this.pendingDonations = new HashMap<>();
38 | this.api = new CraftingStoreCachedAPI(this);
39 | this.selector = new ProviderSelector(this);
40 | this.donationRunner = new DonationRunner(this);
41 | this.getImplementation().runAsyncTask(() -> {
42 | try {
43 | if (this.reload().get()) {
44 | // Every 5 minutes
45 | this.plugin.registerRunnable(new DonationChecker(this), 10, 5 * 60);
46 | // Every minute
47 | this.plugin.registerRunnable(new ProviderChecker(this), 60, 60);
48 | // Every 20 minutes
49 | this.plugin.registerRunnable(new InventoryRenewer(this), 20 * 60, 20 * 60);
50 | // Every 25 minutes
51 | this.plugin.registerRunnable(new APICacheRenewer(this), 10, 60 * 25);
52 | // Every 24 hours
53 | this.plugin.registerRunnable(new InformationUpdater(this), 24 * 60 * 60, 24 * 60 * 60);
54 | }
55 | } catch (InterruptedException | ExecutionException e) {
56 | e.printStackTrace();
57 | }
58 | });
59 | }
60 |
61 | public CraftingStorePlugin getImplementation() {
62 | return plugin;
63 | }
64 |
65 | public CraftingStoreAPI getApi() {
66 | return api;
67 | }
68 |
69 | public ProviderSelector getProviderSelector() {
70 | return this.selector;
71 | }
72 |
73 | public CraftingStoreLogger getLogger() {
74 | return getImplementation().getLogger();
75 | }
76 |
77 | public Future reload() {
78 | this.getApi().setToken(this.getImplementation().getToken());
79 | return executor.submit(() -> {
80 | try {
81 | if (this.getApi().token == null || this.getApi().token.isEmpty()) {
82 | getLogger().error(String.format(
83 | "API key not set in the config. You need to set the correct api key using /%s key .",
84 | this.getImplementation().getConfiguration().getMainCommands()[0]
85 | ));
86 | setEnabled(false);
87 | return false;
88 | }
89 | Root keyResult = this.getApi().checkKey().get();
90 | if (!keyResult.isSuccess()) {
91 | getLogger().error("API key is invalid. The plugin will not work.");
92 | setEnabled(false);
93 | return false;
94 | }
95 | information = this.getApi().getInformation().get();
96 |
97 | if (information.getUpdateInformation() != null) {
98 | UpdateInformation update = information.getUpdateInformation();
99 | getLogger().info(update.getMessage());
100 | if (update.shouldDisable()) {
101 | getLogger().error("Plugin will be disabled until you install the latest update.");
102 | setEnabled(false);
103 | return false;
104 | }
105 | }
106 | setEnabled(true);
107 |
108 | selector.setProviders(information.getProviders());
109 | selector.selectProvider();
110 |
111 | // Renew the inventory on reload / start
112 | new InventoryRenewer(this).run();
113 | getLogger().debug("Startup complete");
114 | } catch (CraftingStoreApiException e) {
115 | e.printStackTrace();
116 | return false;
117 | }
118 | return true;
119 | });
120 | }
121 |
122 | public void executeQueue() {
123 | this.donationRunner.runDonations();
124 | }
125 |
126 | public boolean isEnabled() {
127 | return enabled;
128 | }
129 |
130 | public void setEnabled(boolean enabled) {
131 | this.enabled = enabled;
132 | if (!enabled) {
133 | getProviderSelector().disconnect();
134 | }
135 | }
136 |
137 | public CraftingStoreInformation getInformation() {
138 | return information;
139 | }
140 |
141 | public Map getPendingDonations() {
142 | return pendingDonations;
143 | }
144 |
145 | public DonationRunner getDonationRunner() {
146 | return donationRunner;
147 | }
148 | }
149 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/CraftingStoreAPI.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core;
2 |
3 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
4 | import net.craftingstore.core.models.api.*;
5 | import net.craftingstore.core.models.api.misc.CraftingStoreInformation;
6 | import net.craftingstore.core.models.donation.Donation;
7 |
8 | import java.util.UUID;
9 | import java.util.concurrent.ExecutorService;
10 | import java.util.concurrent.Executors;
11 | import java.util.concurrent.Future;
12 |
13 | public abstract class CraftingStoreAPI {
14 |
15 | protected String token;
16 | protected ExecutorService executor = Executors.newSingleThreadExecutor();
17 |
18 | public abstract Future getInformation() throws CraftingStoreApiException;
19 |
20 | public abstract Future> checkKey() throws CraftingStoreApiException;
21 |
22 | public abstract Future getDonationQueue() throws CraftingStoreApiException;
23 |
24 | public abstract void completeDonations(int[] ids) throws CraftingStoreApiException;
25 |
26 | public abstract Future getPayments() throws CraftingStoreApiException;
27 |
28 | public abstract Future getGUI() throws CraftingStoreApiException;
29 |
30 | public abstract Future getTopDonators() throws CraftingStoreApiException;
31 |
32 | public abstract Future getPackageInformation(
33 | String inGameName,
34 | UUID uuid,
35 | String ip,
36 | int packageId
37 | ) throws CraftingStoreApiException;
38 |
39 | public abstract Future createPayment(
40 | String inGameName,
41 | int price,
42 | int[] packages
43 | ) throws CraftingStoreApiException;
44 |
45 | public String getToken() {
46 | return this.token;
47 | }
48 |
49 | protected void setToken(String token) {
50 | this.token = token;
51 | }
52 |
53 | public void shutdown() {
54 | executor.shutdown();
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/CraftingStorePlugin.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core;
2 |
3 | import net.craftingstore.core.logging.CraftingStoreLogger;
4 | import net.craftingstore.core.models.donation.Donation;
5 |
6 | public interface CraftingStorePlugin {
7 |
8 | boolean executeDonation(Donation donation);
9 |
10 | CraftingStoreLogger getLogger();
11 |
12 | void registerRunnable(Runnable runnable, int delay, int interval);
13 |
14 | void runAsyncTask(Runnable runnable);
15 |
16 | String getToken();
17 |
18 | PluginConfiguration getConfiguration();
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/PluginConfiguration.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core;
2 |
3 | public interface PluginConfiguration {
4 | String getName();
5 |
6 | String[] getMainCommands();
7 |
8 | String getVersion();
9 |
10 | String getPlatform();
11 |
12 | boolean isBuyCommandEnabled();
13 |
14 | int getTimeBetweenCommands();
15 |
16 | String getNotEnoughBalanceMessage();
17 |
18 | boolean isUsingAlternativeApi();
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/exceptions/CraftingStoreApiException.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.exceptions;
2 |
3 | import java.io.IOException;
4 |
5 | public class CraftingStoreApiException extends Exception {
6 |
7 | public CraftingStoreApiException(String s, IOException e) {
8 | super(s, e);
9 | }
10 |
11 | @Override
12 | public void printStackTrace() {
13 | super.getCause().printStackTrace();
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/http/CraftingStoreCachedAPI.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.http;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
5 | import net.craftingstore.core.models.api.ApiInventory;
6 | import net.craftingstore.core.models.api.ApiPayment;
7 | import net.craftingstore.core.models.api.ApiTopDonator;
8 |
9 | import java.util.HashMap;
10 | import java.util.concurrent.ExecutionException;
11 | import java.util.concurrent.Future;
12 |
13 | public class CraftingStoreCachedAPI extends CraftingStoreAPIImpl {
14 |
15 | private final HashMap cache = new HashMap<>();
16 |
17 | public CraftingStoreCachedAPI(CraftingStore instance) {
18 | super(instance);
19 | }
20 |
21 | @Override
22 | public Future getGUI() throws CraftingStoreApiException {
23 | return executor.submit(() -> {
24 | String key = "plugin/inventory";
25 | if (!cache.containsKey(key)) {
26 | cache.put(key, super.getGUI().get());
27 | }
28 | return (ApiInventory) cache.get(key);
29 | });
30 | }
31 |
32 | @Override
33 | public Future getTopDonators() throws CraftingStoreApiException {
34 | return executor.submit(() -> {
35 | String key = "buyers/top";
36 | if (cache.containsKey(key)) {
37 | return (ApiTopDonator[]) cache.get(key);
38 | }
39 | return null;
40 | });
41 | }
42 |
43 | @Override
44 | public Future getPayments() throws CraftingStoreApiException {
45 | return executor.submit(() -> {
46 | String key = "buyers/recent";
47 | if (cache.containsKey(key)) {
48 | return (ApiPayment[]) cache.get(key);
49 | }
50 | return null;
51 | });
52 | }
53 |
54 | public void refreshGUICache() throws CraftingStoreApiException, ExecutionException, InterruptedException {
55 | cache.put("plugin/inventory", super.getGUI().get());
56 | }
57 |
58 | public void refreshTopDonatorsCache() throws CraftingStoreApiException, ExecutionException, InterruptedException {
59 | cache.put("buyers/top", super.getTopDonators().get());
60 | }
61 |
62 | public void refreshPaymentsCache() throws CraftingStoreApiException, ExecutionException, InterruptedException {
63 | cache.put("buyers/recent", super.getPayments().get());
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/http/util/GenericOf.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.http.util;
2 |
3 | import java.lang.reflect.ParameterizedType;
4 | import java.lang.reflect.Type;
5 |
6 | public class GenericOf implements ParameterizedType {
7 |
8 | private final Class container;
9 | private final Class wrapped;
10 |
11 | public GenericOf(Class container, Class wrapped) {
12 | this.container = container;
13 | this.wrapped = wrapped;
14 | }
15 |
16 | public Type[] getActualTypeArguments() {
17 | return new Type[]{wrapped};
18 | }
19 |
20 | public Type getRawType() {
21 | return container;
22 | }
23 |
24 | public Type getOwnerType() {
25 | return null;
26 | }
27 | }
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/http/util/InformationAdapter.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.http.util;
2 |
3 | import com.google.gson.*;
4 | import net.craftingstore.core.models.api.provider.ProviderInformation;
5 | import net.craftingstore.core.models.api.provider.ProviderType;
6 |
7 | import java.lang.reflect.Type;
8 |
9 | public class InformationAdapter implements JsonDeserializer {
10 |
11 | public ProviderInformation deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext context) throws JsonParseException {
12 | JsonObject jsonObject = jsonElement.getAsJsonObject();
13 |
14 | JsonPrimitive prim = (JsonPrimitive) jsonObject.get("type");
15 | ProviderType providerType = ProviderType.valueOf(prim.getAsString());
16 | Class klass = providerType.getActualClass();
17 | return context.deserialize(jsonObject, klass);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/http/util/InventoryAdapter.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.http.util;
2 |
3 | import com.google.gson.*;
4 | import net.craftingstore.core.models.api.inventory.InventoryItem;
5 | import net.craftingstore.core.models.api.inventory.InventoryItemType;
6 |
7 | import java.lang.reflect.Type;
8 |
9 | public class InventoryAdapter implements JsonDeserializer {
10 |
11 | public InventoryItem deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
12 | JsonObject jsonObject = json.getAsJsonObject();
13 |
14 | JsonPrimitive prim = (JsonPrimitive) jsonObject.get("type");
15 | InventoryItemType itemType = InventoryItemType.valueOf(prim.getAsString());
16 | Class extends InventoryItem> klass = itemType.getActualClass();
17 | return context.deserialize(jsonObject, klass);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/http/util/JsonResponseHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.http.util;
2 |
3 | import com.google.gson.Gson;
4 | import net.craftingstore.core.models.api.Root;
5 | import org.apache.http.HttpEntity;
6 | import org.apache.http.HttpResponse;
7 | import org.apache.http.StatusLine;
8 | import org.apache.http.client.ClientProtocolException;
9 | import org.apache.http.client.HttpResponseException;
10 | import org.apache.http.client.ResponseHandler;
11 | import org.apache.http.util.EntityUtils;
12 |
13 | import java.io.IOException;
14 |
15 | public class JsonResponseHandler implements ResponseHandler {
16 |
17 | private Gson gson;
18 | private Class aClass;
19 |
20 | public JsonResponseHandler(Gson gson, Class aClass) {
21 | this.gson = gson;
22 | this.aClass = aClass;
23 | }
24 |
25 | public T handleResponse(HttpResponse response) throws IOException {
26 | StatusLine statusLine = response.getStatusLine();
27 | HttpEntity entity = response.getEntity();
28 |
29 | if (statusLine.getStatusCode() >= 300) {
30 | throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
31 | }
32 |
33 | if (entity == null) {
34 | throw new ClientProtocolException("Response contains no content");
35 | }
36 |
37 | String value = EntityUtils.toString(entity);
38 |
39 | if (aClass == Root.class) {
40 | return gson.fromJson(value, aClass);
41 | }
42 | Root result = gson.fromJson(value, new GenericOf<>(Root.class, aClass));
43 | return result.getResult();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/http/util/JsonResponseHandlerV7.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.http.util;
2 |
3 | import com.google.gson.Gson;
4 | import net.craftingstore.core.models.api.RootV7;
5 | import org.apache.http.HttpEntity;
6 | import org.apache.http.HttpResponse;
7 | import org.apache.http.StatusLine;
8 | import org.apache.http.client.ClientProtocolException;
9 | import org.apache.http.client.HttpResponseException;
10 | import org.apache.http.client.ResponseHandler;
11 | import org.apache.http.util.EntityUtils;
12 |
13 | import java.io.IOException;
14 |
15 | public class JsonResponseHandlerV7 implements ResponseHandler {
16 |
17 | private Gson gson;
18 | private Class aClass;
19 |
20 | public JsonResponseHandlerV7(Gson gson, Class aClass) {
21 | this.gson = gson;
22 | this.aClass = aClass;
23 | }
24 |
25 | public T handleResponse(HttpResponse response) throws IOException {
26 | StatusLine statusLine = response.getStatusLine();
27 | HttpEntity entity = response.getEntity();
28 |
29 | if (statusLine.getStatusCode() >= 300) {
30 | throw new HttpResponseException(statusLine.getStatusCode(), statusLine.getReasonPhrase());
31 | }
32 |
33 | if (entity == null) {
34 | throw new ClientProtocolException("Response contains no content");
35 | }
36 |
37 | String value = EntityUtils.toString(entity);
38 |
39 | if (aClass == RootV7.class) {
40 | return gson.fromJson(value, aClass);
41 | }
42 | RootV7 result = gson.fromJson(value, new GenericOf<>(RootV7.class, aClass));
43 | return result.getData();
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/jobs/ExecuteDonationsJob.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.jobs;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
5 | import net.craftingstore.core.models.donation.Donation;
6 |
7 | import java.util.*;
8 | import java.util.stream.Stream;
9 |
10 | public class ExecuteDonationsJob {
11 |
12 | public static final int CHUNK_SIZE = 25;
13 |
14 | private CraftingStore instance;
15 | private Donation[] donations;
16 |
17 | public ExecuteDonationsJob(CraftingStore instance, Donation[] donations) throws CraftingStoreApiException {
18 | this.instance = instance;
19 | this.donations = donations;
20 | this.execute();
21 | }
22 |
23 | private void execute() throws CraftingStoreApiException {
24 | this.instance.getLogger().debug(String.format("Executing ExecuteDonationsJob for %d donations.", this.donations.length));
25 |
26 | Map donations = new HashMap<>();
27 | for (int i = 0; i < this.donations.length; i++) {
28 | Donation donation = this.donations[i];
29 | this.instance.getLogger().debug(String.format("Executing donation #%d with command id #%d", donation.getPaymentId(), donation.getCommandId()));
30 | this.instance.getLogger().debug(String.format("Command is '%s'", donation.getCommand()));
31 | boolean result = instance.getImplementation().executeDonation(donation);
32 | donations.put(donation, result);
33 | this.instance.getLogger().debug(String.format("Result of execution is %s", result));
34 |
35 | if (i < (this.donations.length - 1)) {
36 | if (!result) {
37 | this.instance.getLogger().debug("Not delaying command execution because last command did not successfully execute.");
38 | continue;
39 | }
40 |
41 | // Wait x ms before executing the next command, so donations with a lot of commands will not create lag
42 | try {
43 | int waitingTime = this.instance.getImplementation().getConfiguration().getTimeBetweenCommands();
44 | this.instance.getLogger().debug(String.format("Waiting %dms before executing next donation", waitingTime));
45 | Thread.sleep(waitingTime);
46 | this.instance.getLogger().debug("Waiting done");
47 | } catch (InterruptedException e) {
48 | e.printStackTrace();
49 | }
50 | }
51 | }
52 |
53 | int[] completedIds = donations.entrySet().stream()
54 | .filter(Map.Entry::getValue)
55 | .mapToInt(entry -> entry.getKey().getId())
56 | .toArray();
57 |
58 | if (completedIds.length > 0) {
59 | this.instance.getLogger().debug("Marking executed donations as complete.");
60 | instance.getApi().completeDonations(completedIds);
61 | }
62 |
63 | for (Map.Entry entry : donations.entrySet()) {
64 | // Check if the donation has been executed and is in the cache
65 | if (entry.getValue() && instance.getPendingDonations().containsKey(entry.getKey().getId())) {
66 | instance.getPendingDonations().remove(entry.getKey().getId());
67 | } else if (!entry.getValue()) {
68 | // Add the donation to the list of pending donations so it gets executed when the player gets online.
69 | instance.getPendingDonations().put(entry.getKey().getId(), entry.getKey());
70 | }
71 | }
72 | this.instance.getLogger().debug("Execution of ExecuteDonationsJob finished.");
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/jobs/ProcessPendingPaymentsJob.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.jobs;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
5 | import net.craftingstore.core.models.donation.Donation;
6 |
7 | import java.util.Map;
8 |
9 | public class ProcessPendingPaymentsJob {
10 | private CraftingStore instance;
11 | private String username;
12 |
13 | public ProcessPendingPaymentsJob(CraftingStore instance, String username) throws CraftingStoreApiException {
14 | this.instance = instance;
15 | this.username = username;
16 | this.execute();
17 | }
18 |
19 | private void execute() throws CraftingStoreApiException {
20 | instance.getLogger().debug("Executing ProcessPendingPaymentsJob.");
21 |
22 | Donation[] donations = instance.getPendingDonations().values().stream()
23 | .filter(donation -> donation.getPlayer().getUsername().equals(this.username))
24 | .toArray(Donation[]::new);
25 | if (donations.length == 0) {
26 | return;
27 | }
28 |
29 | instance.getLogger().debug("Executing pending donations for player " + this.username);
30 | new ExecuteDonationsJob(instance, donations);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/logging/CraftingStoreLogger.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.logging;
2 |
3 | public abstract class CraftingStoreLogger {
4 |
5 | private boolean debugging;
6 |
7 | public abstract void info(String message);
8 |
9 | public abstract void error(String message);
10 |
11 | public void debug(String message) {
12 | if (this.debugging) {
13 | this.info(message);
14 | }
15 | }
16 |
17 | public void setDebugging(boolean debugging) {
18 | this.debugging = debugging;
19 | if (debugging) {
20 | this.debug("Debug logging has been enabled!");
21 | }
22 | }
23 |
24 | public boolean isDebugging() {
25 | return this.debugging;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/logging/impl/JavaLogger.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.logging.impl;
2 |
3 | import net.craftingstore.core.logging.CraftingStoreLogger;
4 |
5 | import java.util.logging.Level;
6 | import java.util.logging.Logger;
7 |
8 | public class JavaLogger extends CraftingStoreLogger {
9 |
10 | private Logger logger;
11 |
12 | public JavaLogger(Logger logger) {
13 | this.logger = logger;
14 | }
15 |
16 | public void info(String message) {
17 | logger.info(message);
18 | }
19 |
20 | public void error(String message) {
21 | logger.log(Level.SEVERE, message);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/ApiCategory.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api;
2 |
3 | public class ApiCategory {
4 |
5 | private int id;
6 | private String name;
7 | private String description;
8 | private String minecraftIconName;
9 | private String url;
10 | private Boolean subCategory;
11 | private Package packages[];
12 |
13 | public int getId() {
14 | return id;
15 | }
16 |
17 | public String getName() {
18 | return name;
19 | }
20 |
21 | public String getDescription() {
22 | return description;
23 | }
24 |
25 | public String getMinecraftIconName() {
26 | return minecraftIconName;
27 | }
28 |
29 | public String getUrl() {
30 | return url;
31 | }
32 |
33 | public Boolean isSubCategory() {
34 | return subCategory;
35 | }
36 |
37 | public Package[] getpackages() {
38 | return packages;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/ApiDonation.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | public class ApiDonation {
6 | @SerializedName("id")
7 | private int commandId;
8 | private int paymentId;
9 | private String command;
10 | @SerializedName("mcName")
11 | private String username;
12 | private String uuid;
13 | private String packageName;
14 | private boolean requireOnline;
15 | private int packagePriceCents;
16 | private int couponDiscount;
17 |
18 | public int getCommandId() {
19 | return commandId;
20 | }
21 |
22 | public int getPaymentId() {
23 | return paymentId;
24 | }
25 |
26 | public String getCommand() {
27 | return command;
28 | }
29 |
30 | public String getMcName() {
31 | return username;
32 | }
33 |
34 | public String getUuid() {
35 | return uuid;
36 | }
37 |
38 | public String getPackageName() {
39 | return packageName;
40 | }
41 |
42 | public boolean getRequireOnline() {
43 | return requireOnline;
44 | }
45 |
46 | public int getPackagePriceCents() {
47 | return packagePriceCents;
48 | }
49 |
50 | public int getCouponDiscount() {
51 | return couponDiscount;
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/ApiInventory.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api;
2 |
3 | import net.craftingstore.core.models.api.inventory.InventoryItem;
4 |
5 | public class ApiInventory {
6 | private String title;
7 | private InventoryItem[] content;
8 | private int size;
9 | private ApiInventory buyMenu;
10 |
11 | public String getTitle() {
12 | return title;
13 | }
14 |
15 | public InventoryItem[] getContent() {
16 | return content;
17 | }
18 |
19 | public int getSize() {
20 | return size;
21 | }
22 |
23 | public ApiInventory getBuyMenu() {
24 | return buyMenu;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/ApiPackageInformation.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api;
2 |
3 | public class ApiPackageInformation {
4 | private boolean mayBuy;
5 | private int price;
6 | private String message;
7 |
8 | public boolean isAllowedToBuy() {
9 | return mayBuy;
10 | }
11 |
12 | public int getPrice() {
13 | return price;
14 | }
15 |
16 | public String getMessage() {
17 | return message;
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/ApiPayment.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api;
2 |
3 | import com.google.gson.annotations.SerializedName;
4 |
5 | public class ApiPayment {
6 |
7 | @SerializedName("playerName")
8 | private String username;
9 |
10 | private String gateway;
11 | private long timestamp;
12 | private String discount;
13 | private String coupon;
14 | private String price;
15 |
16 | private int packageId;
17 | private String packageName;
18 |
19 | public String getUsername() {
20 | return username;
21 | }
22 |
23 | public String getGateway() {
24 | return gateway;
25 | }
26 |
27 | public long getTimestamp() {
28 | return timestamp;
29 | }
30 |
31 | public String getDiscount() {
32 | return discount;
33 | }
34 |
35 | public String getCoupon() {
36 | return coupon;
37 | }
38 |
39 | public String getPrice() {
40 | return price;
41 | }
42 |
43 | public String getPackageName() {
44 | return packageName;
45 | }
46 |
47 | public int getPackageId() {
48 | return packageId;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/ApiTopDonator.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api;
2 |
3 | public class ApiTopDonator {
4 |
5 | private String mcName;
6 | private float total;
7 | private String uuid;
8 |
9 | public String getUsername() {
10 | return mcName;
11 | }
12 |
13 | public float getTotal() {
14 | return total;
15 | }
16 |
17 | public String getUuid() {
18 | return uuid;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/Root.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api;
2 |
3 | public class Root {
4 |
5 | private T result;
6 | private boolean success;
7 | private int error;
8 | private String message;
9 |
10 | public T getResult() {
11 | return result;
12 | }
13 |
14 | public boolean isSuccess() {
15 | return success;
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/RootV7.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api;
2 |
3 | public class RootV7 {
4 |
5 | private T data;
6 | private boolean success;
7 | private String message;
8 |
9 | public T getData() {
10 | return data;
11 | }
12 |
13 | public boolean isSuccess() {
14 | return success;
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/CraftingStoreInventory.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory;
2 |
3 | import java.util.Arrays;
4 |
5 | public class CraftingStoreInventory {
6 | private String title;
7 | private InventoryItem[] content;
8 | private int size;
9 |
10 | public CraftingStoreInventory() {
11 | }
12 |
13 | public CraftingStoreInventory(String title, InventoryItem[] content, int size) {
14 | this.title = title;
15 | this.content = content;
16 | this.size = size;
17 | }
18 |
19 | public String getTitle() {
20 | return title;
21 | }
22 |
23 | public InventoryItem[] getContent() {
24 | return content;
25 | }
26 |
27 | public int getSize() {
28 | return size;
29 | }
30 |
31 | public InventoryItem getByIndex(int index) {
32 | return Arrays.stream(content).filter(i -> i.getIndex() == index).findFirst().orElse(null);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/InventoryItem.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory;
2 |
3 | public class InventoryItem {
4 | protected String name;
5 | protected String[] description;
6 | protected InventoryItemType type;
7 | protected InventoryItemIcon icon;
8 | protected int index;
9 |
10 | public InventoryItem() {
11 |
12 | }
13 |
14 | public InventoryItem(String name, String[] description, InventoryItemType type, InventoryItemIcon icon, int index) {
15 | this.name = name;
16 | this.description = description;
17 | this.type = type;
18 | this.icon = icon;
19 | this.index = index;
20 | }
21 |
22 | public String getName() {
23 | return name;
24 | }
25 |
26 | public String[] getDescription() {
27 | return description;
28 | }
29 |
30 | public InventoryItemType getType() {
31 | return type;
32 | }
33 |
34 | public InventoryItemIcon getIcon() {
35 | return icon;
36 | }
37 |
38 | public int getIndex() {
39 | return index;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/InventoryItemEnhancement.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory;
2 |
3 | public class InventoryItemEnhancement {
4 | private String key;
5 | private int level;
6 |
7 | public String getKey() {
8 | return key;
9 | }
10 |
11 | public int getLevel() {
12 | return level;
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/InventoryItemIcon.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory;
2 |
3 | public class InventoryItemIcon {
4 | private String material;
5 | private Integer amount;
6 | private int customModelData;
7 | private InventoryItemEnhancement[] enhancements;
8 |
9 | public InventoryItemIcon() {
10 | }
11 |
12 | public InventoryItemIcon(String material, Integer amount, int customModelData, InventoryItemEnhancement[] enhancements) {
13 | this.material = material;
14 | this.amount = amount;
15 | this.customModelData = customModelData;
16 | this.enhancements = enhancements;
17 | }
18 |
19 | public String getMaterial() {
20 | return material;
21 | }
22 |
23 | public int getAmount() {
24 | return amount;
25 | }
26 |
27 | public Integer getCustomModelData() {
28 | return customModelData;
29 | }
30 |
31 | public InventoryItemEnhancement[] getEnhancements() {
32 | return enhancements;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/InventoryItemType.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory;
2 |
3 | import net.craftingstore.core.models.api.inventory.types.*;
4 |
5 | public enum InventoryItemType {
6 | NULL(null),
7 | CATEGORY(InventoryItemCategory.class),
8 | MESSAGE(InventoryItemMessage.class),
9 | BACK(InventoryItemBackButton.class),
10 | CLOSE(InventoryItemCloseButton.class),
11 | BUYABLE_PACKAGE(InventoryItemBuyablePackage.class),
12 | BUY_DETAILS(InventoryItemBuyDetails.class),
13 | BUY_BUTTON(InventoryItemBuyButton.class);
14 |
15 | private final Class extends InventoryItem> c;
16 |
17 | InventoryItemType(Class extends InventoryItem> c) {
18 | this.c = c;
19 | }
20 |
21 | public Class extends InventoryItem> getActualClass() {
22 | return c;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/types/InventoryItemBackButton.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory.types;
2 |
3 | import net.craftingstore.core.models.api.inventory.InventoryItem;
4 | import net.craftingstore.core.models.api.inventory.InventoryItemIcon;
5 | import net.craftingstore.core.models.api.inventory.InventoryItemType;
6 |
7 | public class InventoryItemBackButton extends InventoryItem {
8 |
9 | public InventoryItemBackButton() {}
10 |
11 | public InventoryItemBackButton(
12 | String name,
13 | String[] description,
14 | InventoryItemIcon icon,
15 | int index
16 | ) {
17 | super(name, description, InventoryItemType.BACK, icon, index);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/types/InventoryItemBuyButton.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory.types;
2 |
3 | import net.craftingstore.core.models.api.inventory.InventoryItem;
4 | import net.craftingstore.core.models.api.inventory.InventoryItemIcon;
5 | import net.craftingstore.core.models.api.inventory.InventoryItemType;
6 |
7 | public class InventoryItemBuyButton extends InventoryItem {
8 | private final InventoryItemBuyButtonAction action;
9 |
10 | public InventoryItemBuyButton(
11 | String name,
12 | String[] description,
13 | InventoryItemIcon icon,
14 | int index,
15 | InventoryItemBuyButtonAction action
16 | ) {
17 | super(name, description, InventoryItemType.BUY_BUTTON, icon, index);
18 | this.action = action;
19 | }
20 |
21 | public InventoryItemBuyButtonAction getAction() {
22 | return action;
23 | }
24 |
25 | public enum InventoryItemBuyButtonAction {
26 | IN_GAME,
27 | ONLINE,
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/types/InventoryItemBuyDetails.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory.types;
2 |
3 | import net.craftingstore.core.models.api.inventory.InventoryItem;
4 | import net.craftingstore.core.models.api.inventory.InventoryItemIcon;
5 | import net.craftingstore.core.models.api.inventory.InventoryItemType;
6 |
7 | public class InventoryItemBuyDetails extends InventoryItem {
8 |
9 | public InventoryItemBuyDetails() {}
10 |
11 | public InventoryItemBuyDetails(
12 | String name,
13 | String[] description,
14 | InventoryItemIcon icon,
15 | int index
16 | ) {
17 | super(name, description, InventoryItemType.BUY_DETAILS, icon, index);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/types/InventoryItemBuyablePackage.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory.types;
2 |
3 | import net.craftingstore.core.models.api.inventory.InventoryItem;
4 |
5 | public class InventoryItemBuyablePackage extends InventoryItem {
6 | private int price;
7 | private int packageId;
8 | private String[] messages;
9 | private String successMessage;
10 |
11 | public InventoryItemBuyablePackage() {
12 |
13 | }
14 |
15 | public int getPrice() {
16 | return price;
17 | }
18 |
19 | public int getPackageId() {
20 | return packageId;
21 | }
22 |
23 | public String[] getMessages() {
24 | return messages;
25 | }
26 |
27 | public String getSuccessMessage() {
28 | return successMessage;
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/types/InventoryItemCategory.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory.types;
2 |
3 | import net.craftingstore.core.models.api.inventory.InventoryItem;
4 |
5 | public class InventoryItemCategory extends InventoryItem {
6 | private String title;
7 | private InventoryItem[] content;
8 | private int size;
9 |
10 | public String getTitle() {
11 | return title;
12 | }
13 |
14 | public InventoryItem[] getContent() {
15 | return content;
16 | }
17 |
18 | public int getSize() {
19 | return size;
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/types/InventoryItemCloseButton.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory.types;
2 |
3 | import net.craftingstore.core.models.api.inventory.InventoryItem;
4 |
5 | public class InventoryItemCloseButton extends InventoryItem {
6 | }
7 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/inventory/types/InventoryItemMessage.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.inventory.types;
2 |
3 | import net.craftingstore.core.models.api.inventory.InventoryItem;
4 | import net.craftingstore.core.models.api.inventory.InventoryItemIcon;
5 | import net.craftingstore.core.models.api.inventory.InventoryItemType;
6 |
7 | public class InventoryItemMessage extends InventoryItem {
8 | private String[] messages;
9 | private boolean close;
10 |
11 | public InventoryItemMessage() {
12 | }
13 |
14 | public InventoryItemMessage(
15 | String name,
16 | String[] description,
17 | InventoryItemIcon icon,
18 | int index,
19 | String[] messages,
20 | boolean close
21 | ) {
22 | super(name, description, InventoryItemType.MESSAGE, icon, index);
23 | this.messages = messages;
24 | this.close = close;
25 | }
26 |
27 | public String[] getMessages() {
28 | return messages;
29 | }
30 |
31 | public boolean shouldClose() {
32 | return close;
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/misc/ApiKeyResult.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.misc;
2 |
3 | public class ApiKeyResult {
4 |
5 | private boolean success;
6 |
7 | public boolean isSuccess() {
8 | return success;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/misc/CraftingStoreInformation.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.misc;
2 |
3 | import net.craftingstore.core.models.api.provider.ProviderInformation;
4 |
5 | public class CraftingStoreInformation {
6 |
7 | private UpdateInformation update;
8 | private ProviderInformation[] providers;
9 |
10 | public UpdateInformation getUpdateInformation() {
11 | return update;
12 | }
13 |
14 | public ProviderInformation[] getProviders() {
15 | return providers;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/misc/UpdateInformation.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.misc;
2 |
3 | public class UpdateInformation {
4 |
5 | private String message;
6 | private boolean disable;
7 |
8 | public String getMessage() {
9 | return message;
10 | }
11 |
12 | public boolean shouldDisable() {
13 | return disable;
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/provider/ProviderInformation.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.provider;
2 |
3 | public class ProviderInformation {
4 |
5 | private ProviderType type;
6 | private int priority;
7 |
8 | public ProviderType getType() {
9 | return type;
10 | }
11 |
12 | public int getPriority() {
13 | return priority;
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/provider/ProviderType.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.provider;
2 |
3 | import net.craftingstore.core.provider.CraftingStoreProvider;
4 | import net.craftingstore.core.provider.SocketProvider;
5 |
6 | public enum ProviderType {
7 | SOCKET(SocketProviderInformation.class, SocketProvider.class);
8 |
9 | private Class c;
10 | private Class extends CraftingStoreProvider> implementation;
11 |
12 | ProviderType(Class c, Class extends CraftingStoreProvider> implementation) {
13 | this.c = c;
14 | this.implementation = implementation;
15 | }
16 |
17 | public Class getActualClass() {
18 | return c;
19 | }
20 |
21 | public Class extends CraftingStoreProvider> getImplementation() {
22 | return implementation;
23 | }
24 | }
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/provider/SocketProviderInformation.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.provider;
2 |
3 | public class SocketProviderInformation extends ProviderInformation {
4 |
5 | private String url;
6 |
7 | public String getUrl() {
8 | return url;
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/request/PackageInformationRequest.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.request;
2 |
3 | import java.io.Serializable;
4 |
5 | public class PackageInformationRequest implements Serializable {
6 | String inGameName;
7 | String uuid;
8 | String ip;
9 | int packageId;
10 |
11 | public PackageInformationRequest(String inGameName, String uuid, String ip, int packageId) {
12 | this.inGameName = inGameName;
13 | this.uuid = uuid;
14 | this.ip = ip;
15 | this.packageId = packageId;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/api/request/PaymentCreateRequest.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.api.request;
2 |
3 | public class PaymentCreateRequest {
4 | String inGameName;
5 | String notes;
6 | String gateway;
7 | int inGamePricePaid;
8 | Integer pricePaid;
9 | boolean executeCommands;
10 | int[] packages;
11 |
12 | public PaymentCreateRequest(
13 | String inGameName,
14 | String notes,
15 | String gateway,
16 | int inGamePricePaid,
17 | Integer pricePaid,
18 | boolean executeCommands,
19 | int[] packages
20 | ) {
21 | this.inGameName = inGameName;
22 | this.notes = notes;
23 | this.gateway = gateway;
24 | this.inGamePricePaid = inGamePricePaid;
25 | this.pricePaid = pricePaid;
26 | this.executeCommands = executeCommands;
27 | this.packages = packages;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/donation/Donation.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.donation;
2 |
3 | public class Donation {
4 |
5 | private int commandId;
6 | private int paymentId;
7 | private String command;
8 | private DonationPlayer player;
9 | private DonationPackage donationPackage;
10 | private int discount;
11 |
12 | public Donation(int commandId, int paymentId, String command, DonationPlayer player, DonationPackage donationPackage, int discount) {
13 | this.commandId = commandId;
14 | this.paymentId = paymentId;
15 | this.command = command;
16 | this.player = player;
17 | this.donationPackage = donationPackage;
18 | this.discount = discount;
19 | }
20 |
21 | @Deprecated
22 | public int getId() {
23 | return commandId;
24 | }
25 |
26 | public int getCommandId() {
27 | return commandId;
28 | }
29 |
30 | public int getPaymentId() {
31 | return paymentId;
32 | }
33 |
34 | public String getCommand() {
35 | return command;
36 | }
37 |
38 | public DonationPlayer getPlayer() {
39 | return player;
40 | }
41 |
42 | public DonationPackage getPackage() {
43 | return donationPackage;
44 | }
45 |
46 | public int getDiscount() {
47 | return discount;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/donation/DonationPackage.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.donation;
2 |
3 | import java.math.BigDecimal;
4 |
5 | public class DonationPackage {
6 |
7 | private String name;
8 | private int priceInCents;
9 |
10 | public DonationPackage(String name, int priceInCents) {
11 | this.name = name;
12 | this.priceInCents = priceInCents;
13 | }
14 |
15 | public String getName() {
16 | return this.name;
17 | }
18 |
19 | @Deprecated
20 | public int getPrice() {
21 | return (int) Math.round(this.priceInCents / 100d);
22 | }
23 |
24 | public BigDecimal getPriceDecimal() {
25 | return BigDecimal.valueOf(this.priceInCents / 100d);
26 | }
27 |
28 | public int getPriceInCents() {
29 | return this.priceInCents;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/models/donation/DonationPlayer.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.models.donation;
2 |
3 | import java.util.UUID;
4 |
5 | public class DonationPlayer {
6 |
7 | private String username;
8 | private UUID uuid;
9 | private boolean requiredOnline;
10 |
11 | public DonationPlayer(String username, String uuid, boolean requiredOnline) {
12 | this.username = username;
13 | this.requiredOnline = requiredOnline;
14 | if (uuid != null && !uuid.isEmpty()) {
15 | uuid = uuid.replaceFirst("([0-9a-fA-F]{8})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]{4})([0-9a-fA-F]+)", "$1-$2-$3-$4-$5");
16 | this.uuid = UUID.fromString(uuid);
17 | }
18 | }
19 |
20 | public String getUsername() {
21 | return username;
22 | }
23 |
24 | public UUID getUUID() {
25 | return uuid;
26 | }
27 |
28 | public boolean isRequiredOnline() {
29 | return requiredOnline;
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/provider/CraftingStoreProvider.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.provider;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 | import net.craftingstore.core.models.api.provider.ProviderInformation;
5 |
6 | public abstract class CraftingStoreProvider {
7 |
8 | CraftingStore craftingStore;
9 | ProviderInformation information;
10 | ProviderStatus status;
11 |
12 | public CraftingStoreProvider(CraftingStore craftingStore, ProviderStatus status) {
13 | this.craftingStore = craftingStore;
14 | this.status = status;
15 | this.information = status.getInformation();
16 | }
17 |
18 | public abstract boolean isConnected();
19 |
20 | public abstract void disconnect();
21 |
22 | public void disconnected() {
23 | craftingStore.getLogger().debug("Disconnected from provider " + information.getType());
24 | if (!craftingStore.isEnabled()) {
25 | return;
26 | }
27 | this.status.setRetries(this.status.getRetries() + 1);
28 | this.status.setLastFailed(System.currentTimeMillis());
29 | this.craftingStore.getProviderSelector().selectProvider();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/provider/ProviderSelector.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.provider;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 | import net.craftingstore.core.models.api.provider.ProviderInformation;
5 |
6 | import java.lang.reflect.Constructor;
7 | import java.lang.reflect.InvocationTargetException;
8 | import java.util.Arrays;
9 | import java.util.Comparator;
10 | import java.util.List;
11 | import java.util.function.Function;
12 | import java.util.stream.Collectors;
13 |
14 | public class ProviderSelector {
15 |
16 | private CraftingStore instance;
17 | private ProviderStatus[] providers;
18 | private CraftingStoreProvider currentProvider;
19 |
20 | public ProviderSelector(CraftingStore instance) {
21 | this.instance = instance;
22 | }
23 |
24 | public void setProviders(ProviderStatus[] providers) {
25 | this.providers = providers;
26 | }
27 |
28 | public void setProviders(ProviderInformation[] providers) {
29 | this.providers = Arrays.stream(providers)
30 | .map((Function) ProviderStatus::new)
31 | .toArray(ProviderStatus[]::new);
32 | }
33 |
34 | public void selectProvider() {
35 | if (currentProvider != null && currentProvider.isConnected()) {
36 | currentProvider.disconnect();
37 | return;
38 | }
39 | currentProvider = getAvailableProvider();
40 | }
41 |
42 | private CraftingStoreProvider getAvailableProvider() {
43 | long disallowedRange = System.currentTimeMillis() - (1000 * 60); // 1 minute
44 | List availableProviders = Arrays.stream(providers)
45 | .filter(p -> p.getLastFailed() < disallowedRange)
46 | .sorted(Comparator.comparingInt(p -> p.getInformation().getPriority()))
47 | .collect(Collectors.toList());
48 | if (availableProviders.size() == 0) {
49 | instance.getLogger().debug("No providers available");
50 | return null;
51 | }
52 | ProviderStatus status = availableProviders.get(0);
53 | Class extends CraftingStoreProvider> implementation = status.getInformation().getType().getImplementation();
54 | try {
55 | Constructor> ctor = implementation.getConstructor(CraftingStore.class, ProviderStatus.class);
56 | return (CraftingStoreProvider) ctor.newInstance(instance, status);
57 | } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
58 | e.printStackTrace();
59 | }
60 | return null;
61 | }
62 |
63 | public CraftingStoreProvider getCurrentProvider() {
64 | return currentProvider;
65 | }
66 |
67 | public boolean isConnected() {
68 | return getCurrentProvider() != null && getCurrentProvider().isConnected();
69 | }
70 |
71 | public void disconnect() {
72 | if (isConnected()) {
73 | getCurrentProvider().disconnect();
74 | }
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/provider/ProviderStatus.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.provider;
2 |
3 | import net.craftingstore.core.models.api.provider.ProviderInformation;
4 |
5 | public class ProviderStatus {
6 | private ProviderInformation information;
7 | private long lastFailed;
8 | private int retries;
9 |
10 | public ProviderStatus(ProviderInformation information) {
11 | this.information = information;
12 | }
13 |
14 | public long getLastFailed() {
15 | return lastFailed;
16 | }
17 |
18 | public void setLastFailed(long lastFailed) {
19 | this.lastFailed = lastFailed;
20 | }
21 |
22 | public int getRetries() {
23 | return retries;
24 | }
25 |
26 | public void setRetries(int retries) {
27 | this.retries = retries;
28 | }
29 |
30 | public ProviderInformation getInformation() {
31 | return information;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/provider/SocketProvider.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.provider;
2 |
3 | import io.socket.client.IO;
4 | import io.socket.client.Socket;
5 | import net.craftingstore.core.CraftingStore;
6 | import net.craftingstore.core.models.api.provider.SocketProviderInformation;
7 |
8 | import java.net.URISyntaxException;
9 |
10 | public class SocketProvider extends CraftingStoreProvider {
11 |
12 | private Socket client;
13 | private static final long DISABLE_TIMEOUT = 5 * 1000;
14 |
15 | public SocketProvider(CraftingStore craftingStore, ProviderStatus status) {
16 | super(craftingStore, status);
17 | this.connect();
18 | }
19 |
20 | @Override
21 | public boolean isConnected() {
22 | return client != null && client.connected();
23 | }
24 |
25 | @Override
26 | public void disconnect() {
27 | if (client != null) {
28 | client.disconnect();
29 | // Let the current thread wait until disconnected, to prevent the server from killing the threads.
30 | try {
31 | long disconnectStart = System.currentTimeMillis();
32 | while (client.connected()) {
33 | Thread.sleep(5);
34 | if (System.currentTimeMillis() - disconnectStart > DISABLE_TIMEOUT) {
35 | break;
36 | }
37 | }
38 | // Wait some time on SocketIO
39 | Thread.sleep(200);
40 | } catch (InterruptedException e) {
41 | e.printStackTrace();
42 | }
43 | }
44 | }
45 |
46 | private void connect() {
47 | SocketProviderInformation information = (SocketProviderInformation) this.information;
48 | try {
49 | IO.Options options = new IO.Options();
50 | options.reconnection = false;
51 | this.client = IO.socket(information.getUrl(), options);
52 |
53 | // Authenticate
54 | this.client.on(Socket.EVENT_CONNECT, (Object... args) -> {
55 | craftingStore.getLogger().debug("Socket server connected, sending authentication token");
56 | this.client.emit("auth-client", this.craftingStore.getApi().getToken());
57 | });
58 | this.client.on(Socket.EVENT_DISCONNECT, (Object... args) -> {
59 | craftingStore.getLogger().debug("Socket server disconnected, reason: " + args[0]);
60 | this.disconnected();
61 | });
62 | this.client.on(Socket.EVENT_CONNECT_ERROR, (Object... args) -> {
63 | craftingStore.getLogger().debug("Socket server connect error event called");
64 | this.disconnected();
65 | if (!craftingStore.getLogger().isDebugging()) {
66 | return;
67 | }
68 | for (Object arg : args) {
69 | if (arg instanceof Exception) {
70 | ((Exception) arg).printStackTrace();
71 | }
72 | }
73 | });
74 | this.client.on("authenticated", (Object... args) -> {
75 | craftingStore.getLogger().debug("Socket server authenticated");
76 | });
77 |
78 | this.client.on("receive-donation", (Object... args) -> {
79 | craftingStore.getLogger().debug("Received donation from Socket server");
80 | this.craftingStore.executeQueue();
81 | });
82 | this.client.on("reload-plugin", (Object... args) -> this.craftingStore.reload());
83 | this.client.on("disable-plugin", (Object... args) -> {
84 | if (args.length > 0) {
85 | craftingStore.getLogger().error(args[0].toString());
86 | }
87 | this.craftingStore.setEnabled(false);
88 | });
89 | this.client.on(Socket.EVENT_ERROR, (Object... args) -> {
90 | craftingStore.getLogger().debug("Socket error event called");
91 | if (!craftingStore.getLogger().isDebugging()) {
92 | return;
93 | }
94 | for (Object arg : args) {
95 | if (arg instanceof Exception) {
96 | ((Exception) arg).printStackTrace();
97 | }
98 | }
99 | });
100 | this.client.on(Socket.EVENT_RECONNECT, (Object... args) -> {
101 | craftingStore.getLogger().debug("Socket reconnect event called");
102 | });
103 | this.client.on(Socket.EVENT_MESSAGE, (Object... args) -> {
104 | craftingStore.getLogger().debug("Socket message event called");
105 | });
106 | this.client.connect();
107 | craftingStore.getLogger().debug("Connecting to CraftingStore websocket at " + information.getUrl());
108 | } catch (URISyntaxException e) {
109 | e.printStackTrace();
110 | }
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/runner/DonationRunner.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.runner;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
5 | import net.craftingstore.core.jobs.ExecuteDonationsJob;
6 | import net.craftingstore.core.models.donation.Donation;
7 | import net.craftingstore.core.util.ArrayUtil;
8 |
9 | import java.util.Arrays;
10 | import java.util.List;
11 | import java.util.concurrent.ExecutionException;
12 | import java.util.concurrent.ExecutorService;
13 | import java.util.concurrent.Executors;
14 | import java.util.stream.Stream;
15 |
16 | public class DonationRunner {
17 |
18 | protected ExecutorService executor = Executors.newSingleThreadExecutor();
19 | protected CraftingStore craftingStore;
20 |
21 | public DonationRunner(CraftingStore craftingStore) {
22 | this.craftingStore = craftingStore;
23 | }
24 |
25 | public void runDonations() {
26 | this.craftingStore.getLogger().debug("Scheduling new donation runner job.");
27 | this.executor.submit(() -> {
28 | this.craftingStore.getLogger().debug("Requesting donation queue.");
29 | try {
30 | Donation[] donationQueue = this.craftingStore.getApi().getDonationQueue().get();
31 | this.craftingStore.getLogger().debug(String.format("Found %d donations in queue.", donationQueue.length));
32 | Donation[][] chunked = ArrayUtil.splitArray(donationQueue, ExecuteDonationsJob.CHUNK_SIZE);
33 | for (int i = 0; i < chunked.length; i++) {
34 | Donation[] chunk = chunked[i];
35 | this.craftingStore.getLogger().debug(String.format("Creating ExecuteDonationsJob for chunk %d/%d", i + 1, chunked.length));
36 | new ExecuteDonationsJob(this.craftingStore, chunk);
37 | }
38 | } catch (CraftingStoreApiException | InterruptedException | ExecutionException e) {
39 | if (craftingStore.getLogger().isDebugging()) {
40 | e.printStackTrace();
41 | } else {
42 | craftingStore.getLogger().info("Failed to retrieve donation. The plugin will retry every 30 minutes.");
43 | }
44 | }
45 | });
46 | }
47 |
48 | public ExecutorService getExecutor() {
49 | return executor;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/scheduler/APICacheRenewer.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.scheduler;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 | import net.craftingstore.core.http.CraftingStoreCachedAPI;
5 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
6 |
7 | import java.util.concurrent.ExecutionException;
8 |
9 | public class APICacheRenewer implements Runnable {
10 |
11 | private CraftingStore instance;
12 |
13 | public APICacheRenewer(CraftingStore instance) {
14 | this.instance = instance;
15 | }
16 |
17 |
18 | @Override
19 | public void run() {
20 | if (!instance.isEnabled()) {
21 | return;
22 | }
23 | if (!(instance.getApi() instanceof CraftingStoreCachedAPI)) {
24 | return;
25 | }
26 | CraftingStoreCachedAPI api = (CraftingStoreCachedAPI) instance.getApi();
27 | this.instance.getLogger().debug("Refreshing API cache.");
28 | try {
29 | api.refreshPaymentsCache();
30 | api.refreshTopDonatorsCache();
31 | } catch (CraftingStoreApiException | ExecutionException | InterruptedException e) {
32 | if (this.instance.getLogger().isDebugging()) {
33 | e.printStackTrace();
34 | } else {
35 | instance.getLogger().error("Failed to renew API cache. If this issue persists, please contact support at https://craftingstore.net.");
36 | }
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/scheduler/DonationChecker.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.scheduler;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
5 | import net.craftingstore.core.jobs.ExecuteDonationsJob;
6 | import net.craftingstore.core.models.donation.Donation;
7 | import net.craftingstore.core.util.ArrayUtil;
8 |
9 | import java.util.Arrays;
10 | import java.util.concurrent.ExecutionException;
11 |
12 | public class DonationChecker implements Runnable {
13 |
14 | private CraftingStore instance;
15 | private long lastRun = 0;
16 |
17 | public DonationChecker(CraftingStore instance) {
18 | this.instance = instance;
19 | }
20 |
21 | public void run() {
22 | if (!instance.isEnabled()) {
23 | return;
24 | }
25 | if (instance.getProviderSelector().isConnected()) {
26 | // Only run this runnable every 30 minutes when we are connected to a websocket.
27 | long target = System.currentTimeMillis() - (30 * 60 * 1000);
28 | if (lastRun > target) {
29 | return;
30 | }
31 | }
32 | lastRun = System.currentTimeMillis();
33 | this.instance.getLogger().debug("Checking for donations by interval.");
34 | this.instance.getDonationRunner().runDonations();
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/scheduler/InformationUpdater.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.scheduler;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 |
5 | public class InformationUpdater implements Runnable {
6 |
7 | private CraftingStore instance;
8 |
9 | public InformationUpdater(CraftingStore instance) {
10 | this.instance = instance;
11 | }
12 |
13 | public void run() {
14 | this.instance.getLogger().debug("Reloading plugin");
15 | instance.reload();
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/scheduler/InventoryRenewer.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.scheduler;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 | import net.craftingstore.core.http.CraftingStoreCachedAPI;
5 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
6 |
7 | import java.util.concurrent.ExecutionException;
8 |
9 | public class InventoryRenewer implements Runnable {
10 |
11 | private CraftingStore instance;
12 |
13 | public InventoryRenewer(CraftingStore instance) {
14 | this.instance = instance;
15 | }
16 |
17 | @Override
18 | public void run() {
19 | if (!instance.isEnabled()) {
20 | return;
21 | }
22 | if (!(instance.getApi() instanceof CraftingStoreCachedAPI)) {
23 | return;
24 | }
25 | CraftingStoreCachedAPI api = (CraftingStoreCachedAPI) instance.getApi();
26 | instance.getLogger().debug("Refreshing GUI cache.");
27 | try {
28 | api.refreshGUICache();
29 | } catch (CraftingStoreApiException | ExecutionException | InterruptedException e) {
30 | if (instance.getLogger().isDebugging()) {
31 | e.printStackTrace();
32 | } else {
33 | instance.getLogger().error("Failed to renew GUI cache. If this issue persists, please contact support at https://craftingstore.net.");
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/scheduler/ProviderChecker.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.scheduler;
2 |
3 | import net.craftingstore.core.CraftingStore;
4 |
5 | public class ProviderChecker implements Runnable {
6 |
7 | private CraftingStore instance;
8 |
9 | public ProviderChecker(CraftingStore instance) {
10 | this.instance = instance;
11 | }
12 |
13 | @Override
14 | public void run() {
15 | if (!instance.isEnabled()) {
16 | return;
17 | }
18 | if (instance.getProviderSelector().getCurrentProvider() == null ||
19 | !instance.getProviderSelector().getCurrentProvider().isConnected()) {
20 | instance.getLogger().debug("Reconnecting to a provider.");
21 | instance.getProviderSelector().selectProvider();
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/core/src/main/java/net/craftingstore/core/util/ArrayUtil.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.core.util;
2 |
3 | import java.lang.reflect.Array;
4 | import java.util.Arrays;
5 |
6 | public class ArrayUtil {
7 |
8 | public static T[][] splitArray(T[] arrayToSplit, int chunkSize) {
9 | if (chunkSize <= 0) {
10 | return (T[][]) Array.newInstance(arrayToSplit.getClass(), 0);
11 | }
12 | int rest = arrayToSplit.length % chunkSize;
13 | int chunks = arrayToSplit.length / chunkSize + (rest > 0 ? 1 : 0);
14 | T[][] arrays = (T[][]) Array.newInstance(arrayToSplit.getClass(), chunks);
15 |
16 | for (int i = 0; i < (rest > 0 ? chunks - 1 : chunks); i++) {
17 | arrays[i] = Arrays.copyOfRange(arrayToSplit, i * chunkSize, i * chunkSize + chunkSize);
18 | }
19 | if (rest > 0) {
20 | arrays[chunks - 1] = Arrays.copyOfRange(arrayToSplit, (chunks - 1) * chunkSize, (chunks - 1) * chunkSize + rest);
21 | }
22 | return arrays;
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | net.craftingstore
8 | craftingstore
9 | pom
10 | ${revision}
11 |
12 |
13 | ${craftingstore-version}-RELEASE
14 | 2.10.0
15 |
16 |
17 |
18 |
19 |
20 | org.codehaus.mojo
21 | flatten-maven-plugin
22 | 1.1.0
23 |
24 | true
25 | resolveCiFriendliesOnly
26 |
27 |
28 |
29 | flatten
30 | process-resources
31 |
32 | flatten
33 |
34 |
35 |
36 | flatten.clean
37 | clean
38 |
39 | clean
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | core
49 | bukkit
50 | bungee
51 | sponge
52 | assembly
53 | velocity
54 |
55 |
--------------------------------------------------------------------------------
/sponge/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | net.craftingstore
9 | craftingstore
10 | ${revision}
11 |
12 |
13 | sponge
14 |
15 |
16 |
17 |
18 | org.apache.maven.plugins
19 | maven-compiler-plugin
20 |
21 | 8
22 | 8
23 |
24 |
25 |
26 |
27 |
28 | src/main/java
29 | true
30 |
31 |
32 |
33 |
34 |
35 |
36 | sponge
37 | https://repo.spongepowered.org/maven
38 |
39 |
40 |
41 |
42 |
43 | net.craftingstore
44 | core
45 | ${project.version}
46 |
47 |
48 |
49 | org.spongepowered
50 | spongeapi
51 | 7.1.0
52 | provided
53 |
54 |
55 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/CraftingStoreSponge.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge;
2 |
3 | import com.google.inject.Inject;
4 | import com.google.inject.Injector;
5 | import net.craftingstore.core.CraftingStore;
6 | import net.craftingstore.sponge.commands.BuyCommand;
7 | import net.craftingstore.sponge.commands.CraftingStoreCommand;
8 | import net.craftingstore.sponge.config.Config;
9 | import net.craftingstore.sponge.listeners.InventoryClickListener;
10 | import net.craftingstore.sponge.listeners.PendingDonationJoinListener;
11 | import net.craftingstore.sponge.module.ConfigModule;
12 | import net.craftingstore.sponge.module.CraftingStoreModule;
13 | import org.spongepowered.api.Game;
14 | import org.spongepowered.api.command.args.GenericArguments;
15 | import org.spongepowered.api.command.spec.CommandSpec;
16 | import org.spongepowered.api.config.DefaultConfig;
17 | import org.spongepowered.api.event.Listener;
18 | import org.spongepowered.api.event.game.state.GameStartedServerEvent;
19 | import org.spongepowered.api.event.game.state.GameStoppedServerEvent;
20 | import org.spongepowered.api.plugin.Plugin;
21 | import org.spongepowered.api.text.LiteralText;
22 | import org.spongepowered.api.text.Text;
23 | import org.spongepowered.api.text.format.TextColors;
24 |
25 | import java.nio.file.Path;
26 |
27 | @Plugin(id = "craftingstore", name = "CraftingStore")
28 | public class CraftingStoreSponge {
29 | private CraftingStore craftingStore;
30 |
31 | @Inject
32 | private Game game;
33 |
34 | @Inject
35 | private Injector injector;
36 |
37 | @Inject
38 | @DefaultConfig(sharedRoot = false)
39 | private Path defaultConfig;
40 |
41 | private Config config;
42 |
43 | private LiteralText prefix = Text.builder("[").color(TextColors.GRAY)
44 | .append(Text.builder("CraftingStore").color(TextColors.RED).build())
45 | .append(Text.builder("] ").color(TextColors.WHITE).build()).build();
46 |
47 | @Listener
48 | public void onServerStart(GameStartedServerEvent event) {
49 | config = new Config(defaultConfig.toFile(), "config.yml");
50 | injector = injector.createChildInjector(new ConfigModule(config));
51 |
52 | this.craftingStore = new CraftingStore(injector.getInstance(CraftingStoreSpongeImpl.class));
53 | injector = injector.createChildInjector(new CraftingStoreModule(craftingStore));
54 |
55 | CommandSpec craftingStoreCommand = CommandSpec.builder()
56 | .description(Text.of("CraftingStore main command"))
57 | .permission(craftingStore.ADMIN_PERMISSION)
58 | .arguments(
59 | GenericArguments.optional(GenericArguments.string(Text.of("action"))),
60 | GenericArguments.optional(GenericArguments.string(Text.of("key")))
61 | )
62 | .executor(injector.getInstance(CraftingStoreCommand.class))
63 | .build();
64 |
65 | CommandSpec buyCommand = CommandSpec.builder()
66 | .description(Text.of("CraftingStore buy command"))
67 | .executor(injector.getInstance(BuyCommand.class))
68 | .build();
69 | game.getCommandManager().register(this, craftingStoreCommand, "craftingstore", "cs");
70 | if (this.craftingStore.getImplementation().getConfiguration().isBuyCommandEnabled()) {
71 | game.getCommandManager().register(this, buyCommand, "buy");
72 | }
73 |
74 | game.getEventManager().registerListeners(this, injector.getInstance(InventoryClickListener.class));
75 | game.getEventManager().registerListeners(this, injector.getInstance(PendingDonationJoinListener.class));
76 | }
77 |
78 | @Listener
79 | public void onServerStopped(GameStoppedServerEvent event) {
80 | if (this.craftingStore == null) {
81 | return;
82 | }
83 | this.craftingStore.setEnabled(false);
84 | }
85 |
86 | public Config getConfigWrapper() {
87 | return config;
88 | }
89 |
90 | public LiteralText getPrefix() {
91 | return prefix;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/CraftingStoreSpongeImpl.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge;
2 |
3 | import com.google.inject.Inject;
4 | import net.craftingstore.core.CraftingStorePlugin;
5 | import net.craftingstore.core.PluginConfiguration;
6 | import net.craftingstore.core.logging.CraftingStoreLogger;
7 | import net.craftingstore.core.models.donation.Donation;
8 | import net.craftingstore.sponge.config.Config;
9 | import net.craftingstore.sponge.events.DonationReceivedEvent;
10 | import net.craftingstore.sponge.logging.Slf4jLogger;
11 | import org.spongepowered.api.Game;
12 | import org.spongepowered.api.Platform;
13 | import org.spongepowered.api.Sponge;
14 | import org.spongepowered.api.entity.living.player.Player;
15 | import org.spongepowered.api.plugin.PluginContainer;
16 |
17 | import java.util.concurrent.TimeUnit;
18 |
19 | public class CraftingStoreSpongeImpl implements CraftingStorePlugin {
20 |
21 | @Inject
22 | private CraftingStoreSponge spongePlugin;
23 |
24 | @Inject
25 | private Game game;
26 |
27 | @Inject
28 | private Config config;
29 |
30 | @Inject
31 | private SpongePluginConfiguration configuration;
32 |
33 | private Slf4jLogger logger;
34 |
35 | @Inject
36 | private void setLogger(Slf4jLogger logger) {
37 | this.logger = logger;
38 | this.logger.setDebugging(this.config.getConfig().getNode("debug").getBoolean());
39 | }
40 |
41 | public boolean executeDonation(Donation donation) {
42 | if (donation.getPlayer().isRequiredOnline()) {
43 | Player player = game.getServer().getPlayer(donation.getPlayer().getUsername()).orElse(null);
44 | if (player == null || !player.isOnline()) {
45 | return false;
46 | }
47 | }
48 |
49 | DonationReceivedEvent event = new DonationReceivedEvent(donation);
50 | game.getEventManager().post(event);
51 | if (event.isCancelled()) {
52 | return false;
53 | }
54 |
55 | game.getScheduler().createTaskBuilder()
56 | .execute(() -> game.getCommandManager().process(game.getServer().getConsole(), donation.getCommand()))
57 | .submit(spongePlugin);
58 | return true;
59 | }
60 |
61 | public CraftingStoreLogger getLogger() {
62 | return this.logger;
63 | }
64 |
65 | public void registerRunnable(Runnable runnable, int delay, int interval) {
66 | game.getScheduler().createTaskBuilder()
67 | .execute(runnable)
68 | .async()
69 | .delay(delay, TimeUnit.SECONDS)
70 | .interval(interval, TimeUnit.SECONDS)
71 | .submit(spongePlugin);
72 | }
73 |
74 | public void runAsyncTask(Runnable runnable) {
75 | game.getScheduler().createTaskBuilder()
76 | .execute(runnable)
77 | .async()
78 | .submit(spongePlugin);
79 | }
80 |
81 | public String getToken() {
82 | return config.getConfig().getNode("api-key").getString();
83 | }
84 |
85 | @Override
86 | public PluginConfiguration getConfiguration() {
87 | return this.configuration;
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/SpongePluginConfiguration.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge;
2 |
3 | import com.google.inject.Inject;
4 | import net.craftingstore.core.PluginConfiguration;
5 | import org.spongepowered.api.Game;
6 | import org.spongepowered.api.Platform;
7 | import org.spongepowered.api.plugin.PluginContainer;
8 |
9 | public class SpongePluginConfiguration implements PluginConfiguration {
10 |
11 | @Inject
12 | private Game game;
13 |
14 | @Inject
15 | private PluginContainer pluginContainer;
16 |
17 | @Inject
18 | private CraftingStoreSponge craftingStoreSponge;
19 |
20 | @Override
21 | public String getName() {
22 | return "Sponge";
23 | }
24 |
25 | @Override
26 | public String[] getMainCommands() {
27 | return new String[]{"craftingstore", "cs"};
28 | }
29 |
30 | @Override
31 | public String getVersion() {
32 | return pluginContainer.getVersion().orElse("unknown-version");
33 | }
34 |
35 | @Override
36 | public String getPlatform() {
37 | return "sponge/"
38 | + game.getPlatform().getContainer(Platform.Component.API).getVersion().orElse("unknown")
39 | + "/" + game.getPlatform().getContainer(Platform.Component.IMPLEMENTATION).getVersion().orElse("unknown");
40 | }
41 |
42 | @Override
43 | public boolean isBuyCommandEnabled() {
44 | return !craftingStoreSponge.getConfigWrapper().getConfig().getNode("disable-buy-command").getBoolean(false);
45 | }
46 |
47 | @Override
48 | public int getTimeBetweenCommands() {
49 | return craftingStoreSponge.getConfigWrapper().getConfig().getNode("time-between-commands").getInt(200);
50 | }
51 |
52 | @Override
53 | public String getNotEnoughBalanceMessage() {
54 | return null;
55 | }
56 |
57 | @Override
58 | public boolean isUsingAlternativeApi() {
59 | return craftingStoreSponge.getConfigWrapper().getConfig().getNode("use-alternative-api").getBoolean(false);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/commands/BuyCommand.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.commands;
2 |
3 | import com.google.inject.Inject;
4 | import net.craftingstore.core.CraftingStore;
5 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
6 | import net.craftingstore.core.models.api.ApiInventory;
7 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
8 | import net.craftingstore.sponge.CraftingStoreSponge;
9 | import net.craftingstore.sponge.inventory.InventoryBuilder;
10 | import org.spongepowered.api.Game;
11 | import org.spongepowered.api.command.CommandException;
12 | import org.spongepowered.api.command.CommandResult;
13 | import org.spongepowered.api.command.CommandSource;
14 | import org.spongepowered.api.command.args.CommandContext;
15 | import org.spongepowered.api.command.spec.CommandExecutor;
16 | import org.spongepowered.api.entity.living.player.Player;
17 | import org.spongepowered.api.item.inventory.Inventory;
18 | import org.spongepowered.api.text.Text;
19 |
20 | import javax.annotation.Nonnull;
21 | import java.util.concurrent.ExecutionException;
22 |
23 | public class BuyCommand implements CommandExecutor {
24 |
25 | @Inject
26 | private CraftingStore craftingStore;
27 |
28 | @Inject
29 | private CraftingStoreSponge spongePlugin;
30 |
31 | @Inject
32 | private Game game;
33 |
34 | @Inject
35 | private InventoryBuilder inventoryBuilder;
36 |
37 | @Override
38 | public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext args) throws CommandException {
39 | if (!(src instanceof Player)) {
40 | throw new CommandException(Text.of("You can only execute this command as a player"));
41 | }
42 | Player p = (Player) src;
43 |
44 | game.getScheduler().createTaskBuilder()
45 | .execute(() -> {
46 | try {
47 | ApiInventory gui = craftingStore.getApi().getGUI().get();
48 | CraftingStoreInventory craftingStoreInventory = new CraftingStoreInventory(gui.getTitle(), gui.getContent(), gui.getSize());
49 | Inventory inventory = this.inventoryBuilder.buildInventory(craftingStoreInventory);
50 | game.getScheduler().createTaskBuilder()
51 | .execute(() -> {
52 | if (p.isOnline()) {
53 | p.openInventory(inventory);
54 | }
55 | })
56 | .submit(spongePlugin);
57 | } catch (InterruptedException | ExecutionException | CraftingStoreApiException e) {
58 | e.printStackTrace();
59 | }
60 | })
61 | .async()
62 | .submit(spongePlugin);
63 |
64 | return CommandResult.success();
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/commands/CraftingStoreCommand.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.commands;
2 |
3 | import com.google.inject.Inject;
4 | import net.craftingstore.core.CraftingStore;
5 | import net.craftingstore.sponge.CraftingStoreSponge;
6 | import org.spongepowered.api.Game;
7 | import org.spongepowered.api.command.CommandResult;
8 | import org.spongepowered.api.command.CommandSource;
9 | import org.spongepowered.api.command.args.CommandContext;
10 | import org.spongepowered.api.command.spec.CommandExecutor;
11 | import org.spongepowered.api.text.Text;
12 | import org.spongepowered.api.text.format.TextColors;
13 | import org.spongepowered.api.text.format.TextStyles;
14 |
15 | import javax.annotation.Nonnull;
16 | import java.util.Optional;
17 | import java.util.concurrent.ExecutionException;
18 |
19 | public class CraftingStoreCommand implements CommandExecutor {
20 |
21 | @Inject
22 | private CraftingStore craftingStore;
23 |
24 | @Inject
25 | private CraftingStoreSponge spongePlugin;
26 |
27 | @Inject
28 | private Game game;
29 |
30 | @Override
31 | public CommandResult execute(@Nonnull CommandSource src, @Nonnull CommandContext args) {
32 | Optional action = args.getOne("action");
33 | Optional key = args.getOne("key");
34 |
35 | if (action.isPresent() && action.get().equalsIgnoreCase("reload")) {
36 | craftingStore.reload();
37 |
38 | src.sendMessage(spongePlugin.getPrefix().toBuilder()
39 | .append(Text.builder("The plugin is reloading!").build())
40 | .build());
41 |
42 | return CommandResult.success();
43 | } else if (action.isPresent() && key.isPresent() && action.get().equalsIgnoreCase("key")) {
44 | spongePlugin.getConfigWrapper().getConfig().getNode("api-key").setValue(key.get());
45 | spongePlugin.getConfigWrapper().saveConfig();
46 |
47 | game.getScheduler().createTaskBuilder().execute(() -> {
48 | try {
49 | if (craftingStore.reload().get()) {
50 | src.sendMessage(spongePlugin.getPrefix().toBuilder()
51 | .append(Text.builder("The new API key has been set in the config, and the plugin has been reloaded.").build())
52 | .build());
53 | } else {
54 | src.sendMessage(spongePlugin.getPrefix().toBuilder()
55 | .append(Text.builder("The API key is invalid. The plugin will not work until you set a valid API key.").build())
56 | .build());
57 | }
58 | } catch (InterruptedException | ExecutionException e) {
59 | e.printStackTrace();
60 | }
61 | }).async().submit(spongePlugin);
62 | return CommandResult.success();
63 | }
64 |
65 | src.sendMessage(Text.builder("-----------------------").color(TextColors.GRAY).style(TextStyles.STRIKETHROUGH).build());
66 | src.sendMessage(Text.builder("> ").color(TextColors.DARK_GRAY)
67 | .append(Text.builder("/cs reload").color(TextColors.GRAY).build())
68 | .append(Text.builder(" -> ").color(TextColors.DARK_GRAY).build())
69 | .append(Text.builder("Reload the config.").color(TextColors.GRAY).build())
70 | .build()
71 | );
72 |
73 | src.sendMessage(Text.builder("> ").color(TextColors.DARK_GRAY)
74 | .append(Text.builder("/cs key ").color(TextColors.GRAY).build())
75 | .append(Text.builder(" -> ").color(TextColors.DARK_GRAY).build())
76 | .append(Text.builder("Update the key.").color(TextColors.GRAY).build())
77 | .build()
78 | );
79 | src.sendMessage(Text.builder("-----------------------").color(TextColors.GRAY).style(TextStyles.STRIKETHROUGH).build());
80 |
81 | return CommandResult.success();
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/config/Config.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.config;
2 |
3 | import ninja.leaping.configurate.ConfigurationNode;
4 | import ninja.leaping.configurate.yaml.YAMLConfigurationLoader;
5 |
6 | import java.io.File;
7 | import java.io.IOException;
8 | import java.nio.file.Files;
9 |
10 | public class Config extends File {
11 |
12 | private final YAMLConfigurationLoader loader;
13 | private ConfigurationNode config;
14 |
15 | /**
16 | * Create a new instance of Config, specifying a file name and Plugin.
17 | *
18 | * @param name the file name, including .yml
19 | */
20 | public Config(File dir, String name) {
21 | super(dir, name);
22 |
23 | if (!dir.exists()) {
24 | dir.mkdirs();
25 | }
26 |
27 | if (!exists()) {
28 | try {
29 | if (getClass().getClassLoader().getResource(name) != null) {
30 | Files.copy(getClass().getClassLoader().getResourceAsStream(name), toPath());
31 | } else {
32 | createNewFile();
33 | }
34 | } catch (IOException e) {
35 | e.printStackTrace();
36 | }
37 | }
38 |
39 | loader = YAMLConfigurationLoader.builder().setFile(this).build();
40 |
41 | try {
42 | config = loader.load();
43 | } catch (IOException e) {
44 | e.printStackTrace();
45 | }
46 | }
47 |
48 | public ConfigurationNode getConfig() {
49 | return this.config;
50 | }
51 |
52 | /**
53 | * Save all changes to the disk.
54 | */
55 | public void saveConfig() {
56 | try {
57 | loader.save(config);
58 | } catch (IOException e) {
59 | e.printStackTrace();
60 | }
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/events/DonationReceivedEvent.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.events;
2 |
3 | import net.craftingstore.core.models.donation.Donation;
4 | import org.spongepowered.api.event.Cancellable;
5 | import org.spongepowered.api.event.cause.Cause;
6 | import org.spongepowered.api.event.impl.AbstractEvent;
7 |
8 | import java.util.UUID;
9 |
10 | public class DonationReceivedEvent extends AbstractEvent implements Cancellable {
11 |
12 | @Deprecated
13 | private String command;
14 | @Deprecated
15 | private String username;
16 | @Deprecated
17 | private UUID uuid;
18 | @Deprecated
19 | private String packageName;
20 | @Deprecated
21 | private int packagePrice;
22 | @Deprecated
23 | private int couponDiscount;
24 |
25 | private Donation donation;
26 |
27 | private boolean cancelled = false;
28 |
29 | @Deprecated
30 | public DonationReceivedEvent(String command, String username, UUID uuid, String packageName, int packagePrice, int couponDiscount) {
31 | this.command = command;
32 | this.username = username;
33 | this.uuid = uuid;
34 | this.packageName = packageName;
35 | this.packagePrice = packagePrice;
36 | this.couponDiscount = couponDiscount;
37 | }
38 |
39 | public DonationReceivedEvent(Donation donation) {
40 | this.command = donation.getCommand();
41 | this.username = donation.getPlayer().getUsername();
42 | this.uuid = donation.getPlayer().getUUID();
43 | this.packageName = donation.getPackage().getName();
44 | this.packagePrice = donation.getPackage().getPrice();
45 | this.couponDiscount = donation.getDiscount();
46 | this.donation = donation;
47 | }
48 |
49 | @Deprecated
50 | public String getCommand() {
51 | return command;
52 | }
53 |
54 | @Deprecated
55 | public String getUsername() {
56 | return username;
57 | }
58 |
59 | @Deprecated
60 | public UUID getUuid() {
61 | return uuid;
62 | }
63 |
64 | @Deprecated
65 | public String getPackageName() {
66 | return packageName;
67 | }
68 |
69 | @Deprecated
70 | public int getPackagePrice() {
71 | return packagePrice;
72 | }
73 |
74 | @Deprecated
75 | public int getCouponDiscount() {
76 | return couponDiscount;
77 | }
78 |
79 | public Donation getDonation() {
80 | return donation;
81 | }
82 |
83 | @Override
84 | public boolean isCancelled() {
85 | return this.cancelled;
86 | }
87 |
88 | @Override
89 | public void setCancelled(boolean cancel) {
90 | this.cancelled = cancel;
91 | }
92 |
93 | @Override
94 | public Cause getCause() {
95 | return null;
96 | }
97 | }
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/inventory/CraftingStoreInventoryProperty.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.inventory;
2 |
3 | import org.spongepowered.api.data.Property;
4 | import org.spongepowered.api.item.inventory.property.AbstractInventoryProperty;
5 |
6 | public class CraftingStoreInventoryProperty extends AbstractInventoryProperty {
7 |
8 | public CraftingStoreInventoryProperty(InventoryAttachment inventoryAttachment) {
9 | super(inventoryAttachment);
10 | }
11 |
12 | @Override
13 | public int compareTo(Property, ?> o) {
14 | return 0;
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/inventory/InventoryAttachment.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.inventory;
2 |
3 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
4 |
5 | public class InventoryAttachment {
6 |
7 | private CraftingStoreInventory csInventory;
8 | private InventoryAttachment parent;
9 |
10 |
11 | public InventoryAttachment(CraftingStoreInventory csInventory, InventoryAttachment parent) {
12 | this.csInventory = csInventory;
13 | this.parent = parent;
14 | }
15 |
16 | public CraftingStoreInventory getCsInventory() {
17 | return csInventory;
18 | }
19 |
20 | public InventoryAttachment getParent() {
21 | return parent;
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/inventory/InventoryBuilder.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.inventory;
2 |
3 | import com.google.inject.Inject;
4 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
5 | import net.craftingstore.core.models.api.inventory.InventoryItem;
6 | import net.craftingstore.sponge.CraftingStoreSponge;
7 | import org.spongepowered.api.GameRegistry;
8 | import org.spongepowered.api.data.key.Keys;
9 | import org.spongepowered.api.item.ItemType;
10 | import org.spongepowered.api.item.ItemTypes;
11 | import org.spongepowered.api.item.inventory.Inventory;
12 | import org.spongepowered.api.item.inventory.ItemStack;
13 | import org.spongepowered.api.item.inventory.property.InventoryDimension;
14 | import org.spongepowered.api.item.inventory.property.InventoryTitle;
15 | import org.spongepowered.api.item.inventory.query.QueryOperationTypes;
16 | import org.spongepowered.api.item.inventory.type.GridInventory;
17 | import org.spongepowered.api.text.Text;
18 | import org.spongepowered.api.text.serializer.TextSerializers;
19 |
20 | import java.util.Arrays;
21 | import java.util.Optional;
22 | import java.util.stream.Collectors;
23 |
24 | public class InventoryBuilder {
25 |
26 | @Inject
27 | private CraftingStoreSponge spongePlugin;
28 |
29 | @Inject
30 | private GameRegistry gameRegistry;
31 |
32 | public Inventory buildInventory(CraftingStoreInventory csInventory) {
33 | return buildInventory(csInventory, null);
34 | }
35 |
36 | public Inventory buildInventory(CraftingStoreInventory csInventory, InventoryAttachment parent) {
37 | String title = csInventory.getTitle();
38 | if (title == null || title.isEmpty()) {
39 | title = "CraftingStore";
40 | }
41 | Text formattedTitle = TextSerializers.FORMATTING_CODE.deserialize(title).toText();
42 |
43 | InventoryAttachment attachment = new InventoryAttachment(csInventory, parent);
44 | int width = 9;
45 | int height = csInventory.getSize() / 9;
46 |
47 | Inventory inventory = Inventory.builder()
48 | .property(new CraftingStoreInventoryProperty(attachment))
49 | .property(InventoryTitle.of(formattedTitle))
50 | .property(InventoryDimension.of(width, height))
51 | .build(this.spongePlugin);
52 |
53 | GridInventory grid = inventory.query(QueryOperationTypes.INVENTORY_TYPE.of(GridInventory.class));
54 | for (InventoryItem inventoryItem : csInventory.getContent()) {
55 | ItemType type = ItemTypes.CHEST;
56 | if (inventoryItem.getIcon().getMaterial() != null) {
57 | Optional oType = gameRegistry.getType(ItemType.class, inventoryItem.getIcon().getMaterial());
58 | if (oType.isPresent()) {
59 | type = oType.get();
60 | }
61 | }
62 | ItemStack stack = ItemStack.builder()
63 | .itemType(type)
64 | .quantity(inventoryItem.getIcon().getAmount())
65 | .build();
66 |
67 | Text itemName = TextSerializers.FORMATTING_CODE.deserialize(inventoryItem.getName()).toText();
68 | stack.offer(Keys.DISPLAY_NAME, itemName);
69 | if (inventoryItem.getDescription() != null && inventoryItem.getDescription().length != 0) {
70 | stack.offer(Keys.ITEM_LORE, Arrays.stream(inventoryItem.getDescription())
71 | .map(d -> TextSerializers.FORMATTING_CODE.deserialize(d).toText())
72 | .collect(Collectors.toList()));
73 | }
74 | int x = inventoryItem.getIndex() % 9;
75 | int y = inventoryItem.getIndex() / 9;
76 | grid.set(x, y, stack);
77 | }
78 |
79 | return inventory;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/inventory/InventoryItemHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.inventory;
2 |
3 | import net.craftingstore.core.models.api.inventory.InventoryItem;
4 | import org.spongepowered.api.entity.living.player.Player;
5 |
6 | public interface InventoryItemHandler {
7 | void handle(Player p, T item, InventoryAttachment attachment);
8 | }
9 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/inventory/handlers/BackButtonHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.inventory.handlers;
2 |
3 | import com.google.inject.Inject;
4 | import net.craftingstore.core.models.api.inventory.types.InventoryItemBackButton;
5 | import net.craftingstore.sponge.inventory.InventoryAttachment;
6 | import net.craftingstore.sponge.inventory.InventoryBuilder;
7 | import net.craftingstore.sponge.inventory.InventoryItemHandler;
8 | import org.spongepowered.api.entity.living.player.Player;
9 | import org.spongepowered.api.item.inventory.Inventory;
10 |
11 | public class BackButtonHandler implements InventoryItemHandler {
12 |
13 | @Inject
14 | private InventoryBuilder inventoryBuilder;
15 |
16 | @Override
17 | public void handle(Player p, InventoryItemBackButton item, InventoryAttachment attachment) {
18 | if (attachment.getParent() != null) {
19 | Inventory inventory = inventoryBuilder.buildInventory(attachment.getParent().getCsInventory(), attachment.getParent().getParent());
20 | p.openInventory(inventory);
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/inventory/handlers/CategoryItemHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.inventory.handlers;
2 |
3 | import com.google.inject.Inject;
4 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
5 | import net.craftingstore.core.models.api.inventory.types.InventoryItemCategory;
6 | import net.craftingstore.sponge.inventory.InventoryAttachment;
7 | import net.craftingstore.sponge.inventory.InventoryBuilder;
8 | import net.craftingstore.sponge.inventory.InventoryItemHandler;
9 | import org.spongepowered.api.entity.living.player.Player;
10 | import org.spongepowered.api.item.inventory.Inventory;
11 |
12 | public class CategoryItemHandler implements InventoryItemHandler {
13 |
14 | @Inject
15 | private InventoryBuilder inventoryBuilder;
16 |
17 | @Override
18 | public void handle(Player p, InventoryItemCategory item, InventoryAttachment attachment) {
19 | CraftingStoreInventory csInventory = new CraftingStoreInventory(item.getTitle(), item.getContent(), item.getSize());
20 | Inventory inventory = inventoryBuilder.buildInventory(csInventory, attachment);
21 | p.openInventory(inventory);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/inventory/handlers/CloseButtonHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.inventory.handlers;
2 |
3 | import net.craftingstore.core.models.api.inventory.types.InventoryItemCloseButton;
4 | import net.craftingstore.sponge.inventory.InventoryAttachment;
5 | import net.craftingstore.sponge.inventory.InventoryItemHandler;
6 | import org.spongepowered.api.entity.living.player.Player;
7 |
8 | public class CloseButtonHandler implements InventoryItemHandler {
9 |
10 | @Override
11 | public void handle(Player p, InventoryItemCloseButton item, InventoryAttachment attachment) {
12 | p.closeInventory();
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/inventory/handlers/MessageButtonHandler.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.inventory.handlers;
2 |
3 | import net.craftingstore.core.models.api.inventory.types.InventoryItemMessage;
4 | import net.craftingstore.sponge.inventory.InventoryAttachment;
5 | import net.craftingstore.sponge.inventory.InventoryItemHandler;
6 | import org.spongepowered.api.entity.living.player.Player;
7 | import org.spongepowered.api.text.Text;
8 | import org.spongepowered.api.text.action.TextActions;
9 | import org.spongepowered.api.text.serializer.TextSerializers;
10 |
11 | import java.net.MalformedURLException;
12 | import java.net.URL;
13 |
14 | public class MessageButtonHandler implements InventoryItemHandler {
15 | @Override
16 | public void handle(Player p, InventoryItemMessage item, InventoryAttachment attachment) {
17 | for (String message : item.getMessages()) {
18 | Text text = TextSerializers.FORMATTING_CODE.deserialize(message);
19 | String url = null;
20 | if (message.contains("http://")) {
21 | url = message.substring(message.indexOf("http"));
22 | }
23 | if (message.contains("https://")) {
24 | url = message.substring(message.indexOf("https"));
25 | }
26 | if (url != null) {
27 | if (url.contains(" ")) {
28 | url = url.substring(0, url.indexOf(" "));
29 | }
30 | try {
31 | text = Text.builder()
32 | .append(text)
33 | .onClick(TextActions.openUrl(new URL(url)))
34 | .build();
35 | } catch (MalformedURLException e) {
36 | // Do nothing when url is invalid
37 | }
38 | }
39 | p.sendMessage(text);
40 | }
41 | if (item.shouldClose()) {
42 | p.closeInventory();
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/listeners/InventoryClickListener.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.listeners;
2 |
3 | import com.google.inject.Inject;
4 | import net.craftingstore.core.models.api.inventory.CraftingStoreInventory;
5 | import net.craftingstore.core.models.api.inventory.InventoryItem;
6 | import net.craftingstore.core.models.api.inventory.types.InventoryItemBackButton;
7 | import net.craftingstore.core.models.api.inventory.types.InventoryItemCategory;
8 | import net.craftingstore.core.models.api.inventory.types.InventoryItemCloseButton;
9 | import net.craftingstore.core.models.api.inventory.types.InventoryItemMessage;
10 | import net.craftingstore.sponge.CraftingStoreSponge;
11 | import net.craftingstore.sponge.inventory.CraftingStoreInventoryProperty;
12 | import net.craftingstore.sponge.inventory.InventoryAttachment;
13 | import net.craftingstore.sponge.inventory.InventoryItemHandler;
14 | import net.craftingstore.sponge.inventory.handlers.BackButtonHandler;
15 | import net.craftingstore.sponge.inventory.handlers.CategoryItemHandler;
16 | import net.craftingstore.sponge.inventory.handlers.CloseButtonHandler;
17 | import net.craftingstore.sponge.inventory.handlers.MessageButtonHandler;
18 | import org.spongepowered.api.Game;
19 | import org.spongepowered.api.entity.living.player.Player;
20 | import org.spongepowered.api.event.Listener;
21 | import org.spongepowered.api.event.filter.cause.First;
22 | import org.spongepowered.api.event.item.inventory.ClickInventoryEvent;
23 | import org.spongepowered.api.item.inventory.property.SlotIndex;
24 | import org.spongepowered.api.item.inventory.transaction.SlotTransaction;
25 |
26 | import java.util.Collection;
27 | import java.util.HashMap;
28 |
29 | public class InventoryClickListener {
30 |
31 | private HashMap, InventoryItemHandler> handlers = new HashMap<>();
32 |
33 | @Inject
34 | private Game game;
35 |
36 | @Inject
37 | private CraftingStoreSponge spongePlugin;
38 |
39 | @Inject
40 | public InventoryClickListener(BackButtonHandler backButtonHandler, CategoryItemHandler categoryItemHandler,
41 | CloseButtonHandler closeButtonHandler, MessageButtonHandler messageButtonHandler) {
42 | handlers.put(InventoryItemBackButton.class, backButtonHandler);
43 | handlers.put(InventoryItemCategory.class, categoryItemHandler);
44 | handlers.put(InventoryItemCloseButton.class, closeButtonHandler);
45 | handlers.put(InventoryItemMessage.class, messageButtonHandler);
46 | }
47 |
48 | @Listener
49 | public void onClick(ClickInventoryEvent e, @First Player p) {
50 | Collection properties = e.getTargetInventory()
51 | .getProperties(CraftingStoreInventoryProperty.class);
52 | if (properties.size() == 0) {
53 | return;
54 | }
55 | e.setCancelled(true);
56 | if (e.getTransactions().size() == 0) {
57 | return;
58 | }
59 | SlotTransaction transaction = e.getTransactions().get(0);
60 | SlotIndex slotIndex = transaction.getSlot().getInventoryProperty(SlotIndex.class).orElse(null);
61 | if (slotIndex == null) {
62 | return;
63 | }
64 | int index = slotIndex.getValue();
65 |
66 | CraftingStoreInventoryProperty csProperty = properties.iterator().next();
67 | InventoryAttachment attachment = csProperty.getValue();
68 | CraftingStoreInventory csInventory = attachment.getCsInventory();
69 | InventoryItem item = csInventory.getByIndex(index);
70 | if (item == null) {
71 | return;
72 | }
73 |
74 | if (handlers.containsKey(item.getClass())) {
75 | game.getScheduler().createTaskBuilder()
76 | .execute(() -> handlers.get(item.getClass()).handle(p, item, attachment))
77 | .submit(spongePlugin);
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/listeners/PendingDonationJoinListener.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.listeners;
2 |
3 | import com.google.inject.Inject;
4 | import net.craftingstore.core.CraftingStore;
5 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
6 | import net.craftingstore.core.jobs.ProcessPendingPaymentsJob;
7 | import org.spongepowered.api.entity.living.player.Player;
8 | import org.spongepowered.api.event.Listener;
9 | import org.spongepowered.api.event.network.ClientConnectionEvent;
10 |
11 | public class PendingDonationJoinListener {
12 |
13 | @Inject
14 | private CraftingStore craftingStore;
15 |
16 | @Listener
17 | public void onJoin(ClientConnectionEvent.Join e) {
18 | if (!e.getTargetEntity().getPlayer().isPresent()) {
19 | return;
20 | }
21 | Player p = e.getTargetEntity().getPlayer().get();
22 | String username = p.getName();
23 |
24 | craftingStore.getImplementation().runAsyncTask(() -> {
25 | try {
26 | new ProcessPendingPaymentsJob(this.craftingStore, username);
27 | } catch (CraftingStoreApiException ex) {
28 | ex.printStackTrace();
29 | }
30 | });
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/logging/Slf4jLogger.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.logging;
2 |
3 | import com.google.inject.Inject;
4 | import com.google.inject.Singleton;
5 | import net.craftingstore.core.logging.CraftingStoreLogger;
6 | import org.slf4j.Logger;
7 |
8 | @Singleton
9 | public class Slf4jLogger extends CraftingStoreLogger {
10 |
11 | @Inject
12 | private Logger logger;
13 |
14 | @Override
15 | public void info(String message) {
16 | this.logger.info(message);
17 | }
18 |
19 | @Override
20 | public void error(String message) {
21 | this.logger.error(message);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/module/ConfigModule.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.module;
2 |
3 | import com.google.inject.AbstractModule;
4 | import net.craftingstore.sponge.config.Config;
5 |
6 | public class ConfigModule extends AbstractModule {
7 |
8 | private Config config;
9 |
10 | public ConfigModule(Config config) {
11 | this.config = config;
12 | }
13 |
14 | @Override
15 | protected void configure() {
16 | bind(Config.class).toInstance(config);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/sponge/src/main/java/net/craftingstore/sponge/module/CraftingStoreModule.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.sponge.module;
2 |
3 | import com.google.inject.AbstractModule;
4 | import net.craftingstore.core.CraftingStore;
5 |
6 | public class CraftingStoreModule extends AbstractModule {
7 |
8 | private CraftingStore craftingStore;
9 |
10 | public CraftingStoreModule(CraftingStore craftingStore) {
11 | this.craftingStore = craftingStore;
12 | }
13 |
14 | protected void configure() {
15 | bind(CraftingStore.class).toInstance(craftingStore);
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/velocity/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 |
8 | net.craftingstore
9 | craftingstore
10 | ${revision}
11 |
12 |
13 | velocity
14 |
15 |
16 |
17 |
18 | org.apache.maven.plugins
19 | maven-compiler-plugin
20 |
21 | 8
22 | 8
23 |
24 |
25 |
26 |
27 |
28 | src/main/resources
29 | true
30 |
31 |
32 |
33 |
34 |
35 |
36 | velocity
37 | https://repo.velocitypowered.com/snapshots/
38 |
39 |
40 | sponge
41 | https://repo.spongepowered.org/maven
42 |
43 |
44 |
45 |
46 |
47 | net.craftingstore
48 | core
49 | ${project.version}
50 |
51 |
52 |
53 | com.velocitypowered
54 | velocity-api
55 | 3.0.0
56 | provided
57 |
58 |
59 |
60 | com.googlecode.json-simple
61 | json-simple
62 | 1.1.1
63 |
64 |
65 | junit
66 | junit
67 |
68 |
69 | org.hamcrest
70 | hamcrest-core
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/CraftingStoreVelocity.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity;
2 |
3 | import com.google.inject.Inject;
4 | import com.google.inject.Injector;
5 | import com.google.inject.Singleton;
6 | import com.velocitypowered.api.command.CommandManager;
7 | import com.velocitypowered.api.event.EventManager;
8 | import com.velocitypowered.api.event.Subscribe;
9 | import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
10 | import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
11 | import com.velocitypowered.api.plugin.Plugin;
12 | import com.velocitypowered.api.plugin.annotation.DataDirectory;
13 | import net.craftingstore.core.CraftingStore;
14 | import net.craftingstore.velocity.command.CraftingStoreCommand;
15 | import net.craftingstore.velocity.config.Config;
16 | import net.craftingstore.velocity.listeners.PendingDonationJoinListener;
17 | import net.craftingstore.velocity.module.ConfigModule;
18 | import net.craftingstore.velocity.module.CraftingStoreModule;
19 |
20 | import java.nio.file.Path;
21 |
22 | @Singleton
23 | @Plugin(id = "craftingstore", name = "CraftingStore")
24 | public class CraftingStoreVelocity {
25 |
26 | @Inject
27 | private CommandManager commandManager;
28 |
29 | @Inject
30 | private EventManager eventManager;
31 |
32 | private Config config;
33 | private CraftingStore craftingStore;
34 | private Injector injector;
35 |
36 | @Inject
37 | public CraftingStoreVelocity(@DataDirectory Path configDirectory, Injector injector) {
38 | this.config = new Config(configDirectory.toFile(), "config.json");
39 | this.injector = injector.createChildInjector(new ConfigModule(config));
40 | }
41 |
42 | @Subscribe
43 | public void onInitialization(ProxyInitializeEvent event) {
44 | this.craftingStore = new CraftingStore(injector.getInstance(CraftingStoreVelocityImpl.class));
45 | injector = injector.createChildInjector(new CraftingStoreModule(craftingStore));
46 |
47 | commandManager.register("csv", injector.getInstance(CraftingStoreCommand.class));
48 | eventManager.register(this, injector.getInstance(PendingDonationJoinListener.class));
49 | }
50 |
51 | @Subscribe
52 | public void onShutdown(ProxyShutdownEvent event) {
53 | this.craftingStore.setEnabled(false);
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/CraftingStoreVelocityImpl.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity;
2 |
3 | import com.google.inject.Inject;
4 | import com.velocitypowered.api.proxy.Player;
5 | import com.velocitypowered.api.proxy.ProxyServer;
6 | import net.craftingstore.core.CraftingStorePlugin;
7 | import net.craftingstore.core.PluginConfiguration;
8 | import net.craftingstore.core.logging.CraftingStoreLogger;
9 | import net.craftingstore.core.models.donation.Donation;
10 | import net.craftingstore.velocity.config.Config;
11 | import net.craftingstore.velocity.events.DonationReceivedEvent;
12 | import net.craftingstore.velocity.events.DonationResult;
13 | import net.craftingstore.velocity.logging.Slf4jLogger;
14 |
15 | import java.util.Optional;
16 | import java.util.concurrent.TimeUnit;
17 |
18 | public class CraftingStoreVelocityImpl implements CraftingStorePlugin {
19 |
20 | @Inject
21 | private CraftingStoreVelocity velocityPlugin;
22 |
23 | @Inject
24 | private Config config;
25 |
26 | @Inject
27 | private ProxyServer proxyServer;
28 |
29 | private Slf4jLogger logger;
30 |
31 | @Inject
32 | private VelocityPluginConfiguration configuration;
33 |
34 | @Inject
35 | private void setLogger(Slf4jLogger logger) {
36 | this.logger = logger;
37 | this.logger.setDebugging((Boolean) this.config.getConfig().getOrDefault("debug", false));
38 | }
39 |
40 | @Override
41 | public boolean executeDonation(Donation donation) {
42 | if (donation.getPlayer().isRequiredOnline()) {
43 | Optional player = proxyServer.getPlayer(donation.getPlayer().getUsername());
44 | if (!player.isPresent() || !player.get().isActive()) {
45 | return false;
46 | }
47 | }
48 |
49 | DonationReceivedEvent event = new DonationReceivedEvent(donation);
50 | event.setResult(new DonationResult(true));
51 | proxyServer.getEventManager().fire(event);
52 | if (!event.getResult().isAllowed()) {
53 | return false;
54 | }
55 |
56 | proxyServer.getCommandManager().executeAsync(proxyServer.getConsoleCommandSource(), donation.getCommand())
57 | .exceptionally(e -> {
58 | logger.error("Command " + donation.getCommand() + " failed");
59 | return null;
60 | });
61 | return true;
62 | }
63 |
64 | @Override
65 | public CraftingStoreLogger getLogger() {
66 | return logger;
67 | }
68 |
69 | @Override
70 | public void registerRunnable(Runnable runnable, int delay, int interval) {
71 | proxyServer.getScheduler().buildTask(velocityPlugin, runnable)
72 | .delay(delay, TimeUnit.SECONDS)
73 | .repeat(interval, TimeUnit.SECONDS)
74 | .schedule();
75 | }
76 |
77 | @Override
78 | public void runAsyncTask(Runnable runnable) {
79 | proxyServer.getScheduler().buildTask(velocityPlugin, runnable).schedule();
80 | }
81 |
82 | @Override
83 | public String getToken() {
84 | return (String) config.getConfig().get("api-key");
85 | }
86 |
87 | @Override
88 | public PluginConfiguration getConfiguration() {
89 | return this.configuration;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/VelocityPluginConfiguration.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity;
2 |
3 | import com.google.inject.Inject;
4 | import com.velocitypowered.api.plugin.PluginDescription;
5 | import com.velocitypowered.api.proxy.ProxyServer;
6 | import net.craftingstore.core.PluginConfiguration;
7 | import net.craftingstore.velocity.config.Config;
8 |
9 | public class VelocityPluginConfiguration implements PluginConfiguration {
10 |
11 | @Inject
12 | private PluginDescription description;
13 |
14 | @Inject
15 | private ProxyServer proxyServer;
16 |
17 | @Inject
18 | private Config config;
19 |
20 | @Override
21 | public String getName() {
22 | return "Velocity";
23 | }
24 |
25 | @Override
26 | public String[] getMainCommands() {
27 | return new String[] {"csv"};
28 | }
29 |
30 | @Override
31 | public String getVersion() {
32 | return description.getVersion().orElse("unknown");
33 | }
34 |
35 | @Override
36 | public String getPlatform() {
37 | return proxyServer.getVersion().toString();
38 | }
39 |
40 | @Override
41 | public boolean isBuyCommandEnabled() {
42 | return false;
43 | }
44 |
45 | @Override
46 | public int getTimeBetweenCommands() {
47 | Object value = config.getConfig().getOrDefault("time-between-commands", 200);
48 | if (value instanceof Integer) {
49 | return (int) value;
50 | }
51 | if (value instanceof Long) {
52 | return ((Long) value).intValue();
53 | }
54 | throw new RuntimeException("Invalid integer value in time-between-commands");
55 | }
56 |
57 | @Override
58 | public String getNotEnoughBalanceMessage() {
59 | return null;
60 | }
61 |
62 | @Override
63 | public boolean isUsingAlternativeApi() {
64 | Object value = config.getConfig().getOrDefault("use-alternative-api", false);
65 | if (value instanceof Boolean) {
66 | return (boolean) value;
67 | }
68 | throw new RuntimeException("Invalid boolean value in use-alternative-api");
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/annotation/Prefix.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity.annotation;
2 |
3 | import com.google.inject.BindingAnnotation;
4 |
5 | import java.lang.annotation.Retention;
6 | import java.lang.annotation.RetentionPolicy;
7 |
8 | @Retention(RetentionPolicy.RUNTIME)
9 | @BindingAnnotation
10 | public @interface Prefix {
11 | }
12 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/command/CraftingStoreCommand.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity.command;
2 |
3 | import com.google.inject.Inject;
4 | import com.velocitypowered.api.command.CommandSource;
5 | import com.velocitypowered.api.command.SimpleCommand;
6 | import com.velocitypowered.api.proxy.ProxyServer;
7 | import net.craftingstore.core.CraftingStore;
8 | import net.craftingstore.velocity.CraftingStoreVelocity;
9 | import net.craftingstore.velocity.annotation.Prefix;
10 | import net.craftingstore.velocity.config.Config;
11 | import net.kyori.adventure.text.Component;
12 | import net.kyori.adventure.text.format.NamedTextColor;
13 | import net.kyori.adventure.text.format.TextDecoration;
14 |
15 | import java.util.concurrent.ExecutionException;
16 |
17 | public class CraftingStoreCommand implements SimpleCommand {
18 |
19 | @Inject
20 | private CraftingStore craftingStore;
21 |
22 | @Inject
23 | @Prefix
24 | private Component prefix;
25 |
26 | @Inject
27 | private CraftingStoreVelocity velocityPlugin;
28 |
29 | @Inject
30 | private Config config;
31 |
32 | @Inject
33 | private ProxyServer proxyServer;
34 |
35 | @Override
36 | public void execute(Invocation invocation) {
37 | String[] args = invocation.arguments();
38 | CommandSource sender = invocation.source();
39 | if (args.length == 1 && args[0].equalsIgnoreCase("reload")) {
40 | craftingStore.reload();
41 | sender.sendMessage(Component.text()
42 | .append(prefix)
43 | .append(Component.text("The plugin is reloading!"))
44 | .build());
45 | return;
46 | }
47 | if (args.length == 2 && args[0].equalsIgnoreCase("key")) {
48 | config.getConfig().put("api-key", args[1]);
49 | config.saveConfig();
50 | proxyServer.getScheduler().buildTask(velocityPlugin, () -> {
51 | try {
52 | if (craftingStore.reload().get()) {
53 | sender.sendMessage(Component.text()
54 | .append(prefix)
55 | .append(Component.text("The new API key has been set in the config, and the plugin has been reloaded."))
56 | .build());
57 | } else {
58 | sender.sendMessage(Component.text()
59 | .append(prefix)
60 | .append(Component.text("The API key is invalid. The plugin will not work until you set a valid API key."))
61 | .build());
62 | }
63 | } catch (InterruptedException | ExecutionException e) {
64 | e.printStackTrace();
65 | }
66 | }).schedule();
67 | return;
68 | }
69 |
70 | sender.sendMessage(
71 | Component.text("-----------------------", NamedTextColor.GRAY).decoration(TextDecoration.STRIKETHROUGH, true)
72 | );
73 | sender.sendMessage(Component.text()
74 | .append(Component.text("> ", NamedTextColor.DARK_GRAY))
75 | .append(Component.text("/csv reload", NamedTextColor.GRAY))
76 | .append(Component.text(" -> ", NamedTextColor.DARK_GRAY))
77 | .append(Component.text("Reload the config.", NamedTextColor.GRAY))
78 | .build()
79 | );
80 | sender.sendMessage(Component.text()
81 | .append(Component.text("> ", NamedTextColor.DARK_GRAY))
82 | .append(Component.text("/csv key ", NamedTextColor.GRAY))
83 | .append(Component.text(" -> ", NamedTextColor.DARK_GRAY))
84 | .append(Component.text("Update the key.", NamedTextColor.GRAY))
85 | .build()
86 | );
87 | sender.sendMessage(
88 | Component.text("-----------------------", NamedTextColor.GRAY).decoration(TextDecoration.STRIKETHROUGH, true)
89 | );
90 | }
91 |
92 | @Override
93 | public boolean hasPermission(Invocation invocation) {
94 | return invocation.source().hasPermission("craftingstore.admin");
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/config/Config.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity.config;
2 |
3 | import org.json.simple.JSONObject;
4 | import org.json.simple.parser.JSONParser;
5 | import org.json.simple.parser.ParseException;
6 |
7 | import java.io.*;
8 | import java.nio.file.Files;
9 |
10 | public class Config extends File {
11 |
12 | private JSONObject config;
13 |
14 | /**
15 | * Create a new instance of Config, specifying a file name and Plugin.
16 | *
17 | * @param name the file name, including .yml
18 | */
19 | public Config(File dir, String name) {
20 | super(dir, name);
21 |
22 | if (!dir.exists()) {
23 | dir.mkdirs();
24 | }
25 |
26 | if (!exists()) {
27 | try {
28 | if (getClass().getClassLoader().getResource(name) != null) {
29 | Files.copy(getClass().getClassLoader().getResourceAsStream(name), toPath());
30 | } else {
31 | createNewFile();
32 | }
33 | } catch (IOException e) {
34 | e.printStackTrace();
35 | }
36 | }
37 |
38 | JSONParser parser = new JSONParser();
39 | try {
40 | this.config = (JSONObject) parser.parse(new FileReader(this));
41 | } catch (IOException | ParseException e) {
42 | e.printStackTrace();
43 | }
44 | }
45 |
46 | public JSONObject getConfig() {
47 | return config;
48 | }
49 |
50 | /**
51 | * Save all changes to the disk.
52 | */
53 | public void saveConfig() {
54 | try {
55 | PrintWriter pw = new PrintWriter(this);
56 | pw.write(this.config.toJSONString());
57 | pw.flush();
58 | pw.close();
59 | } catch (FileNotFoundException e) {
60 | e.printStackTrace();
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/events/DonationReceivedEvent.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity.events;
2 |
3 | import com.velocitypowered.api.event.ResultedEvent;
4 | import net.craftingstore.core.models.donation.Donation;
5 |
6 | public class DonationReceivedEvent implements ResultedEvent {
7 | private Donation donation;
8 | private DonationResult result;
9 |
10 | public DonationReceivedEvent(Donation donation) {
11 | this.donation = donation;
12 | }
13 |
14 | public Donation getDonation() {
15 | return this.donation;
16 | }
17 |
18 | @Override
19 | public DonationResult getResult() {
20 | return this.result;
21 | }
22 |
23 | @Override
24 | public void setResult(DonationResult result) {
25 | this.result = result;
26 | }
27 | }
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/events/DonationResult.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity.events;
2 |
3 | import com.velocitypowered.api.event.ResultedEvent;
4 |
5 | public class DonationResult implements ResultedEvent.Result {
6 |
7 | private boolean allowed;
8 |
9 | public DonationResult(boolean allowed) {
10 | this.allowed = allowed;
11 | }
12 |
13 | @Override
14 | public boolean isAllowed() {
15 | return this.allowed;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/listeners/PendingDonationJoinListener.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity.listeners;
2 |
3 | import com.google.inject.Inject;
4 | import com.velocitypowered.api.event.Subscribe;
5 | import com.velocitypowered.api.event.connection.PostLoginEvent;
6 | import com.velocitypowered.api.proxy.Player;
7 | import net.craftingstore.core.CraftingStore;
8 | import net.craftingstore.core.exceptions.CraftingStoreApiException;
9 | import net.craftingstore.core.jobs.ProcessPendingPaymentsJob;
10 |
11 | public class PendingDonationJoinListener {
12 |
13 | @Inject
14 | private CraftingStore craftingStore;
15 |
16 | @Subscribe
17 | public void onPlayerJoin(PostLoginEvent event) {
18 | Player player = event.getPlayer();
19 | String username = player.getUsername();
20 |
21 | craftingStore.getImplementation().runAsyncTask(() -> {
22 | try {
23 | new ProcessPendingPaymentsJob(craftingStore, username);
24 | } catch (CraftingStoreApiException ex) {
25 | ex.printStackTrace();
26 | }
27 | });
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/logging/Slf4jLogger.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity.logging;
2 |
3 | import com.google.inject.Inject;
4 | import com.google.inject.Singleton;
5 | import net.craftingstore.core.logging.CraftingStoreLogger;
6 | import org.slf4j.Logger;
7 |
8 | @Singleton
9 | public class Slf4jLogger extends CraftingStoreLogger {
10 |
11 | @Inject
12 | private Logger logger;
13 |
14 | @Override
15 | public void info(String message) {
16 | this.logger.info(message);
17 | }
18 |
19 | @Override
20 | public void error(String message) {
21 | this.logger.error(message);
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/module/ConfigModule.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity.module;
2 |
3 | import com.google.inject.AbstractModule;
4 | import net.craftingstore.velocity.config.Config;
5 |
6 | public class ConfigModule extends AbstractModule {
7 |
8 | private Config config;
9 |
10 | public ConfigModule(Config config) {
11 | this.config = config;
12 | }
13 |
14 | @Override
15 | protected void configure() {
16 | bind(Config.class).toInstance(config);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/velocity/src/main/java/net/craftingstore/velocity/module/CraftingStoreModule.java:
--------------------------------------------------------------------------------
1 | package net.craftingstore.velocity.module;
2 |
3 | import com.google.inject.AbstractModule;
4 | import net.craftingstore.core.CraftingStore;
5 | import net.craftingstore.velocity.annotation.Prefix;
6 | import net.kyori.adventure.text.Component;
7 | import net.kyori.adventure.text.TextComponent;
8 | import net.kyori.adventure.text.format.NamedTextColor;
9 |
10 | public class CraftingStoreModule extends AbstractModule {
11 |
12 | private CraftingStore craftingStore;
13 | private TextComponent prefix = Component.text()
14 | .append(Component.text("[", NamedTextColor.GRAY))
15 | .append(Component.text("CraftingStore", NamedTextColor.RED))
16 | .append(Component.text("] ", NamedTextColor.GRAY))
17 | .append(Component.text("", NamedTextColor.WHITE))
18 | .build();
19 |
20 | public CraftingStoreModule(CraftingStore craftingStore) {
21 | this.craftingStore = craftingStore;
22 | }
23 |
24 | protected void configure() {
25 | bind(CraftingStore.class).toInstance(craftingStore);
26 | bind(Component.class).annotatedWith(Prefix.class).toInstance(prefix);
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/velocity/src/main/resources/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "api-key": ""
3 | }
--------------------------------------------------------------------------------