Skip to content

Commit 5ee11ba

Browse files
Merge pull request #690 from ArikSquad/feat/dynamic-itemtype
Dynamic ItemType
2 parents 969a6ef + b5e9353 commit 5ee11ba

File tree

89 files changed

+5014
-2028
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+5014
-2028
lines changed

commons/build.gradle.kts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ java {
1515
}
1616

1717
dependencies {
18-
implementation("org.yaml:snakeyaml:2.2")
18+
implementation("org.yaml:snakeyaml:2.5")
1919
implementation(project(":packer"))
2020
implementation("org.mongodb:bson:4.11.2")
2121
implementation("org.tinylog:tinylog-api:2.7.0")
@@ -29,4 +29,49 @@ dependencies {
2929
implementation("redis.clients:jedis:7.2.0")
3030

3131
implementation("de.exlll:configlib-yaml:4.8.1")
32-
}
32+
33+
implementation("org.spongepowered:configurate-yaml:4.2.0")
34+
implementation("com.squareup:javapoet:1.13.0")
35+
}
36+
37+
sourceSets {
38+
val main by getting
39+
40+
val codegen by creating {
41+
java.srcDir("src/codegen/java")
42+
43+
compileClasspath += main.compileClasspath
44+
runtimeClasspath += main.compileClasspath
45+
}
46+
47+
codegen // just here to avoid "unused" warning
48+
}
49+
50+
val generateItemTypes by tasks.registering(JavaExec::class) {
51+
group = "codegen"
52+
description = "Generate ItemType enum from SkyBlock YAML"
53+
54+
classpath = sourceSets["codegen"].runtimeClasspath
55+
mainClass.set("net.swofty.codegen.ItemTypeGenerator")
56+
57+
args(
58+
rootProject.projectDir
59+
.resolve("configuration/skyblock/items")
60+
.absolutePath,
61+
layout.projectDirectory
62+
.dir("src/generated/java")
63+
.asFile
64+
.absolutePath
65+
)
66+
67+
inputs.dir(rootProject.projectDir.resolve("configuration/skyblock/items"))
68+
outputs.dir(layout.projectDirectory.dir("src/generated/java"))
69+
}
70+
71+
sourceSets["main"].java {
72+
srcDir(layout.projectDirectory.dir("src/generated/java"))
73+
}
74+
75+
tasks.compileJava {
76+
dependsOn(generateItemTypes)
77+
}
Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
package net.swofty.codegen;
2+
3+
import com.squareup.javapoet.ClassName;
4+
import com.squareup.javapoet.JavaFile;
5+
import com.squareup.javapoet.MethodSpec;
6+
import com.squareup.javapoet.TypeSpec;
7+
import org.yaml.snakeyaml.Yaml;
8+
9+
import java.io.IOException;
10+
import java.nio.file.Files;
11+
import java.nio.file.Path;
12+
import java.util.*;
13+
import java.util.stream.Stream;
14+
15+
import javax.lang.model.element.Modifier;
16+
17+
public class ItemTypeGenerator {
18+
static void main(String[] args) throws Exception {
19+
if (args.length < 2) {
20+
throw new IllegalArgumentException("Expected args: <inputDir> <outputDir>");
21+
}
22+
23+
Path inputDir = Path.of(args[0]);
24+
Path outputDir = Path.of(args[1]);
25+
26+
Map<String, ItemYaml> items = new TreeMap<>();
27+
28+
for (Path file : findYamlFiles(inputDir)) {
29+
for (ItemYaml item : loadItems(file)) {
30+
if (item.id() == null || item.id().isBlank()) continue;
31+
items.put(item.id(), item);
32+
}
33+
}
34+
35+
generateEnum(items.values(), outputDir);
36+
}
37+
38+
static List<Path> findYamlFiles(Path root) throws IOException {
39+
if (!Files.exists(root)) return List.of();
40+
try (Stream<Path> stream = Files.walk(root)) {
41+
return stream
42+
.filter(p -> p.toString().endsWith(".yml") || p.toString().endsWith(".yaml"))
43+
.toList();
44+
}
45+
}
46+
47+
static List<ItemYaml> loadItems(Path file) throws IOException {
48+
Yaml yaml = new Yaml();
49+
Map<String, Object> root = yaml.load(Files.newInputStream(file));
50+
if (root == null) return List.of();
51+
52+
Object rawItems = root.get("items");
53+
if (!(rawItems instanceof List<?> list)) return List.of();
54+
55+
List<ItemYaml> result = new ArrayList<>();
56+
for (Object entry : list) {
57+
if (!(entry instanceof Map<?, ?> item)) continue;
58+
Object id = item.get("id");
59+
Object rarity = item.get("rarity");
60+
Object material = item.get("material");
61+
if (!(id instanceof String)) continue;
62+
result.add(new ItemYaml(
63+
(String) id,
64+
material instanceof String ? (String) material : "BARRIER",
65+
rarity instanceof String ? (String) rarity : null
66+
));
67+
}
68+
return result;
69+
}
70+
71+
static void generateEnum(
72+
Collection<ItemYaml> items,
73+
Path outputDir
74+
) throws IOException {
75+
76+
ClassName material = ClassName.get("net.minestom.server.item", "Material");
77+
ClassName rarity = ClassName.get("net.swofty.commons.skyblock.item", "Rarity");
78+
ClassName nullable = ClassName.get("org.jetbrains.annotations", "Nullable");
79+
80+
TypeSpec.Builder enumBuilder = TypeSpec.enumBuilder("ItemType")
81+
.addModifiers(Modifier.PUBLIC);
82+
83+
for (ItemYaml item : items) {
84+
String enumName = toEnumConstantName(item.id());
85+
String rarityExpr = resolveRarity(item);
86+
87+
enumBuilder.addEnumConstant(
88+
enumName,
89+
TypeSpec.anonymousClassBuilder(
90+
"$T.$L, $T.$L",
91+
material,
92+
item.material().toUpperCase(),
93+
rarity,
94+
rarityExpr
95+
).build()
96+
);
97+
}
98+
99+
// Fields
100+
enumBuilder.addField(material, "material",
101+
Modifier.PUBLIC, Modifier.FINAL);
102+
enumBuilder.addField(rarity, "rarity",
103+
Modifier.PUBLIC, Modifier.FINAL);
104+
105+
// Constructor
106+
enumBuilder.addMethod(MethodSpec.constructorBuilder()
107+
.addParameter(material, "material")
108+
.addParameter(rarity, "rarity")
109+
.addStatement("this.material = material")
110+
.addStatement("this.rarity = rarity")
111+
.build()
112+
);
113+
114+
// get(String)
115+
enumBuilder.addMethod(MethodSpec.methodBuilder("get")
116+
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
117+
.addAnnotation(nullable)
118+
.returns(ClassName.bestGuess("ItemType"))
119+
.addParameter(String.class, "name")
120+
.beginControlFlow("try")
121+
.addStatement(
122+
"return ItemType.valueOf(name.replace($S, $S).toUpperCase())",
123+
"minecraft:", ""
124+
)
125+
.nextControlFlow("catch ($T e)", Exception.class)
126+
.addStatement("return null")
127+
.endControlFlow()
128+
.build()
129+
);
130+
131+
enumBuilder.addMethod(MethodSpec.methodBuilder("isVanillaReplaced")
132+
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
133+
.returns(boolean.class)
134+
.addParameter(String.class, "item")
135+
.addStatement("return get(item) != null")
136+
.build()
137+
);
138+
139+
enumBuilder.addMethod(
140+
MethodSpec.methodBuilder("fromMaterial")
141+
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
142+
.addAnnotation(nullable)
143+
.returns(ClassName.bestGuess("ItemType"))
144+
.addParameter(material, "material")
145+
.addStatement(
146+
"String materialName = material.key().value()"
147+
)
148+
.addStatement(
149+
"String formattedItemName = $T.toNormalCase(materialName)",
150+
ClassName.get("net.swofty.commons", "StringUtility")
151+
)
152+
.beginControlFlow("for (ItemType itemType : ItemType.values())")
153+
.beginControlFlow(
154+
"if (itemType.material == material && formattedItemName.equals($T.toNormalCase(itemType.getDisplayName())))",
155+
ClassName.get("net.swofty.commons", "StringUtility")
156+
)
157+
.addStatement("return itemType")
158+
.endControlFlow()
159+
.endControlFlow()
160+
.addStatement("return null")
161+
.build()
162+
);
163+
164+
enumBuilder.addMethod(
165+
MethodSpec.methodBuilder("getDisplayName")
166+
.addModifiers(Modifier.PUBLIC)
167+
.returns(String.class)
168+
.addStatement(
169+
"return $T.toNormalCase(this.name())",
170+
ClassName.get("net.swofty.commons", "StringUtility")
171+
)
172+
.build()
173+
);
174+
175+
Files.createDirectories(outputDir);
176+
JavaFile.builder("net.swofty.commons.skyblock.item", enumBuilder.build())
177+
.addFileComment("AUTO-GENERATED FILE. DO NOT EDIT.")
178+
.build()
179+
.writeTo(outputDir);
180+
}
181+
182+
private static String resolveRarity(ItemYaml item) {
183+
String rarityString = item.rarity();
184+
if (rarityString == null || rarityString.isBlank()) return "COMMON";
185+
return rarityString.trim().toUpperCase(Locale.ROOT);
186+
}
187+
188+
private static String toEnumConstantName(String id) {
189+
if (id == null) return "UNKNOWN";
190+
String name = id;
191+
int idx = name.indexOf(':');
192+
if (idx >= 0) name = name.substring(idx + 1);
193+
name = name.trim().toUpperCase(Locale.ROOT);
194+
name = name.replace('-', '_');
195+
name = name.replaceAll("[^A-Z0-9_]", "_");
196+
if (name.isEmpty()) name = "UNKNOWN";
197+
if (Character.isDigit(name.charAt(0))) name = "_" + name;
198+
return name;
199+
}
200+
201+
private record ItemYaml(String id, String material, String rarity) {
202+
}
203+
}

0 commit comments

Comments
 (0)