Skip to content
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
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
9 changes: 8 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,11 @@ run/
logs
kbc.yml
plugins
permissions.json
permissions.json

# AI Tools
.claude/
.spec-workflow/
.fastRequest/
AGENTS.md
CLAUDE.md
23 changes: 16 additions & 7 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import java.util.*
plugins {
`java-library`
`maven-publish`
id("com.gorylenko.gradle-git-properties") version "2.4.2"
id("com.gorylenko.gradle-git-properties") version "2.5.3"
id("com.gradleup.shadow") version "9.0.0-beta4"
id("publish-conventions")
}
Expand All @@ -25,7 +25,7 @@ dependencies {
shadow(dep)
api(dep)
}
shadowApi(libs.com.github.snwcreations.jkook)
shadowApi(libs.io.github.snwcreations.jkook)
shadowApi(libs.com.github.snwcreations.terminalconsoleappender)
shadowApi(libs.uk.org.lidalia.sysout.over.slf4j)
shadowApi(libs.org.apache.logging.log4j.log4j.core)
Expand All @@ -38,17 +38,21 @@ dependencies {
shadowApi(libs.net.kyori.event.method)
shadowApi(libs.net.freeutils.jlhttp)
shadowApi(libs.com.google.code.gson.gson)
Comment thread
huanmeng-qwq marked this conversation as resolved.
shadow("com.fasterxml.jackson.core:jackson-core:2.17.2"); api("com.fasterxml.jackson.core:jackson-core:2.17.2")
shadow("com.fasterxml.jackson.core:jackson-databind:2.17.2"); api("com.fasterxml.jackson.core:jackson-databind:2.17.2")
shadow("com.fasterxml.jackson.core:jackson-annotations:2.17.2"); api("com.fasterxml.jackson.core:jackson-annotations:2.17.2")
shadow("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2"); api("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2")
shadowApi(libs.com.github.ben.manes.caffeine.caffeine)
shadowApi(libs.net.fabricmc.sponge.mixin)
shadowApi(libs.dev.rollczi.litecommands.framework)
shadowApi(libs.net.bytebuddy.byte.buddy.agent)
compileOnly(libs.org.jetbrains.annotations)
}
group = "io.github.snwcreations"
version = "0.32.2"
version = "0.33.0"
description = "KookBC"
java.sourceCompatibility = JavaVersion.VERSION_1_8
java.targetCompatibility = JavaVersion.VERSION_1_8
java.sourceCompatibility = JavaVersion.VERSION_21
java.targetCompatibility = JavaVersion.VERSION_21

