@rbxts/covenant 3.5.1 → 3.7.0

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/package.json CHANGED
@@ -1,48 +1,48 @@
1
- {
2
- "name": "@rbxts/covenant",
3
- "version": "3.5.1",
4
- "main": "src/init.luau",
5
- "scripts": {
6
- "build": "rbxtsc",
7
- "watch": "rbxtsc -w",
8
- "prepublishOnly": "npm run build"
9
- },
10
- "repository": {
11
- "type": "git",
12
- "url": "git+https://github.com/cuberootmctoasted/covenant.git"
13
- },
14
- "keywords": [],
15
- "author": "",
16
- "license": "ISC",
17
- "bugs": {
18
- "url": "https://github.com/cuberootmctoasted/covenant/issues"
19
- },
20
- "homepage": "https://github.com/cuberootmctoasted/covenant#readme",
21
- "description": "",
22
- "types": "src/covenant.d.ts",
23
- "files": [
24
- "src",
25
- "!**/*.tsbuildinfo"
26
- ],
27
- "publishConfig": {
28
- "access": "public"
29
- },
30
- "devDependencies": {
31
- "@rbxts/compiler-types": "^3.0.0-types.0",
32
- "@rbxts/covenant": "^2.1.1",
33
- "@rbxts/types": "^1.0.891",
34
- "@typescript-eslint/eslint-plugin": "^8.47.0",
35
- "@typescript-eslint/parser": "^8.47.0",
36
- "eslint": "^9.39.1",
37
- "eslint-config-prettier": "^10.1.8",
38
- "eslint-plugin-prettier": "^5.5.4",
39
- "eslint-plugin-roblox-ts": "^1.3.0",
40
- "prettier": "^3.6.2",
41
- "roblox-ts": "^3.0.0",
42
- "typescript": "^5.9.3"
43
- },
44
- "dependencies": {
45
- "@rbxts/jecs": "^0.9.0",
46
- "@rbxts/services": "^1.6.0"
47
- }
48
- }
1
+ {
2
+ "name": "@rbxts/covenant",
3
+ "version": "3.7.0",
4
+ "main": "src/init.luau",
5
+ "scripts": {
6
+ "build": "rbxtsc",
7
+ "watch": "rbxtsc -w",
8
+ "prepublishOnly": "npm run build"
9
+ },
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "git+https://github.com/cuberootmctoasted/covenant.git"
13
+ },
14
+ "keywords": [],
15
+ "author": "",
16
+ "license": "ISC",
17
+ "bugs": {
18
+ "url": "https://github.com/cuberootmctoasted/covenant/issues"
19
+ },
20
+ "homepage": "https://github.com/cuberootmctoasted/covenant#readme",
21
+ "description": "",
22
+ "types": "src/covenant.d.ts",
23
+ "files": [
24
+ "src",
25
+ "!**/*.tsbuildinfo"
26
+ ],
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "devDependencies": {
31
+ "@rbxts/compiler-types": "^3.0.0-types.0",
32
+ "@rbxts/covenant": "^2.1.1",
33
+ "@rbxts/types": "^1.0.891",
34
+ "@typescript-eslint/eslint-plugin": "^8.47.0",
35
+ "@typescript-eslint/parser": "^8.47.0",
36
+ "eslint": "^9.39.1",
37
+ "eslint-config-prettier": "^10.1.8",
38
+ "eslint-plugin-prettier": "^5.5.4",
39
+ "eslint-plugin-roblox-ts": "^1.3.0",
40
+ "prettier": "^3.6.2",
41
+ "roblox-ts": "^3.0.0",
42
+ "typescript": "^5.9.3"
43
+ },
44
+ "dependencies": {
45
+ "@rbxts/jecs": "^0.9.0",
46
+ "@rbxts/services": "^1.6.0"
47
+ }
48
+ }
package/src/covenant.d.ts CHANGED
@@ -4,8 +4,9 @@ import { Remove, Delete } from "./stringEnums";
4
4
  export * from "@rbxts/jecs";
