Compare commits

...

27 Commits

Author SHA1 Message Date
Auxilor
af91c9d659 Updated to 6.13.9 2021-11-14 13:43:29 +00:00
Auxilor
89eaaf3a5e Updated annotations and jupiter 2021-11-14 13:43:00 +00:00
Auxilor
ab174e2d41 Added configurability to MySQL threads 2021-11-14 13:42:24 +00:00
Auxilor
cfa9badc1e Limited SQL threads to 2 for socket connection limit 2021-11-14 13:41:11 +00:00
Auxilor
3ec1183ec3 Javadoc changes 2021-11-13 11:57:46 +00:00
Auxilor
b3e37ea717 Fixed lang.yml 2021-11-13 11:54:51 +00:00
Auxilor
9d0707a4db Merge remote-tracking branch 'origin/master' 2021-11-13 11:51:01 +00:00
Auxilor
41eee84966 Updated to 6.13.8 2021-11-13 11:50:31 +00:00
Auxilor
0f215b48bf Fixed custom items being used in shapeless vanilla recipes 2021-11-13 11:49:51 +00:00
Auxilor
abad973051 PR Codestyle 2021-11-13 11:06:03 +00:00
Auxilor
b385ebff75 Fixed IridiumSkyblock integration 2021-11-13 11:02:42 +00:00
Auxilor
f924d23feb Merge remote-tracking branch 'origin/master' into develop 2021-11-13 11:00:34 +00:00
Will FP
d603476201 Merge pull request #53
Fixed DeluxeCombat integration
2021-11-13 11:00:28 +00:00
Auxilor
b911bbce87 Updated Config string getters for more explicit formatting options 2021-11-13 11:00:08 +00:00
_OfTeN_
d2676c2af1 Fixed DeluxeCombat integration 2021-11-13 10:41:59 +03:00
Auxilor
e725811c2f Merge branch 'develop' 2021-11-12 18:07:32 +00:00
Auxilor
f861820572 Fixed key registration 2021-11-12 17:58:43 +00:00
Auxilor
6e310a48c1 DurabilityUtils fix 2021-11-12 17:56:07 +00:00
Auxilor
505234ec13 More data changes 2021-11-12 17:32:50 +00:00
Auxilor
587aeb21a1 Overhauled persistent data storage 2021-11-12 15:55:25 +00:00
Auxilor
cc344bf7ca MySQL Threading changes 2021-11-12 14:12:15 +00:00
Auxilor
c912b97438 Changed PlayerProfileHandler 2021-11-12 11:10:56 +00:00
Auxilor
4788f036ee More data changes 2021-11-12 11:07:43 +00:00
Auxilor
f5ff484086 Revert "Updated dependency structure"
This reverts commit a3ba7cdcf2.
2021-11-12 10:28:17 +00:00
Auxilor
c031534b0d Debugging 2021-11-12 10:28:13 +00:00
Auxilor
62ac49db4b Merge remote-tracking branch 'origin/develop' into develop 2021-11-12 10:15:08 +00:00
Auxilor
a3ba7cdcf2 Updated dependency structure 2021-11-10 19:14:09 +00:00
22 changed files with 308 additions and 169 deletions

View File

@@ -60,10 +60,10 @@ allprojects {
} }
dependencies { dependencies {
compileOnly 'org.jetbrains:annotations:19.0.0' compileOnly 'org.jetbrains:annotations:23.0.0'
// Test // Test
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
} }

View File

@@ -24,7 +24,7 @@ public class LangYml extends YamlBaseConfig {
* @return The prefix. * @return The prefix.
*/ */
public String getPrefix() { public String getPrefix() {
return this.getString("messages.prefix"); return this.getFormattedString("messages.prefix");
} }
/** /**
@@ -33,7 +33,7 @@ public class LangYml extends YamlBaseConfig {
* @return The message. * @return The message.
*/ */
public String getNoPermission() { public String getNoPermission() {
return getPrefix() + this.getString("messages.no-permission"); return getPrefix() + this.getFormattedString("messages.no-permission");
} }
/** /**
@@ -55,6 +55,6 @@ public class LangYml extends YamlBaseConfig {
*/ */
public String getMessage(@NotNull final String message, public String getMessage(@NotNull final String message,
@NotNull final StringUtils.FormatOption option) { @NotNull final StringUtils.FormatOption option) {
return getPrefix() + this.getString("messages." + message, option); return getPrefix() + this.getFormattedString("messages." + message, option);
} }
} }

View File