tasks.compileJava {
options.encoding = "UTF-8"
Expand All @@ -71,6 +75,7 @@ gitProperties {
val skipShade = properties["skipShade"] == "true"
tasks.shadowJar {
enabled = !skipShade
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
archiveClassifier = ""
transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer())
exclude(
Expand All @@ -81,9 +86,13 @@ tasks.shadowJar {
)
}

tasks.compileJava {
options.encoding = "UTF-8"
}

tasks.processResources {
filesMatching("*.json") {
expand(properties + mapOf("jkookVersion" to libs.versions.com.github.snwcreations.jkook.get()))
expand(properties + mapOf("jkookVersion" to libs.versions.io.github.snwcreations.jkook.get()))
}
}

Expand All @@ -99,7 +108,7 @@ tasks.jar {
mapOf(
"Build-Time" to Date(),
"Specification-Title" to "JKook",
"Specification-Version" to libs.com.github.snwcreations.jkook.get().version,
"Specification-Version" to libs.io.github.snwcreations.jkook.get().version,
"Specification-Vendor" to "SNWCreations",
"Implementation-Title" to "KookBC",
"Implementation-Version" to version.toString(),
Expand Down
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/publish-conventions.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ indra {
gpl3OnlyLicense()

javaVersions {
target(8)
minimumToolchain(17)
target(21)
minimumToolchain(21)
}

configurePublications {
Expand Down
28 changes: 24 additions & 4 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[versions]
com-github-ben-manes-caffeine-caffeine = "2.9.3"
com-github-snwcreations-jkook = "0.54.1"
com-github-snwcreations-terminalconsoleappender = "1.3.5"
com-google-code-gson-gson = "2.10.1"
io-github-snwcreations-jkook = "0.54.2"
com-github-snwcreations-terminalconsoleappender = "1.3.5"
com-squareup-okhttp3-okhttp = "4.10.0"
dev-rollczi-litecommands-framework = "3.9.5"
net-bytebuddy-byte-buddy = "1.12.10"
Expand All @@ -18,12 +18,19 @@ org-fusesource-jansi-jansi = "2.4.0"
org-jetbrains-annotations = "23.1.0"
org-jline-jline-terminal-jansi = "3.21.0"
uk-org-lidalia-sysout-over-slf4j = "1.0.2"
# Test Dependencies
junit = "5.9.3"
mockito = "4.11.0"
wiremock = "2.27.2"
testcontainers = "1.17.6"
assertj = "3.24.2"
mockwebserver = "4.10.0"

[libraries]
com-github-ben-manes-caffeine-caffeine = { module = "com.github.ben-manes.caffeine:caffeine", version.ref = "com-github-ben-manes-caffeine-caffeine" }
com-github-snwcreations-jkook = { module = "com.github.SNWCreations:JKook", version.ref = "com-github-snwcreations-jkook" }
com-github-snwcreations-terminalconsoleappender = { module = "com.github.SNWCreations:TerminalConsoleAppender", version.ref = "com-github-snwcreations-terminalconsoleappender" }
com-google-code-gson-gson = { module = "com.google.code.gson:gson", version.ref = "com-google-code-gson-gson" }
io-github-snwcreations-jkook = { module = "io.github.snwcreations:jkook", version.ref = "io-github-snwcreations-jkook" }
com-github-snwcreations-terminalconsoleappender = { module = "com.github.SNWCreations:TerminalConsoleAppender", version.ref = "com-github-snwcreations-terminalconsoleappender" }
com-squareup-okhttp3-okhttp = { module = "com.squareup.okhttp3:okhttp", version.ref = "com-squareup-okhttp3-okhttp" }
dev-rollczi-litecommands-framework = { module = "dev.rollczi:litecommands-framework", version.ref = "dev-rollczi-litecommands-framework" }
net-bytebuddy-byte-buddy = { module = "net.bytebuddy:byte-buddy", version.ref = "net-bytebuddy-byte-buddy" }
Expand All @@ -39,3 +46,16 @@ org-fusesource-jansi-jansi = { module = "org.fusesource.jansi:jansi", version.re
org-jetbrains-annotations = { module = "org.jetbrains:annotations", version.ref = "org-jetbrains-annotations" }
org-jline-jline-terminal-jansi = { module = "org.jline:jline-terminal-jansi", version.ref = "org-jline-jline-terminal-jansi" }
uk-org-lidalia-sysout-over-slf4j = { module = "uk.org.lidalia:sysout-over-slf4j", version.ref = "uk-org-lidalia-sysout-over-slf4j" }
# Test Libraries
junit_jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
junit_jupiter_engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit" }
junit_jupiter_params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit" }
mockito_core = { module = "org.mockito:mockito-core", version.ref = "mockito" }
mockito_junit_jupiter = { module = "org.mockito:mockito-junit-jupiter", version.ref = "mockito" }
mockito_inline = { module = "org.mockito:mockito-inline", version.ref = "mockito" }
wiremock_jre8 = { module = "com.github.tomakehurst:wiremock-jre8", version.ref = "wiremock" }
testcontainers_junit_jupiter = { module = "org.testcontainers:junit-jupiter", version.ref = "testcontainers" }
testcontainers_core = { module = "org.testcontainers:testcontainers", version.ref = "testcontainers" }
assertj_core = { module = "org.assertj:assertj-core", version.ref = "assertj" }
mockwebserver = { module = "com.squareup.okhttp3:mockwebserver", version.ref = "mockwebserver" }

2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/snw/kookbc/CLIOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public final class CLIOptions {
static {
NO_BUCKET = Boolean.getBoolean("kookbc.nobucket");
if (NO_BUCKET) {
logger.warn("You've used kookbc.nobucket option, we won't check if you're going to be out of rate limit!");
logger.warn("您已使用 kookbc.nobucket 选项,我们将不会检查是否会超出速率限制!");

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"您已使用" 建议改为 "您已启用"

}
}

Expand Down
53 changes: 30 additions & 23 deletions src/main/java/snw/kookbc/LaunchMain.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
/*
* License: https://github.com/Mojang/LegacyLauncher
*/

package snw.kookbc;

import static snw.kookbc.util.VirtualThreadUtil.startVirtualThread;

import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
Expand Down Expand Up @@ -40,25 +43,31 @@ public static void main(String[] args) {
ClassLoader appClassLoader = LaunchMain.class.getClassLoader();
Class<?> mixinClass = Class.forName("org.spongepowered.asm.util.JavaVersion");
if (mixinClass.getClassLoader() != appClassLoader) {
System.out.println("[KookBC/WARN] Mixin support is already enabled!");
System.out.println("[KookBC/WARN] If you're sure you don't need Mixin support, visit the following link:");
System.out.println("[KookBC/WARN] Mixin 支持已启用!");
System.out.println("[KookBC/WARN] 如果您确定不需要 Mixin 支持,请访问以下链接:");
System.out.println("[KookBC/WARN] https://github.com/SNWCreations/KookBC/blob/main/docs/KookBC_CommandLine.md#%E5%90%AF%E5%8A%A8%E5%85%A5%E5%8F%A3");
// Never part, never give up!
classLoader = new LaunchClassLoader(getUrls(appClassLoader).toArray(new URL[0]));
AccessClassLoader loader = AccessClassLoader.of(classLoader);
MixinPluginManager.instance().loadFolder(loader, new File("plugins"));
String[] finalArgs = args;
Thread thread = new Thread(() -> {
Thread thread = startVirtualThread(() -> {
try {
Class<?> mainClass = Class.forName(LaunchMainTweaker.CLASS_NAME);
MethodHandles.lookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class))
.invoke((Object) finalArgs);
} catch (Throwable e) {
throw new RuntimeException(e);
}
});
}, "Mixin-Launch-Thread");
thread.setContextClassLoader(PluginClassLoaderDelegate.INSTANCE);
thread.start();

// 等待虚拟线程完成
try {
thread.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return;
}
} catch (ClassNotFoundException ignored) {
Expand All @@ -76,14 +85,6 @@ public static void main(String[] args) {
}
args = argsList.toArray(new String[0]);
Thread.currentThread().setName(MAIN_THREAD_NAME);
// Actually here should not be warning, but the logging level of the LaunchWrapper is WARN.
// Also, I think this message can let the user know they are running KookBC under Launch mode.
LogWrapper.LOGGER.warn("Launching KookBC with Mixin support");
LogWrapper.LOGGER.warn("The author of Mixin support: huanmeng_qwq@Github"); // thank you! --- SNWCreations
LogWrapper.LOGGER.warn("Tips: You can safely ignore this.");
LogWrapper.LOGGER.warn("But if you're really sure you don't need Mixin support, visit the following link:");
LogWrapper.LOGGER.warn("https://github.com/SNWCreations/KookBC/blob/main/docs/KookBC_CommandLine.md");
LogWrapper.LOGGER.warn("The documentation will tell you how can you launch KookBC without Mixin support.");
launch.launch(args);
}

Expand Down Expand Up @@ -138,7 +139,7 @@ private void launch(String[] args) {
final OptionParser parser = new OptionParser();
parser.allowsUnrecognizedOptions();

final OptionSpec<String> tweakClassOption = parser.accepts("tweakClass", "Tweak class(es) to load").withRequiredArg().defaultsTo(MIXIN_TWEAK, DEFAULT_TWEAK);
final OptionSpec<String> tweakClassOption = parser.accepts("tweakClass", "要加载的调整类").withRequiredArg().defaultsTo(MIXIN_TWEAK, DEFAULT_TWEAK);
final OptionSpec<String> nonOption = parser.nonOptions();

final OptionSet options = parser.parse(args);
Expand Down Expand Up @@ -175,14 +176,14 @@ private void launch(String[] args) {
final String tweakName = it.next();
// Safety check - don't reprocess something we've already visited
if (allTweakerNames.contains(tweakName)) {
LogWrapper.LOGGER.warn("Tweak class name {} has already been visited -- skipping", tweakName);
LogWrapper.LOGGER.warn("调整类名 {} 已经被访问过 -- 跳过", tweakName);
// remove the tweaker from the stack otherwise it will create an infinite loop
it.remove();
continue;
} else {
allTweakerNames.add(tweakName);
}
LogWrapper.LOGGER.info("Loading tweak class name {}", tweakName);
LogWrapper.LOGGER.info("正在加载调整类 {}", tweakName);

// Ensure we allow the tweak class to load with the parent classloader
classLoader.addClassLoaderExclusion(tweakName.substring(0, tweakName.lastIndexOf('.')));
Expand All @@ -193,15 +194,15 @@ private void launch(String[] args) {
it.remove();
// If we haven't visited a tweaker yet, the first will become the 'primary' tweaker
if (primaryTweaker == null) {
LogWrapper.LOGGER.info("Using primary tweak class name {}", tweakName);
LogWrapper.LOGGER.info("使用主要调整类 {}", tweakName);
primaryTweaker = tweaker;
}
}

// Now, iterate all the tweakers we just instantiated
for (final Iterator<ITweaker> it = tweakers.iterator(); it.hasNext(); ) {
final ITweaker tweaker = it.next();
LogWrapper.LOGGER.info("Calling tweak class {}", tweaker.getClass().getName());
LogWrapper.LOGGER.info("调用调整类 {}", tweaker.getClass().getName());
tweaker.acceptOptions(options.valuesOf(nonOption));
tweaker.injectIntoClassLoader(classLoader);
allTweakers.add(tweaker);
Expand All @@ -221,7 +222,7 @@ private void launch(String[] args) {
}

if (primaryTweaker == null) {
throw new NullPointerException("Tweaker not found");
throw new NullPointerException("未找到调整器");
}

// Finally, we turn to the primary tweaker, and let it tell us where to go to launch
Expand All @@ -231,19 +232,25 @@ private void launch(String[] args) {
if (launchTarget != null && !launchTarget.isEmpty()) {
final Class<?> clazz = Class.forName(launchTarget, false, classLoader);
MethodHandle mainMethodHandle = MethodHandles.lookup().findStatic(clazz, "main", MethodType.methodType(void.class, String[].class));
Thread main = new Thread(() -> {
Thread main = startVirtualThread(() -> {
try {
mainMethodHandle.invoke((Object) argumentList.toArray(new String[0]));
} catch (Throwable e) {
e.printStackTrace();
}
}, clazz.getSimpleName());
}, clazz.getSimpleName() + "-Main-Thread");
main.setContextClassLoader(PluginClassLoaderDelegate.INSTANCE);
main.start();

// 等待虚拟线程完成
try {
main.join();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
} catch (Exception e) {
LogWrapper.LOGGER.error("Unable to launch", e);
LogWrapper.LOGGER.error("无法启动", e);
System.exit(1);
}
}
Expand Down
Loading
Loading