Update Docs
All checks were successful
ScriptCraft/pipeline/head This commit looks good

This commit is contained in:
TheBrokenRail 2020-06-02 13:24:32 -04:00
parent 1acb26caeb
commit 8c356af7a2
21 changed files with 361 additions and 251 deletions

View File

@ -0,0 +1,7 @@
# Java Object Wrappers
When the JS environment receives a Java object through a [bridge](BRIDGES.md), it is converted into a ```JavaObject```. A ```JavaObject``` cannot be used directly in the JS environment, but it can be stored and passed back to the Java environment using another [bridge](BRIDGES.md).
To make interacting wit Java object easier, they are placed in a wrapper class. An example of a wrapper class is ```World```, it can be interacted with like any other JS object, but internally it uses its ```JavaObject``` to execute code in the Java environment.
## Casting
In Java, if you are given a ```LivingEntity```, you can use ```instanceof``` to check if it is a ```PlayerEntity``` and then cast it. However, because the JS environment only knows the class of the ```JavaObject```'s wrapper, it can't do this. However, you can manually cast a JS object wrapper to another wrapper type using the new wrapper type's constructor, like ```new PlayerEntity(livingEntity);```, if this operation is not possible (ie. The ```LivingEntity``` is not a ```PlayerEntity```), it will throw an ```Error```.

View File

@ -7,6 +7,8 @@
[View Architecture](ARCHITECTURE.md) [View Architecture](ARCHITECTURE.md)
[View Java Object Wrappers](JAVA_OBJECT_WRAPPERS.md)
[View Tutorials](tutorials/README.md) [View Tutorials](tutorials/README.md)
[View TypeDoc](https://jenkins.thebrokenrail.com/job/ScriptCraft/job/master/TypeDoc/) [View TypeDoc](https://jenkins.thebrokenrail.com/job/ScriptCraft/job/master/TypeDoc/)

View File

@ -11,6 +11,19 @@
static JavaVM *jvm; static JavaVM *jvm;
static const jint JNI_VERSION = JNI_VERSION_1_6;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
jvm = vm;
JNIEnv *env = NULL;
if (jvm && (*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION) == JNI_OK) {
return JNI_VERSION;
} else {
return -1;
}
}
static void *get_pointer(JNIEnv *env, jobject obj, const char *name) { static void *get_pointer(JNIEnv *env, jobject obj, const char *name) {
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSNative"); jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSNative");
jfieldID field = (*env)->GetFieldID(env, clazz, name, "J"); jfieldID field = (*env)->GetFieldID(env, clazz, name, "J");
@ -25,7 +38,7 @@ static void set_pointer(JNIEnv *env, jobject obj, const char *name, void *value)
static char *js_module_normalize_name(JSContext *ctx, const char *base_name, const char *name, void *opaque) { static char *js_module_normalize_name(JSContext *ctx, const char *base_name, const char *name, void *opaque) {
JNIEnv *env; JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); (*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION);
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSModules"); 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;"); jmethodID methodID = (*env)->GetStaticMethodID(env, clazz, "normalizeModule", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
@ -43,7 +56,6 @@ static char *js_module_normalize_name(JSContext *ctx, const char *base_name, con
(*env)->DeleteLocalRef(env, java_string); (*env)->DeleteLocalRef(env, java_string);
(*jvm)->DetachCurrentThread(jvm);
return new_string; return new_string;
} else { } else {
jthrowable err = (*env)->ExceptionOccurred(env); jthrowable err = (*env)->ExceptionOccurred(env);
@ -54,11 +66,11 @@ static char *js_module_normalize_name(JSContext *ctx, const char *base_name, con
JS_ThrowReferenceError(ctx, "could not normalize module name '%s': %s", name, str); JS_ThrowReferenceError(ctx, "could not normalize module name '%s': %s", name, str);
(*env)->ReleaseStringUTFChars(env, java_string, str);
(*env)->ExceptionClear(env); (*env)->ExceptionClear(env);
} else { } else {
JS_ThrowReferenceError(ctx, "could not normalize module name '%s'", name); JS_ThrowReferenceError(ctx, "could not normalize module name '%s'", name);
} }
(*jvm)->DetachCurrentThread(jvm);
return NULL; return NULL;
} }
} }
@ -97,7 +109,7 @@ static int js_module_set_import_meta(JSContext *ctx, JSValueConst func_val, JS_B
static char *js_load_file(JSContext *ctx, const char *filename) { static char *js_load_file(JSContext *ctx, const char *filename) {
JNIEnv *env; JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); (*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION);
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSModules"); jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSModules");
jmethodID methodID = (*env)->GetStaticMethodID(env, clazz, "loadModule", "(Ljava/lang/String;)Ljava/lang/String;"); jmethodID methodID = (*env)->GetStaticMethodID(env, clazz, "loadModule", "(Ljava/lang/String;)Ljava/lang/String;");
@ -113,7 +125,6 @@ static char *js_load_file(JSContext *ctx, const char *filename) {
(*env)->DeleteLocalRef(env, java_string); (*env)->DeleteLocalRef(env, java_string);
(*jvm)->DetachCurrentThread(jvm);
return new_string; return new_string;
} else { } else {
jthrowable err = (*env)->ExceptionOccurred(env); jthrowable err = (*env)->ExceptionOccurred(env);
@ -124,11 +135,11 @@ static char *js_load_file(JSContext *ctx, const char *filename) {
JS_ThrowReferenceError(ctx, "could not load module filename '%s': %s", filename, str); JS_ThrowReferenceError(ctx, "could not load module filename '%s': %s", filename, str);
(*env)->ReleaseStringUTFChars(env, java_string, str);
(*env)->ExceptionClear(env); (*env)->ExceptionClear(env);
} else { } else {
JS_ThrowReferenceError(ctx, "could not load module filename '%s'", filename); JS_ThrowReferenceError(ctx, "could not load module filename '%s'", filename);
} }
(*jvm)->DetachCurrentThread(jvm);
return NULL; return NULL;
} }
} }
@ -178,12 +189,10 @@ static void java_object_finalizer(JSRuntime *rt, JSValue val) {
java_object_data *data = JS_GetOpaque(val, JS_CLASS_JAVA_OBJECT_ID); java_object_data *data = JS_GetOpaque(val, JS_CLASS_JAVA_OBJECT_ID);
if (data) { if (data) {
JNIEnv *env; JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); (*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION);
(*env)->DeleteGlobalRef(env, data->obj); (*env)->DeleteGlobalRef(env, data->obj);
js_free_rt(rt, data); js_free_rt(rt, data);
(*jvm)->DetachCurrentThread(jvm);
} }
} }
@ -293,7 +302,7 @@ static JSValue js_add_bridge(JSContext *ctx, JSValueConst this_val, int argc, JS
static JSValue js_use_bridge(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) { static JSValue js_use_bridge(JSContext *ctx, JSValueConst this_val, int argc, JSValueConst *argv) {
JNIEnv *env; JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); (*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION);
jclass obj_clazz = (*env)->FindClass(env, "java/lang/Object"); jclass obj_clazz = (*env)->FindClass(env, "java/lang/Object");
jobjectArray arr = (*env)->NewObjectArray(env, argc - 1, obj_clazz, NULL); jobjectArray arr = (*env)->NewObjectArray(env, argc - 1, obj_clazz, NULL);
@ -328,6 +337,7 @@ static JSValue js_use_bridge(JSContext *ctx, JSValueConst this_val, int argc, JS
js_out = JS_ThrowReferenceError(ctx, "unable to use bridge '%s': %s", js_bridge_name, str); js_out = JS_ThrowReferenceError(ctx, "unable to use bridge '%s': %s", js_bridge_name, str);
(*env)->ReleaseStringUTFChars(env, java_string, str);
(*env)->ExceptionClear(env); (*env)->ExceptionClear(env);
} else { } else {
js_out = JS_NULL; js_out = JS_NULL;
@ -336,8 +346,6 @@ static JSValue js_use_bridge(JSContext *ctx, JSValueConst this_val, int argc, JS
JS_FreeCString(ctx, js_bridge_name); JS_FreeCString(ctx, js_bridge_name);
(*jvm)->DetachCurrentThread(jvm);
return js_out; return js_out;
} }
@ -356,7 +364,6 @@ JNIEXPORT jobject JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJ
const char *native_string = (*env)->GetStringUTFChars(env, bridge_name, 0); const char *native_string = (*env)->GetStringUTFChars(env, bridge_name, 0);
JSValue bridge = JS_GetPropertyStr(ctx, scriptcraft_obj, native_string); JSValue bridge = JS_GetPropertyStr(ctx, scriptcraft_obj, native_string);
(*env)->ReleaseStringUTFChars(env, bridge_name, native_string);
JSValue out; JSValue out;
if (JS_IsFunction(ctx, bridge)) { if (JS_IsFunction(ctx, bridge)) {
@ -367,9 +374,14 @@ JNIEXPORT jobject JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJ
} }
} else { } else {
out = JS_NULL; out = JS_NULL;
throw_exception(env, "Invalid Bridge"); char *err;
asprintf(&err, "Invalid Bridge: %s", native_string);
throw_exception(env, err);
free(err);
} }
(*env)->ReleaseStringUTFChars(env, bridge_name, native_string);
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
JS_FreeValue(ctx, args[i]); JS_FreeValue(ctx, args[i]);
} }
@ -393,18 +405,18 @@ static int scriptcraft_core_init(JSContext *ctx, JSModuleDef *m) {
JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative_init(JNIEnv *env, jobject this_val) { JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative_init(JNIEnv *env, jobject this_val) {
jint rc = (*env)->GetJavaVM(env, &jvm); jint rc = (*env)->GetJavaVM(env, &jvm);
if (rc != JNI_OK) { if (rc != JNI_OK) {
throw_exception(env, "qjs: unable to cache JavaVM"); throw_exception(env, "Unable To Cache JavaVM");
return; return;
} }
JSRuntime *rt = JS_NewRuntime(); JSRuntime *rt = JS_NewRuntime();
if (!rt) { if (!rt) {
throw_exception(env, "qjs: cannot allocate JS runtime"); throw_exception(env, "Cannot Allocate JS Runtime");
return; return;
} }
JSContext *ctx = JS_NewContext(rt); JSContext *ctx = JS_NewContext(rt);
if (!ctx) { if (!ctx) {
throw_exception(env, "qjs: cannot allocate JS context"); throw_exception(env, "Cannot Allocate JS Context");
return; return;
} }
@ -418,7 +430,7 @@ JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNa
JSModuleDef *m = JS_NewCModule(ctx, "scriptcraft-core", scriptcraft_core_init); JSModuleDef *m = JS_NewCModule(ctx, "scriptcraft-core", scriptcraft_core_init);
if (!m) { if (!m) {
throw_exception(env, "qjs: unable to allocate C module"); throw_exception(env, "Unable To Allocate C Module");
return; return;
} }
@ -492,13 +504,11 @@ JNIEXPORT void JNICALL Java_com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNa
void print_data(char *data, int err) { void print_data(char *data, int err) {
JNIEnv *env; JNIEnv *env;
(*jvm)->AttachCurrentThread(jvm, (void **) &env, NULL); (*jvm)->GetEnv(jvm, (void**) &env, JNI_VERSION);
jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSNative"); jclass clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/QuickJSNative");
jmethodID print_methodID = (*env)->GetStaticMethodID(env, clazz, "print", "(Ljava/lang/String;Z)V"); jmethodID print_methodID = (*env)->GetStaticMethodID(env, clazz, "print", "(Ljava/lang/String;Z)V");
jstring str = (*env)->NewStringUTF(env, data); jstring str = (*env)->NewStringUTF(env, data);
(*env)->CallStaticVoidMethod(env, clazz, print_methodID, str, err); (*env)->CallStaticVoidMethod(env, clazz, print_methodID, str, err);
(*env)->DeleteLocalRef(env, str); (*env)->DeleteLocalRef(env, str);
(*jvm)->DetachCurrentThread(jvm);
} }

View File

@ -22,5 +22,7 @@ class BlockEntityBridges {
((BlockEntity) args[0]).markDirty(); ((BlockEntity) args[0]).markDirty();
return null; return null;
}); });
ScriptCraftCore.addBridge("BlockEntity.isValid", args -> args[0] instanceof BlockEntity);
} }
} }

