@block_factory/lib 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/_module/BlockFactory.ts +4 -5
  2. package/_module/Framework/EntityTasks.ts +12 -51
  3. package/_module/Framework/ItemTasks.ts +157 -0
  4. package/_module/Framework/PlayerTasks.ts +125 -0
  5. package/_module/Framework/Threads.ts +2 -2
  6. package/_module/util/Signal.ts +71 -7
  7. package/_module/util/Wrapper/IEntity.ts +1 -1
  8. package/_module/util/Wrapper/IPlayer.ts +1 -1
  9. package/_types/_module/BlockFactory.d.ts +4 -4
  10. package/_types/_module/BlockFactory.d.ts.map +1 -1
  11. package/_types/_module/DataTypes.d.ts +10 -0
  12. package/_types/_module/DataTypes.d.ts.map +1 -0
  13. package/_types/_module/Framework/EntityTasks.d.ts +4 -7
  14. package/_types/_module/Framework/EntityTasks.d.ts.map +1 -1
  15. package/_types/_module/Framework/ItemTasks.d.ts +59 -0
  16. package/_types/_module/Framework/ItemTasks.d.ts.map +1 -0
  17. package/_types/_module/Framework/PlayerTasks.d.ts +28 -0
  18. package/_types/_module/Framework/PlayerTasks.d.ts.map +1 -0
  19. package/_types/_module/Framework/Threads.d.ts +2 -2
  20. package/_types/_module/Framework/Threads.d.ts.map +1 -1
  21. package/_types/_module/util/Signal.d.ts +63 -4
  22. package/_types/_module/util/Signal.d.ts.map +1 -1
  23. package/_types/_module/util/Wrapper/IEntity.d.ts +1 -1
  24. package/_types/_module/util/Wrapper/IEntity.d.ts.map +1 -1
  25. package/_types/_module/util/Wrapper/IPlayer.d.ts +1 -1
  26. package/_types/_module/util/Wrapper/IPlayer.d.ts.map +1 -1
  27. package/index.js +306 -53
  28. package/package.json +4 -2
  29. package/typedoc.json +6 -0
  30. package/_module/Framework/_INIT.ts +0 -39
  31. package/_types/_module/Framework/_INIT.d.ts +0 -19
  32. package/_types/_module/Framework/_INIT.d.ts.map +0 -1
  33. /package/_module/{Types.ts → DataTypes.ts} +0 -0
@@ -1,5 +1,3 @@
1
- export { _INITIALIZE_BF_FRAMEWORK_ } from "@block_factory/lib/_module/Framework/_INIT";
2
-
3
1
  export { MathUtils } from "./util/Math";
4
2
  export { Signal } from "./util/Signal";
5
3
  export { Vec2, Vec3 } from "./util/Vector";
@@ -17,6 +15,7 @@ export { Inventory, ContainerWrapper } from "./util/Wrapper/Container";
17
15
  export { type IEntity, IEntityWrapper } from "./util/Wrapper/IEntity";
18
16
  export { type IPlayer, IPlayerWrapper } from "./util/Wrapper/IPlayer";
19
17
 
20
- export { type Sound, type Animation } from "./Types";
21
- export { _THREAD_ } from "@block_factory/lib/_module/Framework/Threads";
22
- export { _EntityHandler_, type EntityEmissionEvent, onEntityEmission } from "@block_factory/lib/_module/Framework/EntityTasks";
18
+ export { Thread } from "./Framework/Threads";
19
+ export { PlayerHandler } from "./Framework/PlayerTasks";
20
+ export { EntityHandler, type EntityEmissionEvent } from "./Framework/EntityTasks";
21
+ export { ItemHandler, type ItemRegistration, type OnItemHeldEvent, type OnItemUnheldEvent, type WhileHoldingItemEvent } from "./Framework/ItemTasks";
@@ -1,59 +1,30 @@
1
- import {
2
- Entity,
3
- system,
4
- ScriptEventCommandMessageAfterEvent,
5
- ScriptEventCommandMessageAfterEventSignal,
6
- world,
7
- WorldLoadAfterEventSignal,
8
- WorldLoadAfterEvent,
9
- EntitySpawnAfterEventSignal,
10
- EntityRemoveAfterEventSignal,
11
- EntitySpawnAfterEvent,
12
- EntityRemoveAfterEvent,
13
- EntityRemoveBeforeEvent,
14
- EntityRemoveBeforeEventSignal,
15
- } from "@minecraft/server";
1
+ import { Entity, system, ScriptEventCommandMessageAfterEvent, ScriptEventCommandMessageAfterEventSignal, world, WorldLoadAfterEventSignal, WorldLoadAfterEvent, EntitySpawnAfterEventSignal, EntitySpawnAfterEvent, EntityRemoveBeforeEvent, EntityRemoveBeforeEventSignal } from "@minecraft/server";
16
2
 
