Restructure
ScriptCraft/pipeline/head This commit looks good Details

This commit is contained in:
TheBrokenRail 2020-04-27 20:15:24 -04:00
parent afeea22abe
commit aa8e3f5e2b
52 changed files with 577 additions and 524 deletions

View File

@ -29,7 +29,7 @@ add_library(
quickjs/cutils.c
quickjs/libbf.c
console.c
com_thebrokenrail_scriptcraft_quickjs_QuickJS.c
com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative.c
)
file(STRINGS "quickjs/VERSION" QUICKJS_VERSION)

View File

@ -6,19 +6,19 @@
#include <cutils.h>
#include <quickjs.h>
#include "com_thebrokenrail_scriptcraft_quickjs_QuickJS.h"
#include "com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative.h"
#include "console.h"
static JavaVM *jvm;
static void *get_pointer(JNIEnv *env, jobject obj, const char *name) {
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/quickjs/QuickJS");
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSNative");
jfieldID field = (*env)->GetFieldID(env, clazz, name, "J");
return (void *) (long) (*env)->GetLongField(env, obj, field);
}
static void set_pointer(JNIEnv *env, jobject obj, const char *name, void *value) {
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/quickjs/QuickJS");
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSNative");
jfieldID field = (*env)->GetFieldID(env, clazz, name, "J");
(*env)->SetLongField(env, obj, field, (jlong) (long) value);
}
@ -27,7 +27,7 @@ static char *js_module_normalize_name(JSContext *ctx, const char *base_name, con
JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/quickjs/QuickJS");
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSModules");
jmethodID methodID = (*env)->GetStaticMethodID(env, clazz, "normalizeModule", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
jstring java_name = (*env)->NewStringUTF(env, name);
@ -99,7 +99,7 @@ static char *js_load_file(JSContext *ctx, const char *filename) {
JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/quickjs/QuickJS");
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSModules");
jmethodID methodID = (*env)->GetStaticMethodID(env, clazz, "loadModule", "(Ljava/lang/String;)Ljava/lang/String;");
jstring java_filename = (*env)->NewStringUTF(env, filename);
@ -164,7 +164,7 @@ static JSModuleDef *js_module_loader(JSContext *ctx, const char *module_name, vo
}
static void throw_exception(JNIEnv *env, const char *message) {
jclass exception_clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/quickjs/JSException");
jclass exception_clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/JSException");
(*env)->ThrowNew(env, exception_clazz, message);
}
@ -193,13 +193,15 @@ static JSClassDef JS_CLASS_JAVA_OBJECT = {
};
static JSValue java_object_to_js_object(JNIEnv *env, JSContext *ctx, jobject obj) {
JSValue out = JS_NULL;
JSValue out;
jclass boolean_clazz = (*env)->FindClass(env, "java/lang/Boolean");
jclass double_clazz = (*env)->FindClass(env, "java/lang/Double");
jclass string_clazz = (*env)->FindClass(env, "java/lang/String");
jclass array_clazz = (*env)->FindClass(env, "[Ljava/lang/Object;");
if ((*env)->IsInstanceOf(env, obj, string_clazz)) {
if (!obj) {
out = JS_NULL;
} else if ((*env)->IsInstanceOf(env, obj, string_clazz)) {
const char *native_string = (*env)->GetStringUTFChars(env, (jstring) obj, 0);
out = JS_NewString(ctx, native_string);
(*env)->ReleaseStringUTFChars(env, (jstring) obj, native_string);
@ -275,7 +277,21 @@ static jobject js_object_to_java_object(JNIEnv *env, JSContext *ctx, JSValue inp
return obj;
}
static JSValue js_bridge(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
static JSValue js_add_bridge(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
JSValue global_obj = JS_GetGlobalObject(ctx);
JSValue scriptcraft_obj = JS_GetPropertyStr(ctx, global_obj, "__scriptcraft_bridges__");
const char *name = JS_ToCString(ctx, argv[0]);
JS_SetPropertyStr(ctx, scriptcraft_obj, name, JS_DupValue(ctx, argv[1]));
JS_FreeCString(ctx, name);
JS_FreeValue(ctx, scriptcraft_obj);
JS_FreeValue(ctx, global_obj);
return JS_UNDEFINED;
}
static JSValue js_use_bridge(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
@ -288,7 +304,7 @@ static JSValue js_bridge(JSContext *ctx, JSValueConst this_val, int argc, JSValu
(*env)->DeleteLocalRef(env, obj);
}
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/bridge/Bridges");
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/ScriptCraftCore");
jmethodID methodID = (*env)->GetStaticMethodID(env, clazz, "useBridge", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;");
const char *js_bridge_name = JS_ToCString(ctx, argv[0]);
@ -325,7 +341,7 @@ static JSValue js_bridge(JSContext *ctx, JSValueConst this_val, int argc, JSValu
return js_out;
}
JNIEXPORT jobject JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_bridge(JNIEnv *env, jobject this_val, jstring bridge_name, jobjectArray arr) {
JNIEXPORT jobject JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative_bridge(JNIEnv *env, jobject this_val, jstring bridge_name, jobjectArray arr) {
JSContext *ctx = (JSContext *) get_pointer(env, this_val, "ctx");
int length = (*env)->GetArrayLength(env, arr);
@ -336,11 +352,10 @@ JNIEXPORT jobject JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_bri
}
JSValue global_obj = JS_GetGlobalObject(ctx);
JSValue scriptcraft_obj = JS_GetPropertyStr(ctx, global_obj, "__scriptcraft__");
JSValue bridges = JS_GetPropertyStr(ctx, scriptcraft_obj, "bridges");
JSValue scriptcraft_obj = JS_GetPropertyStr(ctx, global_obj, "__scriptcraft_bridges__");
const char *native_string = (*env)->GetStringUTFChars(env, bridge_name, 0);
JSValue bridge = JS_GetPropertyStr(ctx, bridges, native_string);
JSValue bridge = JS_GetPropertyStr(ctx, scriptcraft_obj, native_string);
(*env)->ReleaseStringUTFChars(env, bridge_name, native_string);
JSValue out;
@ -360,7 +375,6 @@ JNIEXPORT jobject JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_bri
}
JS_FreeValue(ctx, bridge);
JS_FreeValue(ctx, bridges);
JS_FreeValue(ctx, scriptcraft_obj);
JS_FreeValue(ctx, global_obj);
@ -370,7 +384,13 @@ JNIEXPORT jobject JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_bri
return java_out;
}
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_init(JNIEnv *env, jobject this_val) {
static int scriptcraft_core_init(JSContext *ctx, JSModuleDef *m) {
JS_SetModuleExport(ctx, m, "useBridge", JS_NewCFunction(ctx, js_use_bridge, "useBridge", 1));
JS_SetModuleExport(ctx, m, "addBridge", JS_NewCFunction(ctx, js_add_bridge, "addBridge", 2));
return 0;
}
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative_init(JNIEnv *env, jobject this_val) {
jint rc = (*env)->GetJavaVM(env, &jvm);
if (rc != JNI_OK) {
throw_exception(env, "qjs: unable to cache JavaVM");
@ -392,24 +412,28 @@ JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_init(J
js_console_init(ctx);
JSValue global_obj = JS_GetGlobalObject(ctx);
JSValue scriptcraft_obj = JS_NewObject(ctx);
JS_SetPropertyStr(ctx, scriptcraft_obj, "bridges", JS_NewObject(ctx));
JS_SetPropertyStr(ctx, scriptcraft_obj, "useBridge", JS_NewCFunction(ctx, js_bridge, "useBridge", 1));
JS_SetPropertyStr(ctx, global_obj, "__scriptcraft__", scriptcraft_obj);
JS_FreeValue(ctx, global_obj);
JS_NewClassID(&JS_CLASS_JAVA_OBJECT_ID);
JS_NewClass(JS_GetRuntime(ctx), JS_CLASS_JAVA_OBJECT_ID, &JS_CLASS_JAVA_OBJECT);
JS_SetClassProto(ctx, JS_CLASS_JAVA_OBJECT_ID, JS_NewObject(ctx));
JSModuleDef *m = JS_NewCModule(ctx, "scriptcraft-core", scriptcraft_core_init);
if (!m) {
throw_exception(env, "qjs: unable to allocate C module");
return;
}
JS_AddModuleExport(ctx, m, "useBridge");
JS_AddModuleExport(ctx, m, "addBridge");
JSValue global_obj = JS_GetGlobalObject(ctx);
JS_SetPropertyStr(ctx, global_obj, "__scriptcraft_bridges__", JS_NewObject(ctx));
JS_FreeValue(ctx, global_obj);
set_pointer(env, this_val, "rt", rt);
set_pointer(env, this_val, "ctx", ctx);
}
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_free(JNIEnv *env, jobject this_val) {
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative_free(JNIEnv *env, jobject this_val) {
JSContext *ctx = (JSContext *) get_pointer(env, this_val, "ctx");
JSRuntime *rt = (JSRuntime *) get_pointer(env, this_val, "rt");
@ -442,7 +466,7 @@ static int eval_buf(JNIEnv *env, JSContext *ctx, const void *buf, int buf_len, c
return ret;
}
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_run(JNIEnv *env, jobject this_val, jstring data) {
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative_run(JNIEnv *env, jobject this_val, jstring data) {
JSContext *ctx = (JSContext *) get_pointer(env, this_val, "ctx");
const char *native_string = (*env)->GetStringUTFChars(env, data, 0);
@ -454,7 +478,7 @@ void print_data(char *data, int err) {
JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL);
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/quickjs/QuickJS");
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSNative");
jmethodID print_methodID = (*env)->GetStaticMethodID(env, clazz, "print", "(Ljava/lang/String;Z)V");
jstring str = (*env)->NewStringUTF(env, data);
(*env)->CallStaticVoidMethod(env, clazz, print_methodID, str, err);

View File

@ -0,0 +1,47 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative */
#ifndef _Included_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative
#define _Included_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative
* Method: init
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative_init
(JNIEnv *, jobject);
/*
* Class: com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative
* Method: free
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative_free
(JNIEnv *, jobject);
/*
* Class: com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative
* Method: bridge
* Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative_bridge
(JNIEnv *, jobject, jstring, jobjectArray);
/*
* Class: com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative
* Method: run
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative_run
(JNIEnv *, jobject, jstring);
void print_data(char *data, int err);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,47 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_thebrokenrail_scriptcraft_quickjs_QuickJS */
#ifndef _Included_com_thebrokenrail_scriptcraft_quickjs_QuickJS
#define _Included_com_thebrokenrail_scriptcraft_quickjs_QuickJS
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_thebrokenrail_scriptcraft_quickjs_QuickJS
* Method: init
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_init
(JNIEnv *, jobject);
/*
* Class: com_thebrokenrail_scriptcraft_quickjs_QuickJS
* Method: free
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_free
(JNIEnv *, jobject);
/*
* Class: com_thebrokenrail_scriptcraft_quickjs_QuickJS
* Method: bridge
* Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_bridge
(JNIEnv *, jobject, jstring, jobjectArray);
/*
* Class: com_thebrokenrail_scriptcraft_quickjs_QuickJS
* Method: run
* Signature: (Ljava/lang/String;Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_quickjs_QuickJS_run
(JNIEnv *, jobject, jstring);
void print_data(char *data, int err);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -4,7 +4,7 @@
#include <stdlib.h>
#include <quickjs.h>
#include "com_thebrokenrail_scriptcraft_quickjs_QuickJS.h"
#include "com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative.h"
static JSValue js_print_internal(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv, int err, int prepend_throw) {
int i;

View File

@ -1,6 +1,6 @@
package com.thebrokenrail.scriptcraft;
import com.thebrokenrail.scriptcraft.util.ScriptCraftEntrypoint;
import com.thebrokenrail.scriptcraft.core.ScriptCraftEntrypoint;
public class Demo implements ScriptCraftEntrypoint {
@Override

View File

@ -1,35 +1,13 @@
package com.thebrokenrail.scriptcraft;
import com.thebrokenrail.scriptcraft.quickjs.QuickJS;
import com.thebrokenrail.scriptcraft.quickjs.QuickJSManager;
import com.thebrokenrail.scriptcraft.util.ScriptCraftEntrypoint;
import com.thebrokenrail.scriptcraft.api.ScriptCraftAPI;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.loader.api.FabricLoader;
import java.util.List;
import java.util.regex.Pattern;
public class ScriptCraft implements ModInitializer {
public static final String NAMESPACE = "scriptcraft";
public static final Pattern MOD_ID_PATTERN = Pattern.compile("[a-z][a-z0-9-_]{1,63}");
@Override
public void onInitialize() {
QuickJSManager.init(new QuickJSManager.Task() {
@Override
protected Object run(QuickJS quickjs) {
List<ScriptCraftEntrypoint> mods = FabricLoader.getInstance().getEntrypoints(NAMESPACE, ScriptCraftEntrypoint.class);
for (ScriptCraftEntrypoint mod : mods) {
if (MOD_ID_PATTERN.matcher(mod.getModID()).matches()) {
if (mod.shouldAutoLoad()) {
quickjs.run("import '" + mod.getModID() + "';");
}
} else {
throw new RuntimeException("Invalid Mod ID: " + mod.getModID());
}
}
return null;
}
});
ScriptCraftAPI.init();
ScriptCraftCore.init();
}
}

View File

@ -0,0 +1,26 @@
package com.thebrokenrail.scriptcraft.api;
import com.thebrokenrail.scriptcraft.api.bridge.Bridges;
import com.thebrokenrail.scriptcraft.core.ScriptCraftEntrypoint;
@SuppressWarnings("unused")
public class ScriptCraftAPI implements ScriptCraftEntrypoint {
@Override
public String getModID() {
return "minecraft";
}
@Override
public String getModIndex() {
return "index";
}
@Override
public boolean shouldAutoLoad() {
return false;
}
public static void init() {
Bridges.init();
}
}

View File

@ -1,7 +1,7 @@
package com.thebrokenrail.scriptcraft.api;
package com.thebrokenrail.scriptcraft.api.block;
import com.thebrokenrail.scriptcraft.util.Util;
import com.thebrokenrail.scriptcraft.quickjs.QuickJSManager;
import com.thebrokenrail.scriptcraft.core.ValueUtil;
import com.thebrokenrail.scriptcraft.core.quickjs.QuickJSManager;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
@ -23,6 +23,6 @@ public class CustomBlock extends Block {
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
return Util.getEnumValue(ActionResult.class, (String) QuickJSManager.bridge("CustomBlock.onUse", id.toString(), world, state, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), hit.getSide().name(), player, hand.name()), ActionResult.PASS);
return ValueUtil.getEnumValue(ActionResult.class, (String) QuickJSManager.bridge("CustomBlock.onUse", id.toString(), world, state, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ(), hit.getSide().name(), player, hand.name()), ActionResult.PASS);
}
}

View File

@ -1,6 +1,6 @@
package com.thebrokenrail.scriptcraft.api;
package com.thebrokenrail.scriptcraft.api.block;
import com.thebrokenrail.scriptcraft.quickjs.QuickJSManager;
import com.thebrokenrail.scriptcraft.core.quickjs.QuickJSManager;
import net.fabricmc.fabric.api.block.entity.BlockEntityClientSerializable;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
@ -11,22 +11,15 @@ import net.minecraft.util.Tickable;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.HashMap;
import java.util.Map;
public class CustomBlockEntity extends BlockEntity implements BlockEntityClientSerializable, Tickable {
private static final Map<Identifier, Integer> newObjID = new HashMap<>();
private static long newObjID = 0;
private final Identifier id;
private final int objID;
private final long objID;
public CustomBlockEntity(BlockEntityType<?> type, Identifier id) {
super(type);
this.id = id;
newObjID.putIfAbsent(id, 0);
objID = newObjID.get(id);
newObjID.put(id, newObjID.get(id) + 1);
objID = newObjID++;
QuickJSManager.bridge("CustomBlockEntity.create", id.toString(), (double) objID);
}
@ -34,7 +27,7 @@ public class CustomBlockEntity extends BlockEntity implements BlockEntityClientS
@Override
public void fromTag(CompoundTag tag) {
super.fromTag(tag);
QuickJSManager.bridge("CustomBlockEntity.fromTag", id.toString(), (double) objID, tag);
QuickJSManager.bridge("CustomBlockEntity.fromTag", (double) objID, tag);
}
@Override
@ -44,7 +37,7 @@ public class CustomBlockEntity extends BlockEntity implements BlockEntityClientS
@Override
public CompoundTag toTag(CompoundTag tag) {
return (CompoundTag) QuickJSManager.bridge("CustomBlockEntity.toTag", id.toString(), (double) objID, super.toTag(tag));
return (CompoundTag) QuickJSManager.bridge("CustomBlockEntity.toTag", (double) objID, super.toTag(tag));
}
@Override
@ -54,20 +47,20 @@ public class CustomBlockEntity extends BlockEntity implements BlockEntityClientS
@Override
public void tick() {
QuickJSManager.bridge("CustomBlockEntity.tick", id.toString(), (double) objID);
QuickJSManager.bridge("CustomBlockEntity.tick", (double) objID);
}
@Override
public void setLocation(World world, BlockPos pos) {
super.setLocation(world, pos);
QuickJSManager.bridge("CustomBlockEntity.setLocation", id.toString(), (double) objID, world, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ());
QuickJSManager.bridge("CustomBlockEntity.setLocation", (double) objID, world, (double) pos.getX(), (double) pos.getY(), (double) pos.getZ());
}
@SuppressWarnings("deprecation")
@Override
protected void finalize() throws Throwable {
try {
QuickJSManager.bridge("CustomBlockEntity.free", id.toString(), (double) objID);
QuickJSManager.bridge("CustomBlockEntity.free", (double) objID);
} finally {
super.finalize();
}
@ -80,4 +73,8 @@ public class CustomBlockEntity extends BlockEntity implements BlockEntityClientS
sync();
}
}
public long getObjID() {
return objID;
}
}

View File

@ -1,5 +1,7 @@
package com.thebrokenrail.scriptcraft.api;
package com.thebrokenrail.scriptcraft.api.block;
import com.thebrokenrail.scriptcraft.api.block.CustomBlock;
import com.thebrokenrail.scriptcraft.api.block.CustomBlockEntity;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.Identifier;

View File

@ -1,5 +1,6 @@
package com.thebrokenrail.scriptcraft.bridge;
package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import net.fabricmc.fabric.api.block.FabricBlockSettings;
import net.minecraft.block.Material;
import net.minecraft.block.MaterialColor;
@ -8,7 +9,7 @@ import java.util.Locale;
class BlockSettingsBridges {
static void register() {
Bridges.addBridge("BlockSettings.create", args -> {
ScriptCraftCore.addBridge("BlockSettings.create", args -> {
try {
String materialID = ((String) args[0]).toUpperCase(Locale.ROOT);
Material material = (Material) Material.class.getField(materialID).get(null);

View File

@ -0,0 +1,13 @@
package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import net.minecraft.block.BlockState;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
class BlockStateBridges {
static void register() {
ScriptCraftCore.addBridge("BlockState.getDefaultState", args -> Registry.BLOCK.get(new Identifier((String) args[0])).getDefaultState());
ScriptCraftCore.addBridge("BlockState.getBlock", args -> Registry.BLOCK.getId(((BlockState) args[0]).getBlock()).toString());
}
}

View File

@ -0,0 +1,16 @@
package com.thebrokenrail.scriptcraft.api.bridge;
public class Bridges {
public static void init() {
BlockSettingsBridges.register();
RegistryBridge.register();
ItemStackBridges.register();
LivingEntityBridges.register();
BlockStateBridges.register();
WorldBridges.register();
ItemSettingsBridges.register();
EntityBridges.register();
DamageSourceBridges.register();
TagBridges.register();
}
}

View File

@ -1,5 +1,6 @@
package com.thebrokenrail.scriptcraft.bridge;
package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
@ -8,7 +9,7 @@ import java.util.Locale;
class DamageSourceBridges {
static void register() {
Bridges.addBridge("DamageSource.create", args -> {
ScriptCraftCore.addBridge("DamageSource.create", args -> {
try {
String id = ((String) args[0]).toUpperCase(Locale.ROOT);
return DamageSource.class.getField(id).get(null);
@ -17,7 +18,7 @@ class DamageSourceBridges {
}
});
Bridges.addBridge("DamageSource.createFromPlayer", args -> DamageSource.player((PlayerEntity) args[1]));
Bridges.addBridge("DamageSource.createFromMob", args -> DamageSource.mob((LivingEntity) args[1]));
ScriptCraftCore.addBridge("DamageSource.createFromPlayer", args -> DamageSource.player((PlayerEntity) args[1]));
ScriptCraftCore.addBridge("DamageSource.createFromMob", args -> DamageSource.mob((LivingEntity) args[1]));
}
}

View File

@ -0,0 +1,57 @@
package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import com.thebrokenrail.scriptcraft.core.ValueUtil;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.registry.Registry;
import java.util.Objects;
class EntityBridges {
static void register() {
ScriptCraftCore.addBridge("Entity.getEntityWorld", args -> ((Entity) args[0]).getEntityWorld());
ScriptCraftCore.addBridge("Entity.getID", args -> Registry.ENTITY_TYPE.getId(((Entity) args[0]).getType()).toString());
ScriptCraftCore.addBridge("Entity.getName", args -> ((Entity) args[0]).getName().asString());
ScriptCraftCore.addBridge("Entity.getDisplayName", args -> ((Entity) args[0]).getDisplayName().asString());
ScriptCraftCore.addBridge("Entity.getCustomName", args -> ((Entity) args[0]).hasCustomName() ? Objects.requireNonNull(((Entity) args[0]).getCustomName()).asString() : null);
ScriptCraftCore.addBridge("Entity.kill", args -> {
((Entity) args[0]).kill();
return null;
});
ScriptCraftCore.addBridge("Entity.remove", args -> {
((Entity) args[0]).remove();
return null;
});
ScriptCraftCore.addBridge("Entity.damage", args -> ((Entity) args[0]).damage((DamageSource) args[1], (float) args[2]));
ScriptCraftCore.addBridge("Entity.setFireTicks", args -> {
((Entity) args[0]).setFireTicks((int) args[1]);
return null;
});
ScriptCraftCore.addBridge("Entity.getFireTicks", args -> ((Entity) args[0]).getFireTicks());
ScriptCraftCore.addBridge("Entity.getPosition", args -> {
Vec3d pos = ((Entity) args[0]).getPos();
Double[] out = new Double[3];
out[0] = pos.getX();
out[1] = pos.getY();
out[2] = pos.getZ();
return out;
});
ScriptCraftCore.addBridge("Entity.setPosition", args -> {
((Entity) args[0]).updatePosition(ValueUtil.toDouble(args[1], 0), ValueUtil.toDouble(args[2], 0), ValueUtil.toDouble(args[3], 0));
return null;
});
ScriptCraftCore.addBridge("Entity.toTag", args -> ((Entity) args[0]).toTag(new CompoundTag()));
ScriptCraftCore.addBridge("Entity.fromTag", args -> {
((Entity) args[0]).fromTag((CompoundTag) args[1]);
return null;
});
}
}

View File

@ -1,12 +1,13 @@
package com.thebrokenrail.scriptcraft.bridge;
package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.util.Rarity;
class ItemSettingsBridges {
static void register() {
Bridges.addBridge("ItemSettings.create", args -> {
ScriptCraftCore.addBridge("ItemSettings.create", args -> {
Item.Settings settings = new Item.Settings();
settings.maxCount(((Double) args[0]).intValue());

View File

@ -0,0 +1,38 @@
package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import com.thebrokenrail.scriptcraft.core.ValueUtil;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
class ItemStackBridges {
static void register() {
ScriptCraftCore.addBridge("ItemStack.create", args -> new ItemStack(Registry.ITEM.get(new Identifier((String) args[0])), ((Double) args[1]).intValue()));
ScriptCraftCore.addBridge("ItemStack.getItem", args -> Registry.ITEM.getId(((ItemStack) args[0]).getItem()).toString());
ScriptCraftCore.addBridge("ItemStack.setCount", args -> {
((ItemStack) args[0]).setCount((int) ValueUtil.toDouble(args[1], 0));
return null;
});
ScriptCraftCore.addBridge("ItemStack.getCount", args -> (double) ((ItemStack) args[0]).getCount());
ScriptCraftCore.addBridge("ItemStack.setDamage", args -> {
((ItemStack) args[0]).setDamage((int) ValueUtil.toDouble(args[1], 0));
return null;
});
ScriptCraftCore.addBridge("ItemStack.getDamage", args -> (double) ((ItemStack) args[0]).getDamage());
ScriptCraftCore.addBridge("ItemStack.isDamageable", args -> ((ItemStack) args[0]).isDamageable());
ScriptCraftCore.addBridge("ItemStack.getTag", args -> ((ItemStack) args[0]).getTag());
ScriptCraftCore.addBridge("ItemStack.setTag", args -> {
((ItemStack) args[0]).setTag((CompoundTag) args[1]);
return null;
});
ScriptCraftCore.addBridge("ItemStack.toTag", args -> ((ItemStack) args[0]).toTag(new CompoundTag()));
ScriptCraftCore.addBridge("ItemStack.fromTag", args -> ItemStack.fromTag((CompoundTag) args[1]));
}
}

View File

@ -0,0 +1,12 @@
package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Hand;
class LivingEntityBridges {
static void register() {
ScriptCraftCore.addBridge("LivingEntity.getStackInHand", args -> ((LivingEntity) args[0]).getStackInHand((Hand) args[1]));
ScriptCraftCore.addBridge("LivingEntity.getHealth", args -> ((LivingEntity) args[0]).getHealth());
}
}

View File

@ -1,9 +1,10 @@
package com.thebrokenrail.scriptcraft.bridge;
package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.api.CustomBlock;
import com.thebrokenrail.scriptcraft.api.CustomBlockEntity;
import com.thebrokenrail.scriptcraft.api.CustomBlockWithEntity;
import com.thebrokenrail.scriptcraft.api.CustomItem;
import com.thebrokenrail.scriptcraft.api.block.CustomBlock;
import com.thebrokenrail.scriptcraft.api.block.CustomBlockEntity;
import com.thebrokenrail.scriptcraft.api.block.CustomBlockWithEntity;
import com.thebrokenrail.scriptcraft.api.item.CustomItem;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import net.minecraft.block.Block;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.item.BlockItem;
@ -13,20 +14,20 @@ import net.minecraft.util.registry.Registry;
class RegistryBridge {
static void register() {
Bridges.addBridge("Registry.registerBlock", args -> {
ScriptCraftCore.addBridge("Registry.registerBlock", args -> {
Registry.register(Registry.BLOCK, new Identifier((String) args[0]), new CustomBlock((Block.Settings) args[1], new Identifier((String) args[0])));
return null;
});
Bridges.addBridge("Registry.registerBlockWithEntity", args -> {
ScriptCraftCore.addBridge("Registry.registerBlockWithEntity", args -> {
Registry.register(Registry.BLOCK, new Identifier((String) args[0]), new CustomBlockWithEntity((Block.Settings) args[1], new Identifier((String) args[0])));
Registry.register(Registry.BLOCK_ENTITY_TYPE, new Identifier((String) args[0]), BlockEntityType.Builder.create(() -> new CustomBlockEntity(Registry.BLOCK_ENTITY_TYPE.get(new Identifier((String) args[0])), new Identifier((String) args[0])), Registry.BLOCK.get(new Identifier((String) args[0]))).build(null));
return null;
});
Bridges.addBridge("Registry.registerItem", args -> {
ScriptCraftCore.addBridge("Registry.registerItem", args -> {
Registry.register(Registry.ITEM, new Identifier((String) args[0]), new CustomItem((Item.Settings) args[1], new Identifier((String) args[0])));
return null;
});
Bridges.addBridge("Registry.registerBlockItem", args -> {
ScriptCraftCore.addBridge("Registry.registerBlockItem", args -> {
Registry.register(Registry.ITEM, new Identifier((String) args[0]), new BlockItem(Registry.BLOCK.get(new Identifier((String) args[2])), (Item.Settings) args[1]));
return null;
});

View File

@ -1,6 +1,7 @@
package com.thebrokenrail.scriptcraft.bridge;
package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.util.Util;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import com.thebrokenrail.scriptcraft.core.ValueUtil;
import net.minecraft.nbt.AbstractListTag;
import net.minecraft.nbt.AbstractNumberTag;
import net.minecraft.nbt.ByteTag;
@ -74,37 +75,37 @@ class TagBridges {
}
static void register() {
Bridges.addBridge("CompoundTag.get", args -> {
ScriptCraftCore.addBridge("CompoundTag.get", args -> {
CompoundTag tag = (CompoundTag) args[0];
Tag obj = tag.get((String) args[1]);
return toOut(obj);
});
Bridges.addBridge("CompoundTag.set", args -> {
ScriptCraftCore.addBridge("CompoundTag.set", args -> {
CompoundTag tag = (CompoundTag) args[0];
tag.put((String) args[1], toTag(args[2], (String) args[3]));
return null;
});
Bridges.addBridge("CompoundTag.keys", args -> {
ScriptCraftCore.addBridge("CompoundTag.keys", args -> {
CompoundTag tag = (CompoundTag) args[0];
return tag.getKeys().toArray(new String[0]);
});
Bridges.addBridge("ListTag.get", args -> {
ScriptCraftCore.addBridge("ListTag.get", args -> {
AbstractListTag<?> tag = (AbstractListTag<?>) args[0];
Tag obj = tag.get((int) Util.toDouble(args[1], 0));
Tag obj = tag.get((int) ValueUtil.toDouble(args[1], 0));
return toOut(obj);
});
Bridges.addBridge("ListTag.set", args -> {
ScriptCraftCore.addBridge("ListTag.set", args -> {
AbstractListTag tag = (AbstractListTag) args[0];
tag.set((int) Util.toDouble(args[1], 0), toTag(args[2], (String) args[3]));
tag.set((int) ValueUtil.toDouble(args[1], 0), toTag(args[2], (String) args[3]));
return null;
});
Bridges.addBridge("ListTag.size", args -> {
ScriptCraftCore.addBridge("ListTag.size", args -> {
AbstractListTag<?> tag = (AbstractListTag<?>) args[0];
return tag.size();
});
Bridges.addBridge("CompoundTag.create", args -> new CompoundTag());
Bridges.addBridge("ListTag.create", args -> new ListTag());
ScriptCraftCore.addBridge("CompoundTag.create", args -> new CompoundTag());
ScriptCraftCore.addBridge("ListTag.create", args -> new ListTag());
}
}

View File

@ -0,0 +1,64 @@
package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.api.block.CustomBlockEntity;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import com.thebrokenrail.scriptcraft.core.ValueUtil;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
import java.util.Objects;
class WorldBridges {
static void register() {
ScriptCraftCore.addBridge("World.getBlockState", args -> ((World) args[0]).getBlockState(new BlockPos((double) args[1], (double) args[2], (double) args[3])));
ScriptCraftCore.addBridge("World.setBlockState", args -> ((World) args[0]).setBlockState(new BlockPos((double) args[1], (double) args[2], (double) args[3]), (BlockState) args[4]));
ScriptCraftCore.addBridge("World.spawnEntity", args -> {
Entity entity = Registry.ENTITY_TYPE.get(new Identifier((String) args[4])).create((World) args[0]);
if (entity != null) {
entity.updatePosition(ValueUtil.toDouble(args[1], 0), ValueUtil.toDouble(args[2], 0), ValueUtil.toDouble(args[3], 0));
((World) args[0]).spawnEntity(entity);
return entity;
} else {
return null;
}
});
ScriptCraftCore.addBridge("World.markBlockEntityDirty", args -> {
World world = (World) args[0];
BlockPos pos = new BlockPos(ValueUtil.toDouble(args[1], 0), ValueUtil.toDouble(args[2], 0), ValueUtil.toDouble(args[3], 0));
BlockEntity entity = world.getBlockEntity(pos);
if (entity != null) {
entity.markDirty();
}
return null;
});
ScriptCraftCore.addBridge("World.getBlockEntity", args -> {
World world = (World) args[0];
BlockPos pos = new BlockPos(ValueUtil.toDouble(args[1], 0), ValueUtil.toDouble(args[2], 0), ValueUtil.toDouble(args[3], 0));
BlockEntity entity = world.getBlockEntity(pos);
if (entity != null) {
return Objects.requireNonNull(Registry.BLOCK_ENTITY_TYPE.getId(entity.getType())).toString();
} else {
return null;
}
});
ScriptCraftCore.addBridge("World.getCustomBlockEntity", args -> {
World world = (World) args[0];
BlockPos pos = new BlockPos(ValueUtil.toDouble(args[1], 0), ValueUtil.toDouble(args[2], 0), ValueUtil.toDouble(args[3], 0));
BlockEntity entity = world.getBlockEntity(pos);
if (entity instanceof CustomBlockEntity) {
return ((CustomBlockEntity) entity).getObjID();
} else {
return null;
}
});
}
}

View File

@ -1,7 +1,7 @@
package com.thebrokenrail.scriptcraft.api;
package com.thebrokenrail.scriptcraft.api.item;
import com.thebrokenrail.scriptcraft.util.Util;
import com.thebrokenrail.scriptcraft.quickjs.QuickJSManager;
import com.thebrokenrail.scriptcraft.core.ValueUtil;
import com.thebrokenrail.scriptcraft.core.quickjs.QuickJSManager;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
@ -24,17 +24,17 @@ public class CustomItem extends Item {
@Override
public TypedActionResult<ItemStack> use(World world, PlayerEntity user, Hand hand) {
ItemStack stack = user.getStackInHand(hand);
ActionResult result = Util.getEnumValue(ActionResult.class, (String) QuickJSManager.bridge("CustomItem.onUse", id.toString(), world, user, hand.name()), ActionResult.PASS);
ActionResult result = ValueUtil.getEnumValue(ActionResult.class, (String) QuickJSManager.bridge("CustomItem.onUse", id.toString(), world, user, hand.name()), ActionResult.PASS);
return new TypedActionResult<>(result, stack);
}
@Override
public ActionResult useOnBlock(ItemUsageContext context) {
return Util.getEnumValue(ActionResult.class, (String) QuickJSManager.bridge("CustomItem.onUseOnBlock", id.toString(), context.getWorld(), (double) context.getBlockPos().getX(), (double) context.getBlockPos().getY(), (double) context.getBlockPos().getZ(), context.getSide().name(), context.getPlayer(), context.getHand().name()), ActionResult.PASS);
return ValueUtil.getEnumValue(ActionResult.class, (String) QuickJSManager.bridge("CustomItem.onUseOnBlock", id.toString(), context.getWorld(), (double) context.getBlockPos().getX(), (double) context.getBlockPos().getY(), (double) context.getBlockPos().getZ(), context.getSide().name(), context.getPlayer(), context.getHand().name()), ActionResult.PASS);
}
@Override
public boolean useOnEntity(ItemStack stack, PlayerEntity user, LivingEntity entity, Hand hand) {
return Util.toBoolean(QuickJSManager.bridge("CustomItem.onUseOnEntity", id.toString(), user, entity, hand.name()), false);
return ValueUtil.toBoolean(QuickJSManager.bridge("CustomItem.onUseOnEntity", id.toString(), user, entity, hand.name()), false);
}
}

View File

@ -1,12 +0,0 @@
package com.thebrokenrail.scriptcraft.bridge;
import net.minecraft.block.BlockState;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
class BlockStateBridges {
static void register() {
Bridges.addBridge("BlockState.getDefaultState", args -> Registry.BLOCK.get(new Identifier((String) args[0])).getDefaultState());
Bridges.addBridge("BlockState.getBlock", args -> Registry.BLOCK.getId(((BlockState) args[0]).getBlock()).toString());
}
}

View File

@ -1,42 +0,0 @@
package com.thebrokenrail.scriptcraft.bridge;
import com.thebrokenrail.scriptcraft.quickjs.QuickJS;
import com.thebrokenrail.scriptcraft.quickjs.QuickJSManager;
import java.util.HashMap;
@SuppressWarnings("unused")
public class Bridges {
private static final HashMap<String, Bridge> bridges = new HashMap<>();
public static void addBridge(String name, Bridge bridge) {
bridges.put(name, bridge);
}
public static Object useBridge(String name, Object... args) {
QuickJSManager.Task task = new QuickJSManager.Task() {
@Override
protected Object run(QuickJS quickjs) {
if (bridges.containsKey(name)) {
return bridges.get(name).use(args);
} else {
throw new RuntimeException("Invalid Bridge: '" + name + '\'');
}
}
};
return QuickJSManager.sendTaskFromQuickJS(task);
}
static {
BlockSettingsBridges.register();
RegistryBridge.register();
ItemStackBridges.register();
LivingEntityBridges.register();
BlockStateBridges.register();
WorldBridges.register();
ItemSettingsBridges.register();
EntityBridges.register();
DamageSourceBridges.register();
TagBridges.register();
}
}

View File

@ -1,56 +0,0 @@
package com.thebrokenrail.scriptcraft.bridge;
import com.thebrokenrail.scriptcraft.util.Util;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.registry.Registry;
import java.util.Objects;
class EntityBridges {
static void register() {
Bridges.addBridge("Entity.getEntityWorld", args -> ((Entity) args[0]).getEntityWorld());
Bridges.addBridge("Entity.getID", args -> Registry.ENTITY_TYPE.getId(((Entity) args[0]).getType()).toString());
Bridges.addBridge("Entity.getName", args -> ((Entity) args[0]).getName().asString());
Bridges.addBridge("Entity.getDisplayName", args -> ((Entity) args[0]).getDisplayName().asString());
Bridges.addBridge("Entity.getCustomName", args -> ((Entity) args[0]).hasCustomName() ? Objects.requireNonNull(((Entity) args[0]).getCustomName()).asString() : null);
Bridges.addBridge("Entity.kill", args -> {
((Entity) args[0]).kill();
return null;
});
Bridges.addBridge("Entity.remove", args -> {
((Entity) args[0]).remove();
return null;
});
Bridges.addBridge("Entity.damage", args -> ((Entity) args[0]).damage((DamageSource) args[1], (float) args[2]));
Bridges.addBridge("Entity.setFireTicks", args -> {
((Entity) args[0]).setFireTicks((int) args[1]);
return null;
});
Bridges.addBridge("Entity.getFireTicks", args -> ((Entity) args[0]).getFireTicks());
Bridges.addBridge("Entity.getPosition", args -> {
Vec3d pos = ((Entity) args[0]).getPos();
Double[] out = new Double[3];
out[0] = pos.getX();
out[1] = pos.getY();
out[2] = pos.getZ();
return out;
});
Bridges.addBridge("Entity.setPosition", args -> {
((Entity) args[0]).updatePosition(Util.toDouble(args[1], 0), Util.toDouble(args[2], 0), Util.toDouble(args[3], 0));
return null;
});
Bridges.addBridge("Entity.toTag", args -> ((Entity) args[0]).toTag(new CompoundTag()));
Bridges.addBridge("Entity.fromTag", args -> {
((Entity) args[0]).fromTag((CompoundTag) args[1]);
return null;
});
}
}

View File

@ -1,37 +0,0 @@
package com.thebrokenrail.scriptcraft.bridge;
import com.thebrokenrail.scriptcraft.util.Util;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
class ItemStackBridges {
static void register() {
Bridges.addBridge("ItemStack.create", args -> new ItemStack(Registry.ITEM.get(new Identifier((String) args[0])), ((Double) args[1]).intValue()));
Bridges.addBridge("ItemStack.getItem", args -> Registry.ITEM.getId(((ItemStack) args[0]).getItem()).toString());
Bridges.addBridge("ItemStack.setCount", args -> {
((ItemStack) args[0]).setCount((int) Util.toDouble(args[1], 0));
return null;
});
Bridges.addBridge("ItemStack.getCount", args -> (double) ((ItemStack) args[0]).getCount());
Bridges.addBridge("ItemStack.setDamage", args -> {
((ItemStack) args[0]).setDamage((int) Util.toDouble(args[1], 0));
return null;
});
Bridges.addBridge("ItemStack.getDamage", args -> (double) ((ItemStack) args[0]).getDamage());
Bridges.addBridge("ItemStack.isDamageable", args -> ((ItemStack) args[0]).isDamageable());
Bridges.addBridge("ItemStack.getTag", args -> ((ItemStack) args[0]).getTag());
Bridges.addBridge("ItemStack.setTag", args -> {
((ItemStack) args[0]).setTag((CompoundTag) args[1]);
return null;
});
Bridges.addBridge("ItemStack.toTag", args -> ((ItemStack) args[0]).toTag(new CompoundTag()));
Bridges.addBridge("ItemStack.fromTag", args -> ItemStack.fromTag((CompoundTag) args[1]));
}
}

View File

@ -1,11 +0,0 @@
package com.thebrokenrail.scriptcraft.bridge;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.Hand;
class LivingEntityBridges {
static void register() {
Bridges.addBridge("LivingEntity.getStackInHand", args -> ((LivingEntity) args[0]).getStackInHand((Hand) args[1]));
Bridges.addBridge("LivingEntity.getHealth", args -> ((LivingEntity) args[0]).getHealth());
}
}

View File

@ -1,51 +0,0 @@
package com.thebrokenrail.scriptcraft.bridge;
import com.thebrokenrail.scriptcraft.util.Util;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.World;
import java.util.Objects;
class WorldBridges {
static void register() {
Bridges.addBridge("World.getBlockState", args -> ((World) args[0]).getBlockState(new BlockPos((double) args[1], (double) args[2], (double) args[3])));
Bridges.addBridge("World.setBlockState", args -> ((World) args[0]).setBlockState(new BlockPos((double) args[1], (double) args[2], (double) args[3]), (BlockState) args[4]));
Bridges.addBridge("World.spawnEntity", args -> {
Entity entity = Registry.ENTITY_TYPE.get(new Identifier((String) args[4])).create((World) args[0]);
if (entity != null) {
entity.updatePosition(Util.toDouble(args[1], 0), Util.toDouble(args[2], 0), Util.toDouble(args[3], 0));
((World) args[0]).spawnEntity(entity);
return entity;
} else {
return null;
}
});
Bridges.addBridge("World.markBlockEntityDirty", args -> {
World world = (World) args[0];
BlockPos pos = new BlockPos(Util.toDouble(args[1], 0), Util.toDouble(args[2], 0), Util.toDouble(args[3], 0));
BlockEntity entity = world.getBlockEntity(pos);
if (entity != null) {
entity.markDirty();
}
return null;
});
Bridges.addBridge("World.getBlockEntity", args -> {
World world = (World) args[0];
BlockPos pos = new BlockPos(Util.toDouble(args[1], 0), Util.toDouble(args[2], 0), Util.toDouble(args[3], 0));
BlockEntity entity = world.getBlockEntity(pos);
if (entity != null) {
return Objects.requireNonNull(Registry.BLOCK_ENTITY_TYPE.getId(entity.getType())).toString();
} else {
return null;
}
});
}
}

View File

@ -1,4 +1,4 @@
package com.thebrokenrail.scriptcraft.bridge;
package com.thebrokenrail.scriptcraft.core;
public interface Bridge {
Object use(Object... args);

View File

@ -1,4 +1,4 @@
package com.thebrokenrail.scriptcraft.util;
package com.thebrokenrail.scriptcraft.core;
import java.util.Locale;

View File

@ -0,0 +1,54 @@
package com.thebrokenrail.scriptcraft.core;
import com.thebrokenrail.scriptcraft.core.quickjs.QuickJSNative;
import com.thebrokenrail.scriptcraft.core.quickjs.QuickJSManager;
import net.fabricmc.loader.api.FabricLoader;
import java.util.HashMap;
import java.util.List;
import java.util.regex.Pattern;
@SuppressWarnings("unused")
public class ScriptCraftCore {
private static final HashMap<String, Bridge> bridges = new HashMap<>();
public static void addBridge(String name, Bridge bridge) {
bridges.put(name, bridge);
}
public static Object useBridge(String name, Object... args) {
QuickJSManager.Task task = new QuickJSManager.Task() {
@Override
protected Object run(QuickJSNative quickjs) {
if (bridges.containsKey(name)) {
return bridges.get(name).use(args);
} else {
throw new RuntimeException("Invalid Bridge: '" + name + '\'');
}
}
};
return QuickJSManager.sendTaskFromQuickJS(task);
}
public static final String NAMESPACE = "scriptcraft";
public static final Pattern MOD_ID_PATTERN = Pattern.compile("[a-z][a-z0-9-_]{1,63}");
public static void init() {
QuickJSManager.init(new QuickJSManager.Task() {
@Override
protected Object run(QuickJSNative quickjs) {
List<ScriptCraftEntrypoint> mods = FabricLoader.getInstance().getEntrypoints(NAMESPACE, ScriptCraftEntrypoint.class);
for (ScriptCraftEntrypoint mod : mods) {
if (MOD_ID_PATTERN.matcher(mod.getModID()).matches()) {
if (mod.shouldAutoLoad()) {
quickjs.run("import '" + mod.getModID() + "';");
}
} else {
throw new RuntimeException("Invalid Mod ID: " + mod.getModID());
}
}
return null;
}
});
}
}

View File

@ -1,4 +1,4 @@
package com.thebrokenrail.scriptcraft.util;
package com.thebrokenrail.scriptcraft.core;
public interface ScriptCraftEntrypoint {
String getModID();

View File

@ -1,9 +1,9 @@
package com.thebrokenrail.scriptcraft.util;
package com.thebrokenrail.scriptcraft.core;
import java.util.Locale;
@SuppressWarnings("UnnecessaryUnboxing")
public class Util {
public class ValueUtil {
public static <T extends Enum<T>> T getEnumValue(Class<T> clazz, String value, T defaultValue) {
try {
return Enum.valueOf(clazz, value.toUpperCase(Locale.ROOT));

View File

@ -1,4 +1,4 @@
package com.thebrokenrail.scriptcraft.quickjs;
package com.thebrokenrail.scriptcraft.core.quickjs;
public class JSException extends Exception {
public JSException(String message) {

View File

@ -1,10 +1,10 @@
package com.thebrokenrail.scriptcraft.quickjs;
package com.thebrokenrail.scriptcraft.core.quickjs;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
public class QuickJSManager {
private static QuickJS quickjs;
private static QuickJSNative quickjs;
public static abstract class Task {
private boolean lastTask = false;
@ -12,7 +12,7 @@ public class QuickJSManager {
private boolean err;
private Object obj;
protected abstract Object run(QuickJS quickjs) throws JSException;
protected abstract Object run(QuickJSNative quickjs) throws JSException;
}
private static Thread thread;
@ -83,7 +83,7 @@ public class QuickJSManager {
private void init() {
try {
quickjs = new QuickJS();
quickjs = new QuickJSNative();
synchronized (startedLock) {
startedLock.notifyAll();
}
@ -124,7 +124,7 @@ public class QuickJSManager {
started.set(false);
Task task = new Task() {
@Override
protected Object run(QuickJS quickjs) {
protected Object run(QuickJSNative quickjs) {
System.out.println("Freeing QuickJS");
quickjs.free();
return null;
@ -181,7 +181,7 @@ public class QuickJSManager {
public static Object bridge(String method, Object... args) {
Task task = new Task() {
@Override
protected Object run(QuickJS quickjs) throws JSException {
protected Object run(QuickJSNative quickjs) throws JSException {
return quickjs.bridge(method, args);
}
};

View File

@ -1,8 +1,7 @@
package com.thebrokenrail.scriptcraft.quickjs;
package com.thebrokenrail.scriptcraft.core.quickjs;
import com.thebrokenrail.scriptcraft.ScriptCraft;
import com.thebrokenrail.scriptcraft.util.OSUtil;
import com.thebrokenrail.scriptcraft.util.ScriptCraftEntrypoint;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import com.thebrokenrail.scriptcraft.core.ScriptCraftEntrypoint;
import net.fabricmc.loader.api.FabricLoader;
import java.io.BufferedReader;
@ -11,50 +10,17 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Arrays;
import java.util.List;
@SuppressWarnings("unused")
public class QuickJS {
public QuickJS() throws JSException {
init();
}
private long ctx;
private long rt;
public native void init() throws JSException;
public native void free();
public native Object bridge(String method, Object... args) throws JSException;
public native void run(String data);
static {
try {
File file = File.createTempFile("lib" + ScriptCraft.NAMESPACE, OSUtil.getLibExtension());
file.deleteOnExit();
System.out.println("Extracting ScriptCraft Native To: " + file.getAbsoluteFile().toPath());
InputStream so = (QuickJS.class.getResourceAsStream(File.separator + "natives" + File.separator + OSUtil.getOS() + File.separator + "lib" + ScriptCraft.NAMESPACE + OSUtil.getLibExtension()));
if (so == null) {
throw new RuntimeException("ScriptCraft does not support your OS: " + OSUtil.getOS());
} else {
Files.copy(so, file.getAbsoluteFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
System.load(file.getAbsolutePath());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public class QuickJSModules {
public static String loadModule(String name) {
String[] arr = name.split(File.separator, 2);
if (ScriptCraft.MOD_ID_PATTERN.matcher(arr[0]).matches()) {
List<ScriptCraftEntrypoint> mods = FabricLoader.getInstance().getEntrypoints(ScriptCraft.NAMESPACE, ScriptCraftEntrypoint.class);
if (ScriptCraftCore.MOD_ID_PATTERN.matcher(arr[0]).matches()) {
List<ScriptCraftEntrypoint> mods = FabricLoader.getInstance().getEntrypoints(ScriptCraftCore.NAMESPACE, ScriptCraftEntrypoint.class);
if (arr.length == 1) {
return null;
} else {
@ -62,7 +28,7 @@ public class QuickJS {
if (mod.getModID().equals(arr[0])) {
//noinspection CatchMayIgnoreException
try {
InputStream stream = mod.getClass().getResourceAsStream(File.separator + ScriptCraft.NAMESPACE + File.separator + arr[0] + File.separator + arr[1]);
InputStream stream = mod.getClass().getResourceAsStream(File.separator + ScriptCraftCore.NAMESPACE + File.separator + arr[0] + File.separator + arr[1]);
if (stream != null) {
StringBuilder textBuilder = new StringBuilder();
@ -86,8 +52,13 @@ public class QuickJS {
}
private static final String[] SUPPORTED_EXTENSION = new String[]{"", ".js", ".json", ".mjs"};
private static final String[] BUILTIN_MODULES = new String[]{"scriptcraft-core"};
public static String normalizeModule(String baseName, String name) {
if (Arrays.asList(BUILTIN_MODULES).contains(name)) {
return name;
}
String normalizedPath;
if (name.startsWith(".")) {
@ -107,8 +78,8 @@ public class QuickJS {
boolean success = false;
String[] arr = normalizedPath.split(File.separator, 2);
if (ScriptCraft.MOD_ID_PATTERN.matcher(arr[0]).matches()) {
List<ScriptCraftEntrypoint> mods = FabricLoader.getInstance().getEntrypoints(ScriptCraft.NAMESPACE, ScriptCraftEntrypoint.class);
if (ScriptCraftCore.MOD_ID_PATTERN.matcher(arr[0]).matches()) {
List<ScriptCraftEntrypoint> mods = FabricLoader.getInstance().getEntrypoints(ScriptCraftCore.NAMESPACE, ScriptCraftEntrypoint.class);
if (arr.length == 1) {
for (ScriptCraftEntrypoint mod : mods) {
if (mod.getModID().equals(arr[0])) {
@ -133,15 +104,4 @@ public class QuickJS {
return null;
}
public static void print(String data, boolean err) {
String[] lines = data.split("\n");
for (String line : lines) {
if (err) {
System.err.println(line);
} else {
System.out.println(line);
}
}
}
}

View File

@ -0,0 +1,56 @@
package com.thebrokenrail.scriptcraft.core.quickjs;
import com.thebrokenrail.scriptcraft.core.OSUtil;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
@SuppressWarnings("unused")
public class QuickJSNative {
public QuickJSNative() throws JSException {
init();
}
private long ctx;
private long rt;
public native void init() throws JSException;
public native void free();
public native Object bridge(String method, Object... args) throws JSException;
public native void run(String data);
static {
try {
File file = File.createTempFile("lib" + ScriptCraftCore.NAMESPACE, OSUtil.getLibExtension());
file.deleteOnExit();
System.out.println("Extracting ScriptCraft Native To: " + file.getAbsoluteFile().toPath());
InputStream so = (QuickJSNative.class.getResourceAsStream(File.separator + "natives" + File.separator + OSUtil.getOS() + File.separator + "lib" + ScriptCraftCore.NAMESPACE + OSUtil.getLibExtension()));
if (so == null) {
throw new RuntimeException("ScriptCraft does not support your OS: " + OSUtil.getOS());
} else {
Files.copy(so, file.getAbsoluteFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
System.load(file.getAbsolutePath());
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static void print(String data, boolean err) {
String[] lines = data.split("\n");
for (String line : lines) {
if (err) {
System.err.println(line);
} else {
System.out.println(line);
}
}
}
}

View File

@ -1,18 +0,0 @@
package com.thebrokenrail.scriptcraft.util;
public class MinecraftAPIEntrypoint implements ScriptCraftEntrypoint {
@Override
public String getModID() {
return "minecraft";
}
@Override
public String getModIndex() {
return "index";
}
@Override
public boolean shouldAutoLoad() {
return false;
}
}

View File

@ -20,7 +20,7 @@
"com.thebrokenrail.scriptcraft.ScriptCraft"
],
"scriptcraft": [
"com.thebrokenrail.scriptcraft.util.MinecraftAPIEntrypoint",
"com.thebrokenrail.scriptcraft.api.ScriptCraftAPI",
"com.thebrokenrail.scriptcraft.Demo"
]
},

View File

@ -4,5 +4,5 @@
"semi": true,
"singleQuote": true,
"arrowParens": "avoid",
"printWidth": 2400
"printWidth": 24000
}

View File

@ -1,7 +1,8 @@
import { World } from './world';
import { PlayerEntity } from './entity';
import { useBridge, addBridge, Identifier, Hand, Pos, ActionResult, Direction, SimpleRegistry } from './core';
import { Identifier, Hand, Pos, ActionResult, Direction, SimpleRegistry } from './core';
import { CompoundTag } from './tag';
import { useBridge, addBridge } from 'scriptcraft-core';
/**
* Settings for {@link CustomBlock}
@ -233,11 +234,11 @@ export class BlockRegistry implements SimpleRegistry<CustomBlock> {
#blocks: Map<string, CustomBlock>;
#blockEntities: Map<string, CustomBlockEntity[]>;
#blockEntities: CustomBlockEntity[];
private constructor() {
this.#blocks = new Map<string, CustomBlock>();
this.#blockEntities = new Map<string, CustomBlockEntity[]>();
this.#blockEntities = [];
}
register(id: Identifier, obj: CustomBlock) {
@ -262,29 +263,21 @@ export class BlockRegistry implements SimpleRegistry<CustomBlock> {
return null;
}
getCustomBlockEntity(id: Identifier, i: number): CustomBlockEntity {
return this.#blockEntities.get(id.toString())[i];
getCustomBlockEntity(i: number): CustomBlockEntity {
return this.#blockEntities[i];
}
getCustomBlockEntities(): CustomBlockEntity[] {
let out: CustomBlockEntity[] = [];
for (const key of this.#blockEntities.keys()) {
const list = this.#blockEntities.get(key);
out = out.concat(list);
}
return out;
return this.#blockEntities;
}
createCustomBlockEntity(id: Identifier, i: number) {
const block = this.get(id) as CustomBlockWithEntity;
if (!this.#blockEntities.get(id.toString())) {
this.#blockEntities.set(id.toString(), []);
}
this.#blockEntities.get(id.toString()).push(block.createBlockEntity());
this.#blockEntities[this.#blockEntities.length] = (block.createBlockEntity());
}
freeCustomBlockEntity(id: Identifier, i: number) {
delete this.#blockEntities.get(id.toString())[i];
freeCustomBlockEntity(i: number) {
delete this.#blockEntities[i];
}
}
@ -292,27 +285,25 @@ addBridge('CustomBlockEntity.create', (id: string, i: number) => {
BlockRegistry.INSTANCE.createCustomBlockEntity(new Identifier(id), i);
});
addBridge('CustomBlockEntity.fromTag', (id: string, i: number, tag: JavaObject) => {
BlockRegistry.INSTANCE.getCustomBlockEntity(new Identifier(id), i).fromTag(new CompoundTag(tag));
addBridge('CustomBlockEntity.fromTag', (i: number, tag: JavaObject) => {
BlockRegistry.INSTANCE.getCustomBlockEntity(i).fromTag(new CompoundTag(tag));
});
addBridge(
'CustomBlockEntity.toTag',
(id: string, i: number, tag: JavaObject): JavaObject => {
return BlockRegistry.INSTANCE.getCustomBlockEntity(new Identifier(id), i).toTag(new CompoundTag(tag)).javaObject;
addBridge('CustomBlockEntity.toTag', ( i: number, tag: JavaObject): JavaObject => {
return BlockRegistry.INSTANCE.getCustomBlockEntity(i).toTag(new CompoundTag(tag)).javaObject;
}
);
addBridge('CustomBlockEntity.tick', (id: string, i: number) => {
BlockRegistry.INSTANCE.getCustomBlockEntity(new Identifier(id), i).tick();
addBridge('CustomBlockEntity.tick', (i: number) => {
BlockRegistry.INSTANCE.getCustomBlockEntity(i).tick();
});
addBridge('CustomBlockEntity.setLocation', (id: string, i: number, world: JavaObject, x: number, y: number, z: number) => {
BlockRegistry.INSTANCE.getCustomBlockEntity(new Identifier(id), i).setLocation(new World(world), new Pos(x, y, z));
addBridge('CustomBlockEntity.setLocation', (i: number, world: JavaObject, x: number, y: number, z: number) => {
BlockRegistry.INSTANCE.getCustomBlockEntity(i).setLocation(new World(world), new Pos(x, y, z));
});
addBridge('CustomBlockEntity.free', (id: string, i: number) => {
BlockRegistry.INSTANCE.freeCustomBlockEntity(new Identifier(id), i);
addBridge('CustomBlockEntity.free', (i: number) => {
BlockRegistry.INSTANCE.freeCustomBlockEntity(i);
});
addBridge('CustomBlock.onUse', (id: string, world: JavaObject, state: JavaObject, x: number, y: number, z: number, side: keyof typeof Direction, player: JavaObject, hand: keyof typeof Hand): string => {

View File

@ -1,17 +1,3 @@
/**
* @internal
*/
export function addBridge(name: string, bridge: BridgeType) {
__scriptcraft__.bridges[name] = bridge;
}
/**
* @internal
*/
export function useBridge(name: string, ...args: BridgeValueType[]): BridgeValueType {
return __scriptcraft__.useBridge(name, ...args);
}
/**
* Action Result
*/

View File

@ -1,7 +1,8 @@
import { ItemStack } from './item';
import { useBridge, Hand, Identifier, Pos } from './core';
import { Hand, Identifier, Pos } from './core';
import { World } from './world';
import { CompoundTag } from './tag';
import { useBridge } from 'scriptcraft-core';
/**
* Damage Source

View File

@ -1,7 +1,8 @@
import { useBridge, Identifier, Hand, ActionResult, addBridge, Pos, Direction, SimpleRegistry } from './core';
import { Identifier, Hand, ActionResult, Pos, Direction, SimpleRegistry } from './core';
import { World } from './world';
import { PlayerEntity, LivingEntity } from './entity';
import { CompoundTag } from './tag';
import { useBridge, addBridge } from 'scriptcraft-core';
/**
* Item Stack

View File

@ -1,6 +1,6 @@
import { Identifier, SimpleRegistry } from './core';
import { BlockRegistry } from './block';
import { ItemRegistry } from './item';
import { BlockRegistry, CustomBlock } from './block';
import { ItemRegistry, CustomItem, BlockItem } from './item';
/**
* Registry
@ -9,11 +9,11 @@ export abstract class Registry {
/**
* Block Registry
*/
static BLOCK = BlockRegistry.INSTANCE;
static BLOCK: SimpleRegistry<CustomBlock> = BlockRegistry.INSTANCE;
/**
* Item Registry
*/
static ITEM = ItemRegistry.INSTANCE;
static ITEM: SimpleRegistry<CustomItem | BlockItem> = ItemRegistry.INSTANCE;
/**
* Register Object

View File

@ -1,4 +1,4 @@
import { useBridge } from './core';
import { useBridge } from 'scriptcraft-core';
type TagType = number | boolean | string | CompoundTag | ListTag;

View File

@ -1,6 +1,7 @@
import { BlockState, CustomBlockEntity, BlockRegistry } from './block';
import { Entity } from './entity';
import { useBridge, Pos, Identifier } from './core';
import { Pos, Identifier } from './core';
import { useBridge } from 'scriptcraft-core';
/**
* World
@ -56,26 +57,18 @@ export class World {
}
}
/**
* @internal
*/
private getCustomBlockEntities(): CustomBlockEntity[] {
return BlockRegistry.INSTANCE.getCustomBlockEntities();
}
/**
* Get Custom Block Entity At Position
* @param pos Position
* @returns Custom Block Entity At Position
*/
getCustomBlockEntity(pos: Pos): CustomBlockEntity {
const list = this.getCustomBlockEntities();
for (const entity of list) {
if (pos.equals(entity.getPos())) {
return entity;
}
const obj = useBridge('World.getBlockEntity', this.javaObject, pos.getX(), pos.getY(), pos.getZ()) as number;
if (obj) {
return BlockRegistry.INSTANCE.getCustomBlockEntity(obj);
} else {
return null;
}
return null;
}
/**

View File

@ -3,7 +3,7 @@ import { BlockSettings, Identifier, Registry, BlockState, ActionResult, World, P
console.log('hello');
class MyBlockEntity extends CustomBlockEntity {
ticks: number;
ticks = 0;
toTag(tag: CompoundTag): CompoundTag {
tag.set('MyTicks', this.ticks, NumberType.INT);

View File

@ -15,6 +15,6 @@
}
},
"include": [
"**/*.ts"
"**/*"
]
}

View File

@ -2,8 +2,8 @@
"name": "ScriptCraft API",
"mode": "modules",
"readme": "none",
"excludeExternals": true,
"excludeNotExported": true,
"excludePrivate": true,
"excludeExternals": true,
"stripInternal": true
}

View File

@ -26,3 +26,9 @@ interface Console {
}
declare const console: Console;
declare module 'scriptcraft-core' {
function addBridge(name: string, bridge: BridgeType): void;
function useBridge(name: string, ...args: BridgeValueType[]): BridgeValueType;
}