View File

@ -9,5 +9,7 @@ class BlockStateBridges {
static void register() { static void register() {
ScriptCraftCore.addBridge("BlockState.getDefaultState", args -> Registry.BLOCK.get(new Identifier((String) args[0])).getDefaultState()); 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()); ScriptCraftCore.addBridge("BlockState.getBlock", args -> Registry.BLOCK.getId(((BlockState) args[0]).getBlock()).toString());
ScriptCraftCore.addBridge("BlockState.isValid", args -> args[0] instanceof BlockState);
} }
} }

View File

@ -20,5 +20,7 @@ class DamageSourceBridges {
ScriptCraftCore.addBridge("DamageSource.createFromPlayer", args -> DamageSource.player((PlayerEntity) args[1])); ScriptCraftCore.addBridge("DamageSource.createFromPlayer", args -> DamageSource.player((PlayerEntity) args[1]));
ScriptCraftCore.addBridge("DamageSource.createFromMob", args -> DamageSource.mob((LivingEntity) args[1])); ScriptCraftCore.addBridge("DamageSource.createFromMob", args -> DamageSource.mob((LivingEntity) args[1]));
ScriptCraftCore.addBridge("DamageSource.isValid", args -> args[0] instanceof DamageSource);
} }
} }

View File

@ -53,5 +53,7 @@ class EntityBridges {
((Entity) args[0]).fromTag((CompoundTag) args[1]); ((Entity) args[0]).fromTag((CompoundTag) args[1]);
return null; return null;
}); });
ScriptCraftCore.addBridge("Entity.isValid", args -> args[0] instanceof Entity);
} }
} }

View File

@ -15,5 +15,7 @@ class InventoryBridges {
}); });
ScriptCraftCore.addBridge("Inventory.size", args -> ((Inventory) args[0]).getInvSize()); ScriptCraftCore.addBridge("Inventory.size", args -> ((Inventory) args[0]).getInvSize());
ScriptCraftCore.addBridge("Inventory.getMaxStackSize", args -> ((Inventory) args[0]).getInvMaxStackAmount()); ScriptCraftCore.addBridge("Inventory.getMaxStackSize", args -> ((Inventory) args[0]).getInvMaxStackAmount());
ScriptCraftCore.addBridge("Inventory.isValid", args -> args[0] instanceof Inventory);
} }
} }

View File

@ -36,5 +36,7 @@ class ItemStackBridges {
ScriptCraftCore.addBridge("ItemStack.fromTag", args -> ItemStack.fromTag((CompoundTag) args[1])); ScriptCraftCore.addBridge("ItemStack.fromTag", args -> ItemStack.fromTag((CompoundTag) args[1]));
ScriptCraftCore.addBridge("ItemStack.split", args -> ((ItemStack) args[0]).split((int) ValueUtil.toDouble(args[1], 0))); ScriptCraftCore.addBridge("ItemStack.split", args -> ((ItemStack) args[0]).split((int) ValueUtil.toDouble(args[1], 0)));
ScriptCraftCore.addBridge("ItemStack.isValid", args -> args[0] instanceof ItemStack);
} }
} }

View File

