@block_factory/lib 0.0.2 → 0.0.3

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/index.d.ts CHANGED
@@ -3,10 +3,29 @@ import { Signal } from "./util/Signal";
3
3
  import { Vec2, Vec3 } from "./util/Vector";
4
4
  import { RawText } from "./util/RawText";
5
5
  import { Command } from "./util/Command";
6
- import { Form } from "./util/Form";
7
- import { ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData } from "./util/FormAction";
6
+ import { System } from "./util/System";
8
7
 
9
- export { MathUtils, Signal, Vec2, Vec3, RawText, Command, Form, ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData }
8
+ import { IForm, IFormValue } from "./util/Forms/Form";
9
+ import { ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData } from "./util/Forms/FormAction";
10
+ import { IModalFormResponse,ITextFieldOptions, IDropdownOptions, ISliderOptions, IToggleOptions, IModalFormData } from "./util/Forms/FormModal";
11
+ import { IMessageFormData, IMessageFormResponse } from "./util/Forms/FormMessage";
12
+ import { IFormRegistration, RegisterForm } from "./util/Forms/FormRegistry";
13
+
14
+ import { Inventory, ContainerWrapper } from "./util/Wrapper/Container";
15
+ import { IEntity, IEntityWrapper } from "./util/Wrapper/IEntity";
16
+ import { IPlayer, IPlayerWrapper } from "./util/Wrapper/IPlayer";
17
+
18
+ import { _THREAD_ } from "./sys/Threads";
19
+
20
+ export {
21
+ MathUtils, Signal, Vec2, Vec3, RawText, Command, System,
22
+ IForm, IFormValue,
23
+ ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData,
24
+ IModalFormResponse, ITextFieldOptions, IDropdownOptions, ISliderOptions, IToggleOptions, IModalFormData,
25
+ IMessageFormData, IMessageFormResponse,
26
+ IFormRegistration, RegisterForm,
27
+ Inventory, ContainerWrapper, IEntity, IEntityWrapper, IPlayer, IPlayerWrapper, _THREAD_
28
+ }
10
29
 
