Compare commits
76 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9a8d26990 | ||
|
|
4d3eeaaefc | ||
|
|
610110efde | ||
|
|
7f9052c64d | ||
|
|
55a841b3f5 | ||
|
|
c57c824027 | ||
|
|
7cb905e65a | ||
|
|
31a2c7e338 | ||
|
|
1759b52f82 | ||
|
|
ccf93e3a4d | ||
|
|
abd07389ab | ||
|
|
80ad738bb2 | ||
|
|
b01105819a | ||
|
|
a7c08b0731 | ||
|
|
7e4c071698 | ||
|
|
f94f7ead08 | ||
|
|
b21c5bf3a9 | ||
|
|
7a9e8c5c10 | ||
|
|
a6ddbc46ab | ||
|
|
ffaee137d8 | ||
|
|
18d882dac6 | ||
|
|
52841f7f04 | ||
|
|
47b72e9243 | ||
|
|
854a10e8fd | ||
|
|
823ef6477b | ||
|
|
eccb146852 | ||
|
|
d877b707d6 | ||
|
|
bcb7401c74 | ||
|
|
f05c5f3cd6 | ||
|
|
3bd8bccb81 | ||
|
|
6f55787c84 | ||
|
|
eb4dc168fc | ||
|
|
c5085de5d1 | ||
|
|
019cdbf9c8 | ||
|
|
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 | ||
|
|
052cd74756 | ||
|
|
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:
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ allprojects {
|
|||||||
|
|
||||||
// LibsDisguises
|
// LibsDisguises
|
||||||
maven("https://repo.md-5.net/content/groups/public/")
|
maven("https://repo.md-5.net/content/groups/public/")
|
||||||
|
|
||||||
|
maven("https://repo.techscode.com/repository/maven-releases/")
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.willfp.eco.core;
|
package com.willfp.eco.core;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.PluginCommand;
|
||||||
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.config.interfaces.LoadableConfig;
|
import com.willfp.eco.core.config.interfaces.LoadableConfig;
|
||||||
@@ -29,6 +30,7 @@ import net.kyori.adventure.platform.bukkit.BukkitAudiences;
|
|||||||
import org.apache.commons.lang.Validate;
|
import org.apache.commons.lang.Validate;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.NamespacedKey;
|
import org.bukkit.NamespacedKey;
|
||||||
|
import org.bukkit.command.CommandMap;
|
||||||
import org.bukkit.configuration.ConfigurationSection;
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
import org.bukkit.entity.Mob;
|
import org.bukkit.entity.Mob;
|
||||||
@@ -71,7 +73,7 @@ public interface Eco {
|
|||||||
/**
|
/**
|
||||||
* Create an event manager.
|
* Create an event manager.
|
||||||
*
|
*
|
||||||
* @param plugin The plugin.
|
* @param plugin The plugin.F
|
||||||
* @return The event manager.
|
* @return The event manager.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -136,7 +138,6 @@ public interface Eco {
|
|||||||
*
|
*
|
||||||
* @param plugin The plugin.
|
* @param plugin The plugin.
|
||||||
*/
|
*/
|
||||||
@NotNull
|
|
||||||
void createPAPIIntegration(@NotNull EcoPlugin plugin);
|
void createPAPIIntegration(@NotNull EcoPlugin plugin);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -169,6 +170,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,
|
||||||
@@ -189,6 +191,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,
|
||||||
@@ -202,6 +205,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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -211,6 +215,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);
|
||||||
|
|
||||||
@@ -221,6 +226,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);
|
||||||
|
|
||||||
@@ -331,6 +337,7 @@ public interface Eco {
|
|||||||
*
|
*
|
||||||
* @return The keys.
|
* @return The keys.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
Set<PersistentDataKey<?>> getRegisteredPersistentDataKeys();
|
Set<PersistentDataKey<?>> getRegisteredPersistentDataKeys();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -339,6 +346,7 @@ public interface Eco {
|
|||||||
* @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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -346,6 +354,7 @@ public interface Eco {
|
|||||||
*
|
*
|
||||||
* @return The profile.
|
* @return The profile.
|
||||||
*/
|
*/
|
||||||
|
@NotNull
|
||||||
ServerProfile getServerProfile();
|
ServerProfile getServerProfile();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -498,6 +507,25 @@ public interface Eco {
|
|||||||
@Nullable
|
@Nullable
|
||||||
Menu getOpenMenu(@NotNull Player player);
|
Menu getOpenMenu(@NotNull Player player);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync commands.
|
||||||
|
*/
|
||||||
|
void syncCommands();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the command map.
|
||||||
|
*
|
||||||
|
* @return The command map.
|
||||||
|
*/
|
||||||
|
@NotNull CommandMap getCommandMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister a command.
|
||||||
|
*
|
||||||
|
* @param command The command.
|
||||||
|
*/
|
||||||
|
void unregisterCommand(@NotNull final PluginCommand command);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
|||||||
@@ -699,7 +699,15 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
* @return lang.yml.
|
* @return lang.yml.
|
||||||
*/
|
*/
|
||||||
protected LangYml createLangYml() {
|
protected LangYml createLangYml() {
|
||||||
return new LangYml(this);
|
try {
|
||||||
|
return new LangYml(this);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
this.getLogger().severe("Failed to load lang.yml!");
|
||||||
|
this.getLogger().severe("For the developer of this plugin: make sure you have a lang.yml");
|
||||||
|
e.printStackTrace();
|
||||||
|
Bukkit.getPluginManager().disablePlugin(this);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -710,7 +718,15 @@ public abstract class EcoPlugin extends JavaPlugin implements PluginLike {
|
|||||||
* @return config.yml.
|
* @return config.yml.
|
||||||
*/
|
*/
|
||||||
protected ConfigYml createConfigYml() {
|
protected ConfigYml createConfigYml() {
|
||||||
return new ConfigYml(this);
|
try {
|
||||||
|
return new ConfigYml(this);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
this.getLogger().severe("Failed to load config.yml!");
|
||||||
|
this.getLogger().severe("For the developer of this plugin: make sure you have a config.yml");
|
||||||
|
e.printStackTrace();
|
||||||
|
Bukkit.getPluginManager().disablePlugin(this);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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 = new ArrayList<>(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,60 @@ 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();
|
||||||
|
|
||||||
|
Eco.get().unregisterCommand(this);
|
||||||
|
|
||||||
|
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 +143,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!");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 onRender((player, menu) -> menu.setState(player, Page.MAX_PAGE_KEY, pages.apply(player)));
|
return this.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 {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -83,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
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package com.willfp.eco.core.gui.slot;
|
package com.willfp.eco.core.gui.slot;
|
||||||
|
|
||||||
import com.willfp.eco.core.config.interfaces.Config;
|
import com.willfp.eco.core.config.interfaces.Config;
|
||||||
|
import com.willfp.eco.core.fast.FastItemStack;
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotHandler;
|
import com.willfp.eco.core.gui.slot.functional.SlotHandler;
|
||||||
import com.willfp.eco.core.items.Items;
|
import com.willfp.eco.core.items.Items;
|
||||||
import com.willfp.eco.util.StringUtils;
|
import com.willfp.eco.util.StringUtils;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.inventory.ClickType;
|
import org.bukkit.event.inventory.ClickType;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -37,7 +39,25 @@ public class ConfigSlot extends CustomSlot {
|
|||||||
public ConfigSlot(@NotNull final Config config) {
|
public ConfigSlot(@NotNull final Config config) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
|
||||||
SlotBuilder builder = Slot.builder(Items.lookup(config.getString("item")));
|
ItemStack item = Items.lookup(config.getString("item")).getItem();
|
||||||
|
|
||||||
|
SlotBuilder builder = Slot.builder((player, menu) -> {
|
||||||
|
if (!config.has("lore")) {
|
||||||
|
return item;
|
||||||
|
} else {
|
||||||
|
FastItemStack fast = FastItemStack.wrap(item.clone());
|
||||||
|
List<String> newLore = new ArrayList<>(fast.getLore());
|
||||||
|
newLore.addAll(
|
||||||
|
StringUtils.formatList(
|
||||||
|
config.getStrings("lore"),
|
||||||
|
player,
|
||||||
|
StringUtils.FormatOption.WITH_PLACEHOLDERS
|
||||||
|
)
|
||||||
|
);
|
||||||
|
fast.setLore(newLore);
|
||||||
|
return fast.unwrap();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
for (ClickType clickType : ClickType.values()) {
|
for (ClickType clickType : ClickType.values()) {
|
||||||
builder.onClick(
|
builder.onClick(
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import com.willfp.eco.core.gui.menu.Menu;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for custom slot implementations.
|
* Base class for custom slot implementations.
|
||||||
@@ -31,7 +32,7 @@ public abstract class CustomSlot implements Slot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ItemStack getItemStack(@NotNull final Player player) {
|
public final @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!");
|
||||||
}
|
}
|
||||||
@@ -40,8 +41,8 @@ public abstract class CustomSlot implements Slot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCaptive(@NotNull final Player player,
|
public final boolean isCaptive(@NotNull final Player player,
|
||||||
@NotNull final Menu menu) {
|
@NotNull final Menu menu) {
|
||||||
if (delegate == null) {
|
if (delegate == null) {
|
||||||
throw new IllegalStateException("Custom Slot was not initialized!");
|
throw new IllegalStateException("Custom Slot was not initialized!");
|
||||||
}
|
}
|
||||||
@@ -50,7 +51,18 @@ public abstract class CustomSlot implements Slot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isCaptiveFromEmpty() {
|
public final boolean isAllowedCaptive(@NotNull final Player player,
|
||||||
|
@NotNull final Menu menu,
|
||||||
|
@Nullable final ItemStack itemStack) {
|
||||||
|
if (delegate == null) {
|
||||||
|
throw new IllegalStateException("Custom Slot was not initialized!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return delegate.isAllowedCaptive(player, menu, itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final boolean isCaptiveFromEmpty() {
|
||||||
if (delegate == null) {
|
if (delegate == null) {
|
||||||
throw new IllegalStateException("Custom Slot was not initialized!");
|
throw new IllegalStateException("Custom Slot was not initialized!");
|
||||||
}
|
}
|
||||||
@@ -59,8 +71,8 @@ public abstract class CustomSlot 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 delegate;
|
return delegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for custom slot implementations.
|
* Base class for custom slot implementations.
|
||||||
@@ -29,19 +30,26 @@ 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
|
||||||
public boolean isCaptive(@NotNull final Player player,
|
public final boolean isCaptive(@NotNull final Player player,
|
||||||
@NotNull final Menu menu) {
|
@NotNull final Menu menu) {
|
||||||
return getSlot(player, menu).isCaptive(player, menu);
|
return getSlot(player, menu).isCaptive(player, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Slot getActionableSlot(@NotNull final Player player,
|
public final boolean isAllowedCaptive(@NotNull final Player player,
|
||||||
@NotNull final Menu menu) {
|
@NotNull final Menu menu,
|
||||||
|
@Nullable final ItemStack itemStack) {
|
||||||
|
return getSlot(player, menu).isAllowedCaptive(player, menu, itemStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final @NotNull Slot getActionableSlot(@NotNull final Player player,
|
||||||
|
@NotNull final Menu menu) {
|
||||||
return getSlot(player, menu);
|
return getSlot(player, menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import org.bukkit.Material;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
@@ -30,6 +31,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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -44,6 +46,20 @@ public interface Slot extends GUIComponent {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the slot allows a certain item to be placed in it.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param menu The menu.
|
||||||
|
* @param itemStack The item; use null if the item is unknown.
|
||||||
|
* @return If captive.
|
||||||
|
*/
|
||||||
|
default boolean isAllowedCaptive(@NotNull final Player player,
|
||||||
|
@NotNull final Menu menu,
|
||||||
|
@Nullable final ItemStack itemStack) {
|
||||||
|
return this.isCaptive(player, menu);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the actionable slot to be shown.
|
* Get the actionable slot to be shown.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -60,6 +76,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 +142,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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.willfp.eco.core.gui.slot;
|
package com.willfp.eco.core.gui.slot;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.gui.slot.functional.CaptiveFilter;
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotHandler;
|
import com.willfp.eco.core.gui.slot.functional.SlotHandler;
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotModifier;
|
import com.willfp.eco.core.gui.slot.functional.SlotModifier;
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotUpdater;
|
import com.willfp.eco.core.gui.slot.functional.SlotUpdater;
|
||||||
@@ -143,7 +144,17 @@ public interface SlotBuilder {
|
|||||||
* @param predicate The predicate. Returns true when the slot should not be captive.
|
* @param predicate The predicate. Returns true when the slot should not be captive.
|
||||||
* @return The builder.
|
* @return The builder.
|
||||||
*/
|
*/
|
||||||
SlotBuilder notCaptiveFor(@NotNull Predicate<Player> predicate);
|
SlotBuilder notCaptiveFor(@NotNull final Predicate<Player> predicate);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a whitelist for allowed captive items.
|
||||||
|
*
|
||||||
|
* @param filter The filter.
|
||||||
|
* @return The builder.
|
||||||
|
*/
|
||||||
|
default SlotBuilder setCaptiveFilter(@NotNull final CaptiveFilter filter) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the ItemStack updater.
|
* Set the ItemStack updater.
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.willfp.eco.core.gui.slot.functional;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.gui.menu.Menu;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface to test if a captive slot is allowed to contain an item given a player and a menu.
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface CaptiveFilter {
|
||||||
|
/**
|
||||||
|
* Get if allowed.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param menu The menu.
|
||||||
|
* @param itemStack The item.
|
||||||
|
* @return If captive.
|
||||||
|
*/
|
||||||
|
boolean isAllowed(@NotNull Player player,
|
||||||
|
@NotNull Menu menu,
|
||||||
|
@Nullable ItemStack itemStack);
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.willfp.eco.core.integrations.shop;
|
package com.willfp.eco.core.integrations.shop;
|
||||||
|
|
||||||
import com.willfp.eco.core.integrations.Integration;
|
import com.willfp.eco.core.integrations.Integration;
|
||||||
|
import com.willfp.eco.core.price.Price;
|
||||||
|
import com.willfp.eco.core.price.impl.PriceFree;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.Listener;
|
import org.bukkit.event.Listener;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@@ -29,12 +31,41 @@ public interface ShopIntegration extends Integration {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get if an item is sellable for a player.
|
||||||
|
*
|
||||||
|
* @param itemStack The item.
|
||||||
|
* @param player The player.
|
||||||
|
* @return If sellable.
|
||||||
|
*/
|
||||||
|
default boolean isSellable(@NotNull final ItemStack itemStack,
|
||||||
|
@NotNull final Player player) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of one of an item for a player.
|
||||||
|
* <p>
|
||||||
|
* For example, if you pass in a stack, it will only return the value of <b>one</b> item, not the full stack.
|
||||||
|
*
|
||||||
|
* @param itemStack The item.
|
||||||
|
* @param player The player.
|
||||||
|
* @return The price.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
default Price getUnitValue(@NotNull final ItemStack itemStack,
|
||||||
|
@NotNull final Player player) {
|
||||||
|
return new PriceFree();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the price of an item.
|
* Get the price of an item.
|
||||||
*
|
*
|
||||||
* @param itemStack The item.
|
* @param itemStack The item.
|
||||||
* @return The price.
|
* @return The price.
|
||||||
|
* @deprecated Use getValue instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.47.0", forRemoval = true)
|
||||||
default double getPrice(@NotNull final ItemStack itemStack) {
|
default double getPrice(@NotNull final ItemStack itemStack) {
|
||||||
// Do nothing unless overridden.
|
// Do nothing unless overridden.
|
||||||
return 0.0;
|
return 0.0;
|
||||||
@@ -46,9 +77,11 @@ public interface ShopIntegration extends Integration {
|
|||||||
* @param itemStack The item.
|
* @param itemStack The item.
|
||||||
* @param player The player.
|
* @param player The player.
|
||||||
* @return The price.
|
* @return The price.
|
||||||
|
* @deprecated Use getValue instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.47.0", forRemoval = true)
|
||||||
default double getPrice(@NotNull final ItemStack itemStack,
|
default double getPrice(@NotNull final ItemStack itemStack,
|
||||||
@NotNull final Player player) {
|
@NotNull final Player player) {
|
||||||
return getPrice(itemStack);
|
return getUnitValue(itemStack, player).getValue(player);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.willfp.eco.core.integrations.shop;
|
package com.willfp.eco.core.integrations.shop;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.price.Price;
|
||||||
|
import com.willfp.eco.core.price.impl.PriceFree;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -36,12 +38,57 @@ public final class ShopManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get if an item is sellable for a player.
|
||||||
|
*
|
||||||
|
* @param itemStack The item.
|
||||||
|
* @param player The player.
|
||||||
|
* @return If sellable.
|
||||||
|
*/
|
||||||
|
public static boolean isSellable(@Nullable final ItemStack itemStack,
|
||||||
|
@NotNull final Player player) {
|
||||||
|
if (itemStack == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ShopIntegration integration : REGISTERED) {
|
||||||
|
return integration.isSellable(itemStack, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of one of an item for a player.
|
||||||
|
* <p>
|
||||||
|
* For example, if you pass in a stack, it will only return the value of <b>one</b> item, not the full stack.
|
||||||
|
*
|
||||||
|
* @param itemStack The item.
|
||||||
|
* @param player The player.
|
||||||
|
* @return The price.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Price getUnitValue(@Nullable final ItemStack itemStack,
|
||||||
|
@NotNull final Player player) {
|
||||||
|
if (itemStack == null) {
|
||||||
|
return new PriceFree();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ShopIntegration integration : REGISTERED) {
|
||||||
|
return integration.getUnitValue(itemStack, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PriceFree();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the price of an item.
|
* Get the price of an item.
|
||||||
*
|
*
|
||||||
* @param itemStack The item.
|
* @param itemStack The item.
|
||||||
* @return The price.
|
* @return The price.
|
||||||
|
* @deprecated Use getValue instead. This will always return 0 as prices depend on players.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.47.0", forRemoval = true)
|
||||||
public static double getItemPrice(@Nullable final ItemStack itemStack) {
|
public static double getItemPrice(@Nullable final ItemStack itemStack) {
|
||||||
return getItemPrice(itemStack, null);
|
return getItemPrice(itemStack, null);
|
||||||
}
|
}
|
||||||
@@ -52,19 +99,17 @@ public final class ShopManager {
|
|||||||
* @param itemStack The item.
|
* @param itemStack The item.
|
||||||
* @param player The player.
|
* @param player The player.
|
||||||
* @return The price.
|
* @return The price.
|
||||||
|
* @deprecated Use getValue instead. Null players / null items will always return 0.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.47.0", forRemoval = true)
|
||||||
public static double getItemPrice(@Nullable final ItemStack itemStack,
|
public static double getItemPrice(@Nullable final ItemStack itemStack,
|
||||||
@Nullable final Player player) {
|
@Nullable final Player player) {
|
||||||
if (itemStack == null) {
|
if (itemStack == null || player == null) {
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ShopIntegration shopIntegration : REGISTERED) {
|
for (ShopIntegration shopIntegration : REGISTERED) {
|
||||||
if (player == null) {
|
return shopIntegration.getUnitValue(itemStack, player).getValue(player, itemStack.getAmount());
|
||||||
return shopIntegration.getPrice(itemStack);
|
|
||||||
} else {
|
|
||||||
return shopIntegration.getPrice(itemStack, player);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package com.willfp.eco.core.integrations.shop;
|
package com.willfp.eco.core.integrations.shop;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.price.Price;
|
||||||
|
import com.willfp.eco.core.price.impl.PriceEconomy;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
import org.bukkit.event.player.PlayerEvent;
|
import org.bukkit.event.player.PlayerEvent;
|
||||||
@@ -19,7 +21,12 @@ public class ShopSellEvent extends PlayerEvent {
|
|||||||
/**
|
/**
|
||||||
* The sell price.
|
* The sell price.
|
||||||
*/
|
*/
|
||||||
private double price;
|
private Price price;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The price multiplier.
|
||||||
|
*/
|
||||||
|
private double multiplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The item to be sold.
|
* The item to be sold.
|
||||||
@@ -33,31 +40,64 @@ public class ShopSellEvent extends PlayerEvent {
|
|||||||
* @param who The player.
|
* @param who The player.
|
||||||
* @param price The price.
|
* @param price The price.
|
||||||
* @param item The item.
|
* @param item The item.
|
||||||
|
* @deprecated Use the price system instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.47.0", forRemoval = true)
|
||||||
public ShopSellEvent(@NotNull final Player who,
|
public ShopSellEvent(@NotNull final Player who,
|
||||||
final double price,
|
final double price,
|
||||||
@Nullable final ItemStack item) {
|
@Nullable final ItemStack item) {
|
||||||
|
this(who, new PriceEconomy(price), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new shop sell event.
|
||||||
|
*
|
||||||
|
* @param who The player.
|
||||||
|
* @param price The price.
|
||||||
|
* @param item The item.
|
||||||
|
*/
|
||||||
|
public ShopSellEvent(@NotNull final Player who,
|
||||||
|
@NotNull final Price price,
|
||||||
|
@Nullable final ItemStack item) {
|
||||||
|
this(who, price, item, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create new shop sell event.
|
||||||
|
*
|
||||||
|
* @param who The player.
|
||||||
|
* @param price The price.
|
||||||
|
* @param item The item.
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
*/
|
||||||
|
public ShopSellEvent(@NotNull final Player who,
|
||||||
|
@NotNull final Price price,
|
||||||
|
@Nullable final ItemStack item,
|
||||||
|
final double multiplier) {
|
||||||
super(who);
|
super(who);
|
||||||
|
|
||||||
this.price = price;
|
this.price = price;
|
||||||
this.item = item;
|
this.item = item;
|
||||||
|
|
||||||
|
this.multiplier = multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the price.
|
* Get the value.
|
||||||
*
|
*
|
||||||
* @return The price.
|
* @return The value.
|
||||||
*/
|
*/
|
||||||
public double getPrice() {
|
@NotNull
|
||||||
|
public Price getValue() {
|
||||||
return this.price;
|
return this.price;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the price.
|
* Set the value.
|
||||||
*
|
*
|
||||||
* @param price The price.
|
* @param price The value.
|
||||||
*/
|
*/
|
||||||
public void setPrice(final double price) {
|
public void setValue(@NotNull final Price price) {
|
||||||
this.price = price;
|
this.price = price;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,6 +121,46 @@ public class ShopSellEvent extends PlayerEvent {
|
|||||||
return item != null;
|
return item != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the price multiplier.
|
||||||
|
*
|
||||||
|
* @return The multiplier.
|
||||||
|
*/
|
||||||
|
public double getMultiplier() {
|
||||||
|
return multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the price multiplier.
|
||||||
|
*
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
*/
|
||||||
|
public void setMultiplier(final double multiplier) {
|
||||||
|
this.multiplier = multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the price.
|
||||||
|
*
|
||||||
|
* @return The price.
|
||||||
|
* @deprecated Use the price system instead.
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "6.47.0", forRemoval = true)
|
||||||
|
public double getPrice() {
|
||||||
|
return this.getValue().getValue(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the price.
|
||||||
|
*
|
||||||
|
* @param price The price.
|
||||||
|
* @deprecated Use the price system instead.
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "6.47.0", forRemoval = true)
|
||||||
|
public void setPrice(final double price) {
|
||||||
|
this.setValue(new PriceEconomy(price));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bukkit parity.
|
* Bukkit parity.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ public abstract class AbstractItemStackBuilder<T extends ItemMeta, U extends Abs
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public U setAmount(final int amount) {
|
public U setAmount(final int amount) {
|
||||||
Validate.isTrue(amount >= 1 && amount <= base.getMaxStackSize());
|
Validate.isTrue(amount >= 1);
|
||||||
base.setAmount(amount);
|
base.setAmount(amount);
|
||||||
return (U) this;
|
return (U) this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,4 +44,20 @@ public record MathContext(
|
|||||||
Collections.emptyList()
|
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,156 @@
|
|||||||
|
package com.willfp.eco.core.price;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A group of {@link ConfiguredPrice}s in order to show them
|
||||||
|
* to players in one go.
|
||||||
|
*/
|
||||||
|
public final class CombinedDisplayPrice {
|
||||||
|
/**
|
||||||
|
* Maps configured prices to multipliers.
|
||||||
|
*/
|
||||||
|
private final Map<ConfiguredPrice, Double> prices;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The player to format for.
|
||||||
|
*/
|
||||||
|
private final Player player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a new combined price mapping formatters to multipliers.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param prices The prices.
|
||||||
|
*/
|
||||||
|
private CombinedDisplayPrice(@NotNull final Player player,
|
||||||
|
@NotNull final Map<ConfiguredPrice, Double> prices) {
|
||||||
|
this.player = player;
|
||||||
|
this.prices = prices;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the display strings.
|
||||||
|
*
|
||||||
|
* @return The display strings.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public String[] getDisplayStrings() {
|
||||||
|
List<String> displayStrings = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Map.Entry<ConfiguredPrice, Double> entry : prices.entrySet()) {
|
||||||
|
displayStrings.add(entry.getKey().getDisplay(player, entry.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return displayStrings.toArray(new String[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The builder.
|
||||||
|
*/
|
||||||
|
public static class Builder {
|
||||||
|
/**
|
||||||
|
* All multiplied prices.
|
||||||
|
*/
|
||||||
|
private final List<MultipliedPrice> prices = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The player.
|
||||||
|
*/
|
||||||
|
private final Player player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new builder.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
*/
|
||||||
|
Builder(@NotNull final Player player) {
|
||||||
|
this.player = player;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new price with a certain multiplier.
|
||||||
|
*
|
||||||
|
* @param price The price.
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
* @return The builder.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Builder add(@NotNull final ConfiguredPrice price,
|
||||||
|
final double multiplier) {
|
||||||
|
prices.add(new MultipliedPrice(price, multiplier));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new price.
|
||||||
|
*
|
||||||
|
* @param price The price.
|
||||||
|
* @return The builder.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public Builder add(@NotNull final ConfiguredPrice price) {
|
||||||
|
return this.add(price, 1D);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build into a {@link CombinedDisplayPrice}.
|
||||||
|
*
|
||||||
|
* @return The combined price.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public CombinedDisplayPrice build() {
|
||||||
|
Map<ConfiguredPrice, Double> unitPrices = new HashMap<>();
|
||||||
|
|
||||||
|
// Take first configured price at each ID as the format for all prices with that ID.
|
||||||
|
for (MultipliedPrice price : prices) {
|
||||||
|
// Find the base price.
|
||||||
|
ConfiguredPrice base = unitPrices.keySet()
|
||||||
|
.stream()
|
||||||
|
.filter(it -> it.getIdentifier().equals(price.price().getIdentifier()))
|
||||||
|
.findFirst()
|
||||||
|
.orElse(price.price());
|
||||||
|
|
||||||
|
// Find the multiplier for a value of 1, e.g. a price that's worth 20 will be 0.05.
|
||||||
|
double unitMultiplier = 1 / base.getValue(player);
|
||||||
|
|
||||||
|
double currentMultiplier = unitPrices.getOrDefault(base, 0D);
|
||||||
|
currentMultiplier += unitMultiplier * price.price().getValue(player, price.multiplier());
|
||||||
|
unitPrices.put(base, currentMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new CombinedDisplayPrice(player, unitPrices);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A price with a multiplier.
|
||||||
|
*
|
||||||
|
* @param price The price.
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
*/
|
||||||
|
private record MultipliedPrice(
|
||||||
|
@NotNull ConfiguredPrice price,
|
||||||
|
double multiplier
|
||||||
|
) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new builder for a player.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @return The builder.
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public static Builder builder(@NotNull final Player player) {
|
||||||
|
return new Builder(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,177 @@
|
|||||||
|
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.
|
||||||
|
*/
|
||||||
|
public 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,
|
||||||
|
final double multiplier) {
|
||||||
|
return this.price.canAfford(player, multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void pay(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
this.price.pay(player, multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void giveTo(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
this.price.giveTo(player, multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
return this.price.getValue(player, multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return this.price.getIdentifier();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 this.getDisplay(player, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the display string for a player.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
* @return The display string.
|
||||||
|
*/
|
||||||
|
public String getDisplay(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
return StringUtils.format(
|
||||||
|
formatString.replace("%value%", NumberUtils.format(this.getPrice().getValue(player, multiplier))),
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,34 +1,159 @@
|
|||||||
package com.willfp.eco.core.price;
|
package com.willfp.eco.core.price;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.NotImplementedException;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A price that a player should pay.
|
* A price that a player should pay.
|
||||||
|
* <p>
|
||||||
|
* There are important implementation details:
|
||||||
|
* <p>
|
||||||
|
* For backwards compatibility, all methods are default, however you must override the following:
|
||||||
|
* <ul>
|
||||||
|
* <li><code>canAfford(Player, double)</code></li>
|
||||||
|
* <li><code>pay(Player, double)</code></li>
|
||||||
|
* <li><code>giveTo(Player, double)</code></li>
|
||||||
|
* <li><code>getValue(Player, double)</code></li>
|
||||||
|
* <li><code>getMultiplier(Player)</code></li>
|
||||||
|
* <li><code>setMultiplier(Player, double)</code></li>
|
||||||
|
* </ul>
|
||||||
|
* Otherwise, your implementation will throw {@link NotImplementedException}.
|
||||||
|
* <p>
|
||||||
|
* Also, getValue() should always return the value with player multipliers applied.
|
||||||
*/
|
*/
|
||||||
public interface Price {
|
public interface Price {
|
||||||
/**
|
/**
|
||||||
* Get if the player can afford the price.
|
* Get if a player can afford to pay the price.
|
||||||
*
|
*
|
||||||
* @param player The player.
|
* @param player The player.
|
||||||
* @return If the player can afford.
|
* @return If the player can afford.
|
||||||
*/
|
*/
|
||||||
boolean canAfford(@NotNull Player player);
|
default boolean canAfford(@NotNull final Player player) {
|
||||||
|
return this.canAfford(player, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get if a player can afford to pay x times the price.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
* @return If the player can afford.
|
||||||
|
*/
|
||||||
|
default boolean canAfford(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
throw new NotImplementedException("Override canAfford(Player, double) in your Price implementation!");
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make the player pay the price.
|
* Make the player pay the price.
|
||||||
* <p>
|
* <p>
|
||||||
* Only run this if the player can afford the price.
|
* Check canAfford first.
|
||||||
*
|
*
|
||||||
* @param player The player.
|
* @param player The player.
|
||||||
*/
|
*/
|
||||||
void pay(@NotNull Player player);
|
default void pay(@NotNull final Player player) {
|
||||||
|
this.pay(player, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make the player pay the price x times.
|
||||||
|
* <p>
|
||||||
|
* Check canAfford first.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
*/
|
||||||
|
default void pay(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
throw new NotImplementedException("Override pay(Player, double) in your Price implementation!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give the price to the player.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
*/
|
||||||
|
default void giveTo(@NotNull final Player player) {
|
||||||
|
this.giveTo(player, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Give the price to the player x times.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
*/
|
||||||
|
default void giveTo(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
throw new NotImplementedException("Override giveTo(Player, double) in your Price implementation!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the numerical value that backs this price.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @return The value.
|
||||||
|
*/
|
||||||
|
default double getValue(@NotNull final Player player) {
|
||||||
|
return getValue(player, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the numeral value that backs this price multiplied x times.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
* @return The value.
|
||||||
|
*/
|
||||||
|
default double getValue(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
throw new NotImplementedException("Override getValue(Player, double) in your Price implementation!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value multiplier for the player.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @return The multiplier.
|
||||||
|
*/
|
||||||
|
default double getMultiplier(@NotNull final Player player) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the value multiplier for the player.
|
||||||
|
*
|
||||||
|
* @param player The player.
|
||||||
|
* @param multiplier The multiplier.
|
||||||
|
*/
|
||||||
|
default void setMultiplier(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
throw new NotImplementedException("Override setMultiplier(Player, double) in your Price implementation!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the identifier of this price (as type/instance checks break with delegation,
|
||||||
|
* this is used for combining prices, etc.)
|
||||||
|
* <p>
|
||||||
|
* By default, this uses the class name, but it's good practice to override this.
|
||||||
|
* <p>
|
||||||
|
* It's also good practice to prefix your identifiers with some kind of namespace or
|
||||||
|
* internal ID, in order to prevent conflicts.
|
||||||
|
*
|
||||||
|
* @return The identifier.
|
||||||
|
*/
|
||||||
|
default String getIdentifier() {
|
||||||
|
return this.getClass().getName();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the price is backed by a value, get it here.
|
* If the price is backed by a value, get it here.
|
||||||
*
|
*
|
||||||
* @return The value.
|
* @return The value.
|
||||||
|
* @deprecated Use getValue(Player) instead.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.45.0", forRemoval = true)
|
||||||
default double getValue() {
|
default double getValue() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -37,7 +162,9 @@ public interface Price {
|
|||||||
* If the price is backed by a value, set it here.
|
* If the price is backed by a value, set it here.
|
||||||
*
|
*
|
||||||
* @param value The value.
|
* @param value The value.
|
||||||
|
* @deprecated Values shouldn't be fixed. This method should never work.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(since = "6.45.0", forRemoval = true)
|
||||||
default void setValue(final double value) {
|
default void setValue(final double value) {
|
||||||
// Override when needed.
|
// Override when needed.
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
package com.willfp.eco.core.price;
|
package com.willfp.eco.core.price;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.math.MathContext;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create prices.
|
* Create prices.
|
||||||
|
* <p>
|
||||||
|
* You must override one of the create methods.
|
||||||
*/
|
*/
|
||||||
public interface PriceFactory {
|
public interface PriceFactory {
|
||||||
/**
|
/**
|
||||||
@@ -23,5 +28,19 @@ public interface PriceFactory {
|
|||||||
* @param value The value.
|
* @param value The value.
|
||||||
* @return The price.
|
* @return The price.
|
||||||
*/
|
*/
|
||||||
@NotNull Price create(double value);
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage prices.
|
* Class to manage prices.
|
||||||
@@ -65,18 +66,18 @@ public final class Prices {
|
|||||||
public static Price create(@NotNull final String expression,
|
public static Price create(@NotNull final String expression,
|
||||||
@Nullable final String priceName,
|
@Nullable final String priceName,
|
||||||
@NotNull final MathContext context) {
|
@NotNull final MathContext context) {
|
||||||
double value = NumberUtils.evaluateExpression(
|
Function<MathContext, Double> function = (ctx) -> NumberUtils.evaluateExpression(
|
||||||
expression,
|
expression,
|
||||||
context
|
ctx
|
||||||
);
|
);
|
||||||
|
|
||||||
if (value <= 0) {
|
if (function.apply(context) <= 0) {
|
||||||
return new PriceFree();
|
return new PriceFree();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default to economy
|
// Default to economy
|
||||||
if (priceName == null) {
|
if (priceName == null) {
|
||||||
return new PriceEconomy(value);
|
return new PriceEconomy(context, function);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find price factory
|
// Find price factory
|
||||||
@@ -90,9 +91,9 @@ public final class Prices {
|
|||||||
return new PriceFree();
|
return new PriceFree();
|
||||||
}
|
}
|
||||||
|
|
||||||
return new PriceItem((int) Math.round(value), item);
|
return new PriceItem(context, function, item);
|
||||||
} else {
|
} else {
|
||||||
return factory.create(value);
|
return factory.create(context, function);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
package com.willfp.eco.core.price.impl;
|
package com.willfp.eco.core.price.impl;
|
||||||
|
|
||||||
import com.willfp.eco.core.integrations.economy.EconomyManager;
|
import com.willfp.eco.core.integrations.economy.EconomyManager;
|
||||||
|
import com.willfp.eco.core.math.MathContext;
|
||||||
import com.willfp.eco.core.price.Price;
|
import com.willfp.eco.core.price.Price;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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.)
|
* Economy-based price (for Vault, Treasury, etc.)
|
||||||
*/
|
*/
|
||||||
@@ -12,7 +18,17 @@ public final class PriceEconomy implements Price {
|
|||||||
/**
|
/**
|
||||||
* The value of the price.
|
* The value of the price.
|
||||||
*/
|
*/
|
||||||
private double value;
|
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.
|
* Create a new economy-based price.
|
||||||
@@ -20,26 +36,58 @@ public final class PriceEconomy implements Price {
|
|||||||
* @param value The value.
|
* @param value The value.
|
||||||
*/
|
*/
|
||||||
public PriceEconomy(final double value) {
|
public PriceEconomy(final double value) {
|
||||||
this.value = 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
|
@Override
|
||||||
public boolean canAfford(@NotNull Player player) {
|
public boolean canAfford(@NotNull final Player player,
|
||||||
return EconomyManager.getBalance(player) >= value;
|
final double multiplier) {
|
||||||
|
return EconomyManager.getBalance(player) >= getValue(player, multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pay(@NotNull Player player) {
|
public void pay(@NotNull final Player player,
|
||||||
EconomyManager.removeMoney(player, value);
|
final double multiplier) {
|
||||||
|
EconomyManager.removeMoney(player, getValue(player, multiplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getValue() {
|
public void giveTo(@NotNull final Player player,
|
||||||
return value;
|
final double multiplier) {
|
||||||
|
EconomyManager.giveMoney(player, getValue(player, multiplier));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setValue(final double value) {
|
public double getValue(@NotNull final Player player,
|
||||||
this.value = value;
|
final double multiplier) {
|
||||||
|
return this.function.apply(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player) * multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return "eco:economy";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,42 @@ public final class PriceFree implements Price {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canAfford(@NotNull Player player) {
|
public boolean canAfford(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pay(@NotNull Player player) {
|
public void pay(@NotNull final Player player,
|
||||||
// Do nothing.
|
final double multiplier) {
|
||||||
|
// Nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void giveTo(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
// Nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMultiplier(@NotNull final Player player) {
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMultiplier(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
// Nothing.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return "eco:free";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,33 @@
|
|||||||
package com.willfp.eco.core.price.impl;
|
package com.willfp.eco.core.price.impl;
|
||||||
|
|
||||||
|
import com.willfp.eco.core.drops.DropQueue;
|
||||||
|
import com.willfp.eco.core.items.HashedItem;
|
||||||
import com.willfp.eco.core.items.TestableItem;
|
import com.willfp.eco.core.items.TestableItem;
|
||||||
|
import com.willfp.eco.core.math.MathContext;
|
||||||
import com.willfp.eco.core.price.Price;
|
import com.willfp.eco.core.price.Price;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
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.
|
* Item-based price.
|
||||||
*/
|
*/
|
||||||
public final class PriceItem implements Price {
|
public final class PriceItem implements Price {
|
||||||
|
/**
|
||||||
|
* The base MathContext.
|
||||||
|
*/
|
||||||
|
private final MathContext baseContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The amount of items.
|
* The amount of items.
|
||||||
*/
|
*/
|
||||||
private final int amountToRemove;
|
private final Function<MathContext, Double> function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The item.
|
* The item.
|
||||||
@@ -22,14 +35,33 @@ public final class PriceItem implements Price {
|
|||||||
private final TestableItem item;
|
private final TestableItem item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new economy-based price.
|
* The multipliers.
|
||||||
|
*/
|
||||||
|
private final Map<UUID, Double> multipliers = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new item-based price.
|
||||||
*
|
*
|
||||||
* @param amount The amount.
|
* @param amount The amount.
|
||||||
* @param item The item.
|
* @param item The item.
|
||||||
*/
|
*/
|
||||||
public PriceItem(final int amount,
|
public PriceItem(final int amount,
|
||||||
@NotNull final TestableItem item) {
|
@NotNull final TestableItem item) {
|
||||||
this.amountToRemove = Math.max(0, amount);
|
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;
|
this.item = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,8 +75,10 @@ public final class PriceItem implements Price {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canAfford(@NotNull Player player) {
|
public boolean canAfford(@NotNull final Player player,
|
||||||
if (amountToRemove == 0) {
|
final double multiplier) {
|
||||||
|
int toRemove = (int) getValue(player, multiplier);
|
||||||
|
if (toRemove <= 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,26 +90,28 @@ public final class PriceItem implements Price {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return count >= amountToRemove;
|
return count >= toRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pay(@NotNull Player player) {
|
public void pay(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
int toRemove = (int) getValue(player, multiplier);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
||||||
for (ItemStack itemStack : player.getInventory().getContents()) {
|
for (ItemStack itemStack : player.getInventory().getContents()) {
|
||||||
if (count >= amountToRemove) {
|
if (count >= toRemove) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.matches(itemStack)) {
|
if (item.matches(itemStack)) {
|
||||||
int itemAmount = itemStack.getAmount();
|
int itemAmount = itemStack.getAmount();
|
||||||
|
|
||||||
if (itemAmount > amountToRemove) {
|
if (itemAmount > toRemove) {
|
||||||
itemStack.setAmount(itemAmount - amountToRemove);
|
itemStack.setAmount(itemAmount - toRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (itemAmount <= amountToRemove) {
|
if (itemAmount <= toRemove) {
|
||||||
itemStack.setAmount(0);
|
itemStack.setAmount(0);
|
||||||
itemStack.setType(Material.AIR);
|
itemStack.setType(Material.AIR);
|
||||||
}
|
}
|
||||||
@@ -84,4 +120,41 @@ public final class PriceItem implements Price {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void giveTo(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
ItemStack itemStack = item.getItem().clone();
|
||||||
|
itemStack.setAmount((int) getValue(player, multiplier));
|
||||||
|
|
||||||
|
new DropQueue(player)
|
||||||
|
.addItem(itemStack)
|
||||||
|
.forceTelekinesis()
|
||||||
|
.push();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue(@NotNull final Player player,
|
||||||
|
final double multiplier) {
|
||||||
|
return Math.toIntExact(Math.round(
|
||||||
|
this.function.apply(MathContext.copyWithPlayer(baseContext, player))
|
||||||
|
* getMultiplier(player) * multiplier
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
|
return "eco:item-" + HashedItem.of(this.item.getItem()).getHash();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ public final class ProxyConstants {
|
|||||||
"v1_17_R1",
|
"v1_17_R1",
|
||||||
"v1_18_R1",
|
"v1_18_R1",
|
||||||
"v1_18_R2",
|
"v1_18_R2",
|
||||||
"v1_19_R1"
|
"v1_19_R1",
|
||||||
|
"v1_19_R2"
|
||||||
);
|
);
|
||||||
|
|
||||||
private ProxyConstants() {
|
private ProxyConstants() {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,6 +74,10 @@ fun SlotBuilder.onClick(clickType: ClickType, action: (Player, InventoryClickEve
|
|||||||
fun SlotBuilder.notCaptiveFor(test: (Player) -> Boolean): SlotBuilder =
|
fun SlotBuilder.notCaptiveFor(test: (Player) -> Boolean): SlotBuilder =
|
||||||
this.notCaptiveFor { test(it) }
|
this.notCaptiveFor { test(it) }
|
||||||
|
|
||||||
|
/** @see SlotBuilder.setCaptiveFilter */
|
||||||
|
fun SlotBuilder.setCaptiveFilter(test: (Player, Menu, ItemStack?) -> Boolean): SlotBuilder =
|
||||||
|
this.setCaptiveFilter { a, b, c -> test(a, b, c) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see SlotBuilder.setModifier
|
* @see SlotBuilder.setModifier
|
||||||
* @deprecated Use SlotUpdater instead.
|
* @deprecated Use SlotUpdater instead.
|
||||||
@@ -184,6 +188,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,
|
||||||
|
|||||||
@@ -2,13 +2,31 @@
|
|||||||
|
|
||||||
package com.willfp.eco.core.integrations.shop
|
package com.willfp.eco.core.integrations.shop
|
||||||
|
|
||||||
|
import com.willfp.eco.core.price.Price
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
|
|
||||||
/** @see ShopManager.getItemPrice **/
|
/** @see ShopManager.getItemPrice * */
|
||||||
|
@Deprecated(
|
||||||
|
"Prices depend on players, this will always return 0.",
|
||||||
|
level = DeprecationLevel.ERROR,
|
||||||
|
replaceWith = ReplaceWith("this.getValue(player)")
|
||||||
|
)
|
||||||
val ItemStack.price: Double
|
val ItemStack.price: Double
|
||||||
get() = ShopManager.getItemPrice(this)
|
get() = 0.0
|
||||||
|
|
||||||
/** @see ShopManager.getItemPrice **/
|
/** @see ShopManager.getItemPrice * */
|
||||||
|
@Deprecated(
|
||||||
|
"Use the price system instead, prices may not be currencies.",
|
||||||
|
ReplaceWith("this.getValue(player)"),
|
||||||
|
)
|
||||||
fun ItemStack.getPrice(player: Player): Double =
|
fun ItemStack.getPrice(player: Player): Double =
|
||||||
ShopManager.getItemPrice(this, player)
|
this.getUnitValue(player).getValue(player, this.amount.toDouble())
|
||||||
|
|
||||||
|
/** @see ShopManager.getUnitValue */
|
||||||
|
fun ItemStack.getUnitValue(player: Player): Price =
|
||||||
|
ShopManager.getUnitValue(this, player)
|
||||||
|
|
||||||
|
/** @see ShopManager.isSellable */
|
||||||
|
fun ItemStack?.isSellable(player: Player): Boolean =
|
||||||
|
ShopManager.isSellable(this, player)
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -39,7 +39,7 @@ class EcoMenu(
|
|||||||
override fun getSlot(row: Int, column: Int): Slot =
|
override fun getSlot(row: Int, column: Int): Slot =
|
||||||
getPossiblyReactiveSlot(row, column, 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)
|
getPossiblyReactiveSlot(row, column, player)
|
||||||
|
|
||||||
override fun open(player: Player): Inventory {
|
override fun open(player: Player): Inventory {
|
||||||
|
|||||||
@@ -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,6 +81,11 @@ 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
|
||||||
@@ -122,7 +128,7 @@ class EcoMenuBuilder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return EcoMenu(
|
val menu = EcoMenu(
|
||||||
rows,
|
rows,
|
||||||
columns,
|
columns,
|
||||||
layeredComponents,
|
layeredComponents,
|
||||||
@@ -133,5 +139,9 @@ class EcoMenuBuilder(
|
|||||||
menuEventHandlers,
|
menuEventHandlers,
|
||||||
allowsChangingHeldItem
|
allowsChangingHeldItem
|
||||||
)
|
)
|
||||||
|
|
||||||
|
onBuild.forEach { it(menu) } // Run on build functions.
|
||||||
|
|
||||||
|
return menu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
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
|
||||||
|
import com.willfp.eco.util.openMenu
|
||||||
import org.bukkit.entity.Player
|
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
|
||||||
@@ -31,16 +33,22 @@ class RenderedInventory(
|
|||||||
val state = mutableMapOf<String, Any?>()
|
val state = mutableMapOf<String, Any?>()
|
||||||
|
|
||||||
fun render() {
|
fun render() {
|
||||||
val previousCaptive = captiveItems.toMap()
|
// This can happen when opening menus from other menus,
|
||||||
|
// fixing a bug where multiple paginated menus on top of
|
||||||
|
// each other caused bugs with page changer display.
|
||||||
|
if (this.menu != player.openMenu) {
|
||||||
|
MenuHandler.unregisterInventory(this.inventory)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
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)) {
|
||||||
@@ -48,11 +56,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 {
|
||||||
@@ -61,6 +69,24 @@ 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
|
// Run second render if captive items changed
|
||||||
@@ -69,7 +95,7 @@ class RenderedInventory(
|
|||||||
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)
|
||||||
val renderedItem = slot.getItemStack(player)
|
val renderedItem = slot.getItemStack(player)
|
||||||
|
|
||||||
if (!slot.isCaptive(player, menu)) {
|
if (!slot.isCaptive(player, menu)) {
|
||||||
@@ -87,7 +113,7 @@ class RenderedInventory(
|
|||||||
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,20 +1,24 @@
|
|||||||
package com.willfp.eco.internal.gui.slot
|
package com.willfp.eco.internal.gui.slot
|
||||||
|
|
||||||
import com.willfp.eco.core.gui.menu.Menu
|
import com.willfp.eco.core.gui.menu.Menu
|
||||||
|
import com.willfp.eco.core.gui.slot.functional.CaptiveFilter
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotHandler
|
import com.willfp.eco.core.gui.slot.functional.SlotHandler
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
||||||
import com.willfp.eco.util.toSingletonList
|
import com.willfp.eco.util.toSingletonList
|
||||||
|
import org.bukkit.Material
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.event.inventory.ClickType
|
import org.bukkit.event.inventory.ClickType
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
|
||||||
class EcoCaptiveSlot(
|
class EcoCaptiveSlot(
|
||||||
provider: SlotProvider,
|
provider: SlotProvider,
|
||||||
private val captiveFromEmpty: Boolean,
|
private val captiveFromEmpty: Boolean,
|
||||||
private val notCaptiveFor: (Player) -> Boolean
|
private val notCaptiveFor: (Player) -> Boolean,
|
||||||
|
private val filter: CaptiveFilter
|
||||||
) : EcoSlot(
|
) : EcoSlot(
|
||||||
provider,
|
provider,
|
||||||
ClickType.values().associateWith {
|
ClickType.values().associateWith {
|
||||||
captiveWithTest(notCaptiveFor).toSingletonList()
|
captiveWithTest(notCaptiveFor, filter).toSingletonList()
|
||||||
},
|
},
|
||||||
{ _, _, prev -> prev }
|
{ _, _, prev -> prev }
|
||||||
) {
|
) {
|
||||||
@@ -22,13 +26,25 @@ class EcoCaptiveSlot(
|
|||||||
return !notCaptiveFor(player)
|
return !notCaptiveFor(player)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun isAllowedCaptive(player: Player, menu: Menu, itemStack: ItemStack?): Boolean {
|
||||||
|
return filter.isAllowed(player, menu, itemStack)
|
||||||
|
}
|
||||||
|
|
||||||
override fun isCaptiveFromEmpty(): Boolean {
|
override fun isCaptiveFromEmpty(): Boolean {
|
||||||
return captiveFromEmpty
|
return captiveFromEmpty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun captiveWithTest(test: (Player) -> Boolean): SlotHandler {
|
private fun captiveWithTest(
|
||||||
return SlotHandler { event, _, _ ->
|
notCaptiveFor: (Player) -> Boolean,
|
||||||
event.isCancelled = test(event.whoClicked as Player)
|
filter: CaptiveFilter
|
||||||
}
|
): SlotHandler = SlotHandler { event, _, menu ->
|
||||||
|
val player = event.whoClicked as Player
|
||||||
|
|
||||||
|
val item = event.currentItem.nullIfAir() ?: event.cursor.nullIfAir()
|
||||||
|
|
||||||
|
event.isCancelled = !filter.isAllowed(player, menu, item) || notCaptiveFor(player)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun ItemStack?.nullIfAir(): ItemStack? =
|
||||||
|
if (this?.type == Material.AIR) null else this
|
||||||
|
|||||||
@@ -33,9 +33,5 @@ open class EcoSlot(
|
|||||||
return updater.update(player, menu, base) ?: return ItemStack(Material.AIR)
|
return updater.update(player, menu, base) ?: return ItemStack(Material.AIR)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isCaptive(player: Player, menu: Menu): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getActionableSlot(player: Player, menu: Menu): EcoSlot = this
|
override fun getActionableSlot(player: Player, menu: Menu): EcoSlot = this
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.willfp.eco.internal.gui.slot
|
|||||||
|
|
||||||
import com.willfp.eco.core.gui.slot.Slot
|
import com.willfp.eco.core.gui.slot.Slot
|
||||||
import com.willfp.eco.core.gui.slot.SlotBuilder
|
import com.willfp.eco.core.gui.slot.SlotBuilder
|
||||||
|
import com.willfp.eco.core.gui.slot.functional.CaptiveFilter
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotHandler
|
import com.willfp.eco.core.gui.slot.functional.SlotHandler
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
||||||
import com.willfp.eco.core.gui.slot.functional.SlotUpdater
|
import com.willfp.eco.core.gui.slot.functional.SlotUpdater
|
||||||
@@ -16,7 +17,9 @@ class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
|
|||||||
|
|
||||||
private val handlers = mutableMapOf<ClickType, MutableList<SlotHandler>>()
|
private val handlers = mutableMapOf<ClickType, MutableList<SlotHandler>>()
|
||||||
|
|
||||||
private var notCaptiveFor: (Player) -> Boolean = { false }
|
private var captiveFilter =
|
||||||
|
CaptiveFilter { _, _, _ -> true }
|
||||||
|
private var notCaptiveFor: (Player) -> Boolean = { _ -> false}
|
||||||
|
|
||||||
override fun onClick(type: ClickType, action: SlotHandler): SlotBuilder {
|
override fun onClick(type: ClickType, action: SlotHandler): SlotBuilder {
|
||||||
handlers.computeIfAbsent(type) { mutableListOf() } += action
|
handlers.computeIfAbsent(type) { mutableListOf() } += action
|
||||||
@@ -24,7 +27,12 @@ class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun notCaptiveFor(predicate: Predicate<Player>): SlotBuilder {
|
override fun notCaptiveFor(predicate: Predicate<Player>): SlotBuilder {
|
||||||
notCaptiveFor = { predicate.test(it) }
|
notCaptiveFor = { player -> predicate.test(player) }
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setCaptiveFilter(filter: CaptiveFilter): SlotBuilder {
|
||||||
|
captiveFilter = filter
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +52,8 @@ class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
|
|||||||
EcoCaptiveSlot(
|
EcoCaptiveSlot(
|
||||||
provider,
|
provider,
|
||||||
captiveFromEmpty,
|
captiveFromEmpty,
|
||||||
notCaptiveFor
|
notCaptiveFor,
|
||||||
|
captiveFilter
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
EcoSlot(
|
EcoSlot(
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.willfp.eco.internal.price
|
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.Price
|
||||||
import com.willfp.eco.core.price.PriceFactory
|
import com.willfp.eco.core.price.PriceFactory
|
||||||
import com.willfp.eco.core.price.impl.PriceEconomy
|
import com.willfp.eco.core.price.impl.PriceEconomy
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
object PriceFactoryEconomy : PriceFactory {
|
object PriceFactoryEconomy : PriceFactory {
|
||||||
override fun getNames() = listOf(
|
override fun getNames() = listOf(
|
||||||
@@ -10,5 +12,7 @@ object PriceFactoryEconomy : PriceFactory {
|
|||||||
"$"
|
"$"
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun create(value: Double): Price = PriceEconomy(value)
|
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||||
|
return PriceEconomy(baseContext, function)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package com.willfp.eco.internal.price
|
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.Price
|
||||||
import com.willfp.eco.core.price.PriceFactory
|
import com.willfp.eco.core.price.PriceFactory
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.function.Function
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
object PriceFactoryXP : PriceFactory {
|
object PriceFactoryXP : PriceFactory {
|
||||||
@@ -12,15 +15,40 @@ object PriceFactoryXP : PriceFactory {
|
|||||||
"experience"
|
"experience"
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun create(value: Double): Price = PriceXP(value.roundToInt())
|
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||||
|
return PriceXP(baseContext) { function.apply(it).roundToInt() }
|
||||||
|
}
|
||||||
|
|
||||||
private class PriceXP(
|
private class PriceXP(
|
||||||
private val xp: Int
|
private val baseContext: MathContext,
|
||||||
|
private val xp: (MathContext) -> Int
|
||||||
) : Price {
|
) : Price {
|
||||||
override fun canAfford(player: Player) = player.totalExperience >= xp
|
private val multipliers = mutableMapOf<UUID, Double>()
|
||||||
|
|
||||||
|
override fun canAfford(player: Player) = player.totalExperience >= getValue(player)
|
||||||
|
|
||||||
override fun pay(player: Player) {
|
override fun pay(player: Player) {
|
||||||
player.totalExperience -= xp
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIdentifier(): String {
|
||||||
|
return "eco:xp"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
package com.willfp.eco.internal.price
|
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.Price
|
||||||
import com.willfp.eco.core.price.PriceFactory
|
import com.willfp.eco.core.price.PriceFactory
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.function.Function
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
object PriceFactoryXPLevels : PriceFactory {
|
object PriceFactoryXPLevels : PriceFactory {
|
||||||
@@ -13,15 +16,40 @@ object PriceFactoryXPLevels : PriceFactory {
|
|||||||
"explevels",
|
"explevels",
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun create(value: Double): Price = PriceXPLevel(value.roundToInt())
|
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||||
|
return PriceXPLevel(baseContext) { function.apply(it).roundToInt() }
|
||||||
|
}
|
||||||
|
|
||||||
private class PriceXPLevel(
|
private class PriceXPLevel(
|
||||||
private val levels: Int
|
private val baseContext: MathContext,
|
||||||
|
private val level: (MathContext) -> Int
|
||||||
) : Price {
|
) : Price {
|
||||||
override fun canAfford(player: Player) = player.level >= levels
|
private val multipliers = mutableMapOf<UUID, Double>()
|
||||||
|
|
||||||
|
override fun canAfford(player: Player) = player.level >= getValue(player)
|
||||||
|
|
||||||
override fun pay(player: Player) {
|
override fun pay(player: Player) {
|
||||||
player.level -= levels
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIdentifier(): String {
|
||||||
|
return "eco:xp-levels"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_17_R1
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.PluginCommand
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.BukkitCommandsProxy
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.SimpleCommandMap
|
||||||
|
import org.bukkit.craftbukkit.v1_17_R1.CraftServer
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
|
class BukkitCommands : BukkitCommandsProxy {
|
||||||
|
private val knownCommandsField: Field by lazy {
|
||||||
|
SimpleCommandMap::class.java.getDeclaredField("knownCommands")
|
||||||
|
.apply {
|
||||||
|
isAccessible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val knownCommands: MutableMap<String, Command>
|
||||||
|
get() = knownCommandsField.get(getCommandMap()) as MutableMap<String, Command>
|
||||||
|
|
||||||
|
override fun getCommandMap(): SimpleCommandMap {
|
||||||
|
return (Bukkit.getServer() as CraftServer).commandMap
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun syncCommands() {
|
||||||
|
(Bukkit.getServer() as CraftServer).syncCommands()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterCommand(command: PluginCommand) {
|
||||||
|
knownCommands.remove(command.name)
|
||||||
|
knownCommands.remove("${command.plugin.name.lowercase()}:${command.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.PluginCommand
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.BukkitCommandsProxy
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.SimpleCommandMap
|
||||||
|
import org.bukkit.craftbukkit.v1_18_R1.CraftServer
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
|
class BukkitCommands : BukkitCommandsProxy {
|
||||||
|
private val knownCommandsField: Field by lazy {
|
||||||
|
SimpleCommandMap::class.java.getDeclaredField("knownCommands")
|
||||||
|
.apply {
|
||||||
|
isAccessible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val knownCommands: MutableMap<String, Command>
|
||||||
|
get() = knownCommandsField.get(getCommandMap()) as MutableMap<String, Command>
|
||||||
|
|
||||||
|
override fun getCommandMap(): SimpleCommandMap {
|
||||||
|
return (Bukkit.getServer() as CraftServer).commandMap
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun syncCommands() {
|
||||||
|
(Bukkit.getServer() as CraftServer).syncCommands()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterCommand(command: PluginCommand) {
|
||||||
|
knownCommands.remove(command.name)
|
||||||
|
knownCommands.remove("${command.plugin.name.lowercase()}:${command.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_18_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.PluginCommand
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.BukkitCommandsProxy
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.SimpleCommandMap
|
||||||
|
import org.bukkit.craftbukkit.v1_18_R2.CraftServer
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
|
class BukkitCommands : BukkitCommandsProxy {
|
||||||
|
private val knownCommandsField: Field by lazy {
|
||||||
|
SimpleCommandMap::class.java.getDeclaredField("knownCommands")
|
||||||
|
.apply {
|
||||||
|
isAccessible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val knownCommands: MutableMap<String, Command>
|
||||||
|
get() = knownCommandsField.get(getCommandMap()) as MutableMap<String, Command>
|
||||||
|
|
||||||
|
override fun getCommandMap(): SimpleCommandMap {
|
||||||
|
return (Bukkit.getServer() as CraftServer).commandMap
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun syncCommands() {
|
||||||
|
(Bukkit.getServer() as CraftServer).syncCommands()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterCommand(command: PluginCommand) {
|
||||||
|
knownCommands.remove(command.name)
|
||||||
|
knownCommands.remove("${command.plugin.name.lowercase()}:${command.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R1
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.PluginCommand
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.BukkitCommandsProxy
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.SimpleCommandMap
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R1.CraftServer
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
|
class BukkitCommands : BukkitCommandsProxy {
|
||||||
|
private val knownCommandsField: Field by lazy {
|
||||||
|
SimpleCommandMap::class.java.getDeclaredField("knownCommands")
|
||||||
|
.apply {
|
||||||
|
isAccessible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val knownCommands: MutableMap<String, Command>
|
||||||
|
get() = knownCommandsField.get(getCommandMap()) as MutableMap<String, Command>
|
||||||
|
|
||||||
|
override fun getCommandMap(): SimpleCommandMap {
|
||||||
|
return (Bukkit.getServer() as CraftServer).commandMap
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun syncCommands() {
|
||||||
|
(Bukkit.getServer() as CraftServer).syncCommands()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterCommand(command: PluginCommand) {
|
||||||
|
knownCommands.remove(command.name)
|
||||||
|
knownCommands.remove("${command.plugin.name.lowercase()}:${command.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
39
eco-core/core-nms/v1_19_R2/build.gradle.kts
Normal file
39
eco-core/core-nms/v1_19_R2/build.gradle.kts
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
plugins {
|
||||||
|
id("io.papermc.paperweight.userdev") version "1.3.6"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.willfp"
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":eco-core:core-nms:nms-common"))
|
||||||
|
paperDevBundle("1.19.3-R0.1-SNAPSHOT")
|
||||||
|
|
||||||
|
implementation("net.kyori:adventure-text-minimessage:4.11.0") {
|
||||||
|
version {
|
||||||
|
strictly("4.11.0")
|
||||||
|
}
|
||||||
|
exclude(group = "net.kyori", module = "adventure-api")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
build {
|
||||||
|
dependsOn(reobfJar)
|
||||||
|
}
|
||||||
|
|
||||||
|
reobfJar {
|
||||||
|
mustRunAfter(shadowJar)
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
relocate(
|
||||||
|
"com.willfp.eco.internal.spigot.proxy.common",
|
||||||
|
"com.willfp.eco.internal.spigot.proxy.v1_19_R2.common"
|
||||||
|
)
|
||||||
|
relocate(
|
||||||
|
"net.kyori.adventure.text.minimessage",
|
||||||
|
"com.willfp.eco.internal.spigot.proxy.v1_19_R2.minimessage"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.AutoCraftProxy
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundPlaceGhostRecipePacket
|
||||||
|
import net.minecraft.resources.ResourceLocation
|
||||||
|
|
||||||
|
class AutoCraft : AutoCraftProxy {
|
||||||
|
override fun modifyPacket(packet: Any) {
|
||||||
|
val recipePacket = packet as ClientboundPlaceGhostRecipePacket
|
||||||
|
val fKey = recipePacket.javaClass.getDeclaredField("b")
|
||||||
|
fKey.isAccessible = true
|
||||||
|
val key = fKey[recipePacket] as ResourceLocation
|
||||||
|
fKey[recipePacket] = ResourceLocation(key.namespace, key.path + "_displayed")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.PluginCommand
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.BukkitCommandsProxy
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.SimpleCommandMap
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.CraftServer
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
|
class BukkitCommands : BukkitCommandsProxy {
|
||||||
|
private val knownCommandsField: Field by lazy {
|
||||||
|
SimpleCommandMap::class.java.getDeclaredField("knownCommands")
|
||||||
|
.apply {
|
||||||
|
isAccessible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val knownCommands: MutableMap<String, Command>
|
||||||
|
get() = knownCommandsField.get(getCommandMap()) as MutableMap<String, Command>
|
||||||
|
|
||||||
|
override fun getCommandMap(): SimpleCommandMap {
|
||||||
|
return (Bukkit.getServer() as CraftServer).commandMap
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun syncCommands() {
|
||||||
|
(Bukkit.getServer() as CraftServer).syncCommands()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun unregisterCommand(command: PluginCommand) {
|
||||||
|
knownCommands.remove(command.name)
|
||||||
|
knownCommands.remove("${command.plugin.name.lowercase()}:${command.name}")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.core.display.Display
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.ChatComponentProxy
|
||||||
|
import net.kyori.adventure.nbt.api.BinaryTagHolder
|
||||||
|
import net.kyori.adventure.text.BuildableComponent
|
||||||
|
import net.kyori.adventure.text.Component
|
||||||
|
import net.kyori.adventure.text.TranslatableComponent
|
||||||
|
import net.kyori.adventure.text.event.HoverEvent
|
||||||
|
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
|
||||||
|
import net.minecraft.nbt.TagParser
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
class ChatComponent : ChatComponentProxy {
|
||||||
|
private val gsonComponentSerializer = GsonComponentSerializer.gson()
|
||||||
|
|
||||||
|
override fun modifyComponent(obj: Any, player: Player): Any {
|
||||||
|
if (obj !is net.minecraft.network.chat.Component) {
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
val component = gsonComponentSerializer.deserialize(
|
||||||
|
net.minecraft.network.chat.Component.Serializer.toJson(
|
||||||
|
obj
|
||||||
|
)
|
||||||
|
).asComponent() as BuildableComponent<*, *>
|
||||||
|
|
||||||
|
val newComponent = modifyBaseComponent(component, player)
|
||||||
|
|
||||||
|
return net.minecraft.network.chat.Component.Serializer.fromJson(
|
||||||
|
gsonComponentSerializer.serialize(newComponent.asComponent())
|
||||||
|
) ?: obj
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun modifyBaseComponent(baseComponent: Component, player: Player): Component {
|
||||||
|
var component = baseComponent
|
||||||
|
|
||||||
|
if (component is TranslatableComponent) {
|
||||||
|
val args = mutableListOf<Component>()
|
||||||
|
for (arg in component.args()) {
|
||||||
|
args.add(modifyBaseComponent(arg, player))
|
||||||
|
}
|
||||||
|
component = component.args(args)
|
||||||
|
}
|
||||||
|
|
||||||
|
val children = mutableListOf<Component>()
|
||||||
|
for (child in component.children()) {
|
||||||
|
children.add(modifyBaseComponent(child, player))
|
||||||
|
}
|
||||||
|
component = component.children(children)
|
||||||
|
|
||||||
|
val hoverEvent: HoverEvent<Any> = component.style().hoverEvent() as HoverEvent<Any>? ?: return component
|
||||||
|
|
||||||
|
val showItem = hoverEvent.value()
|
||||||
|
|
||||||
|
if (showItem !is HoverEvent.ShowItem) {
|
||||||
|
return component
|
||||||
|
}
|
||||||
|
|
||||||
|
val newShowItem = showItem.nbt(
|
||||||
|
BinaryTagHolder.binaryTagHolder(
|
||||||
|
CraftItemStack.asNMSCopy(
|
||||||
|
Display.display(
|
||||||
|
CraftItemStack.asBukkitCopy(
|
||||||
|
CraftItemStack.asNMSCopy(
|
||||||
|
ItemStack(
|
||||||
|
Material.matchMaterial(
|
||||||
|
showItem.item()
|
||||||
|
.toString()
|
||||||
|
) ?: return component,
|
||||||
|
showItem.count()
|
||||||
|
)
|
||||||
|
).apply {
|
||||||
|
this.tag = TagParser.parseTag(
|
||||||
|
showItem.nbt()?.string() ?: return component
|
||||||
|
) ?: return component
|
||||||
|
}
|
||||||
|
),
|
||||||
|
player
|
||||||
|
)
|
||||||
|
).orCreateTag.toString()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
val newHover = hoverEvent.value(newShowItem)
|
||||||
|
val style = component.style().hoverEvent(newHover)
|
||||||
|
return component.style(style)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,135 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.CommonsInitializerProxy
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.common.CommonsProvider
|
||||||
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.nbt.Tag
|
||||||
|
import net.minecraft.resources.ResourceLocation
|
||||||
|
import net.minecraft.world.entity.PathfinderMob
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.CraftServer
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftEntity
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.entity.CraftMob
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.persistence.CraftPersistentDataContainer
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.persistence.CraftPersistentDataTypeRegistry
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.util.CraftMagicNumbers
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.util.CraftNamespacedKey
|
||||||
|
import org.bukkit.entity.LivingEntity
|
||||||
|
import org.bukkit.entity.Mob
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
|
class CommonsInitializer : CommonsInitializerProxy {
|
||||||
|
override fun init() {
|
||||||
|
CommonsProvider.setIfNeeded(CommonsProviderImpl)
|
||||||
|
}
|
||||||
|
|
||||||
|
object CommonsProviderImpl : CommonsProvider {
|
||||||
|
private val cisHandle: Field = CraftItemStack::class.java.getDeclaredField("handle").apply {
|
||||||
|
isAccessible = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private val pdcRegsitry = Class.forName("org.bukkit.craftbukkit.v1_19_R2.inventory.CraftMetaItem")
|
||||||
|
.getDeclaredField("DATA_TYPE_REGISTRY")
|
||||||
|
.apply { isAccessible = true }
|
||||||
|
.get(null) as CraftPersistentDataTypeRegistry
|
||||||
|
|
||||||
|
override val nbtTagString = CraftMagicNumbers.NBT.TAG_STRING
|
||||||
|
|
||||||
|
override fun toPathfinderMob(mob: Mob): PathfinderMob? {
|
||||||
|
val craft = mob as? CraftMob ?: return null
|
||||||
|
return craft.handle as? PathfinderMob
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toResourceLocation(namespacedKey: NamespacedKey): ResourceLocation =
|
||||||
|
CraftNamespacedKey.toMinecraft(namespacedKey)
|
||||||
|
|
||||||
|
override fun asNMSStack(itemStack: ItemStack): net.minecraft.world.item.ItemStack {
|
||||||
|
return if (itemStack !is CraftItemStack) {
|
||||||
|
CraftItemStack.asNMSCopy(itemStack)
|
||||||
|
} else {
|
||||||
|
cisHandle[itemStack] as net.minecraft.world.item.ItemStack? ?: CraftItemStack.asNMSCopy(itemStack)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun asBukkitStack(itemStack: net.minecraft.world.item.ItemStack): ItemStack {
|
||||||
|
return CraftItemStack.asBukkitCopy(itemStack)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun mergeIfNeeded(itemStack: ItemStack, nmsStack: net.minecraft.world.item.ItemStack) {
|
||||||
|
if (itemStack !is CraftItemStack) {
|
||||||
|
itemStack.itemMeta = CraftItemStack.asCraftMirror(nmsStack).itemMeta
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toBukkitEntity(entity: net.minecraft.world.entity.LivingEntity): LivingEntity? =
|
||||||
|
CraftEntity.getEntity(Bukkit.getServer() as CraftServer, entity) as? LivingEntity
|
||||||
|
|
||||||
|
override fun makePdc(tag: CompoundTag, base: Boolean): PersistentDataContainer {
|
||||||
|
fun emptyPdc(): CraftPersistentDataContainer = CraftPersistentDataContainer(pdcRegsitry)
|
||||||
|
|
||||||
|
fun CompoundTag?.toPdc(): PersistentDataContainer {
|
||||||
|
val pdc = emptyPdc()
|
||||||
|
this ?: return pdc
|
||||||
|
val keys = this.allKeys
|
||||||
|
for (key in keys) {
|
||||||
|
pdc.put(key, this[key])
|
||||||
|
}
|
||||||
|
|
||||||
|
return pdc
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (base) {
|
||||||
|
tag.toPdc()
|
||||||
|
} else {
|
||||||
|
if (tag.contains("PublicBukkitValues")) {
|
||||||
|
tag.getCompound("PublicBukkitValues").toPdc()
|
||||||
|
} else {
|
||||||
|
emptyPdc()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setPdc(
|
||||||
|
tag: CompoundTag,
|
||||||
|
pdc: PersistentDataContainer?,
|
||||||
|
item: net.minecraft.world.item.ItemStack?
|
||||||
|
) {
|
||||||
|
fun CraftPersistentDataContainer.toTag(): CompoundTag {
|
||||||
|
val compound = CompoundTag()
|
||||||
|
val rawPublicMap: Map<String, Tag> = this.raw
|
||||||
|
for ((key, value) in rawPublicMap) {
|
||||||
|
compound.put(key, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return compound
|
||||||
|
}
|
||||||
|
|
||||||
|
val container = when (pdc) {
|
||||||
|
is CraftPersistentDataContainer? -> pdc
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item != null) {
|
||||||
|
if (container != null && !container.isEmpty) {
|
||||||
|
for (key in tag.allKeys.toSet()) {
|
||||||
|
tag.remove(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
tag.merge(container.toTag())
|
||||||
|
} else {
|
||||||
|
item.setTag(null)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (container != null && !container.isEmpty) {
|
||||||
|
tag.put("PublicBukkitValues", container.toTag())
|
||||||
|
} else {
|
||||||
|
tag.remove("PublicBukkitValues")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.internal.entities.EcoDummyEntity
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.DummyEntityFactoryProxy
|
||||||
|
import org.bukkit.Location
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.CraftWorld
|
||||||
|
import org.bukkit.entity.Entity
|
||||||
|
import org.bukkit.entity.EntityType
|
||||||
|
|
||||||
|
class DummyEntityFactory : DummyEntityFactoryProxy {
|
||||||
|
override fun createDummyEntity(location: Location): Entity {
|
||||||
|
val world = location.world as CraftWorld
|
||||||
|
@Suppress("UsePropertyAccessSyntax")
|
||||||
|
return EcoDummyEntity(world.createEntity(location, EntityType.ZOMBIE.entityClass).getBukkitEntity())
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.core.entities.ai.EntityController
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.EntityControllerFactoryProxy
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.common.ai.EcoEntityController
|
||||||
|
import org.bukkit.entity.Mob
|
||||||
|
|
||||||
|
class EntityControllerFactory : EntityControllerFactoryProxy {
|
||||||
|
override fun <T : Mob> createEntityController(entity: T): EntityController<T> {
|
||||||
|
return EcoEntityController(entity)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.core.data.ExtendedPersistentDataContainer
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.ExtendedPersistentDataContainerFactoryProxy
|
||||||
|
import net.minecraft.nbt.Tag
|
||||||
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.persistence.CraftPersistentDataContainer
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.persistence.CraftPersistentDataTypeRegistry
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.persistence.PersistentDataContainer
|
||||||
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
|
||||||
|
class ExtendedPersistentDataContainerFactory : ExtendedPersistentDataContainerFactoryProxy {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val registry: 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 {
|
||||||
|
return when (pdc) {
|
||||||
|
is CraftPersistentDataContainer -> EcoPersistentDataContainer(pdc)
|
||||||
|
else -> throw IllegalArgumentException("Custom PDC instance ims not supported!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun newPdc(): PersistentDataContainer {
|
||||||
|
return CraftPersistentDataContainer(registry)
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class EcoPersistentDataContainer(
|
||||||
|
val handle: CraftPersistentDataContainer
|
||||||
|
) : ExtendedPersistentDataContainer {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private val customDataTags: MutableMap<String, Tag> =
|
||||||
|
CraftPersistentDataContainer::class.java.getDeclaredField("customDataTags")
|
||||||
|
.apply { isAccessible = true }.get(handle) as MutableMap<String, Tag>
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any, Z : Any> has(key: String, dataType: PersistentDataType<T, Z>): Boolean {
|
||||||
|
val value = customDataTags[key] ?: return false
|
||||||
|
return registry.isInstanceOf(dataType.primitiveType, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any, Z : Any> get(key: String, dataType: PersistentDataType<T, Z>): Z? {
|
||||||
|
val value = customDataTags[key] ?: return null
|
||||||
|
return dataType.fromPrimitive(registry.extract(dataType.primitiveType, value), handle.adapterContext)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T : Any, Z : Any> getOrDefault(
|
||||||
|
key: String,
|
||||||
|
dataType: PersistentDataType<T, Z>,
|
||||||
|
defaultValue: Z
|
||||||
|
): Z {
|
||||||
|
return get(key, dataType) ?: defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun remove(key: String) {
|
||||||
|
customDataTags.remove(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAllKeys(): MutableSet<String> {
|
||||||
|
return customDataTags.keys
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getBase(): PersistentDataContainer {
|
||||||
|
return handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.core.fast.FastItemStack
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.common.item.EcoFastItemStack
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
|
||||||
|
class FastItemStackFactory : FastItemStackFactoryProxy {
|
||||||
|
override fun create(itemStack: ItemStack): FastItemStack {
|
||||||
|
return EcoFastItemStack(itemStack)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.core.display.Display
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.MiniMessageTranslatorProxy
|
||||||
|
import com.willfp.eco.util.toLegacy
|
||||||
|
import net.kyori.adventure.text.minimessage.MiniMessage
|
||||||
|
|
||||||
|
class MiniMessageTranslator : MiniMessageTranslatorProxy {
|
||||||
|
override fun format(message: String): String {
|
||||||
|
var mut = message
|
||||||
|
|
||||||
|
val startsWithPrefix = mut.startsWith(Display.PREFIX)
|
||||||
|
if (startsWithPrefix) {
|
||||||
|
mut = mut.substring(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
mut = mut.replace('§', '&')
|
||||||
|
|
||||||
|
val miniMessage = runCatching {
|
||||||
|
MiniMessage.miniMessage().deserialize(
|
||||||
|
mut
|
||||||
|
).toLegacy()
|
||||||
|
}.getOrNull() ?: mut
|
||||||
|
|
||||||
|
mut = if (startsWithPrefix) {
|
||||||
|
Display.PREFIX + miniMessage
|
||||||
|
} else {
|
||||||
|
miniMessage
|
||||||
|
}
|
||||||
|
|
||||||
|
return mut
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.core.items.TestableItem
|
||||||
|
import com.willfp.eco.core.recipe.parts.EmptyTestableItem
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.SNBTConverterProxy
|
||||||
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.nbt.SnbtPrinterTagVisitor
|
||||||
|
import net.minecraft.nbt.TagParser
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
|
||||||
|
class SNBTConverter : SNBTConverterProxy {
|
||||||
|
override fun fromSNBT(snbt: String): ItemStack? {
|
||||||
|
val nbt = runCatching { TagParser.parseTag(snbt) }.getOrNull() ?: return null
|
||||||
|
val nms = net.minecraft.world.item.ItemStack.of(nbt)
|
||||||
|
return CraftItemStack.asBukkitCopy(nms)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toSNBT(itemStack: ItemStack): String {
|
||||||
|
val nms = CraftItemStack.asNMSCopy(itemStack)
|
||||||
|
return SnbtPrinterTagVisitor().visit(nms.save(CompoundTag()))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun makeSNBTTestable(snbt: String): TestableItem {
|
||||||
|
val nbt = runCatching { TagParser.parseTag(snbt) }.getOrNull() ?: return EmptyTestableItem()
|
||||||
|
val nms = net.minecraft.world.item.ItemStack.of(nbt)
|
||||||
|
if (nms == net.minecraft.world.item.ItemStack.EMPTY) {
|
||||||
|
return EmptyTestableItem()
|
||||||
|
}
|
||||||
|
|
||||||
|
nbt.remove("Count")
|
||||||
|
return SNBTTestableItem(CraftItemStack.asBukkitCopy(nms), nbt)
|
||||||
|
}
|
||||||
|
|
||||||
|
class SNBTTestableItem(
|
||||||
|
private val item: ItemStack,
|
||||||
|
private val tag: CompoundTag
|
||||||
|
) : TestableItem {
|
||||||
|
override fun matches(itemStack: ItemStack?): Boolean {
|
||||||
|
if (itemStack == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
val nms = CraftItemStack.asNMSCopy(itemStack)
|
||||||
|
val nmsTag = nms.save(CompoundTag())
|
||||||
|
nmsTag.remove("Count")
|
||||||
|
return tag.copy().merge(nmsTag) == nmsTag
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItem(): ItemStack = item
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.SkullProxy
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.common.texture
|
||||||
|
import org.bukkit.inventory.meta.SkullMeta
|
||||||
|
|
||||||
|
class Skull : SkullProxy {
|
||||||
|
override fun setSkullTexture(
|
||||||
|
meta: SkullMeta,
|
||||||
|
base64: String
|
||||||
|
) {
|
||||||
|
meta.texture = base64
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSkullTexture(
|
||||||
|
meta: SkullMeta
|
||||||
|
): String? = meta.texture
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.TPSProxy
|
||||||
|
import org.bukkit.Bukkit
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.CraftServer
|
||||||
|
|
||||||
|
class TPS : TPSProxy {
|
||||||
|
override fun getTPS(): Double {
|
||||||
|
return (Bukkit.getServer() as CraftServer).handle.server.recentTps[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy.v1_19_R2
|
||||||
|
|
||||||
|
import com.willfp.eco.core.display.Display
|
||||||
|
import com.willfp.eco.internal.spigot.proxy.VillagerTradeProxy
|
||||||
|
import net.minecraft.nbt.CompoundTag
|
||||||
|
import net.minecraft.world.item.ItemStack
|
||||||
|
import net.minecraft.world.item.trading.MerchantOffer
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack
|
||||||
|
import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftMerchantRecipe
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import org.bukkit.inventory.MerchantRecipe
|
||||||
|
import java.lang.reflect.Field
|
||||||
|
|
||||||
|
class VillagerTrade : VillagerTradeProxy {
|
||||||
|
private val handle: Field = CraftMerchantRecipe::class.java.getDeclaredField("handle")
|
||||||
|
|
||||||
|
override fun displayTrade(
|
||||||
|
recipe: MerchantRecipe,
|
||||||
|
player: Player
|
||||||
|
): MerchantRecipe {
|
||||||
|
recipe as CraftMerchantRecipe
|
||||||
|
|
||||||
|
val nbt = getHandle(recipe).createTag()
|
||||||
|
for (tag in arrayOf("buy", "buyB", "sell")) {
|
||||||
|
val nms = ItemStack.of(nbt.getCompound(tag))
|
||||||
|
val displayed = Display.display(CraftItemStack.asBukkitCopy(nms), player)
|
||||||
|
val itemNBT = CraftItemStack.asNMSCopy(displayed).save(CompoundTag())
|
||||||
|
nbt.put(tag, itemNBT)
|
||||||
|
}
|
||||||
|
|
||||||
|
return CraftMerchantRecipe(MerchantOffer(nbt))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getHandle(recipe: CraftMerchantRecipe): MerchantOffer {
|
||||||
|
return handle[recipe] as MerchantOffer
|
||||||
|
}
|
||||||
|
|
||||||
|
init {
|
||||||
|
handle.isAccessible = true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -50,6 +50,7 @@ dependencies {
|
|||||||
compileOnly 'com.github.Gypopo:EconomyShopGUI-API:1.1.0'
|
compileOnly 'com.github.Gypopo:EconomyShopGUI-API:1.1.0'
|
||||||
compileOnly 'com.github.N0RSKA:ScytherAPI:55a'
|
compileOnly 'com.github.N0RSKA:ScytherAPI:55a'
|
||||||
compileOnly 'com.ticxo.modelengine:api:R3.0.1'
|
compileOnly 'com.ticxo.modelengine:api:R3.0.1'
|
||||||
|
compileOnly 'me.TechsCode:UltraEconomyAPI:1.0.0'
|
||||||
|
|
||||||
// MythicMobs
|
// MythicMobs
|
||||||
compileOnly 'io.lumine:Mythic:5.0.1'
|
compileOnly 'io.lumine:Mythic:5.0.1'
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ 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.command.impl.PluginCommand
|
||||||
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
|
||||||
@@ -50,9 +51,12 @@ 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.BukkitCommandsProxy
|
||||||
import com.willfp.eco.internal.spigot.proxy.TPSProxy
|
import com.willfp.eco.internal.spigot.proxy.TPSProxy
|
||||||
import org.bukkit.Location
|
import org.bukkit.Location
|
||||||
import org.bukkit.NamespacedKey
|
import org.bukkit.NamespacedKey
|
||||||
|
import org.bukkit.command.Command
|
||||||
|
import org.bukkit.command.CommandMap
|
||||||
import org.bukkit.configuration.ConfigurationSection
|
import org.bukkit.configuration.ConfigurationSection
|
||||||
import org.bukkit.entity.Entity
|
import org.bukkit.entity.Entity
|
||||||
import org.bukkit.entity.Mob
|
import org.bukkit.entity.Mob
|
||||||
@@ -282,4 +286,13 @@ class EcoImpl : EcoSpigotPlugin(), Eco {
|
|||||||
|
|
||||||
override fun getOpenMenu(player: Player) =
|
override fun getOpenMenu(player: Player) =
|
||||||
player.renderedInventory?.menu
|
player.renderedInventory?.menu
|
||||||
|
|
||||||
|
override fun syncCommands() =
|
||||||
|
this.getProxy(BukkitCommandsProxy::class.java).syncCommands()
|
||||||
|
|
||||||
|
override fun getCommandMap(): CommandMap =
|
||||||
|
this.getProxy(BukkitCommandsProxy::class.java).getCommandMap()
|
||||||
|
|
||||||
|
override fun unregisterCommand(command: PluginCommand) =
|
||||||
|
this.getProxy(BukkitCommandsProxy::class.java).unregisterCommand(command)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,12 +87,12 @@ import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCombatLogX
|
|||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCombatLogXV11
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCombatLogXV11
|
||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCrashClaim
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCrashClaim
|
||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefDeluxeCombat
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefDeluxeCombat
|
||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefFabledSkyBlock
|
|
||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefFactionsUUID
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefFactionsUUID
|
||||||
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefGriefPrevention
|
import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefGriefPrevention
|
||||||
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
|
||||||
@@ -114,11 +114,11 @@ import com.willfp.eco.internal.spigot.integrations.hologram.HologramHolographicD
|
|||||||
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.placeholder.PlaceholderIntegrationPAPI
|
||||||
|
import com.willfp.eco.internal.spigot.integrations.price.PriceFactoryUltraEconomy
|
||||||
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
|
||||||
@@ -126,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 me.TechsCode.UltraEconomy.UltraEconomy
|
||||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences
|
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
|
||||||
@@ -263,7 +264,6 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
|||||||
IntegrationLoader("IridiumSkyblock") { AntigriefManager.register(AntigriefIridiumSkyblock()) },
|
IntegrationLoader("IridiumSkyblock") { AntigriefManager.register(AntigriefIridiumSkyblock()) },
|
||||||
IntegrationLoader("DeluxeCombat") { AntigriefManager.register(AntigriefDeluxeCombat()) },
|
IntegrationLoader("DeluxeCombat") { AntigriefManager.register(AntigriefDeluxeCombat()) },
|
||||||
IntegrationLoader("SuperiorSkyblock2") { AntigriefManager.register(AntigriefSuperiorSkyblock2()) },
|
IntegrationLoader("SuperiorSkyblock2") { AntigriefManager.register(AntigriefSuperiorSkyblock2()) },
|
||||||
IntegrationLoader("FabledSkyBlock") { AntigriefManager.register(AntigriefFabledSkyBlock()) },
|
|
||||||
IntegrationLoader("BentoBox") { AntigriefManager.register(AntigriefBentoBox()) },
|
IntegrationLoader("BentoBox") { AntigriefManager.register(AntigriefBentoBox()) },
|
||||||
IntegrationLoader("WorldGuard") { AntigriefManager.register(AntigriefWorldGuard()) },
|
IntegrationLoader("WorldGuard") { AntigriefManager.register(AntigriefWorldGuard()) },
|
||||||
IntegrationLoader("GriefPrevention") { AntigriefManager.register(AntigriefGriefPrevention()) },
|
IntegrationLoader("GriefPrevention") { AntigriefManager.register(AntigriefGriefPrevention()) },
|
||||||
@@ -284,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()) },
|
||||||
@@ -332,6 +333,13 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Price
|
||||||
|
IntegrationLoader("UltraEconomy") {
|
||||||
|
for (currency in UltraEconomy.getAPI().currencies) {
|
||||||
|
Prices.registerPriceFactory(PriceFactoryUltraEconomy(currency))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// Placeholder
|
// Placeholder
|
||||||
IntegrationLoader("PlaceholderAPI") { PlaceholderManager.addIntegration(PlaceholderIntegrationPAPI()) },
|
IntegrationLoader("PlaceholderAPI") { PlaceholderManager.addIntegration(PlaceholderIntegrationPAPI()) },
|
||||||
|
|
||||||
@@ -369,7 +377,6 @@ abstract class EcoSpigotPlugin : EcoPlugin() {
|
|||||||
ArmorChangeEventListeners(this),
|
ArmorChangeEventListeners(this),
|
||||||
DataListener(this),
|
DataListener(this),
|
||||||
PlayerBlockListener(this),
|
PlayerBlockListener(this),
|
||||||
PlayerHealthFixer(this),
|
|
||||||
ServerLocking
|
ServerLocking
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ class LegacyMySQLDataHandler(
|
|||||||
plugin: EcoSpigotPlugin,
|
plugin: EcoSpigotPlugin,
|
||||||
handler: ProfileHandler
|
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: ProfileHandler,
|
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ class MySQLDataHandler(
|
|||||||
private val plugin: EcoSpigotPlugin,
|
private val plugin: EcoSpigotPlugin,
|
||||||
private val handler: ProfileHandler
|
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] = "{}"
|
||||||
@@ -135,7 +136,7 @@ class MySQLDataHandler(
|
|||||||
|
|
||||||
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()
|
||||||
}
|
}
|
||||||
@@ -144,7 +145,7 @@ class MySQLDataHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun initialize() {
|
override fun initialize() {
|
||||||
transaction {
|
transaction(database) {
|
||||||
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
SchemaUtils.createMissingTablesAndColumns(table, withLogs = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,9 @@ class ProfileSaver(
|
|||||||
handler: ProfileHandler
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.bukkit.event.Listener
|
|||||||
import org.bukkit.event.inventory.ClickType
|
import org.bukkit.event.inventory.ClickType
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent
|
import org.bukkit.event.inventory.InventoryClickEvent
|
||||||
import org.bukkit.event.inventory.InventoryCloseEvent
|
import org.bukkit.event.inventory.InventoryCloseEvent
|
||||||
|
import org.bukkit.event.inventory.InventoryDragEvent
|
||||||
import org.bukkit.event.player.PlayerItemHeldEvent
|
import org.bukkit.event.player.PlayerItemHeldEvent
|
||||||
import org.bukkit.inventory.PlayerInventory
|
import org.bukkit.inventory.PlayerInventory
|
||||||
|
|
||||||
@@ -70,7 +71,34 @@ 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler(
|
||||||
|
priority = EventPriority.HIGH
|
||||||
|
)
|
||||||
|
fun handleSlotClick(event: InventoryDragEvent) {
|
||||||
|
val rendered = event.view.topInventory.asRenderedInventory() ?: return
|
||||||
|
|
||||||
|
val player = event.whoClicked as? Player ?: return
|
||||||
|
|
||||||
|
val menu = rendered.menu
|
||||||
|
|
||||||
|
val slots = event.inventorySlots
|
||||||
|
|
||||||
|
for (slotID in slots) {
|
||||||
|
val (row, column) = MenuUtils.convertSlotToRowColumn(slotID, menu.columns)
|
||||||
|
|
||||||
|
val slot = menu.getSlot(row, column, player)
|
||||||
|
|
||||||
|
if (slot.isCaptive(player, menu)) {
|
||||||
|
if (!slot.isAllowedCaptive(player, menu, event.oldCursor)) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler(
|
@EventHandler(
|
||||||
@@ -93,9 +121,13 @@ 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)) {
|
||||||
|
if (!slot.isAllowedCaptive(player, menu, event.currentItem)) {
|
||||||
|
event.isCancelled = true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
event.isCancelled = true
|
event.isCancelled = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -115,6 +147,12 @@ class GUIListener(private val plugin: EcoPlugin) : Listener {
|
|||||||
player.renderActiveMenu()
|
player.renderActiveMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
fun forceRender(event: InventoryDragEvent) {
|
||||||
|
val player = event.whoClicked as? Player ?: return
|
||||||
|
player.renderActiveMenu()
|
||||||
|
}
|
||||||
|
|
||||||
@EventHandler(
|
@EventHandler(
|
||||||
priority = EventPriority.HIGHEST
|
priority = EventPriority.HIGHEST
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -45,4 +45,4 @@ class CustomItemsScyther : CustomItemsIntegration {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.integrations.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.util.toSingletonList
|
||||||
|
import me.TechsCode.UltraEconomy.UltraEconomy
|
||||||
|
import me.TechsCode.UltraEconomy.objects.Account
|
||||||
|
import me.TechsCode.UltraEconomy.objects.Currency
|
||||||
|
import org.bukkit.entity.Player
|
||||||
|
import java.util.UUID
|
||||||
|
import java.util.function.Function
|
||||||
|
|
||||||
|
class PriceFactoryUltraEconomy(private val currency: Currency) : PriceFactory {
|
||||||
|
override fun getNames(): List<String> {
|
||||||
|
return currency.name.lowercase().toSingletonList()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun create(baseContext: MathContext, function: Function<MathContext, Double>): Price {
|
||||||
|
return PriceUltraEconomy(currency, baseContext) { function.apply(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private class PriceUltraEconomy(
|
||||||
|
private val currency: Currency,
|
||||||
|
private val baseContext: MathContext,
|
||||||
|
private val function: (MathContext) -> Double
|
||||||
|
) : Price {
|
||||||
|
private val multipliers = mutableMapOf<UUID, Double>()
|
||||||
|
private val api = UltraEconomy.getAPI()
|
||||||
|
|
||||||
|
private val Player.account: Account?
|
||||||
|
get() = api.accounts.uuid(this.uniqueId).orElse(null)
|
||||||
|
|
||||||
|
override fun canAfford(player: Player, multiplier: Double): Boolean {
|
||||||
|
return (player.account?.getBalance(currency)?.onHand ?: 0f) >= getValue(player, multiplier)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun pay(player: Player, multiplier: Double) {
|
||||||
|
player.account?.getBalance(currency)?.removeHand(getValue(player, multiplier).toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun giveTo(player: Player, multiplier: Double) {
|
||||||
|
player.account?.getBalance(currency)?.addHand(getValue(player, multiplier).toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getValue(player: Player, multiplier: Double): Double {
|
||||||
|
return function(MathContext.copyWithPlayer(baseContext, player)) * getMultiplier(player) * multiplier
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getMultiplier(player: Player): Double {
|
||||||
|
return multipliers[player.uniqueId] ?: 1.0
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setMultiplier(player: Player, multiplier: Double) {
|
||||||
|
multipliers[player.uniqueId] = multiplier
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.willfp.eco.internal.spigot.integrations.shop
|
|||||||
|
|
||||||
import com.willfp.eco.core.integrations.shop.ShopIntegration
|
import com.willfp.eco.core.integrations.shop.ShopIntegration
|
||||||
import com.willfp.eco.core.integrations.shop.ShopSellEvent
|
import com.willfp.eco.core.integrations.shop.ShopSellEvent
|
||||||
|
import com.willfp.eco.core.price.impl.PriceEconomy
|
||||||
import dev.norska.dsw.api.DeluxeSellwandSellEvent
|
import dev.norska.dsw.api.DeluxeSellwandSellEvent
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.event.EventHandler
|
import org.bukkit.event.EventHandler
|
||||||
@@ -19,9 +20,9 @@ class ShopDeluxeSellwands : ShopIntegration {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val ecoEvent = ShopSellEvent(event.player, event.money, null)
|
val ecoEvent = ShopSellEvent(event.player, PriceEconomy(event.money), null)
|
||||||
Bukkit.getPluginManager().callEvent(ecoEvent)
|
Bukkit.getPluginManager().callEvent(ecoEvent)
|
||||||
event.money = ecoEvent.price
|
event.money = ecoEvent.value.getValue(event.player) * ecoEvent.multiplier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ package com.willfp.eco.internal.spigot.integrations.shop
|
|||||||
|
|
||||||
import com.willfp.eco.core.integrations.shop.ShopIntegration
|
import com.willfp.eco.core.integrations.shop.ShopIntegration
|
||||||
import com.willfp.eco.core.integrations.shop.ShopSellEvent
|
import com.willfp.eco.core.integrations.shop.ShopSellEvent
|
||||||
|
import com.willfp.eco.core.price.Price
|
||||||
|
import com.willfp.eco.core.price.impl.PriceEconomy
|
||||||
import me.gypopo.economyshopgui.api.EconomyShopGUIHook
|
import me.gypopo.economyshopgui.api.EconomyShopGUIHook
|
||||||
import me.gypopo.economyshopgui.api.events.PreTransactionEvent
|
import me.gypopo.economyshopgui.api.events.PreTransactionEvent
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
@@ -15,12 +17,16 @@ class ShopEconomyShopGUI : ShopIntegration {
|
|||||||
return EconomyShopGUISellEventListeners
|
return EconomyShopGUISellEventListeners
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPrice(itemStack: ItemStack, player: Player): Double {
|
override fun getUnitValue(itemStack: ItemStack, player: Player): Price {
|
||||||
return EconomyShopGUIHook.getItemSellPrice(player, itemStack)
|
return PriceEconomy(
|
||||||
|
EconomyShopGUIHook.getItemSellPrice(player, itemStack.clone().apply {
|
||||||
|
amount = 1
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPrice(itemStack: ItemStack): Double {
|
override fun isSellable(itemStack: ItemStack, player: Player): Boolean {
|
||||||
return EconomyShopGUIHook.getItemSellPrice(itemStack)
|
return EconomyShopGUIHook.getItemSellPrice(player, itemStack) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
object EconomyShopGUISellEventListeners : Listener {
|
object EconomyShopGUISellEventListeners : Listener {
|
||||||
@@ -30,9 +36,9 @@ class ShopEconomyShopGUI : ShopIntegration {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val ecoEvent = ShopSellEvent(event.player, event.price, event.itemStack)
|
val ecoEvent = ShopSellEvent(event.player, PriceEconomy(event.price), event.itemStack)
|
||||||
Bukkit.getPluginManager().callEvent(ecoEvent)
|
Bukkit.getPluginManager().callEvent(ecoEvent)
|
||||||
event.price = ecoEvent.price
|
event.price = ecoEvent.value.getValue(event.player) * ecoEvent.multiplier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package com.willfp.eco.internal.spigot.integrations.shop
|
|||||||
import com.willfp.eco.core.integrations.shop.ShopIntegration
|
import com.willfp.eco.core.integrations.shop.ShopIntegration
|
||||||
import com.willfp.eco.core.integrations.shop.ShopSellEvent
|
import com.willfp.eco.core.integrations.shop.ShopSellEvent
|
||||||
import com.willfp.eco.core.items.Items
|
import com.willfp.eco.core.items.Items
|
||||||
|
import com.willfp.eco.core.price.Price
|
||||||
|
import com.willfp.eco.core.price.impl.PriceEconomy
|
||||||
import net.brcdev.shopgui.ShopGuiPlusApi
|
import net.brcdev.shopgui.ShopGuiPlusApi
|
||||||
import net.brcdev.shopgui.event.ShopPreTransactionEvent
|
import net.brcdev.shopgui.event.ShopPreTransactionEvent
|
||||||
import net.brcdev.shopgui.provider.item.ItemProvider
|
import net.brcdev.shopgui.provider.item.ItemProvider
|
||||||
@@ -23,12 +25,16 @@ class ShopShopGuiPlus : ShopIntegration {
|
|||||||
return ShopGuiPlusSellEventListeners
|
return ShopGuiPlusSellEventListeners
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPrice(itemStack: ItemStack): Double {
|
override fun getUnitValue(itemStack: ItemStack, player: Player): Price {
|
||||||
return ShopGuiPlusApi.getItemStackPriceSell(itemStack)
|
return PriceEconomy(
|
||||||
|
ShopGuiPlusApi.getItemStackPriceSell(player, itemStack.clone().apply {
|
||||||
|
amount = 1
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPrice(itemStack: ItemStack, player: Player): Double {
|
override fun isSellable(itemStack: ItemStack, player: Player): Boolean {
|
||||||
return ShopGuiPlusApi.getItemStackPriceSell(player, itemStack)
|
return ShopGuiPlusApi.getItemStackPriceSell(player, itemStack) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
class EcoShopGuiPlusProvider : ItemProvider("eco") {
|
class EcoShopGuiPlusProvider : ItemProvider("eco") {
|
||||||
@@ -59,9 +65,9 @@ class ShopShopGuiPlus : ShopIntegration {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val ecoEvent = ShopSellEvent(event.player, event.price, event.shopItem.item)
|
val ecoEvent = ShopSellEvent(event.player, PriceEconomy(event.price), event.shopItem.item)
|
||||||
Bukkit.getPluginManager().callEvent(ecoEvent)
|
Bukkit.getPluginManager().callEvent(ecoEvent)
|
||||||
event.price = ecoEvent.price
|
event.price = ecoEvent.value.getValue(event.player) * ecoEvent.multiplier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package com.willfp.eco.internal.spigot.integrations.shop
|
|||||||
|
|
||||||
import com.willfp.eco.core.integrations.shop.ShopIntegration
|
import com.willfp.eco.core.integrations.shop.ShopIntegration
|
||||||
import com.willfp.eco.core.integrations.shop.ShopSellEvent
|
import com.willfp.eco.core.integrations.shop.ShopSellEvent
|
||||||
|
import com.willfp.eco.core.price.impl.PriceEconomy
|
||||||
import fr.maxlego08.shop.api.events.ZShopSellEvent
|
import fr.maxlego08.shop.api.events.ZShopSellEvent
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.event.EventHandler
|
import org.bukkit.event.EventHandler
|
||||||
@@ -19,13 +20,13 @@ class ShopZShop : ShopIntegration {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val ecoEvent = ShopSellEvent(event.player, event.price, event.button.itemStack)
|
val ecoEvent = ShopSellEvent(event.player, PriceEconomy(event.price), event.button.itemStack)
|
||||||
Bukkit.getPluginManager().callEvent(ecoEvent)
|
Bukkit.getPluginManager().callEvent(ecoEvent)
|
||||||
event.price = ecoEvent.price
|
event.price = ecoEvent.value.getValue(event.player) * ecoEvent.multiplier
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getPluginName(): String {
|
override fun getPluginName(): String {
|
||||||
return "zShop"
|
return "zShop"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,6 +15,11 @@ object ComplexInComplex : RecipeListener {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.inventory.size == 5) {
|
||||||
|
event.deny()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val player = event.inventory.viewers.getOrNull(0) as? Player ?: return
|
val player = event.inventory.viewers.getOrNull(0) as? Player ?: return
|
||||||
|
|
||||||
val matrix = event.inventory.matrix
|
val matrix = event.inventory.matrix
|
||||||
|
|||||||
@@ -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,12 @@
|
|||||||
|
package com.willfp.eco.internal.spigot.proxy
|
||||||
|
|
||||||
|
import com.willfp.eco.core.command.impl.PluginCommand
|
||||||
|
import org.bukkit.command.CommandMap
|
||||||
|
|
||||||
|
interface BukkitCommandsProxy {
|
||||||
|
fun getCommandMap(): CommandMap
|
||||||
|
|
||||||
|
fun syncCommands()
|
||||||
|
|
||||||
|
fun unregisterCommand(command: PluginCommand)
|
||||||
|
}
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
version = 6.44.1
|
version = 6.48.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.
@@ -16,6 +16,7 @@ include(":eco-core:core-nms:v1_17_R1")
|
|||||||
include(":eco-core:core-nms:v1_18_R1")
|
include(":eco-core:core-nms:v1_18_R1")
|
||||||
include(":eco-core:core-nms:v1_18_R2")
|
include(":eco-core:core-nms:v1_18_R2")
|
||||||
include(":eco-core:core-nms:v1_19_R1")
|
include(":eco-core:core-nms:v1_19_R1")
|
||||||
|
include(":eco-core:core-nms:v1_19_R2")
|
||||||
include(":eco-core:core-proxy")
|
include(":eco-core:core-proxy")
|
||||||
include(":eco-core:core-plugin")
|
include(":eco-core:core-plugin")
|
||||||
include(":eco-core:core-backend")
|
include(":eco-core:core-backend")
|
||||||
Reference in New Issue
Block a user