Compare commits

..

22 Commits

Author SHA1 Message Date
Auxilor
183b18c0ec Updated to 6.17.6 2021-12-29 18:47:44 +00:00
Auxilor
e026a767d9 Fixed v1_18_R1 bugs 2021-12-29 18:47:33 +00:00
Auxilor
d2966aa428 Updated to 6.17.5 2021-12-26 17:21:21 +00:00
Auxilor
9168e68b5a StringUtils#jsonToLegacy will now fail silently 2021-12-26 17:21:01 +00:00
Auxilor
51a61b65c6 Updated to 6.17.4 2021-12-26 16:57:54 +00:00
Auxilor
76be236dac Error catching to StringUtils#jsonToLegacy 2021-12-26 16:56:53 +00:00
Auxilor
f1bbac2dd0 Codestyle 2021-12-26 16:48:03 +00:00
Auxilor
6e88aef572 FastItemStack#getLore changes 2021-12-26 16:40:09 +00:00
Auxilor
804f187964 legacy <-> json changes 2021-12-26 16:34:52 +00:00
Auxilor
623b8a18f4 Codestyle 2021-12-26 16:20:38 +00:00
Auxilor
0d4e424582 Codestyle 2021-12-26 16:19:59 +00:00
Auxilor
452e499467 Added NumberUtils#logBase 2021-12-26 16:10:33 +00:00
Auxilor
b2950ab035 Added ListUtils#containsIgnoreCase 2021-12-26 12:53:57 +00:00
Auxilor
e47d05ccb2 NMS changes 2021-12-26 12:23:13 +00:00
Auxilor
b9e61b8c0d Merged v1_18_R1 thanks to paperweight update 2021-12-26 12:17:02 +00:00
Auxilor
0f35d5d16e Updated to 6.17.3 2021-12-21 12:20:33 +00:00
Stealth2800
3a7315d728 Make defensive copy of CustomItem's returned item 2021-12-20 20:24:21 -08:00
Auxilor
6f193f70b0 Staggered player profile loading to load when needed 2021-12-15 12:26:20 +00:00
Auxilor
bab3f078f6 Added @JvmStatic mention to @ConfigUpdater 2021-12-15 11:28:07 +00:00
Auxilor
5b4b17b97f Updated to 6.17.2 2021-12-15 10:31:16 +00:00
Auxilor
f0e02ca25e Added HikariCP to plugin.yml 2021-12-15 10:31:05 +00:00
Auxilor
7426e9adba Updated to use hikari 2021-12-15 10:30:49 +00:00
29 changed files with 558 additions and 56 deletions

View File

@@ -12,7 +12,7 @@ dependencies {
implementation(project(":eco-core:core-backend"))
implementation(project(":eco-core:core-nms:v1_16_R3"))
implementation(project(path = ":eco-core:core-nms:v1_17_R1", configuration = "reobf"))
implementation(project(":eco-core:core-nms:v1_18_R1"))
implementation(project(path = ":eco-core:core-nms:v1_18_R1", configuration = "reobf"))
}
allprojects {

View File

@@ -28,6 +28,9 @@ import java.lang.annotation.Target;
* }
* }</pre>
* <p>
* If using kotlin, you have to annotate the method with {@code @JvmStatic}
* in order to prevent null pointer exceptions.
* <p>
* Config update methods in all classes in a plugin jar will be called
* on reload.
* <p>

View File

@@ -66,7 +66,7 @@ public class CustomItem implements TestableItem {
@Override
public ItemStack getItem() {
return item;
return item.clone();
}
/**

View File

@@ -39,7 +39,7 @@ public class EnchantedBookBuilder extends AbstractItemStackBuilder<EnchantmentSt
* @return The builder.
*/
public EnchantedBookBuilder addStoredEnchantment(@NotNull final Supplier<Enchantment> enchantment,
final Supplier<Integer> level) {
@NotNull final Supplier<Integer> level) {
return this.addStoredEnchantment(enchantment.get(), level.get());
}
}

View File