@@ -11,6 +11,7 @@ import java.util.List;
* <p> * <p>
* Contains all methods that must exist in yaml and json configurations. * Contains all methods that must exist in yaml and json configurations.
*/ */
@SuppressWarnings("unused")
public interface Config extends Cloneable { public interface Config extends Cloneable {
/** /**
* Clears cache. * Clears cache.
@@ -159,8 +160,34 @@ public interface Config extends Cloneable {
@Nullable @Nullable
List<Boolean> getBoolsOrNull(@NotNull String path); List<Boolean> getBoolsOrNull(@NotNull String path);
/**
* Get a formatted string from config.
*
* @param path The key to fetch the value from.
* @return The found value, or an empty string if not found.
*/
@NotNull
default String getFormattedString(@NotNull String path) {
return getString(path, true);
}
/**
* Get a formatted string from config.
*
* @param path The key to fetch the value from.
* @param option The format option.
* @return The found value, or an empty string if not found.
*/
@NotNull
default String getFormattedString(@NotNull String path,
@NotNull StringUtils.FormatOption option) {
return getString(path, true, option);
}
/** /**
* Get a string from config. * Get a string from config.
* <p>
* Formatted by default.
* *
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @return The found value, or an empty string if not found. * @return The found value, or an empty string if not found.
@@ -172,12 +199,13 @@ public interface Config extends Cloneable {
/** /**
* Get a string from config. * Get a string from config.
* <p>
* This will be deprecated when {@link Config#getString(String)} no longer formats by default.
* *
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @param format If the string should be formatted. * @param format If the string should be formatted.
* @return The found value, or an empty string if not found. * @return The found value, or an empty string if not found.
*/ */
@NotNull
default String getString(@NotNull String path, default String getString(@NotNull String path,
boolean format) { boolean format) {
return this.getString(path, format, StringUtils.FormatOption.WITH_PLACEHOLDERS); return this.getString(path, format, StringUtils.FormatOption.WITH_PLACEHOLDERS);
@@ -189,8 +217,10 @@ public interface Config extends Cloneable {
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @param option The format option. * @param option The format option.
* @return The found value, or an empty string if not found. * @return The found value, or an empty string if not found.
* @deprecated Use {@link Config#getFormattedString(String, StringUtils.FormatOption)} instead.
*/ */
@NotNull @NotNull
@Deprecated
default String getString(@NotNull String path, default String getString(@NotNull String path,
@NotNull final StringUtils.FormatOption option) { @NotNull final StringUtils.FormatOption option) {
return this.getString(path, true, option); return this.getString(path, true, option);
@@ -209,8 +239,34 @@ public interface Config extends Cloneable {
boolean format, boolean format,
@NotNull StringUtils.FormatOption option); @NotNull StringUtils.FormatOption option);
/**
* Get a formatted string from config.
*
* @param path The key to fetch the value from.
* @return The found value, or an empty string if not found.
*/
@Nullable
default String getFormattedStringOrNull(@NotNull String path) {
return getStringOrNull(path, true);
}
/**
* Get a formatted string from config.
*
* @param path The key to fetch the value from.
* @param option The format option.
* @return The found value, or an empty string if not found.
*/
@Nullable
default String getFormattedStringOrNull(@NotNull String path,
@NotNull StringUtils.FormatOption option) {
return getStringOrNull(path, true, option);
}
/** /**
* Get a string from config. * Get a string from config.
* <p>
* Formatted by default.
* *
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @return The found value, or null if not found. * @return The found value, or null if not found.
@@ -222,6 +278,8 @@ public interface Config extends Cloneable {
/** /**
* Get a string from config. * Get a string from config.
* <p>
* This will be deprecated when {@link Config#getStringOrNull(String)} no longer formats by default.
* *
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @param format If the string should be formatted. * @param format If the string should be formatted.
@@ -239,8 +297,10 @@ public interface Config extends Cloneable {
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @param option The format option. * @param option The format option.
* @return The found value, or null if not found. * @return The found value, or null if not found.
* @deprecated Use {@link Config#getFormattedString(String, StringUtils.FormatOption)} instead.
*/ */
@Nullable @Nullable
@Deprecated
default String getStringOrNull(@NotNull String path, default String getStringOrNull(@NotNull String path,
@NotNull StringUtils.FormatOption option) { @NotNull StringUtils.FormatOption option) {
return this.getStringOrNull(path, true, option); return this.getStringOrNull(path, true, option);
@@ -251,7 +311,7 @@ public interface Config extends Cloneable {
* *
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @param format If the string should be formatted. * @param format If the string should be formatted.
* @param option The format option. * @param option The format option. If format is false, this will be ignored.
* @return The found value, or null if not found. * @return The found value, or null if not found.
*/ */
@Nullable @Nullable
@@ -268,12 +328,44 @@ public interface Config extends Cloneable {
* @return The found value, or a blank {@link java.util.ArrayList} if not found. * @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/ */
@NotNull @NotNull
default List<String> getFormattedStrings(@NotNull String path) {
return getStrings(path, true, StringUtils.FormatOption.WITH_PLACEHOLDERS);
}
/**
* Get a list of strings from config.
* <p>
* Formatted by default.
*
* @param path The key to fetch the value from.
* @param option The format option.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
default List<String> getFormattedStrings(@NotNull String path,
@NotNull StringUtils.FormatOption option) {
return getStrings(path, true, option);
}
/**
* Get a list of strings from config.
* <p>
* Formatted by default.
* <p>
* This will be changed in newer versions to <b>not</b> format by default.
*
* @param path The key to fetch the value from.
* @return The found value, or a blank {@link java.util.ArrayList} if not found.
*/
@NotNull
default List<String> getStrings(@NotNull String path) { default List<String> getStrings(@NotNull String path) {
return getStrings(path, true); return getStrings(path, true);
} }
/** /**
* Get a list of strings from config. * Get a list of strings from config.
* <p>
* This will be deprecated when {@link Config#getStrings(String)} no longer formats by default.
* *
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @param format If the strings should be formatted. * @param format If the strings should be formatted.
@@ -291,8 +383,10 @@ public interface Config extends Cloneable {
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @param option The format option. * @param option The format option.
* @return The found value, or a blank {@link java.util.ArrayList} if not found. * @return The found value, or a blank {@link java.util.ArrayList} if not found.
* @deprecated Use {@link Config#getFormattedStrings(String, StringUtils.FormatOption)} instead.
*/ */
@Nullable @NotNull
@Deprecated
default List<String> getStrings(@NotNull String path, default List<String> getStrings(@NotNull String path,
@NotNull StringUtils.FormatOption option) { @NotNull StringUtils.FormatOption option) {
return getStrings(path, true, option); return getStrings(path, true, option);
@@ -313,6 +407,38 @@ public interface Config extends Cloneable {
/** /**
* Get a list of strings from config. * Get a list of strings from config.
* <p>
* Formatted by default.
*
* @param path The key to fetch the value from.
* @return The found value, or null if not found.
*/
@Nullable
default List<String> getFormattedStringsOrNull(@NotNull String path) {
return getStringsOrNull(path, true, StringUtils.FormatOption.WITH_PLACEHOLDERS);
}
/**
* Get a list of strings from config.
* <p>
* Formatted by default.
*
* @param path The key to fetch the value from.
* @param option The format option.
* @return The found value, or null if not found.
*/
@Nullable
default List<String> getFormattedStringsOrNull(@NotNull String path,
@NotNull StringUtils.FormatOption option) {
return getStringsOrNull(path, true, option);
}
/**
* Get a list of strings from config.
* <p>
* Formatted by default.
* <p>
* This will be changed in newer versions to <b>not</b> format by default.
* *
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @return The found value, or null if not found. * @return The found value, or null if not found.
@@ -341,8 +467,10 @@ public interface Config extends Cloneable {
* @param path The key to fetch the value from. * @param path The key to fetch the value from.
* @param option The format option. * @param option The format option.
* @return The found value, or null if not found. * @return The found value, or null if not found.
* @deprecated Use {@link Config#getFormattedStringsOrNull(String, StringUtils.FormatOption)} instead.
*/ */
@Nullable @Nullable
@Deprecated
default List<String> getStringsOrNull(@NotNull String path, default List<String> getStringsOrNull(@NotNull String path,
@NotNull StringUtils.FormatOption option) { @NotNull StringUtils.FormatOption option) {
return getStringsOrNull(path, true, option); return getStringsOrNull(path, true, option);

View File

@@ -1,7 +1,9 @@
package com.willfp.eco.core.data; package com.willfp.eco.core.data;
import com.willfp.eco.core.data.keys.PersistentDataKey;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import java.util.Set;
import java.util.UUID; import java.util.UUID;
/** /**
@@ -17,11 +19,37 @@ public interface PlayerProfileHandler {
PlayerProfile load(@NotNull UUID uuid); PlayerProfile load(@NotNull UUID uuid);
/** /**
* Save a player profile. * Unload a player profile from memory.
* <p>
* This will not save the profile first.
* *
* @param uuid The uuid. * @param uuid The uuid.
*/ */
void savePlayer(@NotNull UUID uuid); void unloadPlayer(@NotNull UUID uuid);
/**
* Save a player profile.
* <p>
* Can run async if using MySQL.
*
* @param uuid The uuid.
* @deprecated Saving changes is faster and should be used. Saving a player manually is not recommended.
*/
@Deprecated
default void savePlayer(@NotNull UUID uuid) {
this.saveKeysForPlayer(uuid, PersistentDataKey.values());
}
/**
* Save keys for a player.
* <p>
* Can run async if using MySQL.
*
* @param uuid The uuid.
* @param keys The keys.
*/
void saveKeysForPlayer(@NotNull UUID uuid,
@NotNull Set<PersistentDataKey<?>> keys);
/** /**
* Save all player data. * Save all player data.
@@ -36,6 +64,15 @@ public interface PlayerProfileHandler {
/** /**
* Save all player data. * Save all player data.
* <p>
* Can run async if using MySQL.
*/ */
void saveAll(); void saveAll();
/**
* Commit all changes to the file.
* <p>
* Does nothing if using MySQL.
*/
void save();
} }

View File

@@ -2,16 +2,43 @@ package com.willfp.eco.internal.data
import com.willfp.eco.core.data.PlayerProfile import com.willfp.eco.core.data.PlayerProfile
import com.willfp.eco.core.data.keys.PersistentDataKey import com.willfp.eco.core.data.keys.PersistentDataKey
import java.util.*
import java.util.concurrent.ConcurrentHashMap
class EcoPlayerProfile( class EcoPlayerProfile(
val data: MutableMap<PersistentDataKey<*>, Any> val data: MutableMap<PersistentDataKey<*>, Any>,
val uuid: UUID
) : PlayerProfile { ) : PlayerProfile {
override fun <T : Any> write(key: PersistentDataKey<T>, value: T) { override fun <T : Any> write(key: PersistentDataKey<T>, value: T) {
this.data[key] = value this.data[key] = value
val changedKeys = CHANGE_MAP[uuid] ?: mutableSetOf()
changedKeys.add(key)
CHANGE_MAP[uuid] = changedKeys
} }
override fun <T : Any> read(key: PersistentDataKey<T>): T { override fun <T : Any> read(key: PersistentDataKey<T>): T {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return this.data[key] as T? ?: key.defaultValue return this.data[key] as T? ?: key.defaultValue
} }
override fun equals(other: Any?): Boolean {
if (other !is EcoPlayerProfile) {
return false
}
return this.data == other.data
}
override fun hashCode(): Int {
return data.hashCode()
}
override fun toString(): String {
return "EcoPlayerProfile{$data}"
}
companion object {
val CHANGE_MAP: MutableMap<UUID, MutableSet<PersistentDataKey<*>>> = ConcurrentHashMap()
}
} }

View File

@@ -41,7 +41,6 @@ dependencies {
compileOnly 'world.bentobox:bentobox:1.17.3-SNAPSHOT' compileOnly 'world.bentobox:bentobox:1.17.3-SNAPSHOT'
compileOnly 'com.google.guava:guava:31.0.1-jre' compileOnly 'com.google.guava:guava:31.0.1-jre'
compileOnly 'com.iridium:IridiumSkyblock:3.1.2' compileOnly 'com.iridium:IridiumSkyblock:3.1.2'
compileOnly 'net.md-5:bungeecord-api:1.16-R0.5-SNAPSHOT'
// CombatLogX V10 + NewbieHelper Expansion // CombatLogX V10 + NewbieHelper Expansion
compileOnly 'com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT' compileOnly 'com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT'

View File

@@ -10,6 +10,7 @@ import com.willfp.eco.core.recipe.parts.ModifiedTestableItem;
import com.willfp.eco.core.recipe.parts.TestableStack; import com.willfp.eco.core.recipe.parts.TestableStack;
import com.willfp.eco.core.recipe.recipes.CraftingRecipe; import com.willfp.eco.core.recipe.recipes.CraftingRecipe;
import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe; import com.willfp.eco.core.recipe.recipes.ShapedCraftingRecipe;
import org.bukkit.Keyed;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.event.Event; import org.bukkit.event.Event;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@@ -245,7 +246,7 @@ public class ShapedRecipeListener extends PluginDependent<EcoPlugin> implements
@EventHandler @EventHandler
public void preventUsingComplexPartInVanillaRecipe(@NotNull final PrepareItemCraftEvent event) { public void preventUsingComplexPartInVanillaRecipe(@NotNull final PrepareItemCraftEvent event) {
if (!(event.getRecipe() instanceof ShapedRecipe recipe)) { if (!(event.getRecipe() instanceof Keyed recipe)) {
return; return;
} }
@@ -263,7 +264,7 @@ public class ShapedRecipeListener extends PluginDependent<EcoPlugin> implements
@EventHandler @EventHandler
public void preventUsingComplexPartInVanillaRecipe(@NotNull final CraftItemEvent event) { public void preventUsingComplexPartInVanillaRecipe(@NotNull final CraftItemEvent event) {
if (!(event.getRecipe() instanceof ShapedRecipe recipe)) { if (!(event.getRecipe() instanceof Keyed recipe)) {
return; return;
} }

View File

@@ -38,6 +38,8 @@ import com.willfp.eco.internal.scheduling.EcoScheduler
import com.willfp.eco.proxy.FastItemStackFactoryProxy import com.willfp.eco.proxy.FastItemStackFactoryProxy
import com.willfp.eco.spigot.data.EcoKeyRegistry import com.willfp.eco.spigot.data.EcoKeyRegistry
import com.willfp.eco.spigot.data.EcoPlayerProfileHandler import com.willfp.eco.spigot.data.EcoPlayerProfileHandler
import com.willfp.eco.spigot.data.storage.MySQLDataHandler
import com.willfp.eco.spigot.data.storage.YamlDataHandler
import com.willfp.eco.spigot.integrations.bstats.MetricHandler import com.willfp.eco.spigot.integrations.bstats.MetricHandler
import net.kyori.adventure.platform.bukkit.BukkitAudiences import net.kyori.adventure.platform.bukkit.BukkitAudiences
import org.bukkit.inventory.ItemStack import org.bukkit.inventory.ItemStack
@@ -49,7 +51,10 @@ class EcoHandler : EcoSpigotPlugin(), Handler {
private val requirementFactory = EcoRequirementFactory() private val requirementFactory = EcoRequirementFactory()
private var adventure: BukkitAudiences? = null private var adventure: BukkitAudiences? = null
private val keyRegistry = EcoKeyRegistry(this) private val keyRegistry = EcoKeyRegistry(this)
private val playerProfileHandler = EcoPlayerProfileHandler(this) private val playerProfileHandler = EcoPlayerProfileHandler(
if (this.configYml.getBool("mysql.enabled"))
MySQLDataHandler(this) else YamlDataHandler(this)
)
override fun createScheduler(plugin: EcoPlugin): Scheduler { override fun createScheduler(plugin: EcoPlugin): Scheduler {
return EcoScheduler(plugin) return EcoScheduler(plugin)

View File

@@ -25,11 +25,8 @@ import com.willfp.eco.proxy.SkullProxy
import com.willfp.eco.proxy.TPSProxy import com.willfp.eco.proxy.TPSProxy
import com.willfp.eco.spigot.arrows.ArrowDataListener import com.willfp.eco.spigot.arrows.ArrowDataListener
import com.willfp.eco.spigot.data.DataListener import com.willfp.eco.spigot.data.DataListener
import com.willfp.eco.spigot.data.EcoPlayerProfileHandler
import com.willfp.eco.spigot.data.PlayerBlockListener import com.willfp.eco.spigot.data.PlayerBlockListener
import com.willfp.eco.spigot.data.storage.DataHandler import com.willfp.eco.spigot.data.storage.ProfileSaver
import com.willfp.eco.spigot.data.storage.MySQLDataHandler
import com.willfp.eco.spigot.data.storage.YamlDataHandler
import com.willfp.eco.spigot.display.* import com.willfp.eco.spigot.display.*
import com.willfp.eco.spigot.display.frame.clearFrames import com.willfp.eco.spigot.display.frame.clearFrames
import com.willfp.eco.spigot.drops.CollatedRunnable import com.willfp.eco.spigot.drops.CollatedRunnable
@@ -70,8 +67,6 @@ abstract class EcoSpigotPlugin : EcoPlugin(
"com.willfp.eco.proxy", "com.willfp.eco.proxy",
"&a" "&a"
) { ) {
lateinit var dataHandler: DataHandler
init { init {
Items.registerArgParser(EnchantmentArgParser()) Items.registerArgParser(EnchantmentArgParser())
Items.registerArgParser(TextureArgParser()) Items.registerArgParser(TextureArgParser())
@@ -93,9 +88,6 @@ abstract class EcoSpigotPlugin : EcoPlugin(
private fun postInit() { private fun postInit() {
Display.setHandler(EcoDisplayHandler(this)) Display.setHandler(EcoDisplayHandler(this))
this.dataHandler = if (this.configYml.getBool("mysql.enabled"))
MySQLDataHandler(this) else YamlDataHandler(this)
} }
override fun handleEnable() { override fun handleEnable() {
@@ -123,20 +115,12 @@ abstract class EcoSpigotPlugin : EcoPlugin(
// Init FIS // Init FIS
this.getProxy(FastItemStackFactoryProxy::class.java).create(ItemStack(Material.AIR)).unwrap() this.getProxy(FastItemStackFactoryProxy::class.java).create(ItemStack(Material.AIR)).unwrap()
/*
I'll figure this one out eventually...
if (Prerequisite.HAS_BUNGEECORD.isMet) {
BungeeDataListener.register()
}
*/
} }
override fun handleDisable() { override fun handleDisable() {
this.logger.info("Saving player data...") this.logger.info("Saving player data...")
val start = System.currentTimeMillis() val start = System.currentTimeMillis()
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).saveAllBlocking() Eco.getHandler().playerProfileHandler.save()
this.logger.info("Saved player data! Took ${System.currentTimeMillis() - start}ms") this.logger.info("Saved player data! Took ${System.currentTimeMillis() - start}ms")
Eco.getHandler().adventure?.close() Eco.getHandler().adventure?.close()
} }
@@ -144,19 +128,12 @@ abstract class EcoSpigotPlugin : EcoPlugin(
override fun handleReload() { override fun handleReload() {
CollatedRunnable(this) CollatedRunnable(this)
DropManager.update(this) DropManager.update(this)
ProfileSaver(this)
this.scheduler.runTimer( this.scheduler.runTimer(
{ clearFrames() }, { clearFrames() },
this.configYml.getInt("display-frame-ttl").toLong(), this.configYml.getInt("display-frame-ttl").toLong(),
this.configYml.getInt("display-frame-ttl").toLong() this.configYml.getInt("display-frame-ttl").toLong()
) )
this.scheduler.runTimer(
{
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler)
.autosave()
},
this.configYml.getInt("autosave.ticks").toLong(),
this.configYml.getInt("autosave.ticks").toLong()
)
} }
override fun handleAfterLoad() { override fun handleAfterLoad() {

View File

@@ -1,34 +0,0 @@
package com.willfp.eco.spigot.data
import com.willfp.eco.core.Eco
import net.md_5.bungee.api.ProxyServer
import net.md_5.bungee.api.event.ServerConnectedEvent
import net.md_5.bungee.api.event.ServerDisconnectEvent
import net.md_5.bungee.api.event.ServerSwitchEvent
import net.md_5.bungee.api.plugin.Listener
import net.md_5.bungee.event.EventHandler
class BungeeDataListener : Listener {
@EventHandler
fun onConnected(event: ServerConnectedEvent) {
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).unloadPlayer(event.player.uniqueId)
}
@EventHandler
fun onDisconnect(event: ServerDisconnectEvent) {
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).unloadPlayer(event.player.uniqueId)
}
@EventHandler
fun onSwitch(event: ServerSwitchEvent) {
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).unloadPlayer(event.player.uniqueId)
}
companion object {
fun register() {
ProxyServer.getInstance().pluginManager.registerListener(
null, BungeeDataListener()
)
}
}
}

View File

@@ -5,18 +5,23 @@ import com.willfp.eco.util.PlayerUtils
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
import org.bukkit.event.Listener import org.bukkit.event.Listener
import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.event.player.PlayerJoinEvent
import org.bukkit.event.player.PlayerLoginEvent
import org.bukkit.event.player.PlayerQuitEvent import org.bukkit.event.player.PlayerQuitEvent
class DataListener : Listener { class DataListener : Listener {
@EventHandler @EventHandler
fun onLeave(event: PlayerQuitEvent) { fun onLeave(event: PlayerQuitEvent) {
PlayerUtils.updateSavedDisplayName(event.player) PlayerUtils.updateSavedDisplayName(event.player)
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).unloadPlayer(event.player.uniqueId) Eco.getHandler().playerProfileHandler.unloadPlayer(event.player.uniqueId)
} }
@EventHandler @EventHandler
fun onJoin(event: PlayerJoinEvent) { fun onJoin(event: PlayerJoinEvent) {
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).unloadPlayerBlocking(event.player.uniqueId)
PlayerUtils.updateSavedDisplayName(event.player) PlayerUtils.updateSavedDisplayName(event.player)
} }
@EventHandler
fun onLogin(event: PlayerLoginEvent) {
Eco.getHandler().playerProfileHandler.unloadPlayer(event.player.uniqueId)
}
} }

View File

@@ -1,5 +1,6 @@
package com.willfp.eco.spigot.data package com.willfp.eco.spigot.data
import com.willfp.eco.core.Eco
import com.willfp.eco.core.data.keys.KeyRegistry import com.willfp.eco.core.data.keys.KeyRegistry
import com.willfp.eco.core.data.keys.PersistentDataKey import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.core.data.keys.PersistentDataKeyType import com.willfp.eco.core.data.keys.PersistentDataKeyType
@@ -20,7 +21,7 @@ class EcoKeyRegistry(
this.registry[key.key] = key this.registry[key.key] = key
plugin.dataHandler.updateKeys() (Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).updateKeys()
} }
override fun getRegisteredKeys(): MutableSet<PersistentDataKey<*>> { override fun getRegisteredKeys(): MutableSet<PersistentDataKey<*>> {

View File

@@ -1,19 +1,16 @@
package com.willfp.eco.spigot.data package com.willfp.eco.spigot.data
import com.willfp.eco.core.Eco
import com.willfp.eco.core.data.PlayerProfile import com.willfp.eco.core.data.PlayerProfile
import com.willfp.eco.core.data.PlayerProfileHandler import com.willfp.eco.core.data.PlayerProfileHandler
import com.willfp.eco.core.data.keys.PersistentDataKey import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.internal.data.EcoPlayerProfile import com.willfp.eco.internal.data.EcoPlayerProfile
import com.willfp.eco.spigot.EcoSpigotPlugin import com.willfp.eco.spigot.data.storage.DataHandler
import org.bukkit.Bukkit import java.util.UUID
import java.util.*
class EcoPlayerProfileHandler( class EcoPlayerProfileHandler(
private val plugin: EcoSpigotPlugin private val handler: DataHandler
) : PlayerProfileHandler { ) : PlayerProfileHandler {
private val loaded = mutableMapOf<UUID, PlayerProfile>() private val loaded = mutableMapOf<UUID, PlayerProfile>()
private val handler = plugin.dataHandler
override fun load(uuid: UUID): PlayerProfile { override fun load(uuid: UUID): PlayerProfile {
val found = loaded[uuid] val found = loaded[uuid]
@@ -23,50 +20,36 @@ class EcoPlayerProfileHandler(
val data = mutableMapOf<PersistentDataKey<*>, Any>() val data = mutableMapOf<PersistentDataKey<*>, Any>()
for (key in Eco.getHandler().keyRegistry.registeredKeys) { for (key in PersistentDataKey.values()) {
data[key] = handler.read(uuid, key.key) ?: key.defaultValue data[key] = handler.read(uuid, key.key) ?: key.defaultValue
} }
val profile = EcoPlayerProfile(data) val profile = EcoPlayerProfile(data, uuid)
loaded[uuid] = profile loaded[uuid] = profile
return profile return profile
} }
fun unloadPlayer(uuid: UUID) { override fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
handler.savePlayer(uuid) val profile = PlayerProfile.load(uuid)
loaded.remove(uuid)
for (key in keys) {
handler.write(uuid, key.key, profile.read(key))
}
} }
fun unloadPlayerBlocking(uuid: UUID) { override fun unloadPlayer(uuid: UUID) {
handler.saveAllBlocking(listOf(uuid))
loaded.remove(uuid) loaded.remove(uuid)
} }
override fun savePlayer(uuid: UUID) {
handler.savePlayer(uuid)
}
override fun saveAll() { override fun saveAll() {
handler.saveAll(loaded.keys.toList()) handler.saveAll(loaded.keys.toList())
} }
fun saveAllBlocking() { override fun save() {
handler.saveAllBlocking(loaded.keys.toList()) handler.save()
} }
fun autosave() { fun updateKeys() {
if (Bukkit.getOnlinePlayers().isEmpty()) { handler.updateKeys()
return
}
if (plugin.configYml.getBool("autosave.log")) {
plugin.logger.info("Auto-Saving player data!")
}
saveAll()
if (plugin.configYml.getBool("autosave.log")) {
plugin.logger.info("Saved player data!")
}
} }
} }

View File

@@ -1,7 +1,8 @@
package com.willfp.eco.spigot.data.storage package com.willfp.eco.spigot.data.storage
import com.willfp.eco.core.data.keys.PersistentDataKey
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
import java.util.UUID import java.util.*
interface DataHandler { interface DataHandler {
fun save() { fun save() {
@@ -10,15 +11,15 @@ interface DataHandler {
fun saveAll(uuids: Iterable<UUID>) fun saveAll(uuids: Iterable<UUID>)
fun saveAllBlocking(uuids: Iterable<UUID>) {
saveAll(uuids)
}
fun updateKeys() { fun updateKeys() {
} }
fun savePlayer(uuid: UUID) {
saveKeysForPlayer(uuid, PersistentDataKey.values())
}
fun <T> write(uuid: UUID, key: NamespacedKey, value: T) fun <T> write(uuid: UUID, key: NamespacedKey, value: T)
fun savePlayer(uuid: UUID) fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>)
fun <T> read(uuid: UUID, key: NamespacedKey): T? fun <T> read(uuid: UUID, key: NamespacedKey): T?
} }

View File

@@ -9,20 +9,9 @@ import com.willfp.eco.spigot.EcoSpigotPlugin
import org.apache.logging.log4j.Level import org.apache.logging.log4j.Level
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
import org.jetbrains.exposed.dao.id.UUIDTable import org.jetbrains.exposed.dao.id.UUIDTable
import org.jetbrains.exposed.sql.BooleanColumnType import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.Database
import org.jetbrains.exposed.sql.DoubleColumnType
import org.jetbrains.exposed.sql.IntegerColumnType
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.SchemaUtils
import org.jetbrains.exposed.sql.VarCharColumnType
import org.jetbrains.exposed.sql.exposedLogger
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update import java.util.*
import java.util.UUID
import java.util.concurrent.Executors import java.util.concurrent.Executors
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@@ -31,7 +20,7 @@ class MySQLDataHandler(
) : DataHandler { ) : DataHandler {
private val columns = mutableMapOf<String, Column<*>>() private val columns = mutableMapOf<String, Column<*>>()
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build() private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build()
private val executor = Executors.newCachedThreadPool(threadFactory) private val executor = Executors.newFixedThreadPool(plugin.configYml.getInt("mysql.threads"), threadFactory)
init { init {
Database.connect( Database.connect(
@@ -73,26 +62,20 @@ class MySQLDataHandler(
writeAsserted(uuid, key, value) writeAsserted(uuid, key, value)
} }
private fun <T> writeAsserted(uuid: UUID, key: NamespacedKey, value: T, async: Boolean = true) { private fun <T> writeAsserted(uuid: UUID, key: NamespacedKey, value: T) {
val column: Column<T> = getColumn(key.toString()) as Column<T> val column: Column<T> = getColumn(key.toString()) as Column<T>
fun executeTransaction() { executor.submit {
transaction { transaction {
Players.update({ Players.id eq uuid }) { Players.update({ Players.id eq uuid }) {
it[column] = value it[column] = value
} }
} }
} }
if (async) {
executor.execute { executeTransaction() }
} else {
executeTransaction()
}
} }
override fun savePlayer(uuid: UUID) { override fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
savePlayer(uuid, async = false) savePlayer(uuid, keys)
} }
override fun saveAll(uuids: Iterable<UUID>) { override fun saveAll(uuids: Iterable<UUID>) {
@@ -101,20 +84,16 @@ class MySQLDataHandler(
} }
} }
override fun saveAllBlocking(uuids: Iterable<UUID>) { private fun savePlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
for (uuid in uuids) {
savePlayer(uuid, async = false)
}
}
private fun savePlayer(uuid: UUID, async: Boolean = true) {
val profile = PlayerProfile.load(uuid) val profile = PlayerProfile.load(uuid)
transaction { executor.submit {
getPlayer(uuid) transaction {
getPlayer(uuid)
for (key in Eco.getHandler().keyRegistry.registeredKeys) { for (key in keys) {
writeAsserted(uuid, key.key, profile.read(key), async = async) writeAsserted(uuid, key.key, profile.read(key))
}
} }
} }
} }
@@ -125,6 +104,7 @@ class MySQLDataHandler(
val player = getPlayer(uuid) val player = getPlayer(uuid)
value = player[getColumn(key.toString())] as T? value = player[getColumn(key.toString())] as T?
} }
return value return value
} }

View File

@@ -0,0 +1,16 @@
package com.willfp.eco.spigot.data.storage
import com.willfp.eco.core.Eco
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.internal.data.EcoPlayerProfile
class ProfileSaver(plugin: EcoPlugin) {
init {
plugin.scheduler.runTimer({
for ((uuid, set) in EcoPlayerProfile.CHANGE_MAP) {
Eco.getHandler().playerProfileHandler.saveKeysForPlayer(uuid, set)
}
EcoPlayerProfile.CHANGE_MAP.clear()
}, 1, 1)
}
}

View File

@@ -1,11 +1,11 @@
package com.willfp.eco.spigot.data.storage package com.willfp.eco.spigot.data.storage
import com.willfp.eco.core.Eco
import com.willfp.eco.core.config.yaml.YamlBaseConfig import com.willfp.eco.core.config.yaml.YamlBaseConfig
import com.willfp.eco.core.data.PlayerProfile import com.willfp.eco.core.data.PlayerProfile
import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.spigot.EcoSpigotPlugin import com.willfp.eco.spigot.EcoSpigotPlugin
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
import java.util.UUID import java.util.*
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
class YamlDataHandler( class YamlDataHandler(
@@ -25,10 +25,10 @@ class YamlDataHandler(
save() save()
} }
override fun savePlayer(uuid: UUID) { override fun saveKeysForPlayer(uuid: UUID, keys: Set<PersistentDataKey<*>>) {
val profile = PlayerProfile.load(uuid) val profile = PlayerProfile.load(uuid)
for (key in Eco.getHandler().keyRegistry.registeredKeys) { for (key in keys) {
write(uuid, key.key, profile.read(key)) write(uuid, key.key, profile.read(key))
} }
} }

View File

@@ -27,7 +27,7 @@ class AntigriefDeluxeCombat: AntigriefWrapper {
override fun canInjure(player: Player, victim: LivingEntity): Boolean { override fun canInjure(player: Player, victim: LivingEntity): Boolean {
val api = DeluxeCombatAPI() val api = DeluxeCombatAPI()
return when(victim) { return when(victim) {
is Player -> (api.hasProtection(victim) || !api.hasPvPEnabled(victim)) && !api.isInCombat(victim) is Player -> ((!api.hasProtection(victim) && api.hasPvPEnabled(victim)) || api.isInCombat(victim))
else -> true else -> true
} }
} }

View File

@@ -9,12 +9,12 @@ import org.bukkit.entity.LivingEntity
import org.bukkit.entity.Player import org.bukkit.entity.Player
class AntigriefIridiumSkyblock : AntigriefWrapper { class AntigriefIridiumSkyblock : AntigriefWrapper {
private val api = IridiumSkyblockAPI.getInstance()
override fun canBreakBlock( override fun canBreakBlock(
player: Player, player: Player,
block: Block block: Block
): Boolean { ): Boolean {
val api = IridiumSkyblockAPI.getInstance() ?: return true
return api.getIslandPermission(api.getIslandViaLocation(block.location).orElse(null) ?: return true, api.getUser(player), PermissionType.BLOCK_BREAK) return api.getIslandPermission(api.getIslandViaLocation(block.location).orElse(null) ?: return true, api.getUser(player), PermissionType.BLOCK_BREAK)
} }
@@ -22,6 +22,8 @@ class AntigriefIridiumSkyblock : AntigriefWrapper {
player: Player, player: Player,
location: Location location: Location
): Boolean { ): Boolean {
val api = IridiumSkyblockAPI.getInstance() ?: return true
return api.getIslandPermission(api.getIslandViaLocation(location).orElse(null) ?: return true, api.getUser(player), PermissionType.BLOCK_BREAK) return api.getIslandPermission(api.getIslandViaLocation(location).orElse(null) ?: return true, api.getUser(player), PermissionType.BLOCK_BREAK)
} }
@@ -29,6 +31,8 @@ class AntigriefIridiumSkyblock : AntigriefWrapper {
player: Player, player: Player,
block: Block block: Block
): Boolean { ): Boolean {
val api = IridiumSkyblockAPI.getInstance() ?: return true
return api.getIslandPermission(api.getIslandViaLocation(block.location).orElse(null) ?: return true, api.getUser(player), PermissionType.BLOCK_PLACE) return api.getIslandPermission(api.getIslandViaLocation(block.location).orElse(null) ?: return true, api.getUser(player), PermissionType.BLOCK_PLACE)
} }
@@ -36,6 +40,8 @@ class AntigriefIridiumSkyblock : AntigriefWrapper {
player: Player, player: Player,
victim: LivingEntity victim: LivingEntity
): Boolean { ): Boolean {
val api = IridiumSkyblockAPI.getInstance() ?: return true
return when (victim) { return when (victim) {
is Player -> api.getIslandViaLocation(victim.location).orElse(null) != null is Player -> api.getIslandViaLocation(victim.location).orElse(null) != null
else -> api.getIslandPermission(api.getIslandViaLocation(victim.location).orElse(null) ?: return true, api.getUser(player), PermissionType.KILL_MOBS) else -> api.getIslandPermission(api.getIslandViaLocation(victim.location).orElse(null) ?: return true, api.getUser(player), PermissionType.KILL_MOBS)

View File

@@ -17,24 +17,32 @@ class AntigriefSuperiorSkyblock2 : AntigriefWrapper {
} }
override fun canBreakBlock(player: Player, block: Block): Boolean { override fun canBreakBlock(player: Player, block: Block): Boolean {
if (SuperiorSkyblockAPI.getPlayer(player).hasBypassModeEnabled()) return true if (SuperiorSkyblockAPI.getPlayer(player).hasBypassModeEnabled()) {
return true
}
return SuperiorSkyblockAPI.getPlayer(player).hasPermission(IslandPrivilege.getByName("Break")) return SuperiorSkyblockAPI.getPlayer(player).hasPermission(IslandPrivilege.getByName("Break"))
|| SuperiorSkyblockAPI.getPlayer(player).hasPermission(IslandPrivilege.getByName("BREAK")) || SuperiorSkyblockAPI.getPlayer(player).hasPermission(IslandPrivilege.getByName("BREAK"))
} }
override fun canCreateExplosion(player: Player, location: Location): Boolean { override fun canCreateExplosion(player: Player, location: Location): Boolean {
if (SuperiorSkyblockAPI.getPlayer(player).hasBypassModeEnabled()) return true if (SuperiorSkyblockAPI.getPlayer(player).hasBypassModeEnabled()) {
return true
}
return SuperiorSkyblockAPI.getIslandAt(location)?.isMember(SuperiorSkyblockAPI.getPlayer(player)) ?: true return SuperiorSkyblockAPI.getIslandAt(location)?.isMember(SuperiorSkyblockAPI.getPlayer(player)) ?: true
} }
override fun canPlaceBlock(player: Player, block: Block): Boolean { override fun canPlaceBlock(player: Player, block: Block): Boolean {
if (SuperiorSkyblockAPI.getPlayer(player).hasBypassModeEnabled()) return true if (SuperiorSkyblockAPI.getPlayer(player).hasBypassModeEnabled()) {
return true
}
return SuperiorSkyblockAPI.getPlayer(player).hasPermission(IslandPrivilege.getByName("Place")) return SuperiorSkyblockAPI.getPlayer(player).hasPermission(IslandPrivilege.getByName("Place"))
|| SuperiorSkyblockAPI.getPlayer(player).hasPermission(IslandPrivilege.getByName("PLACE")) || SuperiorSkyblockAPI.getPlayer(player).hasPermission(IslandPrivilege.getByName("PLACE"))
} }
override fun canInjure(player: Player, victim: LivingEntity): Boolean { override fun canInjure(player: Player, victim: LivingEntity): Boolean {
if (SuperiorSkyblockAPI.getPlayer(player).hasBypassModeEnabled()) return true if (SuperiorSkyblockAPI.getPlayer(player).hasBypassModeEnabled()) {
return true
}
return when (victim) { return when (victim) {
is Player -> SuperiorSkyblockAPI.getPlayer(player).canHit(SuperiorSkyblockAPI.getPlayer(victim)).equals(HitActionResult.SUCCESS) is Player -> SuperiorSkyblockAPI.getPlayer(player).canHit(SuperiorSkyblockAPI.getPlayer(victim)).equals(HitActionResult.SUCCESS)
is Animals -> { is Animals -> {

View File

@@ -5,17 +5,16 @@
mysql: mysql:
enabled: false # Set to false, data.yml will be used instead. enabled: false # Set to false, data.yml will be used instead.
# How many threads to execute statements on. Higher numbers can be faster however
# very high numbers can cause issues with OS configuration. If writes are taking
# too long, increase this value.
threads: 2
host: localhost host: localhost
port: 3306 port: 3306
database: database database: database
user: username user: username
password: passy password: passy
autosave:
ticks: 20000 # The amount of ticks between autosaves
log: false # If auto-save messages should be sent to console
# Options to fix villager bugs left behind from old (buggy) versions. # Options to fix villager bugs left behind from old (buggy) versions.
villager-display-fix: false villager-display-fix: false

View File

@@ -1,2 +1,2 @@
version = 6.13.6 version = 6.13.9
plugin-name = eco plugin-name = eco