5
5
  export type WorldChangesForReplication = Map<string, Delete | Map<string, defined | Remove>>;
6
6
  export type WorldChangesForPrediction = Map<string, Map<string, defined | Remove>>;
7
+ export type LoggingOption = "FORCE_ON" | "FORCE_OFF" | "COMPONENT_CONTROLLED";
7
8
  export interface CovenantProps {
8
- logging: boolean;
9
+ logging: LoggingOption;
9
10
  requestPayloadSend: () => void;
10
11
  requestPayloadConnect: (callback: (player: Player) => void) => void;
11
12
  replicationSend: (player: Player, worldChanges: WorldChangesForReplication) => void;
@@ -25,6 +26,7 @@ export declare class Covenant {
25
26
  private undefinedStringifiedComponents;
26
27
  private replicatedStringifiedComponents;
27
28
  private predictedStringifiedComponents;
29
+ private loggingStringfiedComponents;
28
30
  private stringfiedComponentsToNameMap;
29
31
  private started;
30
32
  private stringifiedComponentSubscribers;
@@ -41,9 +43,7 @@ export declare class Covenant {
41
43
  constructor({ logging, requestPayloadSend, requestPayloadConnect, replicationSend, replicationConnect, replicationSendAll, predictionSend, predictionConnect, }: CovenantProps);
42
44
  getClientEntity(entity: Entity): Entity | undefined;
43
45
  getServerEntity(entity: Entity): Entity | undefined;
44
- private logging;
45
- enableLogging(): void;
46
- disableLogging(): void;
46
+ private loggingOption;
47
47
  private setupPredictionClient;
48
48
  private forEachComponentChanges;
49
49
  private setupPredictionServer;
@@ -63,14 +63,16 @@ export declare class Covenant {
63
63
  worldTag(): Entity<undefined>;
64
64
  private checkComponentDefined;
65
65
  private defineComponentNetworkBehavior;
66
- defineComponent<T extends defined>({ component, queriedComponents, recipe, replicated, predictionValidator, }: {
66
+ defineComponent<T extends defined>({ logging, component, queriedComponents, recipe, replicated, predictionValidator, }: {
67
+ logging?: true;
67
68
  replicated: boolean;
68
69
  predictionValidator: ComponentPredictionValidator | false;
69
70
  component: Entity<T>;
70
71
  queriedComponents: Entity[][];
71
72
  recipe: (entity: Entity, lastState: T | undefined, updateId: number, hooks: CovenantHooks) => T | undefined;
72
73
  }): void;
73
- defineIdentity<T extends defined>({ identityComponent, replicated, lifetime, factory, }: {
74
+ defineIdentity<T extends defined>({ logging, identityComponent, replicated, lifetime, factory, }: {
75
+ logging?: true;
74
76
  identityComponent: Entity<T>;
75
77
  replicated: boolean;
76
78
  lifetime: (entity: Entity, state: T, despawn: () => void) => (() => void) | undefined;
package/src/covenant.luau CHANGED
@@ -46,13 +46,14 @@ do
46
46
  self.undefinedStringifiedComponents = {}
47
47
  self.replicatedStringifiedComponents = {}
48
48
  self.predictedStringifiedComponents = {}
49
+ self.loggingStringfiedComponents = {}
49
50
  self.stringfiedComponentsToNameMap = {}
50
51
  self.started = false
51
52
  self.stringifiedComponentSubscribers = {}
52
53
  self.stringifiedComponentValidators = {}
53
54
  self.clientToServerEntityMap = {}
54
55
  self.serverToClientEntityMap = {}
55
- self.logging = logging
56
+ self.loggingOption = logging
56
57
  self.requestPayloadSend = requestPayloadSend
57
58
  self.requestPayloadConnect = requestPayloadConnect
58
59
  self.replicationSend = replicationSend
@@ -73,12 +74,6 @@ do
73
74
  local _arg0 = tostring(entity)
74
75
  return _clientToServerEntityMap[_arg0]
75
76
  end
76
- function Covenant:enableLogging()
77
- self.logging = true
78
- end
79
- function Covenant:disableLogging()
80
- self.logging = false
81
- end
82
77
  function Covenant:setupPredictionClient()
83
78
  self:schedule(RunService.Heartbeat, function()
84
79
  if next(self.worldChangesForPrediction) == nil then
@@ -378,7 +373,17 @@ do
378
373
  else
379
374
  self._world:set(entity, component, newState)
380
375
  end
381
- if self.logging and RunService:IsStudio() then
376
+ local _condition = RunService:IsStudio() and self.loggingOption ~= "FORCE_OFF"
377
+ if _condition then
378
+ local _condition_1 = self.loggingOption == "FORCE_ON"
379
+ if not _condition_1 then
380
+ local _loggingStringfiedComponents = self.loggingStringfiedComponents
381
+ local _arg0 = tostring(component)
382
+ _condition_1 = _loggingStringfiedComponents[_arg0] ~= nil
383
+ end
384
+ _condition = _condition_1
385
+ end
386
+ if _condition then
382
387
  print(`{self:getComponentName(component)}.{entity}.[{if doNotReconcile then "remote" else "local"}]:{tableToString(lastState)}->{tableToString(newState)}`)
383
388
  end
384
389
  local _stringifiedComponentSubscribers = self.stringifiedComponentSubscribers
@@ -397,13 +402,13 @@ do
397
402
  if doNotReconcile then
398
403
  return nil
399
404
  end
400
- local _condition = RunService:IsServer()
401
- if _condition then
405
+ local _condition_1 = RunService:IsServer()
406
+ if _condition_1 then
402
407
  local _replicatedStringifiedComponents = self.replicatedStringifiedComponents
403
408
  local _arg0_1 = tostring(component)
404
- _condition = _replicatedStringifiedComponents[_arg0_1] ~= nil
409
+ _condition_1 = _replicatedStringifiedComponents[_arg0_1] ~= nil
405
410
  end
406
- if _condition then
411
+ if _condition_1 then
407
412
  local _worldChangesForReplication = self.worldChangesForReplication
408
413
  local _arg0_1 = tostring(entity)
409
414
  local entityChanges = _worldChangesForReplication[_arg0_1]
@@ -421,13 +426,13 @@ do
421
426
  _entityChanges[_arg0_2] = _arg1
422
427
  end
423
428
  end
424
- local _condition_1 = RunService:IsClient()
425
- if _condition_1 then
429
+ local _condition_2 = RunService:IsClient()
430
+ if _condition_2 then
426
431
  local _predictedStringifiedComponents = self.predictedStringifiedComponents
427
432
  local _arg0_1 = tostring(component)
428
- _condition_1 = _predictedStringifiedComponents[_arg0_1] ~= nil
433
+ _condition_2 = _predictedStringifiedComponents[_arg0_1] ~= nil
429
434
  end
430
- if _condition_1 then
435
+ if _condition_2 then
431
436
  local _worldChangesForPrediction = self.worldChangesForPrediction
432
437
  local _arg0_1 = tostring(component)
433
438
  local componentChanges = _worldChangesForPrediction[_arg0_1]
@@ -553,6 +558,7 @@ do
553
558
  end
554
559
  end
555
560
  function Covenant:defineComponent(_param)
561
+ local logging = _param.logging
556
562
  local component = _param.component
557
563
  local queriedComponents = _param.queriedComponents
558
564
  local recipe = _param.recipe
@@ -560,6 +566,11 @@ do
560
566
  local predictionValidator = _param.predictionValidator
561
567
  self:checkComponentDefined(component)
562
568
  self:defineComponentNetworkBehavior(component, replicated, predictionValidator)
569
+ if logging then
570
+ local _loggingStringfiedComponents = self.loggingStringfiedComponents
571
+ local _arg0 = tostring(component)
572
+ _loggingStringfiedComponents[_arg0] = true
573
+ end
563
574
  local queryThisComponent = self:worldQuery(component):cached()
564
575
  local willUpdate = true
565
576
  local function indicateUpdate()
@@ -567,21 +578,7 @@ do
567
578
  end
568
579
  local hooks = createHooks({
569
580
  indicateUpdate = indicateUpdate,
570
- subscribeComponent = function(component, subscriber)
571
- self:subscribeComponent(component, subscriber)
572
- end,
573
- getPayloadQueue = function(component)
574
- local queue = {}
575
- for entity, state in self:worldQuery(component) do
576
- local _arg0 = {
577
- entity = entity,
578
- state = state,
579
- previousState = nil,
580
- }
581
- table.insert(queue, _arg0)
582
- end
583
- return queue
584
- end,
581
+ covenant = self,
585
582
  })
586
583
  -- ▼ ReadonlyArray.map ▼
587
584
  local _newValue = table.create(#queriedComponents)
@@ -681,11 +678,17 @@ do
681
678
  end)
682
679
  end
683
680
  function Covenant:defineIdentity(_param)
681
+ local logging = _param.logging
684
682
  local identityComponent = _param.identityComponent
685
683
  local replicated = _param.replicated
686
684
  local lifetime = _param.lifetime
687
685
  local factory = _param.factory
688
686
  self:checkComponentDefined(identityComponent)
687
+ if logging then
688
+ local _loggingStringfiedComponents = self.loggingStringfiedComponents
689
+ local _arg0 = tostring(identityComponent)
690
+ _loggingStringfiedComponents[_arg0] = true
691
+ end
689
692
  self:defineComponentNetworkBehavior(identityComponent, replicated, false)
690
693
  factory(function(state)
691
694
  local entity = self:worldEntity()
package/src/hooks.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Entity } from "@rbxts/jecs";
2
+ import { Covenant } from "./covenant";
2
3
  type AsyncResult<T = unknown> = {
3
4
  completed: boolean;
4
5
  value: T | undefined;
@@ -13,6 +14,10 @@ export interface CovenantHooks {
13
14
  state: T | undefined;
14
15
  previousState: T | undefined;
15
16
  }[];
17
+ useComponentChangeOfEntity: <T extends defined>(updateId: number, entity: Entity, component: Entity<T>, payload: boolean) => {
18
+ state: T | undefined;
19
+ previousState: T | undefined;
20
+ } | undefined;
16
21
  useAsync: <T>(updateId: number, asnycFactory: () => T, dependencies: unknown[], discriminator: Discriminator) => AsyncResult<T>;
17
22
  useImperative: <T extends defined>(updateId: number, dirtyFactory: (indicateUpdate: () => void) => {
18
23
  value: T;
@@ -23,12 +28,7 @@ export interface CovenantHooks {
23
28
  }
24
29
  interface CovenantHooksProps {
25
30
  indicateUpdate: () => void;
26
- subscribeComponent: <T extends defined>(component: Entity<T>, subscriber: (entity: Entity, state: T | undefined, previousState: T | undefined) => void) => void;
27
- getPayloadQueue: <T extends defined>(component: Entity<T>) => {
28
- entity: Entity;
29
- state: T | undefined;
30
- previousState: T | undefined;
31
- }[];
31
+ covenant: Covenant;
32
32
  }
33
33
  export declare function createHooks(props: CovenantHooksProps): CovenantHooks;
34
34
  export {};
package/src/hooks.luau CHANGED
@@ -77,9 +77,8 @@ local function createUseEventImmediately(_param)
77
77
  end
78
78
  end
79
79
  local function createUseComponentChange(_param)
80
- local subscribeComponent = _param.subscribeComponent
80
+ local covenant = _param.covenant
81
81
  local indicateUpdate = _param.indicateUpdate
82
- local getPayloadQueue = _param.getPayloadQueue
83
82
  local queues = {}
84
83
  local watchedStringifiedComponents = {}
85
84
  local caches = {}
@@ -100,7 +99,7 @@ local function createUseComponentChange(_param)
100
99
  if not (watchedStringifiedComponents[stringifiedComponent] ~= nil) then
101
100
  watchedStringifiedComponents[stringifiedComponent] = true
102
101
  queues[stringifiedComponent] = {}
103
- subscribeComponent(component, function(entity, state, previousState)
102
+ covenant:subscribeComponent(component, function(entity, state, previousState)
104
103
  local _exp = queues[stringifiedComponent]
105
104
  local _arg0 = {
106
105
  entity = entity,
@@ -114,7 +113,16 @@ local function createUseComponentChange(_param)
114
113
  if not payload then
115
114
  return {}
116
115
  else
117
- return getPayloadQueue(component)
116
+ local payloadQueue = {}
117
+ for entity, state in covenant:worldQuery(component) do
118
+ local _arg0 = {
119
+ entity = entity,
120
+ state = state,
121
+ previousState = nil,
122
+ }
123
+ table.insert(payloadQueue, _arg0)
124
+ end
125
+ return payloadQueue
118
126
  end
119
127
  end
120
128
  local queue = queues[stringifiedComponent]
@@ -125,6 +133,64 @@ local function createUseComponentChange(_param)
125
133
  return queue
126
134
  end
127
135
  end
136
+ local function createUseComponentChangeOfEntity(_param)
137
+ local covenant = _param.covenant
138
+ local indicateUpdate = _param.indicateUpdate
139
+ local changes = {}
140
+ local watchedStringifiedComponents = {}
141
+ local caches = {}
142
+ local lastUpdateId = -1
143
+ return function(updateId, entity, component, payload)
144
+ if payload == nil then
145
+ payload = false
146
+ end
147
+ if lastUpdateId ~= updateId then
148
+ table.clear(caches)
149
+ lastUpdateId = updateId
150
+ end
151
+ local stringifiedComponent = tostring(component)
152
+ local cache = caches[stringifiedComponent]
153
+ if cache ~= nil then
154
+ return if cache == false then nil else cache
155
+ end
156
+ if not (watchedStringifiedComponents[stringifiedComponent] ~= nil) then
157
+ watchedStringifiedComponents[stringifiedComponent] = true
158
+ covenant:subscribeComponent(component, function(anEntity, state, previousState)
159
+ if entity ~= anEntity then
160
+ return nil
161
+ end
162
+ local _arg1 = {
163
+ state = state,
164
+ previousState = previousState,
165
+ }
166
+ changes[stringifiedComponent] = _arg1
167
+ indicateUpdate()
168
+ end)
169
+ caches[stringifiedComponent] = false
170
+ if not payload then
171
+ return nil
172
+ else
173
+ if not covenant:worldContains(entity) then
174
+ return nil
175
+ end
176
+ local state = covenant:worldGet(entity, component)
177
+ if state == nil then
178
+ return nil
179
+ end
180
+ return {
181
+ state = state,
182
+ previousState = nil,
183
+ }
184
+ end
185
+ end
186
+ local change = changes[stringifiedComponent]
187
+ if change ~= nil then
188
+ changes[stringifiedComponent] = nil
189
+ end
190
+ caches[stringifiedComponent] = change
191
+ return change
192
+ end
193
+ end
128
194
  local function equalsDependencies(a, b)
129
195
  if a == b then
130
196
  return true
@@ -357,6 +423,7 @@ local function createHooks(props)
357
423
  useEvent = createUseEvent(props),
358
424
  useEventImmediately = createUseEventImmediately(props),
359
425
  useComponentChange = createUseComponentChange(props),
426
+ useComponentChangeOfEntity = createUseComponentChangeOfEntity(props),
360
427
  useAsync = createUseAsync(props),
361
428
  useImperative = createUseImperative(props),
362
429
  useChange = createUseChange(),