Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
ef6dc58
Merge pull request #701 from zhibeigg/fix/afybroker-bukkit-nms-init
Bkm016 Jun 20, 2026
d42347c
fix(kether): 支持空字符串字面量
Bkm016 Jun 23, 2026
93a15fe
feat(ptc): 增加 SQL 文件迁移
Bkm016 Jun 23, 2026
2650e27
支持 26.2
Micalhl Jun 23, 2026
5a91406
修复 ItemTag
Micalhl Jun 23, 2026
25d44a0
fix(database): 修复 SQLite 连接参数
Bkm016 Jun 23, 2026
3630ccc
fix(env): 启动主线程预热协程运行时,修复多插件共存时登录偶发崩溃
zhibeigg Jun 28, 2026
9d87505
fix(env): 完善协程预热类列表
zhibeigg Jul 2, 2026
63c7962
Merge pull request #702 from zhibeigg/fix/coroutine-warmup-on-load
Bkm016 Jul 4, 2026
fa2d075
fix(nms): 跳过合成 Lambda 的 Spigot 译名告警
Bkm016 Jul 11, 2026
0eb2aa6
fix(nms): 补扫延迟注册的数据包通道
Bkm016 Jul 11, 2026
489532f
fix(core): 修复异步任务与资源生命周期
zhibeigg Jul 13, 2026
5247654
fix(submit-chain): 完善异常与取消传播
zhibeigg Jul 13, 2026
8bcae92
fix(kether): 修复异步上下文完成与线程切换
zhibeigg Jul 13, 2026
335ebf7
fix(common): 修复共享基础组件并发竞态
zhibeigg Jul 13, 2026
2161a1e
fix(database): 完善数据库与 Redis 资源生命周期
zhibeigg Jul 13, 2026
7185839
fix(database): 修复玩家数据并发写入一致性
zhibeigg Jul 13, 2026
ac061eb
fix: 修复配置、SQL 与 JEXL 正确性问题
zhibeigg Jul 13, 2026
51abf12
fix(bukkit): 收紧 Folia 调度与背包线程所有权
zhibeigg Jul 13, 2026
229d4dc
fix(porticus): 修复发送线程与分包竞态
zhibeigg Jul 13, 2026
39baf1e
fix(platform): 修复生命周期终态与任务清理
zhibeigg Jul 13, 2026
fa22c89
fix(platform): 修复多平台适配正确性
zhibeigg Jul 13, 2026
faad63a
fix(navigation): 修复世界边界与路径平滑判定
zhibeigg Jul 13, 2026
8d33d67
fix(lang): 修复语言重载与颜色解析边界
zhibeigg Jul 13, 2026
cc3cffb
fix(build): 修复 Maven 发布模型与 Java 8 门禁
zhibeigg Jul 13, 2026
d078ad0
chore(release): 发布 6.3.1 统一补丁
zhibeigg Jul 13, 2026
3a32452
修复 Mojang 运行时类名转译
Jie-150 Jul 13, 2026
0ea7a10
fix(review): 修复评审指出的跨 PR 回归与阻塞级问题
FxRayHughes Jul 26, 2026
d78fca8
fix(review): 处理 nms 转译性能、平台异常传播与测试稳定性
FxRayHughes Jul 26, 2026
d362e69
fix(review): 消除 porticus 完成判定的异常控制流并修正 Velocity 注释
FxRayHughes Jul 26, 2026
92c9e71
refactor(review): 收紧 Porticus 任务表与命令表的并发结构
FxRayHughes Jul 26, 2026
8513ba0
fix(review): 真正修复导航节点哈希碰撞并统一 JSON 类型判断
FxRayHughes Jul 26, 2026
9f61294
fix(review): 完善数据库写入一致性、资源生命周期与方言兼容
FxRayHughes Jul 26, 2026
a79a254
fix(review): 统一 Redis 连接所有权并标注语义变更的公开字段
FxRayHughes Jul 26, 2026
177ddbb
fix(review): 补齐配置转换的注册表查询与节流状态重置
FxRayHughes Jul 26, 2026
5c19dc4
docs(review): 补充破坏性变更的兼容性说明并统一转译方法命名
FxRayHughes Jul 26, 2026
e772a70
refactor(platform): 抽取四平台 executor 的公共状态机
FxRayHughes Jul 26, 2026
cdf485e
fix(kether): 以无锁状态机消除父子 frame 的 ABBA 死锁
FxRayHughes Jul 26, 2026
a97d8f4
chore: 忽略 JVM 堆转储文件
FxRayHughes Jul 26, 2026
46bf9b9
Merge remote-tracking branch 'upstream/dev/6.3.0' into fix/703-integr…
FxRayHughes Jul 26, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,6 @@ bin
doc
.claude/
nul

