648 lines
16 KiB
TypeScript
648 lines
16 KiB
TypeScript
import { World } from './world';
|
|
import { PlayerEntity } from './entity';
|
|
import { Identifier, Hand, Pos, ActionResult, Direction, SimpleRegistry, JavaObjectWrapper, SimpleBuiltinRegistry } from './core';
|
|
import { CompoundTag } from './tag';
|
|
import { useBridge, addBridge } from 'scriptcraft-core';
|
|
import { Inventory } from './inventory';
|
|
import { Registry } from './registry';
|
|
|
|
/**
|
|
* Block Material
|
|
*/
|
|
export class Material extends JavaObjectWrapper {
|
|
/**
|
|
* Create Material Wrapper From Java Object
|
|
* @param javaObject Java Object
|
|
*/
|
|
constructor(javaObject: JavaObject | JavaObjectWrapper) {
|
|
super(javaObject);
|
|
this.assertValidJavaObject('Material');
|
|
}
|
|
|
|
/**
|
|
* Get Associated Material Color
|
|
* @returns Material Color
|
|
*/
|
|
getColor(): MaterialColor {
|
|
const obj = useBridge('Material.getColor', this.getJavaObject()) as JavaObject;
|
|
if (obj !== null) {
|
|
return new MaterialColor(obj);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Block Material Color
|
|
*/
|
|
export class MaterialColor extends JavaObjectWrapper {
|
|
/**
|
|
* Create Material Color Wrapper From Java Object
|
|
* @param javaObject Java Object
|
|
*/
|
|
constructor(javaObject: JavaObject | JavaObjectWrapper) {
|
|
super(javaObject);
|
|
this.assertValidJavaObject('MaterialColor');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Settings for {@link CustomBlock}
|
|
*/
|
|
export class BlockSettings {
|
|
#material: Material;
|
|
#materialColor: MaterialColor;
|
|
|
|
#resistance: number;
|
|
#hardness: number;
|
|
|
|
/**
|
|
* Create Block Settings
|
|
* @param material Material
|
|
* @param materialColor Material Color
|
|
*/
|
|
constructor(material: Material);
|
|
constructor(material: Material, materialColor: MaterialColor);
|
|
constructor(material: Material, materialColor?: MaterialColor) {
|
|
this.#material = material;
|
|
this.#materialColor = materialColor !== null ? materialColor : material.getColor();
|
|
|
|
this.#resistance = 0;
|
|
this.#hardness = 0;
|
|
}
|
|
|
|
/**
|
|
* Set Block Strength
|
|
* @param hardness Hardness Value
|
|
* @param resistance Blast Resistance Value
|
|
*/
|
|
strength(hardness: number, resistance: number): BlockSettings {
|
|
this.#hardness = hardness;
|
|
this.#resistance = resistance;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set Hardness
|
|
* @param hardness Hardness Value
|
|
*/
|
|
hardness(hardness: number): BlockSettings {
|
|
this.#hardness = hardness;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set Blast Resistance
|
|
* @param resistance Blast Resistance Value
|
|
*/
|
|
resistance(resistance: number): BlockSettings {
|
|
this.#resistance = resistance;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Get Material
|
|
* @returns Material
|
|
*/
|
|
getMaterial(): Material {
|
|
return this.#material;
|
|
}
|
|
|
|
/**
|
|
* Set Material
|
|
* @param material Material
|
|
*/
|
|
material(material: Material): BlockSettings {
|
|
this.#material = material;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Set Material Color
|
|
* @param materialColor Material Color
|
|
*/
|
|
materialColor(materialColor: MaterialColor): BlockSettings {
|
|
this.#materialColor = materialColor;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Get Material Color
|
|
* @returns Material Color
|
|
*/
|
|
getMaterialColor(): MaterialColor {
|
|
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 {
|
|
return useBridge('BlockSettings.create', this.getMaterial().getJavaObject(), this.getMaterialColor().getJavaObject(), this.getHardness(), this.getResistance()) as JavaObject;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Custom Block
|
|
*/
|
|
export class CustomBlock {
|
|
readonly #settings: Readonly<BlockSettings>;
|
|
readonly #propertyBuilder: BlockStatePropertyBuilder;
|
|
|
|
/**
|
|
* Create Custom Block
|
|
* @param settings Block Settings
|
|
*/
|
|
constructor(settings: BlockSettings) {
|
|
this.#settings = Object.freeze(settings);
|
|
this.#propertyBuilder = BlockStatePropertyBuilder.create();
|
|
this.appendProperties(this.getPropertyBuilder());
|
|
}
|
|
|
|
/**
|
|
* Get Block Settings
|
|
* @returns Block Settings
|
|
*/
|
|
getSettings(): Readonly<BlockSettings> {
|
|
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
|
|
* @param blockState Block State
|
|
* @param pos Block Position
|
|
* @param side Side Of The Block Used
|
|
* @param player Player
|
|
* @param hand Hand
|
|
* @returns Action Result
|
|
*/
|
|
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 {
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Custom Block Entity
|
|
*/
|
|
export class CustomBlockEntity {
|
|
/**
|
|
* World
|
|
*/
|
|
protected world: World;
|
|
/**
|
|
* Position
|
|
*/
|
|
protected pos: Pos;
|
|
|
|
/**
|
|
* Set Location
|
|
* @param world New World
|
|
* @param pos New Position
|
|
*/
|
|
setLocation(world: World, pos: Pos): void {
|
|
this.world = world;
|
|
this.pos = pos;
|
|
}
|
|
|
|
/**
|
|
* Save Data To Tag
|
|
* @param tag Tag
|
|
* @returns Tag
|
|
*/
|
|
toTag(tag: CompoundTag): CompoundTag {
|
|
return tag;
|
|
}
|
|
|
|
/**
|
|
* Load Data From Tag
|
|
* @param tag Tag
|
|
*/
|
|
fromTag(tag: CompoundTag): void {}
|
|
|
|
/**
|
|
* Runs Every Tick
|
|
*/
|
|
tick(): void {}
|
|
|
|
/**
|
|
* Get World
|
|
* @returns World
|
|
*/
|
|
getWorld(): World {
|
|
return this.world;
|
|
}
|
|
|
|
/**
|
|
* Get Position
|
|
* @returns Position
|
|
*/
|
|
getPos(): Pos {
|
|
return this.pos;
|
|
}
|
|
|
|
/**
|
|
* Mark Dirty
|
|
*/
|
|
markDirty(): void {
|
|
if (this.getWorld() !== null) {
|
|
const entity = this.getWorld().getBlockEntity(this.getPos());
|
|
if (entity !== null) {
|
|
entity.markDirty();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
export class BlockState extends JavaObjectWrapper {
|
|
/**
|
|
* Create Block State Wrapper From Java Object
|
|
* @param javaObject Java Object
|
|
*/
|
|
constructor(javaObject: JavaObject | JavaObjectWrapper) {
|
|
super(javaObject);
|
|
this.assertValidJavaObject('BlockState');
|
|
}
|
|
|
|
/**
|
|
* Get Block ID
|
|
* @returns Block ID
|
|
*/
|
|
getBlock(): Block {
|
|
const obj = useBridge('BlockState.getBlock', this.getJavaObject()) as JavaObject;
|
|
if (obj !== null) {
|
|
return new Block(obj);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Custom Block
|
|
* @returns Custom Block
|
|
*/
|
|
getCustomBlock(): CustomBlock {
|
|
const id = this.getBlock();
|
|
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(', ') + ']';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Block Entity
|
|
*/
|
|
export class BlockEntity extends JavaObjectWrapper {
|
|
/**
|
|
* Create Block Entity Wrapper From Java Object
|
|
* @param javaObject Java Object
|
|
*/
|
|
constructor(javaObject: JavaObject | JavaObjectWrapper) {
|
|
super(javaObject);
|
|
this.assertValidJavaObject('BlockEntity');
|
|
}
|
|
|
|
/**
|
|
* Get Block Entity ID
|
|
* @returns ID
|
|
*/
|
|
getID(): Identifier {
|
|
const obj = useBridge('BlockEntity.getID', this.getJavaObject()) as string;
|
|
if (obj !== null) {
|
|
return new Identifier(obj);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get Block Entity Inventory
|
|
* @returns Inventory If Block Entity Has One, Otherwise NULL
|
|
*/
|
|
getInventory(): Inventory {
|
|
const obj = useBridge('BlockEntity.getInventory', this.getJavaObject()) as JavaObject;
|
|
if (obj !== null) {
|
|
return new Inventory(obj);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Mark Dirty
|
|
*/
|
|
markDirty(): void {
|
|
useBridge('BlockEntity.markDirty', this.getJavaObject());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@link CustomBlock} With {@link CustomBlockEntity}
|
|
*/
|
|
export class CustomBlockWithEntity extends CustomBlock {
|
|
/**
|
|
* Create Custom Block Entity
|
|
* @returns Custom Block Entity
|
|
*/
|
|
createBlockEntity(): CustomBlockEntity {
|
|
throw new Error('CustomBlockWithEntity.createBlockEntity is not implemented');
|
|
}
|
|
}
|
|
|
|
class BlockRegistry implements SimpleRegistry<CustomBlock> {
|
|
static INSTANCE = new BlockRegistry();
|
|
|
|
readonly #blocks: Map<string, CustomBlock>;
|
|
|
|
readonly #blockEntities: CustomBlockEntity[];
|
|
|
|
private constructor() {
|
|
this.#blocks = new Map<string, CustomBlock>();
|
|
this.#blockEntities = [];
|
|
}
|
|
|
|
register(id: Identifier, obj: CustomBlock): void {
|
|
this.#blocks.set(id.toString(), obj);
|
|
useBridge(obj instanceof CustomBlockWithEntity ? 'Registry.registerBlockWithEntity' : 'Registry.registerBlock', id.toString(), obj.getSettings().createJavaObject(), obj.getPropertyBuilder().getJavaObject());
|
|
}
|
|
|
|
get(id: Identifier): CustomBlock {
|
|
return this.#blocks.get(id.toString());
|
|
}
|
|
|
|
getID(obj: CustomBlock): Identifier {
|
|
for (const block of this.#blocks) {
|
|
if (block[1] === obj) {
|
|
return new Identifier(block[0]);
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
getCustomBlockEntityByID(id: number): CustomBlockEntity {
|
|
return this.#blockEntities[id];
|
|
}
|
|
|
|
createCustomBlockEntity(id: Identifier, i: number): void {
|
|
const block = this.get(id) as CustomBlockWithEntity;
|
|
this.#blockEntities[i] = block.createBlockEntity();
|
|
}
|
|
|
|
freeCustomBlockEntity(i: number): void {
|
|
delete this.#blockEntities[i];
|
|
}
|
|
}
|
|
|
|
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.getCustomBlockEntityByID(i).fromTag(new CompoundTag(tag));
|
|
});
|
|
|
|
addBridge('CustomBlockEntity.toTag', (i: number, tag: JavaObject): JavaObject => {
|
|
return BlockRegistry.INSTANCE.getCustomBlockEntityByID(i).toTag(new CompoundTag(tag)).getJavaObject();
|
|
});
|
|
|
|
addBridge('CustomBlockEntity.tick', (i: number) => {
|
|
BlockRegistry.INSTANCE.getCustomBlockEntityByID(i).tick();
|
|
});
|
|
|
|
addBridge('CustomBlockEntity.setLocation', (i: number, world: JavaObject, x: number, y: number, z: number) => {
|
|
BlockRegistry.INSTANCE.getCustomBlockEntityByID(i).setLocation(new World(world), new Pos(x, y, z));
|
|
});
|
|
|
|
addBridge('CustomBlockEntity.free', (i: number) => {
|
|
BlockRegistry.INSTANCE.freeCustomBlockEntity(i);
|
|
});
|
|
|
|
addBridge('CustomBlock.onUse', (id: string, world: JavaObject, state: JavaObject, x: number, y: number, z: number, side: keyof typeof Direction, player: JavaObject, hand: keyof typeof Hand): string => {
|
|
return BlockRegistry.INSTANCE.get(new Identifier(id)).onUse(new World(world), new BlockState(state), new Pos(x, y, z), Direction[side], new PlayerEntity(player), Hand[hand]);
|
|
});
|
|
|
|
/**
|
|
* @internal
|
|
*/
|
|
export class BlockBuiltinRegistry implements SimpleBuiltinRegistry<Block> {
|
|
static readonly INSTANCE = new BlockBuiltinRegistry();
|
|
|
|
private constructor() {
|
|
}
|
|
|
|
get(id: Identifier): Block {
|
|
const obj = useBridge('BuiltinRegistry.getBlock', id.toString()) as JavaObject;
|
|
if (obj !== null) {
|
|
return new Block(obj);
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|