Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6f139c47e | ||
|
|
1bae159f94 | ||
|
|
43d2835087 | ||
|
|
cb2d4d6a34 | ||
|
|
9bb73d8e90 | ||
|
|
86c4867206 | ||
|
|
43e13248d6 | ||
|
|
f6ff45228a | ||
|
|
af1c20f5c5 | ||
|
|
9ac564c345 | ||
|
|
857d51a7a1 | ||
|
|
ab5f8cee5a | ||
|
|
bdd518b280 | ||
|
|
494c1a87b2 | ||
|
|
f78f92b5f6 | ||
|
|
048b56c58c | ||
|
|
75dec2bf49 | ||
|
|
7119da13b7 | ||
|
|
6a8637922b | ||
|
|
abce7b898c | ||
|
|
562d7f382c | ||
|
|
c72b15c3a6 | ||
|
|
54b7e99c82 | ||
|
|
4b6a0ee05d | ||
|
|
89e5d8898b | ||
|
|
08c14f4def | ||
|
|
0fa6f972c0 | ||
|
|
8837fecfa0 | ||
|
|
af1841770e | ||
|
|
1d85dbf08d | ||
|
|
ba9812534a | ||
|
|
1f95a33385 | ||
|
|
bc652a8154 | ||
|
|
0c2e1f0cae | ||
|
|
39d6eb7f9a | ||
|
|
61bae6de55 | ||
|
|
86f230c836 | ||
|
|
aa4ac4c6d1 | ||
|
|
7141b12e95 | ||
|
|
2382548629 | ||
|
|
0c4bd182f7 | ||
|
|
e90e053b45 | ||
|
|
742c1abb00 | ||
|
|
c0686ca386 | ||
|
|
db2ea7daa9 | ||
|
|
ed4f0b2ab6 |
12
build.gradle
12
build.gradle
@@ -31,10 +31,10 @@ allprojects {
|
||||
// NMS (for jitpack compilation)
|
||||
maven { url 'https://repo.codemc.org/repository/nms/' }
|
||||
|
||||
// bStats, mcMMO
|
||||
maven { url 'https://repo.codemc.org/repository/maven-public' }
|
||||
// bStats, mcMMO, BentoBox
|
||||
maven { url 'https://repo.codemc.org/repository/maven-public/' }
|
||||
|
||||
// Spigot API
|
||||
// Spigot API, Bungee API
|
||||
maven { url 'https://hub.spigotmc.org/nexus/content/repositories/snapshots/' }
|
||||
|
||||
// PlaceholderAPI
|
||||
@@ -54,6 +54,12 @@ allprojects {
|
||||
|
||||
// CombatLogX
|
||||
maven { url 'https://nexus.sirblobman.xyz/repository/public/' }
|
||||
|
||||
// IridiumSkyblock
|
||||
maven { url 'https://nexus.iridiumdevelopment.net/repository/maven-releases/' }
|
||||
|
||||
// Velocity
|
||||
maven { url 'https://repo.velocitypowered.com/snapshots/' }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.core;
|
||||
|
||||
import com.willfp.eco.core.integrations.economy.EconomyManager;
|
||||
import com.willfp.eco.core.proxy.ProxyConstants;
|
||||
import com.willfp.eco.util.ClassUtils;
|
||||
import lombok.Getter;
|
||||
@@ -31,8 +32,11 @@ public class Prerequisite {
|
||||
);
|
||||
|
||||
/**
|
||||
* Requires the server to be running an implementation of paper.
|
||||
* Requires the server to have vault installed.
|
||||
*
|
||||
* @deprecated Use {@link EconomyManager#hasRegistrations()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final Prerequisite HAS_VAULT = new Prerequisite(
|
||||
() -> ClassUtils.exists("net.milkbowl.vault.economy.Economy"),
|
||||
"Requires server to have vault"
|
||||
@@ -46,6 +50,22 @@ public class Prerequisite {
|
||||
"Requires server to be running 1.17+"
|
||||
);
|
||||
|
||||
/**
|
||||
* Requires the server to be running an implementation of BungeeCord.
|
||||
*/
|
||||
public static final Prerequisite HAS_BUNGEECORD = new Prerequisite(
|
||||
() -> ClassUtils.exists("net.md_5.bungee.api.event.ServerConnectedEvent"),
|
||||
"Requires server to be running BungeeCord (or a fork)"
|
||||
);
|
||||
|
||||
/**
|
||||
* Requires the server to be running an implementation of Velocity.
|
||||
*/
|
||||
public static final Prerequisite HAS_VELOCITY = new Prerequisite(
|
||||
() -> ClassUtils.exists("com.velocitypowered.api.event.player.ServerConnectedEvent"),
|
||||
"Requires server to be running Velocity (or a fork)"
|
||||
);
|
||||
|
||||
/**
|
||||
* If the necessary prerequisite condition has been met.
|
||||
*/
|
||||
|
||||
@@ -27,6 +27,15 @@ public interface PlayerProfileHandler {
|
||||
* Save all player data.
|
||||
*
|
||||
* @param async If the saving should be done asynchronously.
|
||||
* @deprecated async is now handled automatically depending on implementation.
|
||||
*/
|
||||
void saveAll(boolean async);
|
||||
@Deprecated
|
||||
default void saveAll(boolean async) {
|
||||
saveAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save all player data.
|
||||
*/
|
||||
void saveAll();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ import lombok.Getter;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A persistent data key is a key with a type that can be stored about an offline player.
|
||||
*
|
||||
@@ -54,4 +56,13 @@ public class PersistentDataKey<T> {
|
||||
+ ", type=" + type
|
||||
+ '}';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all persistent data keys.
|
||||
*
|
||||
* @return The keys.
|
||||
*/
|
||||
public static Set<PersistentDataKey<?>> values() {
|
||||
return Eco.getHandler().getKeyRegistry().getRegisteredKeys();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.willfp.eco.core.display;
|
||||
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@@ -21,7 +20,6 @@ public class Display {
|
||||
/**
|
||||
* The display handler.
|
||||
*/
|
||||
@Setter
|
||||
private static DisplayHandler handler = null;
|
||||
|
||||
/**
|
||||
@@ -162,4 +160,20 @@ public class Display {
|
||||
module.display(itemStack, player, args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the display handler.
|
||||
* <p>
|
||||
* Internal API component, you will cause bugs if you create your own handler.
|
||||
*
|
||||
* @param handler The handler.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public static void setHandler(@NotNull final DisplayHandler handler) {
|
||||
if (Display.handler != null) {
|
||||
throw new IllegalStateException("Display already initialized!");
|
||||
}
|
||||
|
||||
Display.handler = handler;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public interface AntigriefWrapper extends Integration {
|
||||
*
|
||||
* @param player The player.
|
||||
* @param block The block.
|
||||
* @return If player cna break block.
|
||||
* @return If player can break block.
|
||||
*/
|
||||
boolean canBreakBlock(Player player, Block block);
|
||||
|
||||
|
||||
@@ -26,6 +26,15 @@ public class EconomyManager {
|
||||
registered.add(integration);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if any economy registrations are registered.
|
||||
*
|
||||
* @return If any economy.
|
||||
*/
|
||||
public boolean hasRegistrations() {
|
||||
return !registered.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get if a player has a certain amount.
|
||||
*
|
||||
@@ -33,8 +42,8 @@ public class EconomyManager {
|
||||
* @param amount The amount.
|
||||
* @return If the player has the amount.
|
||||
*/
|
||||
boolean hasAmount(@NotNull final OfflinePlayer player,
|
||||
final double amount) {
|
||||
public boolean hasAmount(@NotNull final OfflinePlayer player,
|
||||
final double amount) {
|
||||
for (EconomyWrapper wrapper : registered) {
|
||||
return wrapper.hasAmount(player, amount);
|
||||
}
|
||||
@@ -49,8 +58,8 @@ public class EconomyManager {
|
||||
* @param amount The amount to give.
|
||||
* @return If the transaction was a success.
|
||||
*/
|
||||
boolean giveMoney(@NotNull final OfflinePlayer player,
|
||||
final double amount) {
|
||||
public boolean giveMoney(@NotNull final OfflinePlayer player,
|
||||
final double amount) {
|
||||
for (EconomyWrapper wrapper : registered) {
|
||||
return wrapper.giveMoney(player, amount);
|
||||
}
|
||||
@@ -65,8 +74,8 @@ public class EconomyManager {
|
||||
* @param amount The amount to remove.
|
||||
* @return If the transaction was a success.
|
||||
*/
|
||||
boolean removeMoney(@NotNull final OfflinePlayer player,
|
||||
final double amount) {
|
||||
public boolean removeMoney(@NotNull final OfflinePlayer player,
|
||||
final double amount) {
|
||||
for (EconomyWrapper wrapper : registered) {
|
||||
return wrapper.removeMoney(player, amount);
|
||||
}
|
||||
@@ -80,7 +89,7 @@ public class EconomyManager {
|
||||
* @param player The player.
|
||||
* @return The balance.
|
||||
*/
|
||||
double getBalance(@NotNull final OfflinePlayer player) {
|
||||
public double getBalance(@NotNull final OfflinePlayer player) {
|
||||
for (EconomyWrapper wrapper : registered) {
|
||||
return wrapper.getBalance(player);
|
||||
}
|
||||
|
||||
@@ -73,6 +73,11 @@ public abstract class AbstractItemStackBuilder<T extends ItemMeta, U extends Abs
|
||||
@Override
|
||||
public U addEnchantment(@NotNull final Enchantment enchantment,
|
||||
final int level) {
|
||||
//noinspection ConstantConditions
|
||||
if (enchantment == null) {
|
||||
return (U) this;
|
||||
}
|
||||
|
||||
meta.addEnchant(enchantment, level, true);
|
||||
return (U) this;
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ public class ListUtils {
|
||||
* @return The list, filled will null objects.
|
||||
*/
|
||||
@NotNull
|
||||
public <@Nullable T> List<List<T>> create2DList(final int rows,
|
||||
final int columns) {
|
||||
public static <@Nullable T> List<List<T>> create2DList(final int rows,
|
||||
final int columns) {
|
||||
List<List<T>> list = new ArrayList<>(rows);
|
||||
while (list.size() < rows) {
|
||||
List<T> row = new ArrayList<>(columns);
|
||||
@@ -45,7 +45,7 @@ public class ListUtils {
|
||||
* @return The frequency map.
|
||||
*/
|
||||
@NotNull
|
||||
private static <T> Map<T, Integer> listToFrequencyMap(@NotNull final List<T> list) {
|
||||
public static <T> Map<T, Integer> listToFrequencyMap(@NotNull final List<T> list) {
|
||||
Map<T, Integer> frequencyMap = new HashMap<>();
|
||||
for (T object : list) {
|
||||
if (frequencyMap.containsKey(object)) {
|
||||
|
||||
48
eco-api/src/main/java/com/willfp/eco/util/ServerUtils.java
Normal file
48
eco-api/src/main/java/com/willfp/eco/util/ServerUtils.java
Normal file
@@ -0,0 +1,48 @@
|
||||
package com.willfp.eco.util;
|
||||
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Utilities / API methods for the server.
|
||||
*/
|
||||
@UtilityClass
|
||||
public class ServerUtils {
|
||||
/**
|
||||
* The TPS supplier.
|
||||
*/
|
||||
private Supplier<Double> tpsSupplier = null;
|
||||
|
||||
/**
|
||||
* Get the current server TPS.
|
||||
*
|
||||
* @return The TPS.
|
||||
*/
|
||||
public double getTps() {
|
||||
Validate.notNull(tpsSupplier, "Not initialized!");
|
||||
|
||||
double tps = tpsSupplier.get();
|
||||
|
||||
if (tps > 20) {
|
||||
return 20;
|
||||
} else {
|
||||
return tps;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the tps supplier function.
|
||||
*
|
||||
* @param function The function.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public void initialize(@NotNull final Supplier<Double> function) {
|
||||
Validate.isTrue(tpsSupplier == null, "Already initialized!");
|
||||
|
||||
tpsSupplier = function;
|
||||
}
|
||||
}
|
||||
@@ -7,4 +7,5 @@ dependencies {
|
||||
compileOnly 'org.reflections:reflections:0.9.12'
|
||||
compileOnly 'net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT'
|
||||
compileOnly 'net.kyori:adventure-platform-bukkit:4.0.0'
|
||||
compileOnly 'com.google.guava:guava:31.0.1-jre'
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.willfp.eco.internal.display
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.display.Display
|
||||
import com.willfp.eco.core.display.DisplayHandler
|
||||
@@ -10,16 +11,11 @@ import org.bukkit.NamespacedKey
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.persistence.PersistentDataType
|
||||
import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class EcoDisplayHandler(plugin: EcoPlugin) : DisplayHandler {
|
||||
/**
|
||||
* All registered display modules.
|
||||
*/
|
||||
private val registeredModules = mutableMapOf<DisplayPriority, MutableList<DisplayModule>>()
|
||||
|
||||
/**
|
||||
* NamespacedKey for finalizing.
|
||||
*/
|
||||
private val finalizeKey: NamespacedKey = plugin.namespacedKeyFactory.create("finalized")
|
||||
|
||||
init {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.willfp.eco.proxy.v1_16_R3
|
||||
|
||||
import com.willfp.eco.proxy.TPSProxy
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.craftbukkit.v1_16_R3.CraftServer
|
||||
|
||||
class TPS : TPSProxy {
|
||||
override fun getTPS(): Double {
|
||||
return (Bukkit.getServer() as CraftServer).handle.server.recentTps[0]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package com.willfp.eco.proxy.v1_17_R1
|
||||
|
||||
import com.willfp.eco.proxy.TPSProxy
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.craftbukkit.v1_17_R1.CraftServer
|
||||
|
||||
class TPS : TPSProxy {
|
||||
override fun getTPS(): Double {
|
||||
return (Bukkit.getServer() as CraftServer).handle.server.recentTps[0]
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,11 @@ dependencies {
|
||||
compileOnly 'net.essentialsx:EssentialsX:2.19.0'
|
||||
compileOnly 'com.bgsoftware:SuperiorSkyblockAPI:latest'
|
||||
compileOnly 'com.github.MilkBowl:VaultAPI:1.7'
|
||||
compileOnly 'world.bentobox:bentobox:1.17.3-SNAPSHOT'
|
||||
compileOnly 'com.google.guava:guava:31.0.1-jre'
|
||||
compileOnly 'com.iridium:IridiumSkyblock:3.1.2'
|
||||
compileOnly 'net.md-5:bungeecord-api:1.16-R0.5-SNAPSHOT'
|
||||
compileOnly 'com.velocitypowered:velocity-api:3.0.0-SNAPSHOT'
|
||||
|
||||
// CombatLogX V10 + NewbieHelper Expansion
|
||||
compileOnly 'com.SirBlobman.combatlogx:CombatLogX-API:10.0.0.0-SNAPSHOT'
|
||||
|
||||
@@ -22,19 +22,13 @@ import com.willfp.eco.internal.drops.DropManager
|
||||
import com.willfp.eco.proxy.BlockBreakProxy
|
||||
import com.willfp.eco.proxy.FastItemStackFactoryProxy
|
||||
import com.willfp.eco.proxy.SkullProxy
|
||||
import com.willfp.eco.proxy.TPSProxy
|
||||
import com.willfp.eco.spigot.arrows.ArrowDataListener
|
||||
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.*
|
||||
import com.willfp.eco.spigot.data.storage.DataHandler
|
||||
import com.willfp.eco.spigot.data.storage.MySQLDataHandler
|
||||
import com.willfp.eco.spigot.data.storage.YamlDataHandler
|
||||
import com.willfp.eco.spigot.display.PacketAutoRecipe
|
||||
import com.willfp.eco.spigot.display.PacketChat
|
||||
import com.willfp.eco.spigot.display.PacketOpenWindowMerchant
|
||||
import com.willfp.eco.spigot.display.PacketSetCreativeSlot
|
||||
import com.willfp.eco.spigot.display.PacketSetSlot
|
||||
import com.willfp.eco.spigot.display.PacketWindowItems
|
||||
import com.willfp.eco.spigot.display.*
|
||||
import com.willfp.eco.spigot.display.frame.clearFrames
|
||||
import com.willfp.eco.spigot.drops.CollatedRunnable
|
||||
import com.willfp.eco.spigot.eventlisteners.EntityDeathByEntityListeners
|
||||
@@ -45,21 +39,8 @@ import com.willfp.eco.spigot.eventlisteners.armor.ArmorListener
|
||||
import com.willfp.eco.spigot.gui.GUIListener
|
||||
import com.willfp.eco.spigot.integrations.afk.AFKIntegrationCMI
|
||||
import com.willfp.eco.spigot.integrations.afk.AFKIntegrationEssentials
|
||||
import com.willfp.eco.spigot.integrations.anticheat.AnticheatAAC
|
||||
import com.willfp.eco.spigot.integrations.anticheat.AnticheatAlice
|
||||
import com.willfp.eco.spigot.integrations.anticheat.AnticheatMatrix
|
||||
import com.willfp.eco.spigot.integrations.anticheat.AnticheatNCP
|
||||
import com.willfp.eco.spigot.integrations.anticheat.AnticheatSpartan
|
||||
import com.willfp.eco.spigot.integrations.anticheat.AnticheatVulcan
|
||||
import com.willfp.eco.spigot.integrations.antigrief.AntigriefCombatLogXV10
|
||||
import com.willfp.eco.spigot.integrations.antigrief.AntigriefCombatLogXV11
|
||||
import com.willfp.eco.spigot.integrations.antigrief.AntigriefFactionsUUID
|
||||
import com.willfp.eco.spigot.integrations.antigrief.AntigriefGriefPrevention
|
||||
import com.willfp.eco.spigot.integrations.antigrief.AntigriefKingdoms
|
||||
import com.willfp.eco.spigot.integrations.antigrief.AntigriefLands
|
||||
import com.willfp.eco.spigot.integrations.antigrief.AntigriefSuperiorSkyblock2
|
||||
import com.willfp.eco.spigot.integrations.antigrief.AntigriefTowny
|
||||
import com.willfp.eco.spigot.integrations.antigrief.AntigriefWorldGuard
|
||||
import com.willfp.eco.spigot.integrations.anticheat.*
|
||||
import com.willfp.eco.spigot.integrations.antigrief.*
|
||||
import com.willfp.eco.spigot.integrations.customitems.CustomItemsHeadDatabase
|
||||
import com.willfp.eco.spigot.integrations.customitems.CustomItemsItemsAdder
|
||||
import com.willfp.eco.spigot.integrations.customitems.CustomItemsOraxen
|
||||
@@ -72,16 +53,14 @@ import com.willfp.eco.spigot.integrations.multiverseinventories.MultiverseInvent
|
||||
import com.willfp.eco.spigot.integrations.shop.ShopShopGuiPlus
|
||||
import com.willfp.eco.spigot.recipes.ShapedRecipeListener
|
||||
import com.willfp.eco.util.BlockUtils
|
||||
import com.willfp.eco.util.ServerUtils
|
||||
import com.willfp.eco.util.SkullUtils
|
||||
import net.kyori.adventure.platform.bukkit.BukkitAudiences
|
||||
import net.milkbowl.vault.economy.Economy
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.block.Block
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.Listener
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.SkullMeta
|
||||
|
||||
abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
773,
|
||||
@@ -97,12 +76,15 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
|
||||
val skullProxy = getProxy(SkullProxy::class.java)
|
||||
SkullUtils.initialize(
|
||||
{ meta: SkullMeta, base64: String -> skullProxy.setSkullTexture(meta, base64) },
|
||||
{ meta: SkullMeta -> skullProxy.getSkullTexture(meta) }
|
||||
{ meta, base64 -> skullProxy.setSkullTexture(meta, base64) },
|
||||
{ meta -> skullProxy.getSkullTexture(meta) }
|
||||
)
|
||||
|
||||
val blockBreakProxy = getProxy(BlockBreakProxy::class.java)
|
||||
BlockUtils.initialize { player: Player, block: Block -> blockBreakProxy.breakBlock(player, block) }
|
||||
BlockUtils.initialize { player, block -> blockBreakProxy.breakBlock(player, block) }
|
||||
|
||||
val tpsProxy = getProxy(TPSProxy::class.java)
|
||||
ServerUtils.initialize { tpsProxy.getTPS() }
|
||||
|
||||
postInit()
|
||||
}
|
||||
@@ -141,6 +123,10 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
}
|
||||
|
||||
override fun handleDisable() {
|
||||
this.logger.info("Saving player data...")
|
||||
val start = System.currentTimeMillis()
|
||||
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).saveAllBlocking()
|
||||
this.logger.info("Saved player data! Took ${System.currentTimeMillis() - start}ms")
|
||||
Eco.getHandler().adventure?.close()
|
||||
}
|
||||
|
||||
@@ -155,7 +141,7 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
this.scheduler.runTimer(
|
||||
{
|
||||
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler)
|
||||
.autosave(this.configYml.getBool("autosave.async"))
|
||||
.autosave()
|
||||
},
|
||||
this.configYml.getInt("autosave.ticks").toLong(),
|
||||
this.configYml.getInt("autosave.ticks").toLong()
|
||||
@@ -170,7 +156,10 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
override fun loadIntegrationLoaders(): List<IntegrationLoader> {
|
||||
return listOf(
|
||||
// AntiGrief
|
||||
IntegrationLoader("IridiumSkyblock") { AntigriefManager.register(AntigriefIridiumSkyblock()) },
|
||||
IntegrationLoader("DeluxeCombat") { AntigriefManager.register(AntigriefDeluxeCombat()) },
|
||||
IntegrationLoader("SuperiorSkyblock2") { AntigriefManager.register(AntigriefSuperiorSkyblock2()) },
|
||||
IntegrationLoader("BentoBox") { AntigriefManager.register(AntigriefBentoBox()) },
|
||||
IntegrationLoader("WorldGuard") { AntigriefManager.register(AntigriefWorldGuard()) },
|
||||
IntegrationLoader("GriefPrevention") { AntigriefManager.register(AntigriefGriefPrevention()) },
|
||||
IntegrationLoader("FactionsUUID") { AntigriefManager.register(AntigriefFactionsUUID()) },
|
||||
@@ -244,7 +233,7 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
}
|
||||
|
||||
override fun loadListeners(): List<Listener> {
|
||||
return listOf(
|
||||
val listeners = mutableListOf(
|
||||
NaturalExpGainListeners(),
|
||||
ArmorListener(),
|
||||
EntityDeathByEntityListeners(this),
|
||||
@@ -256,5 +245,15 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
DataListener(),
|
||||
PlayerBlockListener(this)
|
||||
)
|
||||
|
||||
if (Prerequisite.HAS_BUNGEECORD.isMet) {
|
||||
listeners.add(BungeeDataListener())
|
||||
}
|
||||
|
||||
if (Prerequisite.HAS_VELOCITY.isMet) {
|
||||
listeners.add(VelocityDataListener())
|
||||
}
|
||||
|
||||
return listeners
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.willfp.eco.spigot.data
|
||||
|
||||
import com.willfp.eco.core.Eco
|
||||
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 org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
@@ -11,11 +11,12 @@ class DataListener : Listener {
|
||||
@EventHandler
|
||||
fun onLeave(event: PlayerQuitEvent) {
|
||||
PlayerUtils.updateSavedDisplayName(event.player)
|
||||
Eco.getHandler().playerProfileHandler.savePlayer(event.player.uniqueId)
|
||||
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).unloadPlayer(event.player.uniqueId)
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onJoin(event: PlayerJoinEvent) {
|
||||
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).unloadPlayer(event.player.uniqueId)
|
||||
PlayerUtils.updateSavedDisplayName(event.player)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.willfp.eco.core.data.keys.PersistentDataKey
|
||||
import com.willfp.eco.internal.data.EcoPlayerProfile
|
||||
import com.willfp.eco.spigot.EcoSpigotPlugin
|
||||
import org.bukkit.Bukkit
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
|
||||
class EcoPlayerProfileHandler(
|
||||
private val plugin: EcoSpigotPlugin
|
||||
@@ -32,40 +32,24 @@ class EcoPlayerProfileHandler(
|
||||
return profile
|
||||
}
|
||||
|
||||
fun unloadPlayer(uuid: UUID) {
|
||||
handler.savePlayer(uuid)
|
||||
loaded.remove(uuid)
|
||||
}
|
||||
|
||||
override fun savePlayer(uuid: UUID) {
|
||||
writeToHandler(uuid)
|
||||
saveToHandler()
|
||||
handler.savePlayer(uuid)
|
||||
}
|
||||
|
||||
private fun writeToHandler(uuid: UUID) {
|
||||
val profile = load(uuid)
|
||||
|
||||
for (key in Eco.getHandler().keyRegistry.registeredKeys) {
|
||||
handler.write(uuid, key.key, profile.read(key) ?: key.defaultValue)
|
||||
}
|
||||
override fun saveAll() {
|
||||
handler.saveAll(loaded.keys.toList())
|
||||
}
|
||||
|
||||
private fun saveToHandler() {
|
||||
handler.save()
|
||||
fun saveAllBlocking() {
|
||||
handler.saveAllBlocking(loaded.keys.toList())
|
||||
}
|
||||
|
||||
override fun saveAll(async: Boolean) {
|
||||
val saver = {
|
||||
for ((uuid, _) in loaded) {
|
||||
writeToHandler(uuid)
|
||||
}
|
||||
|
||||
saveToHandler()
|
||||
}
|
||||
|
||||
if (async) {
|
||||
plugin.scheduler.runAsync(saver)
|
||||
} else {
|
||||
saver.invoke()
|
||||
}
|
||||
}
|
||||
|
||||
fun autosave(async: Boolean) {
|
||||
fun autosave() {
|
||||
if (Bukkit.getOnlinePlayers().isEmpty()) {
|
||||
return
|
||||
}
|
||||
@@ -74,7 +58,7 @@ class EcoPlayerProfileHandler(
|
||||
plugin.logger.info("Auto-Saving player data!")
|
||||
}
|
||||
|
||||
saveAll(async)
|
||||
saveAll()
|
||||
|
||||
if (plugin.configYml.getBool("autosave.log")) {
|
||||
plugin.logger.info("Saved player data!")
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.willfp.eco.spigot.data
|
||||
|
||||
import com.velocitypowered.api.event.connection.DisconnectEvent
|
||||
import com.velocitypowered.api.event.player.ServerConnectedEvent
|
||||
import com.willfp.eco.core.Eco
|
||||
import org.bukkit.event.EventHandler
|
||||
import org.bukkit.event.Listener
|
||||
|
||||
class VelocityDataListener : Listener {
|
||||
@EventHandler
|
||||
fun onConnected(event: ServerConnectedEvent) {
|
||||
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).unloadPlayer(event.player.uniqueId)
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onDisconnect(event: DisconnectEvent) {
|
||||
(Eco.getHandler().playerProfileHandler as EcoPlayerProfileHandler).unloadPlayer(event.player.uniqueId)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,24 @@
|
||||
package com.willfp.eco.spigot.data.storage
|
||||
|
||||
import org.bukkit.NamespacedKey
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
|
||||
interface DataHandler {
|
||||
fun save()
|
||||
fun save() {
|
||||
|
||||
}
|
||||
|
||||
fun saveAll(uuids: Iterable<UUID>)
|
||||
|
||||
fun saveAllBlocking(uuids: Iterable<UUID>) {
|
||||
saveAll(uuids)
|
||||
}
|
||||
|
||||
fun updateKeys() {
|
||||
|
||||
}
|
||||
|
||||
fun <T> write(uuid: UUID, key: NamespacedKey, value: T)
|
||||
fun savePlayer(uuid: UUID)
|
||||
fun <T> read(uuid: UUID, key: NamespacedKey): T?
|
||||
|
||||
fun updateKeys()
|
||||
}
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.willfp.eco.spigot.data.storage
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
||||
import com.willfp.eco.core.Eco
|
||||
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.spigot.EcoSpigotPlugin
|
||||
import org.apache.logging.log4j.Level
|
||||
import org.bukkit.NamespacedKey
|
||||
import org.jetbrains.exposed.dao.id.UUIDTable
|
||||
import org.jetbrains.exposed.sql.BooleanColumnType
|
||||
@@ -13,18 +16,25 @@ 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.Table
|
||||
import org.jetbrains.exposed.sql.VarCharColumnType
|
||||
import org.jetbrains.exposed.sql.checkMappingConsistence
|
||||
import org.jetbrains.exposed.sql.exposedLogger
|
||||
import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.TransactionManager
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import org.jetbrains.exposed.sql.update
|
||||
import java.util.UUID
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class MySQLDataHandler(
|
||||
plugin: EcoSpigotPlugin
|
||||
) : DataHandler {
|
||||
private val columns = mutableMapOf<String, Column<*>>()
|
||||
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-mysql-thread-%d").build()
|
||||
private val executor = Executors.newCachedThreadPool(threadFactory)
|
||||
|
||||
init {
|
||||
Database.connect(
|
||||
@@ -40,6 +50,15 @@ class MySQLDataHandler(
|
||||
transaction {
|
||||
SchemaUtils.create(Players)
|
||||
}
|
||||
|
||||
// Get Exposed to shut the hell up
|
||||
exposedLogger::class.java.getDeclaredField("logger").apply { isAccessible = true }
|
||||
.apply {
|
||||
get(exposedLogger).apply {
|
||||
this.javaClass.getDeclaredMethod("setLevel", Level::class.java)
|
||||
.invoke(this, Level.OFF)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun updateKeys() {
|
||||
@@ -52,17 +71,53 @@ class MySQLDataHandler(
|
||||
}
|
||||
}
|
||||
|
||||
override fun save() {
|
||||
// Do nothing
|
||||
override fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
|
||||
getPlayer(uuid)
|
||||
writeAsserted(uuid, key, value)
|
||||
}
|
||||
|
||||
override fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
|
||||
private fun <T> writeAsserted(uuid: UUID, key: NamespacedKey, value: T, async: Boolean = true) {
|
||||
val column: Column<T> = getColumn(key.toString()) as Column<T>
|
||||
|
||||
fun executeTransaction() {
|
||||
transaction {
|
||||
Players.update({ Players.id eq uuid }) {
|
||||
it[column] = value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (async) {
|
||||
executor.execute { executeTransaction() }
|
||||
} else {
|
||||
executeTransaction()
|
||||
}
|
||||
}
|
||||
|
||||
override fun savePlayer(uuid: UUID) {
|
||||
savePlayer(uuid, async = false)
|
||||
}
|
||||
|
||||
override fun saveAll(uuids: Iterable<UUID>) {
|
||||
for (uuid in uuids) {
|
||||
savePlayer(uuid)
|
||||
}
|
||||
}
|
||||
|
||||
override fun saveAllBlocking(uuids: Iterable<UUID>) {
|
||||
for (uuid in uuids) {
|
||||
savePlayer(uuid, async = false)
|
||||
}
|
||||
}
|
||||
|
||||
private fun savePlayer(uuid: UUID, async: Boolean = true) {
|
||||
val profile = PlayerProfile.load(uuid)
|
||||
|
||||
transaction {
|
||||
getPlayer(uuid)
|
||||
val column: Column<T> = getColumn(key.toString()) as Column<T>
|
||||
|
||||
Players.update({ Players.id eq uuid }) {
|
||||
it[column] = value
|
||||
for (key in Eco.getHandler().keyRegistry.registeredKeys) {
|
||||
writeAsserted(uuid, key.key, profile.read(key), async = async)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -76,12 +131,14 @@ class MySQLDataHandler(
|
||||
return value
|
||||
}
|
||||
|
||||
object Players : UUIDTable("eco_players") {
|
||||
|
||||
}
|
||||
object Players : UUIDTable("eco_players")
|
||||
|
||||
private fun <T> registerColumn(key: PersistentDataKey<T>, table: UUIDTable) {
|
||||
table.apply {
|
||||
if (this.columns.stream().anyMatch { it.name == key.key.toString() }) {
|
||||
return@apply
|
||||
}
|
||||
|
||||
when (key.type) {
|
||||
PersistentDataKeyType.INT -> registerColumn<Int>(key.key.toString(), IntegerColumnType())
|
||||
.default(key.defaultValue as Int)
|
||||
@@ -89,7 +146,7 @@ class MySQLDataHandler(
|
||||
.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(128))
|
||||
PersistentDataKeyType.STRING -> registerColumn<String>(key.key.toString(), VarCharColumnType(512))
|
||||
.default(key.defaultValue as String)
|
||||
|
||||
else -> throw NullPointerException("Null value found!")
|
||||
@@ -108,12 +165,40 @@ class MySQLDataHandler(
|
||||
}
|
||||
|
||||
private fun getPlayer(uuid: UUID): ResultRow {
|
||||
Players.select { Players.id eq uuid }.firstOrNull() ?: run {
|
||||
Players.insert {
|
||||
it[id] = uuid
|
||||
}
|
||||
val player = transaction {
|
||||
Players.select { Players.id eq uuid }.limit(1).singleOrNull()
|
||||
}
|
||||
|
||||
return Players.select { Players.id eq uuid }.first()
|
||||
return if (player != null) {
|
||||
player
|
||||
} else {
|
||||
transaction {
|
||||
Players.insert { it[id] = uuid }
|
||||
}
|
||||
getPlayer(uuid)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createMissingTablesAndColumnsSilently(table: Table) {
|
||||
with(TransactionManager.current()) {
|
||||
fun execStatements(statements: List<String>) {
|
||||
for (statement in statements) {
|
||||
exec(statement)
|
||||
}
|
||||
}
|
||||
|
||||
db.dialect.resetCaches()
|
||||
val createStatements = SchemaUtils.createStatements(table)
|
||||
execStatements(createStatements)
|
||||
commit()
|
||||
val alterStatements = SchemaUtils.addMissingColumnsStatements(table)
|
||||
execStatements(alterStatements)
|
||||
commit()
|
||||
val executedStatements = createStatements + alterStatements
|
||||
val modifyTablesStatements = checkMappingConsistence(table).filter { it !in executedStatements }
|
||||
execStatements(modifyTablesStatements)
|
||||
commit()
|
||||
db.dialect.resetCaches()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
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.data.PlayerProfile
|
||||
import com.willfp.eco.spigot.EcoSpigotPlugin
|
||||
import org.bukkit.NamespacedKey
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class YamlDataHandler(
|
||||
@@ -15,8 +17,20 @@ class YamlDataHandler(
|
||||
dataYml.save()
|
||||
}
|
||||
|
||||
override fun updateKeys() {
|
||||
// Do nothing
|
||||
override fun saveAll(uuids: Iterable<UUID>) {
|
||||
for (uuid in uuids) {
|
||||
savePlayer(uuid)
|
||||
}
|
||||
|
||||
save()
|
||||
}
|
||||
|
||||
override fun savePlayer(uuid: UUID) {
|
||||
val profile = PlayerProfile.load(uuid)
|
||||
|
||||
for (key in Eco.getHandler().keyRegistry.registeredKeys) {
|
||||
write(uuid, key.key, profile.read(key))
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T> write(uuid: UUID, key: NamespacedKey, value: T) {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package com.willfp.eco.spigot.display
|
||||
|
||||
import com.comphenix.protocol.PacketType
|
||||
import com.comphenix.protocol.ProtocolLibrary
|
||||
import com.comphenix.protocol.events.PacketContainer
|
||||
import com.comphenix.protocol.events.PacketEvent
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
||||
import com.willfp.eco.core.AbstractPacketAdapter
|
||||
import com.willfp.eco.core.EcoPlugin
|
||||
import com.willfp.eco.core.display.Display
|
||||
@@ -10,53 +12,151 @@ import com.willfp.eco.core.fast.FastItemStack
|
||||
import com.willfp.eco.spigot.display.frame.DisplayFrame
|
||||
import com.willfp.eco.spigot.display.frame.HashedItem
|
||||
import com.willfp.eco.spigot.display.frame.lastDisplayFrame
|
||||
import com.willfp.eco.util.ServerUtils
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.Executors
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class PacketWindowItems(plugin: EcoPlugin) : AbstractPacketAdapter(plugin, PacketType.Play.Server.WINDOW_ITEMS, false) {
|
||||
private val ignorePacketList = ConcurrentHashMap.newKeySet<String>()
|
||||
private val playerRates = ConcurrentHashMap<String, Int>()
|
||||
private val threadFactory = ThreadFactoryBuilder().setNameFormat("eco-display-thread-%d").build()
|
||||
private val executor = Executors.newCachedThreadPool(threadFactory)
|
||||
private val scheduledExecutor = Executors.newSingleThreadScheduledExecutor(threadFactory)
|
||||
|
||||
override fun onSend(
|
||||
packet: PacketContainer,
|
||||
player: Player,
|
||||
event: PacketEvent
|
||||
) {
|
||||
if (ignorePacketList.contains(player.name)) {
|
||||
ignorePacketList.remove(player.name)
|
||||
return
|
||||
}
|
||||
|
||||
val windowId = packet.integers.read(0)
|
||||
|
||||
if (windowId != 0) {
|
||||
player.lastDisplayFrame = DisplayFrame.EMPTY
|
||||
}
|
||||
|
||||
packet.itemListModifier.modify(0) { itemStacks: MutableList<ItemStack>? ->
|
||||
if (itemStacks == null) {
|
||||
return@modify null
|
||||
val itemStacks = packet.itemListModifier.read(0) ?: return
|
||||
|
||||
handleRateLimit(player)
|
||||
|
||||
if (usingAsync(player)) {
|
||||
fun modifyAndSend(itemStacks: MutableList<ItemStack>, windowId: Int, player: Player) {
|
||||
modifyWindowItems(itemStacks, windowId, player)
|
||||
|
||||
val newPacket = packet.deepClone()
|
||||
newPacket.itemListModifier.write(0, itemStacks)
|
||||
|
||||
ignorePacketList.add(player.name)
|
||||
|
||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, newPacket)
|
||||
}
|
||||
|
||||
if (this.getPlugin().configYml.getBool("use-display-frame") && windowId == 0) {
|
||||
val frameMap = mutableMapOf<Byte, HashedItem>()
|
||||
executor.execute {
|
||||
try {
|
||||
modifyAndSend(itemStacks, windowId, player)
|
||||
} catch (e: Exception) {
|
||||
if (this.getPlugin().configYml.getBool("async-display.log-errors")) {
|
||||
this.getPlugin().logger.warning("Error happened in async processing! Disable async display (/plugins/eco/config.yml) if this is a frequent issue")
|
||||
}
|
||||
|
||||
for (index in itemStacks.indices) {
|
||||
frameMap[index.toByte()] =
|
||||
HashedItem(FastItemStack.wrap(itemStacks[index]).hashCode(), itemStacks[index])
|
||||
this.getPlugin().scheduler.run {
|
||||
modifyAndSend(itemStacks, windowId, player)
|
||||
}
|
||||
}
|
||||
|
||||
val newFrame = DisplayFrame(frameMap)
|
||||
|
||||
val lastFrame = player.lastDisplayFrame
|
||||
|
||||
player.lastDisplayFrame = newFrame
|
||||
|
||||
val changes = lastFrame.getChangedSlots(newFrame)
|
||||
|
||||
for (index in changes) {
|
||||
Display.display(itemStacks[index.toInt()], player)
|
||||
}
|
||||
|
||||
for (index in (itemStacks.indices subtract changes)) {
|
||||
itemStacks[index.toInt()] = lastFrame.getItem(index.toByte()) ?: itemStacks[index.toInt()]
|
||||
}
|
||||
} else {
|
||||
itemStacks.forEach { Display.display(it, player) }
|
||||
}
|
||||
itemStacks
|
||||
} else {
|
||||
packet.itemListModifier.write(0, modifyWindowItems(itemStacks, windowId, player))
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleRateLimit(player: Player) {
|
||||
fun modifyRateValueBy(player: Player, amount: Int) {
|
||||
val name = player.name
|
||||
val current = playerRates[name] ?: 0
|
||||
val new = current + amount
|
||||
if (new <= 0) {
|
||||
playerRates.remove(name)
|
||||
} else {
|
||||
playerRates[name] = new
|
||||
}
|
||||
}
|
||||
|
||||
modifyRateValueBy(player, 1)
|
||||
|
||||
scheduledExecutor.schedule(
|
||||
{ modifyRateValueBy(player, -1) },
|
||||
this.getPlugin().configYml.getInt("async-display.ratelimit.timeframe").toLong(),
|
||||
TimeUnit.SECONDS
|
||||
)
|
||||
}
|
||||
|
||||
private fun usingAsync(player: Player): Boolean {
|
||||
if (this.getPlugin().configYml.getStrings("async-display.disable-on-types", false)
|
||||
.map { it.lowercase() }.contains(player.openInventory.type.name.lowercase())
|
||||
) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (this.getPlugin().configYml.getBool("async-display.enabled")) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (
|
||||
this.getPlugin().configYml.getBool("async-display.emergency.enabled")
|
||||
&& ServerUtils.getTps() <= this.getPlugin().configYml.getDouble("async-display.emergency.cutoff")
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
if (
|
||||
this.getPlugin().configYml.getBool("async-display.ratelimit.enabled")
|
||||
&& (playerRates[player.name] ?: 0) >= this.getPlugin().configYml.getInt("async-display.ratelimit.cutoff")
|
||||
) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun modifyWindowItems(
|
||||
itemStacks: MutableList<ItemStack>,
|
||||
windowId: Int,
|
||||
player: Player
|
||||
): MutableList<ItemStack> {
|
||||
if (this.getPlugin().configYml.getBool("use-display-frame") && windowId == 0) {
|
||||
val frameMap = mutableMapOf<Byte, HashedItem>()
|
||||
|
||||
for (index in itemStacks.indices) {
|
||||
frameMap[index.toByte()] =
|
||||
HashedItem(FastItemStack.wrap(itemStacks[index]).hashCode(), itemStacks[index])
|
||||
}
|
||||
|
||||
val newFrame = DisplayFrame(frameMap)
|
||||
|
||||
val lastFrame = player.lastDisplayFrame
|
||||
|
||||
player.lastDisplayFrame = newFrame
|
||||
|
||||
val changes = lastFrame.getChangedSlots(newFrame)
|
||||
|
||||
for (index in changes) {
|
||||
Display.display(itemStacks[index.toInt()], player)
|
||||
}
|
||||
|
||||
for (index in (itemStacks.indices subtract changes.toSet())) {
|
||||
itemStacks[index.toInt()] = lastFrame.getItem(index.toByte()) ?: itemStacks[index.toInt()]
|
||||
}
|
||||
} else {
|
||||
itemStacks.forEach { Display.display(it, player) }
|
||||
}
|
||||
|
||||
return itemStacks
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.willfp.eco.spigot.integrations.antigrief
|
||||
|
||||
import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.World
|
||||
import org.bukkit.block.Block
|
||||
import org.bukkit.entity.LivingEntity
|
||||
import org.bukkit.entity.Monster
|
||||
import org.bukkit.entity.Player
|
||||
import world.bentobox.bentobox.BentoBox
|
||||
import world.bentobox.bentobox.api.user.User
|
||||
import world.bentobox.bentobox.lists.Flags
|
||||
|
||||
class AntigriefBentoBox : AntigriefWrapper {
|
||||
override fun canBreakBlock(
|
||||
player: Player,
|
||||
block: Block
|
||||
): Boolean {
|
||||
val island = BentoBox.getInstance().islandsManager.getIslandAt(block.location).orElse(null) ?: return true
|
||||
return island.isAllowed(User.getInstance(player), Flags.BREAK_BLOCKS)
|
||||
}
|
||||
|
||||
override fun canCreateExplosion(
|
||||
player: Player,
|
||||
location: Location
|
||||
): Boolean {
|
||||
val island = BentoBox.getInstance().islandsManager.getIslandAt(location).orElse(null) ?: return true
|
||||
return island.isAllowed(User.getInstance(player), Flags.TNT_DAMAGE)
|
||||
}
|
||||
|
||||
override fun canPlaceBlock(
|
||||
player: Player,
|
||||
block: Block
|
||||
): Boolean {
|
||||
val island = BentoBox.getInstance().islandsManager.getIslandAt(block.location).orElse(null) ?: return true
|
||||
return island.isAllowed(User.getInstance(player), Flags.PLACE_BLOCKS)
|
||||
}
|
||||
|
||||
override fun canInjure(
|
||||
player: Player,
|
||||
victim: LivingEntity
|
||||
): Boolean {
|
||||
val island = BentoBox.getInstance().islandsManager.getIslandAt(victim.location).orElse(null) ?: return true
|
||||
return when (victim) {
|
||||
is Player -> {
|
||||
island.isAllowed(
|
||||
User.getInstance(player), when (victim.world.environment) {
|
||||
World.Environment.NORMAL -> Flags.PVP_OVERWORLD
|
||||
World.Environment.NETHER -> Flags.PVP_NETHER
|
||||
World.Environment.THE_END -> Flags.PVP_END
|
||||
else -> Flags.PVP_OVERWORLD
|
||||
}
|
||||
)
|
||||
}
|
||||
is Monster -> island.isAllowed(User.getInstance(player), Flags.HURT_MONSTERS)
|
||||
else -> island.isAllowed(User.getInstance(player), Flags.HURT_ANIMALS)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "BentoBox"
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is AntigriefWrapper) {
|
||||
return false
|
||||
}
|
||||
|
||||
return other.pluginName == this.pluginName
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return this.pluginName.hashCode()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.willfp.eco.spigot.integrations.antigrief
|
||||
|
||||
import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper
|
||||
import nl.marido.deluxecombat.api.DeluxeCombatAPI
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.block.Block
|
||||
import org.bukkit.entity.LivingEntity
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class AntigriefDeluxeCombat: AntigriefWrapper {
|
||||
override fun getPluginName(): String {
|
||||
return "DeluxeCombat";
|
||||
}
|
||||
|
||||
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 {
|
||||
val api = DeluxeCombatAPI()
|
||||
return when(victim) {
|
||||
is Player -> (api.hasProtection(victim) || !api.hasPvPEnabled(victim)) && !api.isInCombat(victim)
|
||||
else -> true
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.willfp.eco.spigot.integrations.antigrief
|
||||
|
||||
import com.iridium.iridiumskyblock.PermissionType
|
||||
import com.iridium.iridiumskyblock.api.IridiumSkyblockAPI
|
||||
import com.willfp.eco.core.integrations.antigrief.AntigriefWrapper
|
||||
import org.bukkit.Location
|
||||
import org.bukkit.block.Block
|
||||
import org.bukkit.entity.LivingEntity
|
||||
import org.bukkit.entity.Player
|
||||
|
||||
class AntigriefIridiumSkyblock : AntigriefWrapper {
|
||||
private val api = IridiumSkyblockAPI.getInstance()
|
||||
|
||||
override fun canBreakBlock(
|
||||
player: Player,
|
||||
block: Block
|
||||
): Boolean {
|
||||
return api.getIslandPermission(api.getIslandViaLocation(block.location).orElse(null) ?: return true, api.getUser(player), PermissionType.BLOCK_BREAK)
|
||||
}
|
||||
|
||||
override fun canCreateExplosion(
|
||||
player: Player,
|
||||
location: Location
|
||||
): Boolean {
|
||||
return api.getIslandPermission(api.getIslandViaLocation(location).orElse(null) ?: return true, api.getUser(player), PermissionType.BLOCK_BREAK)
|
||||
}
|
||||
|
||||
override fun canPlaceBlock(
|
||||
player: Player,
|
||||
block: Block
|
||||
): Boolean {
|
||||
return api.getIslandPermission(api.getIslandViaLocation(block.location).orElse(null) ?: return true, api.getUser(player), PermissionType.BLOCK_PLACE)
|
||||
}
|
||||
|
||||
override fun canInjure(
|
||||
player: Player,
|
||||
victim: LivingEntity
|
||||
): Boolean {
|
||||
return when (victim) {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPluginName(): String {
|
||||
return "IridiumSkyblock"
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (other !is AntigriefWrapper) {
|
||||
return false
|
||||
}
|
||||
|
||||
return other.pluginName == this.pluginName
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return this.pluginName.hashCode()
|
||||
}
|
||||
}
|
||||
@@ -6,18 +6,19 @@ import com.willfp.eco.core.integrations.hologram.Hologram
|
||||
import com.willfp.eco.core.integrations.hologram.HologramWrapper
|
||||
import net.Zrips.CMILib.Container.CMILocation
|
||||
import org.bukkit.Location
|
||||
import java.util.*
|
||||
import java.util.UUID
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
class HologramCMI : HologramWrapper {
|
||||
override fun createHologram(location: Location, contents: MutableList<String>): Hologram {
|
||||
val cmiHolo = CMIHologram(UUID.randomUUID().toString(), CMILocation(location))
|
||||
cmiHolo.enable()
|
||||
CMI.getInstance().hologramManager.addHologram(cmiHolo)
|
||||
|
||||
val holo = HologramImplCMI(cmiHolo)
|
||||
holo.setContents(contents)
|
||||
|
||||
cmiHolo.enable()
|
||||
|
||||
return holo
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,18 @@
|
||||
# by Auxilor
|
||||
#
|
||||
|
||||
mysql:
|
||||
enabled: false # Set to false, data.yml will be used instead.
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: database
|
||||
user: username
|
||||
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.
|
||||
villager-display-fix: false
|
||||
@@ -17,7 +29,7 @@ use-fast-collated-drops: true
|
||||
enable-bstats: true
|
||||
|
||||
# Some plugins use their own item display systems (eg Triton)
|
||||
# And must be ran after eco. Don't enable this unless you run a conflicting plugin
|
||||
# And must be run after eco. Don't enable this unless you run a conflicting plugin
|
||||
# and have been told to enable it.
|
||||
use-lower-protocollib-priority: false
|
||||
|
||||
@@ -30,15 +42,42 @@ use-display-frame: true
|
||||
# that display frames will be cleared / deleted.
|
||||
display-frame-ttl: 17
|
||||
|
||||
mysql:
|
||||
enabled: false # Set to false, data.yml will be used instead.
|
||||
host: localhost
|
||||
port: 3306
|
||||
database: database
|
||||
user: username
|
||||
password: passy
|
||||
# Window items packets have the option to be run asynchronously. This may cause
|
||||
# some bugs and is considered experimental, however it has been tested without
|
||||
# any apparent issues. Enable this if performance is absolutely crucial or if you
|
||||
# are experiencing severe display lag.
|
||||
async-display:
|
||||
# If async display should always be used.
|
||||
enabled: false
|
||||
|
||||
autosave:
|
||||
ticks: 20000 # The amount of ticks between autosaves
|
||||
log: false # If auto-save messages should be sent to console
|
||||
async: false # If saves should be performed asynchronously. May cause bugs without MySQL
|
||||
# Log errors that occur in async processing.
|
||||
log-errors: true
|
||||
|
||||
# The inventory types that should never be processed asynchronously.
|
||||
# A list of IDs can be found here:
|
||||
# https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/inventory/InventoryType.html
|
||||
disable-on-types:
|
||||
- 'anvil'
|
||||
|
||||
# If the server is running under heavy load (below a certain TPS value), enable
|
||||
# async display automatically. This can prevent some server crashes under load.
|
||||
emergency:
|
||||
# If emergency async should be used.
|
||||
enabled: true
|
||||
# Below this TPS value, emergency async display will be used.
|
||||
cutoff: 18
|
||||
|
||||
# If players with a large amount of display packets should have their processing
|
||||
# done asynchronously. This will help if a player is trying to crash the server
|
||||
# by overloading the display system.
|
||||
ratelimit:
|
||||
# If rate limit async display should be used.
|
||||
enabled: true
|
||||
# The amount of window items packets per timeframe needed to enable async display
|
||||
# for a specified player.
|
||||
cutoff: 4
|
||||
# The length of the timeframe in seconds.
|
||||
# Cutoff 5, Timeframe 1 means that if there are more than 5 window items packets
|
||||
# being sent per second for a player, then that player should have their packets
|
||||
# handled asynchronously.
|
||||
timeframe: 1
|
||||
@@ -32,6 +32,10 @@ softdepend:
|
||||
- CMI
|
||||
- Essentials
|
||||
- Vault
|
||||
- BentoBox
|
||||
- DeluxeCombat
|
||||
- IridiumSkyblock
|
||||
- SuperiorSkyblock2
|
||||
libraries:
|
||||
- 'org.reflections:reflections:0.9.12'
|
||||
- 'org.apache.maven:maven-artifact:3.0.3'
|
||||
@@ -44,4 +48,5 @@ libraries:
|
||||
- 'org.jetbrains.exposed:exposed-core:0.35.1'
|
||||
- 'org.jetbrains.exposed:exposed-dao:0.35.1'
|
||||
- 'org.jetbrains.exposed:exposed-jdbc:0.35.1'
|
||||
- 'mysql:mysql-connector-java:8.0.25'
|
||||
- 'mysql:mysql-connector-java:8.0.25'
|
||||
- 'com.google.guava:guava:31.0.1-jre'
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.willfp.eco.proxy
|
||||
|
||||
import com.willfp.eco.core.proxy.AbstractProxy
|
||||
|
||||
interface TPSProxy : AbstractProxy {
|
||||
fun getTPS(): Double
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
version = 6.12.1
|
||||
version = 6.13.2
|
||||
plugin-name = eco
|
||||
BIN
lib/DeluxeCombat API.jar
Normal file
BIN
lib/DeluxeCombat API.jar
Normal file
Binary file not shown.
Reference in New Issue
Block a user