mirror of
https://github.com/Anuken/Mindustry.git
synced 2026-10-01 18:50:27 +03:00
Schema cleanup
This commit is contained in:
+1
-1
@@ -181,7 +181,7 @@ tasks.register('updateScripts', JavaExec){
|
||||
mainClass = "mindustry.tools.ScriptMainGenerator"
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
standardInput = System.in
|
||||
workingDir = "../"
|
||||
workingDir = "../core/assets"
|
||||
}
|
||||
|
||||
tasks.register('fixMaps', JavaExec){
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
package mindustry.tools;
|
||||
|
||||
import arc.*;
|
||||
import arc.backend.headless.*;
|
||||
import arc.files.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.editor.*;
|
||||
import mindustry.net.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class HeadlessSetup{
|
||||
|
||||
public static void setup(){
|
||||
ApplicationCore core = new ApplicationCore(){
|
||||
@Override
|
||||
public void setup(){
|
||||
Core.settings.setDataDirectory(new Fi("../../tools/build/test_data"));
|
||||
Core.bundle = I18NBundle.createBundle(Core.files.internal("bundles/bundle"), Locale.ENGLISH);
|
||||
headless = true;
|
||||
net = new Net(null);
|
||||
tree = new FileTree();
|
||||
Vars.init();
|
||||
world = new World();
|
||||
content.createBaseContent();
|
||||
mods.loadScripts();
|
||||
content.createModContent();
|
||||
|
||||
add(logic = new Logic());
|
||||
add(netServer = new NetServer());
|
||||
|
||||
content.init();
|
||||
editor = new MapEditor();
|
||||
}
|
||||
};
|
||||
|
||||
new HeadlessApplication(core){
|
||||
@Override
|
||||
protected void initialize(){
|
||||
//don't create a thread, just init on the main thread
|
||||
for(ApplicationListener listener : listeners){
|
||||
listener.init();
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,17 @@
|
||||
package mindustry.tools;
|
||||
|
||||
import arc.*;
|
||||
import arc.backend.headless.*;
|
||||
import arc.files.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.core.*;
|
||||
import mindustry.editor.*;
|
||||
import mindustry.game.MapObjectives.*;
|
||||
import mindustry.io.*;
|
||||
import mindustry.logic.LExecutor.*;
|
||||
import mindustry.maps.Map;
|
||||
import mindustry.maps.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.blocks.logic.LogicBlock.*;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class MapFixer{
|
||||
@@ -32,36 +24,8 @@ public class MapFixer{
|
||||
.findAll(f -> f.extEquals("msav"))
|
||||
.map(f -> f.path().replace(".msav", "").replace("maps/", "")).toArray(String.class));
|
||||
|
||||
ApplicationCore core = new ApplicationCore(){
|
||||
@Override
|
||||
public void setup(){
|
||||
Core.settings.setDataDirectory(new Fi("../../tools/build/test_data"));
|
||||
Core.bundle = I18NBundle.createBundle(Core.files.internal("bundles/bundle"), Locale.ENGLISH);
|
||||
headless = true;
|
||||
net = new Net(null);
|
||||
tree = new FileTree();
|
||||
Vars.init();
|
||||
world = new World();
|
||||
content.createBaseContent();
|
||||
mods.loadScripts();
|
||||
content.createModContent();
|
||||
|
||||
add(logic = new Logic());
|
||||
add(netServer = new NetServer());
|
||||
|
||||
content.init();
|
||||
editor = new MapEditor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(){
|
||||
super.init();
|
||||
|
||||
fixMapNames();
|
||||
}
|
||||
};
|
||||
|
||||
new HeadlessApplication(core);
|
||||
HeadlessSetup.setup();
|
||||
fixMapNames();
|
||||
}
|
||||
|
||||
static void fixMapNames(){
|
||||
|
||||
@@ -2,12 +2,17 @@ package mindustry.tools;
|
||||
|
||||
import arc.files.*;
|
||||
import arc.func.*;
|
||||
import arc.graphics.*;
|
||||
import arc.math.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.serialization.*;
|
||||
import arc.util.serialization.Jval.*;
|
||||
import com.github.javaparser.*;
|
||||
import com.github.javaparser.ast.body.*;
|
||||
import mindustry.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
@@ -15,17 +20,37 @@ import mindustry.world.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class SchemaGenerator{
|
||||
static ObjectMap<String, Fi> classNameToFile = new ObjectMap<>();
|
||||
static JavaParser parser = new JavaParser();
|
||||
static ObjectMap<Class, TypeDeclaration<?>> decls = new ObjectMap<>();
|
||||
static ObjectMap<String, Fi> classNameToFile = new ObjectMap<>();
|
||||
static ObjectMap<Class<?>, TypeDeclaration<?>> decls = new ObjectMap<>();
|
||||
static ObjectMap<Class<?>, Seq<Cons<Jval>>> customInjectors = new ObjectMap<>();
|
||||
static ObjectSet<Class<?>> generatedEnums = new ObjectSet<>();
|
||||
static Fi outputDir = new Fi("../../build/schemas/");
|
||||
|
||||
static{
|
||||
registerBuiltinSchemas();
|
||||
outputDir.mkdirs();
|
||||
}
|
||||
|
||||
public static void writeDefaultContent(){
|
||||
HeadlessSetup.setup();
|
||||
var root = Jval.newObject();
|
||||
var mappings = Jval.newObject();
|
||||
for(ContentType type : ContentType.all){
|
||||
var all = Vars.content.getBy(type);
|
||||
if(type.contentClass != null && all.size > 0 && all.first() instanceof UnlockableContent){
|
||||
mappings.put(type.name(), type.contentClass.getCanonicalName());
|
||||
var arr = Jval.newArray();
|
||||
all.<UnlockableContent>as().each(c -> arr.asArray().add(Jval.valueOf(c.name)));
|
||||
root.asObject().put(type.name(), arr);
|
||||
}
|
||||
}
|
||||
root.put("mappings", mappings);
|
||||
outputDir.child("allContent.json").writeString(root.toString(Jformat.formatted));
|
||||
}
|
||||
|
||||
//called from ScriptMainGenerator
|
||||
public static void writeSchema(Class<?> type) throws Exception{
|
||||
public static void writeSchema(Class<?> type){
|
||||
if(Building.class.isAssignableFrom(type) || type.getSuperclass() == null) return;
|
||||
|
||||
Jval val = Jval.newObject();
|
||||
@@ -49,6 +74,10 @@ public class SchemaGenerator{
|
||||
|
||||
if(field.isAnnotationPresent(Nullable.class)) inner.put("nullable", true);
|
||||
|
||||
if(field.getType().isEnum()){
|
||||
writeEnumSchema(field.getType());
|
||||
}
|
||||
|
||||
var root = getTypeDecl(field.getDeclaringClass());
|
||||
if(root != null) root.getFieldByName(field.getName()).ifPresent(fdec -> {
|
||||
String[] docAndDefault = determineJavadocAndDefault(field, fdec, fdec.getVariables().getFirst().orElseThrow());
|
||||
@@ -64,8 +93,28 @@ public class SchemaGenerator{
|
||||
injector.get(val);
|
||||
}
|
||||
|
||||
Fi dir = new Fi("build/schemas/" + type.getCanonicalName() + ".json");
|
||||
dir.writeString(val.toString(Jformat.formatted));
|
||||
outputDir.child(type.getCanonicalName() + ".json").writeString(val.toString(Jformat.formatted));
|
||||
}
|
||||
|
||||
//writes a schema for an enum type the first time it's encountered as a field value; subsequent calls are no-ops
|
||||
private static void writeEnumSchema(Class<?> enumType){
|
||||
if(!generatedEnums.add(enumType)) return;
|
||||
|
||||
Jval val = Jval.newObject();
|
||||
val.put("superclass", "Enum"); //TODO: should this be java.lang.Enum?
|
||||
|
||||
var typeDec = getTypeDecl(enumType);
|
||||
if(typeDec != null && typeDec.getJavadoc().isPresent()){
|
||||
val.put("doc", typeDec.getJavadoc().get().toText());
|
||||
}
|
||||
|
||||
Jval values = Jval.newArray();
|
||||
for(var constant : enumType.getEnumConstants()){
|
||||
values.add(((Enum<?>)constant).name());
|
||||
}
|
||||
val.put("values", values);
|
||||
|
||||
outputDir.child(enumType.getCanonicalName() + ".json").writeString(val.toString(Jformat.formatted));
|
||||
}
|
||||
|
||||
//registers an injector adding/overwriting fields on type's generated schema, for JSON keys with no real backing field
|
||||
@@ -79,16 +128,259 @@ public class SchemaGenerator{
|
||||
}
|
||||
|
||||
//writes a schema for a type with no backing Java class at all
|
||||
public static void writeFakeSchema(String name, String val){
|
||||
Fi file = new Fi("build/schemas/" + name + ".json");
|
||||
public static void writeSchema(String name, String val){
|
||||
Fi file = outputDir.child(name + ".json");
|
||||
file.writeString(val);
|
||||
}
|
||||
|
||||
static void writePartSchema(String name, String val){
|
||||
Jval base = Jval.read(val);
|
||||
base.add("ops", field("Seq<mindustry.entities.part.DrawPart$PartProgress>", "Consecutive operations."));
|
||||
|
||||
writeSchema(name, base.toString(Jformat.formatted));
|
||||
}
|
||||
|
||||
static void finalizeSchemas(Seq<Class<?>> allClasses){
|
||||
writeSchema("TemplateUnitType", """
|
||||
{
|
||||
"doc": "Template for unit types.",
|
||||
"superclass": "Enum",
|
||||
"values": [%TYPES%]
|
||||
}
|
||||
""".replace("%TYPES%", allClasses.select(UnitType.class::isAssignableFrom).toString(", ", t -> "\"" + t.getSimpleName() + "\"")));
|
||||
|
||||
writePartSchema("mindustry.entities.part.DrawPart$PartProgress", """
|
||||
{
|
||||
"doc": "Base class for progress functions used to animate part transforms. The concrete operation is chosen by 'type' (see PartProgress's static methods for the full list: inv, slope, clamp, delay, sustain, shorten, compress, add, blend, mul, min, sin, absin, mod, loop, curve)."
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("reload", """
|
||||
{
|
||||
"doc": "Reload of the weapon - 1 right after shooting, 0 when ready to fire.",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("smoothReload", """
|
||||
{
|
||||
"doc": "Reload, but smoothed out, so there is no sudden jump between 0-1.",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("warmup", """
|
||||
{
|
||||
"doc": "Weapon warmup, 0 when not firing, 1 when actively shooting. Not equivalent to heat.",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("charge", """
|
||||
{
|
||||
"doc": "Weapon charge, 0 when beginning to charge, 1 when finished.",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("recoil", """
|
||||
{
|
||||
"doc": "Weapon recoil with no curve applied.",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("heat", """
|
||||
{
|
||||
"doc": "Weapon heat, 1 when just fired, 0 when it has cooled down (duration depends on weapon).",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("life", """
|
||||
{
|
||||
"doc": "Lifetime fraction, 0 to 1. Only for missiles.",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("time", """
|
||||
{
|
||||
"doc": "Current unscaled value of Time.time.",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("inv", """
|
||||
{
|
||||
"doc": "Inverts progress (1 - progress).",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("slope", """
|
||||
{
|
||||
"doc": "Slopes progress: rises to 1 then falls back to 0.",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("clamp", """
|
||||
{
|
||||
"doc": "Clamps progress to the [0, 1] range.",
|
||||
"superclass": "PartProgress"
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("delay", """
|
||||
{
|
||||
"doc": "Delays progress by a fixed amount.",
|
||||
"superclass": "PartProgress",
|
||||
"amount": { "type": "float", "doc": "Amount to delay progress by." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("sustain", """
|
||||
{
|
||||
"doc": "Rises to and sustains progress at a plateau.",
|
||||
"superclass": "PartProgress",
|
||||
"offset": { "type": "float", "doc": "Progress offset before rising.", "default": "0" },
|
||||
"grow": { "type": "float", "doc": "Duration of the rise to the plateau.", "default": "0" },
|
||||
"sustain": { "type": "float", "doc": "Length of the sustained plateau." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("shorten", """
|
||||
{
|
||||
"doc": "Shortens the progress range by a fixed amount.",
|
||||
"superclass": "PartProgress",
|
||||
"amount": { "type": "float", "doc": "Amount to shorten progress by." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("compress", """
|
||||
{
|
||||
"doc": "Compresses progress into the [start, end] sub-range.",
|
||||
"superclass": "PartProgress",
|
||||
"start": { "type": "float", "doc": "Start of the compressed range." },
|
||||
"end": { "type": "float", "doc": "End of the compressed range." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("add", """
|
||||
{
|
||||
"doc": "Adds a constant or another PartProgress's value to this one. Set exactly one of 'amount' or 'other'.",
|
||||
"superclass": "PartProgress",
|
||||
"amount": { "type": "float", "doc": "Constant amount to add." },
|
||||
"other": { "type": "PartProgress", "doc": "Another progress function whose value is added instead of a constant." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("blend", """
|
||||
{
|
||||
"doc": "Blends between this progress and another PartProgress by a fixed amount.",
|
||||
"superclass": "PartProgress",
|
||||
"other": { "type": "PartProgress", "doc": "Progress function to blend with." },
|
||||
"amount": { "type": "float", "doc": "Blend factor toward 'other'." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("mul", """
|
||||
{
|
||||
"doc": "Multiplies by a constant or another PartProgress's value. Set exactly one of 'amount' or 'other'.",
|
||||
"superclass": "PartProgress",
|
||||
"amount": { "type": "float", "doc": "Constant multiplier." },
|
||||
"other": { "type": "PartProgress", "doc": "Another progress function whose value is multiplied instead of a constant." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("min", """
|
||||
{
|
||||
"doc": "Takes the minimum of this progress and another PartProgress.",
|
||||
"superclass": "PartProgress",
|
||||
"other": { "type": "PartProgress", "doc": "Progress function to compare against." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("sin", """
|
||||
{
|
||||
"doc": "Applies a sine wave to progress.",
|
||||
"superclass": "PartProgress",
|
||||
"offset": { "type": "float", "doc": "Phase offset.", "default": "0" },
|
||||
"scl": { "type": "float", "doc": "Scale (frequency) of the wave." },
|
||||
"mag": { "type": "float", "doc": "Magnitude (amplitude) of the wave." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("absin", """
|
||||
{
|
||||
"doc": "Applies an absolute-value sine wave to progress.",
|
||||
"superclass": "PartProgress",
|
||||
"scl": { "type": "float", "doc": "Scale (frequency) of the wave." },
|
||||
"mag": { "type": "float", "doc": "Magnitude (amplitude) of the wave." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("mod", """
|
||||
{
|
||||
"doc": "Wraps progress modulo a fixed amount.",
|
||||
"superclass": "PartProgress",
|
||||
"amount": { "type": "float", "doc": "Modulus to wrap progress by." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("loop", """
|
||||
{
|
||||
"doc": "Loops progress over a fixed time period.",
|
||||
"superclass": "PartProgress",
|
||||
"time": { "type": "float", "doc": "Length of one loop cycle." }
|
||||
}
|
||||
""");
|
||||
|
||||
writePartSchema("curve", """
|
||||
{
|
||||
"doc": "Applies an interpolation curve to progress, or slices out a sub-range and interpolates within it. Set either 'interp', or both 'offset' and 'duration'.",
|
||||
"superclass": "PartProgress",
|
||||
"interp": { "type": "arc.util.Interp", "doc": "Interpolation curve to apply directly to progress." },
|
||||
"offset": { "type": "float", "doc": "Start of the sub-range to slice out." },
|
||||
"duration": { "type": "float", "doc": "Length of the sub-range to slice out." }
|
||||
}
|
||||
""");
|
||||
}
|
||||
|
||||
private static void registerBuiltinSchemas(){
|
||||
injectCustomField(UnitType.class, "type", field("JsonUnitType", "Type of the unit that is created.", false));
|
||||
injectCustomField(UnitType.class, "template", field("TemplateUnitType", "UnitType template class.", false));
|
||||
injectCustomField(UnitType.class, "defaultController", field(AIController.class.getCanonicalName(), "Unconditional controller; always assigned, even if on the player team. This overwrites RTS AI.", false));
|
||||
injectCustomField(UnitType.class, "aiController", field(AIController.class.getCanonicalName(), "Controller used when the unit is not on the player team.", false));
|
||||
|
||||
writeSchema("JsonUnitType", """
|
||||
{
|
||||
"doc": "Type of unit that is created.",
|
||||
"superclass": "Enum",
|
||||
"values": ["flying", "mech", "legs", "naval", "payload", "missile", "tank", "hover", "tether", "crawl"]
|
||||
}
|
||||
""");
|
||||
|
||||
writeSchema(Interp.class.getCanonicalName(), """
|
||||
{
|
||||
"doc": "Various types of interpolation.",
|
||||
"superclass": "Enum",
|
||||
"values": [%VALUES%]
|
||||
}
|
||||
""".replace("%VALUES%", Seq.with(Interp.class.getFields()).toString(", ", t -> "\"" + t.getName() + "\"")));
|
||||
|
||||
writeSchema(Blending.class.getCanonicalName(), """
|
||||
{
|
||||
"doc": "Handles sprite blending.",
|
||||
"superclass": "Enum",
|
||||
"values": ["normal", "additive", "disabled"]
|
||||
}
|
||||
""");
|
||||
|
||||
injectCustomField(Planet.class, "sectorSize", field("int", "Planet sector subdivisions.", false));
|
||||
|
||||
writeFakeSchema("Consumes", """
|
||||
writeSchema("Consumes", """
|
||||
{
|
||||
"doc": "Things that the block consumes.",
|
||||
"remove": {"type": "java.lang.String[]", "doc": "Removes consumers instead of adding one: 'all', or a type name from this list, e.g. 'items'."},
|
||||
@@ -113,7 +405,7 @@ public class SchemaGenerator{
|
||||
|
||||
injectCustomField(Block.class, "consumes", field("Consumes", "Things that the block consumes.", true));
|
||||
|
||||
writeFakeSchema("Research", """
|
||||
writeSchema("Research", """
|
||||
{
|
||||
"doc": "Tech tree placement for this content. Also accepts a plain string, treated as 'parent'.",
|
||||
"parent": {"type": "mindustry.ctype.UnlockableContent", "doc": "Name of the parent tech tree node; required unless 'root' is true."},
|
||||
@@ -131,6 +423,10 @@ public class SchemaGenerator{
|
||||
}
|
||||
}
|
||||
|
||||
private static Jval field(String type, String doc){
|
||||
return field(type, doc, false, null);
|
||||
}
|
||||
|
||||
private static Jval field(String type, String doc, boolean nullable){
|
||||
return field(type, doc, nullable, null);
|
||||
}
|
||||
@@ -147,7 +443,7 @@ public class SchemaGenerator{
|
||||
private static @Nullable TypeDeclaration<?> getTypeDecl(Class<?> type){
|
||||
return decls.get(type, () -> {
|
||||
if(classNameToFile.isEmpty()){
|
||||
new Fi("core/src").walk(f -> {
|
||||
new Fi("../../core/src").walk(f -> {
|
||||
if(f.extEquals("java")){
|
||||
classNameToFile.put(f.nameWithoutExtension(), f);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
|
||||
public class ScriptMainGenerator{
|
||||
|
||||
public static void main(String[] args) throws Exception{
|
||||
String base = "mindustry";
|
||||
Seq<String> blacklist = Seq.with("tools", "arc.flabel.effects");
|
||||
@@ -56,7 +57,7 @@ public class ScriptMainGenerator{
|
||||
ObjectSet<String> used = ObjectSet.with();
|
||||
|
||||
StringBuilder result = new StringBuilder("//Generated class. Do not modify.\n");
|
||||
result.append("\n").append(new Fi("core/assets/scripts/base.js").readString()).append("\n");
|
||||
result.append("\n").append(new Fi("scripts/base.js").readString()).append("\n");
|
||||
for(Class type : classes){
|
||||
if(used.contains(type.getPackage().getName()) || nopackage.contains(s -> type.getName().startsWith(s))) continue;
|
||||
result.append("importPackage(Packages.").append(type.getPackage().getName()).append(")\n");
|
||||
@@ -69,7 +70,7 @@ public class ScriptMainGenerator{
|
||||
result.append("const ").append(type.getSimpleName()).append(" = ").append("Packages.").append(type.getName().replace('$', '.')).append("\n");
|
||||
}
|
||||
|
||||
new Fi("core/assets/scripts/global.js").writeString(result.toString());
|
||||
new Fi("scripts/global.js").writeString(result.toString());
|
||||
|
||||
//map simple name to type
|
||||
Seq<String> packages = Seq.with(
|
||||
@@ -111,8 +112,12 @@ public class ScriptMainGenerator{
|
||||
SchemaGenerator.writeSchema(c);
|
||||
}
|
||||
|
||||
new Fi("core/src/mindustry/mod/ClassMap.java").writeString(classTemplate.replace("$CLASSES$", cdef.toString()));
|
||||
SchemaGenerator.finalizeSchemas(mapped);
|
||||
|
||||
new Fi("../../core/src/mindustry/mod/ClassMap.java").writeString(classTemplate.replace("$CLASSES$", cdef.toString()));
|
||||
Log.info("Generated @ class mappings.", mapped.size);
|
||||
|
||||
SchemaGenerator.writeDefaultContent();
|
||||
}
|
||||
public static Seq<Class> getClasses(String packageName) throws Exception{
|
||||
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
Reference in New Issue
Block a user