Skip to content

Commit c12e9da

Browse files
authored
Concrete types (#21)
* get custom types working * shadow + tests * polish * return empty array when creating a struct whose template doesn't exist * comment out local test * keep classes/classinfos around and re-use to avoid stale references, add converters from Struct to subclasses. * handle chained converters * struct copy docs
1 parent 234bb6d commit c12e9da

File tree

17 files changed

+528
-44
lines changed

17 files changed

+528
-44
lines changed

build.gradle

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import org.apache.tools.ant.filters.ReplaceTokens
22

33
plugins {
44
id 'java'
5+
// id 'skript-test' version('1.0.1')
6+
id 'com.gradleup.shadow' version('9.2.2')
57
}
68

79
group = 'com.sovdee'
@@ -12,6 +14,7 @@ test {
1214

1315
repositories {
1416
mavenCentral()
17+
mavenLocal()
1518
maven {
1619
url 'https://repo.papermc.io/repository/maven-public/'
1720
}
@@ -21,14 +24,31 @@ repositories {
2124
}
2225

2326
dependencies {
24-
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
25-
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
26-
2727
compileOnly 'org.spigotmc:spigot-api:1.21.4-R0.1-SNAPSHOT'
28-
compileOnly "com.github.SkriptLang:Skript:2.11.0"
28+
compileOnly "com.github.SkriptLang:Skript:2.12.2"
2929
compileOnly 'org.jetbrains:annotations:26.0.1'
30+
implementation 'net.bytebuddy:byte-buddy:1.14.18' // for runtime code generation
3031
}
3132

3233
processResources {
3334
filter ReplaceTokens, tokens: ["version": project.property("version")]
3435
}
36+
37+
shadowJar {
38+
relocate 'net.bytebuddy', 'com.sovdee.oopsk.bytebuddy'
39+
minimize()
40+
archiveClassifier.set('')
41+
}
42+
43+
build {
44+
dependsOn shadowJar
45+
}
46+
47+
48+
//skriptTest {
49+
// dependsOn build
50+
// testScriptDirectory = file("src/test/scripts")
51+
// extraPluginsDirectory = new File("./build/libs")
52+
// skriptRepoRef = "dev/patch"
53+
// runVanillaTests = false
54+
//}

settings.gradle

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,10 @@
1+
pluginManagement {
2+
repositories {
3+
mavenLocal()
4+
gradlePluginPortal()
5+
}
6+
}
7+
18
rootProject.name = 'oopsk'
9+
10+

src/main/java/com/sovdee/oopsk/Oopsk.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import ch.njol.skript.bstats.bukkit.Metrics;
66
import com.sovdee.oopsk.core.StructManager;
77
import com.sovdee.oopsk.core.TemplateManager;
8+
import com.sovdee.oopsk.core.generation.TemporaryClassManager;
89
import org.bukkit.plugin.java.JavaPlugin;
910

1011
import java.io.IOException;
@@ -16,6 +17,7 @@ public final class Oopsk extends JavaPlugin {
1617
private static SkriptAddon addon;
1718
private static StructManager structManager;
1819
private static TemplateManager templateManager;
20+
private static TemporaryClassManager classManager = new TemporaryClassManager();
1921
private static Logger logger;
2022

2123
public static Oopsk getInstance() {
@@ -34,6 +36,10 @@ public static TemplateManager getTemplateManager() {
3436
return templateManager;
3537
}
3638

39+
public static TemporaryClassManager getClassManager() {
40+
return classManager;
41+
}
42+
3743
public static void info(String message) {
3844
logger.info(message);
3945
}

src/main/java/com/sovdee/oopsk/core/Struct.java

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,41 @@ public class Struct {
2222
private StructTemplate template;
2323
private final Map<Field<?>, Object[]> fieldValues;
2424

25+
public static Struct newInstance(@NotNull StructTemplate template, @Nullable Event event) {
26+
Class<? extends Struct> structClass = template.getCustomClass();
27+
try {
28+
return structClass.getDeclaredConstructor(StructTemplate.class, Event.class).newInstance(template, event);
29+
} catch (Exception e) {
30+
throw new RuntimeException("Failed to create new instance of struct class " + structClass.getName(), e);
31+
}
32+
}
33+
34+
public static Struct newInstance(Struct source) {
35+
Class<? extends Struct> structClass = source.getTemplate().getCustomClass();
36+
try {
37+
return structClass.getDeclaredConstructor(Struct.class).newInstance(source);
38+
} catch (Exception e) {
39+
throw new RuntimeException("Failed to create new instance of struct class " + structClass.getName(), e);
40+
}
41+
}
42+
43+
public static Struct newInstance(@NotNull StructTemplate template, @Nullable Event event, @Nullable Map<String, Expression<?>> initialValues) {
44+
Class<? extends Struct> structClass = template.getCustomClass();
45+
try {
46+
return structClass.getDeclaredConstructor(StructTemplate.class, Event.class, Map.class).newInstance(template, event, initialValues);
47+
} catch (Exception e) {
48+
throw new RuntimeException("Failed to create new instance of struct class " + structClass.getName(), e);
49+
}
50+
}
51+
2552
/**
2653
* Creates a new struct with the given template and event.
2754
*
2855
* @param template The template to create the struct from.
2956
* @param event The event to evaluate the default values in.
3057
* @see StructManager#createStruct(StructTemplate, Event)
3158
*/
32-
public Struct(@NotNull StructTemplate template, @Nullable Event event) {
59+
protected Struct(@NotNull StructTemplate template, @Nullable Event event) {
3360
this.template = template;
3461
fieldValues = new HashMap<>();
3562
for (Field<?> field : template.getFields()) {
@@ -44,7 +71,7 @@ public Struct(@NotNull StructTemplate template, @Nullable Event event) {
4471
* @param source The struct to copy from.
4572
* @see StructManager#createStruct(StructTemplate, Event)
4673
*/
47-
public Struct(Struct source) {
74+
protected Struct(Struct source) {
4875
this.template = source.template;
4976
fieldValues = new HashMap<>();
5077
for (Map.Entry<Field<?>, Object[]> entry : source.fieldValues.entrySet()) {
@@ -64,7 +91,7 @@ public Struct(Struct source) {
6491
* @param initialValues The initial values to set in the struct. This is a map of field names to expressions.
6592
* @see StructManager#createStruct(StructTemplate, Event)
6693
*/
67-
Struct(@NotNull StructTemplate template, @Nullable Event event, @Nullable Map<String, Expression<?>> initialValues) {
94+
protected Struct(@NotNull StructTemplate template, @Nullable Event event, @Nullable Map<String, Expression<?>> initialValues) {
6895
this.template = template;
6996
fieldValues = new HashMap<>();
7097
for (Field<?> field : template.getFields()) {

src/main/java/com/sovdee/oopsk/core/StructManager.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ public Struct createStruct(StructTemplate template, @Nullable Event event) {
4141
* @return The created struct.
4242
*/
4343
public Struct createStruct(StructTemplate template, @Nullable Event event, @Nullable Map<String, Expression<?>> initialValues) {
44-
Struct struct = new Struct(template, event, initialValues);
44+
Struct struct = Struct.newInstance(template, event, initialValues);
4545
activeStructs.computeIfAbsent(template, k -> Collections.newSetFromMap(new WeakHashMap<>())).add(struct);
4646
return struct;
4747
}

src/main/java/com/sovdee/oopsk/core/StructTemplate.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,17 @@
1414
public class StructTemplate {
1515
private final String name;
1616
private final Map<String, Field<?>> fields;
17+
private final Class<? extends Struct> customClass;
1718

1819
/**
1920
* Creates a new struct template with the given name and fields.
2021
*
2122
* @param name The name of the template.
2223
* @param fields The fields of the template.
2324
*/
24-
public StructTemplate(String name, @NotNull List<Field<?>> fields) {
25+
public StructTemplate(String name, @NotNull List<Field<?>> fields, Class<? extends Struct> customClass) {
2526
this.name = name;
27+
this.customClass = customClass;
2628
this.fields = new HashMap<>();
2729
for (Field<?> field : fields) {
2830
this.fields.put(field.name(), field);
@@ -36,6 +38,13 @@ public String getName() {
3638
return name;
3739
}
3840

41+
/**
42+
* @return The custom class for this struct, or null if none was specified.
43+
*/
44+
public Class<? extends Struct> getCustomClass() {
45+
return customClass;
46+
}
47+
3948
/**
4049
* Parses all the default value expressions for this struct. Prints errors.
4150
* @return true if no errors were encountered. False otherwise.

src/main/java/com/sovdee/oopsk/core/TemplateManager.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
public class TemplateManager {
1919

2020
private final Map<String, StructTemplate> templates = new HashMap<>();
21+
private final Map<Class<? extends Struct>, StructTemplate> templatesByClass = new HashMap<>();
2122

2223
/**
2324
* Adds a new template to the manager. Attempts to reparent all orphaned structs that match this template's name.
@@ -29,6 +30,7 @@ public boolean addTemplate(@NotNull StructTemplate template) {
2930
if (templates.containsKey(template.getName()))
3031
return false; // Template with the same name already exists
3132
templates.put(template.getName(), template);
33+
templatesByClass.put(template.getCustomClass(), template);
3234
// reparent all orphaned structs of this template
3335
Oopsk.getStructManager().reparentStructs(template);
3436
return true; // Template added successfully
@@ -44,6 +46,16 @@ public StructTemplate getTemplate(String name) {
4446
return templates.get(name);
4547
}
4648

49+
/**
50+
* Retrieves a template by class.
51+
*
52+
* @param structClass The name of the template to retrieve.
53+
* @return The template, or null if it does not exist.
54+
*/
55+
public StructTemplate getTemplate(Class<?extends Struct> structClass) {
56+
return templatesByClass.get(structClass);
57+
}
58+
4759
/**
4860
* Removes a template from the manager. This will orphan all structs of this template.
4961
*
@@ -54,6 +66,7 @@ public void removeTemplate(@NotNull StructTemplate template) {
5466
if (!templates.containsKey(name))
5567
return; // Template with the given name does not exist
5668
templates.remove(name);
69+
templatesByClass.remove(template.getCustomClass());
5770
// mark all structs of this template as orphaned
5871
Oopsk.getStructManager().orphanStructs(template);
5972
}

0 commit comments

Comments
 (0)