Compare commits
89 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d5ddcaea4b | ||
|
|
d3a7ef72e8 | ||
|
|
a311ce1227 | ||
|
|
5c0d4540a8 | ||
|
|
7e66ee8071 | ||
|
|
fd233df736 | ||
|
|
6baf636e6a | ||
|
|
9ee579f2c4 | ||
|
|
3b5ea87353 | ||
|
|
00d32ed218 | ||
|
|
5ce9a1c04e | ||
|
|
966549065d | ||
|
|
ee2911b57c | ||
|
|
f15ec5eec0 | ||
|
|
a9c32000d8 | ||
|
|
b68459951f | ||
|
|
b520c76169 | ||
|
|
d081afbd8e | ||
|
|
46fd0439a5 | ||
|
|
ad58ce4a74 | ||
|
|
b5cd8f42e0 | ||
|
|
d0baf50709 | ||
|
|
2496f318fa | ||
|
|
048c200c95 | ||
|
|
17446acb2e | ||
|
|
7929113c91 | ||
|
|
6acc5864bd | ||
|
|
fa64950d28 | ||
|
|
730c20dbc0 | ||
|
|
0c5ae54c3a | ||
|
|
b48e80837d | ||
|
|
17eb4cf5f8 | ||
|
|
890f85fa56 | ||
|
|
86b427c95e | ||
|
|
8c1fde57b0 | ||
|
|
2efc040a8e | ||
|
|
54b2b42512 | ||
|
|
e67d9d634c | ||
|
|
39fb676b9a | ||
|
|
ec8936b765 | ||
|
|
cf347de4b8 | ||
|
|
2b7122c5c2 | ||
|
|
062b5c9b92 | ||
|
|
052cd74756 | ||
|
|
082b39a2e4 | ||
|
|
616fa032d9 | ||
|
|
ea997239fc | ||
|
|
ad04abab73 | ||
|
|
f440ef922b | ||
|
|
933271fb4a | ||
|
|
9679d3100f | ||
|
|
6e20763522 | ||
|
|
18dea2c20c | ||
|
|
62b666559c | ||
|
|
465563523b | ||
|
|
f0f014ed89 | ||
|
|
58811c5d77 | ||
|
|
81d495e76e | ||
|
|
c78e397959 | ||
|
|
95740f155e | ||
|
|
5638d5e152 | ||
|
|
4d3712057c | ||
|
|
458fcd78b3 | ||
|
|
ee13de31f4 | ||
|
|
9588d49788 | ||
|
|
8e7ce298b0 | ||
|
|
32a11ce5b8 | ||
|
|
960f62cc8b | ||
|
|
28ceb83eb5 | ||
|
|
6f748b6b8a | ||
|
|
190ea5d49f | ||
|
|
c0ed083a5c | ||
|
|
04f04bb7a6 | ||
|
|
b8a3806ff9 | ||
|
|
ae49d41542 | ||
|
|
5f2255a3bc | ||
|
|
065ccfbe67 | ||
|
|
17727c9015 | ||
|
|
ea64e69b4d | ||
|
|
07ca6c2359 | ||
|
|
162558b1c2 | ||
|
|
10f9e8dce0 | ||
|
|
b02943d7ff | ||
|
|
40ad970ffa | ||
|
|
aefdfa786d | ||
|
|
1cf08955a0 | ||
|
|
4077a4c28b | ||
|
|
6c375ef297 | ||
|
|
7767e48e51 |
@@ -39,7 +39,7 @@ and many more.
|
|||||||
# For developers
|
# For developers
|
||||||
|
|
||||||
## Javadoc
|
## Javadoc
|
||||||
The 6.38.2 Javadoc can be found [here](https://javadoc.jitpack.io/com/willfp/eco/6.38.2/javadoc/)
|
The 6.45.0 Javadoc can be found [here](https://javadoc.jitpack.io/com/willfp/eco/6.45.0/javadoc/)
|
||||||
|
|
||||||
## Plugin Information
|
## Plugin Information
|
||||||
|
|
||||||
@@ -68,7 +68,7 @@ dependencies {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Replace `Tag` with a release tag for eco, eg `6.27.2`.
|
Replace `Tag` with a release tag for eco, eg `6.45.0`.
|
||||||
|
|
||||||
Maven:
|
Maven:
|
||||||
|
|
||||||
@@ -88,7 +88,7 @@ Maven:
|
|||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
Replace `Tag` with a release tag for eco, eg `6.27.2`.
|
Replace `Tag` with a release tag for eco, eg `6.45.0`.
|
||||||
|
|
||||||
## Build locally:
|
## Build locally:
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,8 @@ import com.willfp.eco.core.gui.menu.MenuBuilder;
|
|||||||
import com.willfp.eco.core.gui.menu.MenuType;
|
import com.willfp.eco.core.gui.menu.MenuType;
|
||||||
import com.willfp.eco.core.gui.slot.SlotBuilder;
|
import com.willfp.eco.core.gui.slot.SlotBuilder;
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
|
import com.willfp.eco.core.gui.slot.functional.SlotProvider;
|
||||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration;
|
|
||||||
import com.willfp.eco.core.items.TestableItem;
|
import com.willfp.eco.core.items.TestableItem;
|
||||||
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
import com.willfp.eco.core.math.MathContext;
|
||||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
|
||||||
import com.willfp.eco.core.proxy.ProxyFactory;
|
import com.willfp.eco.core.proxy.ProxyFactory;
|
||||||
import com.willfp.eco.core.scheduling.Scheduler;
|
import com.willfp.eco.core.scheduling.Scheduler;
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
||||||
@@ -42,7 +40,6 @@ import org.jetbrains.annotations.ApiStatus;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -138,10 +135,8 @@ public interface Eco {
|
|||||||
* Create a PAPI integration.
|
* Create a PAPI integration.
|
||||||
*
|
*
|
||||||
* @param plugin The plugin.
|
* @param plugin The plugin.
|
||||||
* @return The integration.
|
|
||||||
*/
|
*/
|
||||||
@NotNull
|
void createPAPIIntegration(@NotNull EcoPlugin plugin);
|
||||||
PlaceholderIntegration createPAPIIntegration(@NotNull EcoPlugin plugin);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a proxy factory.
|
* Create a proxy factory.
|
||||||
@@ -173,6 +168,7 @@ public interface Eco {
|
|||||||
* @param requiresChangesToSave If the config must be changed in order to save the config.
|
* @param requiresChangesToSave If the config must be changed in order to save the config.
|
||||||
* @return The config implementation.
|
* @return The config implementation.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
LoadableConfig createUpdatableConfig(@NotNull String configName,
|
LoadableConfig createUpdatableConfig(@NotNull String configName,
|
||||||
@NotNull PluginLike plugin,
|
@NotNull PluginLike plugin,
|
||||||
@NotNull String subDirectoryPath,
|
@NotNull String subDirectoryPath,
|
||||||
@@ -193,6 +189,7 @@ public interface Eco {
|
|||||||
* @param requiresChangesToSave If the config must be changed in order to save the config.
|
* @param requiresChangesToSave If the config must be changed in order to save the config.
|
||||||
* @return The config implementation.
|
* @return The config implementation.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
LoadableConfig createLoadableConfig(@NotNull String configName,
|
LoadableConfig createLoadableConfig(@NotNull String configName,
|
||||||
@NotNull PluginLike plugin,
|
@NotNull PluginLike plugin,
|
||||||
@NotNull String subDirectoryPath,
|
@NotNull String subDirectoryPath,
|
||||||
@@ -206,6 +203,7 @@ public interface Eco {
|
|||||||
* @param config The handle.
|
* @param config The handle.
|
||||||
* @return The config implementation.
|
* @return The config implementation.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
Config wrapConfigurationSection(@NotNull ConfigurationSection config);
|
Config wrapConfigurationSection(@NotNull ConfigurationSection config);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -215,6 +213,7 @@ public interface Eco {
|
|||||||
* @param type The config type.
|
* @param type The config type.
|
||||||
* @return The config implementation.
|
* @return The config implementation.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
Config createConfig(@NotNull Map<String, Object> values,
|
Config createConfig(@NotNull Map<String, Object> values,
|
||||||
@NotNull ConfigType type);
|
@NotNull ConfigType type);
|
||||||
|
|
||||||
@@ -225,6 +224,7 @@ public interface Eco {
|
|||||||
* @param type The type.
|
* @param type The type.
|
||||||
* @return The config implementation.
|
* @return The config implementation.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
Config createConfig(@NotNull String contents,
|
Config createConfig(@NotNull String contents,
|
||||||
@NotNull ConfigType type);
|
@NotNull ConfigType type);
|
||||||
|
|
||||||
@@ -335,23 +335,16 @@ public interface Eco {
|
|||||||
*
|
*
|
||||||
* @return The keys.
|
* @return The keys.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
Set<PersistentDataKey<?>> getRegisteredPersistentDataKeys();
|
Set<PersistentDataKey<?>> getRegisteredPersistentDataKeys();
|
||||||
|
|
||||||
/**
|
|
||||||
* Get persistent data key from namespaced key.
|
|
||||||
*
|
|
||||||
* @param namespacedKey The key.
|
|
||||||
* @return The key, or null if not found.
|
|
||||||
*/
|
|
||||||
@Nullable
|
|
||||||
PersistentDataKey<?> getPersistentDataKeyFrom(@NotNull NamespacedKey namespacedKey);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load a player profile.
|
* Load a player profile.
|
||||||
*
|
*
|
||||||
* @param uuid The UUID.
|
* @param uuid The UUID.
|
||||||
* @return The profile.
|
* @return The profile.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
PlayerProfile loadPlayerProfile(@NotNull UUID uuid);
|
PlayerProfile loadPlayerProfile(@NotNull UUID uuid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -359,6 +352,7 @@ public interface Eco {
|
|||||||
*
|
*
|
||||||
* @return The profile.
|
* @return The profile.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
ServerProfile getServerProfile();
|
ServerProfile getServerProfile();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -370,24 +364,6 @@ public interface Eco {
|
|||||||
*/
|
*/
|
||||||
void unloadPlayerProfile(@NotNull UUID uuid);
|
void unloadPlayerProfile(@NotNull UUID uuid);
|
||||||
|
|
||||||
/**
|
|
||||||
* Save keys for a player.
|
|
||||||
* <p>
|
|
||||||
* Can run async if using MySQL.
|
|
||||||
*
|
|
||||||
* @param uuid The uuid.
|
|
||||||
* @param keys The keys.
|
|
||||||
*/
|
|
||||||
void savePersistentDataKeysFor(@NotNull UUID uuid,
|
|
||||||
@NotNull Set<PersistentDataKey<?>> keys);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Commit all changes to the file.
|
|
||||||
* <p>
|
|
||||||
* Does nothing if using MySQL.
|
|
||||||
*/
|
|
||||||
void saveAllProfiles();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create dummy entity - never spawned, exists purely in code.
|
* Create dummy entity - never spawned, exists purely in code.
|
||||||
*
|
*
|
||||||
@@ -513,16 +489,12 @@ public interface Eco {
|
|||||||
/**
|
/**
|
||||||
* Evaluate an expression.
|
* Evaluate an expression.
|
||||||
*
|
*
|
||||||
* @param expression The expression.
|
* @param expression The expression.
|
||||||
* @param player The player.
|
* @param context The context.
|
||||||
* @param injectable The injectable placeholders.
|
|
||||||
* @param additionalPlayers The additional players.
|
|
||||||
* @return The value of the expression, or zero if invalid.
|
* @return The value of the expression, or zero if invalid.
|
||||||
*/
|
*/
|
||||||
double evaluate(@NotNull String expression,
|
double evaluate(@NotNull String expression,
|
||||||
@Nullable Player player,
|
@NotNull MathContext context);
|
||||||
@NotNull PlaceholderInjectable injectable,
|
|
||||||
@NotNull Collection<AdditionalPlayer> additionalPlayers);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the menu a player currently has open.
|
* Get the menu a player currently has open.
|
||||||
@@ -533,6 +505,11 @@ public interface Eco {
|
|||||||
@Nullable
|
@Nullable
|
||||||
Menu getOpenMenu(@NotNull Player player);
|
Menu getOpenMenu(@NotNull Player player);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync commands.
|
||||||
|
*/
|
||||||
|
void syncCommands();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the instance of eco; the bridge between the api frontend
|
* Get the instance of eco; the bridge between the api frontend
|
||||||
* and the implementation backend.
|
* and the implementation backend.
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import com.willfp.eco.core.factory.MetadataValueFactory;
|
|||||||
import com.willfp.eco.core.factory.NamespacedKeyFactory;
|
import com.willfp.eco.core.factory.NamespacedKeyFactory;
|
||||||
import com.willfp.eco.core.factory.RunnableFactory;
|
import com.willfp.eco.core.factory.RunnableFactory;
|
||||||
import com.willfp.eco.core.integrations.IntegrationLoader;
|
import com.willfp.eco.core.integrations.IntegrationLoader;
|
||||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
|
||||||
import com.willfp.eco.core.proxy.ProxyFactory;
|
import com.willfp.eco.core.proxy.ProxyFactory;
|
||||||
import com.willfp.eco.core.scheduling.Scheduler;
|
import com.willfp.eco.core.scheduling.Scheduler;
|
||||||
import com.willfp.eco.core.web.UpdateChecker;
|
import com.willfp.eco.core.web.UpdateChecker;
|
||||||
@@ -153,6 +152,31 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
@Nullable
|
@Nullable
|
||||||
private final ProxyFactory proxyFactory;
|
private final ProxyFactory proxyFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tasks to run on enable.
|
||||||
|
*/
|
||||||
|
private final List<Runnable> onEnable = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tasks to run on disable.
|
||||||
|
*/
|
||||||
|
private final List<Runnable> onDisable = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tasks to run on reload.
|
||||||
|
*/
|
||||||
|
private final List<Runnable> onReload = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tasks to run on load.
|
||||||
|
*/
|
||||||
|
private final List<Runnable> onLoad = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The tasks to run after load.
|
||||||
|
*/
|
||||||
|
private final List<Runnable> afterLoad = new ArrayList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new plugin.
|
* Create a new plugin.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -375,8 +399,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
if (enabledPlugins.contains("PlaceholderAPI".toLowerCase())) {
|
if (enabledPlugins.contains("PlaceholderAPI".toLowerCase())) {
|
||||||
this.loadedIntegrations.add("PlaceholderAPI");
|
Eco.get().createPAPIIntegration(this);
|
||||||
PlaceholderManager.addIntegration(Eco.get().createPAPIIntegration(this));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadIntegrationLoaders().forEach(integrationLoader -> {
|
this.loadIntegrationLoaders().forEach(integrationLoader -> {
|
||||||
@@ -386,6 +409,8 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.loadedIntegrations.removeIf(pl -> pl.equalsIgnoreCase(this.getName()));
|
||||||
|
|
||||||
this.getLogger().info("Loaded integrations: " + String.join(", ", this.getLoadedIntegrations()));
|
this.getLogger().info("Loaded integrations: " + String.join(", ", this.getLoadedIntegrations()));
|
||||||
|
|
||||||
Prerequisite.update();
|
Prerequisite.update();
|
||||||
@@ -414,10 +439,20 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.handleEnable();
|
this.handleEnable();
|
||||||
|
this.onEnable.forEach(Runnable::run);
|
||||||
|
|
||||||
this.getLogger().info("");
|
this.getLogger().info("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new task to run on enable.
|
||||||
|
*
|
||||||
|
* @param task The task.
|
||||||
|
*/
|
||||||
|
public final void onEnable(@NotNull final Runnable task) {
|
||||||
|
this.onEnable.add(task);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default code to be executed on plugin disable.
|
* Default code to be executed on plugin disable.
|
||||||
*/
|
*/
|
||||||
@@ -429,6 +464,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
this.getScheduler().cancelAll();
|
this.getScheduler().cancelAll();
|
||||||
|
|
||||||
this.handleDisable();
|
this.handleDisable();
|
||||||
|
this.onDisable.forEach(Runnable::run);
|
||||||
|
|
||||||
if (this.isSupportingExtensions()) {
|
if (this.isSupportingExtensions()) {
|
||||||
this.getExtensionLoader().unloadExtensions();
|
this.getExtensionLoader().unloadExtensions();
|
||||||
@@ -438,6 +474,15 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
Eco.get().clean(this);
|
Eco.get().clean(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new task to run on disable.
|
||||||
|
*
|
||||||
|
* @param task The task.
|
||||||
|
*/
|
||||||
|
public final void onDisable(@NotNull final Runnable task) {
|
||||||
|
this.onDisable.add(task);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default code to be executed on plugin load.
|
* Default code to be executed on plugin load.
|
||||||
*/
|
*/
|
||||||
@@ -446,6 +491,16 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
super.onLoad();
|
super.onLoad();
|
||||||
|
|
||||||
this.handleLoad();
|
this.handleLoad();
|
||||||
|
this.onLoad.forEach(Runnable::run);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new task to run on load.
|
||||||
|
*
|
||||||
|
* @param task The task.
|
||||||
|
*/
|
||||||
|
public final void onLoad(@NotNull final Runnable task) {
|
||||||
|
this.onLoad.add(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -478,6 +533,7 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.handleAfterLoad();
|
this.handleAfterLoad();
|
||||||
|
this.afterLoad.forEach(Runnable::run);
|
||||||
|
|
||||||
this.reload();
|
this.reload();
|
||||||
|
|
||||||
@@ -488,6 +544,15 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
this.getLogger().info("Loaded " + this.color + this.getName());
|
this.getLogger().info("Loaded " + this.color + this.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new task to run after load.
|
||||||
|
*
|
||||||
|
* @param task The task.
|
||||||
|
*/
|
||||||
|
public final void afterLoad(@NotNull final Runnable task) {
|
||||||
|
this.afterLoad.add(task);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reload the plugin.
|
* Reload the plugin.
|
||||||
*/
|
*/
|
||||||
@@ -499,12 +564,22 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
this.getConfigHandler().callUpdate(); // Call twice to fix issues
|
this.getConfigHandler().callUpdate(); // Call twice to fix issues
|
||||||
|
|
||||||
this.handleReload();
|
this.handleReload();
|
||||||
|
this.onReload.forEach(Runnable::run);
|
||||||
|
|
||||||
for (Extension extension : this.extensionLoader.getLoadedExtensions()) {
|
for (Extension extension : this.extensionLoader.getLoadedExtensions()) {
|
||||||
extension.handleReload();
|
extension.handleReload();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add new task to run on enable.
|
||||||
|
*
|
||||||
|
* @param task The task.
|
||||||
|
*/
|
||||||
|
public final void onReload(@NotNull final Runnable task) {
|
||||||
|
this.onReload.add(task);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reload the plugin and return the time taken to reload.
|
* Reload the plugin and return the time taken to reload.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package com.willfp.eco.core.command;
|
package com.willfp.eco.core.command;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
import com.willfp.eco.core.EcoPlugin;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -43,8 +45,6 @@ public interface CommandBase {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle command execution.
|
* Handle command execution.
|
||||||
* <p>
|
|
||||||
* Marked as default void with no implementation for backwards compatibility.
|
|
||||||
*
|
*
|
||||||
* @param sender The sender.
|
* @param sender The sender.
|
||||||
* @param args The args.
|
* @param args The args.
|
||||||
@@ -54,20 +54,43 @@ public interface CommandBase {
|
|||||||
// Do nothing.
|
// Do nothing.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle command execution from players.
|
||||||
|
*
|
||||||
|
* @param sender The sender.
|
||||||
|
* @param args The args.
|
||||||
|
*/
|
||||||
|
default void onExecute(@NotNull Player sender,
|
||||||
|
@NotNull List<String> args) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle tab completion.
|
* Handle tab completion.
|
||||||
* <p>
|
|
||||||
* Marked as default void with no implementation for backwards compatibility.
|
|
||||||
*
|
*
|
||||||
* @param sender The sender.
|
* @param sender The sender.
|
||||||
* @param args The args.
|
* @param args The args.
|
||||||
* @return The results.
|
* @return The results.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
default List<String> tabComplete(@NotNull CommandSender sender,
|
default List<String> tabComplete(@NotNull CommandSender sender,
|
||||||
@NotNull List<String> args) {
|
@NotNull List<String> args) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle tab completion.
|
||||||
|
*
|
||||||
|
* @param sender The sender.
|
||||||
|
* @param args The args.
|
||||||
|
* @return The results.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
default List<String> tabComplete(@NotNull Player sender,
|
||||||
|
@NotNull List<String> args) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the plugin.
|
* Get the plugin.
|
||||||
*
|
*
|
||||||
@@ -83,7 +106,11 @@ public interface CommandBase {
|
|||||||
* @deprecated Use {@link CommandBase#onExecute(CommandSender, List)} instead.
|
* @deprecated Use {@link CommandBase#onExecute(CommandSender, List)} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true)
|
@Deprecated(forRemoval = true)
|
||||||
CommandHandler getHandler();
|
default CommandHandler getHandler() {
|
||||||
|
return (a, b) -> {
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the handler.
|
* Set the handler.
|
||||||
@@ -93,7 +120,9 @@ public interface CommandBase {
|
|||||||
* @deprecated Handlers have been deprecated.
|
* @deprecated Handlers have been deprecated.
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true)
|
@Deprecated(forRemoval = true)
|
||||||
void setHandler(@NotNull CommandHandler handler);
|
default void setHandler(@NotNull final CommandHandler handler) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the tab completer.
|
* Get the tab completer.
|
||||||
@@ -103,7 +132,9 @@ public interface CommandBase {
|
|||||||
* @deprecated Use {@link CommandBase#tabComplete(CommandSender, List)} instead.
|
* @deprecated Use {@link CommandBase#tabComplete(CommandSender, List)} instead.
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true)
|
@Deprecated(forRemoval = true)
|
||||||
TabCompleteHandler getTabCompleter();
|
default TabCompleteHandler getTabCompleter() {
|
||||||
|
return (a, b) -> ImmutableList.of();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the tab completer.
|
* Set the tab completer.
|
||||||
@@ -113,5 +144,7 @@ public interface CommandBase {
|
|||||||
* @deprecated Handlers have been deprecated.
|
* @deprecated Handlers have been deprecated.
|
||||||
*/
|
*/
|
||||||
@Deprecated(forRemoval = true)
|
@Deprecated(forRemoval = true)
|
||||||
void setTabCompleter(@NotNull TabCompleteHandler handler);
|
default void setTabCompleter(@NotNull final TabCompleteHandler handler) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package com.willfp.eco.core.command.impl;
|
||||||
|
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.PluginIdentifiableCommand;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegates a bukkit command to an eco command (for registrations).
|
||||||
|
*/
|
||||||
|
public final class DelegatedBukkitCommand extends Command implements TabCompleter, PluginIdentifiableCommand {
|
||||||
|
/**
|
||||||
|
* The delegate command.
|
||||||
|
*/
|
||||||
|
private final PluginCommand delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new delegated command.
|
||||||
|
*
|
||||||
|
* @param delegate The delegate.
|
||||||
|
*/
|
||||||
|
public DelegatedBukkitCommand(@NotNull final PluginCommand delegate) {
|
||||||
|
super(delegate.getName());
|
||||||
|
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean execute(@NotNull final CommandSender commandSender,
|
||||||
|
@NotNull final String label,
|
||||||
|
@NotNull final String[] args) {
|
||||||
|
return delegate.onCommand(commandSender, this, label, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> onTabComplete(@NotNull final CommandSender commandSender,
|
||||||
|
@NotNull final Command command,
|
||||||
|
@NotNull final String label,
|
||||||
|
@NotNull final String[] args) {
|
||||||
|
return delegate.onTabComplete(commandSender, command, label, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Plugin getPlugin() {
|
||||||
|
return this.delegate.getPlugin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public String getPermission() {
|
||||||
|
return this.delegate.getPermission();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return this.delegate.getDescription() == null ? "" : this.delegate.getDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public List<String> getAliases() {
|
||||||
|
return this.delegate.getAliases();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -145,6 +145,9 @@ abstract class HandledCommand implements CommandBase {
|
|||||||
this.getHandler().onExecute(sender, Arrays.asList(args));
|
this.getHandler().onExecute(sender, Arrays.asList(args));
|
||||||
} else {
|
} else {
|
||||||
this.onExecute(sender, Arrays.asList(args));
|
this.onExecute(sender, Arrays.asList(args));
|
||||||
|
if (sender instanceof Player player) {
|
||||||
|
this.onExecute(player, Arrays.asList(args));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,7 +205,11 @@ abstract class HandledCommand implements CommandBase {
|
|||||||
if (this.getTabCompleter() != null) {
|
if (this.getTabCompleter() != null) {
|
||||||
return this.getTabCompleter().tabComplete(sender, Arrays.asList(args));
|
return this.getTabCompleter().tabComplete(sender, Arrays.asList(args));
|
||||||
} else {
|
} else {
|
||||||
return this.tabComplete(sender, Arrays.asList(args));
|
List<String> completions = this.tabComplete(sender, Arrays.asList(args));
|
||||||
|
if (sender instanceof Player player) {
|
||||||
|
completions.addAll(this.tabComplete(player, Arrays.asList(args)));
|
||||||
|
}
|
||||||
|
return completions;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
package com.willfp.eco.core.command.impl;
|
package com.willfp.eco.core.command.impl;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.Eco;
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
import com.willfp.eco.core.EcoPlugin;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.Command;
|
import org.bukkit.command.Command;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandMap;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.command.TabCompleter;
|
import org.bukkit.command.TabCompleter;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,14 +42,63 @@ public abstract class PluginCommand extends HandledCommand implements CommandExe
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers the command with the server,
|
* Registers the command with the server,
|
||||||
* <p>
|
|
||||||
* Requires the command name to exist, defined in plugin.yml.
|
|
||||||
*/
|
*/
|
||||||
public final void register() {
|
public final void register() {
|
||||||
org.bukkit.command.PluginCommand command = Bukkit.getPluginCommand(this.getName());
|
org.bukkit.command.PluginCommand command = Bukkit.getPluginCommand(this.getName());
|
||||||
assert command != null;
|
if (command != null) {
|
||||||
command.setExecutor(this);
|
command.setExecutor(this);
|
||||||
command.setTabCompleter(this);
|
command.setTabCompleter(this);
|
||||||
|
|
||||||
|
if (this.getDescription() != null) {
|
||||||
|
command.setDescription(this.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> aliases = new ArrayList<>(command.getAliases());
|
||||||
|
aliases.addAll(this.getAliases());
|
||||||
|
command.setAliases(aliases);
|
||||||
|
} else {
|
||||||
|
this.unregister();
|
||||||
|
|
||||||
|
CommandMap commandMap = getCommandMap();
|
||||||
|
|
||||||
|
commandMap.register(this.getPlugin().getName().toLowerCase(), new DelegatedBukkitCommand(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
Eco.get().syncCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters the command from the server.
|
||||||
|
*/
|
||||||
|
public final void unregister() {
|
||||||
|
CommandMap commandMap = getCommandMap();
|
||||||
|
|
||||||
|
Command found = commandMap.getCommand(this.getName());
|
||||||
|
if (found != null) {
|
||||||
|
found.unregister(commandMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
Eco.get().syncCommands();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get aliases. Leave null if this command is from plugin.yml.
|
||||||
|
*
|
||||||
|
* @return The aliases.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public List<String> getAliases() {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get description.
|
||||||
|
*
|
||||||
|
* @return The description.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public String getDescription() {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -93,4 +146,19 @@ public abstract class PluginCommand extends HandledCommand implements CommandExe
|
|||||||
|
|
||||||
return this.handleTabCompletion(sender, args);
|
return this.handleTabCompletion(sender, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the internal server CommandMap.
|
||||||
|
*
|
||||||
|
* @return The CommandMap.
|
||||||
|
*/
|
||||||
|
public static CommandMap getCommandMap() {
|
||||||
|
try {
|
||||||
|
Field field = Bukkit.getServer().getClass().getDeclaredField("commandMap");
|
||||||
|
field.setAccessible(true);
|
||||||
|
return (CommandMap) field.get(Bukkit.getServer());
|
||||||
|
} catch (NoSuchFieldException | IllegalAccessException e) {
|
||||||
|
throw new NullPointerException("Command map wasn't found!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,12 +6,12 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
/**
|
/**
|
||||||
* Builder for configs to create them programmatically.
|
* Builder for configs to create them programmatically.
|
||||||
*/
|
*/
|
||||||
public class BuildableConfig extends TransientConfig {
|
public class BuildableConfig extends GenericConfig {
|
||||||
/**
|
/**
|
||||||
* Create a new empty config builder.
|
* Create a new empty config builder.
|
||||||
*/
|
*/
|
||||||
public BuildableConfig() {
|
public BuildableConfig() {
|
||||||
super();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
157
eco-api/src/main/java/com/willfp/eco/core/config/Configs.java
Normal file
157
eco-api/src/main/java/com/willfp/eco/core/config/Configs.java
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
package com.willfp.eco.core.config;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.Eco;
|
||||||
|
import com.willfp.eco.core.config.interfaces.Config;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities / API methods for configs.
|
||||||
|
*/
|
||||||
|
public final class Configs {
|
||||||
|
/**
|
||||||
|
* Load a Config from a bukkit {@link ConfigurationSection}.
|
||||||
|
*
|
||||||
|
* @param config The ConfigurationSection.
|
||||||
|
* @return The config.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Config fromBukkit(@Nullable final ConfigurationSection config) {
|
||||||
|
return config == null ? empty() : Eco.get().wrapConfigurationSection(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a config from an {@link InputStream}.
|
||||||
|
* <p>
|
||||||
|
* Only for yaml configs.
|
||||||
|
*
|
||||||
|
* @param stream The InputStream.
|
||||||
|
* @return The config.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Config fromStream(@Nullable final InputStream stream) {
|
||||||
|
return stream != null ? fromBukkit(YamlConfiguration.loadConfiguration(
|
||||||
|
new InputStreamReader(stream)
|
||||||
|
)) : empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a config from a file.
|
||||||
|
*
|
||||||
|
* @param file The file.
|
||||||
|
* @return The config.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Config fromFile(@Nullable final File file) {
|
||||||
|
if (file == null) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastIndex = file.getName().lastIndexOf(".");
|
||||||
|
|
||||||
|
if (lastIndex < 0) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ConfigType type : ConfigType.values()) {
|
||||||
|
if (file.getName().substring(lastIndex + 1).equalsIgnoreCase(type.getExtension())) {
|
||||||
|
return fromFile(file, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load a config from a file.
|
||||||
|
*
|
||||||
|
* @param file The file.
|
||||||
|
* @param type The type.
|
||||||
|
* @return The config.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Config fromFile(@Nullable final File file,
|
||||||
|
@NotNull final ConfigType type) {
|
||||||
|
if (file == null) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Eco.get().createConfig(Files.readString(file.toPath()), type);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load config from map (uses {@link ConfigType#JSON}).
|
||||||
|
*
|
||||||
|
* @param values The values.
|
||||||
|
* @return The config.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Config fromMap(@NotNull final Map<String, Object> values) {
|
||||||
|
return fromMap(values, ConfigType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load config from map.
|
||||||
|
*
|
||||||
|
* @param values The values.
|
||||||
|
* @param type The type.
|
||||||
|
* @return The config.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Config fromMap(@NotNull final Map<String, Object> values,
|
||||||
|
@NotNull final ConfigType type) {
|
||||||
|
return Eco.get().createConfig(values, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create empty config (uses {@link ConfigType#JSON}).
|
||||||
|
*
|
||||||
|
* @return An empty config.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Config empty() {
|
||||||
|
return fromMap(new HashMap<>(), ConfigType.JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create empty config.
|
||||||
|
*
|
||||||
|
* @param type The type.
|
||||||
|
* @return An empty config.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Config empty(@NotNull final ConfigType type) {
|
||||||
|
return fromMap(new HashMap<>(), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load config from string.
|
||||||
|
*
|
||||||
|
* @param contents The contents of the config.
|
||||||
|
* @param type The config type.
|
||||||
|
* @return The config.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Config fromString(@NotNull final String contents,
|
||||||
|
@NotNull final ConfigType type) {
|
||||||
|
return Eco.get().createConfig(contents, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Configs() {
|
||||||
|
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.willfp.eco.core.config;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.config.interfaces.Config;
|
||||||
|
import com.willfp.eco.core.config.wrapper.ConfigWrapper;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic config to simplify creating custom configs without having
|
||||||
|
* to meddle with delegation.
|
||||||
|
*/
|
||||||
|
public abstract class GenericConfig extends ConfigWrapper<Config> {
|
||||||
|
/**
|
||||||
|
* Create a new generic config.
|
||||||
|
*/
|
||||||
|
protected GenericConfig() {
|
||||||
|
super(Configs.empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new generic config.
|
||||||
|
*
|
||||||
|
* @param type The config type.
|
||||||
|
*/
|
||||||
|
protected GenericConfig(@NotNull final ConfigType type) {
|
||||||
|
super(Configs.empty(type));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,10 @@ import java.util.Map;
|
|||||||
* Config that exists purely in the code, not linked to any file.
|
* Config that exists purely in the code, not linked to any file.
|
||||||
* <p>
|
* <p>
|
||||||
* Use for inline configs to move data around or to add subsections to other configs.
|
* Use for inline configs to move data around or to add subsections to other configs.
|
||||||
|
*
|
||||||
|
* @deprecated Poorly named class, makes the config system seem needlessly complicated.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.44.0", forRemoval = true)
|
||||||
public class TransientConfig extends ConfigWrapper<Config> {
|
public class TransientConfig extends ConfigWrapper<Config> {
|
||||||
/**
|
/**
|
||||||
* @param config The ConfigurationSection handle.
|
* @param config The ConfigurationSection handle.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package com.willfp.eco.core.config.interfaces;
|
|||||||
|
|
||||||
import com.willfp.eco.core.config.BuildableConfig;
|
import com.willfp.eco.core.config.BuildableConfig;
|
||||||
import com.willfp.eco.core.config.ConfigType;
|
import com.willfp.eco.core.config.ConfigType;
|
||||||
import com.willfp.eco.core.config.TransientConfig;
|
import com.willfp.eco.core.config.Configs;
|
||||||
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
||||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
||||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||||
@@ -103,7 +103,7 @@ public interface Config extends Cloneable, PlaceholderInjectable {
|
|||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
default Config getSubsection(@NotNull String path) {
|
default Config getSubsection(@NotNull String path) {
|
||||||
return Objects.requireNonNullElse(getSubsectionOrNull(path), new TransientConfig());
|
return Objects.requireNonNullElse(getSubsectionOrNull(path), Configs.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import org.bukkit.entity.Player;
|
|||||||
import org.bukkit.inventory.Inventory;
|
import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.persistence.PersistentDataType;
|
import org.bukkit.persistence.PersistentDataType;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
|||||||
@@ -63,11 +63,29 @@ public interface Menu {
|
|||||||
* @param player The player
|
* @param player The player
|
||||||
* @param menu The menu.
|
* @param menu The menu.
|
||||||
* @return The slot.
|
* @return The slot.
|
||||||
|
* @deprecated Menu shouldn't be a parameter.
|
||||||
*/
|
*/
|
||||||
default Slot getSlot(int row,
|
@Deprecated(since = "6.46.0", forRemoval = true)
|
||||||
int column,
|
default Slot getSlot(final int row,
|
||||||
@NotNull Player player,
|
final int column,
|
||||||
@NotNull Menu menu) {
|
@NotNull final Player player,
|
||||||
|
@NotNull final Menu menu) {
|
||||||
|
return this.getSlot(row, column, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a slot at a given row and column.
|
||||||
|
* <p>
|
||||||
|
* Defaults to static slot if no reactive slot exists.
|
||||||
|
*
|
||||||
|
* @param row The row.
|
||||||
|
* @param column The column.
|
||||||
|
* @param player The player
|
||||||
|
* @return The slot.
|
||||||
|
*/
|
||||||
|
default Slot getSlot(final int row,
|
||||||
|
final int column,
|
||||||
|
@NotNull final Player player) {
|
||||||
return this.getSlot(row, column);
|
return this.getSlot(row, column);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,15 +128,32 @@ public interface Menu {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add state for a player.
|
* Set state for a player.
|
||||||
*
|
*
|
||||||
* @param player The player.
|
* @param player The player.
|
||||||
* @param key The key.
|
* @param key The key.
|
||||||
* @param value The state.
|
* @param value The state.
|
||||||
*/
|
*/
|
||||||
void addState(@NotNull Player player,
|
default void setState(@NotNull Player player,
|
||||||
@NotNull String key,
|
@NotNull String key,
|
||||||
@Nullable Object value);
|
@Nullable Object value) {
|
||||||
|
// Blank method for backwards compatibility.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add state for a player.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param key The key.
|
||||||
|
* @param value The state.
|
||||||
|
* @deprecated Poorly named, use setState instead.
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "6.44.0", forRemoval = true)
|
||||||
|
default void addState(@NotNull Player player,
|
||||||
|
@NotNull String key,
|
||||||
|
@Nullable Object value) {
|
||||||
|
this.setState(player, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove state for a player.
|
* Remove state for a player.
|
||||||
@@ -221,7 +256,7 @@ public interface Menu {
|
|||||||
@NotNull final NamespacedKey key,
|
@NotNull final NamespacedKey key,
|
||||||
@NotNull final PersistentDataType<T, Z> type,
|
@NotNull final PersistentDataType<T, Z> type,
|
||||||
@NotNull final Z value) {
|
@NotNull final Z value) {
|
||||||
this.addState(player, key.toString(), value);
|
this.setState(player, key.toString(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ public interface MenuBuilder extends PageBuilder {
|
|||||||
* @return The builder.
|
* @return The builder.
|
||||||
*/
|
*/
|
||||||
default MenuBuilder addPage(@NotNull final Page page) {
|
default MenuBuilder addPage(@NotNull final Page page) {
|
||||||
return this.addComponent(MenuLayer.TOP, 1, 1, page);
|
return this.addComponent(MenuLayer.UPPER, 1, 1, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -139,7 +139,7 @@ public interface MenuBuilder extends PageBuilder {
|
|||||||
* @return The builder.
|
* @return The builder.
|
||||||
*/
|
*/
|
||||||
default MenuBuilder maxPages(@NotNull final Function<Player, Integer> pages) {
|
default MenuBuilder maxPages(@NotNull final Function<Player, Integer> pages) {
|
||||||
return onOpen((player, menu) -> menu.addState(player, Page.MAX_PAGE_KEY, pages.apply(player)));
|
return onRender((player, menu) -> menu.setState(player, Page.MAX_PAGE_KEY, pages.apply(player)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -195,6 +195,16 @@ public interface MenuBuilder extends PageBuilder {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an action to run on build.
|
||||||
|
*
|
||||||
|
* @param action The action.
|
||||||
|
* @return The builder.
|
||||||
|
*/
|
||||||
|
default MenuBuilder onBuild(@NotNull Consumer<Menu> action) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the menu.
|
* Build the menu.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
package com.willfp.eco.core.gui.menu.events;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.gui.menu.MenuEvent;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a captive item change.
|
||||||
|
*
|
||||||
|
* @param row The row.
|
||||||
|
* @param column The column.
|
||||||
|
* @param before The previous item in the slot.
|
||||||
|
* @param after The new item in the slot.
|
||||||
|
*/
|
||||||
|
public record CaptiveItemChangeEvent(
|
||||||
|
int row,
|
||||||
|
int column,
|
||||||
|
@Nullable ItemStack before,
|
||||||
|
@Nullable ItemStack after
|
||||||
|
) implements MenuEvent {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,8 +9,6 @@ import org.bukkit.entity.Player;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A page is a component representing another menu.
|
* A page is a component representing another menu.
|
||||||
* This allows full component support in pagination.
|
* This allows full component support in pagination.
|
||||||
@@ -85,7 +83,7 @@ public final class Page implements GUIComponent {
|
|||||||
delegate = Eco.get().blendMenuState(page, menu);
|
delegate = Eco.get().blendMenuState(page, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
return page.getSlot(row, column, player, delegate);
|
return page.getSlot(row, column, player);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ public final class PageChanger implements GUIComponent {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
menu.addState(player, Page.PAGE_KEY, newPage);
|
menu.setState(player, Page.PAGE_KEY, newPage);
|
||||||
menu.callEvent(player, new PageChangeEvent(
|
menu.callEvent(player, new PageChangeEvent(
|
||||||
newPage,
|
newPage,
|
||||||
page
|
page
|
||||||
@@ -79,7 +79,7 @@ public final class PageChanger implements GUIComponent {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page >= maxPage - 1 && this.direction == Direction.FORWARDS) {
|
if (page >= maxPage && this.direction == Direction.FORWARDS) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public abstract class CustomSlot implements Slot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItemStack(@NotNull final Player player) {
|
public @NotNull ItemStack getItemStack(@NotNull final Player player) {
|
||||||
if (delegate == null) {
|
if (delegate == null) {
|
||||||
throw new IllegalStateException("Custom Slot was not initialized!");
|
throw new IllegalStateException("Custom Slot was not initialized!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ public abstract class ReactiveSlot implements Slot {
|
|||||||
@NotNull final Menu menu);
|
@NotNull final Menu menu);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItemStack(@NotNull final Player player) {
|
public @NotNull ItemStack getItemStack(@NotNull final Player player) {
|
||||||
return new ItemStack(Material.STONE);
|
return new ItemStack(Material.AIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -40,8 +40,8 @@ public abstract class ReactiveSlot implements Slot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Slot getActionableSlot(@NotNull final Player player,
|
public final @NotNull Slot getActionableSlot(@NotNull final Player player,
|
||||||
@NotNull final Menu menu) {
|
@NotNull final Menu menu) {
|
||||||
return getSlot(player, menu);
|
return getSlot(player, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ public interface Slot extends GUIComponent {
|
|||||||
* @param player The player.
|
* @param player The player.
|
||||||
* @return The ItemStack.
|
* @return The ItemStack.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
ItemStack getItemStack(@NotNull Player player);
|
ItemStack getItemStack(@NotNull Player player);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,6 +61,7 @@ public interface Slot extends GUIComponent {
|
|||||||
* @param menu The menu.
|
* @param menu The menu.
|
||||||
* @return The slot.
|
* @return The slot.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
default Slot getActionableSlot(@NotNull final Player player,
|
default Slot getActionableSlot(@NotNull final Player player,
|
||||||
@NotNull final Menu menu) {
|
@NotNull final Menu menu) {
|
||||||
return this;
|
return this;
|
||||||
@@ -125,7 +127,9 @@ public interface Slot extends GUIComponent {
|
|||||||
*
|
*
|
||||||
* @param provider The provider.
|
* @param provider The provider.
|
||||||
* @return The builder.
|
* @return The builder.
|
||||||
|
* @deprecated This method was written incorrectly, should have been a Player + Menu function.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.45.0", forRemoval = true)
|
||||||
static SlotBuilder builder(@NotNull final Function<Player, ItemStack> provider) {
|
static SlotBuilder builder(@NotNull final Function<Player, ItemStack> provider) {
|
||||||
return Eco.get().createSlotBuilder((player, menu) -> provider.apply(player));
|
return Eco.get().createSlotBuilder((player, menu) -> provider.apply(player));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,10 +51,15 @@ public final class PlaceholderManager {
|
|||||||
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
|
.expireAfterWrite(50, TimeUnit.MILLISECONDS)
|
||||||
.build(key -> key.entry.getValue(key.player));
|
.build(key -> key.entry.getValue(key.player));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default PlaceholderAPI pattern; brought in for compatibility.
|
||||||
|
*/
|
||||||
|
private static final Pattern PATTERN = Pattern.compile("[%]([^% ]+)[%]");
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Empty injectable object.
|
* Empty injectable object.
|
||||||
*/
|
*/
|
||||||
private static final PlaceholderInjectable EMPTY_INJECTABLE = new PlaceholderInjectable() {
|
public static final PlaceholderInjectable EMPTY_INJECTABLE = new PlaceholderInjectable() {
|
||||||
@Override
|
@Override
|
||||||
public void clearInjectedPlaceholders() {
|
public void clearInjectedPlaceholders() {
|
||||||
// Do nothing.
|
// Do nothing.
|
||||||
@@ -67,11 +72,6 @@ public final class PlaceholderManager {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* The default PlaceholderAPI pattern; brought in for compatibility.
|
|
||||||
*/
|
|
||||||
private static final Pattern PATTERN = Pattern.compile("[%]([^%]+)[%]");
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new placeholder integration.
|
* Register a new placeholder integration.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
package com.willfp.eco.core.integrations.shop;
|
package com.willfp.eco.core.integrations.shop;
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.ApiStatus;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -86,6 +87,11 @@ public final class Items {
|
|||||||
*/
|
*/
|
||||||
private static final TestableItem EMPTY_TESTABLE_ITEM = new EmptyTestableItem();
|
private static final TestableItem EMPTY_TESTABLE_ITEM = new EmptyTestableItem();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Friendly material names (without underscores, etc.)
|
||||||
|
*/
|
||||||
|
private static final Map<String, Material> FRIENDLY_MATERIAL_NAMES = new HashMap<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a new custom item.
|
* Register a new custom item.
|
||||||
*
|
*
|
||||||
@@ -216,7 +222,7 @@ public final class Items {
|
|||||||
if (isWildcard) {
|
if (isWildcard) {
|
||||||
itemType = itemType.substring(1);
|
itemType = itemType.substring(1);
|
||||||
}
|
}
|
||||||
Material material = Material.getMaterial(itemType.toUpperCase());
|
Material material = FRIENDLY_MATERIAL_NAMES.get(itemType.toLowerCase());
|
||||||
if (material == null || material == Material.AIR) {
|
if (material == null || material == Material.AIR) {
|
||||||
return new EmptyTestableItem();
|
return new EmptyTestableItem();
|
||||||
}
|
}
|
||||||
@@ -565,4 +571,25 @@ public final class Items {
|
|||||||
private Items() {
|
private Items() {
|
||||||
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
for (Material material : Material.values()) {
|
||||||
|
FRIENDLY_MATERIAL_NAMES.put(material.name().toLowerCase(), material);
|
||||||
|
|
||||||
|
String oneWord = material.name().toLowerCase().replace("_", "");
|
||||||
|
if (!FRIENDLY_MATERIAL_NAMES.containsKey(oneWord)) {
|
||||||
|
FRIENDLY_MATERIAL_NAMES.put(oneWord, material);
|
||||||
|
}
|
||||||
|
|
||||||
|
String plural = material.name().toLowerCase() + "s";
|
||||||
|
if (!FRIENDLY_MATERIAL_NAMES.containsKey(plural)) {
|
||||||
|
FRIENDLY_MATERIAL_NAMES.put(plural, material);
|
||||||
|
}
|
||||||
|
|
||||||
|
String oneWordPlural = oneWord + "s";
|
||||||
|
if (!FRIENDLY_MATERIAL_NAMES.containsKey(oneWordPlural)) {
|
||||||
|
FRIENDLY_MATERIAL_NAMES.put(oneWordPlural, material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import org.bukkit.persistence.PersistentDataType;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package com.willfp.eco.core.math;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||||
|
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
||||||
|
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a context to do math in.
|
||||||
|
*
|
||||||
|
* @param injectableContext The PlaceholderInjectable context.
|
||||||
|
* @param player The player.
|
||||||
|
* @param additionalPlayers The additional players.
|
||||||
|
*/
|
||||||
|
public record MathContext(
|
||||||
|
@NotNull PlaceholderInjectable injectableContext,
|
||||||
|
@Nullable Player player,
|
||||||
|
@NotNull Collection<AdditionalPlayer> additionalPlayers
|
||||||
|
) {
|
||||||
|
/**
|
||||||
|
* Empty math context.
|
||||||
|
*/
|
||||||
|
public static final MathContext EMPTY = new MathContext(
|
||||||
|
PlaceholderManager.EMPTY_INJECTABLE,
|
||||||
|
null,
|
||||||
|
Collections.emptyList()
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create MathContext of a PlaceholderInjectable context.
|
||||||
|
*
|
||||||
|
* @param injectableContext The PlaceholderInjectable context.
|
||||||
|
* @return The MathContext.
|
||||||
|
*/
|
||||||
|
public static MathContext of(@NotNull final PlaceholderInjectable injectableContext) {
|
||||||
|
return new MathContext(
|
||||||
|
injectableContext,
|
||||||
|
null,
|
||||||
|
Collections.emptyList()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy a MathContext with a player.
|
||||||
|
*
|
||||||
|
* @param context The context.
|
||||||
|
* @param player The player.
|
||||||
|
* @return The new MathContext.
|
||||||
|
*/
|
||||||
|
public static MathContext copyWithPlayer(@NotNull final MathContext context,
|
||||||
|
@Nullable final Player player) {
|
||||||
|
return new MathContext(
|
||||||
|
context.injectableContext(),
|
||||||
|
player,
|
||||||
|
context.additionalPlayers()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.willfp.eco.core.particle;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create particles.
|
||||||
|
*/
|
||||||
|
public interface ParticleFactory {
|
||||||
|
/**
|
||||||
|
* Get the names (how the particle looks in lookup strings).
|
||||||
|
* <p>
|
||||||
|
* For example, for RGB particles this would be 'rgb', 'color', etc.
|
||||||
|
*
|
||||||
|
* @return The allowed names.
|
||||||
|
*/
|
||||||
|
@NotNull List<String> getNames();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the particle
|
||||||
|
*
|
||||||
|
* @param key The key.
|
||||||
|
* @return The particle.
|
||||||
|
*/
|
||||||
|
@Nullable SpawnableParticle create(@NotNull String key);
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package com.willfp.eco.core.particle;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.particle.impl.EmptyParticle;
|
||||||
|
import com.willfp.eco.core.particle.impl.SimpleParticle;
|
||||||
|
import com.willfp.eco.util.StringUtils;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to manage particles.
|
||||||
|
*/
|
||||||
|
public final class Particles {
|
||||||
|
/**
|
||||||
|
* All factories.
|
||||||
|
*/
|
||||||
|
private static final Map<String, ParticleFactory> FACTORIES = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new particle factory.
|
||||||
|
*
|
||||||
|
* @param factory The factory.
|
||||||
|
*/
|
||||||
|
public static void registerParticleFactory(@NotNull final ParticleFactory factory) {
|
||||||
|
for (String name : factory.getNames()) {
|
||||||
|
FACTORIES.put(name.toLowerCase(), factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lookup a particle from a string.
|
||||||
|
* <p>
|
||||||
|
* A particle string should look like {@code magic}, {@code rgb:00ff00}
|
||||||
|
*
|
||||||
|
* @param key The key.
|
||||||
|
* @return The particle, or an {@link EmptyParticle} if invalid.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static SpawnableParticle lookup(@NotNull final String key) {
|
||||||
|
String[] args = StringUtils.parseTokens(key.toLowerCase());
|
||||||
|
|
||||||
|
if (args.length == 0) {
|
||||||
|
return new EmptyParticle();
|
||||||
|
}
|
||||||
|
|
||||||
|
SpawnableParticle spawnableParticle;
|
||||||
|
|
||||||
|
String[] split = args[0].split(":");
|
||||||
|
|
||||||
|
if (split.length == 1) {
|
||||||
|
try {
|
||||||
|
Particle particle = Particle.valueOf(args[0].toUpperCase());
|
||||||
|
spawnableParticle = new SimpleParticle(particle);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
spawnableParticle = new EmptyParticle();
|
||||||
|
}
|
||||||
|
} else if (split.length == 2) {
|
||||||
|
String name = split[0];
|
||||||
|
String factoryKey = split[1];
|
||||||
|
|
||||||
|
ParticleFactory factory = FACTORIES.get(name);
|
||||||
|
if (factory == null) {
|
||||||
|
spawnableParticle = new EmptyParticle();
|
||||||
|
} else {
|
||||||
|
spawnableParticle = factory.create(factoryKey);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return new EmptyParticle();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spawnableParticle == null || spawnableParticle instanceof EmptyParticle) {
|
||||||
|
return new EmptyParticle();
|
||||||
|
}
|
||||||
|
|
||||||
|
return spawnableParticle;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Particles() {
|
||||||
|
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.willfp.eco.core.particle;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A particle that can be spawned.
|
||||||
|
*/
|
||||||
|
public interface SpawnableParticle {
|
||||||
|
/**
|
||||||
|
* Spawn the particle at a location.
|
||||||
|
*
|
||||||
|
* @param location The location.
|
||||||
|
* @param amount The amount to spawn.
|
||||||
|
*/
|
||||||
|
void spawn(@NotNull Location location,
|
||||||
|
int amount);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spawn the particle at a location.
|
||||||
|
*
|
||||||
|
* @param location The location.
|
||||||
|
*/
|
||||||
|
default void spawn(@NotNull Location location) {
|
||||||
|
spawn(location, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.willfp.eco.core.particle.impl;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.particle.SpawnableParticle;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty (invalid) particle that is spawned when an invalid key is provided.
|
||||||
|
*/
|
||||||
|
public final class EmptyParticle implements SpawnableParticle {
|
||||||
|
@Override
|
||||||
|
public void spawn(@NotNull final Location location,
|
||||||
|
final int amount) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.willfp.eco.core.particle.impl;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.particle.SpawnableParticle;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Particle;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Empty (invalid) particle that is spawned when an invalid key is provided.
|
||||||
|
*/
|
||||||
|
public final class SimpleParticle implements SpawnableParticle {
|
||||||
|
/**
|
||||||
|
* The particle to be spawned.
|
||||||
|
*/
|
||||||
|
private final Particle particle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new spawnable particle.
|
||||||
|
*
|
||||||
|
* @param particle The particle.
|
||||||
|
*/
|
||||||
|
public SimpleParticle(@NotNull final Particle particle) {
|
||||||
|
this.particle = particle;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void spawn(@NotNull final Location location,
|
||||||
|
final int amount) {
|
||||||
|
World world = location.getWorld();
|
||||||
|
|
||||||
|
if (world == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.spawnParticle(particle, location, amount, 0, 0, 0, 0, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
package com.willfp.eco.core.price;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.config.interfaces.Config;
|
||||||
|
import com.willfp.eco.core.math.MathContext;
|
||||||
|
import com.willfp.eco.core.price.impl.PriceFree;
|
||||||
|
import com.willfp.eco.core.serialization.ConfigDeserializer;
|
||||||
|
import com.willfp.eco.util.NumberUtils;
|
||||||
|
import com.willfp.eco.util.StringUtils;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A price that can be shown to a player.
|
||||||
|
*/
|
||||||
|
public final class ConfiguredPrice implements Price {
|
||||||
|
/**
|
||||||
|
* The deserializer.
|
||||||
|
*/
|
||||||
|
private static final ConfigDeserializer<ConfiguredPrice> DESERIALIZER = new Deserializer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free.
|
||||||
|
*/
|
||||||
|
private static final ConfiguredPrice FREE = new ConfiguredPrice(
|
||||||
|
new PriceFree(),
|
||||||
|
"Free"
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The price.
|
||||||
|
*/
|
||||||
|
private final Price price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The format string.
|
||||||
|
*/
|
||||||
|
private final String formatString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Configured Price.
|
||||||
|
*
|
||||||
|
* @param price The price.
|
||||||
|
* @param formatString The format string.
|
||||||
|
*/
|
||||||
|
public ConfiguredPrice(@NotNull final Price price,
|
||||||
|
@NotNull final String formatString) {
|
||||||
|
this.price = price;
|
||||||
|
this.formatString = formatString;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canAfford(@NotNull final Player player) {
|
||||||
|
return this.price.canAfford(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pay(@NotNull final Player player) {
|
||||||
|
this.price.pay(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void giveTo(@NotNull final Player player) {
|
||||||
|
this.price.giveTo(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(@NotNull final Player player) {
|
||||||
|
return this.price.getValue(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMultiplier(@NotNull final Player player) {
|
||||||
|
return this.price.getMultiplier(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMultiplier(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
this.price.setMultiplier(player, multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the price that this delegates to.
|
||||||
|
*
|
||||||
|
* @return The price.
|
||||||
|
*/
|
||||||
|
public Price getPrice() {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the display string for a player.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @return The display string.
|
||||||
|
*/
|
||||||
|
public String getDisplay(@NotNull final Player player) {
|
||||||
|
return StringUtils.format(
|
||||||
|
formatString.replace("%value%", NumberUtils.format(this.getPrice().getValue(player))),
|
||||||
|
player,
|
||||||
|
StringUtils.FormatOption.WITH_PLACEHOLDERS
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a configured price from config.
|
||||||
|
*
|
||||||
|
* @param config The config.
|
||||||
|
* @return The price, or null if it's invalid.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static ConfiguredPrice create(@NotNull final Config config) {
|
||||||
|
return DESERIALIZER.deserialize(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a configured price from config.
|
||||||
|
*
|
||||||
|
* @param config The config.
|
||||||
|
* @return The price, or free if invalid.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static ConfiguredPrice createOrFree(@NotNull final Config config) {
|
||||||
|
return Objects.requireNonNullElse(create(config), FREE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The deserializer for {@link ConfiguredPrice}.
|
||||||
|
*/
|
||||||
|
private static final class Deserializer implements ConfigDeserializer<ConfiguredPrice> {
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public ConfiguredPrice deserialize(@NotNull final Config config) {
|
||||||
|
if (!(
|
||||||
|
config.has("value")
|
||||||
|
&& config.has("type")
|
||||||
|
&& config.has("display")
|
||||||
|
)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String formatString = config.getString("display");
|
||||||
|
|
||||||
|
Price price = Prices.create(
|
||||||
|
config.getString("value"),
|
||||||
|
config.getString("type"),
|
||||||
|
MathContext.of(config)
|
||||||
|
);
|
||||||
|
|
||||||
|
return new ConfiguredPrice(price, formatString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
91
eco-api/src/main/java/com/willfp/eco/core/price/Price.java
Normal file
91
eco-api/src/main/java/com/willfp/eco/core/price/Price.java
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package com.willfp.eco.core.price;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A price that a player should pay.
|
||||||
|
*/
|
||||||
|
public interface Price {
|
||||||
|
/**
|
||||||
|
* Get if the player can afford the price.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @return If the player can afford.
|
||||||
|
*/
|
||||||
|
boolean canAfford(@NotNull Player player);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the player pay the price.
|
||||||
|
* <p>
|
||||||
|
* Only run this if the player can afford the price.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
*/
|
||||||
|
void pay(@NotNull Player player);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give the value of the price to the player.
|
||||||
|
* <p>
|
||||||
|
* You should override this method, it's only marked as default for
|
||||||
|
* backwards compatibility purposes.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
*/
|
||||||
|
default void giveTo(@NotNull Player player) {
|
||||||
|
// Override when needed.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the price is backed by a value, get it here.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @return The value.
|
||||||
|
*/
|
||||||
|
default double getValue(@NotNull final Player player) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the price is backed by a value, get it here.
|
||||||
|
*
|
||||||
|
* @return The value.
|
||||||
|
* @deprecated Use getValue(Player) instead.
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "6.45.0", forRemoval = true)
|
||||||
|
default double getValue() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the price is backed by a value, set it here.
|
||||||
|
*
|
||||||
|
* @param value The value.
|
||||||
|
* @deprecated Values shouldn't be fixed.
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "6.45.0", forRemoval = true)
|
||||||
|
default void setValue(final double value) {
|
||||||
|
// Override when needed.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the price multiplier for a player.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @return The value.
|
||||||
|
*/
|
||||||
|
default double getMultiplier(@NotNull final Player player) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the price multiplier for a player.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
*/
|
||||||
|
default void setMultiplier(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
// Override when needed.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.willfp.eco.core.price;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.math.MathContext;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create prices.
|
||||||
|
* <p>
|
||||||
|
* You must override one of the create methods.
|
||||||
|
*/
|
||||||
|
public interface PriceFactory {
|
||||||
|
/**
|
||||||
|
* Get the names (how the price looks in lookup strings).
|
||||||
|
* <p>
|
||||||
|
* For example, for XP Levels this would be 'l', 'xpl', 'levels', etc.
|
||||||
|
*
|
||||||
|
* @return The allowed names.
|
||||||
|
*/
|
||||||
|
@NotNull List<String> getNames();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the price.
|
||||||
|
*
|
||||||
|
* @param value The value.
|
||||||
|
* @return The price.
|
||||||
|
*/
|
||||||
|
default @NotNull Price create(final double value) {
|
||||||
|
return create(MathContext.EMPTY, (ctx) -> value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the price.
|
||||||
|
*
|
||||||
|
* @param baseContext The base MathContext.
|
||||||
|
* @param function The function to use. Should use {@link MathContext#copyWithPlayer(MathContext, Player)} on calls.
|
||||||
|
* @return The price.
|
||||||
|
*/
|
||||||
|
default @NotNull Price create(@NotNull final MathContext baseContext,
|
||||||
|
@NotNull final Function<MathContext, Double> function) {
|
||||||
|
return create(function.apply(baseContext));
|
||||||
|
}
|
||||||
|
}
|
||||||
103
eco-api/src/main/java/com/willfp/eco/core/price/Prices.java
Normal file
103
eco-api/src/main/java/com/willfp/eco/core/price/Prices.java
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
package com.willfp.eco.core.price;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.items.Items;
|
||||||
|
import com.willfp.eco.core.items.TestableItem;
|
||||||
|
import com.willfp.eco.core.math.MathContext;
|
||||||
|
import com.willfp.eco.core.price.impl.PriceEconomy;
|
||||||
|
import com.willfp.eco.core.price.impl.PriceFree;
|
||||||
|
import com.willfp.eco.core.price.impl.PriceItem;
|
||||||
|
import com.willfp.eco.core.recipe.parts.EmptyTestableItem;
|
||||||
|
import com.willfp.eco.util.NumberUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class to manage prices.
|
||||||
|
*/
|
||||||
|
public final class Prices {
|
||||||
|
/**
|
||||||
|
* All factories.
|
||||||
|
*/
|
||||||
|
private static final Map<String, PriceFactory> FACTORIES = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a new price factory.
|
||||||
|
*
|
||||||
|
* @param factory The factory.
|
||||||
|
*/
|
||||||
|
public static void registerPriceFactory(@NotNull final PriceFactory factory) {
|
||||||
|
for (String name : factory.getNames()) {
|
||||||
|
FACTORIES.put(name.toLowerCase(), factory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create price from an expression (representing the value),
|
||||||
|
* and a price name.
|
||||||
|
* <p>
|
||||||
|
* Supports items as price names.
|
||||||
|
*
|
||||||
|
* @param expression The expression for the value.
|
||||||
|
* @param priceName The price name.
|
||||||
|
* @return The price, or free if invalid.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Price create(@NotNull final String expression,
|
||||||
|
@Nullable final String priceName) {
|
||||||
|
return create(expression, priceName, MathContext.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create price from an expression (representing the value),
|
||||||
|
* and a price name. Uses a context to parse the expression.
|
||||||
|
* <p>
|
||||||
|
* Supports items as price names.
|
||||||
|
*
|
||||||
|
* @param expression The expression for the value.
|
||||||
|
* @param priceName The price name.
|
||||||
|
* @param context The math context to parse the expression.
|
||||||
|
* @return The price, or free if invalid.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Price create(@NotNull final String expression,
|
||||||
|
@Nullable final String priceName,
|
||||||
|
@NotNull final MathContext context) {
|
||||||
|
Function<MathContext, Double> function = (ctx) -> NumberUtils.evaluateExpression(
|
||||||
|
expression,
|
||||||
|
ctx
|
||||||
|
);
|
||||||
|
|
||||||
|
if (function.apply(context) <= 0) {
|
||||||
|
return new PriceFree();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default to economy
|
||||||
|
if (priceName == null) {
|
||||||
|
return new PriceEconomy(context, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find price factory
|
||||||
|
PriceFactory factory = FACTORIES.get(priceName);
|
||||||
|
|
||||||
|
// If no price factory, default to item price
|
||||||
|
if (factory == null) {
|
||||||
|
TestableItem item = Items.lookup(priceName);
|
||||||
|
|
||||||
|
if (item instanceof EmptyTestableItem) {
|
||||||
|
return new PriceFree();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PriceItem(context, function, item);
|
||||||
|
} else {
|
||||||
|
return factory.create(context, function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Prices() {
|
||||||
|
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package com.willfp.eco.core.price.impl;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.integrations.economy.EconomyManager;
|
||||||
|
import com.willfp.eco.core.math.MathContext;
|
||||||
|
import com.willfp.eco.core.price.Price;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Economy-based price (for Vault, Treasury, etc.)
|
||||||
|
*/
|
||||||
|
public final class PriceEconomy implements Price {
|
||||||
|
/**
|
||||||
|
* The value of the price.
|
||||||
|
*/
|
||||||
|
private final Function<MathContext, Double> function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The base math context.
|
||||||
|
*/
|
||||||
|
private final MathContext baseContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The multipliers.
|
||||||
|
*/
|
||||||
|
private final Map<UUID, Double> multipliers = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new economy-based price.
|
||||||
|
*
|
||||||
|
* @param value The value.
|
||||||
|
*/
|
||||||
|
public PriceEconomy(final double value) {
|
||||||
|
this(MathContext.EMPTY, ctx -> value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new economy-based price.
|
||||||
|
*
|
||||||
|
* @param baseContext The base context.
|
||||||
|
* @param function The function.
|
||||||
|
*/
|
||||||
|
public PriceEconomy(@NotNull final MathContext baseContext,
|
||||||
|
@NotNull final Function<MathContext, Double> function) {
|
||||||
|
this.baseContext = baseContext;
|
||||||
|
this.function = function;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canAfford(@NotNull final Player player) {
|
||||||
|
return EconomyManager.getBalance(player) >= getValue(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pay(@NotNull final Player player) {
|
||||||
|
EconomyManager.removeMoney(player, getValue(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void giveTo(@NotNull final Player player) {
|
||||||
|
EconomyManager.giveMoney(player, getValue(player));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(@NotNull final Player player) {
|
||||||
|
return this.function.apply(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMultiplier(@NotNull final Player player) {
|
||||||
|
return this.multipliers.getOrDefault(player.getUniqueId(), 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMultiplier(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
this.multipliers.put(player.getUniqueId(), multiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.willfp.eco.core.price.impl;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.price.Price;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free (default) price.
|
||||||
|
*/
|
||||||
|
public final class PriceFree implements Price {
|
||||||
|
/**
|
||||||
|
* Create a new free price.
|
||||||
|
*/
|
||||||
|
public PriceFree() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canAfford(@NotNull final Player player) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pay(@NotNull final Player player) {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
package com.willfp.eco.core.price.impl;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.drops.DropQueue;
|
||||||
|
import com.willfp.eco.core.items.TestableItem;
|
||||||
|
import com.willfp.eco.core.math.MathContext;
|
||||||
|
import com.willfp.eco.core.price.Price;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item-based price.
|
||||||
|
*/
|
||||||
|
public final class PriceItem implements Price {
|
||||||
|
/**
|
||||||
|
* The base MathContext.
|
||||||
|
*/
|
||||||
|
private final MathContext baseContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The amount of items.
|
||||||
|
*/
|
||||||
|
private final Function<MathContext, Double> function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The item.
|
||||||
|
*/
|
||||||
|
private final TestableItem item;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The multipliers.
|
||||||
|
*/
|
||||||
|
private final Map<UUID, Double> multipliers = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new item-based price.
|
||||||
|
*
|
||||||
|
* @param amount The amount.
|
||||||
|
* @param item The item.
|
||||||
|
*/
|
||||||
|
public PriceItem(final int amount,
|
||||||
|
@NotNull final TestableItem item) {
|
||||||
|
this(MathContext.EMPTY, ctx -> (double) amount, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new item-based price.
|
||||||
|
*
|
||||||
|
* @param baseContext The base MathContext.
|
||||||
|
* @param function The function to get the amount of items to remove.
|
||||||
|
* @param item The item.
|
||||||
|
*/
|
||||||
|
public PriceItem(@NotNull final MathContext baseContext,
|
||||||
|
@NotNull final Function<MathContext, Double> function,
|
||||||
|
@NotNull final TestableItem item) {
|
||||||
|
this.baseContext = baseContext;
|
||||||
|
this.function = function;
|
||||||
|
this.item = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the item.
|
||||||
|
*
|
||||||
|
* @return The item.
|
||||||
|
*/
|
||||||
|
public TestableItem getItem() {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canAfford(@NotNull final Player player) {
|
||||||
|
int toRemove = (int) getValue(player);
|
||||||
|
if (toRemove <= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (ItemStack itemStack : player.getInventory().getContents()) {
|
||||||
|
if (item.matches(itemStack)) {
|
||||||
|
count += itemStack.getAmount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return count >= toRemove;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pay(@NotNull final Player player) {
|
||||||
|
int toRemove = (int) getValue(player);
|
||||||
|
int count = 0;
|
||||||
|
|
||||||
|
for (ItemStack itemStack : player.getInventory().getContents()) {
|
||||||
|
if (count >= toRemove) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.matches(itemStack)) {
|
||||||
|
int itemAmount = itemStack.getAmount();
|
||||||
|
|
||||||
|
if (itemAmount > toRemove) {
|
||||||
|
itemStack.setAmount(itemAmount - toRemove);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemAmount <= toRemove) {
|
||||||
|
itemStack.setAmount(0);
|
||||||
|
itemStack.setType(Material.AIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
count += itemAmount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void giveTo(@NotNull final Player player) {
|
||||||
|
ItemStack itemStack = item.getItem().clone();
|
||||||
|
itemStack.setAmount((int) getValue(player));
|
||||||
|
|
||||||
|
new DropQueue(player)
|
||||||
|
.addItem(itemStack)
|
||||||
|
.forceTelekinesis()
|
||||||
|
.push();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(@NotNull final Player player) {
|
||||||
|
return Math.toIntExact(Math.round(
|
||||||
|
this.function.apply(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMultiplier(@NotNull final Player player) {
|
||||||
|
return this.multipliers.getOrDefault(player.getUniqueId(), 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMultiplier(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
this.multipliers.put(player.getUniqueId(), multiplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
package com.willfp.eco.core.sound;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.config.interfaces.Config;
|
||||||
|
import com.willfp.eco.core.serialization.ConfigDeserializer;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.Sound;
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sound that can be played at a location.
|
||||||
|
*
|
||||||
|
* @param sound The sound.
|
||||||
|
* @param pitch The pitch.
|
||||||
|
* @param volume The volume.
|
||||||
|
*/
|
||||||
|
public record PlayableSound(@NotNull Sound sound,
|
||||||
|
double pitch,
|
||||||
|
double volume) {
|
||||||
|
/**
|
||||||
|
* The deserializer.
|
||||||
|
*/
|
||||||
|
private static final ConfigDeserializer<PlayableSound> DESERIALIZER = new Deserializer();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a sound with a default volume.
|
||||||
|
*
|
||||||
|
* @param sound The sound.
|
||||||
|
* @param pitch The pitch.
|
||||||
|
*/
|
||||||
|
public PlayableSound(@NotNull final Sound sound,
|
||||||
|
final double pitch) {
|
||||||
|
this(sound, pitch, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play the sound to a player.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
*/
|
||||||
|
public void playTo(@NotNull final Player player) {
|
||||||
|
player.playSound(player.getLocation(), sound, (float) volume, (float) pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Play the sound at a location.
|
||||||
|
*
|
||||||
|
* @param location The location.
|
||||||
|
*/
|
||||||
|
public void playAt(@NotNull final Location location) {
|
||||||
|
World world = location.getWorld();
|
||||||
|
|
||||||
|
if (world == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
world.playSound(location, sound, (float) volume, (float) pitch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse a playable sound from config.
|
||||||
|
*
|
||||||
|
* @param config The config.
|
||||||
|
* @return The sound, or null if it's invalid.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static PlayableSound create(@NotNull final Config config) {
|
||||||
|
return DESERIALIZER.deserialize(config);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The deserializer for {@link PlayableSound}.
|
||||||
|
*/
|
||||||
|
private static final class Deserializer implements ConfigDeserializer<PlayableSound> {
|
||||||
|
@Override
|
||||||
|
public @Nullable PlayableSound deserialize(@NotNull final Config config) {
|
||||||
|
if (!config.has("sound")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
Sound sound = Sound.valueOf(config.getString("sound").toUpperCase());
|
||||||
|
|
||||||
|
double pitch = Objects.requireNonNullElse(config.getDouble("pitch"), 1.0);
|
||||||
|
double volume = Objects.requireNonNullElse(config.getDouble("volume"), 1.0);
|
||||||
|
|
||||||
|
return new PlayableSound(
|
||||||
|
sound,
|
||||||
|
pitch,
|
||||||
|
volume
|
||||||
|
);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.willfp.eco.util;
|
package com.willfp.eco.util;
|
||||||
|
|
||||||
import com.willfp.eco.core.Eco;
|
import com.willfp.eco.core.Eco;
|
||||||
|
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
|
||||||
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
import com.willfp.eco.core.placeholder.AdditionalPlayer;
|
||||||
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
import com.willfp.eco.core.placeholder.InjectablePlaceholder;
|
||||||
|
import com.willfp.eco.core.math.MathContext;
|
||||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
import com.willfp.eco.core.placeholder.PlaceholderInjectable;
|
||||||
import com.willfp.eco.core.placeholder.StaticPlaceholder;
|
import com.willfp.eco.core.placeholder.StaticPlaceholder;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -12,7 +14,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.text.DecimalFormat;
|
import java.text.DecimalFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
@@ -240,7 +241,7 @@ public final class NumberUtils {
|
|||||||
* @return The value of the expression, or zero if invalid.
|
* @return The value of the expression, or zero if invalid.
|
||||||
*/
|
*/
|
||||||
public static double evaluateExpression(@NotNull final String expression) {
|
public static double evaluateExpression(@NotNull final String expression) {
|
||||||
return evaluateExpression(expression, null);
|
return evaluateExpression(expression, MathContext.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -252,18 +253,7 @@ public final class NumberUtils {
|
|||||||
*/
|
*/
|
||||||
public static double evaluateExpression(@NotNull final String expression,
|
public static double evaluateExpression(@NotNull final String expression,
|
||||||
@Nullable final Player player) {
|
@Nullable final Player player) {
|
||||||
return evaluateExpression(expression, player, new PlaceholderInjectable() {
|
return evaluateExpression(expression, player, PlaceholderManager.EMPTY_INJECTABLE);
|
||||||
@Override
|
|
||||||
public void clearInjectedPlaceholders() {
|
|
||||||
// Nothing.
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull
|
|
||||||
List<InjectablePlaceholder> getPlaceholderInjections() {
|
|
||||||
return Collections.emptyList();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -323,7 +313,23 @@ public final class NumberUtils {
|
|||||||
@Nullable final Player player,
|
@Nullable final Player player,
|
||||||
@NotNull final PlaceholderInjectable context,
|
@NotNull final PlaceholderInjectable context,
|
||||||
@NotNull final Collection<AdditionalPlayer> additionalPlayers) {
|
@NotNull final Collection<AdditionalPlayer> additionalPlayers) {
|
||||||
return Eco.get().evaluate(expression, player, context, additionalPlayers);
|
return Eco.get().evaluate(expression, new MathContext(
|
||||||
|
context,
|
||||||
|
player,
|
||||||
|
additionalPlayers
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evaluate an expression with respect to a player (for placeholders).
|
||||||
|
*
|
||||||
|
* @param expression The expression.
|
||||||
|
* @param context The math context.
|
||||||
|
* @return The value of the expression, or zero if invalid.
|
||||||
|
*/
|
||||||
|
public static double evaluateExpression(@NotNull final String expression,
|
||||||
|
@NotNull final MathContext context) {
|
||||||
|
return Eco.get().evaluate(expression, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NumberUtils() {
|
private NumberUtils() {
|
||||||
|
|||||||
@@ -3,9 +3,12 @@
|
|||||||
package com.willfp.eco.core.config
|
package com.willfp.eco.core.config
|
||||||
|
|
||||||
import com.willfp.eco.core.config.interfaces.Config
|
import com.willfp.eco.core.config.interfaces.Config
|
||||||
|
import org.bukkit.configuration.ConfigurationSection
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
/** Helper class to create configs with a kotlin DSL. */
|
/** Helper class to create configs with a kotlin DSL. */
|
||||||
class DSLConfig internal constructor(type: ConfigType) : TransientConfig(emptyMap(), type) {
|
class DSLConfig internal constructor(type: ConfigType) : GenericConfig(type) {
|
||||||
/**
|
/**
|
||||||
* Map a key to a value.
|
* Map a key to a value.
|
||||||
*
|
*
|
||||||
@@ -34,3 +37,30 @@ class DSLConfig internal constructor(type: ConfigType) : TransientConfig(emptyMa
|
|||||||
*/
|
*/
|
||||||
fun config(type: ConfigType = ConfigType.YAML, builder: DSLConfig.() -> Unit): Config =
|
fun config(type: ConfigType = ConfigType.YAML, builder: DSLConfig.() -> Unit): Config =
|
||||||
DSLConfig(type).apply(builder)
|
DSLConfig(type).apply(builder)
|
||||||
|
|
||||||
|
/** @see Configs.empty */
|
||||||
|
fun emptyConfig() = Configs.empty()
|
||||||
|
|
||||||
|
/** @see Configs.empty */
|
||||||
|
fun emptyConfig(type: ConfigType) = Configs.empty(type)
|
||||||
|
|
||||||
|
/** @see Configs.fromBukkit */
|
||||||
|
fun ConfigurationSection?.toConfig() = Configs.fromBukkit(this)
|
||||||
|
|
||||||
|
/** @see Configs.fromStream */
|
||||||
|
fun InputStream?.readConfig() = Configs.fromStream(this)
|
||||||
|
|
||||||
|
/** @see Configs.fromFile */
|
||||||
|
fun File?.readConfig() = Configs.fromFile(this)
|
||||||
|
|
||||||
|
/** @see Configs.fromFile */
|
||||||
|
fun File?.readConfig(type: ConfigType) = Configs.fromFile(this, type)
|
||||||
|
|
||||||
|
/** @see Configs.fromMap */
|
||||||
|
fun Map<String?, Any?>.toConfig() = Configs.fromMap(this)
|
||||||
|
|
||||||
|
/** @see Configs.fromMap */
|
||||||
|
fun Map<String?, Any?>.toConfig(type: ConfigType) = Configs.fromMap(this, type)
|
||||||
|
|
||||||
|
/** @see Configs.fromString */
|
||||||
|
fun readConfig(contents: String, type: ConfigType) = Configs.fromString(contents, type)
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ package com.willfp.eco.core.gui
|
|||||||
|
|
||||||
import com.willfp.eco.core.gui.menu.Menu
|
import com.willfp.eco.core.gui.menu.Menu
|
||||||
import com.willfp.eco.core.gui.menu.MenuBuilder
|
import com.willfp.eco.core.gui.menu.MenuBuilder
|
||||||
import com.willfp.eco.core.gui.menu.MenuType
|
|
||||||
import com.willfp.eco.core.gui.menu.MenuEvent
|
import com.willfp.eco.core.gui.menu.MenuEvent
|
||||||
import com.willfp.eco.core.gui.menu.MenuEventHandler
|
import com.willfp.eco.core.gui.menu.MenuEventHandler
|
||||||
|
import com.willfp.eco.core.gui.menu.MenuType
|
||||||
import com.willfp.eco.core.gui.page.Page
|
import com.willfp.eco.core.gui.page.Page
|
||||||
import com.willfp.eco.core.gui.page.PageBuilder
|
import com.willfp.eco.core.gui.page.PageBuilder
|
||||||
import com.willfp.eco.core.gui.slot.Slot
|
import com.willfp.eco.core.gui.slot.Slot
|
||||||
@@ -184,6 +184,10 @@ inline fun <reified T : MenuEvent> MenuBuilder.onEvent(crossinline handler: (Pla
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @see MenuBuilder.onBuild */
|
||||||
|
fun MenuBuilder.onBuild(action: (Menu) -> Unit): MenuBuilder =
|
||||||
|
this.onBuild { action(it) }
|
||||||
|
|
||||||
/** Kotlin builder for menus. */
|
/** Kotlin builder for menus. */
|
||||||
fun menu(
|
fun menu(
|
||||||
rows: Int,
|
rows: Int,
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
@file:JvmName("ItemBuilderExtensions")
|
||||||
|
|
||||||
|
package com.willfp.eco.core.items.builder
|
||||||
|
|
||||||
|
import com.willfp.eco.core.items.TestableItem
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
|
||||||
|
/** Modify an item with a builder. */
|
||||||
|
fun TestableItem.modify(builder: ItemBuilder.() -> Unit): ItemStack =
|
||||||
|
this.item.modify(builder)
|
||||||
|
|
||||||
|
/** Modify an item with a builder. */
|
||||||
|
fun ItemStack.modify(builder: ItemBuilder.() -> Unit): ItemStack =
|
||||||
|
ItemStackBuilder(this).apply(builder).build()
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
@file:JvmName("TestableExtensions")
|
||||||
|
|
||||||
|
package com.willfp.eco.core.lookup
|
||||||
|
|
||||||
|
/** @see Testable.matches */
|
||||||
|
fun <T> T?.matches(test: Testable<T>) =
|
||||||
|
test.matches(this)
|
||||||
@@ -2,8 +2,8 @@ package com.willfp.eco.internal
|
|||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin
|
import com.willfp.eco.core.EcoPlugin
|
||||||
import com.willfp.eco.core.PluginProps
|
import com.willfp.eco.core.PluginProps
|
||||||
import com.willfp.eco.core.config.TransientConfig
|
|
||||||
import com.willfp.eco.core.config.interfaces.Config
|
import com.willfp.eco.core.config.interfaces.Config
|
||||||
|
import com.willfp.eco.core.config.readConfig
|
||||||
|
|
||||||
object EcoPropsParser : PluginProps.PropsParser<Config> {
|
object EcoPropsParser : PluginProps.PropsParser<Config> {
|
||||||
override fun parseFrom(config: Config): PluginProps {
|
override fun parseFrom(config: Config): PluginProps {
|
||||||
@@ -28,7 +28,7 @@ object EcoPropsParser : PluginProps.PropsParser<Config> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return PluginProps.parse(
|
return PluginProps.parse(
|
||||||
TransientConfig(plugin.getResourceAsStream("/eco.yml")),
|
plugin.getResourceAsStream("/eco.yml").readConfig(),
|
||||||
Config::class.java
|
Config::class.java
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ open class EcoConfig(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getSubsectionsOrNull(path: String): List<Config>? {
|
override fun getSubsectionsOrNull(path: String): List<Config>? {
|
||||||
return (get(path) as? Iterable<Config>)
|
return getList<Config>(path)
|
||||||
?.map { it.apply { this.addInjectablePlaceholder(injections) } }
|
?.map { it.apply { this.addInjectablePlaceholder(injections) } }
|
||||||
?.toList()
|
?.toList()
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ open class EcoConfig(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getIntsOrNull(path: String): List<Int>? {
|
override fun getIntsOrNull(path: String): List<Int>? {
|
||||||
return (get(path) as? Iterable<Number>)?.map { it.toInt() }
|
return getList<Number>(path)?.map { it.toInt() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getBoolOrNull(path: String): Boolean? {
|
override fun getBoolOrNull(path: String): Boolean? {
|
||||||
@@ -130,7 +130,7 @@ open class EcoConfig(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getBoolsOrNull(path: String): List<Boolean>? {
|
override fun getBoolsOrNull(path: String): List<Boolean>? {
|
||||||
return (get(path) as? Iterable<Boolean>)?.toList()
|
return getList<Boolean>(path)?.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getStringOrNull(
|
override fun getStringOrNull(
|
||||||
@@ -154,7 +154,7 @@ open class EcoConfig(
|
|||||||
format: Boolean,
|
format: Boolean,
|
||||||
option: StringUtils.FormatOption
|
option: StringUtils.FormatOption
|
||||||
): List<String>? {
|
): List<String>? {
|
||||||
val strings = (get(path) as? Iterable<*>)
|
val strings = getList<Any?>(path)
|
||||||
?.map { it?.toString() ?: "" }
|
?.map { it?.toString() ?: "" }
|
||||||
?.toMutableList() ?: return null
|
?.toMutableList() ?: return null
|
||||||
if (placeholderInjections.isNotEmpty() && format && option == StringUtils.FormatOption.WITH_PLACEHOLDERS) {
|
if (placeholderInjections.isNotEmpty() && format && option == StringUtils.FormatOption.WITH_PLACEHOLDERS) {
|
||||||
@@ -176,7 +176,7 @@ open class EcoConfig(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun getDoublesOrNull(path: String): List<Double>? {
|
override fun getDoublesOrNull(path: String): List<Double>? {
|
||||||
return (get(path) as? Iterable<Number>)?.map { it.toDouble() }
|
return getList<Number>(path)?.map { it.toDouble() }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addInjectablePlaceholder(placeholders: Iterable<InjectablePlaceholder>) {
|
override fun addInjectablePlaceholder(placeholders: Iterable<InjectablePlaceholder>) {
|
||||||
@@ -215,4 +215,15 @@ open class EcoConfig(
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return this.toPlaintext()
|
return this.toPlaintext()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T> getList(path: String): List<T>? {
|
||||||
|
val asIterable = get(path) as? Iterable<*> ?: return null
|
||||||
|
val asList = asIterable.toList()
|
||||||
|
|
||||||
|
if (asList.firstOrNull() !is T?) {
|
||||||
|
return emptyList()
|
||||||
|
}
|
||||||
|
|
||||||
|
return asList as List<T>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.willfp.eco.internal.extensions
|
|||||||
import com.google.common.collect.ImmutableSet
|
import com.google.common.collect.ImmutableSet
|
||||||
import com.willfp.eco.core.Eco
|
import com.willfp.eco.core.Eco
|
||||||
import com.willfp.eco.core.EcoPlugin
|
import com.willfp.eco.core.EcoPlugin
|
||||||
import com.willfp.eco.core.config.TransientConfig
|
import com.willfp.eco.core.config.toConfig
|
||||||
import com.willfp.eco.core.extensions.Extension
|
import com.willfp.eco.core.extensions.Extension
|
||||||
import com.willfp.eco.core.extensions.ExtensionLoader
|
import com.willfp.eco.core.extensions.ExtensionLoader
|
||||||
import com.willfp.eco.core.extensions.ExtensionMetadata
|
import com.willfp.eco.core.extensions.ExtensionMetadata
|
||||||
@@ -48,7 +48,7 @@ class EcoExtensionLoader(
|
|||||||
val ymlIn = classLoader.getResourceAsStream("extension.yml")
|
val ymlIn = classLoader.getResourceAsStream("extension.yml")
|
||||||
?: throw MalformedExtensionException("No extension.yml found in " + extensionJar.name)
|
?: throw MalformedExtensionException("No extension.yml found in " + extensionJar.name)
|
||||||
|
|
||||||
val extensionYml = TransientConfig(YamlConfiguration.loadConfiguration(InputStreamReader(ymlIn)))
|
val extensionYml = YamlConfiguration.loadConfiguration(InputStreamReader(ymlIn)).toConfig()
|
||||||
|
|
||||||
val mainClass = extensionYml.getStringOrNull("main")
|
val mainClass = extensionYml.getStringOrNull("main")
|
||||||
var name = extensionYml.getStringOrNull("name")
|
var name = extensionYml.getStringOrNull("name")
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ class MergedStateMenu(
|
|||||||
return base.getState(player) + additional.getState(player)
|
return base.getState(player) + additional.getState(player)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addState(player: Player, key: String, value: Any?) {
|
override fun setState(player: Player, key: String, value: Any?) {
|
||||||
base.addState(player, key, value)
|
base.setState(player, key, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun clearState(player: Player) {
|
override fun clearState(player: Player) {
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import org.bukkit.inventory.ItemStack
|
|||||||
class EcoMenu(
|
class EcoMenu(
|
||||||
private val rows: Int,
|
private val rows: Int,
|
||||||
private val columns: Int,
|
private val columns: Int,
|
||||||
private val componentsAtPoints: Map<GUIPosition, List<OffsetComponent>>,
|
private val components: LayeredComponents,
|
||||||
private val title: String,
|
private val title: String,
|
||||||
private val onClose: List<CloseHandler>,
|
private val onClose: List<CloseHandler>,
|
||||||
private val onRender: List<(Player, Menu) -> Unit>,
|
private val onRender: List<(Player, Menu) -> Unit>,
|
||||||
@@ -28,38 +28,19 @@ class EcoMenu(
|
|||||||
private val menuEventHandlers: List<MenuEventHandler<*>>,
|
private val menuEventHandlers: List<MenuEventHandler<*>>,
|
||||||
private val allowsChangingHeldItem: Boolean
|
private val allowsChangingHeldItem: Boolean
|
||||||
) : Menu {
|
) : Menu {
|
||||||
private fun getPossiblyReactiveSlot(row: Int, column: Int, player: Player?, menu: Menu?): Slot {
|
private fun getPossiblyReactiveSlot(row: Int, column: Int, player: Player?): Slot {
|
||||||
if (row < 1 || row > this.rows || column < 1 || column > this.columns) {
|
if (row < 1 || row > this.rows || column < 1 || column > this.columns) {
|
||||||
return emptyFillerSlot
|
return emptyFillerSlot
|
||||||
}
|
}
|
||||||
|
|
||||||
val guiPosition = GUIPosition(row, column)
|
return components.getSlotAt(row, column, player, this)
|
||||||
val components = componentsAtPoints[guiPosition] ?: return emptyFillerSlot
|
|
||||||
|
|
||||||
for (component in components) {
|
|
||||||
val found = if (player != null && menu != null) component.component.getSlotAt(
|
|
||||||
component.rowOffset,
|
|
||||||
component.columnOffset,
|
|
||||||
player,
|
|
||||||
menu
|
|
||||||
) else component.component.getSlotAt(
|
|
||||||
component.rowOffset,
|
|
||||||
component.columnOffset
|
|
||||||
)
|
|
||||||
|
|
||||||
if (found != null) {
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return emptyFillerSlot
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getSlot(row: Int, column: Int): Slot =
|
override fun getSlot(row: Int, column: Int): Slot =
|
||||||
getPossiblyReactiveSlot(row, column, null, null)
|
getPossiblyReactiveSlot(row, column, null)
|
||||||
|
|
||||||
override fun getSlot(row: Int, column: Int, player: Player, menu: Menu): Slot =
|
override fun getSlot(row: Int, column: Int, player: Player): Slot =
|
||||||
getPossiblyReactiveSlot(row, column, player, menu)
|
getPossiblyReactiveSlot(row, column, player)
|
||||||
|
|
||||||
override fun open(player: Player): Inventory {
|
override fun open(player: Player): Inventory {
|
||||||
val inventory = if (columns == 9) {
|
val inventory = if (columns == 9) {
|
||||||
@@ -129,7 +110,7 @@ class EcoMenu(
|
|||||||
this.handle(player, this@EcoMenu, event as T)
|
this.handle(player, this@EcoMenu, event as T)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addState(player: Player, key: String, value: Any?) {
|
override fun setState(player: Player, key: String, value: Any?) {
|
||||||
val inventory = player.renderedInventory ?: return
|
val inventory = player.renderedInventory ?: return
|
||||||
inventory.state[key] = value
|
inventory.state[key] = value
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ class EcoMenuBuilder(
|
|||||||
private val onOpen = mutableListOf<OpenHandler>()
|
private val onOpen = mutableListOf<OpenHandler>()
|
||||||
private val onRender = mutableListOf<(Player, Menu) -> Unit>()
|
private val onRender = mutableListOf<(Player, Menu) -> Unit>()
|
||||||
private val menuEventHandlers = mutableListOf<MenuEventHandler<*>>()
|
private val menuEventHandlers = mutableListOf<MenuEventHandler<*>>()
|
||||||
|
private val onBuild = mutableListOf<(Menu) -> Unit>()
|
||||||
private var allowsChangingHeldItem = false
|
private var allowsChangingHeldItem = false
|
||||||
|
|
||||||
override fun getRows() = rows
|
override fun getRows() = rows
|
||||||
@@ -80,13 +81,18 @@ class EcoMenuBuilder(
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onBuild(action: Consumer<Menu>): MenuBuilder {
|
||||||
|
onBuild += { action.accept(it) }
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
override fun allowChangingHeldItem(): MenuBuilder {
|
override fun allowChangingHeldItem(): MenuBuilder {
|
||||||
allowsChangingHeldItem = true
|
allowsChangingHeldItem = true
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun build(): Menu {
|
override fun build(): Menu {
|
||||||
val layeredComponents = mutableMapOf<MenuLayer, MutableMap<GUIPosition, MutableList<OffsetComponent>>>()
|
val layeredComponents = LayeredComponents()
|
||||||
|
|
||||||
// 5 nested for loops? Shut up. Silence. Quiet.
|
// 5 nested for loops? Shut up. Silence. Quiet.
|
||||||
for (layer in MenuLayer.values()) {
|
for (layer in MenuLayer.values()) {
|
||||||
@@ -107,11 +113,14 @@ class EcoMenuBuilder(
|
|||||||
|
|
||||||
val point = GUIPosition(row, column)
|
val point = GUIPosition(row, column)
|
||||||
|
|
||||||
layeredComponents.computeIfAbsent(layer) { mutableMapOf() }
|
layeredComponents.addOffsetComponent(
|
||||||
.computeIfAbsent(point) { mutableListOf() } += OffsetComponent(
|
layer,
|
||||||
component,
|
point,
|
||||||
rowOffset,
|
OffsetComponent(
|
||||||
columnOffset
|
component,
|
||||||
|
rowOffset,
|
||||||
|
columnOffset
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,18 +128,10 @@ class EcoMenuBuilder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val componentsAtPoints = mutableMapOf<GUIPosition, MutableList<OffsetComponent>>()
|
val menu = EcoMenu(
|
||||||
|
|
||||||
for (menuLayer in MenuLayer.values()) {
|
|
||||||
for ((anchor, offsetComponents) in layeredComponents[menuLayer] ?: emptyMap()) {
|
|
||||||
componentsAtPoints[anchor] = offsetComponents
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return EcoMenu(
|
|
||||||
rows,
|
rows,
|
||||||
columns,
|
columns,
|
||||||
componentsAtPoints,
|
layeredComponents,
|
||||||
title,
|
title,
|
||||||
onClose,
|
onClose,
|
||||||
onRender,
|
onRender,
|
||||||
@@ -138,5 +139,9 @@ class EcoMenuBuilder(
|
|||||||
menuEventHandlers,
|
menuEventHandlers,
|
||||||
allowsChangingHeldItem
|
allowsChangingHeldItem
|
||||||
)
|
)
|
||||||
|
|
||||||
|
onBuild.forEach { it(menu) } // Run on build functions.
|
||||||
|
|
||||||
|
return menu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.willfp.eco.internal.gui.menu
|
||||||
|
|
||||||
|
import com.willfp.eco.core.gui.menu.Menu
|
||||||
|
import com.willfp.eco.core.gui.menu.MenuLayer
|
||||||
|
import com.willfp.eco.core.gui.slot.Slot
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
|
class LayeredComponents {
|
||||||
|
private val layers = mutableMapOf<MenuLayer, Map<GUIPosition, List<OffsetComponent>>>()
|
||||||
|
|
||||||
|
fun getSlotAt(row: Int, column: Int, player: Player?, menu: Menu): Slot {
|
||||||
|
val guiPosition = GUIPosition(row, column)
|
||||||
|
|
||||||
|
for (layer in MenuLayer.values().reversed()) {
|
||||||
|
val componentsAtPoints = layers[layer] ?: continue
|
||||||
|
|
||||||
|
val components = componentsAtPoints[guiPosition] ?: continue
|
||||||
|
|
||||||
|
for (component in components) {
|
||||||
|
val found = if (player != null) component.component.getSlotAt(
|
||||||
|
component.rowOffset,
|
||||||
|
component.columnOffset,
|
||||||
|
player,
|
||||||
|
menu
|
||||||
|
) else component.component.getSlotAt(
|
||||||
|
component.rowOffset,
|
||||||
|
component.columnOffset
|
||||||
|
)
|
||||||
|
|
||||||
|
if (found != null) {
|
||||||
|
return found
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return emptyFillerSlot
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addOffsetComponent(layer: MenuLayer, position: GUIPosition, component: OffsetComponent) {
|
||||||
|
val inLayer = layers[layer]?.toMutableMap() ?: mutableMapOf()
|
||||||
|
val atPosition = inLayer[position]?.toMutableList() ?: mutableListOf()
|
||||||
|
atPosition.add(component)
|
||||||
|
inLayer[position] = atPosition
|
||||||
|
layers[layer] = inLayer
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.willfp.eco.internal.gui.menu
|
package com.willfp.eco.internal.gui.menu
|
||||||
|
|
||||||
|
import com.willfp.eco.core.gui.menu.events.CaptiveItemChangeEvent
|
||||||
import com.willfp.eco.core.items.isEmpty
|
import com.willfp.eco.core.items.isEmpty
|
||||||
import com.willfp.eco.core.recipe.parts.EmptyTestableItem
|
import com.willfp.eco.core.recipe.parts.EmptyTestableItem
|
||||||
import com.willfp.eco.util.MenuUtils
|
import com.willfp.eco.util.MenuUtils
|
||||||
@@ -31,14 +32,14 @@ class RenderedInventory(
|
|||||||
val state = mutableMapOf<String, Any?>()
|
val state = mutableMapOf<String, Any?>()
|
||||||
|
|
||||||
fun render() {
|
fun render() {
|
||||||
captiveItems.clear()
|
val newCaptive = mutableMapOf<GUIPosition, ItemStack>()
|
||||||
|
|
||||||
for (row in (1..menu.rows)) {
|
for (row in (1..menu.rows)) {
|
||||||
for (column in (1..menu.columns)) {
|
for (column in (1..menu.columns)) {
|
||||||
val position = GUIPosition(row, column)
|
val position = GUIPosition(row, column)
|
||||||
val bukkit = MenuUtils.rowColumnToSlot(row, column, menu.columns)
|
val bukkit = MenuUtils.rowColumnToSlot(row, column, menu.columns)
|
||||||
|
|
||||||
val slot = menu.getSlot(row, column, player, menu)
|
val slot = menu.getSlot(row, column, player)
|
||||||
val renderedItem = slot.getItemStack(player)
|
val renderedItem = slot.getItemStack(player)
|
||||||
|
|
||||||
if (slot.isCaptive(player, menu)) {
|
if (slot.isCaptive(player, menu)) {
|
||||||
@@ -46,11 +47,11 @@ class RenderedInventory(
|
|||||||
|
|
||||||
if (slot.isCaptiveFromEmpty) {
|
if (slot.isCaptiveFromEmpty) {
|
||||||
if (!actualItem.isEmpty) {
|
if (!actualItem.isEmpty) {
|
||||||
captiveItems[position] = actualItem
|
newCaptive[position] = actualItem
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (actualItem != renderedItem && !EmptyTestableItem().matches(actualItem)) {
|
if (actualItem != renderedItem && !EmptyTestableItem().matches(actualItem)) {
|
||||||
captiveItems[position] = actualItem
|
newCaptive[position] = actualItem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -59,15 +60,51 @@ class RenderedInventory(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val previousCaptive = captiveItems.toMap()
|
||||||
|
captiveItems.clear()
|
||||||
|
captiveItems.putAll(newCaptive)
|
||||||
|
|
||||||
|
// Call captive item change event
|
||||||
|
for (position in previousCaptive.keys union newCaptive.keys) {
|
||||||
|
if (previousCaptive[position] != newCaptive[position]) {
|
||||||
|
menu.callEvent(
|
||||||
|
player, CaptiveItemChangeEvent(
|
||||||
|
position.row,
|
||||||
|
position.column,
|
||||||
|
previousCaptive[position],
|
||||||
|
newCaptive[position]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
menu.runOnRender(player)
|
menu.runOnRender(player)
|
||||||
|
|
||||||
|
// Run second render if captive items changed
|
||||||
|
if (captiveItems != previousCaptive) {
|
||||||
|
for (row in (1..menu.rows)) {
|
||||||
|
for (column in (1..menu.columns)) {
|
||||||
|
val bukkit = MenuUtils.rowColumnToSlot(row, column, menu.columns)
|
||||||
|
|
||||||
|
val slot = menu.getSlot(row, column, player)
|
||||||
|
val renderedItem = slot.getItemStack(player)
|
||||||
|
|
||||||
|
if (!slot.isCaptive(player, menu)) {
|
||||||
|
inventory.setItem(bukkit, renderedItem)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun renderDefaultCaptiveItems() {
|
fun renderDefaultCaptiveItems() {
|
||||||
|
menu.runOnRender(player)
|
||||||
|
|
||||||
for (row in (1..menu.rows)) {
|
for (row in (1..menu.rows)) {
|
||||||
for (column in (1..menu.columns)) {
|
for (column in (1..menu.columns)) {
|
||||||
val bukkit = MenuUtils.rowColumnToSlot(row, column, menu.columns)
|
val bukkit = MenuUtils.rowColumnToSlot(row, column, menu.columns)
|
||||||
|
|
||||||
val slot = menu.getSlot(row, column, player, menu)
|
val slot = menu.getSlot(row, column, player)
|
||||||
|
|
||||||
if (slot.isCaptive(player, menu)) {
|
if (slot.isCaptive(player, menu)) {
|
||||||
inventory.setItem(bukkit, slot.getItemStack(player))
|
inventory.setItem(bukkit, slot.getItemStack(player))
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
package com.willfp.eco.internal.integrations
|
package com.willfp.eco.internal.integrations
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin
|
import com.willfp.eco.core.EcoPlugin
|
||||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration
|
|
||||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
||||||
import me.clip.placeholderapi.PlaceholderAPI
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
class PlaceholderIntegrationPAPI(private val plugin: EcoPlugin) : PlaceholderExpansion(), PlaceholderIntegration {
|
class PAPIExpansion(private val plugin: EcoPlugin) : PlaceholderExpansion() {
|
||||||
|
init {
|
||||||
|
register()
|
||||||
|
}
|
||||||
|
|
||||||
override fun persist(): Boolean {
|
override fun persist(): Boolean {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -34,29 +36,4 @@ class PlaceholderIntegrationPAPI(private val plugin: EcoPlugin) : PlaceholderExp
|
|||||||
): String {
|
): String {
|
||||||
return PlaceholderManager.getResult(player, identifier, plugin)
|
return PlaceholderManager.getResult(player, identifier, plugin)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
override fun registerIntegration() {
|
|
||||||
register()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getPluginName(): String {
|
|
||||||
return "PlaceholderAPI"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun translate(
|
|
||||||
text: String,
|
|
||||||
player: Player?
|
|
||||||
): String {
|
|
||||||
return PlaceholderAPI.setPlaceholders(player, text)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun findPlaceholdersIn(text: String): MutableList<String> {
|
|
||||||
val placeholders = mutableListOf<String>()
|
|
||||||
val matcher = PlaceholderAPI.getPlaceholderPattern().matcher(text)
|
|
||||||
while (matcher.find()) {
|
|
||||||
placeholders.add(matcher.group())
|
|
||||||
}
|
|
||||||
|
|
||||||
return placeholders
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -27,6 +27,10 @@ object ArgParserCustomModelData : LookupArgParser {
|
|||||||
return Predicate {
|
return Predicate {
|
||||||
val testMeta = it.itemMeta ?: return@Predicate false
|
val testMeta = it.itemMeta ?: return@Predicate false
|
||||||
|
|
||||||
|
if (!testMeta.hasCustomModelData()) {
|
||||||
|
return@Predicate false
|
||||||
|
}
|
||||||
|
|
||||||
testMeta.customModelData == modelData
|
testMeta.customModelData == modelData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
package com.willfp.eco.internal.particle
|
||||||
|
|
||||||
|
import com.willfp.eco.core.particle.ParticleFactory
|
||||||
|
import com.willfp.eco.core.particle.SpawnableParticle
|
||||||
|
import org.bukkit.Color
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.Particle
|
||||||
|
|
||||||
|
object ParticleFactoryRGB : ParticleFactory {
|
||||||
|
override fun getNames() = listOf(
|
||||||
|
"color",
|
||||||
|
"rgb",
|
||||||
|
"hex"
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun create(key: String): SpawnableParticle? {
|
||||||
|
val hex = key.toIntOrNull(16) ?: return null
|
||||||
|
val color = try {
|
||||||
|
Color.fromRGB(hex)
|
||||||
|
} catch (e: IllegalArgumentException) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
return SpawnableParticleRGB(Particle.DustOptions(color, 1.0f))
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SpawnableParticleRGB(
|
||||||
|
private val options: Particle.DustOptions
|
||||||
|
) : SpawnableParticle {
|
||||||
|
override fun spawn(location: Location, amount: Int) {
|
||||||
|
val world = location.world ?: return
|
||||||
|
|
||||||
|
world.spawnParticle(Particle.REDSTONE, location, amount, 0.0, 0.0, 0.0, 0.0, options)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.willfp.eco.internal.price
|
||||||
|
|
||||||
|
import com.willfp.eco.core.math.MathContext
|
||||||
|
import com.willfp.eco.core.price.Price
|
||||||
|
import com.willfp.eco.core.price.PriceFactory
|
||||||
|
import com.willfp.eco.core.price.impl.PriceEconomy
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
object PriceFactoryEconomy : PriceFactory {
|
||||||
|
override fun getNames() = listOf(
|
||||||
|
"coins",
|
||||||
|
"$"
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||||
|
return PriceEconomy(baseContext, function)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.willfp.eco.internal.price
|
||||||
|
|
||||||
|
import com.willfp.eco.core.math.MathContext
|
||||||
|
import com.willfp.eco.core.price.Price
|
||||||
|
import com.willfp.eco.core.price.PriceFactory
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.function.Function
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
object PriceFactoryXP : PriceFactory {
|
||||||
|
override fun getNames() = listOf(
|
||||||
|
"xp",
|
||||||
|
"exp",
|
||||||
|
"experience"
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||||
|
return PriceXP(baseContext) { function.apply(it).roundToInt() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PriceXP(
|
||||||
|
private val baseContext: MathContext,
|
||||||
|
private val xp: (MathContext) -> Int
|
||||||
|
) : Price {
|
||||||
|
private val multipliers = mutableMapOf<UUID, Double>()
|
||||||
|
|
||||||
|
override fun canAfford(player: Player) = player.totalExperience >= getValue(player)
|
||||||
|
|
||||||
|
override fun pay(player: Player) {
|
||||||
|
player.totalExperience -= getValue(player).roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun giveTo(player: Player) {
|
||||||
|
player.totalExperience += getValue(player).roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getValue(player: Player): Double {
|
||||||
|
return xp(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getMultiplier(player: Player): Double {
|
||||||
|
return multipliers[player.uniqueId] ?: 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setMultiplier(player: Player, multiplier: Double) {
|
||||||
|
multipliers[player.uniqueId] = multiplier.roundToInt().toDouble()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.willfp.eco.internal.price
|
||||||
|
|
||||||
|
import com.willfp.eco.core.math.MathContext
|
||||||
|
import com.willfp.eco.core.price.Price
|
||||||
|
import com.willfp.eco.core.price.PriceFactory
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.function.Function
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
object PriceFactoryXPLevels : PriceFactory {
|
||||||
|
override fun getNames() = listOf(
|
||||||
|
"l",
|
||||||
|
"levels",
|
||||||
|
"xplevels",
|
||||||
|
"explevels",
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||||
|
return PriceXPLevel(baseContext) { function.apply(it).roundToInt() }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PriceXPLevel(
|
||||||
|
private val baseContext: MathContext,
|
||||||
|
private val level: (MathContext) -> Int
|
||||||
|
) : Price {
|
||||||
|
private val multipliers = mutableMapOf<UUID, Double>()
|
||||||
|
|
||||||
|
override fun canAfford(player: Player) = player.level >= getValue(player)
|
||||||
|
|
||||||
|
override fun pay(player: Player) {
|
||||||
|
player.level -= getValue(player).roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun giveTo(player: Player) {
|
||||||
|
player.level += getValue(player).roundToInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getValue(player: Player): Double {
|
||||||
|
return level(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getMultiplier(player: Player): Double {
|
||||||
|
return multipliers[player.uniqueId] ?: 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setMultiplier(player: Player, multiplier: Double) {
|
||||||
|
multipliers[player.uniqueId] = multiplier.roundToInt().toDouble()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,7 +29,27 @@ var SkullMeta.texture: String?
|
|||||||
setProfile.isAccessible = true
|
setProfile.isAccessible = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base64 == null) {
|
/* This length check below was lost in the conversion. For some reason the base64
|
||||||
|
* string is length 8 when this is called pretty frequently, causing an
|
||||||
|
* out of bounds exception.
|
||||||
|
*
|
||||||
|
* Could not pass event EntityPotionEffectEvent to Talismans v5.116.0
|
||||||
|
* java.lang.StringIndexOutOfBoundsException: begin -12, end 8, length 8
|
||||||
|
* at java.lang.String.checkBoundsBeginEnd(String.java:4604) ~[?:?]
|
||||||
|
* at java.lang.String.substring(String.java:2707) ~[?:?]
|
||||||
|
* at java.lang.String.substring(String.java:2680) ~[?:?]
|
||||||
|
* at com.willfp.eco.internal.spigot.proxy.v1_19_R1.common.SkullKt.setTexture(Skull.kt:36)
|
||||||
|
*
|
||||||
|
if (base64.length < 20) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
*
|
||||||
|
* ^ Update to this comment: a length 8 string ("textures") was being sent
|
||||||
|
* because the get() method wasn't working right. This has been fixed, but the
|
||||||
|
* check needs to remain implemented.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (base64 == null || base64.length < 20) {
|
||||||
setProfile.invoke(this, null)
|
setProfile.invoke(this, null)
|
||||||
} else {
|
} else {
|
||||||
val uuid = UUID(
|
val uuid = UUID(
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||||
|
|
||||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalLeapAtTarget
|
import com.willfp.eco.core.entities.ai.entity.EntityGoalIllusionerBlindnessSpell
|
||||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||||
import com.willfp.eco.internal.spigot.proxy.common.ai.opengoals.IllusionerBlindnessSpellGoal
|
|
||||||
import net.minecraft.world.entity.PathfinderMob
|
import net.minecraft.world.entity.PathfinderMob
|
||||||
import net.minecraft.world.entity.ai.goal.Goal
|
import net.minecraft.world.entity.ai.goal.Goal
|
||||||
import net.minecraft.world.entity.monster.Illusioner
|
import net.minecraft.world.entity.monster.Illusioner
|
||||||
|
|
||||||
object IllusionerBlindnessSpellGoalFactory : EntityGoalFactory<EntityGoalLeapAtTarget> {
|
object IllusionerBlindnessSpellGoalFactory : EntityGoalFactory<EntityGoalIllusionerBlindnessSpell> {
|
||||||
override fun create(apiGoal: EntityGoalLeapAtTarget, entity: PathfinderMob): Goal? {
|
override fun create(apiGoal: EntityGoalIllusionerBlindnessSpell, entity: PathfinderMob): Goal? {
|
||||||
if (entity !is Illusioner) return null
|
if (entity !is Illusioner) return null
|
||||||
|
|
||||||
return IllusionerBlindnessSpellGoal(
|
// Have to use reflection for it to work
|
||||||
entity
|
return Illusioner::class.java.declaredClasses[1]
|
||||||
)
|
.getDeclaredConstructor(Illusioner::class.java)
|
||||||
|
.apply { isAccessible = true }
|
||||||
|
.newInstance(entity) as Goal
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isGoalOfType(goal: Goal) = goal is IllusionerBlindnessSpellGoal
|
override fun isGoalOfType(goal: Goal): Boolean {
|
||||||
|| goal::class.java.name.contains("IllusionerBlindnessSpellGoal")
|
return Illusioner::class.java.declaredClasses[1].isInstance(goal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,23 @@
|
|||||||
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
package com.willfp.eco.internal.spigot.proxy.common.ai.entity
|
||||||
|
|
||||||
import com.willfp.eco.core.entities.ai.entity.EntityGoalLeapAtTarget
|
import com.willfp.eco.core.entities.ai.entity.EntityGoalIllusionerMirrorSpell
|
||||||
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
import com.willfp.eco.internal.spigot.proxy.common.ai.EntityGoalFactory
|
||||||
import com.willfp.eco.internal.spigot.proxy.common.ai.opengoals.IllusionerMirrorSpellGoal
|
|
||||||
import net.minecraft.world.entity.PathfinderMob
|
import net.minecraft.world.entity.PathfinderMob
|
||||||
import net.minecraft.world.entity.ai.goal.Goal
|
import net.minecraft.world.entity.ai.goal.Goal
|
||||||
import net.minecraft.world.entity.monster.Illusioner
|
import net.minecraft.world.entity.monster.Illusioner
|
||||||
|
|
||||||
object IllusionerMirrorSpellGoalFactory : EntityGoalFactory<EntityGoalLeapAtTarget> {
|
object IllusionerMirrorSpellGoalFactory : EntityGoalFactory<EntityGoalIllusionerMirrorSpell> {
|
||||||
override fun create(apiGoal: EntityGoalLeapAtTarget, entity: PathfinderMob): Goal? {
|
override fun create(apiGoal: EntityGoalIllusionerMirrorSpell, entity: PathfinderMob): Goal? {
|
||||||
if (entity !is Illusioner) return null
|
if (entity !is Illusioner) return null
|
||||||
|
|
||||||
return IllusionerMirrorSpellGoal(
|
// Have to use reflection for it to work
|
||||||
entity
|
return Illusioner::class.java.declaredClasses[0]
|
||||||
)
|
.getDeclaredConstructor(Illusioner::class.java)
|
||||||
|
.apply { isAccessible = true }
|
||||||
|
.newInstance(entity) as Goal
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isGoalOfType(goal: Goal) = goal is IllusionerMirrorSpellGoal
|
override fun isGoalOfType(goal: Goal): Boolean {
|
||||||
|| goal::class.java.name.contains("IllusionerMirrorSpellGoal")
|
return Illusioner::class.java.declaredClasses[0].isInstance(goal)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
package com.willfp.eco.internal.spigot.proxy.common.ai.opengoals
|
|
||||||
|
|
||||||
import net.minecraft.sounds.SoundEvent
|
|
||||||
import net.minecraft.sounds.SoundEvents
|
|
||||||
import net.minecraft.world.Difficulty
|
|
||||||
import net.minecraft.world.effect.MobEffectInstance
|
|
||||||
import net.minecraft.world.effect.MobEffects
|
|
||||||
import net.minecraft.world.entity.monster.Illusioner
|
|
||||||
import net.minecraft.world.entity.monster.SpellcasterIllager
|
|
||||||
import org.bukkit.event.entity.EntityPotionEffectEvent
|
|
||||||
|
|
||||||
class IllusionerBlindnessSpellGoal(
|
|
||||||
private val illusioner: Illusioner
|
|
||||||
) : OpenUseSpellGoal(illusioner) {
|
|
||||||
override val castingInterval = 180
|
|
||||||
override val castingTime = 20
|
|
||||||
override val spellPrepareSound: SoundEvent = SoundEvents.ILLUSIONER_PREPARE_BLINDNESS
|
|
||||||
override val spell: SpellcasterIllager.IllagerSpell = SpellcasterIllager.IllagerSpell.BLINDNESS
|
|
||||||
|
|
||||||
private var lastTargetId = 0
|
|
||||||
|
|
||||||
override fun canUse(): Boolean {
|
|
||||||
return if (super.canUse()) {
|
|
||||||
false
|
|
||||||
} else if (illusioner.target == null) {
|
|
||||||
false
|
|
||||||
} else if (illusioner.target!!.id == lastTargetId) {
|
|
||||||
false
|
|
||||||
} else {
|
|
||||||
illusioner.level.getCurrentDifficultyAt(illusioner.blockPosition()).isHarderThan(
|
|
||||||
Difficulty.NORMAL.ordinal.toFloat()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun start() {
|
|
||||||
super.start()
|
|
||||||
if (illusioner.target != null) {
|
|
||||||
lastTargetId = illusioner.target!!.id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun performSpellCasting() {
|
|
||||||
illusioner.target?.addEffect(
|
|
||||||
MobEffectInstance(MobEffects.BLINDNESS, 400),
|
|
||||||
illusioner,
|
|
||||||
EntityPotionEffectEvent.Cause.ATTACK
|
|
||||||
) // CraftBukkit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.willfp.eco.internal.spigot.proxy.common.ai.opengoals
|
|
||||||
|
|
||||||
import net.minecraft.sounds.SoundEvent
|
|
||||||
import net.minecraft.sounds.SoundEvents
|
|
||||||
import net.minecraft.world.effect.MobEffectInstance
|
|
||||||
import net.minecraft.world.effect.MobEffects
|
|
||||||
import net.minecraft.world.entity.monster.Illusioner
|
|
||||||
import net.minecraft.world.entity.monster.SpellcasterIllager
|
|
||||||
import org.bukkit.event.entity.EntityPotionEffectEvent
|
|
||||||
|
|
||||||
class IllusionerMirrorSpellGoal(
|
|
||||||
private val illusioner: Illusioner
|
|
||||||
) : OpenUseSpellGoal(illusioner) {
|
|
||||||
override val castingInterval = 340
|
|
||||||
override val castingTime = 20
|
|
||||||
override val spellPrepareSound: SoundEvent = SoundEvents.ILLUSIONER_PREPARE_MIRROR
|
|
||||||
override val spell: SpellcasterIllager.IllagerSpell = SpellcasterIllager.IllagerSpell.DISAPPEAR
|
|
||||||
|
|
||||||
override fun canUse(): Boolean {
|
|
||||||
return if (!super.canUse()) false else !illusioner.hasEffect(MobEffects.INVISIBILITY)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun performSpellCasting() {
|
|
||||||
illusioner.addEffect(
|
|
||||||
MobEffectInstance(MobEffects.INVISIBILITY, 1200),
|
|
||||||
EntityPotionEffectEvent.Cause.ILLUSION
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
package com.willfp.eco.internal.spigot.proxy.common.ai.opengoals
|
|
||||||
|
|
||||||
import net.minecraft.sounds.SoundEvent
|
|
||||||
import net.minecraft.world.entity.EntityType
|
|
||||||
import net.minecraft.world.entity.LivingEntity
|
|
||||||
import net.minecraft.world.entity.ai.goal.Goal
|
|
||||||
import net.minecraft.world.entity.monster.SpellcasterIllager
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
class DelegatedSpellcaster(private val handle: SpellcasterIllager) : SpellcasterIllager(
|
|
||||||
handle.type as EntityType<out SpellcasterIllager>,
|
|
||||||
handle.level
|
|
||||||
) {
|
|
||||||
var openSpellCastingTickCount
|
|
||||||
get() = this.spellCastingTickCount
|
|
||||||
set(value) {
|
|
||||||
this.spellCastingTickCount = value
|
|
||||||
}
|
|
||||||
|
|
||||||
val openCastingSoundEvent = this.castingSoundEvent
|
|
||||||
|
|
||||||
override fun applyRaidBuffs(wave: Int, unused: Boolean) {
|
|
||||||
handle.applyRaidBuffs(wave, unused)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getCelebrateSound(): SoundEvent {
|
|
||||||
return handle.celebrateSound
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getCastingSoundEvent(): SoundEvent {
|
|
||||||
return this.openCastingSoundEvent
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS")
|
|
||||||
abstract class OpenUseSpellGoal(
|
|
||||||
private val handle: SpellcasterIllager
|
|
||||||
) : Goal() {
|
|
||||||
private var attackWarmupDelay = 0
|
|
||||||
private var nextAttackTickCount = 0
|
|
||||||
|
|
||||||
private val openHandle = DelegatedSpellcaster(handle)
|
|
||||||
|
|
||||||
override fun canUse(): Boolean {
|
|
||||||
val entityliving: LivingEntity = handle.target ?: return false
|
|
||||||
return if (entityliving.isAlive) if (handle.isCastingSpell) false else handle.tickCount >= nextAttackTickCount else false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun canContinueToUse(): Boolean {
|
|
||||||
val entityliving: LivingEntity = handle.target ?: return false
|
|
||||||
return entityliving.isAlive && attackWarmupDelay > 0
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun start() {
|
|
||||||
attackWarmupDelay = castWarmupTime
|
|
||||||
openHandle.openSpellCastingTickCount = castingTime
|
|
||||||
nextAttackTickCount = handle.tickCount + castingInterval
|
|
||||||
val soundeffect = spellPrepareSound
|
|
||||||
if (soundeffect != null) {
|
|
||||||
handle.playSound(soundeffect, 1.0f, 1.0f)
|
|
||||||
}
|
|
||||||
handle.setIsCastingSpell(spell)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun tick() {
|
|
||||||
--attackWarmupDelay
|
|
||||||
if (attackWarmupDelay == 0) {
|
|
||||||
performSpellCasting()
|
|
||||||
handle.playSound(openHandle.openCastingSoundEvent, 1.0f, 1.0f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun performSpellCasting()
|
|
||||||
protected abstract val castingTime: Int
|
|
||||||
protected abstract val castingInterval: Int
|
|
||||||
protected abstract val spellPrepareSound: SoundEvent?
|
|
||||||
protected abstract val spell: SpellcasterIllager.IllagerSpell?
|
|
||||||
protected open val castWarmupTime: Int = 60
|
|
||||||
}
|
|
||||||
@@ -3,16 +3,28 @@ package com.willfp.eco.internal.spigot.proxy.v1_17_R1
|
|||||||
import com.willfp.eco.core.data.ExtendedPersistentDataContainer
|
import com.willfp.eco.core.data.ExtendedPersistentDataContainer
|
||||||
import com.willfp.eco.internal.spigot.proxy.ExtendedPersistentDataContainerFactoryProxy
|
import com.willfp.eco.internal.spigot.proxy.ExtendedPersistentDataContainerFactoryProxy
|
||||||
import net.minecraft.nbt.Tag
|
import net.minecraft.nbt.Tag
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.craftbukkit.v1_17_R1.inventory.CraftItemStack
|
||||||
import org.bukkit.craftbukkit.v1_17_R1.persistence.CraftPersistentDataContainer
|
import org.bukkit.craftbukkit.v1_17_R1.persistence.CraftPersistentDataContainer
|
||||||
import org.bukkit.craftbukkit.v1_17_R1.persistence.CraftPersistentDataTypeRegistry
|
import org.bukkit.craftbukkit.v1_17_R1.persistence.CraftPersistentDataTypeRegistry
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
import org.bukkit.persistence.PersistentDataContainer
|
import org.bukkit.persistence.PersistentDataContainer
|
||||||
import org.bukkit.persistence.PersistentDataType
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
|
||||||
class ExtendedPersistentDataContainerFactory: ExtendedPersistentDataContainerFactoryProxy {
|
class ExtendedPersistentDataContainerFactory : ExtendedPersistentDataContainerFactoryProxy {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private val registry: CraftPersistentDataTypeRegistry =
|
private val registry: CraftPersistentDataTypeRegistry
|
||||||
CraftPersistentDataContainer::class.java.getDeclaredField("registry")
|
|
||||||
.apply { isAccessible = true }.get(null) as CraftPersistentDataTypeRegistry
|
init {
|
||||||
|
/*
|
||||||
|
Can't grab actual instance since it's in CraftMetaItem (which is package-private)
|
||||||
|
And getting it would mean more janky reflection
|
||||||
|
*/
|
||||||
|
val item = CraftItemStack.asCraftCopy(ItemStack(Material.STONE))
|
||||||
|
val pdc = item.itemMeta!!.persistentDataContainer
|
||||||
|
this.registry = CraftPersistentDataContainer::class.java.getDeclaredField("registry")
|
||||||
|
.apply { isAccessible = true }.get(pdc) as CraftPersistentDataTypeRegistry
|
||||||
|
}
|
||||||
|
|
||||||
override fun adapt(pdc: PersistentDataContainer): ExtendedPersistentDataContainer {
|
override fun adapt(pdc: PersistentDataContainer): ExtendedPersistentDataContainer {
|
||||||
return when (pdc) {
|
return when (pdc) {
|
||||||
@@ -34,7 +46,8 @@ class ExtendedPersistentDataContainerFactory: ExtendedPersistentDataContainerFac
|
|||||||
.apply { isAccessible = true }.get(handle) as MutableMap<String, Tag>
|
.apply { isAccessible = true }.get(handle) as MutableMap<String, Tag>
|
||||||
|
|
||||||
override fun <T : Any, Z : Any> set(key: String, dataType: PersistentDataType<T, Z>, value: Z) {
|
override fun <T : Any, Z : Any> set(key: String, dataType: PersistentDataType<T, Z>, value: Z) {
|
||||||
customDataTags[key] = registry.wrap(dataType.primitiveType, dataType.toPrimitive(value, handle.adapterContext))
|
customDataTags[key] =
|
||||||
|
registry.wrap(dataType.primitiveType, dataType.toPrimitive(value, handle.adapterContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any, Z : Any> has(key: String, dataType: PersistentDataType<T, Z>): Boolean {
|
override fun <T : Any, Z : Any> has(key: String, dataType: PersistentDataType<T, Z>): Boolean {
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_17_R1
|
||||||
|
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.SyncCommandsProxy
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.craftbukkit.v1_17_R1.CraftServer
|
||||||
|
|
||||||
|
class SyncCommands : SyncCommandsProxy {
|
||||||
|
override fun syncCommands() {
|
||||||
|
(Bukkit.getServer() as CraftServer).syncCommands()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,16 +3,28 @@ package com.willfp.eco.internal.spigot.proxy.v1_18_R1
|
|||||||
import com.willfp.eco.core.data.ExtendedPersistentDataContainer
|
import com.willfp.eco.core.data.ExtendedPersistentDataContainer
|
||||||
import com.willfp.eco.internal.spigot.proxy.ExtendedPersistentDataContainerFactoryProxy
|
import com.willfp.eco.internal.spigot.proxy.ExtendedPersistentDataContainerFactoryProxy
|
||||||
import net.minecraft.nbt.Tag
|
import net.minecraft.nbt.Tag
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack
|
||||||
import org.bukkit.craftbukkit.v1_18_R1.persistence.CraftPersistentDataContainer
|
import org.bukkit.craftbukkit.v1_18_R1.persistence.CraftPersistentDataContainer
|
||||||
import org.bukkit.craftbukkit.v1_18_R1.persistence.CraftPersistentDataTypeRegistry
|
import org.bukkit.craftbukkit.v1_18_R1.persistence.CraftPersistentDataTypeRegistry
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
import org.bukkit.persistence.PersistentDataContainer
|
import org.bukkit.persistence.PersistentDataContainer
|
||||||
import org.bukkit.persistence.PersistentDataType
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
|
||||||
class ExtendedPersistentDataContainerFactory : ExtendedPersistentDataContainerFactoryProxy {
|
class ExtendedPersistentDataContainerFactory : ExtendedPersistentDataContainerFactoryProxy {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private val registry: CraftPersistentDataTypeRegistry =
|
private val registry: CraftPersistentDataTypeRegistry
|
||||||
CraftPersistentDataContainer::class.java.getDeclaredField("registry")
|
|
||||||
.apply { isAccessible = true }.get(null) as CraftPersistentDataTypeRegistry
|
init {
|
||||||
|
/*
|
||||||
|
Can't grab actual instance since it's in CraftMetaItem (which is package-private)
|
||||||
|
And getting it would mean more janky reflection
|
||||||
|
*/
|
||||||
|
val item = CraftItemStack.asCraftCopy(ItemStack(Material.STONE))
|
||||||
|
val pdc = item.itemMeta!!.persistentDataContainer
|
||||||
|
this.registry = CraftPersistentDataContainer::class.java.getDeclaredField("registry")
|
||||||
|
.apply { isAccessible = true }.get(pdc) as CraftPersistentDataTypeRegistry
|
||||||
|
}
|
||||||
|
|
||||||
override fun adapt(pdc: PersistentDataContainer): ExtendedPersistentDataContainer {
|
override fun adapt(pdc: PersistentDataContainer): ExtendedPersistentDataContainer {
|
||||||
return when (pdc) {
|
return when (pdc) {
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
|
||||||
|
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.SyncCommandsProxy
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.craftbukkit.v1_18_R1.CraftServer
|
||||||
|
|
||||||
|
class SyncCommands : SyncCommandsProxy {
|
||||||
|
override fun syncCommands() {
|
||||||
|
(Bukkit.getServer() as CraftServer).syncCommands()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,16 +3,28 @@ package com.willfp.eco.internal.spigot.proxy.v1_18_R2
|
|||||||
import com.willfp.eco.core.data.ExtendedPersistentDataContainer
|
import com.willfp.eco.core.data.ExtendedPersistentDataContainer
|
||||||
import com.willfp.eco.internal.spigot.proxy.ExtendedPersistentDataContainerFactoryProxy
|
import com.willfp.eco.internal.spigot.proxy.ExtendedPersistentDataContainerFactoryProxy
|
||||||
import net.minecraft.nbt.Tag
|
import net.minecraft.nbt.Tag
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.craftbukkit.v1_18_R2.inventory.CraftItemStack
|
||||||
import org.bukkit.craftbukkit.v1_18_R2.persistence.CraftPersistentDataContainer
|
import org.bukkit.craftbukkit.v1_18_R2.persistence.CraftPersistentDataContainer
|
||||||
import org.bukkit.craftbukkit.v1_18_R2.persistence.CraftPersistentDataTypeRegistry
|
import org.bukkit.craftbukkit.v1_18_R2.persistence.CraftPersistentDataTypeRegistry
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
import org.bukkit.persistence.PersistentDataContainer
|
import org.bukkit.persistence.PersistentDataContainer
|
||||||
import org.bukkit.persistence.PersistentDataType
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
|
||||||
class ExtendedPersistentDataContainerFactory: ExtendedPersistentDataContainerFactoryProxy {
|
class ExtendedPersistentDataContainerFactory : ExtendedPersistentDataContainerFactoryProxy {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private val registry: CraftPersistentDataTypeRegistry =
|
private val registry: CraftPersistentDataTypeRegistry
|
||||||
CraftPersistentDataContainer::class.java.getDeclaredField("registry")
|
|
||||||
.apply { isAccessible = true }.get(null) as CraftPersistentDataTypeRegistry
|
init {
|
||||||
|
/*
|
||||||
|
Can't grab actual instance since it's in CraftMetaItem (which is package-private)
|
||||||
|
And getting it would mean more janky reflection
|
||||||
|
*/
|
||||||
|
val item = CraftItemStack.asCraftCopy(ItemStack(Material.STONE))
|
||||||
|
val pdc = item.itemMeta!!.persistentDataContainer
|
||||||
|
this.registry = CraftPersistentDataContainer::class.java.getDeclaredField("registry")
|
||||||
|
.apply { isAccessible = true }.get(pdc) as CraftPersistentDataTypeRegistry
|
||||||
|
}
|
||||||
|
|
||||||
override fun adapt(pdc: PersistentDataContainer): ExtendedPersistentDataContainer {
|
override fun adapt(pdc: PersistentDataContainer): ExtendedPersistentDataContainer {
|
||||||
return when (pdc) {
|
return when (pdc) {
|
||||||
@@ -34,7 +46,8 @@ class ExtendedPersistentDataContainerFactory: ExtendedPersistentDataContainerFac
|
|||||||
.apply { isAccessible = true }.get(handle) as MutableMap<String, Tag>
|
.apply { isAccessible = true }.get(handle) as MutableMap<String, Tag>
|
||||||
|
|
||||||
override fun <T : Any, Z : Any> set(key: String, dataType: PersistentDataType<T, Z>, value: Z) {
|
override fun <T : Any, Z : Any> set(key: String, dataType: PersistentDataType<T, Z>, value: Z) {
|
||||||
customDataTags[key] = registry.wrap(dataType.primitiveType, dataType.toPrimitive(value, handle.adapterContext))
|
customDataTags[key] =
|
||||||
|
registry.wrap(dataType.primitiveType, dataType.toPrimitive(value, handle.adapterContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any, Z : Any> has(key: String, dataType: PersistentDataType<T, Z>): Boolean {
|
override fun <T : Any, Z : Any> has(key: String, dataType: PersistentDataType<T, Z>): Boolean {
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_18_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.SyncCommandsProxy
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.craftbukkit.v1_18_R2.CraftServer
|
||||||
|
|
||||||
|
class SyncCommands : SyncCommandsProxy {
|
||||||
|
override fun syncCommands() {
|
||||||
|
(Bukkit.getServer() as CraftServer).syncCommands()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,21 +3,33 @@ package com.willfp.eco.internal.spigot.proxy.v1_19_R1
|
|||||||
import com.willfp.eco.core.data.ExtendedPersistentDataContainer
|
import com.willfp.eco.core.data.ExtendedPersistentDataContainer
|
||||||
import com.willfp.eco.internal.spigot.proxy.ExtendedPersistentDataContainerFactoryProxy
|
import com.willfp.eco.internal.spigot.proxy.ExtendedPersistentDataContainerFactoryProxy
|
||||||
import net.minecraft.nbt.Tag
|
import net.minecraft.nbt.Tag
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack
|
||||||
import org.bukkit.craftbukkit.v1_19_R1.persistence.CraftPersistentDataContainer
|
import org.bukkit.craftbukkit.v1_19_R1.persistence.CraftPersistentDataContainer
|
||||||
import org.bukkit.craftbukkit.v1_19_R1.persistence.CraftPersistentDataTypeRegistry
|
import org.bukkit.craftbukkit.v1_19_R1.persistence.CraftPersistentDataTypeRegistry
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
import org.bukkit.persistence.PersistentDataContainer
|
import org.bukkit.persistence.PersistentDataContainer
|
||||||
import org.bukkit.persistence.PersistentDataType
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
|
||||||
class ExtendedPersistentDataContainerFactory: ExtendedPersistentDataContainerFactoryProxy {
|
class ExtendedPersistentDataContainerFactory : ExtendedPersistentDataContainerFactoryProxy {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private val registry: CraftPersistentDataTypeRegistry =
|
private val registry: CraftPersistentDataTypeRegistry
|
||||||
CraftPersistentDataContainer::class.java.getDeclaredField("registry")
|
|
||||||
.apply { isAccessible = true }.get(null) as CraftPersistentDataTypeRegistry
|
init {
|
||||||
|
/*
|
||||||
|
Can't grab actual instance since it's in CraftMetaItem (which is package-private)
|
||||||
|
And getting it would mean more janky reflection
|
||||||
|
*/
|
||||||
|
val item = CraftItemStack.asCraftCopy(ItemStack(Material.STONE))
|
||||||
|
val pdc = item.itemMeta!!.persistentDataContainer
|
||||||
|
this.registry = CraftPersistentDataContainer::class.java.getDeclaredField("registry")
|
||||||
|
.apply { isAccessible = true }.get(pdc) as CraftPersistentDataTypeRegistry
|
||||||
|
}
|
||||||
|
|
||||||
override fun adapt(pdc: PersistentDataContainer): ExtendedPersistentDataContainer {
|
override fun adapt(pdc: PersistentDataContainer): ExtendedPersistentDataContainer {
|
||||||
return when (pdc) {
|
return when (pdc) {
|
||||||
is CraftPersistentDataContainer -> EcoPersistentDataContainer(pdc)
|
is CraftPersistentDataContainer -> EcoPersistentDataContainer(pdc)
|
||||||
else -> throw IllegalArgumentException("Custom PDC instance is not supported!")
|
else -> throw IllegalArgumentException("Custom PDC instance ims not supported!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,7 +46,8 @@ class ExtendedPersistentDataContainerFactory: ExtendedPersistentDataContainerFac
|
|||||||
.apply { isAccessible = true }.get(handle) as MutableMap<String, Tag>
|
.apply { isAccessible = true }.get(handle) as MutableMap<String, Tag>
|
||||||
|
|
||||||
override fun <T : Any, Z : Any> set(key: String, dataType: PersistentDataType<T, Z>, value: Z) {
|
override fun <T : Any, Z : Any> set(key: String, dataType: PersistentDataType<T, Z>, value: Z) {
|
||||||
customDataTags[key] = registry.wrap(dataType.primitiveType, dataType.toPrimitive(value, handle.adapterContext))
|
customDataTags[key] =
|
||||||
|
registry.wrap(dataType.primitiveType, dataType.toPrimitive(value, handle.adapterContext))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun <T : Any, Z : Any> has(key: String, dataType: PersistentDataType<T, Z>): Boolean {
|
override fun <T : Any, Z : Any> has(key: String, dataType: PersistentDataType<T, Z>): Boolean {
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R1
|
||||||
|
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.SyncCommandsProxy
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R1.CraftServer
|
||||||
|
|
||||||
|
class SyncCommands : SyncCommandsProxy {
|
||||||
|
override fun syncCommands() {
|
||||||
|
(Bukkit.getServer() as CraftServer).syncCommands()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,6 @@ import com.willfp.eco.core.Eco
|
|||||||
import com.willfp.eco.core.EcoPlugin
|
import com.willfp.eco.core.EcoPlugin
|
||||||
import com.willfp.eco.core.PluginLike
|
import com.willfp.eco.core.PluginLike
|
||||||
import com.willfp.eco.core.PluginProps
|
import com.willfp.eco.core.PluginProps
|
||||||
import com.willfp.eco.core.Prerequisite
|
|
||||||
import com.willfp.eco.core.config.ConfigType
|
import com.willfp.eco.core.config.ConfigType
|
||||||
import com.willfp.eco.core.config.interfaces.Config
|
import com.willfp.eco.core.config.interfaces.Config
|
||||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||||
@@ -12,8 +11,7 @@ import com.willfp.eco.core.gui.menu.Menu
|
|||||||
import com.willfp.eco.core.gui.menu.MenuType
|
import com.willfp.eco.core.gui.menu.MenuType
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
||||||
import com.willfp.eco.core.items.Items
|
import com.willfp.eco.core.items.Items
|
||||||
import com.willfp.eco.core.placeholder.AdditionalPlayer
|
import com.willfp.eco.core.math.MathContext
|
||||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable
|
|
||||||
import com.willfp.eco.internal.EcoPropsParser
|
import com.willfp.eco.internal.EcoPropsParser
|
||||||
import com.willfp.eco.internal.config.EcoConfigHandler
|
import com.willfp.eco.internal.config.EcoConfigHandler
|
||||||
import com.willfp.eco.internal.config.EcoConfigSection
|
import com.willfp.eco.internal.config.EcoConfigSection
|
||||||
@@ -34,13 +32,13 @@ import com.willfp.eco.internal.gui.MergedStateMenu
|
|||||||
import com.willfp.eco.internal.gui.menu.EcoMenuBuilder
|
import com.willfp.eco.internal.gui.menu.EcoMenuBuilder
|
||||||
import com.willfp.eco.internal.gui.menu.renderedInventory
|
import com.willfp.eco.internal.gui.menu.renderedInventory
|
||||||
import com.willfp.eco.internal.gui.slot.EcoSlotBuilder
|
import com.willfp.eco.internal.gui.slot.EcoSlotBuilder
|
||||||
import com.willfp.eco.internal.integrations.PlaceholderIntegrationPAPI
|
import com.willfp.eco.internal.integrations.PAPIExpansion
|
||||||
import com.willfp.eco.internal.logging.EcoLogger
|
import com.willfp.eco.internal.logging.EcoLogger
|
||||||
import com.willfp.eco.internal.proxy.EcoProxyFactory
|
import com.willfp.eco.internal.proxy.EcoProxyFactory
|
||||||
import com.willfp.eco.internal.scheduling.EcoScheduler
|
import com.willfp.eco.internal.scheduling.EcoScheduler
|
||||||
import com.willfp.eco.internal.spigot.data.DataYml
|
import com.willfp.eco.internal.spigot.data.DataYml
|
||||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
|
||||||
import com.willfp.eco.internal.spigot.data.KeyRegistry
|
import com.willfp.eco.internal.spigot.data.KeyRegistry
|
||||||
|
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
||||||
import com.willfp.eco.internal.spigot.data.storage.HandlerType
|
import com.willfp.eco.internal.spigot.data.storage.HandlerType
|
||||||
import com.willfp.eco.internal.spigot.integrations.bstats.MetricHandler
|
import com.willfp.eco.internal.spigot.integrations.bstats.MetricHandler
|
||||||
import com.willfp.eco.internal.spigot.math.evaluateExpression
|
import com.willfp.eco.internal.spigot.math.evaluateExpression
|
||||||
@@ -52,8 +50,8 @@ import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
|
|||||||
import com.willfp.eco.internal.spigot.proxy.MiniMessageTranslatorProxy
|
import com.willfp.eco.internal.spigot.proxy.MiniMessageTranslatorProxy
|
||||||
import com.willfp.eco.internal.spigot.proxy.SNBTConverterProxy
|
import com.willfp.eco.internal.spigot.proxy.SNBTConverterProxy
|
||||||
import com.willfp.eco.internal.spigot.proxy.SkullProxy
|
import com.willfp.eco.internal.spigot.proxy.SkullProxy
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.SyncCommandsProxy
|
||||||
import com.willfp.eco.internal.spigot.proxy.TPSProxy
|
import com.willfp.eco.internal.spigot.proxy.TPSProxy
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences
|
|
||||||
import org.bukkit.Location
|
import org.bukkit.Location
|
||||||
import org.bukkit.NamespacedKey
|
import org.bukkit.NamespacedKey
|
||||||
import org.bukkit.configuration.ConfigurationSection
|
import org.bukkit.configuration.ConfigurationSection
|
||||||
@@ -72,7 +70,7 @@ private val loadedEcoPlugins = mutableMapOf<String, EcoPlugin>()
|
|||||||
class EcoImpl : EcoSpigotPlugin(), Eco {
|
class EcoImpl : EcoSpigotPlugin(), Eco {
|
||||||
override val dataYml = DataYml(this)
|
override val dataYml = DataYml(this)
|
||||||
|
|
||||||
override val profileHandler = EcoProfileHandler(
|
override val profileHandler = ProfileHandler(
|
||||||
HandlerType.valueOf(this.configYml.getString("data-handler").uppercase()),
|
HandlerType.valueOf(this.configYml.getString("data-handler").uppercase()),
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
@@ -81,10 +79,6 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
|||||||
getProxy(CommonsInitializerProxy::class.java).init()
|
getProxy(CommonsInitializerProxy::class.java).init()
|
||||||
}
|
}
|
||||||
|
|
||||||
private var adventure: BukkitAudiences? = if (!Prerequisite.HAS_PAPER.isMet) {
|
|
||||||
BukkitAudiences.create(this)
|
|
||||||
} else null
|
|
||||||
|
|
||||||
@Suppress("RedundantNullableReturnType")
|
@Suppress("RedundantNullableReturnType")
|
||||||
private val keyFactory: InternalNamespacedKeyFactory? =
|
private val keyFactory: InternalNamespacedKeyFactory? =
|
||||||
if (this.configYml.getBool("use-safer-namespacedkey-creation"))
|
if (this.configYml.getBool("use-safer-namespacedkey-creation"))
|
||||||
@@ -114,8 +108,9 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
|||||||
override fun createLogger(plugin: EcoPlugin) =
|
override fun createLogger(plugin: EcoPlugin) =
|
||||||
EcoLogger(plugin)
|
EcoLogger(plugin)
|
||||||
|
|
||||||
override fun createPAPIIntegration(plugin: EcoPlugin) =
|
override fun createPAPIIntegration(plugin: EcoPlugin) {
|
||||||
PlaceholderIntegrationPAPI(plugin)
|
PAPIExpansion(plugin)
|
||||||
|
}
|
||||||
|
|
||||||
override fun getEcoPlugin(): EcoPlugin =
|
override fun getEcoPlugin(): EcoPlugin =
|
||||||
this
|
this
|
||||||
@@ -174,9 +169,6 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
|||||||
override fun createDropQueue(player: Player) = if (this.configYml.getBool("use-fast-collated-drops"))
|
override fun createDropQueue(player: Player) = if (this.configYml.getBool("use-fast-collated-drops"))
|
||||||
EcoFastCollatedDropQueue(player) else EcoDropQueue(player)
|
EcoFastCollatedDropQueue(player) else EcoDropQueue(player)
|
||||||
|
|
||||||
override fun getPersistentDataKeyFrom(namespacedKey: NamespacedKey) =
|
|
||||||
KeyRegistry.getKeyFrom(namespacedKey)
|
|
||||||
|
|
||||||
override fun getRegisteredPersistentDataKeys() =
|
override fun getRegisteredPersistentDataKeys() =
|
||||||
KeyRegistry.getRegisteredKeys()
|
KeyRegistry.getRegisteredKeys()
|
||||||
|
|
||||||
@@ -235,7 +227,7 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
|||||||
MetricHandler.createMetrics(plugin)
|
MetricHandler.createMetrics(plugin)
|
||||||
|
|
||||||
override fun getAdventure() =
|
override fun getAdventure() =
|
||||||
adventure
|
bukkitAudiences
|
||||||
|
|
||||||
override fun getServerProfile() =
|
override fun getServerProfile() =
|
||||||
profileHandler.loadServerProfile()
|
profileHandler.loadServerProfile()
|
||||||
@@ -243,12 +235,6 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
|||||||
override fun loadPlayerProfile(uuid: UUID) =
|
override fun loadPlayerProfile(uuid: UUID) =
|
||||||
profileHandler.load(uuid)
|
profileHandler.load(uuid)
|
||||||
|
|
||||||
override fun saveAllProfiles() =
|
|
||||||
profileHandler.save()
|
|
||||||
|
|
||||||
override fun savePersistentDataKeysFor(uuid: UUID, keys: Set<PersistentDataKey<*>>) =
|
|
||||||
profileHandler.saveKeysFor(uuid, keys)
|
|
||||||
|
|
||||||
override fun unloadPlayerProfile(uuid: UUID) =
|
override fun unloadPlayerProfile(uuid: UUID) =
|
||||||
profileHandler.unloadPlayer(uuid)
|
profileHandler.unloadPlayer(uuid)
|
||||||
|
|
||||||
@@ -292,13 +278,12 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
|||||||
override fun getTPS() =
|
override fun getTPS() =
|
||||||
getProxy(TPSProxy::class.java).getTPS()
|
getProxy(TPSProxy::class.java).getTPS()
|
||||||
|
|
||||||
override fun evaluate(
|
override fun evaluate(expression: String, context: MathContext) =
|
||||||
expression: String,
|
evaluateExpression(expression, context)
|
||||||
player: Player?,
|
|
||||||
injectable: PlaceholderInjectable,
|
|
||||||
additionalPlayers: MutableCollection<AdditionalPlayer>
|
|
||||||
) = evaluateExpression(expression, player, injectable, additionalPlayers)
|
|
||||||
|
|
||||||
override fun getOpenMenu(player: Player) =
|
override fun getOpenMenu(player: Player) =
|
||||||
player.renderedInventory?.menu
|
player.renderedInventory?.menu
|
||||||
|
|
||||||
|
override fun syncCommands() =
|
||||||
|
this.getProxy(SyncCommandsProxy::class.java).syncCommands()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,8 +14,11 @@ import com.willfp.eco.core.integrations.customitems.CustomItemsManager
|
|||||||
import com.willfp.eco.core.integrations.economy.EconomyManager
|
import com.willfp.eco.core.integrations.economy.EconomyManager
|
||||||
import com.willfp.eco.core.integrations.hologram.HologramManager
|
import com.willfp.eco.core.integrations.hologram.HologramManager
|
||||||
import com.willfp.eco.core.integrations.mcmmo.McmmoManager
|
import com.willfp.eco.core.integrations.mcmmo.McmmoManager
|
||||||
|
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
||||||
import com.willfp.eco.core.integrations.shop.ShopManager
|
import com.willfp.eco.core.integrations.shop.ShopManager
|
||||||
import com.willfp.eco.core.items.Items
|
import com.willfp.eco.core.items.Items
|
||||||
|
import com.willfp.eco.core.particle.Particles
|
||||||
|
import com.willfp.eco.core.price.Prices
|
||||||
import com.willfp.eco.internal.entities.EntityArgParserAdult
|
import com.willfp.eco.internal.entities.EntityArgParserAdult
|
||||||
import com.willfp.eco.internal.entities.EntityArgParserAttackDamage
|
import com.willfp.eco.internal.entities.EntityArgParserAttackDamage
|
||||||
import com.willfp.eco.internal.entities.EntityArgParserAttackSpeed
|
import com.willfp.eco.internal.entities.EntityArgParserAttackSpeed
|
||||||
@@ -44,11 +47,15 @@ import com.willfp.eco.internal.items.ArgParserTexture
|
|||||||
import com.willfp.eco.internal.items.ArgParserUnbreakable
|
import com.willfp.eco.internal.items.ArgParserUnbreakable
|
||||||
import com.willfp.eco.internal.lookup.SegmentParserGroup
|
import com.willfp.eco.internal.lookup.SegmentParserGroup
|
||||||
import com.willfp.eco.internal.lookup.SegmentParserUseIfPresent
|
import com.willfp.eco.internal.lookup.SegmentParserUseIfPresent
|
||||||
|
import com.willfp.eco.internal.particle.ParticleFactoryRGB
|
||||||
|
import com.willfp.eco.internal.price.PriceFactoryEconomy
|
||||||
|
import com.willfp.eco.internal.price.PriceFactoryXP
|
||||||
|
import com.willfp.eco.internal.price.PriceFactoryXPLevels
|
||||||
import com.willfp.eco.internal.spigot.arrows.ArrowDataListener
|
import com.willfp.eco.internal.spigot.arrows.ArrowDataListener
|
||||||
import com.willfp.eco.internal.spigot.data.DataListener
|
import com.willfp.eco.internal.spigot.data.DataListener
|
||||||
import com.willfp.eco.internal.spigot.data.DataYml
|
import com.willfp.eco.internal.spigot.data.DataYml
|
||||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
|
||||||
import com.willfp.eco.internal.spigot.data.PlayerBlockListener
|
import com.willfp.eco.internal.spigot.data.PlayerBlockListener
|
||||||
|
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
||||||
import com.willfp.eco.internal.spigot.data.storage.ProfileSaver
|
import com.willfp.eco.internal.spigot.data.storage.ProfileSaver
|
||||||
import com.willfp.eco.internal.spigot.display.PacketAutoRecipe
|
import com.willfp.eco.internal.spigot.display.PacketAutoRecipe
|
||||||
import com.willfp.eco.internal.spigot.display.PacketChat
|
import com.willfp.eco.internal.spigot.display.PacketChat
|
||||||
@@ -86,6 +93,7 @@ import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefGriefPreve
|
|||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefIridiumSkyblock
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefIridiumSkyblock
|
||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefKingdoms
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefKingdoms
|
||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefLands
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefLands
|
||||||
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefPvPManager
|
||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefRPGHorses
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefRPGHorses
|
||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefSuperiorSkyblock2
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefSuperiorSkyblock2
|
||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefTowny
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefTowny
|
||||||
@@ -106,11 +114,11 @@ import com.willfp.eco.internal.spigot.integrations.hologram.HologramDecentHologr
|
|||||||
import com.willfp.eco.internal.spigot.integrations.hologram.HologramHolographicDisplays
|
import com.willfp.eco.internal.spigot.integrations.hologram.HologramHolographicDisplays
|
||||||
import com.willfp.eco.internal.spigot.integrations.mcmmo.McmmoIntegrationImpl
|
import com.willfp.eco.internal.spigot.integrations.mcmmo.McmmoIntegrationImpl
|
||||||
import com.willfp.eco.internal.spigot.integrations.multiverseinventories.MultiverseInventoriesIntegration
|
import com.willfp.eco.internal.spigot.integrations.multiverseinventories.MultiverseInventoriesIntegration
|
||||||
|
import com.willfp.eco.internal.spigot.integrations.placeholder.PlaceholderIntegrationPAPI
|
||||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopDeluxeSellwands
|
import com.willfp.eco.internal.spigot.integrations.shop.ShopDeluxeSellwands
|
||||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopEconomyShopGUI
|
import com.willfp.eco.internal.spigot.integrations.shop.ShopEconomyShopGUI
|
||||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopShopGuiPlus
|
import com.willfp.eco.internal.spigot.integrations.shop.ShopShopGuiPlus
|
||||||
import com.willfp.eco.internal.spigot.integrations.shop.ShopZShop
|
import com.willfp.eco.internal.spigot.integrations.shop.ShopZShop
|
||||||
import com.willfp.eco.internal.spigot.player.PlayerHealthFixer
|
|
||||||
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
|
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
|
||||||
import com.willfp.eco.internal.spigot.recipes.CraftingRecipeListener
|
import com.willfp.eco.internal.spigot.recipes.CraftingRecipeListener
|
||||||
import com.willfp.eco.internal.spigot.recipes.StackedRecipeListener
|
import com.willfp.eco.internal.spigot.recipes.StackedRecipeListener
|
||||||
@@ -118,6 +126,7 @@ import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInComplex
|
|||||||
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInVanilla
|
import com.willfp.eco.internal.spigot.recipes.listeners.ComplexInVanilla
|
||||||
import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapedCraftingRecipeStackHandler
|
import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapedCraftingRecipeStackHandler
|
||||||
import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapelessCraftingRecipeStackHandler
|
import com.willfp.eco.internal.spigot.recipes.stackhandlers.ShapelessCraftingRecipeStackHandler
|
||||||
|
import net.kyori.adventure.platform.bukkit.BukkitAudiences
|
||||||
import net.milkbowl.vault.economy.Economy
|
import net.milkbowl.vault.economy.Economy
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.Material
|
import org.bukkit.Material
|
||||||
@@ -126,7 +135,8 @@ import org.bukkit.inventory.ItemStack
|
|||||||
|
|
||||||
abstract class EcoSpigotPlugin : EcoPlugin() {
|
abstract class EcoSpigotPlugin : EcoPlugin() {
|
||||||
abstract val dataYml: DataYml
|
abstract val dataYml: DataYml
|
||||||
protected abstract val profileHandler: EcoProfileHandler
|
protected abstract val profileHandler: ProfileHandler
|
||||||
|
protected var bukkitAudiences: BukkitAudiences? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
Items.registerArgParser(ArgParserEnchantment)
|
Items.registerArgParser(ArgParserEnchantment)
|
||||||
@@ -157,6 +167,12 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
|||||||
Entities.registerArgParser(EntityArgParserSilent)
|
Entities.registerArgParser(EntityArgParserSilent)
|
||||||
Entities.registerArgParser(EntityArgParserEquipment)
|
Entities.registerArgParser(EntityArgParserEquipment)
|
||||||
|
|
||||||
|
Prices.registerPriceFactory(PriceFactoryEconomy)
|
||||||
|
Prices.registerPriceFactory(PriceFactoryXPLevels)
|
||||||
|
Prices.registerPriceFactory(PriceFactoryXP)
|
||||||
|
|
||||||
|
Particles.registerParticleFactory(ParticleFactoryRGB)
|
||||||
|
|
||||||
CraftingRecipeListener.registerListener(ComplexInComplex)
|
CraftingRecipeListener.registerListener(ComplexInComplex)
|
||||||
CraftingRecipeListener.registerListener(ComplexInVanilla)
|
CraftingRecipeListener.registerListener(ComplexInVanilla)
|
||||||
|
|
||||||
@@ -205,6 +221,11 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
|||||||
|
|
||||||
// Preload categorized persistent data keys
|
// Preload categorized persistent data keys
|
||||||
profileHandler.initialize()
|
profileHandler.initialize()
|
||||||
|
|
||||||
|
// Init adventure
|
||||||
|
if (!Prerequisite.HAS_PAPER.isMet) {
|
||||||
|
bukkitAudiences = BukkitAudiences.create(this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun handleDisable() {
|
override fun handleDisable() {
|
||||||
@@ -263,6 +284,7 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
|||||||
AntigriefManager.register(AntigriefCombatLogXV11())
|
AntigriefManager.register(AntigriefCombatLogXV11())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
IntegrationLoader("PvPManager") { AntigriefManager.register(AntigriefPvPManager()) },
|
||||||
|
|
||||||
// Anticheat
|
// Anticheat
|
||||||
IntegrationLoader("AAC5") { AnticheatManager.register(AnticheatAAC()) },
|
IntegrationLoader("AAC5") { AnticheatManager.register(AnticheatAAC()) },
|
||||||
@@ -311,6 +333,9 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Placeholder
|
||||||
|
IntegrationLoader("PlaceholderAPI") { PlaceholderManager.addIntegration(PlaceholderIntegrationPAPI()) },
|
||||||
|
|
||||||
// Misc
|
// Misc
|
||||||
IntegrationLoader("mcMMO") { McmmoManager.register(McmmoIntegrationImpl()) },
|
IntegrationLoader("mcMMO") { McmmoManager.register(McmmoIntegrationImpl()) },
|
||||||
IntegrationLoader("Multiverse-Inventories") {
|
IntegrationLoader("Multiverse-Inventories") {
|
||||||
@@ -345,7 +370,6 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
|||||||
ArmorChangeEventListeners(this),
|
ArmorChangeEventListeners(this),
|
||||||
DataListener(this),
|
DataListener(this),
|
||||||
PlayerBlockListener(this),
|
PlayerBlockListener(this),
|
||||||
PlayerHealthFixer(this),
|
|
||||||
ServerLocking
|
ServerLocking
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -48,8 +48,4 @@ object KeyRegistry {
|
|||||||
else -> throw NullPointerException("Null value found!")
|
else -> throw NullPointerException("Null value found!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getKeyFrom(namespacedKey: NamespacedKey): PersistentDataKey<*>? {
|
|
||||||
return registry[namespacedKey]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import java.util.UUID
|
|||||||
|
|
||||||
val serverProfileUUID = UUID(0, 0)
|
val serverProfileUUID = UUID(0, 0)
|
||||||
|
|
||||||
class EcoProfileHandler(
|
class ProfileHandler(
|
||||||
private val type: HandlerType,
|
private val type: HandlerType,
|
||||||
private val plugin: EcoSpigotPlugin
|
private val plugin: EcoSpigotPlugin
|
||||||
) {
|
) {
|
||||||
@@ -7,7 +7,7 @@ import com.willfp.eco.core.EcoPlugin
|
|||||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
||||||
import com.willfp.eco.internal.spigot.data.serverProfileUUID
|
import com.willfp.eco.internal.spigot.data.serverProfileUUID
|
||||||
import com.zaxxer.hikari.HikariConfig
|
import com.zaxxer.hikari.HikariConfig
|
||||||
import com.zaxxer.hikari.HikariDataSource
|
import com.zaxxer.hikari.HikariDataSource
|
||||||
@@ -49,8 +49,9 @@ the worst bodge I've shipped in production.
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
class LegacyMySQLDataHandler(
|
class LegacyMySQLDataHandler(
|
||||||
plugin: EcoSpigotPlugin,
|
plugin: EcoSpigotPlugin,
|
||||||
handler: EcoProfileHandler
|
handler: ProfileHandler
|
||||||
) : DataHandler(HandlerType.LEGACY_MYSQL) {
|
) : DataHandler(HandlerType.LEGACY_MYSQL) {
|
||||||
|
private val database: Database
|
||||||
private val playerHandler: ImplementedMySQLHandler
|
private val playerHandler: ImplementedMySQLHandler
|
||||||
private val serverHandler: ImplementedMySQLHandler
|
private val serverHandler: ImplementedMySQLHandler
|
||||||
|
|
||||||
@@ -65,7 +66,7 @@ class LegacyMySQLDataHandler(
|
|||||||
plugin.configYml.getString("mysql.database")
|
plugin.configYml.getString("mysql.database")
|
||||||
config.maximumPoolSize = plugin.configYml.getInt("mysql.connections")
|
config.maximumPoolSize = plugin.configYml.getInt("mysql.connections")
|
||||||
|
|
||||||
Database.connect(HikariDataSource(config))
|
database = Database.connect(HikariDataSource(config))
|
||||||
|
|
||||||
playerHandler = ImplementedMySQLHandler(
|
playerHandler = ImplementedMySQLHandler(
|
||||||
handler,
|
handler,
|
||||||
@@ -110,180 +111,180 @@ class LegacyMySQLDataHandler(
|
|||||||
playerHandler.initialize()
|
playerHandler.initialize()
|
||||||
serverHandler.initialize()
|
serverHandler.initialize()
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
private class ImplementedMySQLHandler(
|
private inner class ImplementedMySQLHandler(
|
||||||
private val handler: EcoProfileHandler,
|
private val handler: ProfileHandler,
|
||||||
private val table: UUIDTable,
|
private val table: UUIDTable,
|
||||||
private val plugin: EcoPlugin
|
private val plugin: EcoPlugin
|
||||||
) {
|
) {
|
||||||
private val rows = Caffeine.newBuilder()
|
private val rows = Caffeine.newBuilder()
|
||||||
.expireAfterWrite(3, TimeUnit.SECONDS)
|
.expireAfterWrite(3, TimeUnit.SECONDS)
|
||||||
.build<UUID, ResultRow>()
|
.build<UUID, ResultRow>()
|
||||||
|
|
||||||
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build()
|
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-legacy-mysql-thread-%d").build()
|
||||||
private val executor = Executors.newFixedThreadPool(plugin.configYml.getInt("mysql.threads"), threadFactory)
|
private val executor = Executors.newFixedThreadPool(plugin.configYml.getInt("mysql.threads"), threadFactory)
|
||||||
val registeredKeys = mutableSetOf<PersistentDataKey<*>>()
|
val registeredKeys = mutableSetOf<PersistentDataKey<*>>()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
transaction {
|
transaction(database) {
|
||||||
SchemaUtils.create(table)
|
SchemaUtils.create(table)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun initialize() {
|
fun initialize() {
|
||||||
transaction {
|
transaction(database) {
|
||||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun ensureKeyRegistration(key: PersistentDataKey<*>) {
|
fun ensureKeyRegistration(key: PersistentDataKey<*>) {
|
||||||
if (table.columns.any { it.name == key.key.toString() }) {
|
if (table.columns.any { it.name == key.key.toString() }) {
|
||||||
|
registeredKeys.add(key)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
registerColumn(key)
|
||||||
registeredKeys.add(key)
|
registeredKeys.add(key)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
registerColumn(key)
|
fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: Any) {
|
||||||
registeredKeys.add(key)
|
getRow(uuid)
|
||||||
}
|
doWrite(uuid, key, key.type.constrainSQLTypes(value))
|
||||||
|
|
||||||
fun <T : Any> write(uuid: UUID, key: PersistentDataKey<T>, value: Any) {
|
|
||||||
getRow(uuid)
|
|
||||||
doWrite(uuid, key, key.type.constrainSQLTypes(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doWrite(uuid: UUID, key: PersistentDataKey<*>, constrainedValue: Any) {
|
|
||||||
val column: Column<Any> = getColumn(key) as Column<Any>
|
|
||||||
|
|
||||||
executor.submit {
|
|
||||||
transaction {
|
|
||||||
table.update({ table.id eq uuid }) {
|
|
||||||
it[column] = constrainedValue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveKeysForRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
|
||||||
saveRow(uuid, keys)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun saveRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
|
||||||
val profile = handler.loadGenericProfile(uuid)
|
|
||||||
|
|
||||||
executor.submit {
|
|
||||||
transaction {
|
|
||||||
getRow(uuid)
|
|
||||||
|
|
||||||
for (key in keys) {
|
|
||||||
doWrite(uuid, key, key.type.constrainSQLTypes(profile.read(key)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T> read(uuid: UUID, key: PersistentDataKey<T>): T? {
|
|
||||||
val doRead = Callable<T?> {
|
|
||||||
transaction {
|
|
||||||
val row = getRow(uuid)
|
|
||||||
val column = getColumn(key)
|
|
||||||
val raw = row[column]
|
|
||||||
key.type.fromConstrained(raw)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ensureKeyRegistration(key) // DON'T DELETE THIS LINE! I know it's covered in getColumn, but I need to do it here as well.
|
private fun doWrite(uuid: UUID, key: PersistentDataKey<*>, constrainedValue: Any) {
|
||||||
|
val column: Column<Any> = getColumn(key) as Column<Any>
|
||||||
|
|
||||||
doRead.call()
|
executor.submit {
|
||||||
|
transaction(database) {
|
||||||
return if (Eco.get().ecoPlugin.configYml.getBool("mysql.async-reads")) {
|
table.update({ table.id eq uuid }) {
|
||||||
executor.submit(doRead).get()
|
it[column] = constrainedValue
|
||||||
} else {
|
|
||||||
doRead.call()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun <T> registerColumn(key: PersistentDataKey<T>) {
|
|
||||||
try {
|
|
||||||
transaction {
|
|
||||||
try {
|
|
||||||
table.apply {
|
|
||||||
if (table.columns.any { it.name == key.key.toString() }) {
|
|
||||||
return@apply
|
|
||||||
}
|
|
||||||
|
|
||||||
when (key.type) {
|
|
||||||
PersistentDataKeyType.INT -> registerColumn<Int>(key.key.toString(), IntegerColumnType())
|
|
||||||
.default(key.defaultValue as Int)
|
|
||||||
|
|
||||||
PersistentDataKeyType.DOUBLE -> registerColumn<Double>(
|
|
||||||
key.key.toString(),
|
|
||||||
DoubleColumnType()
|
|
||||||
).default(key.defaultValue as Double)
|
|
||||||
|
|
||||||
PersistentDataKeyType.BOOLEAN -> registerColumn<Boolean>(
|
|
||||||
key.key.toString(),
|
|
||||||
BooleanColumnType()
|
|
||||||
).default(key.defaultValue as Boolean)
|
|
||||||
|
|
||||||
PersistentDataKeyType.STRING -> registerColumn<String>(
|
|
||||||
key.key.toString(),
|
|
||||||
VarCharColumnType(512)
|
|
||||||
).default(key.defaultValue as String)
|
|
||||||
|
|
||||||
PersistentDataKeyType.STRING_LIST -> registerColumn<String>(
|
|
||||||
key.key.toString(),
|
|
||||||
VarCharColumnType(8192)
|
|
||||||
).default(PersistentDataKeyType.STRING_LIST.constrainSQLTypes(key.defaultValue as List<String>) as String)
|
|
||||||
|
|
||||||
PersistentDataKeyType.CONFIG -> throw IllegalArgumentException(
|
|
||||||
"Config Persistent Data Keys are not supported by the legacy MySQL handler!"
|
|
||||||
)
|
|
||||||
|
|
||||||
else -> throw NullPointerException("Null value found!")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
|
||||||
} catch (e: Exception) {
|
|
||||||
plugin.logger.info("MySQL Error 1!")
|
|
||||||
e.printStackTrace()
|
|
||||||
// What's that? Two enormous exception catches? That's right! This code sucks.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
|
||||||
plugin.logger.info("MySQL Error 2!")
|
|
||||||
e.printStackTrace()
|
|
||||||
// It might fail. Who cares? This is legacy.
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun getColumn(key: PersistentDataKey<*>): Column<*> {
|
fun saveKeysForRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||||
ensureKeyRegistration(key)
|
saveRow(uuid, keys)
|
||||||
|
}
|
||||||
|
|
||||||
val name = key.key.toString()
|
private fun saveRow(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
|
||||||
|
val profile = handler.loadGenericProfile(uuid)
|
||||||
|
|
||||||
return table.columns.first { it.name == name }
|
executor.submit {
|
||||||
}
|
transaction(database) {
|
||||||
|
getRow(uuid)
|
||||||
|
|
||||||
private fun getRow(uuid: UUID): ResultRow {
|
for (key in keys) {
|
||||||
fun select(uuid: UUID): ResultRow? {
|
doWrite(uuid, key, key.type.constrainSQLTypes(profile.read(key)))
|
||||||
return transaction {
|
}
|
||||||
table.select { table.id eq uuid }.limit(1).singleOrNull()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rows.get(uuid) {
|
fun <T> read(uuid: UUID, key: PersistentDataKey<T>): T? {
|
||||||
val row = select(uuid)
|
val doRead = Callable<T?> {
|
||||||
|
transaction(database) {
|
||||||
|
val row = getRow(uuid)
|
||||||
|
val column = getColumn(key)
|
||||||
|
val raw = row[column]
|
||||||
|
key.type.fromConstrained(raw)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return@get if (row != null) {
|
ensureKeyRegistration(key) // DON'T DELETE THIS LINE! I know it's covered in getColumn, but I need to do it here as well.
|
||||||
row
|
|
||||||
|
doRead.call()
|
||||||
|
|
||||||
|
return if (Eco.get().ecoPlugin.configYml.getBool("mysql.async-reads")) {
|
||||||
|
executor.submit(doRead).get()
|
||||||
} else {
|
} else {
|
||||||
transaction {
|
doRead.call()
|
||||||
table.insert { it[id] = uuid }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> registerColumn(key: PersistentDataKey<T>) {
|
||||||
|
try {
|
||||||
|
transaction(database) {
|
||||||
|
try {
|
||||||
|
table.apply {
|
||||||
|
if (table.columns.any { it.name == key.key.toString() }) {
|
||||||
|
return@apply
|
||||||
|
}
|
||||||
|
|
||||||
|
when (key.type) {
|
||||||
|
PersistentDataKeyType.INT -> registerColumn<Int>(key.key.toString(), IntegerColumnType())
|
||||||
|
.default(key.defaultValue as Int)
|
||||||
|
|
||||||
|
PersistentDataKeyType.DOUBLE -> registerColumn<Double>(
|
||||||
|
key.key.toString(),
|
||||||
|
DoubleColumnType()
|
||||||
|
).default(key.defaultValue as Double)
|
||||||
|
|
||||||
|
PersistentDataKeyType.BOOLEAN -> registerColumn<Boolean>(
|
||||||
|
key.key.toString(),
|
||||||
|
BooleanColumnType()
|
||||||
|
).default(key.defaultValue as Boolean)
|
||||||
|
|
||||||
|
PersistentDataKeyType.STRING -> registerColumn<String>(
|
||||||
|
key.key.toString(),
|
||||||
|
VarCharColumnType(512)
|
||||||
|
).default(key.defaultValue as String)
|
||||||
|
|
||||||
|
PersistentDataKeyType.STRING_LIST -> registerColumn<String>(
|
||||||
|
key.key.toString(),
|
||||||
|
VarCharColumnType(8192)
|
||||||
|
).default(PersistentDataKeyType.STRING_LIST.constrainSQLTypes(key.defaultValue as List<String>) as String)
|
||||||
|
|
||||||
|
PersistentDataKeyType.CONFIG -> throw IllegalArgumentException(
|
||||||
|
"Config Persistent Data Keys are not supported by the legacy MySQL handler!"
|
||||||
|
)
|
||||||
|
|
||||||
|
else -> throw NullPointerException("Null value found!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
plugin.logger.info("MySQL Error 1!")
|
||||||
|
e.printStackTrace()
|
||||||
|
// What's that? Two enormous exception catches? That's right! This code sucks.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
plugin.logger.info("MySQL Error 2!")
|
||||||
|
e.printStackTrace()
|
||||||
|
// It might fail. Who cares? This is legacy.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getColumn(key: PersistentDataKey<*>): Column<*> {
|
||||||
|
ensureKeyRegistration(key)
|
||||||
|
|
||||||
|
val name = key.key.toString()
|
||||||
|
|
||||||
|
return table.columns.first { it.name == name }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getRow(uuid: UUID): ResultRow {
|
||||||
|
fun select(uuid: UUID): ResultRow? {
|
||||||
|
return transaction(database) {
|
||||||
|
table.select { table.id eq uuid }.limit(1).singleOrNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rows.get(uuid) {
|
||||||
|
val row = select(uuid)
|
||||||
|
|
||||||
|
return@get if (row != null) {
|
||||||
|
row
|
||||||
|
} else {
|
||||||
|
transaction(database) {
|
||||||
|
table.insert { it[id] = uuid }
|
||||||
|
}
|
||||||
|
select(uuid)
|
||||||
}
|
}
|
||||||
select(uuid)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ package com.willfp.eco.internal.spigot.data.storage
|
|||||||
import com.willfp.eco.core.data.Profile
|
import com.willfp.eco.core.data.Profile
|
||||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -20,7 +20,7 @@ import java.util.UUID
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
class MongoDataHandler(
|
class MongoDataHandler(
|
||||||
plugin: EcoSpigotPlugin,
|
plugin: EcoSpigotPlugin,
|
||||||
private val handler: EcoProfileHandler
|
private val handler: ProfileHandler
|
||||||
) : DataHandler(HandlerType.MONGO) {
|
) : DataHandler(HandlerType.MONGO) {
|
||||||
private val client: CoroutineClient
|
private val client: CoroutineClient
|
||||||
private val collection: CoroutineCollection<UUIDProfile>
|
private val collection: CoroutineCollection<UUIDProfile>
|
||||||
|
|||||||
@@ -3,12 +3,12 @@ package com.willfp.eco.internal.spigot.data.storage
|
|||||||
import com.github.benmanes.caffeine.cache.Caffeine
|
import com.github.benmanes.caffeine.cache.Caffeine
|
||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
||||||
import com.willfp.eco.core.config.ConfigType
|
import com.willfp.eco.core.config.ConfigType
|
||||||
import com.willfp.eco.core.config.TransientConfig
|
|
||||||
import com.willfp.eco.core.config.interfaces.Config
|
import com.willfp.eco.core.config.interfaces.Config
|
||||||
|
import com.willfp.eco.core.config.readConfig
|
||||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
||||||
import com.zaxxer.hikari.HikariConfig
|
import com.zaxxer.hikari.HikariConfig
|
||||||
import com.zaxxer.hikari.HikariDataSource
|
import com.zaxxer.hikari.HikariDataSource
|
||||||
import org.jetbrains.exposed.dao.id.UUIDTable
|
import org.jetbrains.exposed.dao.id.UUIDTable
|
||||||
@@ -35,8 +35,9 @@ Whatever. At least it works.
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
class MySQLDataHandler(
|
class MySQLDataHandler(
|
||||||
private val plugin: EcoSpigotPlugin,
|
private val plugin: EcoSpigotPlugin,
|
||||||
private val handler: EcoProfileHandler
|
private val handler: ProfileHandler
|
||||||
) : DataHandler(HandlerType.MYSQL) {
|
) : DataHandler(HandlerType.MYSQL) {
|
||||||
|
private val database: Database
|
||||||
private val table = UUIDTable("eco_data")
|
private val table = UUIDTable("eco_data")
|
||||||
|
|
||||||
private val rows = Caffeine.newBuilder()
|
private val rows = Caffeine.newBuilder()
|
||||||
@@ -60,9 +61,9 @@ class MySQLDataHandler(
|
|||||||
plugin.configYml.getString("mysql.database")
|
plugin.configYml.getString("mysql.database")
|
||||||
config.maximumPoolSize = plugin.configYml.getInt("mysql.connections")
|
config.maximumPoolSize = plugin.configYml.getInt("mysql.connections")
|
||||||
|
|
||||||
Database.connect(HikariDataSource(config))
|
database = Database.connect(HikariDataSource(config))
|
||||||
|
|
||||||
transaction {
|
transaction(database) {
|
||||||
SchemaUtils.create(table)
|
SchemaUtils.create(table)
|
||||||
|
|
||||||
table.apply {
|
table.apply {
|
||||||
@@ -110,14 +111,14 @@ class MySQLDataHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getData(uuid: UUID): Config {
|
private fun getData(uuid: UUID): Config {
|
||||||
val plaintext = transaction {
|
val plaintext = transaction(database) {
|
||||||
val row = rows.get(uuid) {
|
val row = rows.get(uuid) {
|
||||||
val row = table.select { table.id eq uuid }.limit(1).singleOrNull()
|
val row = table.select { table.id eq uuid }.limit(1).singleOrNull()
|
||||||
|
|
||||||
if (row != null) {
|
if (row != null) {
|
||||||
row
|
row
|
||||||
} else {
|
} else {
|
||||||
transaction {
|
transaction(database) {
|
||||||
table.insert {
|
table.insert {
|
||||||
it[id] = uuid
|
it[id] = uuid
|
||||||
it[dataColumn] = "{}"
|
it[dataColumn] = "{}"
|
||||||
@@ -130,13 +131,12 @@ class MySQLDataHandler(
|
|||||||
row.getOrNull(dataColumn) ?: "{}"
|
row.getOrNull(dataColumn) ?: "{}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return readConfig(plaintext, ConfigType.JSON)
|
||||||
return TransientConfig(plaintext, ConfigType.JSON)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setData(uuid: UUID, config: Config) {
|
private fun setData(uuid: UUID, config: Config) {
|
||||||
executor.submit {
|
executor.submit {
|
||||||
transaction {
|
transaction(database) {
|
||||||
table.update({ table.id eq uuid }) {
|
table.update({ table.id eq uuid }) {
|
||||||
it[dataColumn] = config.toPlaintext()
|
it[dataColumn] = config.toPlaintext()
|
||||||
}
|
}
|
||||||
@@ -145,7 +145,7 @@ class MySQLDataHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
transaction {
|
transaction(database) {
|
||||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,14 +2,16 @@ package com.willfp.eco.internal.spigot.data.storage
|
|||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin
|
import com.willfp.eco.core.EcoPlugin
|
||||||
import com.willfp.eco.internal.spigot.data.EcoProfile
|
import com.willfp.eco.internal.spigot.data.EcoProfile
|
||||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
||||||
|
|
||||||
class ProfileSaver(
|
class ProfileSaver(
|
||||||
plugin: EcoPlugin,
|
plugin: EcoPlugin,
|
||||||
handler: EcoProfileHandler
|
handler: ProfileHandler
|
||||||
) {
|
) {
|
||||||
init {
|
init {
|
||||||
plugin.scheduler.runTimer(1, 1) {
|
val interval = plugin.configYml.getInt("save-interval").toLong()
|
||||||
|
|
||||||
|
plugin.scheduler.runTimer(20, interval) {
|
||||||
for ((uuid, set) in EcoProfile.CHANGE_MAP) {
|
for ((uuid, set) in EcoProfile.CHANGE_MAP) {
|
||||||
handler.saveKeysFor(uuid, set)
|
handler.saveKeysFor(uuid, set)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ package com.willfp.eco.internal.spigot.data.storage
|
|||||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
||||||
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
|
||||||
import com.willfp.eco.internal.spigot.data.EcoProfileHandler
|
import com.willfp.eco.internal.spigot.data.ProfileHandler
|
||||||
import org.bukkit.NamespacedKey
|
import org.bukkit.NamespacedKey
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
class YamlDataHandler(
|
class YamlDataHandler(
|
||||||
plugin: EcoSpigotPlugin,
|
plugin: EcoSpigotPlugin,
|
||||||
private val handler: EcoProfileHandler
|
private val handler: ProfileHandler
|
||||||
) : DataHandler(HandlerType.YAML) {
|
) : DataHandler(HandlerType.YAML) {
|
||||||
private val dataYml = plugin.dataYml
|
private val dataYml = plugin.dataYml
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.willfp.eco.internal.spigot.display.frame
|
package com.willfp.eco.internal.spigot.display.frame
|
||||||
|
|
||||||
|
import com.comphenix.protocol.injector.temporary.TemporaryPlayer
|
||||||
import com.willfp.eco.core.items.HashedItem
|
import com.willfp.eco.core.items.HashedItem
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
@@ -32,9 +33,19 @@ private val frames = ConcurrentHashMap<UUID, DisplayFrame>()
|
|||||||
|
|
||||||
var Player.lastDisplayFrame: DisplayFrame
|
var Player.lastDisplayFrame: DisplayFrame
|
||||||
get() {
|
get() {
|
||||||
|
// ProtocolLib fix
|
||||||
|
if (this is TemporaryPlayer) {
|
||||||
|
return DisplayFrame.EMPTY
|
||||||
|
}
|
||||||
|
|
||||||
return frames[this.uniqueId] ?: DisplayFrame.EMPTY
|
return frames[this.uniqueId] ?: DisplayFrame.EMPTY
|
||||||
}
|
}
|
||||||
set(value) {
|
set(value) {
|
||||||
|
// ProtocolLib fix
|
||||||
|
if (this is TemporaryPlayer) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
frames[this.uniqueId] = value
|
frames[this.uniqueId] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,14 @@ class GUIListener(private val plugin: EcoPlugin) : Listener {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
priority = EventPriority.HIGHEST
|
||||||
|
)
|
||||||
|
fun handleRender(event: InventoryClickEvent) {
|
||||||
|
val player = event.whoClicked as? Player ?: return
|
||||||
|
player.renderActiveMenu()
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(
|
@EventHandler(
|
||||||
priority = EventPriority.HIGH
|
priority = EventPriority.HIGH
|
||||||
)
|
)
|
||||||
@@ -62,9 +70,7 @@ class GUIListener(private val plugin: EcoPlugin) : Listener {
|
|||||||
|
|
||||||
val (row, column) = MenuUtils.convertSlotToRowColumn(event.slot, menu.columns)
|
val (row, column) = MenuUtils.convertSlotToRowColumn(event.slot, menu.columns)
|
||||||
|
|
||||||
menu.getSlot(row, column, player, menu).handle(player, event, menu)
|
menu.getSlot(row, column, player).handle(player, event, menu)
|
||||||
|
|
||||||
plugin.scheduler.run { rendered.render() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(
|
@EventHandler(
|
||||||
@@ -87,7 +93,7 @@ class GUIListener(private val plugin: EcoPlugin) : Listener {
|
|||||||
|
|
||||||
val (row, column) = MenuUtils.convertSlotToRowColumn(inv.firstEmpty(), menu.columns)
|
val (row, column) = MenuUtils.convertSlotToRowColumn(inv.firstEmpty(), menu.columns)
|
||||||
|
|
||||||
val slot = menu.getSlot(row, column, player, menu)
|
val slot = menu.getSlot(row, column, player)
|
||||||
|
|
||||||
if (!slot.isCaptive(player, menu)) {
|
if (!slot.isCaptive(player, menu)) {
|
||||||
event.isCancelled = true
|
event.isCancelled = true
|
||||||
@@ -125,6 +131,27 @@ class GUIListener(private val plugin: EcoPlugin) : Listener {
|
|||||||
event.isCancelled = true
|
event.isCancelled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
priority = EventPriority.HIGHEST
|
||||||
|
)
|
||||||
|
fun preventMovingHeld(event: InventoryClickEvent) {
|
||||||
|
val player = event.player
|
||||||
|
|
||||||
|
val rendered = player.renderedInventory ?: return
|
||||||
|
|
||||||
|
if (rendered.menu.allowsChangingHeldItem()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.clickedInventory !is PlayerInventory) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.slot == player.inventory.heldItemSlot) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(
|
@EventHandler(
|
||||||
priority = EventPriority.LOW
|
priority = EventPriority.LOW
|
||||||
)
|
)
|
||||||
@@ -151,7 +178,6 @@ class GUIListener(private val plugin: EcoPlugin) : Listener {
|
|||||||
val rendered = player.renderedInventory ?: return
|
val rendered = player.renderedInventory ?: return
|
||||||
|
|
||||||
if (rendered.menu.allowsChangingHeldItem()) {
|
if (rendered.menu.allowsChangingHeldItem()) {
|
||||||
player.renderActiveMenu()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.integrations.antigrief
|
||||||
|
|
||||||
|
import com.willfp.eco.core.integrations.antigrief.AntigriefIntegration
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.block.Block
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import me.NoChance.PvPManager.PvPlayer
|
||||||
|
|
||||||
|
class AntigriefPvPManager: AntigriefIntegration {
|
||||||
|
override fun getPluginName(): String {
|
||||||
|
return "PvPManager"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canBreakBlock(player: Player, block: Block): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canCreateExplosion(player: Player, location: Location): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canPlaceBlock(player: Player, block: Block): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canInjure(player: Player, victim: LivingEntity): Boolean {
|
||||||
|
return when(victim) {
|
||||||
|
is Player -> {
|
||||||
|
(PvPlayer.get(victim).isInCombat())}
|
||||||
|
else -> true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun canPickupItem(player: Player, location: Location): Boolean {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,11 @@ import com.willfp.eco.core.integrations.antigrief.AntigriefIntegration
|
|||||||
import org.apache.commons.lang.Validate
|
import org.apache.commons.lang.Validate
|
||||||
import org.bukkit.Location
|
import org.bukkit.Location
|
||||||
import org.bukkit.block.Block
|
import org.bukkit.block.Block
|
||||||
import org.bukkit.entity.*
|
import org.bukkit.entity.Animals
|
||||||
|
import org.bukkit.entity.ArmorStand
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import org.bukkit.entity.Monster
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
|
||||||
class AntigriefWorldGuard : AntigriefIntegration {
|
class AntigriefWorldGuard : AntigriefIntegration {
|
||||||
override fun canBreakBlock(
|
override fun canBreakBlock(
|
||||||
|
|||||||
@@ -45,4 +45,4 @@ class CustomItemsScyther : CustomItemsIntegration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.integrations.placeholder
|
||||||
|
|
||||||
|
import com.willfp.eco.core.integrations.placeholder.PlaceholderIntegration
|
||||||
|
import me.clip.placeholderapi.PlaceholderAPI
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
class PlaceholderIntegrationPAPI : PlaceholderIntegration {
|
||||||
|
private val pattern = Pattern.compile("[%]([^% ]+)[%]")
|
||||||
|
|
||||||
|
override fun registerIntegration() {
|
||||||
|
// Do nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getPluginName(): String {
|
||||||
|
return "PlaceholderAPI"
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun translate(
|
||||||
|
text: String,
|
||||||
|
player: Player?
|
||||||
|
): String {
|
||||||
|
return PlaceholderAPI.setPlaceholders(player, text)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findPlaceholdersIn(text: String): MutableList<String> {
|
||||||
|
val placeholders = mutableListOf<String>()
|
||||||
|
val matcher = pattern.matcher(text)
|
||||||
|
while (matcher.find()) {
|
||||||
|
placeholders.add(matcher.group())
|
||||||
|
}
|
||||||
|
|
||||||
|
return placeholders
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ import com.github.benmanes.caffeine.cache.Cache
|
|||||||
import com.github.benmanes.caffeine.cache.Caffeine
|
import com.github.benmanes.caffeine.cache.Caffeine
|
||||||
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager
|
||||||
import com.willfp.eco.core.placeholder.AdditionalPlayer
|
import com.willfp.eco.core.placeholder.AdditionalPlayer
|
||||||
|
import com.willfp.eco.core.math.MathContext
|
||||||
import com.willfp.eco.core.placeholder.PlaceholderInjectable
|
import com.willfp.eco.core.placeholder.PlaceholderInjectable
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import redempt.crunch.CompiledExpression
|
import redempt.crunch.CompiledExpression
|
||||||
@@ -25,7 +26,15 @@ private val max = Function("max", 2) {
|
|||||||
max(it[0], it[1])
|
max(it[0], it[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
fun evaluateExpression(expression: String, player: Player?, context: PlaceholderInjectable, additional: Collection<AdditionalPlayer>): Double {
|
fun evaluateExpression(expression: String, context: MathContext) =
|
||||||
|
evaluateExpression(expression, context.player, context.injectableContext, context.additionalPlayers)
|
||||||
|
|
||||||
|
private fun evaluateExpression(
|
||||||
|
expression: String,
|
||||||
|
player: Player?,
|
||||||
|
context: PlaceholderInjectable,
|
||||||
|
additional: Collection<AdditionalPlayer>
|
||||||
|
): Double {
|
||||||
val placeholderValues = PlaceholderManager.findPlaceholdersIn(expression)
|
val placeholderValues = PlaceholderManager.findPlaceholdersIn(expression)
|
||||||
.map { PlaceholderManager.translatePlaceholders(it, player, context, additional) }
|
.map { PlaceholderManager.translatePlaceholders(it, player, context, additional) }
|
||||||
.map { runCatching { FastNumberParsing.parseDouble(it) }.getOrDefault(0.0) }
|
.map { runCatching { FastNumberParsing.parseDouble(it) }.getOrDefault(0.0) }
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
package com.willfp.eco.internal.spigot.player
|
|
||||||
|
|
||||||
import com.willfp.eco.core.EcoPlugin
|
|
||||||
import com.willfp.eco.core.data.keys.PersistentDataKey
|
|
||||||
import com.willfp.eco.core.data.keys.PersistentDataKeyType
|
|
||||||
import com.willfp.eco.core.data.profile
|
|
||||||
import org.bukkit.event.EventHandler
|
|
||||||
import org.bukkit.event.Listener
|
|
||||||
import org.bukkit.event.player.PlayerJoinEvent
|
|
||||||
import org.bukkit.event.player.PlayerQuitEvent
|
|
||||||
|
|
||||||
class PlayerHealthFixer(
|
|
||||||
private val plugin: EcoPlugin
|
|
||||||
): Listener {
|
|
||||||
private val lastHealthKey = PersistentDataKey(
|
|
||||||
plugin.createNamespacedKey("last_health"),
|
|
||||||
PersistentDataKeyType.DOUBLE,
|
|
||||||
0.0
|
|
||||||
)
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
fun onLeave(event: PlayerQuitEvent) {
|
|
||||||
if (!plugin.configYml.getBool("health-fixer")) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val player = event.player
|
|
||||||
player.profile.write(lastHealthKey, player.health)
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
fun onJoin(event: PlayerJoinEvent) {
|
|
||||||
if (!plugin.configYml.getBool("health-fixer")) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val player = event.player
|
|
||||||
plugin.scheduler.runLater(2) {
|
|
||||||
player.health = player.profile.read(lastHealthKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -30,6 +30,12 @@ mysql:
|
|||||||
user: username
|
user: username
|
||||||
password: passy
|
password: passy
|
||||||
|
|
||||||
|
# How many ticks to wait between committing data to a database. This doesn't
|
||||||
|
# affect yaml storage, only MySQL and MongoDB. By default, data is committed
|
||||||
|
# every tick, but you can increase this to be every x ticks, for example 20
|
||||||
|
# would be committing once a second.
|
||||||
|
save-interval: 1
|
||||||
|
|
||||||
# Options to manage the conflict finder
|
# Options to manage the conflict finder
|
||||||
conflicts:
|
conflicts:
|
||||||
whitelist: # Plugins that should never be marked as conflicts
|
whitelist: # Plugins that should never be marked as conflicts
|
||||||
@@ -73,9 +79,6 @@ log-full-extension-errors: false
|
|||||||
# a custom crafting table, though, this won't affect anything, and you should disable the option.
|
# a custom crafting table, though, this won't affect anything, and you should disable the option.
|
||||||
displayed-recipes: true
|
displayed-recipes: true
|
||||||
|
|
||||||
# Save health on leave and set it back on join - works around attribute modifiers.
|
|
||||||
health-fixer: false
|
|
||||||
|
|
||||||
# If eco plugins should not check for updates; only enable this if you know what you're doing
|
# If eco plugins should not check for updates; only enable this if you know what you're doing
|
||||||
# as there can be urgent hotfixes that you are then not notified about. If you're confident
|
# as there can be urgent hotfixes that you are then not notified about. If you're confident
|
||||||
# that you can manage updates on your own, turn this on.
|
# that you can manage updates on your own, turn this on.
|
||||||
|
|||||||
@@ -48,4 +48,5 @@ softdepend:
|
|||||||
- zShop
|
- zShop
|
||||||
- DeluxeSellwands
|
- DeluxeSellwands
|
||||||
- Scyther
|
- Scyther
|
||||||
- ModelEngine
|
- ModelEngine
|
||||||
|
- PvPManager
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy
|
||||||
|
|
||||||
|
interface SyncCommandsProxy {
|
||||||
|
fun syncCommands()
|
||||||
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
version = 6.43.0
|
version = 6.46.0
|
||||||
plugin-name = eco
|
plugin-name = eco
|
||||||
kotlin.code.style = official
|
kotlin.code.style = official
|
||||||
BIN
lib/PvPManager-3.10.9.jar
Normal file
BIN
lib/PvPManager-3.10.9.jar
Normal file
Binary file not shown.
Reference in New Issue
Block a user