17
3
  import { Signal } from "../util/Signal";
18
4
  import { IEntityWrapper, IEntity } from "../util/Wrapper/IEntity";
19
5
 
20
- /* -------------------------------------------------------------------------- */
21
- /* Public API */
22
- /* -------------------------------------------------------------------------- */
23
-
24
6
  export type EntityEmissionEvent = {
25
7
  iEntity: IEntity;
26
8
  parms: any;
27
9
  };
28
10
 
29
- export const onEntityEmission = new Signal<EntityEmissionEvent>();
30
-
31
- /* -------------------------------------------------------------------------- */
32
- /* Singleton */
33
- /* -------------------------------------------------------------------------- */
34
-
35
-
36
-
37
- class EntityHandler {
11
+ class SingletonEntityHandler {
38
12
  private PACK_ID: string | undefined;
39
- private GLOBAL_MEMORY_ID = "GLB_MEM.ENTITY";
13
+
14
+ public readonly onEntityEmission = new Signal<EntityEmissionEvent>();
15
+ private readonly GLOBAL_MEMORY_ID = "GLB_MEM.ENTITY";
40
16
 
41
17
  private readonly scriptEventSignal: ScriptEventCommandMessageAfterEventSignal = system.afterEvents.scriptEventReceive;
42
18
  private readonly loadEventSignal: WorldLoadAfterEventSignal = world.afterEvents.worldLoad;
43
19
  private readonly spawnEventSignal: EntitySpawnAfterEventSignal = world.afterEvents.entitySpawn;
44
- private readonly removeAfterEventSignal: EntityRemoveAfterEventSignal = world.afterEvents.entityRemove;
45
20
  private readonly removeBeforeEventSignal: EntityRemoveBeforeEventSignal = world.beforeEvents.entityRemove;
46
21
 
47
22
  private readonly EM_INDEX = new Map<string, Entity>();
48
23
  private readonly EM_KEYS: string[] = [];
49
24
  private readonly SEARCH_TYPES = new Set<string>();
50
25
 
51
- private _started = false;
52
- private _wired = false;
53
-
54
- public configure(): void {
55
- if (this._started) throw new Error("BFLIB: EntityHandler already started;");
56
- }
26
+ private _started: boolean = false;
27
+ private _wired: boolean = false;
57
28
 
58
29
  public registerEntity(typeId: string | string[]): void {
59
30
  if (Array.isArray(typeId)) typeId.forEach((t) => this.SEARCH_TYPES.add(t));
@@ -61,10 +32,9 @@ class EntityHandler {
61
32
  }
62
33
 
63
34
  public start(packId: string): void {
64
- if (this._started) return;
35
+ if (this._started) throw new Error("BFLIB: EntityHandler already started;");
65
36
  this._started = true;
66
37
  this.PACK_ID = packId;
67
-
68
38
  this.loadEventSignal.subscribe(this.onWorldLoad);
69
39
  }
70
40
 
@@ -76,7 +46,6 @@ class EntityHandler {
76
46
  this.scriptEventSignal.unsubscribe(this.processScriptEvents);
77
47
  this.spawnEventSignal.unsubscribe(this.onEntitySpawned);
78
48
  this.removeBeforeEventSignal.unsubscribe(this.onEntityRemovedBefore);
79
- this.removeAfterEventSignal.unsubscribe(this.onEntityRemovedAfter);
80
49
  this._wired = false;
81
50
  }
82
51
 
@@ -87,14 +56,12 @@ class EntityHandler {
87
56
  /* Event Wiring */
88
57
  /* ------------------------------------------------------------------------ */
89
58
 
90
- private onWorldLoad = (_event: WorldLoadAfterEvent): void => {
91
-
59
+ private onWorldLoad = (): void => {
92
60
  this.scriptEventSignal.subscribe(this.processScriptEvents);
93
61
 
94
62
  if (this.SEARCH_TYPES.size > 0) {
95
63
  this.spawnEventSignal.subscribe(this.onEntitySpawned);
96
64
  this.removeBeforeEventSignal.subscribe(this.onEntityRemovedBefore);
97
- this.removeAfterEventSignal.subscribe(this.onEntityRemovedAfter);
98
65
  }
99
66
 
100
67
  this._wired = true;
@@ -114,10 +81,7 @@ class EntityHandler {
114
81
  return;
115
82
  }
116
83
 
117
- onEntityEmission.emit({
118
- iEntity: IEntityWrapper.wrap(event.sourceEntity),
119
- parms,
120
- });
84
+ this.onEntityEmission.emit({ iEntity: IEntityWrapper.wrap(event.sourceEntity), parms });
121
85
  };
122
86
 
123
87
  /* ------------------------------------------------------------------------ */
@@ -125,6 +89,7 @@ class EntityHandler {
125
89
  /* ------------------------------------------------------------------------ */
126
90
 
127
91
  private isValidType(typeId: string): boolean {
92
+ if (this.PACK_ID && !typeId.startsWith(this.PACK_ID)) return false;
128
93
  return this.SEARCH_TYPES.has(typeId);
129
94
  }
130
95
 
@@ -140,10 +105,6 @@ class EntityHandler {
140
105
  this.deleteEntityInMemory(entity);
141
106
  };
142
107
 
143
- private onEntityRemovedAfter = (_event: EntityRemoveAfterEvent): void => {
144
- //
145
- };
146
-
147
108
  /* ------------------------------------------------------------------------ */
148
109
  /* Persistence */
149
110
  /* ------------------------------------------------------------------------ */
@@ -200,4 +161,4 @@ class EntityHandler {
200
161
  }
201
162
  }
202
163
 
203
- export const _EntityHandler_ = new EntityHandler();
164
+ export const EntityHandler = new SingletonEntityHandler();
@@ -0,0 +1,157 @@
1
+ import { Signal } from "../util/Signal.js";
2
+ import { ItemCompleteUseAfterEvent, ItemCompleteUseAfterEventSignal, ItemReleaseUseAfterEvent, ItemReleaseUseAfterEventSignal, ItemStack, ItemStartUseAfterEvent, ItemStartUseAfterEventSignal, ItemStartUseOnAfterEvent, ItemStartUseOnAfterEventSignal, ItemStopUseAfterEvent, ItemStopUseAfterEventSignal, ItemStopUseOnAfterEvent, ItemStopUseOnAfterEventSignal, ItemUseAfterEvent, ItemUseAfterEventSignal, ItemUseBeforeEvent, ItemUseBeforeEventSignal, Player, PlayerHotbarSelectedSlotChangeAfterEvent, PlayerHotbarSelectedSlotChangeAfterEventSignal, PlayerInventoryItemChangeAfterEvent, PlayerInventoryItemChangeAfterEventSignal, system, world, WorldLoadAfterEvent, WorldLoadAfterEventSignal } from "@minecraft/server";
3
+
4
+ export type ItemRegistration = {
5
+ typeId: string;
6
+ emitWhileHolding?: boolean
7
+ emitOnUse?: boolean;
8
+ }
9
+
10
+ export type WhileHoldingItemEvent = { player: Player; itemStack: ItemStack };
11
+ export type OnItemHeldEvent = { player: Player; itemStack: ItemStack };
12
+ export type OnItemUnheldEvent = { player: Player; itemStack: ItemStack | undefined };
13
+ export type OnItemUsedEvent = { player: Player; itemStack: ItemStack };
14
+
15
+ interface HoldData {
16
+ instanceId: number;
17
+ itemStack: ItemStack;
18
+ }
19
+
20
+ class SingletonItemHandler {
21
+ private PACK_ID: string | undefined;
22
+
23
+ public readonly whileHoldingItemEvent = new Signal<WhileHoldingItemEvent>();
24
+ public readonly onItemHeldEvent = new Signal<OnItemHeldEvent>();
25
+ public readonly onItemUnheldEvent = new Signal<OnItemUnheldEvent>();
26
+ public readonly onItemUsedEvent = new Signal<OnItemUsedEvent>();
27
+
28
+ private readonly loadEventSignal: WorldLoadAfterEventSignal = world.afterEvents.worldLoad;
29
+ private readonly useBeforeSignal: ItemUseBeforeEventSignal = world.beforeEvents.itemUse;
30
+ private readonly useAfterSignal: ItemUseAfterEventSignal = world.afterEvents.itemUse;
31
+ private readonly completeUseSignal: ItemCompleteUseAfterEventSignal = world.afterEvents.itemCompleteUse;
32
+ private readonly releaseUseSignal: ItemReleaseUseAfterEventSignal = world.afterEvents.itemReleaseUse;
33
+ private readonly startUseSignal: ItemStartUseAfterEventSignal = world.afterEvents.itemStartUse;
34
+ private readonly startUseOnSignal: ItemStartUseOnAfterEventSignal = world.afterEvents.itemStartUseOn;
35
+ private readonly stopUseSignal: ItemStopUseAfterEventSignal = world.afterEvents.itemStopUse;
36
+ private readonly stopUseOnSignal: ItemStopUseOnAfterEventSignal = world.afterEvents.itemStopUseOn;
37
+ private readonly inventoryItemChangeSignal: PlayerInventoryItemChangeAfterEventSignal = world.afterEvents.playerInventoryItemChange;
38
+ private readonly hotbarChangeSignal: PlayerHotbarSelectedSlotChangeAfterEventSignal = world.afterEvents.playerHotbarSelectedSlotChange;
39
+
40
+ private readonly IM_INDEX = new Map<string, ItemRegistration>();
41
+ private readonly HOLD_INDEX: Map<string, HoldData> = new Map<string, HoldData>();
42
+
43
+ private _started = false;
44
+ private _wired = false;
45
+
46
+ public registerItem(itemRegistration: ItemRegistration | ItemRegistration[]): void {
47
+ if (Array.isArray(itemRegistration)) itemRegistration.forEach(i => this.IM_INDEX.set(i.typeId, i));
48
+ else this.IM_INDEX.set(itemRegistration.typeId, itemRegistration);
49
+ }
50
+
51
+ public start(packId: string): void {
52
+ if (this._started) throw new Error("BFLIB: ItemHandler already started;");
53
+ this._started = true;
54
+ this.PACK_ID = packId;
55
+ this.loadEventSignal.subscribe(this.onWorldLoad);
56
+ }
57
+
58
+ public stop(): void {
59
+ if (!this._started) return;
60
+
61
+ this.loadEventSignal.unsubscribe(this.onWorldLoad);
62
+
63
+ if (this._wired) {
64
+ this.useBeforeSignal.unsubscribe(this.onUseBefore);
65
+ this.useAfterSignal.unsubscribe(this.onUseAfter);
66
+ this.completeUseSignal.unsubscribe(this.onCompleteUse);
67
+ this.releaseUseSignal.unsubscribe(this.onReleaseUse);
68
+ this.startUseSignal.unsubscribe(this.onStartUse);
69
+ this.startUseOnSignal.unsubscribe(this.onStartUseOn);
70
+ this.stopUseSignal.unsubscribe(this.onStopUse);
71
+ this.stopUseOnSignal.unsubscribe(this.onStopUseOn);
72
+ this.hotbarChangeSignal.unsubscribe(this.onHotbarChange);
73
+ this.inventoryItemChangeSignal.unsubscribe(this.onInventoryItemChange);
74
+
75
+ this._wired = false;
76
+ }
77
+
78
+ this._started = false;
79
+ }
80
+
81
+
82
+ private onWorldLoad = (): void => {
83
+ if (this.IM_INDEX.size > 0) {
84
+ this.useBeforeSignal.subscribe(this.onUseBefore);
85
+ this.useAfterSignal.subscribe(this.onUseAfter);
86
+ this.completeUseSignal.subscribe(this.onCompleteUse);
87
+ this.releaseUseSignal.subscribe(this.onReleaseUse);
88
+ this.startUseSignal.subscribe(this.onStartUse);
89
+ this.startUseOnSignal.subscribe(this.onStartUseOn);
90
+ this.stopUseSignal.subscribe(this.onStopUse);
91
+ this.stopUseOnSignal.subscribe(this.onStopUseOn);
92
+ this.hotbarChangeSignal.subscribe(this.onHotbarChange);
93
+ this.inventoryItemChangeSignal.subscribe(this.onInventoryItemChange);
94
+
95
+ this._wired = true;
96
+ }
97
+
98
+ this.loadEventSignal.unsubscribe(this.onWorldLoad);
99
+ };
100
+
101
+
102
+ private onUseBefore = (event: ItemUseBeforeEvent): void => {
103
+ const itemStack: ItemStack = event.itemStack;
104
+ if (!this.isValidType(itemStack.typeId)) return;
105
+ const i: ItemRegistration | undefined = this.IM_INDEX.get(itemStack.typeId);
106
+ if (!i || !i.emitOnUse) return;
107
+ const runId: number = system.run(() => {
108
+ try { this.onItemUsedEvent.emit({ player: event.source, itemStack: event.itemStack }) }
109
+ catch (error) { throw new Error(`${error}`) }
110
+ finally { system.clearRun(runId) }
111
+ })
112
+
113
+ };
114
+ private onUseAfter = (_event: ItemUseAfterEvent): void => { };
115
+ private onCompleteUse = (_event: ItemCompleteUseAfterEvent): void => { };
116
+ private onReleaseUse = (_event: ItemReleaseUseAfterEvent): void => { };
117
+ private onStartUse = (_event: ItemStartUseAfterEvent): void => { };
118
+ private onStartUseOn = (_event: ItemStartUseOnAfterEvent): void => { };
119
+ private onStopUse = (_event: ItemStopUseAfterEvent): void => { };
120
+ private onStopUseOn = (_event: ItemStopUseOnAfterEvent): void => { };
121
+ private onInventoryItemChange = (_event: PlayerInventoryItemChangeAfterEvent): void => { };
122
+
123
+ private onHotbarChange = (event: PlayerHotbarSelectedSlotChangeAfterEvent): void => {
124
+ const itemStack: ItemStack | undefined = event.itemStack;
125
+ if (this.HOLD_INDEX.has(event.player.id)) this.releaseHold(event.player);
126
+ if (!itemStack || (itemStack && !this.isValidType(itemStack.typeId))) return;
127
+ this.setNewHold(itemStack, event.player);
128
+ };
129
+
130
+ private setNewHold(itemStack: ItemStack, player: Player) {
131
+ this.onItemHeldEvent.emit({ player: player, itemStack: itemStack });
132
+
133
+ const i: ItemRegistration | undefined = this.IM_INDEX.get(itemStack.typeId);
134
+ let instanceId: number = -1
135
+ if (i && i.emitWhileHolding) {
136
+ instanceId = system.runInterval(() => {
137
+ this.whileHoldingItemEvent.emit({ player: player, itemStack: itemStack });
138
+ })
139
+ }
140
+ this.HOLD_INDEX.set(player.id, { instanceId: instanceId, itemStack: itemStack });
141
+ }
142
+
143
+ private releaseHold(player: Player) {
144
+ const holdData: HoldData | undefined = this.HOLD_INDEX.get(player.id);
145
+ if (!holdData) return;
146
+ this.onItemUnheldEvent.emit({ player: player, itemStack: holdData.itemStack });
147
+ if (holdData.instanceId !== -1) system.clearRun(holdData.instanceId);
148
+ this.HOLD_INDEX.delete(player.id);
149
+ }
150
+
151
+ private isValidType(typeId: string): boolean {
152
+ if (this.PACK_ID && !typeId.startsWith(this.PACK_ID)) return false;
153
+ return this.IM_INDEX.has(typeId);
154
+ }
155
+ }
156
+
157
+ export const ItemHandler = new SingletonItemHandler();
@@ -0,0 +1,125 @@
1
+ import { IPlayerWrapper, IPlayer } from "../util/Wrapper/IPlayer";
2
+ import { ButtonState, InputButton, Player, PlayerButtonInputAfterEvent, PlayerButtonInputAfterEventSignal, PlayerLeaveBeforeEvent, PlayerLeaveBeforeEventSignal, PlayerSpawnAfterEvent, PlayerSpawnAfterEventSignal, world, WorldLoadAfterEvent, WorldLoadAfterEventSignal } from "@minecraft/server";
3
+
4
+ class SingletonPlayerHandler {
5
+ private readonly GLOBAL_MEMORY_ID = "GLB_MEM.PLAYER";
6
+
7
+ private readonly loadEventSignal: WorldLoadAfterEventSignal = world.afterEvents.worldLoad;
8
+ private readonly playerSpawnSignal: PlayerSpawnAfterEventSignal = world.afterEvents.playerSpawn;
9
+ private readonly playerLeaveBeforeSignal: PlayerLeaveBeforeEventSignal = world.beforeEvents.playerLeave;
10
+ private readonly buttonInputSignal: PlayerButtonInputAfterEventSignal = world.afterEvents.playerButtonInput;
11
+
12
+ private readonly PR_INDEX = new Map<string, Player>();
13
+ private readonly PR_KEYS: string[] = [];
14
+
15
+ private _started: boolean = false;
16
+ private _wired: boolean = false;
17
+
18
+ public start(): void {
19
+ if (this._started) throw new Error("BFLIB: PlayerHandler already started;");
20
+ this._started = true;
21
+ this.onSystemLoad();
22
+ this.loadEventSignal.subscribe(this.onWorldLoad);
23
+ this.buttonInputSignal.subscribe(this.onButtonPress);
24
+ }
25
+
26
+ public stop(): void {
27
+ if (!this._started) return;
28
+ if (this._wired) {
29
+ this.playerSpawnSignal.unsubscribe(this.onPlayerSpawned);
30
+ this.playerLeaveBeforeSignal.unsubscribe(this.onPlayerLeaveBefore);
31
+ this.buttonInputSignal.unsubscribe(this.onButtonPress);
32
+ this._wired = false;
33
+ }
34
+ this._started = false;
35
+ }
36
+
37
+ private onWorldLoad = (): void => {
38
+ this.reloadPlayerMemory();
39
+ this.loadEventSignal.unsubscribe(this.onWorldLoad);
40
+ };
41
+
42
+ private onSystemLoad(): void {
43
+ this.playerSpawnSignal.subscribe(this.onPlayerSpawned);
44
+ this.playerLeaveBeforeSignal.subscribe(this.onPlayerLeaveBefore);
45
+ this._wired = true;
46
+ }
47
+
48
+ private onPlayerSpawned = (event: PlayerSpawnAfterEvent): void => {
49
+ if (!event) return;
50
+ if (this.hasPlayer(event.player.id)) return;
51
+ this.savePlayerInMemory(event.player);
52
+ };
53
+
54
+ private onPlayerLeaveBefore = (event: PlayerLeaveBeforeEvent): void => {
55
+ if (!this.hasPlayer(event.player.id)) return;
56
+ this.deletePlayerInMemory(event.player);
57
+ };
58
+
59
+ private onButtonPress = (event: PlayerButtonInputAfterEvent): void => {
60
+ if (event.button === InputButton.Jump) {
61
+
62
+ }
63
+ else if (event.button === InputButton.Sneak) {
64
+
65
+ }
66
+ console.warn(`Player ${event.player.name} pressed button ${InputButton[event.button]}: ${ButtonState[event.newButtonState]}`);
67
+ };
68
+
69
+ public hasPlayer(playerId: string): boolean {
70
+ return this.PR_INDEX.has(playerId);
71
+ }
72
+
73
+ /* ------------------------------------------------------------------------ */
74
+ /* Persistence */
75
+ /* ------------------------------------------------------------------------ */
76
+
77
+ private reloadPlayerMemory(): void {
78
+ this.PR_INDEX.clear();
79
+ this.PR_KEYS.length = 0;
80
+
81
+ const players: Player[] = world.getAllPlayers();
82
+ for (const player of players) {
83
+ this.PR_INDEX.set(player.id, player);
84
+ this.PR_KEYS.push(player.id);
85
+ }
86
+ }
87
+
88
+
89
+
90
+ private persistKeys(): void {
91
+ world.setDynamicProperty(this.GLOBAL_MEMORY_ID, JSON.stringify(this.PR_KEYS));
92
+ }
93
+
94
+ public savePlayerInMemory(player: Player): boolean {
95
+ if (this.PR_INDEX.has(player.id)) return false;
96
+ this.PR_KEYS.push(player.id);
97
+ this.PR_INDEX.set(player.id, player);
98
+ this.persistKeys();
99
+
100
+ return true;
101
+ }
102
+
103
+ public deletePlayerInMemory(player: Player): boolean {
104
+ const existed = this.PR_INDEX.delete(player.id);
105
+ if (!existed) return false;
106
+
107
+ const idx = this.PR_KEYS.indexOf(player.id);
108
+ if (idx !== -1) this.PR_KEYS.splice(idx, 1);
109
+
110
+ this.persistKeys();
111
+
112
+ return true;
113
+ }
114
+
115
+ public getPlayersInMemory(): Player[] {
116
+ return Array.from(this.PR_INDEX.values());
117
+ }
118
+
119
+ public getIPlayersInMemory(): IPlayer[] {
120
+ return Array.from(this.PR_INDEX.values())
121
+ .map(player => IPlayerWrapper.wrap(player));
122
+ }
123
+ }
124
+
125
+ export const PlayerHandler = new SingletonPlayerHandler();
@@ -6,7 +6,7 @@ export type ThreadConfig = {
6
6
  lateRate?: number; // interval ticks
7
7
  };
8
8
 
9
- class Threads {
9
+ class SingletonThreadManager {
10
10
  public readonly MAIN = new Signal<number>();
11
11
  public readonly LATE = new Signal<void>();
12
12
 
@@ -69,4 +69,4 @@ class Threads {
69
69
  }
70
70
  }
71
71
 
72
- export const _THREAD_ = new Threads();
72
+ export const Thread = new SingletonThreadManager();
@@ -1,33 +1,97 @@
1
- export type Callback<T> = (data: T) => void;
1
+ /**
2
+ * Function signature for signal subscription callbacks.
3
+ *
4
+ * @template T Payload type emitted by the signal
5
+ */
6
+ export type SubscriptionCallback<T> = (data: T) => void;
2
7
 
8
+ /**
9
+ * Lightweight signal / event dispatcher inspired by Godot's signal system.
10
+ *
11
+ * Signals allow decoupled communication by emitting typed payloads to
12
+ * subscribed listeners.
13
+ *
14
+ * @template T Payload type (use `void` for no data)
15
+ */
3
16
  export class Signal<T = void> {
4
- private readonly listeners = new Set<Callback<T>>();
17
+ /**
18
+ * Registered signal listeners.
19
+ */
20
+ private readonly listeners = new Set<SubscriptionCallback<T>>();
5
21
 
22
+ /**
23
+ * Number of currently subscribed listeners.
24
+ */
6
25
  public get count(): number {
7
26
  return this.listeners.size;
8
27
  }
9
28
 
10
- public connect(callback: Callback<T>): void {
29
+ /**
30
+ * Subscribes a callback to this signal.
31
+ *
32
+ * The callback will be invoked every time the signal is emitted
33
+ * until it is explicitly unsubscribed or the signal is cleared.
34
+ *
35
+ * @param callback Function invoked on signal emission
36
+ */
37
+ public subscribe(callback: SubscriptionCallback<T>): void {
11
38
  this.listeners.add(callback);
12
39
  }
13
40
 
14
- public disconnect(callback: Callback<T>): boolean {
41
+ /**
42
+ * Unsubscribes a previously registered callback.
43
+ *
44
+ * @param callback Callback to remove
45
+ * @returns `true` if the callback was removed, `false` otherwise
46
+ */
47
+ public unsubscribe(callback: SubscriptionCallback<T>): boolean {
15
48
  return this.listeners.delete(callback);
16
49
  }
17
50
 
51
+ /**
52
+ * Removes all subscribed listeners from this signal.
53
+ */
18
54
  public clear(): void {
19
55
  this.listeners.clear();
20
56
  }
21
57
 
22
- public isConnected(callback: Callback<T>): boolean {
58
+ /**
59
+ * Checks whether a callback is currently subscribed.
60
+ *
61
+ * @param callback Callback to test
62
+ * @returns `true` if the callback is subscribed
63
+ */
64
+ public isSubscribed(callback: SubscriptionCallback<T>): boolean {
23
65
  return this.listeners.has(callback);
24
66
  }
25
67
 
68
+ /**
69
+ * Emits the signal immediately, invoking all subscribed callbacks.
70
+ *
71
+ * Listener errors are caught and logged to prevent a single failure
72
+ * from interrupting signal propagation.
73
+ *
74
+ * @param data Payload to pass to listeners
75
+ */
26
76
  public emit(data: T): void {
27
77
  for (const callback of Array.from(this.listeners)) {
28
- try { callback(data) } catch (err) {
29
- console.error("BFLIB: Signal listener error:", err);
78
+ try {
79
+ callback(data);
80
+ } catch (err) {
81
+ console.error("BFLIB: Subscription listener error:", err);
30
82
  }
31
83
  }
32
84
  }
85
+
86
+ /**
87
+ * Emits the signal asynchronously on the microtask queue.
88
+ *
89
+ * Useful for deferring execution to avoid re-entrancy issues
90
+ * or emitting during unsafe execution phases.
91
+ *
92
+ * @param data Payload to pass to listeners
93
+ */
94
+ public emitDeferred(data: T): void {
95
+ queueMicrotask(() => this.emit(data));
96
+ }
33
97
  }
@@ -1,7 +1,7 @@
1
1
  import { Entity, EntityInventoryComponent, PlayAnimationOptions, system, TicksPerSecond } from "@minecraft/server";
2
2
  import { ContainerWrapper, Inventory } from "./Container";
3
3
  import { System } from "../System";
4
- import { Animation } from "../../Types";
4
+ import { Animation } from "../../DataTypes";
5
5
 
6
6
  export type IEntity = IEntityWrapper & Entity;
7
7
 
@@ -1,7 +1,7 @@
1
1
  import { EntityInventoryComponent, PlayAnimationOptions, Player, PlayerSoundOptions, system, TicksPerSecond } from "@minecraft/server";
2
2
  import { ContainerWrapper, Inventory } from "./Container";
3
3
  import { System } from "../System";
4
- import { Animation, Sound } from "../../Types";
4
+ import { Animation, Sound } from "../../DataTypes";
5
5
 
6
6
  export type IPlayer = IPlayerWrapper & Player;
7
7
 
@@ -1,4 +1,3 @@
1
- export { _INITIALIZE_BF_FRAMEWORK_ } from "@block_factory/lib/_module/Framework/_INIT";
2
1
  export { MathUtils } from "./util/Math";
3
2
  export { Signal } from "./util/Signal";
4
3
  export { Vec2, Vec3 } from "./util/Vector";
@@ -13,7 +12,8 @@ export { type IFormRegistration, RegisterForm } from "./util/Forms/FormRegistry"
13
12
  export { Inventory, ContainerWrapper } from "./util/Wrapper/Container";
14
13
  export { type IEntity, IEntityWrapper } from "./util/Wrapper/IEntity";
15
14
  export { type IPlayer, IPlayerWrapper } from "./util/Wrapper/IPlayer";
16
- export { type Sound, type Animation } from "./Types";
17
- export { _THREAD_ } from "@block_factory/lib/_module/Framework/Threads";
18
- export { _EntityHandler_, type EntityEmissionEvent, onEntityEmission } from "@block_factory/lib/_module/Framework/EntityTasks";
15
+ export { Thread } from "./Framework/Threads";
16
+ export { PlayerHandler } from "./Framework/PlayerTasks";
17
+ export { EntityHandler, type EntityEmissionEvent } from "./Framework/EntityTasks";
18
+ export { ItemHandler, type ItemRegistration, type OnItemHeldEvent, type OnItemUnheldEvent, type WhileHoldingItemEvent } from "./Framework/ItemTasks";
19
19
  //# sourceMappingURL=BlockFactory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BlockFactory.d.ts","sourceRoot":"","sources":["../../_module/BlockFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,4CAA4C,CAAC;AAEvF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC9H,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC/K,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAC5F,OAAO,EAAE,KAAK,iBAAiB,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEjF,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,KAAK,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,KAAK,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEtE,OAAO,EAAE,KAAK,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,8CAA8C,CAAC;AACxE,OAAO,EAAE,eAAe,EAAG,KAAK,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,kDAAkD,CAAC"}
1
+ {"version":3,"file":"BlockFactory.d.ts","sourceRoot":"","sources":["../../_module/BlockFactory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AACzC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAEvC,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,mBAAmB,EAAE,KAAK,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC9H,OAAO,EAAE,KAAK,kBAAkB,EAAE,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC/K,OAAO,EAAE,KAAK,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAC5F,OAAO,EAAE,KAAK,iBAAiB,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAEjF,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAE,KAAK,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,KAAK,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAEtE,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAG,KAAK,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,eAAe,EAAE,KAAK,iBAAiB,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,10 @@
1
+ export type Sound = {
2
+ id: string;
3
+ length: number;
4
+ };
5
+ export type Animation = {
6
+ id: string;
7
+ length: number;
8
+ loop?: boolean;
9
+ };
10
+ //# sourceMappingURL=DataTypes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTypes.d.ts","sourceRoot":"","sources":["../../_module/DataTypes.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,KAAK,GAAG;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,SAAS,GAAG;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,CAAC;CAClB,CAAA"}
@@ -5,36 +5,33 @@ export type EntityEmissionEvent = {
5
5
  iEntity: IEntity;
6
6
  parms: any;
7
7
  };
8
- export declare const onEntityEmission: Signal<EntityEmissionEvent>;
9
- declare class EntityHandler {
8
+ declare class SingletonEntityHandler {
9
+ onEntityEmission: Signal<EntityEmissionEvent>;
10
10
  private PACK_ID;
11
11
  private GLOBAL_MEMORY_ID;
12
12
  private readonly scriptEventSignal;
13
13
  private readonly loadEventSignal;
14
14
  private readonly spawnEventSignal;
15
- private readonly removeAfterEventSignal;
16
15
  private readonly removeBeforeEventSignal;
17
16
  private readonly EM_INDEX;
18
17
  private readonly EM_KEYS;
19
18
  private readonly SEARCH_TYPES;
20
19
  private _started;
21
20
  private _wired;
22
- configure(): void;
23
21
  registerEntity(typeId: string | string[]): void;
24
- start(): void;
22
+ start(packId: string): void;
25
23
  stop(): void;
26
24
  private onWorldLoad;
27
25
  private processScriptEvents;
28
26
  private isValidType;
29
27
  private onEntitySpawned;
30
28
  private onEntityRemovedBefore;
31
- private onEntityRemovedAfter;
32
29
  private reloadEntityMemory;
33
30
  private persistKeys;
34
31
  saveEntityInMemory(entity: Entity): boolean;
35
32
  deleteEntityInMemory(entity: Entity): boolean;
36
33
  getEntitiesInMemory(): Entity[];
37
34
  }
38
- export declare const _EntityHandler_: EntityHandler;
35
+ export declare const EntityHandler: SingletonEntityHandler;
39
36
  export {};
40
37
  //# sourceMappingURL=EntityTasks.d.ts.map