import { World } from './world'; import { addBridge } from 'scriptcraft-core'; import { PlayerEntity } from './entity'; import { ActionResult, Hand, Pos, Direction } from './core'; /** * Event */ class Event { /** * @internal */ #listeners: ((obj: T) => K)[] = []; /** * @internal */ #defaultValue: K; /** * @internal */ constructor(defaultValue: K) { this.#defaultValue = defaultValue; } /** * Add Event Listener * @param listener Event Listener */ addListener(listener: (obj: T) => K): void { this.#listeners.push(listener); } /** * Remove Event Listener * @param listener Event Listener */ removeListener(listener: (obj: T) => K): void { const index = this.#listeners.indexOf(listener, 0); if (index > -1) { this.#listeners.splice(index, 1); } } /** * @internal */ run(obj: T): K { for (const listener of this.#listeners) { const value = listener(obj); if (this.#defaultValue !== null && value != this.#defaultValue) { return value; } } return this.#defaultValue; } } /** * Tick Event */ class WorldTickEvent { /** * @internal */ readonly #world: World; /** * Get World * @returns World */ getWorld(): World { return this.#world; } /** * @internal */ constructor(world: World) { this.#world = world; } } /** * Block Event */ class BlockEvent { /** * @internal */ readonly #world: World; /** * @internal */ readonly #player: PlayerEntity; /** * @internal */ readonly #hand: Hand; /** * @internal */ readonly #pos: Pos; /** * @internal */ readonly #side: Direction; /** * Get World * @returns World */ getWorld(): World { return this.#world; } /** * Get Player * @returns Player */ getPlayer(): PlayerEntity { return this.#player; } /** * Get Hand * @returns Hand */ getHand(): Hand { return this.#hand; } /** * Get Block Position * @returns Block Position */ getPos(): Pos { return this.#pos; } /** * Get Block Side * @returns Block Side */ getSide(): Direction { return this.#side; } /** * @internal */ constructor(player: PlayerEntity, world: World, hand: Hand, pos: Pos, side: Direction) { this.#player = player; this.#world = world; this.#hand = hand; this.#pos = pos; this.#side = side; } } /** * Item Event */ class ItemEvent { /** * @internal */ readonly #world: World; /** * @internal */ readonly #player: PlayerEntity; /** * @internal */ readonly #hand: Hand; /** * Get World * @returns World */ getWorld(): World { return this.#world; } /** * Get Player * @returns Player */ getPlayer(): PlayerEntity { return this.#player; } /** * Get Hand * @returns Hand */ getHand(): Hand { return this.#hand; } /** * @internal */ constructor(player: PlayerEntity, world: World, hand: Hand) { this.#player = player; this.#world = world; this.#hand = hand; } } /** * All Events */ export class Events { /** * World Tick Event */ static WORLD_TICK = new Event(null); /** * Attack Block Event */ static ATTACK_BLOCK = new Event(ActionResult.PASS); /** * Use Block Event */ static USE_BLOCK = new Event(ActionResult.PASS); /** * Use Item Event */ static USE_ITEM = new Event(ActionResult.PASS); } addBridge('Event.worldTick', (world: JavaObject) => Events.WORLD_TICK.run(new WorldTickEvent(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.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.useItem', (player: JavaObject, world: JavaObject, hand: keyof typeof Hand) => Events.USE_ITEM.run(new ItemEvent(new PlayerEntity(player), new World(world), Hand[hand])));