# JVM 堆转储(构建期 OOM 时生成,体积可达数百 MB)
*.hprof
249 changes: 233 additions & 16 deletions build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,18 +1,30 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.gradle.api.artifacts.ExternalModuleDependency
import org.gradle.api.artifacts.ProjectDependency
import org.gradle.api.publish.maven.tasks.GenerateMavenPom
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.compile.JavaCompile
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import ru.vyarus.gradle.plugin.animalsniffer.AnimalSnifferExtension
import java.io.DataInputStream
import java.io.File
import javax.xml.parsers.DocumentBuilderFactory

plugins {
`maven-publish`
java
id("org.jetbrains.kotlin.jvm") version "1.8.22" apply false
id("com.github.johnrengelman.shadow") version "7.1.2" apply false
id("ru.vyarus.animalsniffer") version "2.0.1" apply false
}

subprojects {
apply(plugin = "java-library")
apply(plugin = "org.jetbrains.kotlin.jvm")
apply(plugin = "com.github.johnrengelman.shadow")
apply(plugin = "maven-publish")
apply(plugin = "ru.vyarus.animalsniffer")

repositories {
maven("https://jitpack.io")
Expand All @@ -33,6 +45,7 @@ subprojects {
compileOnly("org.apache.commons:commons-lang3:3.5")
compileOnly("org.tabooproject.reflex:reflex:1.2.4")
compileOnly("org.tabooproject.reflex:analyser:1.2.4")
add("signature", "org.codehaus.mojo.signature:java18:1.0@signature")
// 测试依赖
testImplementation(kotlin("stdlib"))
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
Expand All @@ -49,6 +62,27 @@ subprojects {
withSourcesJar()
}

configure<AnimalSnifferExtension> {
ignore = listOf(
"java.lang.invoke.MethodHandle",
"co.*",
"com.*",
"dev.*",
"ink.*",
"io.*",
"it.*",
"kotlin.*",
"kotlinx.*",
"me.*",
"net.*",
"org.*",
"reactor.*",
"redis.*",
"taboolib.*",
)
excludeJars = listOf("v260100-260100-minimize")
}

tasks.withType<Test> {
useJUnitPlatform()
}
Expand All @@ -74,12 +108,17 @@ subprojects {
relocate("org.tabooproject", "taboolib.library")
}

tasks.named<Jar>("jar") {
archiveClassifier.set("plain")
}

tasks.build {
dependsOn("shadowJar")
}

tasks.withType<JavaCompile> {
options.encoding = "UTF-8"
options.release.set(8)
options.compilerArgs.addAll(listOf("-XDenableSunApiLintControl"))
}

Expand All @@ -100,11 +139,183 @@ gradle.buildFinished {
buildDir.deleteRecursively()
}

subprojects
.filter { it.name != "module" && it.name != "platform" && it.name != "expansion" && !it.name.startsWith("impl") }
.forEach { proj ->
proj.publishing { applyToSub(proj) }
data class MavenCoordinate(val groupId: String, val artifactId: String, val version: String)

fun Project.publishedArtifactId(): String {
val extra = extensions.extraProperties
return if (extra.has("publishId")) extra.get("publishId").toString() else name
}

fun Project.publishedVersion(): String {
return when {
rootProject.hasProperty("devLocal") -> "${version}-local-dev"
rootProject.hasProperty("dev") -> "${version}-dev"
else -> version.toString()
}
}

fun Project.isPublishableModule(): Boolean {
if (name == "module" || name == "platform" || name == "expansion" || name.startsWith("impl")) {
return false
}
val mainSourceSet = extensions.getByType<SourceSetContainer>().getByName("main")
val hasMainContent = mainSourceSet.allSource.srcDirs.any { sourceDirectory ->
sourceDirectory.isDirectory && sourceDirectory.walkTopDown().any(File::isFile)
}
return hasMainContent || path == ":common-reflex"
}

fun Project.apiPomCoordinates(): List<MavenCoordinate> {
val publicDependencies = configurations.getByName("api").dependencies +
configurations.getByName("compileOnlyApi").dependencies
return publicDependencies.mapNotNull { dependency ->
when (dependency) {
is ProjectDependency -> {
val dependencyProject = dependency.dependencyProject
MavenCoordinate("io.izzel.taboolib", dependencyProject.publishedArtifactId(), dependencyProject.publishedVersion())
}
is ExternalModuleDependency -> {
val groupId = dependency.group ?: return@mapNotNull null
val version = dependency.version ?: return@mapNotNull null
MavenCoordinate(groupId, dependency.name, version)
}
else -> null
}
}.distinct().sortedWith(compareBy(MavenCoordinate::groupId, MavenCoordinate::artifactId, MavenCoordinate::version))
}

fun readPomCoordinates(pomFile: File): Set<MavenCoordinate> {
val document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(pomFile)
val dependencies = document.getElementsByTagName("dependency")
return buildSet {
for (index in 0 until dependencies.length) {
val dependency = dependencies.item(index)
val children = dependency.childNodes
var groupId: String? = null
var artifactId: String? = null
var version: String? = null
for (childIndex in 0 until children.length) {
val child = children.item(childIndex)
when (child.nodeName) {
"groupId" -> groupId = child.textContent.trim()
"artifactId" -> artifactId = child.textContent.trim()
"version" -> version = child.textContent.trim()
}
}
if (groupId != null && artifactId != null && version != null) {
add(MavenCoordinate(groupId, artifactId, version))
}
}
}
}

fun classFileMajorVersion(classFile: File): Int {
return DataInputStream(classFile.inputStream().buffered()).use { input ->
check(input.readInt() == 0xCAFEBABE.toInt()) { "Invalid class file: $classFile" }
input.readUnsignedShort()
input.readUnsignedShort()
}
}

val verifyPublishingModel = tasks.register("verifyPublishingModel") {
group = "verification"
description = "Verifies published artifacts, excluded projects, and generated Maven dependencies."
}

val verifyJava8Compatibility = tasks.register("verifyJava8Compatibility") {
group = "verification"
description = "Verifies Java 8 API gates and generated JVM bytecode versions."
}

tasks.named("check") {
dependsOn(verifyPublishingModel, verifyJava8Compatibility)
}

subprojects {
val subProject = this
afterEvaluate {
val publishable = subProject.isPublishableModule()
subProject.extensions.extraProperties.set("taboolibPublishable", publishable)
if (publishable) {
subProject.configure<PublishingExtension> { applyToSub(subProject) }
}
}
}

gradle.projectsEvaluated {
val publishableProjects = subprojects.filter {
it.extensions.extraProperties.get("taboolibPublishable") == true
}
val excludedProjects = subprojects - publishableProjects.toSet()

verifyPublishingModel.configure {
dependsOn(publishableProjects.map { project ->
project.tasks.named<GenerateMavenPom>("generatePomFileForMavenPublication")
})
doLast {
publishableProjects.forEach { project ->
val publication = project.extensions.getByType<PublishingExtension>()
.publications.getByName("maven") as MavenPublication
val classifiers = publication.artifacts.map { artifact ->
artifact.classifier?.takeIf(String::isNotBlank) ?: "main"
}.sorted()
check(classifiers == listOf("main", "sources")) {
"${project.path} must publish one main shadow artifact and one sources artifact, got $classifiers"
}
val pomTask = project.tasks.named<GenerateMavenPom>("generatePomFileForMavenPublication").get()
val expectedDependencies = project.apiPomCoordinates().toSet()
val actualDependencies = readPomCoordinates(pomTask.destination)
check(actualDependencies == expectedDependencies) {
"${project.path} POM dependencies differ: expected=$expectedDependencies, actual=$actualDependencies"
}
}
excludedProjects.forEach { project ->
val publications = project.extensions.getByType<PublishingExtension>().publications
check(publications.isEmpty()) { "${project.path} must not create Maven publications" }
}
}
}

val compileTasks = subprojects.flatMap { project ->
project.tasks.withType<JavaCompile>().toList() + project.tasks.withType<KotlinCompile>().toList()
}
val animalSnifferTasks = subprojects.mapNotNull { project ->
project.tasks.findByName("animalsnifferMain")
}
verifyJava8Compatibility.configure {
dependsOn(compileTasks, animalSnifferTasks)
doLast {
subprojects.forEach { project ->
project.tasks.withType<JavaCompile>().forEach { compileTask ->
check(compileTask.options.release.orNull == 8) {
"${compileTask.path} must compile with --release 8"
}
}
project.tasks.withType<KotlinCompile>().forEach { compileTask ->
check(compileTask.kotlinOptions.jvmTarget == "1.8") {
"${compileTask.path} must target JVM 1.8"
}
}
}
val classFiles = subprojects.flatMap { project ->
val classesDirectory = project.layout.buildDirectory.dir("classes").get().asFile
if (classesDirectory.isDirectory) {
classesDirectory.walkTopDown().filter { it.isFile && it.extension == "class" }.toList()
} else {
emptyList()
}
}
check(classFiles.isNotEmpty()) { "No compiled classes found for Java 8 verification" }
val incompatibleClasses = classFiles.mapNotNull { classFile ->
val majorVersion = classFileMajorVersion(classFile)
if (majorVersion == 52) null else "$classFile ($majorVersion)"
}
check(incompatibleClasses.isEmpty()) {
"Non-Java-8 class files found:\n${incompatibleClasses.joinToString("\n")}"
}
}
}
}

fun PublishingExtension.applyToSub(subProject: Project) {
repositories {
Expand All @@ -131,20 +342,26 @@ fun PublishingExtension.applyToSub(subProject: Project) {
}
publications {
create<MavenPublication>("maven") {
// 构件名
artifactId = if (subProject.ext.has("publishId")) subProject.ext.get("publishId").toString() else subProject.name
// 组
artifactId = subProject.publishedArtifactId()
groupId = "io.izzel.taboolib"
// 版本号
version = when {
project.hasProperty("devLocal") -> "${project.version}-local-dev"
project.hasProperty("dev") -> "${project.version}-dev"
else -> "${project.version}"
version = subProject.publishedVersion()
artifact(subProject.tasks.named<Jar>("sourcesJar"))
artifact(subProject.tasks.named<ShadowJar>("shadowJar"))
val apiDependencies = subProject.apiPomCoordinates()
if (apiDependencies.isNotEmpty()) {
pom.withXml {
val dependencies = asNode().appendNode("dependencies")
apiDependencies.forEach { dependency ->
dependencies.appendNode("dependency").apply {
appendNode("groupId", dependency.groupId)
appendNode("artifactId", dependency.artifactId)
appendNode("version", dependency.version)
appendNode("scope", "compile")
}
}
}
}
// 构件
artifact(subProject.tasks["kotlinSourcesJar"])
artifact(subProject.tasks["shadowJar"])
println("> Apply \"$groupId:$artifactId:$version\"")
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,30 +124,38 @@ public static AetherResolver of(@NotNull String repository) {
String id = file.getParentFile().getParentFile().getPath()
+ ":" + PrimitiveSettings.IS_ISOLATED_MODE // 区分类加载器 (隔离类加载器或插件类加载器)
+ ":" + (relocation != null ? relocation.hashCode() : 0); // 区分不同的重定向规则
if (injectedDependencies.contains(id)) return null;
else injectedDependencies.add(id);
// 如果没有重定向规则,直接注入
if (relocation == null || relocation.isEmpty()) {
return ClassAppender.addPath(file.toPath(), PrimitiveSettings.IS_ISOLATED_MODE, isExternal);
} else {
// 获取重定向后的文件
String name = file.getName().substring(0, file.getName().lastIndexOf('.'));
File rel = new File(file.getParentFile(), name + "_r2_" + Math.abs(relocation.hashCode()) + ".jar");
// 如果文件不存在或者文件大小为 0,就执行重定向逻辑
if (!rel.exists() || rel.length() == 0) {
try {
// 获取重定向规则
List<Relocation> rules = relocation.stream().map(JarRelocation::toRelocation).collect(Collectors.toList());
// 获取临时文件
File tempSourceFile = PrimitiveIO.copyFile(file, File.createTempFile(file.getName(), ".jar"));
// 运行
new JarRelocator(tempSourceFile, rel, rules).run();
} catch (IOException e) {
throw new IllegalStateException(String.format("Unable to relocate %s%n", file), e);
if (!injectedDependencies.add(id)) return null;
try {
// 如果没有重定向规则,直接注入
if (relocation == null || relocation.isEmpty()) {
return ClassAppender.addPath(file.toPath(), PrimitiveSettings.IS_ISOLATED_MODE, isExternal);
} else {
// 获取重定向后的文件
String name = file.getName().substring(0, file.getName().lastIndexOf('.'));
File rel = new File(file.getParentFile(), name + "_r2_" + Math.abs(relocation.hashCode()) + ".jar");
// 如果文件不存在或者文件大小为 0,就执行重定向逻辑
if (!rel.exists() || rel.length() == 0) {
File tempSourceFile = File.createTempFile(file.getName(), ".jar");
try {
// 获取重定向规则
List<Relocation> rules = relocation.stream().map(JarRelocation::toRelocation).collect(Collectors.toList());
PrimitiveIO.copyFile(file, tempSourceFile);
new JarRelocator(tempSourceFile, rel, rules).run();
} catch (IOException e) {
throw new IllegalStateException(String.format("Unable to relocate %s%n", file), e);
} finally {
if (!tempSourceFile.delete()) {
tempSourceFile.deleteOnExit();
}
}
}
// 注入重定向后的文件
return ClassAppender.addPath(rel.toPath(), PrimitiveSettings.IS_ISOLATED_MODE, isExternal);
}
// 注入重定向后的文件
return ClassAppender.addPath(rel.toPath(), PrimitiveSettings.IS_ISOLATED_MODE, isExternal);
} catch (Throwable ex) {
// 注入失败后允许后续调用重试,避免失败状态永久污染缓存。
injectedDependencies.remove(id);
throw ex;
}
}
}
11 changes: 6 additions & 5 deletions common-legacy-api/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
dependencies {
compileOnly(project(":common"))
compileOnly(project(":common-env"))
compileOnly(project(":common-platform-api"))
compileOnly(project(":common-util"))
}
compileOnlyApi(project(":common"))
compileOnlyApi(project(":common-env"))
compileOnlyApi(project(":common-platform-api"))
compileOnlyApi(project(":common-util"))
testImplementation(project(":common"))
}
Loading
Loading