11
30
  export declare const BlockFactory: {
12
31
  MathUtils: typeof MathUtils;
@@ -15,6 +34,14 @@ export declare const BlockFactory: {
15
34
  Vec3: typeof Vec3;
16
35
  RawText: typeof RawText;
17
36
  Command: typeof Command;
18
- Form: typeof Form;
37
+ System: typeof System;
38
+ IForm: typeof IForm;
19
39
  IActionFormData: typeof IActionFormData;
40
+ IModalFormData: typeof IModalFormData;
41
+ IMessageFormData: typeof IMessageFormData;
42
+ RegisterForm: typeof RegisterForm;
43
+ ContainerWrapper: typeof ContainerWrapper
44
+ IEntityWrapper: typeof IEntityWrapper
45
+ IPlayerWrapper: typeof IPlayerWrapper
46
+ _THREAD_: typeof _THREAD_;
20
47
  };
package/index.js CHANGED
@@ -77,31 +77,23 @@ var Signal = class {
77
77
  constructor() {
78
78
  __publicField(this, "listeners", /* @__PURE__ */ new Set());
79
79
  }
80
- /** Connect a listener */
80
+ get count() {
81
+ return this.listeners.size;
82
+ }
81
83
  connect(callback) {
82
84
  this.listeners.add(callback);
83
85
  }
84
- /** Disconnect a listener */
85
86
  disconnect(callback) {
86
- if (callback) {
87
- this.listeners.delete(callback);
88
- return true;
89
- } else {
90
- this.listeners.clear();
91
- return false;
92
- }
87
+ return this.listeners.delete(callback);
93
88
  }
94
- /** Connect a listener that runs only once */
95
- once(callback) {
96
- const wrapper = (data) => {
97
- this.disconnect(wrapper);
98
- callback(data);
99
- };
100
- this.connect(wrapper);
89
+ clear() {
90
+ this.listeners.clear();
91
+ }
92
+ isConnected(callback) {
93
+ return this.listeners.has(callback);
101
94
  }
102
- /** Emit signal to all listeners */
103
95
  emit(data) {
104
- for (const cb of [...this.listeners]) {
96
+ for (const cb of Array.from(this.listeners)) {
105
97
  cb(data);
106
98
  }
107
99
  }
@@ -508,24 +500,60 @@ system.beforeEvents.startup.subscribe(
508
500
  }
509
501
  );
510
502
 
511
- // util/Form.ts
512
- var _Form = class _Form {
503
+ // util/System.ts
504
+ var System;
505
+ ((System2) => {
506
+ System2.ProxyConstructor = ((_instance, source) => {
507
+ return new Proxy(_instance, {
508
+ get: (target, prop) => {
509
+ if (prop in target) return target[prop];
510
+ const v = source[prop];
511
+ return typeof v === "function" ? v.bind(source) : v;
512
+ },
513
+ set: (target, prop, value) => {
514
+ if (prop in target) {
515
+ target[prop] = value;
516
+ return true;
517
+ }
518
+ source[prop] = value;
519
+ return true;
520
+ },
521
+ has: (target, prop) => prop in target || prop in source,
522
+ ownKeys: () => [...Reflect.ownKeys(source), ...Reflect.ownKeys(_instance)],
523
+ getOwnPropertyDescriptor: (_t, prop) => Object.getOwnPropertyDescriptor(prop in _instance ? _instance : source, prop)
524
+ });
525
+ });
526
+ })(System || (System = {}));
527
+
528
+ // util/Forms/Form.ts
529
+ import { world } from "@minecraft/server";
530
+ import { uiManager } from "@minecraft/server-ui";
531
+ var _IForm = class _IForm {
513
532
  static isOccupied(player) {
514
- return _Form.occupiedPlayers.has(player.id);
533
+ return _IForm.occupiedPlayers.has(player.id);
534
+ }
535
+ static closeForms(player) {
536
+ uiManager.closeAllForms(player);
537
+ }
538
+ static closeOccupiedForms() {
539
+ for (const playerId of _IForm.occupiedPlayers) {
540
+ const player = world.getEntity(playerId);
541
+ if (player) uiManager.closeAllForms(player);
542
+ }
515
543
  }
516
544
  setOccupied(player, occupied) {
517
- if (occupied) _Form.occupiedPlayers.add(player.id);
518
- else _Form.occupiedPlayers.delete(player.id);
545
+ if (occupied) _IForm.occupiedPlayers.add(player.id);
546
+ else _IForm.occupiedPlayers.delete(player.id);
519
547
  }
520
548
  };
521
- __publicField(_Form, "occupiedPlayers", /* @__PURE__ */ new Set());
522
- __publicField(_Form, "returnText", "Back");
523
- var Form = _Form;
549
+ __publicField(_IForm, "occupiedPlayers", /* @__PURE__ */ new Set());
550
+ __publicField(_IForm, "returnText", "Back");
551
+ var IForm = _IForm;
524
552
 
525
- // util/FormAction.ts
553
+ // util/Forms/FormAction.ts
526
554
  import { ActionFormData } from "@minecraft/server-ui";
527
555
  var RETURN_ID = "d7213196-4cb6-4199-a40b-22fbf2d944ef";
528
- var IActionFormData = class extends Form {
556
+ var IActionFormData = class extends IForm {
529
557
  constructor() {
530
558
  super(...arguments);
531
559
  __publicField(this, "form", new ActionFormData());
@@ -568,7 +596,7 @@ var IActionFormData = class extends Form {
568
596
  return this;
569
597
  }
570
598
  async show(player) {
571
- if (Form.isOccupied(player)) {
599
+ if (IForm.isOccupied(player)) {
572
600
  throw new Error(`Player ${player.id} is already occupied by form: ${this._id}`);
573
601
  }
574
602
  this.setOccupied(player, true);
@@ -595,7 +623,7 @@ var IActionFormData = class extends Form {
595
623
  this._nextButtonIndex = 0;
596
624
  this.build(player);
597
625
  if (returnStack.length > 0) {
598
- this.form.button(Form.returnText);
626
+ this.form.button(IForm.returnText);
599
627
  this._buttons.set(this._nextButtonIndex, {
600
628
  id: RETURN_ID,
601
629
  subForm: returnStack[returnStack.length - 1],
@@ -628,6 +656,302 @@ var IActionFormData = class extends Form {
628
656
  }
629
657
  };
630
658
 
659
+ // util/Forms/FormModal.ts
660
+ import {
661
+ ModalFormData
662
+ } from "@minecraft/server-ui";
663
+ var IModalFormData = class extends IForm {
664
+ constructor() {
665
+ super(...arguments);
666
+ __publicField(this, "form", new ModalFormData());
667
+ __publicField(this, "_id", "untitled");
668
+ __publicField(this, "_widgetMeta", []);
669
+ }
670
+ title(titleText) {
671
+ this.form.title(titleText);
672
+ this._id = typeof titleText === "string" ? titleText : JSON.stringify(titleText);
673
+ return this;
674
+ }
675
+ divider() {
676
+ this.form.divider();
677
+ return this;
678
+ }
679
+ header(text) {
680
+ this.form.header(text);
681
+ return this;
682
+ }
683
+ label(text) {
684
+ this.form.label(text);
685
+ return this;
686
+ }
687
+ textField(label, options) {
688
+ const opts = { defaultValue: options.defaultValue };
689
+ this.form.textField(label, options.placeholder, opts);
690
+ this._widgetMeta.push({ type: "textField", id: options.id });
691
+ return this;
692
+ }
693
+ dropdown(label, options) {
694
+ const opts = { defaultValueIndex: options.defaultValueIndex };
695
+ this.form.dropdown(label, options.choices, opts);
696
+ this._widgetMeta.push({ type: "dropdown", id: options.id });
697
+ return this;
698
+ }
699
+ slider(label, options) {
700
+ const opts = {
701
+ defaultValue: options.defaultValue,
702
+ valueStep: options.step
703
+ };
704
+ this.form.slider(label, options.min, options.max, opts);
705
+ this._widgetMeta.push({ type: "slider", id: options.id });
706
+ return this;
707
+ }
708
+ toggle(label, options) {
709
+ const opts = { defaultValue: options.defaultValue };
710
+ this.form.toggle(label, opts);
711
+ this._widgetMeta.push({ type: "toggle", id: options.id });
712
+ return this;
713
+ }
714
+ async show(player) {
715
+ if (IForm.isOccupied(player)) {
716
+ throw new Error(`Player ${player.id} is already occupied by form: ${this._id}`);
717
+ }
718
+ this.setOccupied(player, true);
719
+ try {
720
+ return await this._showInternal(player);
721
+ } finally {
722
+ this.setOccupied(player, false);
723
+ }
724
+ }
725
+ _wrapResponse(res, values) {
726
+ return {
727
+ canceled: res.canceled,
728
+ cancelationReason: res.cancelationReason,
729
+ formValues: res.formValues,
730
+ widget: values
731
+ };
732
+ }
733
+ _mapValues(formValues) {
734
+ if (!formValues) return void 0;
735
+ const out = /* @__PURE__ */ new Map();
736
+ for (let i = 0; i < formValues.length; i++) {
737
+ const meta = this._widgetMeta[i];
738
+ if (!meta) continue;
739
+ out.set(meta.id, formValues[i]);
740
+ }
741
+ return out;
742
+ }
743
+ async _showInternal(player) {
744
+ this.form = new ModalFormData();
745
+ this._widgetMeta = [];
746
+ this.build(player);
747
+ const res = await this.form.show(player);
748
+ if (res.canceled) {
749
+ const wrapped2 = this._wrapResponse(res);
750
+ this.onCancel?.(player, wrapped2);
751
+ return wrapped2;
752
+ }
753
+ const values = this._mapValues(res.formValues);
754
+ const wrapped = this._wrapResponse(res, values);
755
+ this.onSubmit(player, wrapped);
756
+ return wrapped;
757
+ }
758
+ };
759
+
760
+ // util/Forms/FormMessage.ts
761
+ import {
762
+ MessageFormData
763
+ } from "@minecraft/server-ui";
764
+ var IMessageFormData = class extends IForm {
765
+ constructor() {
766
+ super(...arguments);
767
+ __publicField(this, "form", new MessageFormData());
768
+ __publicField(this, "_id", "untitled");
769
+ }
770
+ title(titleText) {
771
+ this.form.title(titleText);
772
+ this._id = typeof titleText === "string" ? titleText : JSON.stringify(titleText);
773
+ return this;
774
+ }
775
+ body(bodyText) {
776
+ this.form.body(bodyText);
777
+ return this;
778
+ }
779
+ button0(text, id = 0) {
780
+ this.form.button1(text);
781
+ return this;
782
+ }
783
+ button1(text, id = 1) {
784
+ this.form.button2(text);
785
+ return this;
786
+ }
787
+ async show(player) {
788
+ if (IForm.isOccupied(player)) {
789
+ throw new Error(
790
+ `Player ${player.id} is already occupied by form: ${this._id}`
791
+ );
792
+ }
793
+ this.setOccupied(player, true);
794
+ try {
795
+ return await this._showInternal(player);
796
+ } finally {
797
+ this.setOccupied(player, false);
798
+ }
799
+ }
800
+ async _showInternal(player) {
801
+ this.form = new MessageFormData();
802
+ this.build(player);
803
+ const res = await this.form.show(player);
804
+ if (res.canceled || res.selection === void 0) {
805
+ this.onCancel?.(player, res);
806
+ return res;
807
+ }
808
+ this.onSubmit(player, res);
809
+ return res;
810
+ }
811
+ };
812
+
813
+ // util/Forms/FormRegistry.ts
814
+ import { Player as Player2, world as world2 } from "@minecraft/server";
815
+ var registeredForms = [];
816
+ function RegisterForm(itemId) {
817
+ return function(formCtor) {
818
+ const i = registeredForms.findIndex((r) => r.itemId === itemId);
819
+ if (i !== -1) registeredForms[i] = { itemId, formCtor };
820
+ else registeredForms.push({ itemId, formCtor });
821
+ };
822
+ }
823
+ function getFormForItem(itemId) {
824
+ return registeredForms.find((r) => r.itemId === itemId)?.formCtor;
825
+ }
826
+ world2.afterEvents.itemUse.subscribe((event) => {
827
+ const player = event.source;
828
+ if (!(player instanceof Player2)) return;
829
+ const item = event.itemStack;
830
+ if (!item) return;
831
+ const formCtor = getFormForItem(item.typeId);
832
+ if (!formCtor) return;
833
+ const form = new formCtor();
834
+ form.show(player).catch((e) => {
835
+ player.sendMessage(`\xA7cForm error: ${String(e)}`);
836
+ });
837
+ });
838
+
839
+ // util/Wrapper/Container.ts
840
+ var ContainerWrapper = class _ContainerWrapper {
841
+ constructor(source) {
842
+ __publicField(this, "source");
843
+ this.source = source;
844
+ return System.ProxyConstructor(this, source);
845
+ }
846
+ static wrap(source) {
847
+ return new _ContainerWrapper(source);
848
+ }
849
+ //======================== Interal ========================
850
+ reduce(slot, amount = 1) {
851
+ let itemStack = this.source.getItem(slot);
852
+ let currentAmount = itemStack?.amount || 0;
853
+ currentAmount -= amount;
854
+ if (itemStack != void 0 && currentAmount > 0) {
855
+ const newItemStack = itemStack;
856
+ newItemStack.amount = currentAmount;
857
+ itemStack = newItemStack;
858
+ } else itemStack = void 0;
859
+ this.source.setItem(slot, itemStack);
860
+ }
861
+ };
862
+
863
+ // util/Wrapper/IEntity.ts
864
+ import { EntityInventoryComponent } from "@minecraft/server";
865
+ var IEntityWrapper = class _IEntityWrapper {
866
+ constructor(source) {
867
+ __publicField(this, "source");
868
+ //======================== Interal ========================
869
+ __publicField(this, "isAlive", false);
870
+ this.source = source;
871
+ return System.ProxyConstructor(this, source);
872
+ }
873
+ static wrap(source) {
874
+ return new _IEntityWrapper(source);
875
+ }
876
+ get inventory() {
877
+ const i = this.source.getComponent(
878
+ EntityInventoryComponent.componentId
879
+ );
880
+ return ContainerWrapper.wrap(i.container);
881
+ }
882
+ test() {
883
+ }
884
+ };
885
+
886
+ // util/Wrapper/IPlayer.ts
887
+ import { EntityInventoryComponent as EntityInventoryComponent2 } from "@minecraft/server";
888
+ var IPlayerWrapper = class _IPlayerWrapper {
889
+ constructor(source) {
890
+ __publicField(this, "source");
891
+ //======================== Interal ========================
892
+ __publicField(this, "isAlive", false);
893
+ this.source = source;
894
+ return System.ProxyConstructor(this, source);
895
+ }
896
+ static wrap(player) {
897
+ return new _IPlayerWrapper(player);
898
+ }
899
+ get inventory() {
900
+ const i = this.source.getComponent(
901
+ EntityInventoryComponent2.componentId
902
+ );
903
+ return ContainerWrapper.wrap(i.container);
904
+ }
905
+ test() {
906
+ this.source.sendMessage(`${this.source.name} was tested`);
907
+ }
908
+ };
909
+
910
+ // sys/Threads.ts
911
+ import { system as system2, TicksPerSecond } from "@minecraft/server";
912
+ var Threads = class _Threads {
913
+ constructor() {
914
+ __publicField(this, "MAIN", new Signal());
915
+ __publicField(this, "LATE", new Signal());
916
+ __publicField(this, "MAIN_INTERVAL_RATE", 0);
917
+ __publicField(this, "LATE_INTERVAL_RATE", TicksPerSecond);
918
+ __publicField(this, "_MAIN_ID");
919
+ __publicField(this, "_LATE_ID");
920
+ __publicField(this, "_delta", this.createDeltaTimer());
921
+ this._MAIN_ID = system2.runInterval(() => {
922
+ if (this.MAIN.count <= 0) return;
923
+ try {
924
+ const delta = this._delta();
925
+ this.MAIN.emit(delta);
926
+ } catch (error) {
927
+ throw Error(`ERROR: _THREAD_.MAIN:${this._MAIN_ID} | ${error}`);
928
+ }
929
+ }, this.MAIN_INTERVAL_RATE);
930
+ this._LATE_ID = system2.runInterval(() => {
931
+ if (this.LATE.count <= 0) return;
932
+ try {
933
+ this.LATE.emit();
934
+ } catch (error) {
935
+ throw Error(`ERROR: _THREAD_.LATE:${this._LATE_ID} | ${error}`);
936
+ }
937
+ }, this.LATE_INTERVAL_RATE);
938
+ }
939
+ static create() {
940
+ return new _Threads();
941
+ }
942
+ createDeltaTimer() {
943
+ let last = Date.now();
944
+ return function nextDelta() {
945
+ const now = Date.now();
946
+ const delta = (now - last) / 1e3;
947
+ last = now;
948
+ return delta;
949
+ };
950
+ }
951
+ };
952
+ var _THREAD_ = Threads.create();
953
+ _THREAD_.MAIN_INTERVAL_RATE = 10;
954
+
631
955
  // index.ts
632
956
  var BlockFactory;
633
957
  ((BlockFactory2) => {
@@ -637,17 +961,33 @@ var BlockFactory;
637
961
  Vec3;
638
962
  RawText;
639
963
  Command;
640
- Form;
964
+ System;
965
+ IForm;
641
966
  IActionFormData;
967
+ IModalFormData;
968
+ IMessageFormData;
969
+ RegisterForm;
970
+ ContainerWrapper;
971
+ IEntityWrapper;
972
+ IPlayerWrapper;
973
+ _THREAD_;
642
974
  })(BlockFactory || (BlockFactory = {}));
643
975
  export {
644
976
  BlockFactory,
645
977
  Command,
646
- Form,
978
+ ContainerWrapper,
647
979
  IActionFormData,
980
+ IEntityWrapper,
981
+ IForm,
982
+ IMessageFormData,
983
+ IModalFormData,
984
+ IPlayerWrapper,
648
985
  MathUtils,
649
986
  RawText,
987
+ RegisterForm,
650
988
  Signal,
989
+ System,
651
990
  Vec2,
652
- Vec3
991
+ Vec3,
992
+ _THREAD_
653
993
  };
package/index.ts CHANGED
@@ -3,11 +3,30 @@ import { Signal } from "./util/Signal";
3
3
  import { Vec2, Vec3 } from "./util/Vector";
4
4
  import { RawText } from "./util/RawText";
5
5
  import { Command } from "./util/Command";
6
- import { Form } from "./util/Form";
7
- import { ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData } from "./util/FormAction";
6
+ import { System } from "./util/System";
8
7
 
9
- export { MathUtils, Signal, Vec2, Vec3, RawText, Command, Form, ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData };
8
+ import { IForm, IFormValue } from "./util/Forms/Form";
9
+ import { ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData } from "./util/Forms/FormAction";
10
+ import { IModalFormResponse, ITextFieldOptions, IDropdownOptions, ISliderOptions, IToggleOptions, IModalFormData } from "./util/Forms/FormModal";
11
+ import { IMessageFormData, IMessageFormResponse } from "./util/Forms/FormMessage";
12
+ import { IFormRegistration, RegisterForm } from "./util/Forms/FormRegistry";
10
13
 
14
+ import { Inventory, ContainerWrapper } from "./util/Wrapper/Container";
15
+ import { IEntity, IEntityWrapper } from "./util/Wrapper/IEntity";
16
+ import { IPlayer, IPlayerWrapper } from "./util/Wrapper/IPlayer";
17
+
18
+ import { _THREAD_ } from "./sys/Threads";
19
+
20
+ export {
21
+ MathUtils, Signal, Vec2, Vec3, RawText, Command, System,
22
+ IForm, IFormValue,
23
+ ActionFormCtor, IButtonOptions, IActionFormResponse, IActionFormData,
24
+ IModalFormResponse, ITextFieldOptions, IDropdownOptions, ISliderOptions, IToggleOptions, IModalFormData,
25
+ IMessageFormData, IMessageFormResponse,
26
+ IFormRegistration, RegisterForm,
27
+ Inventory, ContainerWrapper, IEntity, IEntityWrapper, IPlayer, IPlayerWrapper,
28
+ _THREAD_
29
+ };
11
30
 
12
31
  export namespace BlockFactory {
13
32
  MathUtils;
@@ -16,6 +35,14 @@ export namespace BlockFactory {
16
35
  Vec3;
17
36
  RawText;
18
37
  Command;
19
- Form;
38
+ System;
39
+ IForm;
20
40
  IActionFormData;
41
+ IModalFormData;
42
+ IMessageFormData;
43
+ RegisterForm;
44
+ ContainerWrapper;
45
+ IEntityWrapper;
46
+ IPlayerWrapper
47
+ _THREAD_;
21
48
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@block_factory/lib",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "description": "Typescript Library for Minecraft Bedrock Edition",
@@ -27,6 +27,7 @@
27
27
  "esbuild": "^0.27.2"
28
28
  },
29
29
  "scripts": {
30
- "build": "node esbuild.config.mjs"
30
+ "build": "node esbuild.config.mjs",
31
+ "build:types": "tsc -p tsconfig.types.json"
31
32
  }
32
33
  }
@@ -0,0 +1,16 @@
1
+ import { Signal } from "../util/Signal";
2
+ declare class Threads {
3
+ static create(): Threads;
4
+ readonly MAIN: Signal<number>;
5
+ readonly LATE: Signal<void>;
6
+ MAIN_INTERVAL_RATE: number;
7
+ LATE_INTERVAL_RATE: number;
8
+ private _MAIN_ID;
9
+ private _LATE_ID;
10
+ private _delta;
11
+ private constructor();
12
+ private createDeltaTimer;
13
+ }
14
+ export declare const _THREAD_: Threads;
15
+ export {};
16
+ //# sourceMappingURL=Threads.d.ts.map
package/sys/Threads.ts ADDED
@@ -0,0 +1,43 @@
1
+ import { system, TicksPerSecond } from "@minecraft/server";
2
+ import { Signal } from "../util/Signal";
3
+
4
+ class Threads {
5
+ public static create(): Threads { return new Threads() }
6
+ public readonly MAIN = new Signal<number>();
7
+ public readonly LATE = new Signal();
8
+ public MAIN_INTERVAL_RATE: number = 0;
9
+ public LATE_INTERVAL_RATE: number = TicksPerSecond;
10
+
11
+ private _MAIN_ID: number;
12
+ private _LATE_ID: number;
13
+ private _delta = this.createDeltaTimer();
14
+
15
+ private constructor() {
16
+ this._MAIN_ID = system.runInterval(() => {
17
+ if (this.MAIN.count <= 0) return;
18
+ try { const delta = this._delta(); this.MAIN.emit(delta) }
19
+ catch (error) {
20
+ throw Error(`ERROR: _THREAD_.MAIN:${this._MAIN_ID} | ${error}`)
21
+ }
22
+ }, this.MAIN_INTERVAL_RATE);
23
+
24
+ this._LATE_ID = system.runInterval(() => {
25
+ if (this.LATE.count <= 0) return;
26
+ try { this.LATE.emit() }
27
+ catch (error) { throw Error(`ERROR: _THREAD_.LATE:${this._LATE_ID} | ${error}`) }
28
+ }, this.LATE_INTERVAL_RATE);
29
+ }
30
+
31
+ private createDeltaTimer() {
32
+ let last = Date.now();
33
+
34
+ return function nextDelta(): number {
35
+ const now = Date.now();
36
+ const delta = (now - last) / 1000; // seconds
37
+ last = now;
38
+ return delta;
39
+ };
40
+ }
41
+ }
42
+
43
+ export const _THREAD_ = Threads.create();
@@ -0,0 +1,13 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "emitDeclarationOnly": true,
5
+ "noEmit": false,
6
+ "outDir": "dist",
7
+ "rootDir": ".",
8
+ "declaration": true,
9
+ "declarationMap": true
10
+ },
11
+ "include": ["**/*.ts"],
12
+ "exclude": ["node_modules", "dist"]
13
+ }
@@ -0,0 +1,16 @@
1
+ import { Player, RawMessage } from "@minecraft/server";
2
+
3
+ export declare type IFormValue =
4
+ | string
5
+ | boolean
6
+ | number
7
+ | undefined;
8
+
9
+ export declare abstract class IForm {
10
+ static returnText: RawMessage | string;
11
+ static isOccupied(player: Player): boolean;
12
+ static closeForms(player: Player): void;
13
+ static closeOccupiedForms(): void;
14
+ protected setOccupied(player: Player, occupied: boolean): void;
15
+ protected abstract build(player: Player): void;
16
+ }