This repository has been archived on 2023-11-26. You can view files and clone it, but cannot push or open issues or pull requests.
ScriptCraft/scriptcraft/src/main/ts/src/minecraft/block.ts

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;
}
}
}