@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.
- package/_module/BlockFactory.ts +4 -5
- package/_module/Framework/EntityTasks.ts +12 -51
- package/_module/Framework/ItemTasks.ts +157 -0
- package/_module/Framework/PlayerTasks.ts +125 -0
- package/_module/Framework/Threads.ts +2 -2
- package/_module/util/Signal.ts +71 -7
- package/_module/util/Wrapper/IEntity.ts +1 -1
- package/_module/util/Wrapper/IPlayer.ts +1 -1
- package/_types/_module/BlockFactory.d.ts +4 -4
- package/_types/_module/BlockFactory.d.ts.map +1 -1
- package/_types/_module/DataTypes.d.ts +10 -0
- package/_types/_module/DataTypes.d.ts.map +1 -0
- package/_types/_module/Framework/EntityTasks.d.ts +4 -7
- package/_types/_module/Framework/EntityTasks.d.ts.map +1 -1
- package/_types/_module/Framework/ItemTasks.d.ts +59 -0
- package/_types/_module/Framework/ItemTasks.d.ts.map +1 -0
- package/_types/_module/Framework/PlayerTasks.d.ts +28 -0
- package/_types/_module/Framework/PlayerTasks.d.ts.map +1 -0
- package/_types/_module/Framework/Threads.d.ts +2 -2
- package/_types/_module/Framework/Threads.d.ts.map +1 -1
- package/_types/_module/util/Signal.d.ts +63 -4
- package/_types/_module/util/Signal.d.ts.map +1 -1
- package/_types/_module/util/Wrapper/IEntity.d.ts +1 -1
- package/_types/_module/util/Wrapper/IEntity.d.ts.map +1 -1
- package/_types/_module/util/Wrapper/IPlayer.d.ts +1 -1
- package/_types/_module/util/Wrapper/IPlayer.d.ts.map +1 -1
- package/index.js +306 -53
- package/package.json +4 -2
- package/typedoc.json +6 -0
- package/_module/Framework/_INIT.ts +0 -39
- package/_types/_module/Framework/_INIT.d.ts +0 -19
- package/_types/_module/Framework/_INIT.d.ts.map +0 -1
- /package/_module/{Types.ts → DataTypes.ts} +0 -0
package/_module/BlockFactory.ts
CHANGED
|
@@ -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 {
|
|
21
|
-
export {
|
|
22
|
-
export {
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
/* -------------------------------------------------------------------------- */
|
|
32
|
-
/* Singleton */
|
|
33
|
-
/* -------------------------------------------------------------------------- */
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class EntityHandler {
|
|
11
|
+
class SingletonEntityHandler {
|
|
38
12
|
private PACK_ID: string | undefined;
|
|
39
|
-
|
|
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)
|
|
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 = (
|
|
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
|
|
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
|
|
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
|
|
72
|
+
export const Thread = new SingletonThreadManager();
|
package/_module/util/Signal.ts
CHANGED
|
@@ -1,33 +1,97 @@
|
|
|
1
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|
|
29
|
-
|
|
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 "../../
|
|
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 "../../
|
|
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 {
|
|
17
|
-
export {
|
|
18
|
-
export {
|
|
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,
|
|
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 @@
|
|
|
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
|
-
|
|
9
|
-
|
|
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
|
|
35
|
+
export declare const EntityHandler: SingletonEntityHandler;
|
|
39
36
|
export {};
|
|
40
37
|
//# sourceMappingURL=EntityTasks.d.ts.map
|