@@ -92,7 +92,7 @@ public class Paste {
conn.setRequestMethod("GET");
try (var reader = new BufferedReader(
new InputStreamReader(conn.getInputStream()))) {
for (String line; (line = reader.readLine()) != null; ) {
for (String line; (line = reader.readLine()) != null;) {
result.append(line);
}
}

View File

@@ -91,6 +91,24 @@ public final class ListUtils {
return index >= 0 && index < list.size() ? list.get(index) : null;
}
/**
* Get if an iterable of strings contains a certain element regardless of case.
*
* @param list The list.
* @param element The element.
* @return If contained.
*/
public static boolean containsIgnoreCase(@NotNull final Iterable<String> list,
@NotNull final String element) {
for (String s : list) {
if (s.equalsIgnoreCase(element)) {
return true;
}
}
return false;
}
private ListUtils() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}

View File

@@ -185,11 +185,23 @@ public final class NumberUtils {
/**
* Get Log base 2 of a number.
*
* @param toLog The number.
* @param a The number.
* @return The result.
*/
public static int log2(final int toLog) {
return (int) (Math.log(toLog) / Math.log(2));
public static int log2(final int a) {
return (int) logBase(a, 2);
}
/**
* Log with a base.
*
* @param a The number.
* @param base The base.
* @return The logarithm.
*/
public static double logBase(final double a,
final double base) {
return Math.log(a) / Math.log(base);
}
/**

View File

@@ -2,6 +2,7 @@ package com.willfp.eco.util;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.gson.JsonSyntaxException;
import com.willfp.eco.core.Prerequisite;
import com.willfp.eco.core.integrations.placeholder.PlaceholderManager;
import net.kyori.adventure.text.Component;
@@ -58,6 +59,13 @@ public final class StringUtils {
.hexColors()
.build();
/**
* GSON serializer.
*/
private static final GsonComponentSerializer GSON_COMPONENT_SERIALIZER = GsonComponentSerializer.builder()
.emitLegacyHoverEvent()
.build();
/**
* Color map.
*/
@@ -415,7 +423,7 @@ public final class StringUtils {
if (legacy == null) {
processed = "";
}
return GsonComponentSerializer.gson().serialize(
return GSON_COMPONENT_SERIALIZER.serialize(
Component.empty().decoration(TextDecoration.ITALIC, false).append(
LEGACY_COMPONENT_SERIALIZER.deserialize(processed)
)
@@ -429,10 +437,17 @@ public final class StringUtils {
* @return The legacy string.
*/
@NotNull
public static String jsonToLegacy(@NotNull final String json) {
return LEGACY_COMPONENT_SERIALIZER.serialize(
GsonComponentSerializer.gson().deserialize(json)
);
public static String jsonToLegacy(@Nullable final String json) {
if (json == null || json.isEmpty()) {
return "";
}
try {
Component component = GSON_COMPONENT_SERIALIZER.deserialize(json);
return LEGACY_COMPONENT_SERIALIZER.serialize(component);
} catch (JsonSyntaxException e) {
return json;
}
}
/**

View File

@@ -1,5 +1,5 @@
plugins {
id("io.papermc.paperweight.userdev") version "1.2.0"
id("io.papermc.paperweight.userdev") version "1.3.3"
}
group = "com.willfp"

View File

@@ -87,33 +87,29 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
override fun getLore(): List<String> {
if (loreCache != null) {
return loreCache as List<String>
}
val lore: MutableList<String> = ArrayList()
for (s in getLoreJSON()) {
lore.add(StringUtils.jsonToLegacy(s))
return loreCache!!
}
val lore = this.getLoreJSON().map { StringUtils.jsonToLegacy(it) }
loreCache = lore
return lore
}
private fun getLoreJSON(): List<String> {
val displayTag = handle.getTagElement("display") ?: return emptyList()
return if (displayTag.contains("Lore")) {
val loreTag = displayTag.getList("Lore", CraftMagicNumbers.NBT.TAG_STRING)
val lore: MutableList<String> = ArrayList(loreTag.size)
for (i in loreTag.indices) {
lore.add(loreTag.getString(i))
}
lore
} else {
emptyList()
if (!displayTag.contains("Lore")) {
return emptyList()
}
val loreTag = displayTag.getList("Lore", CraftMagicNumbers.NBT.TAG_STRING)
val lore = mutableListOf<String>()
for (i in loreTag.indices) {
lore.add(loreTag.getString(i))
}
return lore
}
override fun addItemFlags(vararg hideFlags: ItemFlag) {
@@ -155,11 +151,11 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
private var flagBits: Int
get() =
if (handle.hasTag() && handle.tag!!.contains(
if (handle.hasTag() && handle.tag.contains(
"HideFlags",
99
)
) handle.tag!!.getInt("HideFlags") else 0
) handle.tag.getInt("HideFlags") else 0
set(value) =
handle.orCreateTag.putInt("HideFlags", value)
@@ -188,4 +184,4 @@ class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemS
bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta
}
}
}
}

View File

@@ -1,6 +1,16 @@
plugins {
id("io.papermc.paperweight.userdev") version "1.3.3"
}
group = "com.willfp"
version = rootProject.version
dependencies {
implementation(files("./impl.jar"))
paperDevBundle("1.18.1-R0.1-SNAPSHOT")
}
tasks {
build {
dependsOn(reobfJar)
}
}

Binary file not shown.

View File

@@ -0,0 +1,15 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
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")
}
}

View File

@@ -0,0 +1,14 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
import com.willfp.eco.internal.spigot.proxy.BlockBreakProxy
import org.bukkit.block.Block
import org.bukkit.entity.Player
class BlockBreak : BlockBreakProxy {
override fun breakBlock(
player: Player,
block: Block
) {
player.breakBlock(block)
}
}

View File

@@ -0,0 +1,93 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
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_18_R1.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.of(
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)
}
}

View File

@@ -0,0 +1,12 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
import com.willfp.eco.core.fast.FastItemStack
import com.willfp.eco.internal.spigot.proxy.v1_18_R1.fast.NMSFastItemStack
import com.willfp.eco.internal.spigot.proxy.FastItemStackFactoryProxy
import org.bukkit.inventory.ItemStack
class FastItemStackFactory : FastItemStackFactoryProxy {
override fun create(itemStack: ItemStack): FastItemStack {
return NMSFastItemStack(itemStack)
}
}

View File

@@ -0,0 +1,44 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
import com.mojang.authlib.GameProfile
import com.mojang.authlib.properties.Property
import com.willfp.eco.internal.spigot.proxy.SkullProxy
import org.bukkit.inventory.meta.SkullMeta
import java.lang.reflect.Field
import java.lang.reflect.Method
import java.util.UUID
class Skull : SkullProxy {
private lateinit var setProfile: Method
private lateinit var profile: Field
override fun setSkullTexture(
meta: SkullMeta,
base64: String
) {
if (!this::setProfile.isInitialized) {
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
setProfile.isAccessible = true
}
val uuid = UUID(
base64.substring(base64.length - 20).hashCode().toLong(),
base64.substring(base64.length - 10).hashCode().toLong()
)
val profile = GameProfile(uuid, "eco")
profile.properties.put("textures", Property("textures", base64))
setProfile.invoke(meta, profile)
}
override fun getSkullTexture(
meta: SkullMeta
): String? {
if (!this::profile.isInitialized) {
profile = meta.javaClass.getDeclaredField("profile")
profile.isAccessible = true
}
val profile = profile[meta] as GameProfile? ?: return null
val properties = profile.properties ?: return null
val prop = properties["textures"] ?: return null
return prop.toMutableList().firstOrNull()?.name
}
}

View File

@@ -0,0 +1,11 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
import com.willfp.eco.internal.spigot.proxy.TPSProxy
import org.bukkit.Bukkit
import org.bukkit.craftbukkit.v1_18_R1.CraftServer
class TPS : TPSProxy {
override fun getTPS(): Double {
return (Bukkit.getServer() as CraftServer).handle.server.recentTps[0]
}
}

View File

@@ -0,0 +1,41 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1
import com.willfp.eco.core.display.Display
import com.willfp.eco.internal.spigot.proxy.VillagerTradeProxy
import net.minecraft.world.item.trading.MerchantOffer
import org.bukkit.craftbukkit.v1_18_R1.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 {
val oldRecipe = recipe as CraftMerchantRecipe
val newRecipe = CraftMerchantRecipe(
Display.display(recipe.getResult().clone(), player),
recipe.getUses(),
recipe.getMaxUses(),
recipe.hasExperienceReward(),
recipe.getVillagerExperience(),
recipe.getPriceMultiplier()
)
for (ingredient in recipe.getIngredients()) {
newRecipe.addIngredient(Display.display(ingredient.clone(), player))
}
getHandle(newRecipe).setSpecialPriceDiff(getHandle(oldRecipe).getSpecialPriceDiff())
return newRecipe
}
private fun getHandle(recipe: CraftMerchantRecipe): MerchantOffer {
return handle[recipe] as MerchantOffer
}
init {
handle.isAccessible = true
}
}

View File

@@ -0,0 +1,17 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1.fast
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack
import org.bukkit.inventory.ItemStack
import java.lang.reflect.Field
private val field: Field = CraftItemStack::class.java.getDeclaredField("handle").apply {
isAccessible = true
}
fun ItemStack.getNMSStack(): net.minecraft.world.item.ItemStack {
return if (this !is CraftItemStack) {
CraftItemStack.asNMSCopy(this)
} else {
field[this] as net.minecraft.world.item.ItemStack? ?: CraftItemStack.asNMSCopy(this)
}
}

View File

@@ -0,0 +1,188 @@
package com.willfp.eco.internal.spigot.proxy.v1_18_R1.fast
import com.willfp.eco.internal.fast.EcoFastItemStack
import com.willfp.eco.util.StringUtils
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.StringTag
import net.minecraft.world.item.EnchantedBookItem
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import org.bukkit.craftbukkit.v1_18_R1.inventory.CraftItemStack
import org.bukkit.craftbukkit.v1_18_R1.util.CraftMagicNumbers
import org.bukkit.craftbukkit.v1_18_R1.util.CraftNamespacedKey
import org.bukkit.enchantments.Enchantment
import org.bukkit.inventory.ItemFlag
import kotlin.experimental.and
@Suppress("UsePropertyAccessSyntax")
class NMSFastItemStack(itemStack: org.bukkit.inventory.ItemStack) : EcoFastItemStack<ItemStack>(
itemStack.getNMSStack(), itemStack
) {
private var loreCache: List<String>? = null
override fun getEnchantmentsOnItem(checkStored: Boolean): Map<Enchantment, Int> {
val enchantmentNBT =
if (checkStored && handle.item === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
handle
) else handle.enchantmentTags
val foundEnchantments: MutableMap<Enchantment, Int> = HashMap()
for (base in enchantmentNBT) {
val compound = base as CompoundTag
val key = compound.getString("id")
val level = ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt()
val found = Enchantment.getByKey(CraftNamespacedKey.fromStringOrNull(key))
if (found != null) {
foundEnchantments[found] = level
}
}
return foundEnchantments
}
override fun getLevelOnItem(
enchantment: Enchantment,
checkStored: Boolean
): Int {
val enchantmentNBT =
if (checkStored && handle.item === Items.ENCHANTED_BOOK) EnchantedBookItem.getEnchantments(
handle
) else handle.enchantmentTags
for (base in enchantmentNBT) {
val compound = base as CompoundTag
val key = compound.getString("id")
if (key != enchantment.key.toString()) {
continue
}
return ('\uffff'.code.toShort() and compound.getShort("lvl")).toInt()
}
return 0
}
override fun setLore(lore: List<String>?) {
loreCache = null
val jsonLore: MutableList<String> = ArrayList()
if (lore != null) {
for (s in lore) {
jsonLore.add(StringUtils.legacyToJson(s))
}
}
val displayTag = handle.getOrCreateTagElement("display")
if (!displayTag.contains("Lore")) {
displayTag.put("Lore", ListTag())
}
val loreTag = displayTag.getList("Lore", CraftMagicNumbers.NBT.TAG_STRING)
loreTag.clear()
for (s in jsonLore) {
loreTag.add(StringTag.valueOf(s))
}
apply()
}
override fun getLore(): List<String> {
if (loreCache != null) {
return loreCache!!
}
val lore = this.getLoreJSON().map { StringUtils.jsonToLegacy(it) }
loreCache = lore
return lore
}
private fun getLoreJSON(): List<String> {
val displayTag = handle.getTagElement("display") ?: return emptyList()
if (!displayTag.contains("Lore")) {
return emptyList()
}
val loreTag = displayTag.getList("Lore", CraftMagicNumbers.NBT.TAG_STRING)
val lore = ArrayList<String>(loreTag.size)
for (i in loreTag.indices) {
lore.add(loreTag.getString(i))
}
return lore
}
override fun addItemFlags(vararg hideFlags: ItemFlag) {
for (flag in hideFlags) {
this.flagBits = this.flagBits or getBitModifier(flag)
}
apply()
}
override fun removeItemFlags(vararg hideFlags: ItemFlag) {
for (flag in hideFlags) {
this.flagBits = this.flagBits and getBitModifier(flag)
}
apply()
}
override fun getItemFlags(): MutableSet<ItemFlag> {
val flags = mutableSetOf<ItemFlag>()
var flagArr: Array<ItemFlag>
val size = ItemFlag.values().also { flagArr = it }.size
for (i in 0 until size) {
val flag = flagArr[i]
if (this.hasItemFlag(flag)) {
flags.add(flag)
}
}
return flags
}
override fun hasItemFlag(flag: ItemFlag): Boolean {
val bitModifier = getBitModifier(flag)
return this.flagBits and bitModifier == bitModifier
}
private var flagBits: Int
get() =
if (handle.hasTag() && handle.tag!!.contains(
"HideFlags",
99
)
) handle.tag!!.getInt("HideFlags") else 0
set(value) =
handle.orCreateTag.putInt("HideFlags", value)
override fun getRepairCost(): Int {
return handle.baseRepairCost
}
override fun setRepairCost(cost: Int) {
handle.setRepairCost(cost)
}
override fun equals(other: Any?): Boolean {
if (other !is NMSFastItemStack) {
return false
}
return other.hashCode() == this.hashCode()
}
override fun hashCode(): Int {
return handle.tag?.hashCode() ?: (0b00010101 * 31 + Item.getId(handle.getItem()))
}
private fun apply() {
if (bukkit !is CraftItemStack) {
bukkit.itemMeta = CraftItemStack.asCraftMirror(handle).itemMeta
}
}
}

View File

@@ -16,7 +16,9 @@ dependencies {
compileOnly 'com.github.TechFortress:GriefPrevention:16.17.1'
compileOnly 'com.massivecraft:Factions:1.6.9.5-U0.5.10'
compileOnly 'com.github.cryptomorin:kingdoms:1.11.9'
compileOnly 'com.github.TownyAdvanced:Towny:0.97.2.6'
compileOnly('com.github.TownyAdvanced:Towny:0.97.2.6') {
exclude group: 'com.zaxxer', module: 'HikariCP'
}
compileOnly 'com.github.angeschossen:LandsAPI:5.15.2'
compileOnly 'fr.neatmonster:nocheatplus:3.16.1-SNAPSHOT'
compileOnly 'com.github.jiangdashao:matrix-api-repo:317d4635fd'
@@ -30,6 +32,7 @@ dependencies {
compileOnly 'org.jetbrains.exposed:exposed-dao:0.36.2'
compileOnly 'org.jetbrains.exposed:exposed-jdbc:0.36.2'
compileOnly 'mysql:mysql-connector-java:8.0.25'
compileOnly 'com.zaxxer:HikariCP:5.0.0'
compileOnly 'com.gmail.filoghost.holographicdisplays:holographicdisplays-api:2.4.0'
compileOnly 'com.github.EssentialsX:Essentials:2.19.0'
compileOnly 'com.bgsoftware:SuperiorSkyblockAPI:latest'

View File

@@ -1,13 +1,15 @@
package com.willfp.eco.internal.data
package com.willfp.eco.internal.spigot.data
import com.willfp.eco.core.data.PlayerProfile
import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.internal.spigot.data.storage.DataHandler
import java.util.UUID
import java.util.concurrent.ConcurrentHashMap
class EcoPlayerProfile(
val data: MutableMap<PersistentDataKey<*>, Any>,
val uuid: UUID
val uuid: UUID,
private val handler: DataHandler
) : PlayerProfile {
override fun <T : Any> write(key: PersistentDataKey<T>, value: T) {
this.data[key] = value
@@ -19,7 +21,12 @@ class EcoPlayerProfile(
override fun <T : Any> read(key: PersistentDataKey<T>): T {
@Suppress("UNCHECKED_CAST")
return this.data[key] as T? ?: key.defaultValue
if (this.data.containsKey(key)) {
return this.data[key] as T
}
this.data[key] = handler.read(uuid, key.key) ?: key.defaultValue
return read(key)
}
override fun equals(other: Any?): Boolean {

View File

@@ -3,7 +3,6 @@ package com.willfp.eco.internal.spigot.data
import com.willfp.eco.core.data.PlayerProfile
import com.willfp.eco.core.data.PlayerProfileHandler
import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.internal.data.EcoPlayerProfile
import com.willfp.eco.internal.spigot.data.storage.DataHandler
import java.util.UUID
@@ -20,11 +19,7 @@ class EcoPlayerProfileHandler(
val data = mutableMapOf<PersistentDataKey<*>, Any>()
for (key in PersistentDataKey.values()) {
data[key] = handler.read(uuid, key.key) ?: key.defaultValue
}
val profile = EcoPlayerProfile(data, uuid)
val profile = EcoPlayerProfile(data, uuid, handler)
loaded[uuid] = profile
return profile
}

View File

@@ -6,6 +6,8 @@ import com.willfp.eco.core.data.PlayerProfile
import com.willfp.eco.core.data.keys.PersistentDataKey
import com.willfp.eco.core.data.keys.PersistentDataKeyType
import com.willfp.eco.internal.spigot.EcoSpigotPlugin
import com.zaxxer.hikari.HikariConfig
import com.zaxxer.hikari.HikariDataSource
import org.apache.logging.log4j.Level
import org.bukkit.NamespacedKey
import org.jetbrains.exposed.dao.id.UUIDTable
@@ -35,15 +37,18 @@ class MySQLDataHandler(
private val executor = Executors.newFixedThreadPool(plugin.configYml.getInt("mysql.threads"), threadFactory)
init {
Database.connect(
"jdbc:mysql://" +
"${plugin.configYml.getString("mysql.host")}:" +
"${plugin.configYml.getString("mysql.port")}/" +
plugin.configYml.getString("mysql.database"),
driver = "com.mysql.cj.jdbc.Driver",
user = plugin.configYml.getString("mysql.user"),
password = plugin.configYml.getString("mysql.password")
)
val config = HikariConfig()
config.driverClassName = "com.mysql.cj.jdbc.Driver"
config.username = plugin.configYml.getString("mysql.user")
config.password = plugin.configYml.getString("mysql.password")
config.jdbcUrl = "jdbc:mysql://" +
"${plugin.configYml.getString("mysql.host")}:" +
"${plugin.configYml.getString("mysql.port")}/" +
plugin.configYml.getString("mysql.database")
config.maximumPoolSize = plugin.configYml.getInt("mysql.connections")
Database.connect(HikariDataSource(config))
transaction {
SchemaUtils.create(Players)

View File

@@ -2,7 +2,7 @@ package com.willfp.eco.internal.spigot.data.storage
import com.willfp.eco.core.Eco
import com.willfp.eco.core.EcoPlugin
import com.willfp.eco.internal.data.EcoPlayerProfile
import com.willfp.eco.internal.spigot.data.EcoPlayerProfile
class ProfileSaver(plugin: EcoPlugin) {
init {

View File

@@ -9,6 +9,8 @@ mysql:
# very high numbers can cause issues with OS configuration. If writes are taking
# too long, increase this value.
threads: 2
# The maximum number of MySQL connections.
connections: 10
# If read operations should be ran in the thread pool. Runs on main thread by default.
async-reads: false
host: localhost

View File

@@ -51,4 +51,5 @@ libraries:
- 'org.jetbrains.exposed:exposed-dao:0.36.2'
- 'org.jetbrains.exposed:exposed-jdbc:0.36.2'
- 'mysql:mysql-connector-java:8.0.25'
- 'com.google.guava:guava:31.0.1-jre'
- 'com.google.guava:guava:31.0.1-jre'
- 'com.zaxxer:HikariCP:5.0.0'

View File

@@ -1,3 +1,3 @@
version = 6.17.1
version = 6.17.6
plugin-name = eco
kotlin.code.style = official