@ -8,5 +8,7 @@ class LivingEntityBridges {
static void register() { static void register() {
ScriptCraftCore.addBridge("LivingEntity.getStackInHand", args -> ((LivingEntity) args[0]).getStackInHand((Hand) args[1])); ScriptCraftCore.addBridge("LivingEntity.getStackInHand", args -> ((LivingEntity) args[0]).getStackInHand((Hand) args[1]));
ScriptCraftCore.addBridge("LivingEntity.getHealth", args -> ((LivingEntity) args[0]).getHealth()); ScriptCraftCore.addBridge("LivingEntity.getHealth", args -> ((LivingEntity) args[0]).getHealth());
ScriptCraftCore.addBridge("LivingEntity.isValid", args -> args[0] instanceof LivingEntity);
} }
} }

View File

@ -6,5 +6,6 @@ import net.minecraft.entity.player.PlayerEntity;
class PlayerEntityBridges { class PlayerEntityBridges {
static void register() { static void register() {
ScriptCraftCore.addBridge("PlayerEntity.getInventory", args -> ((PlayerEntity) args[0]).inventory); ScriptCraftCore.addBridge("PlayerEntity.getInventory", args -> ((PlayerEntity) args[0]).inventory);
ScriptCraftCore.addBridge("PlayerEntity.isValid", args -> args[0] instanceof PlayerEntity);
} }
} }

View File

@ -2,7 +2,6 @@ package com.thebrokenrail.scriptcraft.api.bridge;
import com.thebrokenrail.scriptcraft.core.ScriptCraftCore; import com.thebrokenrail.scriptcraft.core.ScriptCraftCore;
import com.thebrokenrail.scriptcraft.core.ValueUtil; import com.thebrokenrail.scriptcraft.core.ValueUtil;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.AbstractListTag; import net.minecraft.nbt.AbstractListTag;
import net.minecraft.nbt.AbstractNumberTag; import net.minecraft.nbt.AbstractNumberTag;
import net.minecraft.nbt.ByteTag; import net.minecraft.nbt.ByteTag;
@ -92,6 +91,8 @@ class TagBridges {
return tag.getKeys().toArray(new String[0]); return tag.getKeys().toArray(new String[0]);
}); });
ScriptCraftCore.addBridge("CompoundTag.isValid", args -> args[0] instanceof CompoundTag);
ScriptCraftCore.addBridge("ListTag.get", args -> { ScriptCraftCore.addBridge("ListTag.get", args -> {
AbstractListTag<?> tag = (AbstractListTag<?>) args[0]; AbstractListTag<?> tag = (AbstractListTag<?>) args[0];
Tag obj = tag.get((int) ValueUtil.toDouble(args[1], 0)); Tag obj = tag.get((int) ValueUtil.toDouble(args[1], 0));
@ -107,6 +108,8 @@ class TagBridges {
return tag.size(); return tag.size();
}); });
ScriptCraftCore.addBridge("ListTag.isValid", args -> args[0] instanceof ListTag);
ScriptCraftCore.addBridge("CompoundTag.create", args -> new CompoundTag()); ScriptCraftCore.addBridge("CompoundTag.create", args -> new CompoundTag());
ScriptCraftCore.addBridge("ListTag.create", args -> new ListTag()); ScriptCraftCore.addBridge("ListTag.create", args -> new ListTag());
} }

View File

@ -45,5 +45,7 @@ class WorldBridges {
}); });
ScriptCraftCore.addBridge("World.isClient", args -> ((World) args[0]).isClient()); ScriptCraftCore.addBridge("World.isClient", args -> ((World) args[0]).isClient());
ScriptCraftCore.addBridge("World.isValid", args -> args[0] instanceof World);
} }
} }

View File

