diff --git a/docs/tutorials/BLOCK.md b/docs/tutorials/BLOCK.md index a404ac1..b9a178b 100644 --- a/docs/tutorials/BLOCK.md +++ b/docs/tutorials/BLOCK.md @@ -48,5 +48,5 @@ Registry.register(Registry.BLOCK, new Identifier('modid', 'my_block'), new MyBlo ```javascript import { Registry, Identifier, BlockItem, ItemSettings } from 'minecraft'; -Registry.register(Registry.ITEM, new Identifier('modid', 'my_block'), new BlockItem(new Identifier('modid', 'my_block'), new ItemSettings().setItemGroup('building_blocks'))); +Registry.register(Registry.ITEM, new Identifier('modid', 'my_block'), new BlockItem(new Identifier('modid', 'my_block'), new ItemSettings().itemGroup('building_blocks'))); ``` diff --git a/docs/tutorials/BLOCK_ENTITY.md b/docs/tutorials/BLOCK_ENTITY.md index 4d27797..76cc94b 100644 --- a/docs/tutorials/BLOCK_ENTITY.md +++ b/docs/tutorials/BLOCK_ENTITY.md @@ -112,5 +112,5 @@ Registry.register(Registry.BLOCK, new Identifier('modid', 'my_block'), new MyBlo ```javascript import { Registry, Identifier, BlockItem, ItemSettings } from 'minecraft'; -Registry.register(Registry.ITEM, new Identifier('modid', 'my_block'), new BlockItem(new Identifier('modid', 'my_block'), new ItemSettings().setItemGroup('building_blocks'))); +Registry.register(Registry.ITEM, new Identifier('modid', 'my_block'), new BlockItem(new Identifier('modid', 'my_block'), new ItemSettings().itemGroup('building_blocks'))); ``` diff --git a/docs/tutorials/ITEM.md b/docs/tutorials/ITEM.md index c6a2146..77f5d80 100644 --- a/docs/tutorials/ITEM.md +++ b/docs/tutorials/ITEM.md @@ -7,7 +7,7 @@ import { ActionResult, ItemSettings, CustomItem } from 'minecraft'; class MyItem extends CustomItem { constructor() { - super(new ItemSettings().setItemGroup('building_blocks').setMaxCount(16)); + super(new ItemSettings().itemGroup('building_blocks').maxCount(16)); } onUse(world, player, hand) { @@ -33,7 +33,7 @@ import { ActionResult, World, Pos, Hand, PlayerEntity, ItemSettings, CustomItem, class MyItem extends CustomItem { constructor() { - super(new ItemSettings().setItemGroup('building_blocks').setMaxCount(18)); + super(new ItemSettings().itemGroup('building_blocks').maxCount(18)); } onUse(world: World, player: PlayerEntity, hand: Hand): ActionResult { diff --git a/scriptcraft/src/main/c/com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative.c b/scriptcraft/src/main/c/com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative.c index 732a7d4..bd56e84 100644 --- a/scriptcraft/src/main/c/com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative.c +++ b/scriptcraft/src/main/c/com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative.c @@ -9,6 +9,14 @@ #include "com_thebrokenrail_scriptcraft_core_quickjs_QuickJSNative.h" #include "console.h" +#define GET_JAVA_ERROR \ + jclass exception_clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/JSException"); \ + jmethodID err_to_string = (*env)->GetStaticMethodID(env, exception_clazz, "getStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;"); \ + jstring err_java_string = (jstring) (*env)->CallObjectMethod(env, exception_clazz, err_to_string, err); \ + const char *err_str = (*env)->GetStringUTFChars(env, err_java_string, 0); + +#define FREE_JAVA_ERROR (*env)->ReleaseStringUTFChars(env, err_java_string, err_str); + typedef struct { JSContext *ctx; JSRuntime *rt; @@ -66,13 +74,12 @@ static char *js_module_normalize_name(JSContext *ctx, const char *base_name, con } else { jthrowable err = (*env)->ExceptionOccurred(env); if (err) { - jmethodID to_string = (*env)->GetMethodID(env, (*env)->FindClass(env, "java/lang/Object"), "toString", "()Ljava/lang/String;"); - jstring java_string = (jstring) (*env)->CallObjectMethod(env, err, to_string); - const char *str = (*env)->GetStringUTFChars(env, java_string, 0); + GET_JAVA_ERROR; - JS_ThrowReferenceError(ctx, "could not normalize module name '%s': %s", name, str); + JS_ThrowReferenceError(ctx, "could not normalize module name '%s': %s", name, err_str); + + FREE_JAVA_ERROR; - (*env)->ReleaseStringUTFChars(env, java_string, str); (*env)->ExceptionClear(env); } else { JS_ThrowReferenceError(ctx, "could not normalize module name '%s'", name); @@ -135,13 +142,12 @@ static char *js_load_file(JSContext *ctx, const char *filename) { } else { jthrowable err = (*env)->ExceptionOccurred(env); if (err) { - jmethodID to_string = (*env)->GetMethodID(env, (*env)->FindClass(env, "java/lang/Object"), "toString", "()Ljava/lang/String;"); - jstring java_string = (jstring) (*env)->CallObjectMethod(env, err, to_string); - const char *str = (*env)->GetStringUTFChars(env, java_string, 0); + GET_JAVA_ERROR; - JS_ThrowReferenceError(ctx, "could not load module filename '%s': %s", filename, str); + JS_ThrowReferenceError(ctx, "could not load module filename '%s': %s", filename, err_str); + + FREE_JAVA_ERROR; - (*env)->ReleaseStringUTFChars(env, java_string, str); (*env)->ExceptionClear(env); } else { JS_ThrowReferenceError(ctx, "could not load module filename '%s'", filename); @@ -334,14 +340,12 @@ static JSValue js_use_bridge(JSContext *ctx, JSValueConst this_val, int argc, JS } else { jthrowable err = (*env)->ExceptionOccurred(env); if (err) { - jclass exception_clazz = (*env)->FindClass(env, "com/thebrokenrail/scriptcraft/core/quickjs/JSException"); - jmethodID to_string = (*env)->GetMethodID(env, exception_clazz, "getStackTrace", "(Ljava/lang/Throwable;)Ljava/lang/String;"); - jstring java_string = (jstring) (*env)->CallObjectMethod(env, err, to_string); - const char *str = (*env)->GetStringUTFChars(env, java_string, 0); + GET_JAVA_ERROR; - 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, err_str); + + FREE_JAVA_ERROR; - (*env)->ReleaseStringUTFChars(env, java_string, str); (*env)->ExceptionClear(env); } else { js_out = JS_NULL; diff --git a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/block/CustomBlock.java b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/block/CustomBlock.java index c1eedc5..711c151 100644 --- a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/block/CustomBlock.java +++ b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/block/CustomBlock.java @@ -5,6 +5,8 @@ import com.thebrokenrail.scriptcraft.api.util.ValueUtil; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.Property; import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.Identifier; @@ -12,17 +14,51 @@ import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import java.util.HashMap; +import java.util.Map; + @SuppressWarnings("deprecation") -public class CustomBlock extends Block { +public abstract class CustomBlock extends Block { + @SuppressWarnings({"unchecked", "rawtypes"}) + public static class BlockStatePropertyBuilder { + private final Map map = new HashMap<>(); + + public void add(Property property, Comparable defaultValue) { + map.put(property, defaultValue); + } + + private void appendProperties(StateManager.Builder builder) { + for (Property property : map.keySet()) { + builder.add(property); + } + } + + private BlockState updateDefaultState(BlockState defaultState) { + for (Map.Entry entry : map.entrySet()) { + defaultState = defaultState.with(entry.getKey(), entry.getValue()); + } + return defaultState; + } + } + protected final Identifier id; public CustomBlock(Settings settings, Identifier id) { super(settings); this.id = id; + setDefaultState(getPropertyBuilder().updateDefaultState(getDefaultState())); } @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { return ValueUtil.getEnumValue(ActionResult.class, (String) ScriptCraftCore.useBridge("CustomBlock.onUse", id.toString(), world, state, pos.getX(), pos.getY(), pos.getZ(), hit.getSide().name(), player, hand.name()), ActionResult.PASS); } + + @Override + protected void appendProperties(StateManager.Builder builder) { + super.appendProperties(builder); + getPropertyBuilder().appendProperties(builder); + } + + protected abstract BlockStatePropertyBuilder getPropertyBuilder(); } diff --git a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/block/CustomBlockWithEntity.java b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/block/CustomBlockWithEntity.java index ac583c9..a55b9da 100644 --- a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/block/CustomBlockWithEntity.java +++ b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/block/CustomBlockWithEntity.java @@ -6,7 +6,7 @@ import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; import net.minecraft.world.BlockView; -public class CustomBlockWithEntity extends CustomBlock implements BlockEntityProvider { +public abstract class CustomBlockWithEntity extends CustomBlock implements BlockEntityProvider { public CustomBlockWithEntity(Settings settings, Identifier id) { super(settings, id); } diff --git a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockBridges.java b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockBridges.java index aee3a61..c8f78ae 100644 --- a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockBridges.java +++ b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockBridges.java @@ -2,12 +2,15 @@ package com.thebrokenrail.scriptcraft.api.bridge; import com.thebrokenrail.scriptcraft.core.ScriptCraftCore; import net.minecraft.block.Block; -import net.minecraft.block.Material; +import net.minecraft.util.registry.Registry; class BlockBridges { static void register() { ScriptCraftCore.addBridge("Block.getMaterial", args -> ((Block) args[0]).getDefaultState().getMaterial()); ScriptCraftCore.addBridge("Block.getMaterialColor", args -> ((Block) args[0]).getDefaultState().getTopMaterialColor(null, null)); + ScriptCraftCore.addBridge("Block.getID", args -> Registry.BLOCK.getId((Block) args[0]).toString()); + ScriptCraftCore.addBridge("Block.getDefaultState", args -> ((Block) args[0]).getDefaultState()); + ScriptCraftCore.addBridge("Block.isValid", args -> args[0] instanceof Block); } } diff --git a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockStateBridges.java b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockStateBridges.java index bf86a4d..3d5d6b9 100644 --- a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockStateBridges.java +++ b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockStateBridges.java @@ -2,13 +2,52 @@ 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; +import net.minecraft.state.property.Property; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +@SuppressWarnings({"rawtypes", "unchecked"}) 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()); + ScriptCraftCore.addBridge("BlockState.getBlock", args -> ((BlockState) args[0]).getBlock()); + + ScriptCraftCore.addBridge("BlockState.get", args -> { + BlockState state = (BlockState) args[0]; + String name = (String) args[1]; + Collection> properties = state.getProperties(); + for (Property property : properties) { + if (property.getName().equals(name)) { + return property.name(state.get(property)); + } + } + return null; + }); + ScriptCraftCore.addBridge("BlockState.with", args -> { + BlockState state = (BlockState) args[0]; + String name = (String) args[1]; + Comparable value = (Comparable) args[2]; + Collection> properties = state.getProperties(); + for (Property property : properties) { + if (property.getName().equals(name)) { + if (value instanceof String) { + value = (Comparable) property.parse((String) value).orElse(null); + } + return state.with(property, value); + } + } + return null; + }); + ScriptCraftCore.addBridge("BlockState.properties", args -> { + BlockState state = (BlockState) args[0]; + List names = new ArrayList<>(); + Collection> properties = state.getProperties(); + for (Property property : properties) { + names.add(property.getName()); + } + return names.toArray(); + }); ScriptCraftCore.addBridge("BlockState.isValid", args -> args[0] instanceof BlockState); } diff --git a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockStatePropertyBuilderBridges.java b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockStatePropertyBuilderBridges.java new file mode 100644 index 0000000..1472e39 --- /dev/null +++ b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/BlockStatePropertyBuilderBridges.java @@ -0,0 +1,24 @@ +package com.thebrokenrail.scriptcraft.api.bridge; + +import com.thebrokenrail.scriptcraft.api.block.CustomBlock; +import com.thebrokenrail.scriptcraft.api.util.ValueUtil; +import com.thebrokenrail.scriptcraft.core.ScriptCraftCore; +import net.minecraft.state.property.BooleanProperty; +import net.minecraft.state.property.IntProperty; + +class BlockStatePropertyBuilderBridges { + static void register() { + ScriptCraftCore.addBridge("BlockStatePropertyBuilder.create", args -> new CustomBlock.BlockStatePropertyBuilder()); + + ScriptCraftCore.addBridge("BlockStatePropertyBuilder.intProperty", args -> { + ((CustomBlock.BlockStatePropertyBuilder) args[0]).add(IntProperty.of((String) args[1], (int) ValueUtil.toDouble(args[2], 0), (int) ValueUtil.toDouble(args[3], 0)), (int) ValueUtil.toDouble(args[4], 0)); + return null; + }); + ScriptCraftCore.addBridge("BlockStatePropertyBuilder.booleanProperty", args -> { + ((CustomBlock.BlockStatePropertyBuilder) args[0]).add(BooleanProperty.of((String) args[1]), (Boolean) args[2]); + return null; + }); + + ScriptCraftCore.addBridge("BlockStatePropertyBuilder.isValid", args -> args[0] instanceof CustomBlock.BlockStatePropertyBuilder); + } +} diff --git a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/Bridges.java b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/Bridges.java index 2410126..97b799b 100644 --- a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/Bridges.java +++ b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/Bridges.java @@ -20,5 +20,6 @@ public class Bridges { MaterialColorBridges.register(); BlockBridges.register(); BuiltinRegistryBridges.register(); + BlockStatePropertyBuilderBridges.register(); } } diff --git a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/RegistryBridges.java b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/RegistryBridges.java index 2494cde..b08cbb1 100644 --- a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/RegistryBridges.java +++ b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/api/bridge/RegistryBridges.java @@ -15,11 +15,23 @@ import net.minecraft.util.registry.Registry; class RegistryBridges { static void register() { 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]))); + CustomBlock.BlockStatePropertyBuilder builder = (CustomBlock.BlockStatePropertyBuilder) args[2]; + Registry.register(Registry.BLOCK, new Identifier((String) args[0]), new CustomBlock((Block.Settings) args[1], new Identifier((String) args[0])) { + @Override + protected BlockStatePropertyBuilder getPropertyBuilder() { + return builder; + } + }); return null; }); 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]))); + CustomBlock.BlockStatePropertyBuilder builder = (CustomBlock.BlockStatePropertyBuilder) args[2]; + Registry.register(Registry.BLOCK, new Identifier((String) args[0]), new CustomBlockWithEntity((Block.Settings) args[1], new Identifier((String) args[0])) { + @Override + protected BlockStatePropertyBuilder getPropertyBuilder() { + return builder; + } + }); 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; }); diff --git a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/core/quickjs/JSException.java b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/core/quickjs/JSException.java index 6a7caf0..f5426bb 100644 --- a/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/core/quickjs/JSException.java +++ b/scriptcraft/src/main/java/com/thebrokenrail/scriptcraft/core/quickjs/JSException.java @@ -9,7 +9,7 @@ public class JSException extends Exception { } @SuppressWarnings("unused") - public String getStackTrace(Throwable e) { + public static String getStackTrace(Throwable e) { StringWriter writer = new StringWriter(); e.printStackTrace(new PrintWriter(writer)); return writer.toString(); diff --git a/scriptcraft/src/main/ts/.vscode/settings.json b/scriptcraft/src/main/ts/.vscode/settings.json index 12914a8..93a7ce5 100644 --- a/scriptcraft/src/main/ts/.vscode/settings.json +++ b/scriptcraft/src/main/ts/.vscode/settings.json @@ -7,5 +7,6 @@ "eslint.format.enable": true, "editor.insertSpaces": true, "editor.detectIndentation": false, - "editor.tabSize": 4 + "editor.tabSize": 4, + "typescript.tsdk": "./node_modules/typescript/lib" } \ No newline at end of file diff --git a/scriptcraft/src/main/ts/src/minecraft/block.ts b/scriptcraft/src/main/ts/src/minecraft/block.ts index f4a8058..bbe35df 100644 --- a/scriptcraft/src/main/ts/src/minecraft/block.ts +++ b/scriptcraft/src/main/ts/src/minecraft/block.ts @@ -4,11 +4,12 @@ import { Identifier, Hand, Pos, ActionResult, Direction, SimpleRegistry, JavaObj import { CompoundTag } from './tag'; import { useBridge, addBridge } from 'scriptcraft-core'; import { Inventory } from './inventory'; +import { Registry } from './registry'; /** * Block Material */ -class Material extends JavaObjectWrapper { +export class Material extends JavaObjectWrapper { /** * Create Material Wrapper From Java Object * @param javaObject Java Object @@ -24,7 +25,7 @@ class Material extends JavaObjectWrapper { */ getColor(): MaterialColor { const obj = useBridge('Material.getColor', this.getJavaObject()) as JavaObject; - if (obj) { + if (obj !== null) { return new MaterialColor(obj); } else { return null; @@ -35,7 +36,7 @@ class Material extends JavaObjectWrapper { /** * Block Material Color */ -class MaterialColor extends JavaObjectWrapper { +export class MaterialColor extends JavaObjectWrapper { /** * Create Material Color Wrapper From Java Object * @param javaObject Java Object @@ -76,7 +77,7 @@ export class BlockSettings { * @param hardness Hardness Value * @param resistance Blast Resistance Value */ - setStrength(hardness: number, resistance: number): BlockSettings { + strength(hardness: number, resistance: number): BlockSettings { this.#hardness = hardness; this.#resistance = resistance; return this; @@ -86,7 +87,7 @@ export class BlockSettings { * Set Hardness * @param hardness Hardness Value */ - setHardness(hardness: number): BlockSettings { + hardness(hardness: number): BlockSettings { this.#hardness = hardness; return this; } @@ -95,7 +96,7 @@ export class BlockSettings { * Set Blast Resistance * @param resistance Blast Resistance Value */ - setResistance(resistance: number): BlockSettings { + resistance(resistance: number): BlockSettings { this.#resistance = resistance; return this; } @@ -112,7 +113,7 @@ export class BlockSettings { * Set Material * @param material Material */ - setMaterial(material: Material): BlockSettings { + material(material: Material): BlockSettings { this.#material = material; return this; } @@ -121,7 +122,7 @@ export class BlockSettings { * Set Material Color * @param materialColor Material Color */ - setMaterialColor(materialColor: MaterialColor): BlockSettings { + materialColor(materialColor: MaterialColor): BlockSettings { this.#materialColor = materialColor; return this; } @@ -164,6 +165,7 @@ export class BlockSettings { */ export class CustomBlock { readonly #settings: Readonly; + readonly #propertyBuilder: BlockStatePropertyBuilder; /** * Create Custom Block @@ -171,6 +173,8 @@ export class CustomBlock { */ constructor(settings: BlockSettings) { this.#settings = Object.freeze(settings); + this.#propertyBuilder = BlockStatePropertyBuilder.create(); + this.appendProperties(this.getPropertyBuilder()); } /** @@ -181,6 +185,14 @@ export class CustomBlock { return this.#settings; } + /** + * Get Block State Property Builder + * @returns Block State Property Builder + */ + getPropertyBuilder(): BlockStatePropertyBuilder { + return this.#propertyBuilder; + } + /** * Called When The Block Is Used * @param world World @@ -194,6 +206,13 @@ export class CustomBlock { onUse(world: World, blockState: BlockState, pos: Pos, side: Direction, player: PlayerEntity, hand: Hand): ActionResult { return ActionResult.PASS; } + + /** + * Add Block State Properties + * @param builder Block State Property Builder + */ + appendProperties(builder: BlockStatePropertyBuilder): void { + } } /** @@ -266,8 +285,132 @@ export class CustomBlockEntity { } } } + + /** + * Get Custom Block Entity by ID + * @param id ID + * @returns Custom Block Entity + */ + static getByID(id: number): CustomBlockEntity { + return BlockRegistry.INSTANCE.getCustomBlockEntityByID(id); + } } +/** + * Block + */ +export class Block extends JavaObjectWrapper { + /** + * Create Block Wrapper From Java Object + * @param javaObject Java Object + */ + constructor(javaObject: JavaObject | JavaObjectWrapper) { + super(javaObject); + this.assertValidJavaObject('Block'); + } + + /** + * Get Block Material + */ + getMaterial(): Material { + const obj = useBridge('Block.getMaterial', this.getJavaObject()) as JavaObject; + if (obj !== null) { + return new Material(obj); + } else { + return null; + } + } + + /** + * Get Block Material Color + */ + getMaterialColor(): MaterialColor { + const obj = useBridge('Block.getMaterialColor', this.getJavaObject()) as JavaObject; + if (obj !== null) { + return new MaterialColor(obj); + } else { + return null; + } + } + + /** + * Get Block ID + * @returns ID + */ + getID(): Identifier { + const obj = useBridge('Block.getID', this.getJavaObject()) as string; + if (obj !== null) { + return new Identifier(obj); + } else { + return null; + } + } + + /** + * Get Default Block State + * @returns Default Block State + */ + getDefaultState(): BlockState { + const obj = useBridge('Block.getDefaultState', this.getJavaObject()) as JavaObject; + if (obj !== null) { + return new BlockState(obj); + } else { + return null; + } + } +} + +/** + * Custom Block State Property Builder + */ +export class BlockStatePropertyBuilder extends JavaObjectWrapper { + /** + * Create Block State Property Builder Wrapper From Java Object + * @param javaObject Java Object + */ + constructor(javaObject: JavaObject | JavaObjectWrapper) { + super(javaObject); + this.assertValidJavaObject('BlockStatePropertyBuilder'); + } + + /** + * Create Block State Property Builder + * @returns New Block State Property Builder + */ + static create(): BlockStatePropertyBuilder { + const obj = useBridge('BlockStatePropertyBuilder.create') as JavaObject; + if (obj) { + return new BlockStatePropertyBuilder(obj); + } else { + return null; + } + } + + /** + * Add Integer Property + * @param name Property Name + * @param min Minimum Value + * @param max Maximum Value + * @param defaultValue Default Value + */ + intProperty(name: string, min: number, max: number, defaultValue: number): BlockStatePropertyBuilder { + useBridge('BlockStatePropertyBuilder.intProperty', this.getJavaObject(), name, min, max, defaultValue); + return this; + } + + /** + * Add Boolean Property + * @param name Property Name + * @param defaultValue Default Value + */ + booleanProperty(name: string, defaultValue: boolean): BlockStatePropertyBuilder { + useBridge('BlockStatePropertyBuilder.booleanProperty', this.getJavaObject(), name, defaultValue); + return this; + } +} + +type BlockStatePropertyType = string | number | boolean; + /** * Block State */ @@ -281,28 +424,14 @@ export class BlockState extends JavaObjectWrapper { this.assertValidJavaObject('BlockState'); } - /** - * Get Default Block State for Block - * @param block Block ID - * @returns Default Block State - */ - static getDefaultState(block: Identifier): BlockState { - const obj = useBridge('BlockState.getDefaultState', block.toString()) as JavaObject; - if (obj) { - return new BlockState(obj); - } else { - return null; - } - } - /** * Get Block ID * @returns Block ID */ - getBlock(): Identifier { - const obj = useBridge('BlockState.getBlock', this.getJavaObject()) as string; - if (obj) { - return new Identifier(obj); + getBlock(): Block { + const obj = useBridge('BlockState.getBlock', this.getJavaObject()) as JavaObject; + if (obj !== null) { + return new Block(obj); } else { return null; } @@ -314,7 +443,53 @@ export class BlockState extends JavaObjectWrapper { */ getCustomBlock(): CustomBlock { const id = this.getBlock(); - return BlockRegistry.INSTANCE.get(id); + return BlockRegistry.INSTANCE.get(id.getID()); + } + + /** + * Get Block State Property + * @param property Property Name + * @returns Value + */ + get(property: string): BlockStatePropertyType { + return useBridge('BlockState.get', this.getJavaObject(), property) as BlockStatePropertyType; + } + + /** + * Get New Block State With Property Set To Value + * @param property Property Name + * @param value Value + * @returns New Block State + */ + with(property: string, value: BlockStatePropertyType): BlockState { + const obj = useBridge('BlockState.with', this.getJavaObject(), property, value) as JavaObject; + if (obj !== null) { + return new BlockState(obj); + } else { + return null; + } + } + + /** + * Get All Block State Properties + * @returns All Block State Properties + */ + properties(): string[] { + return useBridge('BlockState.properties', this.getJavaObject()) as string[]; + } + + /** + * Convert To String + * @returns String + */ + toString(): string { + const start = this.getBlock().getID().toString(); + const properties = this.properties(); + const parts: string[] = []; + for (const property of properties) { + parts.push(property + ' = ' + this.get(property).toString()); + } + return start + '[' + parts.join(', ') + ']'; } } @@ -378,49 +553,8 @@ export class CustomBlockWithEntity extends CustomBlock { } } -/** - * Built-In Block - */ -export class Block extends JavaObjectWrapper { - /** - * Create Built-In Block Wrapper From Java Object - * @param javaObject Java Object - */ - constructor(javaObject: JavaObject | JavaObjectWrapper) { - super(javaObject); - this.assertValidJavaObject('Block'); - } - - /** - * Get Block Material - */ - getMaterial(): Material { - const obj = useBridge('Block.getMaterial', this.getJavaObject()) as JavaObject; - if (obj) { - return new Material(obj); - } else { - return null; - } - } - - /** - * Get Block MaterialColor - */ - getMaterialColor(): MaterialColor { - const obj = useBridge('Block.getMaterialColor', this.getJavaObject()) as JavaObject; - if (obj) { - return new MaterialColor(obj); - } else { - return null; - } - } -} - -/** - * @internal - */ -export class BlockRegistry implements SimpleRegistry { - static readonly INSTANCE = new BlockRegistry(); +class BlockRegistry implements SimpleRegistry { + static INSTANCE = new BlockRegistry(); readonly #blocks: Map; @@ -433,11 +567,7 @@ export class BlockRegistry implements SimpleRegistry { register(id: Identifier, obj: CustomBlock): void { this.#blocks.set(id.toString(), obj); - if (obj instanceof CustomBlockWithEntity) { - useBridge('Registry.registerBlockWithEntity', id.toString(), obj.getSettings().createJavaObject()); - } else { - useBridge('Registry.registerBlock', id.toString(), obj.getSettings().createJavaObject()); - } + useBridge(obj instanceof CustomBlockWithEntity ? 'Registry.registerBlockWithEntity' : 'Registry.registerBlock', id.toString(), obj.getSettings().createJavaObject(), obj.getPropertyBuilder().getJavaObject()); } get(id: Identifier): CustomBlock { @@ -453,12 +583,8 @@ export class BlockRegistry implements SimpleRegistry { return null; } - getCustomBlockEntity(i: number): CustomBlockEntity { - return this.#blockEntities[i]; - } - - getCustomBlockEntities(): CustomBlockEntity[] { - return this.#blockEntities; + getCustomBlockEntityByID(id: number): CustomBlockEntity { + return this.#blockEntities[id]; } createCustomBlockEntity(id: Identifier, i: number): void { @@ -471,24 +597,26 @@ export class BlockRegistry implements SimpleRegistry { } } +Registry.BLOCK = BlockRegistry.INSTANCE; + addBridge('CustomBlockEntity.create', (id: string, i: number) => { BlockRegistry.INSTANCE.createCustomBlockEntity(new Identifier(id), i); }); addBridge('CustomBlockEntity.fromTag', (i: number, tag: JavaObject) => { - BlockRegistry.INSTANCE.getCustomBlockEntity(i).fromTag(new CompoundTag(tag)); + BlockRegistry.INSTANCE.getCustomBlockEntityByID(i).fromTag(new CompoundTag(tag)); }); addBridge('CustomBlockEntity.toTag', (i: number, tag: JavaObject): JavaObject => { - return BlockRegistry.INSTANCE.getCustomBlockEntity(i).toTag(new CompoundTag(tag)).getJavaObject(); + return BlockRegistry.INSTANCE.getCustomBlockEntityByID(i).toTag(new CompoundTag(tag)).getJavaObject(); }); addBridge('CustomBlockEntity.tick', (i: number) => { - BlockRegistry.INSTANCE.getCustomBlockEntity(i).tick(); + BlockRegistry.INSTANCE.getCustomBlockEntityByID(i).tick(); }); 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)); + BlockRegistry.INSTANCE.getCustomBlockEntityByID(i).setLocation(new World(world), new Pos(x, y, z)); }); addBridge('CustomBlockEntity.free', (i: number) => { @@ -510,7 +638,7 @@ export class BlockBuiltinRegistry implements SimpleBuiltinRegistry { get(id: Identifier): Block { const obj = useBridge('BuiltinRegistry.getBlock', id.toString()) as JavaObject; - if (obj) { + if (obj !== null) { return new Block(obj); } else { return null; diff --git a/scriptcraft/src/main/ts/src/minecraft/entity.ts b/scriptcraft/src/main/ts/src/minecraft/entity.ts index 51de76c..3d13d5a 100644 --- a/scriptcraft/src/main/ts/src/minecraft/entity.ts +++ b/scriptcraft/src/main/ts/src/minecraft/entity.ts @@ -242,7 +242,7 @@ export class LivingEntity extends Entity { */ getStackInHand(hand: Hand): ItemStack { const obj = useBridge('LivingEntity.getStackInHand', this.getJavaObject(), hand.toString()) as JavaObject; - if (obj) { + if (obj !== null) { return new ItemStack(obj); } else { return null; diff --git a/scriptcraft/src/main/ts/src/minecraft/index.ts b/scriptcraft/src/main/ts/src/minecraft/index.ts index 4ffdba3..2dbc9d2 100644 --- a/scriptcraft/src/main/ts/src/minecraft/index.ts +++ b/scriptcraft/src/main/ts/src/minecraft/index.ts @@ -9,7 +9,7 @@ */ export { Identifier, ActionResult, Hand, Pos, Direction, DirectionUtil } from './core'; -export { CustomBlock, CustomBlockEntity, CustomBlockWithEntity, BlockSettings, BlockState, BlockEntity } from './block'; +export { CustomBlock, CustomBlockEntity, CustomBlockWithEntity, BlockSettings, BlockState, Block, Material, MaterialColor } from './block'; export { ItemStack, ItemSettings, CustomItem, BlockItem, ItemRarity } from './item'; export { World } from './world'; export { LivingEntity, PlayerEntity } from './entity'; diff --git a/scriptcraft/src/main/ts/src/minecraft/item.ts b/scriptcraft/src/main/ts/src/minecraft/item.ts index b69e7be..95c8bde 100644 --- a/scriptcraft/src/main/ts/src/minecraft/item.ts +++ b/scriptcraft/src/main/ts/src/minecraft/item.ts @@ -3,6 +3,7 @@ import { World } from './world'; import { PlayerEntity, LivingEntity } from './entity'; import { CompoundTag } from './tag'; import { useBridge, addBridge } from 'scriptcraft-core'; +import { Registry } from './registry'; /** * Item Stack @@ -185,7 +186,7 @@ export class ItemSettings { * Set Max Count * @param maxCount Max Count */ - setMaxCount(maxCount: number): ItemSettings { + maxCount(maxCount: number): ItemSettings { this.#maxCount = maxCount; return this; } @@ -194,7 +195,7 @@ export class ItemSettings { * Set Item Group * @param itemGroup Item Group */ - setItemGroup(itemGroup: string | Identifier): ItemSettings { + itemGroup(itemGroup: string | Identifier): ItemSettings { this.#itemGroup = itemGroup.toString(); return this; } @@ -203,7 +204,7 @@ export class ItemSettings { * Set Item Rarity * @param rarity Item Rarity */ - setRarity(rarity: ItemRarity): ItemSettings { + rarity(rarity: ItemRarity): ItemSettings { this.#rarity = rarity; return this; } @@ -310,10 +311,7 @@ export class BlockItem { } } -/** - * @internal - */ -export class ItemRegistry implements SimpleRegistry { +class ItemRegistry implements SimpleRegistry { static readonly INSTANCE = new ItemRegistry(); readonly #items: Map; @@ -345,6 +343,8 @@ export class ItemRegistry implements SimpleRegistry { } } +Registry.ITEM = ItemRegistry.INSTANCE; + addBridge('CustomItem.onUse', (id: string, world: JavaObject, player: JavaObject, hand: keyof typeof Hand): string => { return ItemRegistry.INSTANCE.get(new Identifier(id)).onUse(new World(world), new PlayerEntity(player), Hand[hand]); }); diff --git a/scriptcraft/src/main/ts/src/minecraft/registry.ts b/scriptcraft/src/main/ts/src/minecraft/registry.ts index 7c26136..82951fe 100644 --- a/scriptcraft/src/main/ts/src/minecraft/registry.ts +++ b/scriptcraft/src/main/ts/src/minecraft/registry.ts @@ -1,6 +1,6 @@ import { Identifier, SimpleRegistry } from './core'; -import { BlockRegistry, CustomBlock } from './block'; -import { ItemRegistry, CustomItem, BlockItem } from './item'; +import { CustomBlock } from './block'; +import { CustomItem, BlockItem } from './item'; /** * Registry @@ -9,11 +9,11 @@ export abstract class Registry { /** * Block Registry */ - static BLOCK: SimpleRegistry = BlockRegistry.INSTANCE; + static BLOCK: SimpleRegistry; /** * Item Registry */ - static ITEM: SimpleRegistry = ItemRegistry.INSTANCE; + static ITEM: SimpleRegistry; /** * Register Object diff --git a/scriptcraft/src/main/ts/src/minecraft/tag.ts b/scriptcraft/src/main/ts/src/minecraft/tag.ts index 703bafe..b91bfeb 100644 --- a/scriptcraft/src/main/ts/src/minecraft/tag.ts +++ b/scriptcraft/src/main/ts/src/minecraft/tag.ts @@ -3,7 +3,7 @@ import { JavaObjectWrapper } from './core'; type TagType = number | boolean | string | CompoundTag | ListTag; -function getTagValue(obj: [boolean, BridgeValueType]): Exclude { +function getTagValue(obj: [isList: boolean, value: BridgeValueType]): Exclude { if (typeof obj[1] === 'object') { if (obj[0]) { return new ListTag(obj[1] as JavaObject); diff --git a/scriptcraft/src/main/ts/src/minecraft/world.ts b/scriptcraft/src/main/ts/src/minecraft/world.ts index d514510..80115aa 100644 --- a/scriptcraft/src/main/ts/src/minecraft/world.ts +++ b/scriptcraft/src/main/ts/src/minecraft/world.ts @@ -1,4 +1,4 @@ -import { BlockState, CustomBlockEntity, BlockRegistry, BlockEntity } from './block'; +import { BlockState, CustomBlockEntity, BlockEntity } from './block'; import { Entity } from './entity'; import { Pos, Identifier, JavaObjectWrapper } from './core'; import { useBridge } from 'scriptcraft-core'; @@ -62,7 +62,7 @@ export class World extends JavaObjectWrapper { getCustomBlockEntity(pos: Pos): CustomBlockEntity { const obj = useBridge('World.getCustomBlockEntity', this.getJavaObject(), pos.getX(), pos.getY(), pos.getZ()) as number; if (obj !== null) { - return BlockRegistry.INSTANCE.getCustomBlockEntity(obj); + return CustomBlockEntity.getByID(obj); } else { return null; } diff --git a/scriptcraft/src/main/ts/types/scriptcraft-core/index.d.ts b/scriptcraft/src/main/ts/types/scriptcraft-core/index.d.ts index 5e40a04..fc27a61 100644 --- a/scriptcraft/src/main/ts/types/scriptcraft-core/index.d.ts +++ b/scriptcraft/src/main/ts/types/scriptcraft-core/index.d.ts @@ -20,6 +20,7 @@ interface Console { declare const console: Console; interface String { + // eslint-disable-next-line @typescript-eslint/naming-convention __quote(): string; }