From 9c5684ed1e0617e5175913d803ea11cba4accffa Mon Sep 17 00:00:00 2001
From: nostalfinals <yuu8583@proton.me>
Date: Fri, 27 Dec 2024 14:58:46 +0800
Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=AE=8C=E6=88=90=E8=BF=81?=
 =?UTF-8?q?=E7=A7=BB=20Util?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../framework/common/util/Empty.kt            |  5 ++
 .../common/util/{logger => }/Logger.kt        |  2 +-
 .../common/util/MessageExceptionCatching.kt   |  5 +-
 .../framework/common/util/NumberExtensions.kt | 15 ++++
 .../common/util/chat/ColorConvert.kt          | 16 ----
 .../common/util/chat/ColorExtensions.kt       |  8 ++
 ...rationConvert.kt => DurationExtensions.kt} |  0
 .../common/util/chat/MessageConstants.kt      | 84 +++++++++----------
 .../{DoubleConvert.kt => NumberExtensions.kt} |  8 ++
 .../common/util/chat/SoundConstants.kt        | 35 ++++----
 ...{Replacement.kt => ComponentExtensions.kt} | 37 +++++---
 .../util/chat/component/IterableExtensions.kt | 15 ++++
 .../common/util/chat/component/Split.kt       | 26 ------
 .../util/chat/{palette => palettes}/Mocha.kt  |  2 +-
 .../common/util/command/AnnotationParser.kt   |  8 --
 ...cessors.kt => CommandManagerExtensions.kt} |  7 +-
 .../{suggestion => }/PrivilegedSuggestion.kt  |  2 +-
 .../common/util/config/ConfigLoaderBuilder.kt |  4 +-
 .../{decoder => decoders}/CharDecoder.kt      |  2 +-
 .../{decoder => decoders}/ComponentDecoder.kt |  2 +-
 .../util/coroutine/CoroutineLaunchers.kt      |  6 +-
 .../common/util/coroutine/Environment.kt      |  8 +-
 .../{Constants.kt => PlutoCoroutineScope.kt}  |  2 +-
 ...PrimitiveConvertor.kt => AnyExtensions.kt} | 14 +---
 .../common/util/data/BsonValueExtensions.kt   | 17 ++++
 .../ShortUuid.kt => StringExtensions.kt}      | 13 ++-
 .../common/util/data/UuidExtensions.kt        |  5 ++
 ...Concurrent.kt => ConcurrentCollections.kt} |  0
 .../{SafeSubList.kt => IterableExtensions.kt} |  0
 .../common/util/data/json/Any2Json.kt         | 17 ----
 .../util/data/json/{Constants.kt => Gson.kt}  |  2 +-
 .../{Json2Object.kt => JsonConvertors.kt}     | 20 ++++-
 .../JavaUuidSerializer.kt                     |  2 +-
 .../bson/JavaUuidBsonSerializer.kt            |  2 +-
 .../common/util/data/uuid/String2Uuid.kt      | 12 ---
 .../util/jvm/{Constants.kt => ByteBuddy.kt}   |  3 +-
 .../jvm/{clazz/Load.kt => ClassHelpers.kt}    |  9 +-
 .../framework/common/util/jvm/clazz/Find.kt   |  7 --
 .../common/util/network/CostantUrls.kt        |  3 -
 ...onvertor.kt => SocketAddressExtensions.kt} |  0
 .../common/util/network/UrlConstants.kt       |  5 ++
 .../framework/common/util/proto/Constant.kt   |  5 --
 .../common/util/time/NumberExtensions.kt      | 12 +++
 .../common/util/time/TemporalExtensions.kt    | 39 +++++++++
 .../framework/common/util/time/Timestamp.kt   |  3 +
 .../framework/common/util/time/Timezone.kt    |  8 ++
 .../common/util/time/ZoneIdExtensions.kt      |  7 +-
 ...SkullTexture.kt => ItemStackExtensions.kt} |  2 +-
 .../framework/paper/util/Platform.kt          |  2 +-
 .../util/{resource => }/ResourceLocation.kt   |  2 +-
 .../{ColorConvert.kt => ColorExtensions.kt}   |  0
 .../{NmsConvert.kt => ComponentExtensions.kt} |  0
 ...estion.kt => PaperPrivilegedSuggestion.kt} |  4 +-
 .../{PlayerEnsure.kt => PlayerHelpers.kt}     |  9 +-
 .../paper/util/command/PlayerSelect.kt        |  8 --
 ...{CommandManager.kt => PluginExtensions.kt} |  0
 .../util/coroutine/CoroutineLaunchers.kt      | 10 +--
 .../data/{model => models}/LocationModel.kt   |  2 +-
 .../{Teleport.kt => EntityExtensions.kt}      |  0
 .../SwitchServer.kt => PlayerExtensions.kt}   | 11 ++-
 ...{UuidEntityLookup.kt => UuidExtensions.kt} |  0
 .../paper/util/entity/player/NmsConvert.kt    |  7 --
 .../paper/util/entity/player/SendPacket.kt    |  8 --
 .../{Title.kt => InventoryViewExtensions.kt}  |  2 +-
 .../framework/paper/util/inventory/IsFull.kt  |  6 --
 ...OrDrop.kt => PlayerInventoryExtensions.kt} |  5 +-
 .../paper/util/world/WorldExtensions.kt       | 18 ++++
 .../paper/util/world/chunk/ChunkExtensions.kt | 17 +---
 .../paper/util/world/chunk/ChunkLocation.kt   | 28 +++++++
 .../paper/util/world/location/Comparisons.kt  | 22 +++++
 .../paper/util/world/location/Location2D.kt   | 18 ++++
 .../util/world/location/LocationExtensions.kt | 10 +++
 .../SwitchServer.kt => PlayerExtensions.kt}   |  3 +-
 .../Broadcast.kt => ProxyServerExtensions.kt} |  2 +-
 .../{PlayerEnsure.kt => PlayerHelpers.kt}     |  8 +-
 .../velocity/util/command/PlayerSelect.kt     |  8 --
 ...anager.kt => PluginContainerExtensions.kt} |  0
 .../VelocityPrivilegedSuggestion.kt           |  4 +-
 .../src/main/kotlin/ink/pmc/framework/Env.kt  | 18 ----
 .../main/kotlin/ink/pmc/framework/EnvPaper.kt |  7 --
 .../kotlin/ink/pmc/framework/EnvVelocity.kt   |  5 --
 .../src/main/kotlin/ink/pmc/framework/Math.kt | 20 -----
 .../src/main/kotlin/ink/pmc/framework/Time.kt |  4 -
 .../kotlin/ink/pmc/framework/Typealiases.kt   | 12 ---
 .../ink/pmc/framework/time/Formatter.kt       | 40 ---------
 .../kotlin/ink/pmc/framework/time/IntExts.kt  |  9 --
 .../pmc/framework/time/LocalDateTimeExts.kt   |  9 --
 .../kotlin/ink/pmc/framework/time/LongExts.kt |  6 --
 .../kotlin/ink/pmc/framework/time/Timezone.kt | 11 ---
 .../ink/pmc/framework/time/YearMonthExts.kt   |  9 --
 .../kotlin/ink/pmc/framework/world/Loc2.kt    | 31 -------
 .../ink/pmc/framework/world/LocationExts.kt   | 32 -------
 .../ink/pmc/framework/world/ValueVec2.kt      | 33 --------
 .../kotlin/ink/pmc/framework/world/Vec2.kt    | 29 -------
 .../ink/pmc/framework/world/WorldExts.kt      | 15 ----
 95 files changed, 427 insertions(+), 583 deletions(-)
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/Empty.kt
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/{logger => }/Logger.kt (55%)
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/NumberExtensions.kt
 delete mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/ColorConvert.kt
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/ColorExtensions.kt
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/{DurationConvert.kt => DurationExtensions.kt} (100%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/{DoubleConvert.kt => NumberExtensions.kt} (57%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/{Replacement.kt => ComponentExtensions.kt} (66%)
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/IterableExtensions.kt
 delete mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/Split.kt
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/{palette => palettes}/Mocha.kt (97%)
 delete mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/AnnotationParser.kt
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/{MethodArgumentParserAccessors.kt => CommandManagerExtensions.kt} (69%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/{suggestion => }/PrivilegedSuggestion.kt (93%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/{decoder => decoders}/CharDecoder.kt (92%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/{decoder => decoders}/ComponentDecoder.kt (92%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/{Constants.kt => PlutoCoroutineScope.kt} (61%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/{bson/BsonPrimitiveConvertor.kt => AnyExtensions.kt} (59%)
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/BsonValueExtensions.kt
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/{uuid/ShortUuid.kt => StringExtensions.kt} (52%)
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/UuidExtensions.kt
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/collection/{Concurrent.kt => ConcurrentCollections.kt} (100%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/collection/{SafeSubList.kt => IterableExtensions.kt} (100%)
 delete mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Any2Json.kt
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/{Constants.kt => Gson.kt} (77%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/{Json2Object.kt => JsonConvertors.kt} (52%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/{serializer => serializers}/JavaUuidSerializer.kt (92%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/{serializer => serializers}/bson/JavaUuidBsonSerializer.kt (95%)
 delete mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/uuid/String2Uuid.kt
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/{Constants.kt => ByteBuddy.kt} (73%)
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/{clazz/Load.kt => ClassHelpers.kt} (71%)
 delete mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/clazz/Find.kt
 delete mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/CostantUrls.kt
 rename framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/{InetSocketAddressConvertor.kt => SocketAddressExtensions.kt} (100%)
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/UrlConstants.kt
 delete mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/proto/Constant.kt
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/NumberExtensions.kt
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/TemporalExtensions.kt
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/Timestamp.kt
 create mode 100644 framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/Timezone.kt
 rename framework/api/src/main/kotlin/ink/pmc/framework/time/ZoneIdExts.kt => framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/ZoneIdExtensions.kt (53%)
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/{item/SkullTexture.kt => ItemStackExtensions.kt} (94%)
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/{resource => }/ResourceLocation.kt (88%)
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/chat/{ColorConvert.kt => ColorExtensions.kt} (100%)
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/chat/component/{NmsConvert.kt => ComponentExtensions.kt} (100%)
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/{suggestion/PrivilegedSuggestion.kt => PaperPrivilegedSuggestion.kt} (85%)
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/{PlayerEnsure.kt => PlayerHelpers.kt} (58%)
 delete mode 100644 framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PlayerSelect.kt
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/{CommandManager.kt => PluginExtensions.kt} (100%)
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/data/{model => models}/LocationModel.kt (89%)
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/{Teleport.kt => EntityExtensions.kt} (100%)
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/{player/SwitchServer.kt => PlayerExtensions.kt} (62%)
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/{UuidEntityLookup.kt => UuidExtensions.kt} (100%)
 delete mode 100644 framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/NmsConvert.kt
 delete mode 100644 framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/SendPacket.kt
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/{Title.kt => InventoryViewExtensions.kt} (92%)
 delete mode 100644 framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/IsFull.kt
 rename framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/{player/AddItemOrDrop.kt => PlayerInventoryExtensions.kt} (81%)
 create mode 100644 framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/WorldExtensions.kt
 rename framework/api/src/main/kotlin/ink/pmc/framework/world/ChunkExts.kt => framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/chunk/ChunkExtensions.kt (70%)
 create mode 100644 framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/chunk/ChunkLocation.kt
 create mode 100644 framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/Comparisons.kt
 create mode 100644 framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/Location2D.kt
 create mode 100644 framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/LocationExtensions.kt
 rename framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/{player/SwitchServer.kt => PlayerExtensions.kt} (78%)
 rename framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/{chat/Broadcast.kt => ProxyServerExtensions.kt} (82%)
 rename framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/{PlayerEnsure.kt => PlayerHelpers.kt} (64%)
 delete mode 100644 framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PlayerSelect.kt
 rename framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/{CommandManager.kt => PluginContainerExtensions.kt} (100%)
 rename framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/{suggestion => }/VelocityPrivilegedSuggestion.kt (85%)
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/Env.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/EnvPaper.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/EnvVelocity.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/Math.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/Time.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/Typealiases.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/time/Formatter.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/time/IntExts.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/time/LocalDateTimeExts.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/time/LongExts.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/time/Timezone.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/time/YearMonthExts.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/world/Loc2.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/world/LocationExts.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/world/ValueVec2.kt
 delete mode 100644 framework/api/src/main/kotlin/ink/pmc/framework/world/Vec2.kt

diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/Empty.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/Empty.kt
new file mode 100644
index 000000000..e21269163
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/Empty.kt
@@ -0,0 +1,5 @@
+package plutoproject.framework.common.util
+
+import com.google.protobuf.Empty as EmptyClass
+
+val Empty: EmptyClass = EmptyClass.getDefaultInstance()
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/logger/Logger.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/Logger.kt
similarity index 55%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/logger/Logger.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/Logger.kt
index 98642b36e..202336d12 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/logger/Logger.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/Logger.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.common.util.logger
+package plutoproject.framework.common.util
 
 import java.util.logging.Logger
 
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/MessageExceptionCatching.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/MessageExceptionCatching.kt
index 093bd7298..ddc3fab51 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/MessageExceptionCatching.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/MessageExceptionCatching.kt
@@ -4,9 +4,8 @@ import ink.pmc.advkt.component.newline
 import ink.pmc.advkt.component.text
 import ink.pmc.advkt.send
 import net.kyori.adventure.audience.Audience
-import plutoproject.framework.common.util.chat.palette.MOCHA_MAROON
-import plutoproject.framework.common.util.chat.palette.MOCHA_SUBTEXT_0
-import plutoproject.framework.common.util.logger.logger
+import plutoproject.framework.common.util.chat.palettes.MOCHA_MAROON
+import plutoproject.framework.common.util.chat.palettes.MOCHA_SUBTEXT_0
 import java.util.logging.Level
 
 inline fun <T> T.catchException(
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/NumberExtensions.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/NumberExtensions.kt
new file mode 100644
index 000000000..6d66c2dbc
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/NumberExtensions.kt
@@ -0,0 +1,15 @@
+package plutoproject.framework.common.util
+
+import kotlin.math.roundToInt
+
+fun Double.toTrimmedString(): String {
+    var result = toBigDecimal().stripTrailingZeros().toPlainString()
+    if (result.endsWith(".")) {
+        result = result.dropLast(1)
+    }
+    return result
+}
+
+fun Double.roundTo2(): Double {
+    return ((this * 100).roundToInt() / 100.0)
+}
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/ColorConvert.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/ColorConvert.kt
deleted file mode 100644
index 6fc41c0eb..000000000
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/ColorConvert.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package plutoproject.framework.common.util.chat
-
-import net.kyori.adventure.text.format.TextColor
-import java.awt.Color
-
-fun Int.toRgbaColor(): Color = Color(
-    (this shr 16) and 0xFF,
-    (this shr 8) and 0xFF,
-    this and 0xFF,
-    (this shr 24) and 0xFF
-)
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun Color.toTextColor(): TextColor {
-    return TextColor.color(red, green, blue)
-}
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/ColorExtensions.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/ColorExtensions.kt
new file mode 100644
index 000000000..70f5c0dc9
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/ColorExtensions.kt
@@ -0,0 +1,8 @@
+package plutoproject.framework.common.util.chat
+
+import net.kyori.adventure.text.format.TextColor
+import java.awt.Color
+
+fun Color.toTextColor(): TextColor {
+    return TextColor.color(red, green, blue)
+}
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/DurationConvert.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/DurationExtensions.kt
similarity index 100%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/DurationConvert.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/DurationExtensions.kt
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/MessageConstants.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/MessageConstants.kt
index e35684c90..5cfaa6449 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/MessageConstants.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/MessageConstants.kt
@@ -1,48 +1,44 @@
 package plutoproject.framework.common.util.chat
 
 import ink.pmc.advkt.component.*
-import plutoproject.framework.common.util.chat.palette.MOCHA_MAROON
-import plutoproject.framework.common.util.chat.palette.MOCHA_SUBTEXT_0
-import plutoproject.framework.common.util.chat.palette.MOCHA_YELLOW
-
-const val ECONOMY_SYMBOL = "\uD83C\uDF1F"
-
-val NON_PLAYER = component {
-    text("该命令仅限玩家使用") with MOCHA_MAROON
-}
-
-val EMPTY_LINE = component { }
-
-val PLUTO_PROJECT = component {
-    miniMessage("<gradient:#c6a0f6:#f5bde6:#f0c6c6:#f4dbd6>星社 ᴘʀᴏᴊᴇᴄᴛ</gradient>")
-}
-
-val PLAYER_NOT_ONLINE = component {
-    text("该玩家不在线") with MOCHA_MAROON
-}
-
-val NO_PERMISSION = component {
-    text("你似乎没有权限这么做") with MOCHA_MAROON
-    newline()
-    text("如果你认为这是一个错误的话,请向管理组报告") with MOCHA_SUBTEXT_0
-}
-
-val UNUSUAL_ISSUE = component {
-    text("看起来你似乎遇见了一个很罕见的问题") with MOCHA_MAROON
-    newline()
-    text("我们建议你反馈这个问题,有助于将服务器变得更好") with MOCHA_SUBTEXT_0
-}
-
-val IN_PROGRESS = component {
-    text("正在施工中...") with MOCHA_MAROON
-    newline()
-    text("前面的路,以后再来探索吧!") with MOCHA_SUBTEXT_0
-}
-
-val UI_CLOSE = component {
-    text("关闭") with MOCHA_MAROON without italic()
-}
-
-val UI_BACK = component {
-    text("返回") with MOCHA_YELLOW without italic()
+import plutoproject.framework.common.util.chat.palettes.MOCHA_MAROON
+import plutoproject.framework.common.util.chat.palettes.MOCHA_SUBTEXT_0
+import plutoproject.framework.common.util.chat.palettes.MOCHA_YELLOW
+
+object MessageConstants {
+    const val ECONOMY_SYMBOL = "\uD83C\uDF1F"
+    val emptyLine = component { }
+    val nonPlayer = component {
+        text("该命令仅限玩家使用") with MOCHA_MAROON
+    }
+    val plutoProject = component {
+        miniMessage("<gradient:#c6a0f6:#f5bde6:#f0c6c6:#f4dbd6>星社 ᴘʀᴏᴊᴇᴄᴛ</gradient>")
+    }
+    val playerNotOnline = component {
+        text("该玩家不在线") with MOCHA_MAROON
+    }
+    val noPermission = component {
+        text("你似乎没有权限这么做") with MOCHA_MAROON
+        newline()
+        text("如果你认为这是一个错误的话,请向管理组报告") with MOCHA_SUBTEXT_0
+    }
+    val unusualIssue = component {
+        text("看起来你似乎遇见了一个很罕见的问题") with MOCHA_MAROON
+        newline()
+        text("我们建议你反馈这个问题,有助于将服务器变得更好") with MOCHA_SUBTEXT_0
+    }
+    val inProgress = component {
+        text("正在施工中...") with MOCHA_MAROON
+        newline()
+        text("前面的路,以后再来探索吧!") with MOCHA_SUBTEXT_0
+    }
+
+    object UI {
+        val close = component {
+            text("关闭") with MOCHA_MAROON without italic()
+        }
+        val back = component {
+            text("返回") with MOCHA_YELLOW without italic()
+        }
+    }
 }
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/DoubleConvert.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/NumberExtensions.kt
similarity index 57%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/DoubleConvert.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/NumberExtensions.kt
index 305ab2713..0a722377e 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/DoubleConvert.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/NumberExtensions.kt
@@ -1,7 +1,15 @@
 package plutoproject.framework.common.util.chat
 
+import java.awt.Color
 import java.text.DecimalFormat
 
+fun Int.toRgbaColor(): Color = Color(
+    (this shr 16) and 0xFF,
+    (this shr 8) and 0xFF,
+    this and 0xFF,
+    (this shr 24) and 0xFF
+)
+
 fun Double.toCurrencyFormattedString(): String {
     val decimalFormat = DecimalFormat("#,##0.00")
     return decimalFormat.format(this)
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/SoundConstants.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/SoundConstants.kt
index 44e5b3006..f575094db 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/SoundConstants.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/SoundConstants.kt
@@ -4,22 +4,23 @@ import ink.pmc.advkt.sound.key
 import ink.pmc.advkt.sound.sound
 import net.kyori.adventure.key.Key
 
-val MESSAGE_SOUND = sound {
-    key(Key.key("block.decorated_pot.insert"))
-}
-
-val UI_INVALID_SOUND = sound {
-    key(Key.key("block.note_block.didgeridoo"))
-}
+object SoundConstants {
+    val message = sound {
+        key(Key.key("block.decorated_pot.insert"))
+    }
 
-val UI_SUCCEED_SOUND = sound {
-    key(Key.key("block.note_block.bell"))
+    object UI {
+        val invalid = sound {
+            key(Key.key("block.note_block.didgeridoo"))
+        }
+        val succeed = sound {
+            key(Key.key("block.note_block.bell"))
+        }
+        val paging = sound {
+            key(Key.key("item.book.page_turn"))
+        }
+        val selector = sound {
+            key(Key.key("block.note_block.hat"))
+        }
+    }
 }
-
-val UI_PAGING_SOUND = sound {
-    key(Key.key("item.book.page_turn"))
-}
-
-val UI_SELECTOR_SOUND = sound {
-    key(Key.key("block.note_block.hat"))
-}
\ No newline at end of file
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/Replacement.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/ComponentExtensions.kt
similarity index 66%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/Replacement.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/ComponentExtensions.kt
index cd0548b33..e0020242e 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/Replacement.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/ComponentExtensions.kt
@@ -24,18 +24,6 @@ fun Component.replace(string: String, any: Any?): Component {
     return replace(string, any.toString())
 }
 
-fun Iterable<Component>.replace(pattern: String, str: String): Iterable<Component> {
-    return map { it.replace(pattern, str) }
-}
-
-fun Iterable<Component>.replace(pattern: String, component: Component): Iterable<Component> {
-    return map { it.replace(pattern, component) }
-}
-
-fun Iterable<Component>.replace(pattern: String, any: Any?): Iterable<Component> {
-    return map { it.replace(pattern, any) }
-}
-
 fun Component.replaceColor(original: TextColor, new: TextColor): Component {
     val updatedComponent =
         if (this.style().color() == original) {
@@ -48,4 +36,27 @@ fun Component.replaceColor(original: TextColor, new: TextColor): Component {
         .fold(updatedComponent.children(emptyList())) { comp, child ->
             comp.append(child.replaceColor(original, new))
         }
-}
\ No newline at end of file
+}
+
+fun Component.splitLines(): Iterable<Component> {
+    var curr = Component.empty()
+    return buildList {
+        val root = this@splitLines.children(emptyList())
+        if (root != Component.empty()) {
+            add(root)
+        }
+        children().forEach { child ->
+            if (child == Component.newline()) {
+                if (curr != Component.empty()) {
+                    add(curr)
+                }
+                curr = Component.empty()
+                return@forEach
+            }
+            curr = curr.append(child)
+        }
+        if (curr != Component.empty()) {
+            add(curr)
+        }
+    }
+}
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/IterableExtensions.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/IterableExtensions.kt
new file mode 100644
index 000000000..d4afc1622
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/IterableExtensions.kt
@@ -0,0 +1,15 @@
+package plutoproject.framework.common.util.chat.component
+
+import net.kyori.adventure.text.Component
+
+fun Iterable<Component>.replace(pattern: String, str: String): Iterable<Component> {
+    return map { it.replace(pattern, str) }
+}
+
+fun Iterable<Component>.replace(pattern: String, component: Component): Iterable<Component> {
+    return map { it.replace(pattern, component) }
+}
+
+fun Iterable<Component>.replace(pattern: String, any: Any?): Iterable<Component> {
+    return map { it.replace(pattern, any) }
+}
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/Split.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/Split.kt
deleted file mode 100644
index 38f8b2e5c..000000000
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/component/Split.kt
+++ /dev/null
@@ -1,26 +0,0 @@
-package plutoproject.framework.common.util.chat.component
-
-import net.kyori.adventure.text.Component
-
-fun Component.splitLines(): Iterable<Component> {
-    var curr = Component.empty()
-    return buildList {
-        val root = this@splitLines.children(emptyList())
-        if (root != Component.empty()) {
-            add(root)
-        }
-        children().forEach { child ->
-            if (child == Component.newline()) {
-                if (curr != Component.empty()) {
-                    add(curr)
-                }
-                curr = Component.empty()
-                return@forEach
-            }
-            curr = curr.append(child)
-        }
-        if (curr != Component.empty()) {
-            add(curr)
-        }
-    }
-}
\ No newline at end of file
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/palette/Mocha.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/palettes/Mocha.kt
similarity index 97%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/palette/Mocha.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/palettes/Mocha.kt
index 3da44b566..069affe43 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/palette/Mocha.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/chat/palettes/Mocha.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.common.util.chat.palette
+package plutoproject.framework.common.util.chat.palettes
 
 import com.catppuccin.Palette
 import plutoproject.framework.common.util.chat.toTextColor
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/AnnotationParser.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/AnnotationParser.kt
deleted file mode 100644
index dab75d7bd..000000000
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/AnnotationParser.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package plutoproject.framework.common.util.command
-
-import org.incendo.cloud.CommandManager
-import org.incendo.cloud.annotations.AnnotationParser
-import org.incendo.cloud.kotlin.coroutines.annotations.installCoroutineSupport
-
-inline val <reified C> CommandManager<C>.annotationParser: AnnotationParser<C>
-    get() = AnnotationParser(this, C::class.java).installCoroutineSupport()
\ No newline at end of file
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/MethodArgumentParserAccessors.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/CommandManagerExtensions.kt
similarity index 69%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/MethodArgumentParserAccessors.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/CommandManagerExtensions.kt
index f1c4a908a..a4f2cab66 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/MethodArgumentParserAccessors.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/CommandManagerExtensions.kt
@@ -1,9 +1,11 @@
 package plutoproject.framework.common.util.command
 
 import org.incendo.cloud.CommandManager
+import org.incendo.cloud.annotations.AnnotationParser
 import org.incendo.cloud.annotations.parser.MethodArgumentParser
+import org.incendo.cloud.kotlin.coroutines.annotations.installCoroutineSupport
 import org.incendo.cloud.parser.ArgumentParser
-import plutoproject.framework.common.util.jvm.clazz.findClass
+import plutoproject.framework.common.util.jvm.findClass
 
 @Suppress("UNCHECKED_CAST", "UnusedReceiverParameter")
 fun <C, T> CommandManager<C>.getKotlinMethodArgumentParserClass(): Class<ArgumentParser<C, T>> =
@@ -13,3 +15,6 @@ fun <C, T> CommandManager<C>.getKotlinMethodArgumentParserClass(): Class<Argumen
 @Suppress("UNCHECKED_CAST", "UnusedReceiverParameter")
 fun <C, T> CommandManager<C>.getMethodArgumentParserClass(): Class<ArgumentParser<C, T>> =
     MethodArgumentParser::class.java as Class<ArgumentParser<C, T>>
+
+inline val <reified C> CommandManager<C>.annotationParser: AnnotationParser<C>
+    get() = AnnotationParser(this, C::class.java).installCoroutineSupport()
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/suggestion/PrivilegedSuggestion.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/PrivilegedSuggestion.kt
similarity index 93%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/suggestion/PrivilegedSuggestion.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/PrivilegedSuggestion.kt
index 98379dc89..7ddfaf3ad 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/suggestion/PrivilegedSuggestion.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/command/PrivilegedSuggestion.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.common.util.command.suggestion
+package plutoproject.framework.common.util.command
 
 import org.incendo.cloud.context.CommandContext
 import org.incendo.cloud.context.CommandInput
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/ConfigLoaderBuilder.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/ConfigLoaderBuilder.kt
index 324db5ee0..e9a3886fb 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/ConfigLoaderBuilder.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/ConfigLoaderBuilder.kt
@@ -2,8 +2,8 @@ package plutoproject.framework.common.util.config
 
 import com.sksamuel.hoplite.ConfigLoaderBuilder
 import com.sksamuel.hoplite.ExperimentalHoplite
-import plutoproject.framework.common.util.config.decoder.CharDecoder
-import plutoproject.framework.common.util.config.decoder.ComponentDecoder
+import plutoproject.framework.common.util.config.decoders.CharDecoder
+import plutoproject.framework.common.util.config.decoders.ComponentDecoder
 
 @OptIn(ExperimentalHoplite::class)
 fun ConfigLoaderBuilder(): ConfigLoaderBuilder {
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoder/CharDecoder.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoders/CharDecoder.kt
similarity index 92%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoder/CharDecoder.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoders/CharDecoder.kt
index 3494bcb17..9f02453a3 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoder/CharDecoder.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoders/CharDecoder.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.common.util.config.decoder
+package plutoproject.framework.common.util.config.decoders
 
 import com.sksamuel.hoplite.*
 import com.sksamuel.hoplite.decoder.NullHandlingDecoder
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoder/ComponentDecoder.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoders/ComponentDecoder.kt
similarity index 92%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoder/ComponentDecoder.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoders/ComponentDecoder.kt
index 3ffe4d336..68a385577 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoder/ComponentDecoder.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/config/decoders/ComponentDecoder.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.common.util.config.decoder
+package plutoproject.framework.common.util.config.decoders
 
 import com.sksamuel.hoplite.*
 import com.sksamuel.hoplite.decoder.NullHandlingDecoder
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/CoroutineLaunchers.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/CoroutineLaunchers.kt
index 644182bea..e5eae7d5b 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/CoroutineLaunchers.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/CoroutineLaunchers.kt
@@ -5,7 +5,7 @@ import kotlin.coroutines.CoroutineContext
 
 @Suppress("UNUSED")
 fun <T> runAsync(
-    coroutineScope: CoroutineScope = COROUTINE_SCOPE,
+    coroutineScope: CoroutineScope = PlutoCoroutineScope,
     coroutineContext: CoroutineContext = Dispatchers.Default,
     coroutineStart: CoroutineStart = CoroutineStart.DEFAULT,
     block: suspend CoroutineScope.() -> T,
@@ -13,14 +13,14 @@ fun <T> runAsync(
 
 @Suppress("UNUSED")
 fun <T> runAsyncIO(
-    coroutineScope: CoroutineScope = COROUTINE_SCOPE,
+    coroutineScope: CoroutineScope = PlutoCoroutineScope,
     coroutineStart: CoroutineStart = CoroutineStart.DEFAULT,
     block: suspend CoroutineScope.() -> T,
 ): Deferred<T> = coroutineScope.async(Dispatchers.IO, coroutineStart) { block() }
 
 @Suppress("UNUSED")
 fun <T> runAsyncUnconfined(
-    coroutineScope: CoroutineScope = COROUTINE_SCOPE,
+    coroutineScope: CoroutineScope = PlutoCoroutineScope,
     coroutineStart: CoroutineStart = CoroutineStart.DEFAULT,
     block: suspend CoroutineScope.() -> T,
 ): Deferred<T> = coroutineScope.async(Dispatchers.Unconfined, coroutineStart) { block() }
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/Environment.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/Environment.kt
index 6d8ca6df9..e830df042 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/Environment.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/Environment.kt
@@ -6,18 +6,18 @@ import kotlinx.coroutines.cancel
 import kotlinx.coroutines.isActive
 import java.util.logging.Logger
 
-private val LOGGER = Logger.getLogger("framework/common/util/coroutine/Environment")
+private val logger = Logger.getLogger("framework/common/util/coroutine/Environment")
 
 @OptIn(DelicateCoroutinesApi::class)
 fun shutdownCoroutineEnvironment() {
-    if (COROUTINE_SCOPE.isActive) {
-        COROUTINE_SCOPE.cancel()
+    if (PlutoCoroutineScope.isActive) {
+        PlutoCoroutineScope.cancel()
     }
     Dispatchers.shutdown()
     waitFinalize()
 }
 
 private fun waitFinalize() {
-    LOGGER.info("Wait 1s for finalizing...")
+    logger.info("Wait 1s for finalizing...")
     Thread.sleep(1000)
 }
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/Constants.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/PlutoCoroutineScope.kt
similarity index 61%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/Constants.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/PlutoCoroutineScope.kt
index e36169447..93bd654f1 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/Constants.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/coroutine/PlutoCoroutineScope.kt
@@ -3,4 +3,4 @@ package plutoproject.framework.common.util.coroutine
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 
-val COROUTINE_SCOPE = CoroutineScope(Dispatchers.Default)
+object PlutoCoroutineScope : CoroutineScope by CoroutineScope(Dispatchers.Default)
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/bson/BsonPrimitiveConvertor.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/AnyExtensions.kt
similarity index 59%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/bson/BsonPrimitiveConvertor.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/AnyExtensions.kt
index 22582ba5a..6c463a762 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/bson/BsonPrimitiveConvertor.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/AnyExtensions.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.common.util.data.bson
+package plutoproject.framework.common.util.data
 
 import org.bson.*
 import org.jetbrains.annotations.ApiStatus
@@ -19,15 +19,3 @@ fun Any?.convertPrimitiveToBson(): BsonValue = when (this) {
     else -> error("Not a primitive")
 }
 
-@Deprecated("")
-@ApiStatus.ScheduledForRemoval
-fun BsonValue?.toPrimitive(): Any? = when (this) {
-    is BsonInt32 -> value
-    is BsonInt64 -> value
-    is BsonDouble -> value
-    is BsonString -> value
-    is BsonBoolean -> value
-    is BsonNull -> null
-    null -> null
-    else -> error("Not a primitive")
-}
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/BsonValueExtensions.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/BsonValueExtensions.kt
new file mode 100644
index 000000000..9dba427fb
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/BsonValueExtensions.kt
@@ -0,0 +1,17 @@
+package plutoproject.framework.common.util.data
+
+import org.bson.*
+import org.jetbrains.annotations.ApiStatus
+
+@Deprecated("")
+@ApiStatus.ScheduledForRemoval
+fun BsonValue?.toPrimitive(): Any? = when (this) {
+    is BsonInt32 -> value
+    is BsonInt64 -> value
+    is BsonDouble -> value
+    is BsonString -> value
+    is BsonBoolean -> value
+    is BsonNull -> null
+    null -> null
+    else -> error("Not a primitive")
+}
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/uuid/ShortUuid.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/StringExtensions.kt
similarity index 52%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/uuid/ShortUuid.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/StringExtensions.kt
index bbf975c85..e4761cf23 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/uuid/ShortUuid.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/StringExtensions.kt
@@ -1,9 +1,7 @@
-package plutoproject.framework.common.util.data.uuid
+package plutoproject.framework.common.util.data
 
 import java.util.*
 
-fun UUID.toShortUuidString(): String = toString().replace("-", "")
-
 fun String.convertShortUuidToLong(): String {
     check(length == 32) { "Not a valid short uuid" }
     return replace(
@@ -11,3 +9,12 @@ fun String.convertShortUuidToLong(): String {
         "$1-$2-$3-$4-$5"
     )
 }
+
+fun String.convertToUuid(): UUID = UUID.fromString(this)
+
+fun String.convertToUuidOrNull(): UUID? =
+    try {
+        UUID.fromString(this)
+    } catch (e: IllegalArgumentException) {
+        null
+    }
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/UuidExtensions.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/UuidExtensions.kt
new file mode 100644
index 000000000..8504da7ea
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/UuidExtensions.kt
@@ -0,0 +1,5 @@
+package plutoproject.framework.common.util.data
+
+import java.util.*
+
+fun UUID.toShortUuidString(): String = toString().replace("-", "")
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/collection/Concurrent.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/collection/ConcurrentCollections.kt
similarity index 100%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/collection/Concurrent.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/collection/ConcurrentCollections.kt
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/collection/SafeSubList.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/collection/IterableExtensions.kt
similarity index 100%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/collection/SafeSubList.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/collection/IterableExtensions.kt
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Any2Json.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Any2Json.kt
deleted file mode 100644
index 7dc99b216..000000000
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Any2Json.kt
+++ /dev/null
@@ -1,17 +0,0 @@
-package plutoproject.framework.common.util.data.json
-
-import com.google.gson.Gson
-import com.google.gson.JsonElement
-import com.google.gson.JsonObject
-
-fun Any.toJsonObject(gson: Gson = GSON): JsonObject {
-    return gson.toJsonTree(this).asJsonObject
-}
-
-fun Any.toJsonElement(gson: Gson = GSON): JsonElement {
-    return gson.toJsonTree(this)
-}
-
-fun Any.toJsonString(gson: Gson = GSON): String {
-    return gson.toJson(this)
-}
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Constants.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Gson.kt
similarity index 77%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Constants.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Gson.kt
index 9fc277599..eac2e252e 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Constants.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Gson.kt
@@ -2,4 +2,4 @@ package plutoproject.framework.common.util.data.json
 
 import com.google.gson.Gson
 
-val GSON: Gson = Gson()
+val Gson: Gson = Gson()
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Json2Object.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/JsonConvertors.kt
similarity index 52%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Json2Object.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/JsonConvertors.kt
index 35f2827b3..ba3884aeb 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/Json2Object.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/json/JsonConvertors.kt
@@ -4,18 +4,30 @@ import com.google.gson.Gson
 import com.google.gson.JsonElement
 import com.google.gson.JsonObject
 
-inline fun <reified T> JsonElement.toObject(gson: Gson = GSON): T {
+fun Any.toJsonObject(gson: Gson = Gson): JsonObject {
+    return gson.toJsonTree(this).asJsonObject
+}
+
+fun Any.toJsonElement(gson: Gson = Gson): JsonElement {
+    return gson.toJsonTree(this)
+}
+
+fun Any.toJsonString(gson: Gson = Gson): String {
+    return gson.toJson(this)
+}
+
+inline fun <reified T> JsonElement.toObject(gson: Gson = Gson): T {
     return gson.fromJson(this, T::class.java)
 }
 
-inline fun <reified T> JsonObject.toObject(gson: Gson = GSON): T {
+inline fun <reified T> JsonObject.toObject(gson: Gson = Gson): T {
     return gson.fromJson(this, T::class.java)
 }
 
-inline fun <reified T> String.convertJsonToObject(gson: Gson = GSON): T {
+inline fun <reified T> String.convertJsonToObject(gson: Gson = Gson): T {
     return gson.fromJson(this, T::class.java)
 }
 
-fun <T> String.convertJsonToObject(type: Class<T>, gson: Gson = GSON): T {
+fun <T> String.convertJsonToObject(type: Class<T>, gson: Gson = Gson): T {
     return gson.fromJson(this, type)
 }
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializer/JavaUuidSerializer.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializers/JavaUuidSerializer.kt
similarity index 92%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializer/JavaUuidSerializer.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializers/JavaUuidSerializer.kt
index 86c10f546..ef481028a 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializer/JavaUuidSerializer.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializers/JavaUuidSerializer.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.common.util.data.serializer
+package plutoproject.framework.common.util.data.serializers
 
 import kotlinx.serialization.KSerializer
 import kotlinx.serialization.descriptors.PrimitiveKind
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializer/bson/JavaUuidBsonSerializer.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializers/bson/JavaUuidBsonSerializer.kt
similarity index 95%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializer/bson/JavaUuidBsonSerializer.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializers/bson/JavaUuidBsonSerializer.kt
index 633173bd1..12f4670f2 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializer/bson/JavaUuidBsonSerializer.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/serializers/bson/JavaUuidBsonSerializer.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.common.util.data.serializer.bson
+package plutoproject.framework.common.util.data.serializers.bson
 
 import kotlinx.serialization.ExperimentalSerializationApi
 import kotlinx.serialization.KSerializer
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/uuid/String2Uuid.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/uuid/String2Uuid.kt
deleted file mode 100644
index 26052458c..000000000
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/data/uuid/String2Uuid.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package plutoproject.framework.common.util.data.uuid
-
-import java.util.*
-
-fun String.convertToUuid(): UUID = UUID.fromString(this)
-
-fun String.convertToUuidOrNull(): UUID? =
-    try {
-        UUID.fromString(this)
-    } catch (e: IllegalArgumentException) {
-        null
-    }
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/Constants.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/ByteBuddy.kt
similarity index 73%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/Constants.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/ByteBuddy.kt
index be32cada1..4101b64d0 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/Constants.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/ByteBuddy.kt
@@ -3,7 +3,6 @@ package plutoproject.framework.common.util.jvm
 import net.bytebuddy.ByteBuddy
 import net.bytebuddy.agent.ByteBuddyAgent
 
-@Suppress("UNUSED")
-val BYTE_BUDDY = ByteBuddy().also {
+val ByteBuddy = ByteBuddy().also {
     ByteBuddyAgent.install()
 }
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/clazz/Load.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/ClassHelpers.kt
similarity index 71%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/clazz/Load.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/ClassHelpers.kt
index 98db901df..17abadf35 100644
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/clazz/Load.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/ClassHelpers.kt
@@ -1,8 +1,13 @@
-package plutoproject.framework.common.util.jvm.clazz
+package plutoproject.framework.common.util.jvm
 
 import io.github.classgraph.ClassGraph
 
-@Suppress("UNUSED")
+fun findClass(fqn: String): Class<*>? {
+    return runCatching {
+        Class.forName(fqn)
+    }.getOrNull()
+}
+
 fun loadClassesInPackages(
     vararg packageName: String,
     classLoader: ClassLoader = Thread.currentThread().contextClassLoader,
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/clazz/Find.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/clazz/Find.kt
deleted file mode 100644
index 4892831ce..000000000
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/jvm/clazz/Find.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package plutoproject.framework.common.util.jvm.clazz
-
-fun findClass(fqn: String): Class<*>? {
-    return runCatching {
-        Class.forName(fqn)
-    }.getOrNull()
-}
\ No newline at end of file
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/CostantUrls.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/CostantUrls.kt
deleted file mode 100644
index ed6ca4931..000000000
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/CostantUrls.kt
+++ /dev/null
@@ -1,3 +0,0 @@
-package plutoproject.framework.common.util.network
-
-const val MOJANG_API = "https://api.mojang.com/"
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/InetSocketAddressConvertor.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/SocketAddressExtensions.kt
similarity index 100%
rename from framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/InetSocketAddressConvertor.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/SocketAddressExtensions.kt
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/UrlConstants.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/UrlConstants.kt
new file mode 100644
index 000000000..c7433ed10
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/network/UrlConstants.kt
@@ -0,0 +1,5 @@
+package plutoproject.framework.common.util.network
+
+object UrlConstants {
+    const val MOJANG_API = "https://api.mojang.com/"
+}
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/proto/Constant.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/proto/Constant.kt
deleted file mode 100644
index 67e745469..000000000
--- a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/proto/Constant.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package plutoproject.framework.common.util.proto
-
-import com.google.protobuf.Empty
-
-val EMPTY: Empty = Empty.getDefaultInstance()
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/NumberExtensions.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/NumberExtensions.kt
new file mode 100644
index 000000000..21b6cc433
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/NumberExtensions.kt
@@ -0,0 +1,12 @@
+package plutoproject.framework.common.util.time
+
+import java.time.Instant
+import kotlin.time.Duration
+import kotlin.time.DurationUnit
+import kotlin.time.toDuration
+
+val Int.ticks: Duration get() = (this * 50).toDuration(DurationUnit.MILLISECONDS)
+
+val Long.ticks: Duration get() = (this * 50).toDuration(DurationUnit.MILLISECONDS)
+
+fun Long.toInstant(): Instant = Instant.ofEpochMilli(this)
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/TemporalExtensions.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/TemporalExtensions.kt
new file mode 100644
index 000000000..c513b5534
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/TemporalExtensions.kt
@@ -0,0 +1,39 @@
+package plutoproject.framework.common.util.time
+
+import java.time.LocalDate
+import java.time.LocalDateTime
+import java.time.YearMonth
+import java.time.ZonedDateTime
+import java.time.format.DateTimeFormatter
+
+private val morningDateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd 上午 hh:mm:ss")
+private val afternoonDateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd 下午 hh:mm:ss")
+private val morningTimeFormatter = DateTimeFormatter.ofPattern("上午 hh:mm:ss")
+private val afternoonTimeFormatter = DateTimeFormatter.ofPattern("下午 hh:mm:ss")
+private val dateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd")
+
+fun LocalDateTime.format(): String =
+    if (hour < 12) morningDateFormatter.format(this) else afternoonDateFormatter.format(this)
+
+fun LocalDateTime.formatTime(): String =
+    if (hour < 12) morningTimeFormatter.format(this) else afternoonTimeFormatter.format(this)
+
+fun LocalDateTime.formatDate(): String = dateFormatter.format(this)
+
+fun ZonedDateTime.format(): String =
+    if (hour < 12) morningDateFormatter.format(this) else afternoonDateFormatter.format(this)
+
+fun ZonedDateTime.formatTime(): String =
+    if (hour < 12) morningTimeFormatter.format(this) else afternoonTimeFormatter.format(this)
+
+fun ZonedDateTime.formatDate(): String = dateFormatter.format(this)
+
+fun LocalDate.formatDate(): String = dateFormatter.format(this)
+
+fun LocalDate.atEndOfDay(): LocalDateTime {
+    return atTime(23, 59, 59)
+}
+
+fun YearMonth.atStartOfMonth(): LocalDate {
+    return atDay(1)
+}
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/Timestamp.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/Timestamp.kt
new file mode 100644
index 000000000..2abb66a44
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/Timestamp.kt
@@ -0,0 +1,3 @@
+package plutoproject.framework.common.util.time
+
+val currentTimestampMillis get() = System.currentTimeMillis()
diff --git a/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/Timezone.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/Timezone.kt
new file mode 100644
index 000000000..ceb75a62c
--- /dev/null
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/Timezone.kt
@@ -0,0 +1,8 @@
+package plutoproject.framework.common.util.time
+
+import java.time.ZoneId
+import java.util.*
+
+val LocalZoneId: ZoneId = ZoneId.systemDefault()
+
+val LocalTimeZone: TimeZone = TimeZone.getTimeZone(LocalZoneId)
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/time/ZoneIdExts.kt b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/ZoneIdExtensions.kt
similarity index 53%
rename from framework/api/src/main/kotlin/ink/pmc/framework/time/ZoneIdExts.kt
rename to framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/ZoneIdExtensions.kt
index a4ca09985..c1e59ca07 100644
--- a/framework/api/src/main/kotlin/ink/pmc/framework/time/ZoneIdExts.kt
+++ b/framework-common-api/src/main/kotlin/plutoproject/framework/common/util/time/ZoneIdExtensions.kt
@@ -1,10 +1,9 @@
-package ink.pmc.framework.time
+package plutoproject.framework.common.util.time
 
 import java.time.Instant
 import java.time.ZoneId
 import java.time.ZoneOffset
 
-@Suppress("NOTHING_TO_INLINE")
-inline fun ZoneId.toOffset(): ZoneOffset {
+fun ZoneId.toOffset(): ZoneOffset {
     return rules.getOffset(Instant.now())
-}
\ No newline at end of file
+}
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/item/SkullTexture.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/ItemStackExtensions.kt
similarity index 94%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/item/SkullTexture.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/ItemStackExtensions.kt
index c5c1cf609..4ff5e8140 100644
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/item/SkullTexture.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/ItemStackExtensions.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.paper.util.item
+package plutoproject.framework.paper.util
 
 import com.destroystokyo.paper.profile.ProfileProperty
 import org.bukkit.Bukkit
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/Platform.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/Platform.kt
index 82becca68..28af2665d 100644
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/Platform.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/Platform.kt
@@ -4,7 +4,7 @@ import net.minecraft.server.MinecraftServer
 import org.bukkit.Server
 import org.bukkit.craftbukkit.CraftServer
 import org.bukkit.plugin.java.JavaPlugin
-import plutoproject.framework.common.util.jvm.clazz.findClass
+import plutoproject.framework.common.util.jvm.findClass
 
 val IS_FOLIA = findClass("io.papermc.paper.threadedregions.RegionizedServer") != null
 
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/resource/ResourceLocation.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/ResourceLocation.kt
similarity index 88%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/resource/ResourceLocation.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/ResourceLocation.kt
index bf42556a1..d75d9d60d 100644
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/resource/ResourceLocation.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/ResourceLocation.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.paper.util.resource
+package plutoproject.framework.paper.util
 
 import net.minecraft.resources.ResourceLocation
 
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/chat/ColorConvert.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/chat/ColorExtensions.kt
similarity index 100%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/chat/ColorConvert.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/chat/ColorExtensions.kt
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/chat/component/NmsConvert.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/chat/component/ComponentExtensions.kt
similarity index 100%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/chat/component/NmsConvert.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/chat/component/ComponentExtensions.kt
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/suggestion/PrivilegedSuggestion.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PaperPrivilegedSuggestion.kt
similarity index 85%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/suggestion/PrivilegedSuggestion.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PaperPrivilegedSuggestion.kt
index 7712d75d3..5ff19a250 100644
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/suggestion/PrivilegedSuggestion.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PaperPrivilegedSuggestion.kt
@@ -1,9 +1,9 @@
-package plutoproject.framework.paper.util.command.suggestion
+package plutoproject.framework.paper.util.command
 
 import org.bukkit.command.CommandSender
 import org.incendo.cloud.context.CommandContext
 import org.incendo.cloud.suggestion.SuggestionProvider
-import plutoproject.framework.common.util.command.suggestion.PrivilegedSuggestion
+import plutoproject.framework.common.util.command.PrivilegedSuggestion
 
 class PaperPrivilegedSuggestion<T : CommandSender>(
     wrap: SuggestionProvider<T>,
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PlayerEnsure.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PlayerHelpers.kt
similarity index 58%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PlayerEnsure.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PlayerHelpers.kt
index d61ac18c9..99ce4dc34 100644
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PlayerEnsure.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PlayerHelpers.kt
@@ -1,12 +1,13 @@
 package plutoproject.framework.paper.util.command
 
+import org.bukkit.OfflinePlayer
 import org.bukkit.command.CommandSender
 import org.bukkit.entity.Player
-import plutoproject.framework.common.util.chat.NON_PLAYER
+import plutoproject.framework.common.util.chat.MessageConstants
 
 fun ensurePlayer(sender: CommandSender, action: Player.() -> Unit) {
     if (sender !is Player) {
-        sender.sendMessage(NON_PLAYER)
+        sender.sendMessage(MessageConstants.nonPlayer)
         return
     }
     sender.action()
@@ -16,3 +17,7 @@ fun ensurePlayer(sender: CommandSender, action: Player.() -> Unit) {
 fun CommandSender.ensurePlayer(action: Player.() -> Unit) {
     ensurePlayer(this, action)
 }
+
+inline fun <reified T : OfflinePlayer> selectPlayer(self: CommandSender, other: T?): T? {
+    return other ?: self as? T
+}
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PlayerSelect.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PlayerSelect.kt
deleted file mode 100644
index e18dd550f..000000000
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PlayerSelect.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package plutoproject.framework.paper.util.command
-
-import org.bukkit.OfflinePlayer
-import org.bukkit.command.CommandSender
-
-inline fun <reified T : OfflinePlayer> selectPlayer(self: CommandSender, other: T?): T? {
-    return other ?: self as? T
-}
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/CommandManager.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PluginExtensions.kt
similarity index 100%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/CommandManager.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/command/PluginExtensions.kt
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/coroutine/CoroutineLaunchers.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/coroutine/CoroutineLaunchers.kt
index 821d140b8..42d9bc301 100644
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/coroutine/CoroutineLaunchers.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/coroutine/CoroutineLaunchers.kt
@@ -6,30 +6,30 @@ import kotlinx.coroutines.withContext
 import org.bukkit.Chunk
 import org.bukkit.Location
 import org.bukkit.entity.Entity
-import plutoproject.framework.common.util.coroutine.COROUTINE_SCOPE
+import plutoproject.framework.common.util.coroutine.PlutoCoroutineScope
 import plutoproject.framework.paper.util.server
 
 @Suppress("UNUSED")
 fun <T> runSync(
-    coroutineScope: CoroutineScope = COROUTINE_SCOPE,
+    coroutineScope: CoroutineScope = PlutoCoroutineScope,
     block: suspend CoroutineScope.() -> T,
 ) = coroutineScope.async(server.coroutineContext) { block() }
 
 @Suppress("UNUSED")
 fun <T> Entity.runSync(
-    coroutineScope: CoroutineScope = COROUTINE_SCOPE,
+    coroutineScope: CoroutineScope = PlutoCoroutineScope,
     block: suspend CoroutineScope.() -> T,
 ) = coroutineScope.async(coroutineContext) { block() }
 
 @Suppress("UNUSED")
 fun <T> Chunk.runSync(
-    coroutineScope: CoroutineScope = COROUTINE_SCOPE,
+    coroutineScope: CoroutineScope = PlutoCoroutineScope,
     block: suspend CoroutineScope.() -> T,
 ) = coroutineScope.async(coroutineContext) { block() }
 
 @Suppress("UNUSED")
 fun <T> Location.runSync(
-    coroutineScope: CoroutineScope = COROUTINE_SCOPE,
+    coroutineScope: CoroutineScope = PlutoCoroutineScope,
     block: suspend CoroutineScope.() -> T,
 ) = coroutineScope.async(coroutineContext) { block() }
 
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/data/model/LocationModel.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/data/models/LocationModel.kt
similarity index 89%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/data/model/LocationModel.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/data/models/LocationModel.kt
index 80260ffed..60107d164 100644
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/data/model/LocationModel.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/data/models/LocationModel.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.paper.util.data.model
+package plutoproject.framework.paper.util.data.models
 
 import kotlinx.serialization.Serializable
 import org.bukkit.Bukkit
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/Teleport.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/EntityExtensions.kt
similarity index 100%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/Teleport.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/EntityExtensions.kt
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/SwitchServer.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/PlayerExtensions.kt
similarity index 62%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/SwitchServer.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/PlayerExtensions.kt
index c8b7f8de9..98b45b56f 100644
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/SwitchServer.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/PlayerExtensions.kt
@@ -1,11 +1,20 @@
-package plutoproject.framework.paper.util.entity.player
+package plutoproject.framework.paper.util.entity
 
 import com.google.common.io.ByteStreams
+import net.minecraft.network.protocol.Packet
+import net.minecraft.server.level.ServerPlayer
+import org.bukkit.craftbukkit.entity.CraftPlayer
 import org.bukkit.entity.Player
 import plutoproject.framework.common.util.coroutine.runAsyncIO
 import plutoproject.framework.common.util.coroutine.withIO
 import plutoproject.framework.paper.util.plugin
 
+fun Player.toNmsPlayer(): ServerPlayer = (this as CraftPlayer).handle
+
+fun Player.sendPacket(packet: Packet<*>) {
+    toNmsPlayer().connection.send(packet)
+}
+
 suspend fun Player.switchServer(name: String) {
     withIO {
         val out = ByteStreams.newDataOutput()
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/UuidEntityLookup.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/UuidExtensions.kt
similarity index 100%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/UuidEntityLookup.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/UuidExtensions.kt
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/NmsConvert.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/NmsConvert.kt
deleted file mode 100644
index 9a1baf754..000000000
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/NmsConvert.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package plutoproject.framework.paper.util.entity.player
-
-import net.minecraft.server.level.ServerPlayer
-import org.bukkit.craftbukkit.entity.CraftPlayer
-import org.bukkit.entity.Player
-
-fun Player.toNmsPlayer(): ServerPlayer = (this as CraftPlayer).handle
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/SendPacket.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/SendPacket.kt
deleted file mode 100644
index 67b8a3699..000000000
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/entity/player/SendPacket.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package plutoproject.framework.paper.util.entity.player
-
-import net.minecraft.network.protocol.Packet
-import org.bukkit.entity.Player
-
-fun Player.sendPacket(packet: Packet<*>) {
-    toNmsPlayer().connection.send(packet)
-}
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/Title.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/InventoryViewExtensions.kt
similarity index 92%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/Title.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/InventoryViewExtensions.kt
index 4f3a648a2..8d87f2e47 100644
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/Title.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/InventoryViewExtensions.kt
@@ -7,7 +7,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer
 import org.bukkit.craftbukkit.inventory.CraftContainer
 import org.bukkit.entity.Player
 import org.bukkit.inventory.InventoryView
-import plutoproject.framework.paper.util.entity.player.sendPacket
+import plutoproject.framework.paper.util.entity.sendPacket
 
 fun InventoryView.title(component: Component) {
     val player = player as Player
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/IsFull.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/IsFull.kt
deleted file mode 100644
index efbe2cf89..000000000
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/IsFull.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package plutoproject.framework.paper.util.inventory
-
-import org.bukkit.inventory.PlayerInventory
-
-val PlayerInventory.isFull: Boolean
-    get() = !storageContents.contains(null)
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/player/AddItemOrDrop.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/PlayerInventoryExtensions.kt
similarity index 81%
rename from framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/player/AddItemOrDrop.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/PlayerInventoryExtensions.kt
index 25e78d7e9..31bcfc694 100644
--- a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/player/AddItemOrDrop.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/inventory/PlayerInventoryExtensions.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.paper.util.inventory.player
+package plutoproject.framework.paper.util.inventory
 
 import org.bukkit.entity.Item
 import org.bukkit.entity.Player
@@ -17,3 +17,6 @@ fun PlayerInventory.addItemOrDrop(vararg items: ItemStack): Map<Int, ItemStack>
     }
     return left
 }
+
+val PlayerInventory.isFull: Boolean
+    get() = !storageContents.contains(null)
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/WorldExtensions.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/WorldExtensions.kt
new file mode 100644
index 000000000..39f1b8aa6
--- /dev/null
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/WorldExtensions.kt
@@ -0,0 +1,18 @@
+package plutoproject.framework.paper.util.world
+
+import kotlinx.coroutines.future.await
+import net.minecraft.world.level.chunk.LevelChunk
+import net.minecraft.world.level.chunk.status.ChunkStatus
+import org.bukkit.Chunk
+import org.bukkit.World
+import org.bukkit.craftbukkit.CraftChunk
+import org.bukkit.craftbukkit.CraftWorld
+
+suspend fun World.getChunkFromSource(x: Int, z: Int): Chunk? {
+    val serverLevel = (this as CraftWorld).handle
+    val chunkSource = serverLevel.chunkSource
+    val result = chunkSource.getChunkFuture(x, z, ChunkStatus.FULL, true).await()
+    val chunkAccess = result.orElse(null) ?: return null
+    val levelChunk = chunkAccess as LevelChunk
+    return CraftChunk(levelChunk)
+}
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/world/ChunkExts.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/chunk/ChunkExtensions.kt
similarity index 70%
rename from framework/api/src/main/kotlin/ink/pmc/framework/world/ChunkExts.kt
rename to framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/chunk/ChunkExtensions.kt
index 71d0a6005..ce05a1abd 100644
--- a/framework/api/src/main/kotlin/ink/pmc/framework/world/ChunkExts.kt
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/chunk/ChunkExtensions.kt
@@ -1,22 +1,9 @@
-package ink.pmc.framework.world
+package plutoproject.framework.paper.util.world.chunk
 
-import ink.pmc.framework.concurrent.submitSync
-import ink.pmc.framework.platform.isFoliaOrAsync
 import net.minecraft.server.level.TicketType
 import org.bukkit.Chunk
 import org.bukkit.craftbukkit.CraftWorld
 
-@Suppress("UNUSED")
-fun Chunk.ensureThreadSafe(block: Chunk.() -> Unit) {
-    if (isFoliaOrAsync) {
-        this.submitSync {
-            block()
-        }
-        return
-    }
-    block()
-}
-
 fun <T> Chunk.addTicket(type: TicketType<T>, x: Int, z: Int, level: Int, identifier: T) {
     val handle = (this.world as CraftWorld).handle.chunkSource
     val distanceManager = handle.chunkMap.distanceManager
@@ -29,4 +16,4 @@ fun <T> Chunk.removeTicket(type: TicketType<T>, x: Int, z: Int, level: Int, iden
     val distanceManager = handle.chunkMap.distanceManager
     val holder = distanceManager.chunkHolderManager
     holder.removeTicketAtLevel(type, x, z, level, identifier)
-}
\ No newline at end of file
+}
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/chunk/ChunkLocation.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/chunk/ChunkLocation.kt
new file mode 100644
index 000000000..2e364e2d4
--- /dev/null
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/chunk/ChunkLocation.kt
@@ -0,0 +1,28 @@
+package plutoproject.framework.paper.util.world.chunk
+
+import kotlinx.coroutines.Deferred
+import kotlinx.coroutines.future.await
+import org.bukkit.Chunk
+import org.bukkit.World
+import plutoproject.framework.common.util.coroutine.runAsyncIO
+
+@JvmInline
+value class ChunkLocation(private val value: Long) {
+    constructor(x: Int, y: Int) : this(x.toLong() shl 32 or y.toLong())
+
+    val x: Int
+        get() = (value ushr 32).toInt()
+    val y: Int
+        get() = value.toInt()
+
+    fun isChunkLoaded(world: World): Boolean {
+        return world.isChunkLoaded(x, y)
+    }
+
+    suspend fun coordinateChunkIn(world: World): Chunk {
+        return world.getChunkAtAsync(x, y).await()
+    }
+
+    fun coordinateChunkInAsync(world: World): Deferred<Chunk> =
+        runAsyncIO { coordinateChunkIn(world) }
+}
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/Comparisons.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/Comparisons.kt
new file mode 100644
index 000000000..c309485dc
--- /dev/null
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/Comparisons.kt
@@ -0,0 +1,22 @@
+package plutoproject.framework.paper.util.world.location
+
+import org.bukkit.Location
+
+fun minLocationOf(a: Location, b: Location): Location =
+    Location(
+        a.world,
+        minOf(a.x, b.x),
+        minOf(a.y, b.y),
+        minOf(a.z, b.z)
+    )
+
+fun maxLocationOf(a: Location, b: Location): Location =
+    Location(
+        a.world,
+        maxOf(a.x, b.x),
+        maxOf(a.y, b.y),
+        maxOf(a.z, b.z)
+    )
+
+fun Location.blockEquals(other: Location): Boolean =
+    blockX == other.blockX && blockY == other.blockY && blockZ == other.blockZ
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/Location2D.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/Location2D.kt
new file mode 100644
index 000000000..c6c4473b1
--- /dev/null
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/Location2D.kt
@@ -0,0 +1,18 @@
+package plutoproject.framework.paper.util.world.location
+
+import org.bukkit.Location
+import org.bukkit.World
+
+data class Location2D(val world: World, val x: Double, val z: Double) {
+    constructor(location: Location) : this(location.world, location.x, location.z)
+
+    fun add(x: Double, z: Double): Location2D = copy(
+        x = this.x + x,
+        z = this.z + z,
+    )
+
+    fun subtract(x: Double, z: Double): Location2D = copy(
+        x = this.x - x,
+        z = this.z - z,
+    )
+}
diff --git a/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/LocationExtensions.kt b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/LocationExtensions.kt
new file mode 100644
index 000000000..01eaeb6ae
--- /dev/null
+++ b/framework-paper-api/src/main/kotlin/plutoproject/framework/paper/util/world/location/LocationExtensions.kt
@@ -0,0 +1,10 @@
+package plutoproject.framework.paper.util.world.location
+
+import org.bukkit.Location
+
+fun Location.toAngleErased(): Location {
+    val rawLocation = clone().toBlockLocation()
+    rawLocation.yaw = 0F
+    rawLocation.pitch = 0F
+    return rawLocation
+}
diff --git a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/player/SwitchServer.kt b/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/PlayerExtensions.kt
similarity index 78%
rename from framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/player/SwitchServer.kt
rename to framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/PlayerExtensions.kt
index 53dd00f24..349bb6ef8 100644
--- a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/player/SwitchServer.kt
+++ b/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/PlayerExtensions.kt
@@ -1,9 +1,8 @@
-package plutoproject.framework.velocity.util.player
+package plutoproject.framework.velocity.util
 
 import com.velocitypowered.api.proxy.ConnectionRequestBuilder
 import com.velocitypowered.api.proxy.Player
 import kotlinx.coroutines.future.await
-import plutoproject.framework.velocity.util.server
 
 suspend fun Player.switchServer(name: String): ConnectionRequestBuilder.Result {
     val registeredServer = server.getServer(name).get()
diff --git a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/chat/Broadcast.kt b/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/ProxyServerExtensions.kt
similarity index 82%
rename from framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/chat/Broadcast.kt
rename to framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/ProxyServerExtensions.kt
index a9fd738a3..ce9e337cb 100644
--- a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/chat/Broadcast.kt
+++ b/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/ProxyServerExtensions.kt
@@ -1,4 +1,4 @@
-package plutoproject.framework.velocity.util.chat
+package plutoproject.framework.velocity.util
 
 import com.velocitypowered.api.proxy.ProxyServer
 import net.kyori.adventure.text.Component
diff --git a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PlayerEnsure.kt b/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PlayerHelpers.kt
similarity index 64%
rename from framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PlayerEnsure.kt
rename to framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PlayerHelpers.kt
index e25fc1413..23fc9236b 100644
--- a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PlayerEnsure.kt
+++ b/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PlayerHelpers.kt
@@ -2,11 +2,11 @@ package plutoproject.framework.velocity.util.command
 
 import com.velocitypowered.api.command.CommandSource
 import com.velocitypowered.api.proxy.Player
-import plutoproject.framework.common.util.chat.NON_PLAYER
+import plutoproject.framework.common.util.chat.MessageConstants
 
 fun ensurePlayer(sender: CommandSource, action: Player.() -> Unit) {
     if (sender !is Player) {
-        sender.sendMessage(NON_PLAYER)
+        sender.sendMessage(MessageConstants.nonPlayer)
         return
     }
     sender.action()
@@ -16,3 +16,7 @@ fun ensurePlayer(sender: CommandSource, action: Player.() -> Unit) {
 fun CommandSource.ensurePlayer(action: Player.() -> Unit) {
     ensurePlayer(this, action)
 }
+
+inline fun <reified T : Player> selectPlayer(self: CommandSource, other: T?): T? {
+    return other ?: self as? T
+}
diff --git a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PlayerSelect.kt b/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PlayerSelect.kt
deleted file mode 100644
index 3ff2f8cdb..000000000
--- a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PlayerSelect.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package plutoproject.framework.velocity.util.command
-
-import com.velocitypowered.api.command.CommandSource
-import com.velocitypowered.api.proxy.Player
-
-inline fun <reified T : Player> selectPlayer(self: CommandSource, other: T?): T? {
-    return other ?: self as? T
-}
diff --git a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/CommandManager.kt b/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PluginContainerExtensions.kt
similarity index 100%
rename from framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/CommandManager.kt
rename to framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/PluginContainerExtensions.kt
diff --git a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/suggestion/VelocityPrivilegedSuggestion.kt b/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/VelocityPrivilegedSuggestion.kt
similarity index 85%
rename from framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/suggestion/VelocityPrivilegedSuggestion.kt
rename to framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/VelocityPrivilegedSuggestion.kt
index 2256d912f..850a2ce8b 100644
--- a/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/suggestion/VelocityPrivilegedSuggestion.kt
+++ b/framework-velocity-api/src/main/kotlin/plutoproject/framework/velocity/util/command/VelocityPrivilegedSuggestion.kt
@@ -1,9 +1,9 @@
-package plutoproject.framework.velocity.util.command.suggestion
+package plutoproject.framework.velocity.util.command
 
 import com.velocitypowered.api.command.CommandSource
 import org.incendo.cloud.context.CommandContext
 import org.incendo.cloud.suggestion.SuggestionProvider
-import plutoproject.framework.common.util.command.suggestion.PrivilegedSuggestion
+import plutoproject.framework.common.util.command.PrivilegedSuggestion
 
 class VelocityPrivilegedSuggestion<T : CommandSource>(
     wrap: SuggestionProvider<T>,
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/Env.kt b/framework/api/src/main/kotlin/ink/pmc/framework/Env.kt
deleted file mode 100644
index bc58e44d5..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/Env.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package ink.pmc.framework
-
-import ink.pmc.framework.jvm.findClass
-import java.io.File
-import java.util.logging.Logger
-
-lateinit var frameworkLogger: Logger
-lateinit var frameworkDataFolder: File
-
-inline val frameworkClassLoader
-    get() = findClass("ink.pmc.framework.PaperPlugin")?.classLoader
-        ?: findClass("ink.pmc.framework.VelocityPlugin")?.classLoader
-        ?: error("Cannot find framework plugin class")
-
-inline val runtimeClassLoader
-    get() = findClass("ink.pmc.runtime.PaperPlugin")?.classLoader
-        ?: findClass("ink.pmc.runtime.VelocityPlugin")?.classLoader
-        ?: error("Cannot find runtime plugin class")
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/EnvPaper.kt b/framework/api/src/main/kotlin/ink/pmc/framework/EnvPaper.kt
deleted file mode 100644
index b864aa336..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/EnvPaper.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package ink.pmc.framework
-
-import org.bukkit.Bukkit
-import org.bukkit.plugin.Plugin
-
-inline val frameworkPaper: Plugin
-    get() = Bukkit.getServer().pluginManager.getPlugin("plutoproject_framework")!!
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/EnvVelocity.kt b/framework/api/src/main/kotlin/ink/pmc/framework/EnvVelocity.kt
deleted file mode 100644
index 4303df952..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/EnvVelocity.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package ink.pmc.framework
-
-import com.velocitypowered.api.plugin.PluginContainer
-
-lateinit var frameworkVelocity: PluginContainer
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/Math.kt b/framework/api/src/main/kotlin/ink/pmc/framework/Math.kt
deleted file mode 100644
index 91a55d824..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/Math.kt
+++ /dev/null
@@ -1,20 +0,0 @@
-package ink.pmc.framework
-
-import java.math.BigDecimal
-import java.math.RoundingMode
-
-fun Double.roundToTwoDecimals(): Double {
-    return BigDecimal(this).setScale(2, RoundingMode.HALF_EVEN).toDouble()
-}
-
-fun Double.trimmed(): String {
-    // 将 Double 转换为字符串并去除末尾多余的 0
-    var result = toBigDecimal().stripTrailingZeros().toPlainString()
-
-    // 如果最后一位是 '.',去除它
-    if (result.endsWith(".")) {
-        result = result.dropLast(1)
-    }
-
-    return result
-}
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/Time.kt b/framework/api/src/main/kotlin/ink/pmc/framework/Time.kt
deleted file mode 100644
index 8d54f6eb2..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/Time.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package ink.pmc.framework
-
-inline val currentUnixTimestamp
-    get() = System.currentTimeMillis()
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/Typealiases.kt b/framework/api/src/main/kotlin/ink/pmc/framework/Typealiases.kt
deleted file mode 100644
index a9a70ac41..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/Typealiases.kt
+++ /dev/null
@@ -1,12 +0,0 @@
-package ink.pmc.framework
-
-import com.velocitypowered.api.command.CommandSource
-import io.papermc.paper.command.brigadier.CommandSourceStack
-import org.incendo.cloud.context.CommandContext
-import org.incendo.cloud.paper.PaperCommandManager
-import org.incendo.cloud.velocity.VelocityCommandManager
-
-typealias PaperCm = PaperCommandManager<CommandSourceStack>
-typealias PaperCtx = CommandContext<CommandSourceStack>
-typealias VelocityCm = VelocityCommandManager<CommandSource>
-typealias VelocityCtx = CommandContext<CommandSource>
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/time/Formatter.kt b/framework/api/src/main/kotlin/ink/pmc/framework/time/Formatter.kt
deleted file mode 100644
index dc120fb8f..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/time/Formatter.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package ink.pmc.framework.time
-
-import java.time.LocalDate
-import java.time.LocalDateTime
-import java.time.ZonedDateTime
-import java.time.format.DateTimeFormatter
-
-private val morningFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd 上午 hh:mm:ss")
-private val afternoonFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd 下午 hh:mm:ss")
-private val morningTimeFormatter = DateTimeFormatter.ofPattern("上午 hh:mm:ss")
-private val afterTimeFormatter = DateTimeFormatter.ofPattern("下午 hh:mm:ss")
-private val dateFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd")
-
-fun LocalDateTime.format(): String {
-    return if (hour < 12) morningFormatter.format(this) else afternoonFormatter.format(this)
-}
-
-fun LocalDateTime.formatTime(): String {
-    return if (hour < 12) morningTimeFormatter.format(this) else afterTimeFormatter.format(this)
-}
-
-fun LocalDateTime.formatDate(): String {
-    return dateFormatter.format(this)
-}
-
-fun ZonedDateTime.format(): String {
-    return if (hour < 12) morningFormatter.format(this) else afternoonFormatter.format(this)
-}
-
-fun ZonedDateTime.formatTime(): String {
-    return if (hour < 12) morningTimeFormatter.format(this) else afterTimeFormatter.format(this)
-}
-
-fun ZonedDateTime.formatDate(): String {
-    return dateFormatter.format(this)
-}
-
-fun LocalDate.formatDate(): String {
-    return dateFormatter.format(this)
-}
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/time/IntExts.kt b/framework/api/src/main/kotlin/ink/pmc/framework/time/IntExts.kt
deleted file mode 100644
index 1af940ad6..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/time/IntExts.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package ink.pmc.framework.time
-
-import kotlin.time.Duration
-import kotlin.time.DurationUnit
-import kotlin.time.toDuration
-
-inline val Int.ticks: Duration get() = (this * 50).toDuration(DurationUnit.MILLISECONDS)
-
-inline val Long.ticks: Duration get() = (this * 50).toDuration(DurationUnit.MILLISECONDS)
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/time/LocalDateTimeExts.kt b/framework/api/src/main/kotlin/ink/pmc/framework/time/LocalDateTimeExts.kt
deleted file mode 100644
index 456fad295..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/time/LocalDateTimeExts.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package ink.pmc.framework.time
-
-import java.time.LocalDate
-import java.time.LocalDateTime
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun LocalDate.atEndOfDay(): LocalDateTime {
-    return atTime(23, 59, 59)
-}
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/time/LongExts.kt b/framework/api/src/main/kotlin/ink/pmc/framework/time/LongExts.kt
deleted file mode 100644
index 84ddfe78f..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/time/LongExts.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package ink.pmc.framework.time
-
-import java.time.Instant
-
-inline val Long.instant: Instant
-    get() = Instant.ofEpochMilli(this)
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/time/Timezone.kt b/framework/api/src/main/kotlin/ink/pmc/framework/time/Timezone.kt
deleted file mode 100644
index 0be8dca43..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/time/Timezone.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package ink.pmc.framework.time
-
-import java.time.ZoneId
-import java.util.*
-
-@Suppress("UNUSED")
-inline val currentZoneId: ZoneId
-    get() = ZoneId.systemDefault()
-
-inline val currentTimeZone: TimeZone
-    get() = TimeZone.getTimeZone(currentZoneId)
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/time/YearMonthExts.kt b/framework/api/src/main/kotlin/ink/pmc/framework/time/YearMonthExts.kt
deleted file mode 100644
index dcae8ee4f..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/time/YearMonthExts.kt
+++ /dev/null
@@ -1,9 +0,0 @@
-package ink.pmc.framework.time
-
-import java.time.LocalDate
-import java.time.YearMonth
-
-@Suppress("NOTHING_TO_INLINE")
-inline fun YearMonth.atStartOfMonth(): LocalDate {
-    return atDay(1)
-}
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/world/Loc2.kt b/framework/api/src/main/kotlin/ink/pmc/framework/world/Loc2.kt
deleted file mode 100644
index e8012c987..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/world/Loc2.kt
+++ /dev/null
@@ -1,31 +0,0 @@
-package ink.pmc.framework.world
-
-import org.bukkit.Location
-import org.bukkit.World
-
-@Suppress("UNUSED")
-data class Loc2(var world: World, var x: Double, var z: Double) : Cloneable {
-    constructor(world: World, vec2: Vec2) : this(world, vec2.x, vec2.z)
-
-    constructor(location: Location) : this(location.world, location.x, location.z)
-
-    fun toVec2(): Vec2 {
-        return Vec2(this.x, this.z)
-    }
-
-    fun add(x: Double, z: Double): Loc2 {
-        this.x += x
-        this.z += z
-        return this
-    }
-
-    fun subtract(x: Double, z: Double): Loc2 {
-        this.x -= x
-        this.z -= z
-        return this
-    }
-
-    override fun clone(): Loc2 {
-        return Loc2(this.world, this.x, this.z)
-    }
-}
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/world/LocationExts.kt b/framework/api/src/main/kotlin/ink/pmc/framework/world/LocationExts.kt
deleted file mode 100644
index b6de8df7d..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/world/LocationExts.kt
+++ /dev/null
@@ -1,32 +0,0 @@
-package ink.pmc.framework.world
-
-import org.bukkit.Location
-
-fun Location.eraseAngle(): Location {
-    val rawLocation = clone().toBlockLocation()
-    rawLocation.yaw = 0F
-    rawLocation.pitch = 0F
-    return rawLocation
-}
-
-fun minLocation(a: Location, b: Location): Location {
-    return Location(
-        a.world,
-        minOf(a.x, b.x),
-        minOf(a.y, b.y),
-        minOf(a.z, b.z)
-    )
-}
-
-fun maxLocation(a: Location, b: Location): Location {
-    return Location(
-        a.world,
-        maxOf(a.x, b.x),
-        maxOf(a.y, b.y),
-        maxOf(a.z, b.z)
-    )
-}
-
-fun Location.blockEquals(other: Location): Boolean {
-    return blockX == other.blockX && blockY == other.blockY && blockZ == other.blockZ
-}
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/world/ValueVec2.kt b/framework/api/src/main/kotlin/ink/pmc/framework/world/ValueVec2.kt
deleted file mode 100644
index 0c0539131..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/world/ValueVec2.kt
+++ /dev/null
@@ -1,33 +0,0 @@
-package ink.pmc.framework.world
-
-import kotlinx.coroutines.future.await
-import org.bukkit.Chunk
-import org.bukkit.World
-import java.util.concurrent.CompletableFuture
-
-@Suppress("UNUSED")
-@JvmInline
-value class ValueVec2(private val value: Long) {
-    constructor(x: Int, y: Int) : this(x.toLong() shl 32 or y.toLong())
-
-    val x: Int
-        get() = (value ushr 32).toInt()
-    val y: Int
-        get() = value.toInt()
-
-    fun isLoaded(world: World): Boolean {
-        return world.isChunkLoaded(x, y)
-    }
-
-    fun getChunk(world: World): Chunk {
-        return world.getChunkAt(x, y)
-    }
-
-    fun getChunkAsync(world: World): CompletableFuture<Chunk> {
-        return world.getChunkAtAsync(x, y)
-    }
-
-    suspend fun getChunkSuspend(world: World): Chunk {
-        return getChunkAsync(world).await()
-    }
-}
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/world/Vec2.kt b/framework/api/src/main/kotlin/ink/pmc/framework/world/Vec2.kt
deleted file mode 100644
index 23e4001f5..000000000
--- a/framework/api/src/main/kotlin/ink/pmc/framework/world/Vec2.kt
+++ /dev/null
@@ -1,29 +0,0 @@
-package ink.pmc.framework.world
-
-import org.bukkit.Location
-import org.bukkit.World
-
-@Suppress("UNUSED")
-data class Vec2(var x: Double, var z: Double) : Cloneable {
-    constructor(location: Location) : this(location.x, location.z)
-
-    fun toLoc2(world: World): Loc2 {
-        return Loc2(world, this)
-    }
-
-    fun add(x: Double, z: Double): Vec2 {
-        this.x += x
-        this.z += z
-        return this
-    }
-
-    fun subtract(x: Double, z: Double): Vec2 {
-        this.x -= x
-        this.z -= z
-        return this
-    }
-
-    override fun clone(): Vec2 {
-        return Vec2(this.x, this.z)
-    }
-}
\ No newline at end of file
diff --git a/framework/api/src/main/kotlin/ink/pmc/framework/world/WorldExts.kt b/framework/api/src/main/kotlin/ink/pmc/framework/world/WorldExts.kt
index 4ad70c98d..97fdd4330 100644
--- a/framework/api/src/main/kotlin/ink/pmc/framework/world/WorldExts.kt
+++ b/framework/api/src/main/kotlin/ink/pmc/framework/world/WorldExts.kt
@@ -1,24 +1,9 @@
 package ink.pmc.framework.world
 
 import ink.pmc.framework.FrameworkConfig
-import kotlinx.coroutines.future.await
-import net.minecraft.world.level.chunk.LevelChunk
-import net.minecraft.world.level.chunk.status.ChunkStatus
-import org.bukkit.Chunk
 import org.bukkit.World
-import org.bukkit.craftbukkit.CraftChunk
-import org.bukkit.craftbukkit.CraftWorld
 import org.koin.java.KoinJavaComponent.getKoin
 
-suspend fun World.getChunkViaSource(x: Int, z: Int): Chunk? {
-    val serverLevel = (this as CraftWorld).handle
-    val chunkSource = serverLevel.chunkSource
-    val result = chunkSource.getChunkFuture(x, z, ChunkStatus.FULL, true).await()
-    val chunkAccess = result.orElse(null) ?: return null
-    val levelChunk = chunkAccess as LevelChunk
-    return CraftChunk(levelChunk)
-}
-
 val World.alias: String?
     get() = getKoin().get<FrameworkConfig>().worldAliases[name]