@ -1,6 +1,6 @@
import { World } from './world'; import { World } from './world';
import { PlayerEntity } from './entity'; import { PlayerEntity } from './entity';
import { Identifier, Hand, Pos, ActionResult, Direction, SimpleRegistry } from './core'; import { Identifier, Hand, Pos, ActionResult, Direction, SimpleRegistry, JavaObjectWrapper } from './core';
import { CompoundTag } from './tag'; import { CompoundTag } from './tag';
import { useBridge, addBridge } from 'scriptcraft-core'; import { useBridge, addBridge } from 'scriptcraft-core';
import { Inventory } from './inventory'; import { Inventory } from './inventory';
@ -9,8 +9,8 @@ import { Inventory } from './inventory';
* Settings for {@link CustomBlock} * Settings for {@link CustomBlock}
*/ */
export class BlockSettings { export class BlockSettings {
readonly #material: string; #material: string;
readonly #materialColor: string; #materialColor: string;
#resistance: number; #resistance: number;
#hardness: number; #hardness: number;
@ -60,10 +60,61 @@ export class BlockSettings {
} }
/** /**
* @internal * Get Material
* @returns Material
*/
getMaterial(): string {
return this.#material;
}
/**
* Set Material
* @param material Material
*/
setMaterial(material: string): BlockSettings {
this.#material = material;
return this;
}
/**
* Set Material Color
* @param materialColor Material Color
*/
setMaterialColor(materialColor: string): BlockSettings {
this.#materialColor = materialColor;
return this;
}
/**
* Get Material Color
* @returns Material Color
*/
getMaterialColor(): string {
return this.#materialColor;
}
/**
* Get Blast Resistance
* @returns Blast Resistance
*/
getResistance(): number {
return this.#resistance;
}
/**
* Get Hardness
* @returns Hardness
*/
getHardness(): number {
return this.#hardness;
}
/**
* Create Java Object
* @returns Java Object
*/ */
createJavaObject(): JavaObject { createJavaObject(): JavaObject {
return useBridge('BlockSettings.create', this.#material, this.#materialColor, this.#hardness, this.#resistance) as JavaObject; return useBridge('BlockSettings.create', this.getMaterial(), this.getMaterialColor(), this.getHardness(), this.getResistance()) as JavaObject;
} }
} }
@ -71,17 +122,22 @@ export class BlockSettings {
* Custom Block * Custom Block
*/ */
export class CustomBlock { export class CustomBlock {
/** readonly #settings: Readonly<BlockSettings>;
* @internal
*/
readonly settings: BlockSettings;
/** /**
* Create Custom Block * Create Custom Block
* @param settings Block Settings * @param settings Block Settings
*/ */
constructor(settings: BlockSettings) { constructor(settings: BlockSettings) {
this.settings = settings; this.#settings = Object.freeze(settings);
}
/**
* Get Block Settings
* @returns Block Settings
*/
getSettings(): Readonly<BlockSettings> {
return this.#settings;
} }
/** /**
@ -174,17 +230,14 @@ export class CustomBlockEntity {
/** /**
* Block State * Block State
*/ */
export class BlockState { export class BlockState extends JavaObjectWrapper {
/** /**
* @internal * Create Block State Wrapper From Java Object
* @param javaObject Java Object
*/ */
readonly javaObject: JavaObject; constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
/** this.assertValidJavaObject('BlockState');
* @internal
*/
constructor(javaObject: JavaObject) {
this.javaObject = javaObject;
} }
/** /**
@ -206,7 +259,7 @@ export class BlockState {
* @returns Block ID * @returns Block ID
*/ */
getBlock(): Identifier { getBlock(): Identifier {
const obj = useBridge('BlockState.getBlock', this.javaObject) as string; const obj = useBridge('BlockState.getBlock', this.getJavaObject()) as string;
if (obj) { if (obj) {
return new Identifier(obj); return new Identifier(obj);
} else { } else {
@ -227,17 +280,14 @@ export class BlockState {
/** /**
* Block Entity * Block Entity
*/ */
export class BlockEntity { export class BlockEntity extends JavaObjectWrapper {
/** /**
* @internal * Create Block Entity Wrapper From Java Object
* @param javaObject Java Object
*/ */
readonly javaObject: JavaObject; constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
/** this.assertValidJavaObject('BlockEntity');
* @internal
*/
constructor(object: JavaObject) {
this.javaObject = object;
} }
/** /**
@ -245,7 +295,7 @@ export class BlockEntity {
* @returns ID * @returns ID
*/ */
getID(): Identifier { getID(): Identifier {
const obj = useBridge('BlockEntity.getID', this.javaObject) as string; const obj = useBridge('BlockEntity.getID', this.getJavaObject()) as string;
if (obj !== null) { if (obj !== null) {
return new Identifier(obj); return new Identifier(obj);
} else { } else {
@ -258,7 +308,7 @@ export class BlockEntity {
* @returns Inventory If Block Entity Has One, Otherwise NULL * @returns Inventory If Block Entity Has One, Otherwise NULL
*/ */
getInventory(): Inventory { getInventory(): Inventory {
const obj = useBridge('BlockEntity.getInventory', this.javaObject) as JavaObject; const obj = useBridge('BlockEntity.getInventory', this.getJavaObject()) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new Inventory(obj); return new Inventory(obj);
} else { } else {
@ -270,7 +320,7 @@ export class BlockEntity {
* Mark Dirty * Mark Dirty
*/ */
markDirty(): void { markDirty(): void {
useBridge('BlockEntity.markDirty', this.javaObject); useBridge('BlockEntity.markDirty', this.getJavaObject());
} }
} }
@ -305,9 +355,9 @@ export class BlockRegistry implements SimpleRegistry<CustomBlock> {
register(id: Identifier, obj: CustomBlock): void { register(id: Identifier, obj: CustomBlock): void {
this.#blocks.set(id.toString(), obj); this.#blocks.set(id.toString(), obj);
if (obj instanceof CustomBlockWithEntity) { if (obj instanceof CustomBlockWithEntity) {
useBridge('Registry.registerBlockWithEntity', id.toString(), obj.settings.createJavaObject()); useBridge('Registry.registerBlockWithEntity', id.toString(), obj.getSettings().createJavaObject());
} else { } else {
useBridge('Registry.registerBlock', id.toString(), obj.settings.createJavaObject()); useBridge('Registry.registerBlock', id.toString(), obj.getSettings().createJavaObject());
} }
} }
@ -351,7 +401,7 @@ addBridge('CustomBlockEntity.fromTag', (i: number, tag: JavaObject) => {
}); });
addBridge('CustomBlockEntity.toTag', (i: number, tag: JavaObject): JavaObject => { addBridge('CustomBlockEntity.toTag', (i: number, tag: JavaObject): JavaObject => {
return BlockRegistry.INSTANCE.getCustomBlockEntity(i).toTag(new CompoundTag(tag)).javaObject; return BlockRegistry.INSTANCE.getCustomBlockEntity(i).toTag(new CompoundTag(tag)).getJavaObject();
}); });
addBridge('CustomBlockEntity.tick', (i: number) => { addBridge('CustomBlockEntity.tick', (i: number) => {

View File

@ -1,3 +1,43 @@
import { useBridge } from 'scriptcraft-core';
/**
* Base Class For Objects Wrapping A Java Object
*/
export class JavaObjectWrapper {
readonly #javaObject: JavaObject;
/**
* Get Java Object
* @returns Java Object
*/
getJavaObject(): JavaObject {
return this.#javaObject;
}
/**
* Create Object Wrapper From A Java Object Or Another Object Wrapper
* @param javaObject Java Object
*/
constructor(javaObject: JavaObject | JavaObjectWrapper) {
if (javaObject instanceof JavaObjectWrapper) {
this.#javaObject = javaObject.getJavaObject();
} else {
this.#javaObject = javaObject;
}
}
/**
* Assert Provided Java Object Is Valid
* @param type Object Type
*/
protected assertValidJavaObject(type: string): void {
const valid = useBridge(type + '.isValid', this.getJavaObject()) as boolean;
if (!valid) {
throw new Error('Provided Java Object Is Not A Valid ' + type);
}
}
}
/** /**
* Action Result * Action Result
*/ */

View File

@ -1,45 +1,39 @@
import { ItemStack } from './item'; import { ItemStack } from './item';
import { Hand, Identifier, Pos } from './core'; import { Hand, Identifier, Pos, JavaObjectWrapper } from './core';
import { World } from './world'; import { World } from './world';
import { CompoundTag } from './tag'; import { CompoundTag } from './tag';
import { useBridge } from 'scriptcraft-core'; import { useBridge } from 'scriptcraft-core';
import { Inventory } from './inventory'; import { Inventory } from './inventory';
/** function buildDamageSource(bridge: string, value: BridgeValueType): DamageSource {
* Damage Source
*/
export class DamageSource {
/**
* @internal
*/
readonly javaObject: JavaObject;
/**
* @internal
*/
constructor(javaObject: JavaObject) {
this.javaObject = javaObject;
}
/**
* @internal
*/
private static build(bridge: string, value: BridgeValueType): DamageSource {
const obj = useBridge(bridge, value) as JavaObject; const obj = useBridge(bridge, value) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new DamageSource(obj); return new DamageSource(obj);
} else { } else {
return null; return null;
} }
}
/**
* Damage Source
*/
export class DamageSource extends JavaObjectWrapper {
/**
* Create Damage Source Wrapper From Java Object
* @param javaObject Java Object
*/
constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
this.assertValidJavaObject('DamageSource');
} }
/** /**
* Create Damage Source from a name * Create Damage Source from type
* @param value Name * @param value Type
* @returns Damage Source * @returns Damage Source
*/ */
static create(value: string): DamageSource { static create(value: string): DamageSource {
return this.build('DamageSource.create', value); return buildDamageSource('DamageSource.create', value);
} }
/** /**
@ -48,7 +42,7 @@ export class DamageSource {
* @returns Damage Source * @returns Damage Source
*/ */
static createFromPlayer(value: PlayerEntity): DamageSource { static createFromPlayer(value: PlayerEntity): DamageSource {
return this.build('DamageSource.createFromPlayer', value.javaObject); return buildDamageSource('DamageSource.createFromPlayer', value.getJavaObject());
} }
/** /**
@ -57,29 +51,21 @@ export class DamageSource {
* @returns Damage Source * @returns Damage Source
*/ */
static createFromMob(value: LivingEntity): DamageSource { static createFromMob(value: LivingEntity): DamageSource {
return this.build('DamageSource.createFromMob', value.javaObject); return buildDamageSource('DamageSource.createFromMob', value.getJavaObject());
} }
} }
/** /**
* Entity * Entity
*/ */
export class Entity { export class Entity extends JavaObjectWrapper {
/** /**
* @internal * Create Entity Wrapper Class From Existing Entity Or Java Object
* @param object Existing Entity Or Java Object
*/ */
readonly javaObject: JavaObject; constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
/** this.assertValidJavaObject('Entity');
* Cast Existing Entity To This Class (Use With Caution)
* @param object Existing Entity
*/
constructor(object: JavaObject | Entity) {
if (object instanceof Entity) {
this.javaObject = object.javaObject;
} else {
this.javaObject = object;
}
} }
/** /**
@ -87,7 +73,7 @@ export class Entity {
* @returns Entity World * @returns Entity World
*/ */
getEntityWorld(): World { getEntityWorld(): World {
const obj = useBridge('Entity.getEntityWorld', this.javaObject) as JavaObject; const obj = useBridge('Entity.getEntityWorld', this.getJavaObject()) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new World(obj); return new World(obj);
} else { } else {
@ -100,7 +86,7 @@ export class Entity {
* @returns Entity ID * @returns Entity ID
*/ */
getID(): Identifier { getID(): Identifier {
const obj = useBridge('Entity.getID', this.javaObject) as string; const obj = useBridge('Entity.getID', this.getJavaObject()) as string;
if (obj !== null) { if (obj !== null) {
return new Identifier(obj); return new Identifier(obj);
} else { } else {
@ -113,7 +99,7 @@ export class Entity {
* @returns Entity Name * @returns Entity Name
*/ */
getName(): string { getName(): string {
return useBridge('Entity.getName', this.javaObject) as string; return useBridge('Entity.getName', this.getJavaObject()) as string;
} }
/** /**
@ -121,7 +107,7 @@ export class Entity {
* @returns Entity Display Name * @returns Entity Display Name
*/ */
getDisplayName(): string { getDisplayName(): string {
return useBridge('Entity.getDisplayName', this.javaObject) as string; return useBridge('Entity.getDisplayName', this.getJavaObject()) as string;
} }
/** /**
@ -129,7 +115,7 @@ export class Entity {
* @returns Entity Custom Name * @returns Entity Custom Name
*/ */
getCustomName(): string { getCustomName(): string {
return useBridge('Entity.getCustomName', this.javaObject) as string; return useBridge('Entity.getCustomName', this.getJavaObject()) as string;
} }
/** /**
@ -144,14 +130,14 @@ export class Entity {
* Kill Entity * Kill Entity
*/ */
kill(): void { kill(): void {
useBridge('Entity.kill', this.javaObject); useBridge('Entity.kill', this.getJavaObject());
} }
/** /**
* Remove Entity * Remove Entity
*/ */
remove(): void { remove(): void {
useBridge('Entity.remove', this.javaObject); useBridge('Entity.remove', this.getJavaObject());
} }
/** /**
@ -159,7 +145,7 @@ export class Entity {
* @param ticks Fire Ticks * @param ticks Fire Ticks
*/ */
setFireTicks(ticks: number): void { setFireTicks(ticks: number): void {
useBridge('Entity.setFireTicks', this.javaObject, ticks); useBridge('Entity.setFireTicks', this.getJavaObject(), ticks);
} }
/** /**
@ -167,7 +153,7 @@ export class Entity {
* @returns Fire Ticks * @returns Fire Ticks
*/ */
getFireTicks(): number { getFireTicks(): number {
return useBridge('Entity.getFireTicks', this.javaObject) as number; return useBridge('Entity.getFireTicks', this.getJavaObject()) as number;
} }
/** /**
@ -176,7 +162,7 @@ export class Entity {
* @param amount Damage Amount * @param amount Damage Amount
*/ */
damage(source: DamageSource, amount: number): void { damage(source: DamageSource, amount: number): void {
useBridge('Entity.damage', source.javaObject, amount); useBridge('Entity.damage', source.getJavaObject(), amount);
} }
/** /**
@ -184,7 +170,7 @@ export class Entity {
* @returns Entity Position * @returns Entity Position
*/ */
getPosition(): Pos { getPosition(): Pos {
const pos: number[] = useBridge('Entity.getPosition', this.javaObject) as number[]; const pos: number[] = useBridge('Entity.getPosition', this.getJavaObject()) as number[];
if (pos !== null && pos.length === 3) { if (pos !== null && pos.length === 3) {
return new Pos(pos[0], pos[1], pos[2]); return new Pos(pos[0], pos[1], pos[2]);
} else { } else {
@ -197,7 +183,7 @@ export class Entity {
* @param pos Entity Position * @param pos Entity Position
*/ */
setPosition(pos: Pos): void { setPosition(pos: Pos): void {
useBridge('Entity.setPosition', this.javaObject, pos.getX(), pos.getY(), pos.getZ()); useBridge('Entity.setPosition', this.getJavaObject(), pos.getX(), pos.getY(), pos.getZ());
} }
/** /**
@ -205,7 +191,7 @@ export class Entity {
* @returns Tag * @returns Tag
*/ */
toTag(): CompoundTag { toTag(): CompoundTag {
const obj = useBridge('Entity.toTag', this.javaObject) as JavaObject; const obj = useBridge('Entity.toTag', this.getJavaObject()) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new CompoundTag(obj); return new CompoundTag(obj);
} else { } else {
@ -218,7 +204,7 @@ export class Entity {
* @param tag Tag * @param tag Tag
*/ */
fromTag(tag: CompoundTag): void { fromTag(tag: CompoundTag): void {
useBridge('Entity.fromTag', this.javaObject, tag.javaObject); useBridge('Entity.fromTag', this.getJavaObject(), tag.getJavaObject());
} }
} }
@ -226,13 +212,18 @@ export class Entity {
* Living Entity * Living Entity
*/ */
export class LivingEntity extends Entity { export class LivingEntity extends Entity {
constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
this.assertValidJavaObject('LivingEntity');
}
/** /**
* Get Stack in {@link Hand} * Get Stack in {@link Hand}
* @param hand Hand * @param hand Hand
* @returns Item Stack * @returns Item Stack
*/ */
getStackInHand(hand: Hand): ItemStack { getStackInHand(hand: Hand): ItemStack {
const obj = useBridge('LivingEntity.getStackInHand', this.javaObject, hand.toString()) as JavaObject; const obj = useBridge('LivingEntity.getStackInHand', this.getJavaObject(), hand.toString()) as JavaObject;
if (obj) { if (obj) {
return new ItemStack(obj); return new ItemStack(obj);
} else { } else {
@ -245,7 +236,7 @@ export class LivingEntity extends Entity {
* @returns Entity Health * @returns Entity Health
*/ */
getHealth(): number { getHealth(): number {
return useBridge('LivingEntity.getHealth', this.javaObject) as number; return useBridge('LivingEntity.getHealth', this.getJavaObject()) as number;
} }
} }
@ -253,8 +244,13 @@ export class LivingEntity extends Entity {
* Player Entity * Player Entity
*/ */
export class PlayerEntity extends LivingEntity { export class PlayerEntity extends LivingEntity {
constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
this.assertValidJavaObject('PlayerEntity');
}
getInventory(): Inventory { getInventory(): Inventory {
const obj = useBridge('PlayerEntity.getInventory', this.javaObject) as JavaObject; const obj = useBridge('PlayerEntity.getInventory', this.getJavaObject()) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new Inventory(obj); return new Inventory(obj);
} else { } else {

View File

@ -5,19 +5,16 @@ import { ActionResult, Hand, Pos, Direction } from './core';
/** /**
* Event * Event
* @typeParam T Event Data Type
* @typeParam K Event Return Type
*/ */
class Event<T, K> { export class Event<T, K> {
/**
* @internal
*/
#listeners: ((obj: T) => K)[] = []; #listeners: ((obj: T) => K)[] = [];
/**
* @internal
*/
#defaultValue: K; #defaultValue: K;
/** /**
* @internal * Create Event
* @param defaultValue Default Return Value If There Are No Events (Can be Null)
*/ */
constructor(defaultValue: K) { constructor(defaultValue: K) {
this.#defaultValue = defaultValue; this.#defaultValue = defaultValue;
@ -43,9 +40,11 @@ class Event<T, K> {
} }
/** /**
* @internal * Trigger Event
* @param obj Event Data
* @returns Event Return Value
*/ */
run(obj: T): K { trigger(obj: T): K {
for (const listener of this.#listeners) { for (const listener of this.#listeners) {
const value = listener(obj); const value = listener(obj);
if (this.#defaultValue !== null && value != this.#defaultValue) { if (this.#defaultValue !== null && value != this.#defaultValue) {
@ -57,12 +56,9 @@ class Event<T, K> {
} }
/** /**
* Tick Event * World Event
*/
class WorldTickEvent {
/**
* @internal
*/ */
export class WorldEvent {
readonly #world: World; readonly #world: World;
/** /**
@ -74,7 +70,8 @@ class WorldTickEvent {
} }
/** /**
* @internal * Create World Event
* @param world World
*/ */
constructor(world: World) { constructor(world: World) {
this.#world = world; this.#world = world;
@ -84,26 +81,11 @@ class WorldTickEvent {
/** /**
* Block Event * Block Event
*/ */
class BlockEvent { export class BlockEvent {
/**
* @internal
*/
readonly #world: World; readonly #world: World;
/**
* @internal
*/
readonly #player: PlayerEntity; readonly #player: PlayerEntity;
/**
* @internal
*/
readonly #hand: Hand; readonly #hand: Hand;
/**
* @internal
*/
readonly #pos: Pos; readonly #pos: Pos;
/**
* @internal
*/
readonly #side: Direction; readonly #side: Direction;
/** /**
@ -147,7 +129,12 @@ class BlockEvent {
} }
/** /**
* @internal * Create Block Event
* @param player Player
* @param world World
* @param hand Hand
* @param pos Position
* @param side Block Side
*/ */
constructor(player: PlayerEntity, world: World, hand: Hand, pos: Pos, side: Direction) { constructor(player: PlayerEntity, world: World, hand: Hand, pos: Pos, side: Direction) {
this.#player = player; this.#player = player;
@ -161,18 +148,9 @@ class BlockEvent {
/** /**
* Item Event * Item Event
*/ */
class ItemEvent { export class ItemEvent {
/**
* @internal
*/
readonly #world: World; readonly #world: World;
/**
* @internal
*/
readonly #player: PlayerEntity; readonly #player: PlayerEntity;
/**
* @internal
*/
readonly #hand: Hand; readonly #hand: Hand;
/** /**
@ -200,7 +178,10 @@ class ItemEvent {
} }
/** /**
* @internal * Create Item Event
* @param player Player
* @param world World
* @param hand Hand
*/ */
constructor(player: PlayerEntity, world: World, hand: Hand) { constructor(player: PlayerEntity, world: World, hand: Hand) {
this.#player = player; this.#player = player;
@ -216,7 +197,7 @@ export class Events {
/** /**
* World Tick Event * World Tick Event
*/ */
static WORLD_TICK = new Event<WorldTickEvent, void>(null); static WORLD_TICK = new Event<WorldEvent, void>(null);
/** /**
* Attack Block Event * Attack Block Event
*/ */
@ -231,7 +212,7 @@ export class Events {
static USE_ITEM = new Event<ItemEvent, ActionResult>(ActionResult.PASS); static USE_ITEM = new Event<ItemEvent, ActionResult>(ActionResult.PASS);
} }
addBridge('Event.worldTick', (world: JavaObject) => Events.WORLD_TICK.run(new WorldTickEvent(new World(world)))); addBridge('Event.worldTick', (world: JavaObject) => Events.WORLD_TICK.trigger(new WorldEvent(new World(world))));
addBridge('Event.attackBlock', (player: JavaObject, world: JavaObject, hand: keyof typeof Hand, x: number, y: number, z: number, side: keyof typeof Direction) => Events.ATTACK_BLOCK.run(new BlockEvent(new PlayerEntity(player), new World(world), Hand[hand], new Pos(x, y, z), Direction[side]))); addBridge('Event.attackBlock', (player: JavaObject, world: JavaObject, hand: keyof typeof Hand, x: number, y: number, z: number, side: keyof typeof Direction) => Events.ATTACK_BLOCK.trigger(new BlockEvent(new PlayerEntity(player), new World(world), Hand[hand], new Pos(x, y, z), Direction[side])));
addBridge('Event.useBlock', (player: JavaObject, world: JavaObject, hand: keyof typeof Hand, x: number, y: number, z: number, side: keyof typeof Direction) => Events.USE_BLOCK.run(new BlockEvent(new PlayerEntity(player), new World(world), Hand[hand], new Pos(x, y, z), Direction[side]))); addBridge('Event.useBlock', (player: JavaObject, world: JavaObject, hand: keyof typeof Hand, x: number, y: number, z: number, side: keyof typeof Direction) => Events.USE_BLOCK.trigger(new BlockEvent(new PlayerEntity(player), new World(world), Hand[hand], new Pos(x, y, z), Direction[side])));
addBridge('Event.useItem', (player: JavaObject, world: JavaObject, hand: keyof typeof Hand) => Events.USE_ITEM.run(new ItemEvent(new PlayerEntity(player), new World(world), Hand[hand]))); addBridge('Event.useItem', (player: JavaObject, world: JavaObject, hand: keyof typeof Hand) => Events.USE_ITEM.trigger(new ItemEvent(new PlayerEntity(player), new World(world), Hand[hand])));

View File

@ -1,20 +1,18 @@
import { useBridge } from 'scriptcraft-core'; import { useBridge } from 'scriptcraft-core';
import { ItemStack } from './item'; import { ItemStack } from './item';
import { JavaObjectWrapper } from './core';
/** /**
* Inventory * Inventory
*/ */
export class Inventory { export class Inventory extends JavaObjectWrapper {
/** /**
* @internal * Create Inventory Wrapper From Java Object
* @param object Java Object
*/ */
readonly javaObject: JavaObject; constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
/** this.assertValidJavaObject('Inventory');
* @internal
*/
constructor(object: JavaObject) {
this.javaObject = object;
} }
/** /**
@ -22,7 +20,7 @@ export class Inventory {
* @returns Inventory Size * @returns Inventory Size
*/ */
size(): number { size(): number {
return useBridge('Inventory.size', this.javaObject) as number; return useBridge('Inventory.size', this.getJavaObject()) as number;
} }
/** /**
@ -30,7 +28,7 @@ export class Inventory {
* @returns Inventory Maximum Stack Size * @returns Inventory Maximum Stack Size
*/ */
getMaxStackSize(): number { getMaxStackSize(): number {
return useBridge('Inventory.getMaxStackSize', this.javaObject) as number; return useBridge('Inventory.getMaxStackSize', this.getJavaObject()) as number;
} }
/** /**
@ -39,7 +37,7 @@ export class Inventory {
* @returns Item Stack * @returns Item Stack
*/ */
get(slot: number): ItemStack { get(slot: number): ItemStack {
const obj = useBridge('Inventory.get', this.javaObject, slot) as JavaObject; const obj = useBridge('Inventory.get', this.getJavaObject(), slot) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new ItemStack(obj); return new ItemStack(obj);
} else { } else {
@ -54,7 +52,7 @@ export class Inventory {
* @returns Item Stack * @returns Item Stack
*/ */
take(slot: number, count: number): ItemStack { take(slot: number, count: number): ItemStack {
const obj = useBridge('Inventory.take', this.javaObject, slot, count) as JavaObject; const obj = useBridge('Inventory.take', this.getJavaObject(), slot, count) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new ItemStack(obj); return new ItemStack(obj);
} else { } else {
@ -68,6 +66,6 @@ export class Inventory {
* @param item Item Stack * @param item Item Stack
*/ */
set(slot: number, item: ItemStack): void { set(slot: number, item: ItemStack): void {
useBridge('Inventory.set', this.javaObject, slot, item.javaObject); useBridge('Inventory.set', this.getJavaObject(), slot, item.getJavaObject());
} }
} }

View File

@ -1,4 +1,4 @@
import { Identifier, Hand, ActionResult, Pos, Direction, SimpleRegistry } from './core'; import { Identifier, Hand, ActionResult, Pos, Direction, SimpleRegistry, JavaObjectWrapper } from './core';
import { World } from './world'; import { World } from './world';
import { PlayerEntity, LivingEntity } from './entity'; import { PlayerEntity, LivingEntity } from './entity';
import { CompoundTag } from './tag'; import { CompoundTag } from './tag';
@ -7,17 +7,14 @@ import { useBridge, addBridge } from 'scriptcraft-core';
/** /**
* Item Stack * Item Stack
*/ */
export class ItemStack { export class ItemStack extends JavaObjectWrapper {
/** /**
* @internal * Create Item Stack Wrapper From Java Object
* @param object Java Object
*/ */
readonly javaObject: JavaObject; constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
/** this.assertValidJavaObject('ItemStack');
* @internal
*/
constructor(obj: JavaObject) {
this.javaObject = obj;
} }
/** /**
@ -39,7 +36,7 @@ export class ItemStack {
* @returns Item ID * @returns Item ID
*/ */
getItem(): Identifier { getItem(): Identifier {
const obj = useBridge('ItemStack.getItem', this.javaObject) as string; const obj = useBridge('ItemStack.getItem', this.getJavaObject()) as string;
if (obj !== null) { if (obj !== null) {
return new Identifier(obj); return new Identifier(obj);
} else { } else {
@ -60,7 +57,7 @@ export class ItemStack {
* @returns Item Count * @returns Item Count
*/ */
getCount(): number { getCount(): number {
return useBridge('ItemStack.getCount', this.javaObject) as number; return useBridge('ItemStack.getCount', this.getJavaObject()) as number;
} }
/** /**
@ -68,7 +65,7 @@ export class ItemStack {
* @param count New Count * @param count New Count
*/ */
setCount(count: number): void { setCount(count: number): void {
useBridge('ItemStack.setCount', this.javaObject, count); useBridge('ItemStack.setCount', this.getJavaObject(), count);
} }
/** /**
@ -76,7 +73,7 @@ export class ItemStack {
* @returns Item Damage * @returns Item Damage
*/ */
getDamage(): number { getDamage(): number {
return useBridge('ItemStack.getDamage', this.javaObject) as number; return useBridge('ItemStack.getDamage', this.getJavaObject()) as number;
} }
/** /**
@ -84,7 +81,7 @@ export class ItemStack {
* @param count New Damage * @param count New Damage
*/ */
setDamage(damage: number): void { setDamage(damage: number): void {
useBridge('ItemStack.setDamage', this.javaObject, damage); useBridge('ItemStack.setDamage', this.getJavaObject(), damage);
} }
/** /**
@ -92,7 +89,7 @@ export class ItemStack {
* @returns TRUE If Item Is Damageable, Otherwise FALSE * @returns TRUE If Item Is Damageable, Otherwise FALSE
*/ */
isDamageable(): boolean { isDamageable(): boolean {
return useBridge('ItemStack.isDamageable', this.javaObject) as boolean; return useBridge('ItemStack.isDamageable', this.getJavaObject()) as boolean;
} }
/** /**
@ -100,7 +97,7 @@ export class ItemStack {
* @returns Item Tag * @returns Item Tag
*/ */
getTag(): CompoundTag { getTag(): CompoundTag {
const obj = useBridge('ItemStack.getTag', this.javaObject) as JavaObject; const obj = useBridge('ItemStack.getTag', this.getJavaObject()) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new CompoundTag(obj); return new CompoundTag(obj);
} else { } else {
@ -113,7 +110,7 @@ export class ItemStack {
* @param tag New Item Tag * @param tag New Item Tag
*/ */
setTag(tag: CompoundTag): void { setTag(tag: CompoundTag): void {
useBridge('ItemStack.setTag', this.javaObject, tag.javaObject); useBridge('ItemStack.setTag', this.getJavaObject(), tag.getJavaObject());
} }
/** /**
@ -121,7 +118,7 @@ export class ItemStack {
* @returns Item Tag * @returns Item Tag
*/ */
toTag(): CompoundTag { toTag(): CompoundTag {
const obj = useBridge('ItemStack.toTag', this.javaObject) as JavaObject; const obj = useBridge('ItemStack.toTag', this.getJavaObject()) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new CompoundTag(obj); return new CompoundTag(obj);
} else { } else {
@ -135,7 +132,7 @@ export class ItemStack {
* @returns Item Stack * @returns Item Stack
*/ */
static fromTag(tag: CompoundTag): ItemStack { static fromTag(tag: CompoundTag): ItemStack {
const obj = useBridge('ItemStack.fromTag', tag.javaObject) as JavaObject; const obj = useBridge('ItemStack.fromTag', tag.getJavaObject()) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new ItemStack(obj); return new ItemStack(obj);
} else { } else {
@ -149,7 +146,7 @@ export class ItemStack {
* @returns New Item Stack * @returns New Item Stack
*/ */
split(amount: number): ItemStack { split(amount: number): ItemStack {
const obj = useBridge('ItemStack.split', this.javaObject, amount) as JavaObject; const obj = useBridge('ItemStack.split', this.getJavaObject(), amount) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new ItemStack(obj); return new ItemStack(obj);
} else { } else {
@ -212,7 +209,8 @@ export class ItemSettings {
} }
/** /**
* @internal * Create Java Object
* @returns Java Object
*/ */
createJavaObject(): JavaObject { createJavaObject(): JavaObject {
return useBridge('ItemSettings.create', this.#maxCount, this.#rarity, this.#itemGroup) as JavaObject; return useBridge('ItemSettings.create', this.#maxCount, this.#rarity, this.#itemGroup) as JavaObject;
@ -223,17 +221,22 @@ export class ItemSettings {
* Custom Item * Custom Item
*/ */
export class CustomItem { export class CustomItem {
readonly #settings: Readonly<ItemSettings>;
/** /**
* @internal * Get Item Settings
* @returns Item Settings
*/ */
readonly settings: ItemSettings; getSettings(): Readonly<ItemSettings> {
return this.#settings;
}
/** /**
* Create Custom Item * Create Custom Item
* @param settings Item Settings * @param settings Item Settings
*/ */
constructor(settings: ItemSettings) { constructor(settings: ItemSettings) {
this.settings = settings; this.#settings = Object.freeze(settings);
} }
/** /**
@ -276,14 +279,25 @@ export class CustomItem {
* Block Item * Block Item
*/ */
export class BlockItem { export class BlockItem {
readonly #settings: Readonly<ItemSettings>;
/** /**
* @internal * Get Item Settings
* @returns Item Settings
*/ */
readonly settings: ItemSettings; getSettings(): Readonly<ItemSettings> {
return this.#settings;
}
readonly #block: Identifier;
/** /**
* @internal * Get Block ID
* @returns Block ID
*/ */
readonly block: Identifier; getBlock(): Identifier {
return this.#block;
}
/** /**
* Create Block Item * Create Block Item
@ -291,8 +305,8 @@ export class BlockItem {
* @param settings Item Settings * @param settings Item Settings
*/ */
constructor(block: Identifier, settings: ItemSettings) { constructor(block: Identifier, settings: ItemSettings) {
this.settings = settings; this.#settings = Object.freeze(settings);
this.block = block; this.#block = block;
} }
} }
@ -311,9 +325,9 @@ export class ItemRegistry implements SimpleRegistry<CustomItem | BlockItem> {
register(id: Identifier, obj: CustomItem | BlockItem): void { register(id: Identifier, obj: CustomItem | BlockItem): void {
if (obj instanceof CustomItem) { if (obj instanceof CustomItem) {
this.#items.set(id.toString(), obj); this.#items.set(id.toString(), obj);
useBridge('Registry.registerItem', id.toString(), obj.settings.createJavaObject()); useBridge('Registry.registerItem', id.toString(), obj.getSettings().createJavaObject());
} else { } else {
useBridge('Registry.registerBlockItem', id.toString(), obj.settings.createJavaObject(), obj.block.toString()); useBridge('Registry.registerBlockItem', id.toString(), obj.getSettings().createJavaObject(), obj.getBlock().toString());
} }
} }

View File

@ -1,4 +1,5 @@
import { useBridge } from 'scriptcraft-core'; import { useBridge } from 'scriptcraft-core';
import { JavaObjectWrapper } from './core';
type TagType = number | boolean | string | CompoundTag | ListTag; type TagType = number | boolean | string | CompoundTag | ListTag;
@ -55,17 +56,14 @@ export enum NumberType {
/** /**
* Compound Tag * Compound Tag
*/ */
export class CompoundTag { export class CompoundTag extends JavaObjectWrapper {
/** /**
* @internal * Create Compound Tag Wrapper From Java Object
* @param javaObject Java Object
*/ */
readonly javaObject: JavaObject; constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
/** this.assertValidJavaObject('CompoundTag');
* @internal
*/
constructor(javaObject: JavaObject) {
this.javaObject = javaObject;
} }
/** /**
@ -76,7 +74,7 @@ export class CompoundTag {
* @returns Value * @returns Value
*/ */
get(key: string): Exclude<TagType, boolean> { get(key: string): Exclude<TagType, boolean> {
const obj = useBridge('CompoundTag.get', this.javaObject, key) as [boolean, BridgeValueType]; const obj = useBridge('CompoundTag.get', this.getJavaObject(), key) as [boolean, BridgeValueType];
return getTagValue(obj); return getTagValue(obj);
} }
@ -89,7 +87,7 @@ export class CompoundTag {
set(key: string, value: number, numberType: NumberType): void; set(key: string, value: number, numberType: NumberType): void;
set(key: string, value: Exclude<TagType, number>): void; set(key: string, value: Exclude<TagType, number>): void;
set(key: string, value: TagType, numberType?: NumberType): void { set(key: string, value: TagType, numberType?: NumberType): void {
useBridge('CompoundTag.set', this.javaObject, key, value instanceof CompoundTag || value instanceof ListTag ? value.javaObject : value, numberType !== null ? numberType : NumberType.DOUBLE); useBridge('CompoundTag.set', this.getJavaObject(), key, value instanceof CompoundTag || value instanceof ListTag ? value.getJavaObject() : value, numberType !== null ? numberType : NumberType.DOUBLE);
} }
/** /**
@ -97,7 +95,7 @@ export class CompoundTag {
* @returns List Of Keys * @returns List Of Keys
*/ */
keys(): string[] { keys(): string[] {
return useBridge('CompoundTag.keys', this.javaObject) as string[]; return useBridge('CompoundTag.keys', this.getJavaObject()) as string[];
} }
/** /**
@ -138,17 +136,14 @@ export class CompoundTag {
/** /**
* List Tag * List Tag
*/ */
export class ListTag { export class ListTag extends JavaObjectWrapper {
/** /**
* @internal * Create List Tag Wrapper From Java Object
* @param javaObject Java Object
*/ */
readonly javaObject: JavaObject; constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
/** this.assertValidJavaObject('ListTag');
* @internal
*/
constructor(javaObject: JavaObject) {
this.javaObject = javaObject;
} }
/** /**
@ -159,7 +154,7 @@ export class ListTag {
* @returns Value * @returns Value
*/ */
get(key: number): Exclude<TagType, boolean> { get(key: number): Exclude<TagType, boolean> {
const obj = useBridge('ListTag.get', this.javaObject, key) as [boolean, BridgeValueType]; const obj = useBridge('ListTag.get', this.getJavaObject(), key) as [boolean, BridgeValueType];
return getTagValue(obj); return getTagValue(obj);
} }
@ -172,7 +167,7 @@ export class ListTag {
set(key: number, value: number, numberType: NumberType): void; set(key: number, value: number, numberType: NumberType): void;
set(key: number, value: Exclude<TagType, number>): void; set(key: number, value: Exclude<TagType, number>): void;
set(key: number, value: TagType, numberType?: NumberType): void { set(key: number, value: TagType, numberType?: NumberType): void {
useBridge('ListTag.set', this.javaObject, key, value instanceof CompoundTag || value instanceof ListTag ? value.javaObject : value, numberType !== null ? numberType : NumberType.DOUBLE); useBridge('ListTag.set', this.getJavaObject(), key, value instanceof CompoundTag || value instanceof ListTag ? value.getJavaObject() : value, numberType !== null ? numberType : NumberType.DOUBLE);
} }
/** /**
@ -180,7 +175,7 @@ export class ListTag {
* @returns Size * @returns Size
*/ */
size(): number { size(): number {
return useBridge('ListTag.size', this.javaObject) as number; return useBridge('ListTag.size', this.getJavaObject()) as number;
} }
/** /**

View File

@ -1,22 +1,19 @@
import { BlockState, CustomBlockEntity, BlockRegistry, BlockEntity } from './block'; import { BlockState, CustomBlockEntity, BlockRegistry, BlockEntity } from './block';
import { Entity } from './entity'; import { Entity } from './entity';
import { Pos, Identifier } from './core'; import { Pos, Identifier, JavaObjectWrapper } from './core';
import { useBridge } from 'scriptcraft-core'; import { useBridge } from 'scriptcraft-core';
/** /**
* World * World
*/ */
export class World { export class World extends JavaObjectWrapper {
/** /**
* @internal * Create World Wrapper From Java Object
* @param javaObject Java Object
*/ */
readonly javaObject: JavaObject; constructor(javaObject: JavaObject | JavaObjectWrapper) {
super(javaObject);
/** this.assertValidJavaObject('World');
* @internal
*/
constructor(javaObject: JavaObject) {
this.javaObject = javaObject;
} }
/** /**
@ -26,7 +23,7 @@ export class World {
* @returns TRUE If Successful, Otherwise FALSE * @returns TRUE If Successful, Otherwise FALSE
*/ */
setBlockState(pos: Pos, state: BlockState): boolean { setBlockState(pos: Pos, state: BlockState): boolean {
return useBridge('World.setBlockState', this.javaObject, pos.getX(), pos.getY(), pos.getZ(), state.javaObject) as boolean; return useBridge('World.setBlockState', this.getJavaObject(), pos.getX(), pos.getY(), pos.getZ(), state.getJavaObject()) as boolean;
} }
/** /**
@ -35,7 +32,7 @@ export class World {
* @returns Block State * @returns Block State
*/ */
getBlockState(pos: Pos): BlockState { getBlockState(pos: Pos): BlockState {
const obj = useBridge('World.getBlockState', this.javaObject, pos.getX(), pos.getY(), pos.getZ()) as JavaObject; const obj = useBridge('World.getBlockState', this.getJavaObject(), pos.getX(), pos.getY(), pos.getZ()) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new BlockState(obj); return new BlockState(obj);
} else { } else {
@ -49,7 +46,7 @@ export class World {
* @param pos Position * @param pos Position
*/ */
spawnEntity(id: Identifier, pos: Pos): Entity { spawnEntity(id: Identifier, pos: Pos): Entity {
const obj = useBridge('World.spawnEntity', this.javaObject, pos.getX(), pos.getY(), pos.getZ(), id.toString()) as JavaObject; const obj = useBridge('World.spawnEntity', this.getJavaObject(), pos.getX(), pos.getY(), pos.getZ(), id.toString()) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new Entity(obj); return new Entity(obj);
} else { } else {
@ -63,7 +60,7 @@ export class World {
* @returns Custom Block Entity At Position * @returns Custom Block Entity At Position
*/ */
getCustomBlockEntity(pos: Pos): CustomBlockEntity { getCustomBlockEntity(pos: Pos): CustomBlockEntity {
const obj = useBridge('World.getCustomBlockEntity', this.javaObject, pos.getX(), pos.getY(), pos.getZ()) as number; const obj = useBridge('World.getCustomBlockEntity', this.getJavaObject(), pos.getX(), pos.getY(), pos.getZ()) as number;
if (obj !== null) { if (obj !== null) {
return BlockRegistry.INSTANCE.getCustomBlockEntity(obj); return BlockRegistry.INSTANCE.getCustomBlockEntity(obj);
} else { } else {
@ -77,7 +74,7 @@ export class World {
* @returns Block Entity ID At Position * @returns Block Entity ID At Position
*/ */
getBlockEntity(pos: Pos): BlockEntity { getBlockEntity(pos: Pos): BlockEntity {
const obj = useBridge('World.getBlockEntity', this.javaObject, pos.getX(), pos.getY(), pos.getZ()) as JavaObject; const obj = useBridge('World.getBlockEntity', this.getJavaObject(), pos.getX(), pos.getY(), pos.getZ()) as JavaObject;
if (obj !== null) { if (obj !== null) {
return new BlockEntity(obj); return new BlockEntity(obj);
} else { } else {
@ -86,6 +83,6 @@ export class World {
} }
isClient(): boolean { isClient(): boolean {
return useBridge('World.isClient', this.javaObject) as boolean; return useBridge('World.isClient', this.getJavaObject()) as boolean;
} }
} }