Skip to content

Commit 6ab5b6d

Browse files
committed
Add asynchronous in-plugin YSM migration
Bundle the migration pipeline and MIT JNI parser so operators can convert YSM models off the Paper/Folia main thread and receive ModelEngine, MythicMobs, and Molang-preserving outputs directly.
1 parent 814dbe5 commit 6ab5b6d

16 files changed

Lines changed: 2516 additions & 19 deletions

THIRD_PARTY_NOTICES

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,16 @@ Molang compiler
55
- License: MIT
66
- Project: Ocelot5836/molang-compiler
77

8+
Gson
9+
- Artifact: com.google.code.gson:gson:2.10.1
10+
- License: Apache License 2.0
11+
- Project: google/gson
12+
13+
YSMParser JNI
14+
- Component: native/YSMParserJNI.dll
15+
- License: MIT
16+
- Project: OpenYSM/YSMParser
17+
- The bundled binary is used only by the asynchronous migration worker.
18+
819
ModelEngine and Paper APIs are compile-time/runtime dependencies supplied by
920
those projects and are not bundled into the plugin JAR.

build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ dependencies {
2121
}
2222

2323
implementation("gg.moonflower:molang-compiler:3.1.1.19")
24+
implementation("com.google.code.gson:gson:2.10.1")
2425

2526
testImplementation("org.junit.jupiter:junit-jupiter:5.12.2")
2627
testRuntimeOnly("org.junit.platform:junit-platform-launcher")

src/main/java/com/ysm/converter/BbModel.java

Lines changed: 575 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package com.ysm.converter;
2+
3+
import com.google.gson.JsonArray;
4+
import com.google.gson.JsonElement;
5+
import com.google.gson.JsonObject;
6+
import com.google.gson.JsonParser;
7+
8+
import java.io.IOException;
9+
import java.nio.charset.StandardCharsets;
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
12+
import java.nio.file.StandardCopyOption;
13+
14+
/**
15+
* Post-processes a Blockbench .bbmodel for ModelEngine compatibility.
16+
*
17+
* <p>Actions performed:
18+
* <ul>
19+
* <li>Rename bones that start with "hit_" → ModelEngine hitbox bone</li>
20+
* <li>Copy textures to the model's texture folder</li>
21+
* <li>Strip non-ModelEngine animation controllers</li>
22+
* <li>Write a basic ModelEngine model configuration</li>
23+
* </ul>
24+
*/
25+
public final class BlockbenchToModelEngine {
26+
27+
private BlockbenchToModelEngine() {}
28+
29+
public static void convert(Path bbmodelPath, Path outputDir) throws IOException {
30+
Files.createDirectories(outputDir);
31+
32+
String raw = Files.readString(bbmodelPath, StandardCharsets.UTF_8);
33+
JsonObject model = JsonParser.parseString(raw).getAsJsonObject();
34+
35+
// Copy the processed .bbmodel alongside
36+
Path destBbmodel = outputDir.resolve(bbmodelPath.getFileName());
37+
Files.copy(bbmodelPath, destBbmodel, StandardCopyOption.REPLACE_EXISTING);
38+
39+
// Flag hitbox bones
40+
if (model.has("outliner")) {
41+
flagModelEngineBones(model.getAsJsonArray("outliner"));
42+
}
43+
44+
// Write the augmented .bbmodel back
45+
Files.writeString(destBbmodel, model.toString(), StandardCharsets.UTF_8);
46+
47+
// Write a skeleton ModelEngine model.yml
48+
String modelName = bbmodelPath.getFileName().toString().replace(".bbmodel", "");
49+
writeModelEngineConfig(outputDir, modelName);
50+
}
51+
52+
private static void flagModelEngineBones(JsonArray outliner) {
53+
for (JsonElement el : outliner) {
54+
if (!el.isJsonObject()) continue;
55+
JsonObject group = el.getAsJsonObject();
56+
String name = group.has("name") ? group.get("name").getAsString() : "";
57+
if (name.toLowerCase().startsWith("hit_")) {
58+
group.addProperty("model_engine_hitbox", true);
59+
}
60+
if (name.equalsIgnoreCase("mount") || name.equalsIgnoreCase("seat")) {
61+
group.addProperty("model_engine_seat", true);
62+
}
63+
if (group.has("children")) {
64+
flagModelEngineBones(group.getAsJsonArray("children"));
65+
}
66+
}
67+
}
68+
69+
private static void writeModelEngineConfig(Path outputDir, String modelName) throws IOException {
70+
String yml = """
71+
# ModelEngine model configuration for %s
72+
model:
73+
id: %s
74+
type: GENERIC
75+
scale: 1.0
76+
# Hitbox, seat, and nametag bones are auto-detected from .bbmodel.
77+
# Adjust mountHeight and other settings as needed.
78+
""".formatted(modelName, modelName);
79+
80+
Files.writeString(outputDir.resolve("model.yml"), yml, StandardCharsets.UTF_8);
81+
}
82+
}

0 commit comments

Comments
 (0)