Skip to content

Commit 10f69e8

Browse files
committed
Add createPrefab factory function
1 parent 0fee5ff commit 10f69e8

File tree

4 files changed

+264
-0
lines changed

4 files changed

+264
-0
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
},
3434
"devDependencies": {
3535
"@types/jest": "^26.0.24",
36+
"@types/node": "^16.9.1",
3637
"husky": "^7.0.1",
3738
"jest": "^27.0.6",
3839
"lint-staged": "^11.1.1",

src/createPrefab.ts

Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
import { createString } from './createString';
2+
import { Prefab } from './decoders';
3+
import { PrefabHash } from './PrefabHash';
4+
import { PrefabSlot } from './PrefabSlot';
5+
6+
export type PrefabFactory = {
7+
prefab: Prefab;
8+
slots: { [slotName: string]: number };
9+
setPosition: (x: number, y: number, z: number) => PrefabFactory;
10+
setRotation: (x: number, y: number, z: number, w: number) => PrefabFactory;
11+
setKinematic: (isKinematic?: boolean) => PrefabFactory;
12+
setServerSleeping: (isServerSleeping?: boolean) => PrefabFactory;
13+
setVelocity: (x: number, y: number, z: number) => PrefabFactory;
14+
setAngularVelocity: (x: number, y: number, z: number) => PrefabFactory;
15+
setMaterial: (materialHash: number) => PrefabFactory;
16+
setIntegrity: (integrity: number) => PrefabFactory;
17+
setOnFire: (isLit?: boolean) => PrefabFactory;
18+
useSlot: (slotHash: number, childPrefab: PrefabFactory) => PrefabFactory;
19+
toString: () => string;
20+
print: () => void;
21+
};
22+
23+
const availableSlots = (prefabObjectHash: number) => {
24+
const prefabName = PrefabHash[prefabObjectHash];
25+
const slots = PrefabSlot[prefabName as keyof typeof PrefabSlot] ?? {};
26+
const filteredEntries = Object.entries(slots).filter(([key]) => key.startsWith('Slot_'));
27+
28+
return Object.fromEntries(filteredEntries);
29+
};
30+
31+
export const createPrefab = (prefabObjectHash: number): PrefabFactory => ({
32+
prefab: {
33+
prefabObject: { hash: prefabObjectHash },
34+
components: {},
35+
embeddedEntities: {},
36+
childPrefabs: []
37+
},
38+
39+
slots: availableSlots(prefabObjectHash),
40+
41+
setPosition(x, y, z) {
42+
if (typeof x === 'undefined' || typeof y === 'undefined' || typeof z === 'undefined') {
43+
throw new Error(`setPosition called with invalid arguments.\n\nUsage: .setPosition(x, y, z)`);
44+
}
45+
46+
const position = { x, y, z };
47+
48+
this.prefab.prefabObject.position = position;
49+
this.prefab.components!.NetworkRigidbody = {
50+
...this.prefab.components!.NetworkRigidbody,
51+
position
52+
};
53+
54+
return this;
55+
},
56+
57+
setRotation(x, y, z, w) {
58+
if (typeof x === 'undefined' || typeof y === 'undefined' || typeof z === 'undefined' || typeof w === 'undefined') {
59+
throw new Error(`setRotation called with invalid arguments.\n\nUsage: .setRotation(x, y, z, w)`);
60+
}
61+
62+
const rotation = { x, y, z, w };
63+
64+
this.prefab.prefabObject.rotation = rotation;
65+
this.prefab.components!.NetworkRigidbody = {
66+
...this.prefab.components!.NetworkRigidbody,
67+
rotation
68+
};
69+
70+
return this;
71+
},
72+
73+
setKinematic(isKinematic = true) {
74+
this.prefab.components!.NetworkRigidbody = {
75+
...this.prefab.components!.NetworkRigidbody,
76+
isKinematic
77+
};
78+
79+
return this;
80+
},
81+
82+
setServerSleeping(isServerSleeping = true) {
83+
this.prefab.components!.NetworkRigidbody = {
84+
...this.prefab.components!.NetworkRigidbody,
85+
isServerSleeping
86+
};
87+
88+
return this;
89+
},
90+
91+
setVelocity(x, y, z) {
92+
if (typeof x === 'undefined' || typeof y === 'undefined' || typeof z === 'undefined') {
93+
throw new Error(`setVelocity called with invalid arguments.\n\nUsage: .setVelocity(x, y, z)`);
94+
}
95+
96+
const velocity = { x, y, z };
97+
98+
this.prefab.components!.NetworkRigidbody = {
99+
...this.prefab.components!.NetworkRigidbody,
100+
velocity
101+
};
102+
103+
return this;
104+
},
105+
106+
setAngularVelocity(x, y, z) {
107+
if (typeof x === 'undefined' || typeof y === 'undefined' || typeof z === 'undefined') {
108+
throw new Error(`setAngularVelocity called with invalid arguments.\n\nUsage: .setAngularVelocity(x, y, z)`);
109+
}
110+
111+
const angularVelocity = { x, y, z };
112+
113+
this.prefab.components!.NetworkRigidbody = {
114+
...this.prefab.components!.NetworkRigidbody,
115+
angularVelocity
116+
};
117+
118+
return this;
119+
},
120+
121+
setMaterial(materialHash) {
122+
if (typeof materialHash === 'undefined') {
123+
throw new Error(`setMaterial called with invalid arguments.\n\nUsage: .setMaterial(materialHash)`);
124+
}
125+
126+
this.prefab.components = {
127+
...this.prefab.components,
128+
PhysicalMaterialPart: { materialHash }
129+
};
130+
131+
return this;
132+
},
133+
134+
setIntegrity(integrity) {
135+
if (typeof integrity === 'undefined') {
136+
throw new Error(`setIntegrity called with invalid arguments.\n\nUsage: .setIntegrity(integrity)`);
137+
}
138+
139+
this.prefab.components = {
140+
...this.prefab.components,
141+
DurabilityModule: { integrity }
142+
};
143+
144+
return this;
145+
},
146+
147+
setOnFire(isLit = true) {
148+
this.prefab.embeddedEntities!.Fire = {
149+
...this.prefab.embeddedEntities!.Fire,
150+
isAlive: isLit,
151+
components: {
152+
...this.prefab.embeddedEntities!.Fire!.components,
153+
HeatSourceBase: {
154+
...this.prefab.embeddedEntities!.Fire!.components!.HeatSourceBase,
155+
isLit
156+
}
157+
}
158+
};
159+
160+
return this;
161+
},
162+
163+
useSlot(slotHash, childPrefab) {
164+
if (typeof slotHash === 'undefined' || typeof childPrefab === 'undefined') {
165+
throw new Error(`useSlot called with invalid arguments.\n\nUsage: .useSlot(slotHash, prefab)`);
166+
}
167+
168+
const validHashes = Object.values(this.slots);
169+
170+
if (!validHashes.includes(slotHash)) {
171+
const prefabName = PrefabHash[prefabObjectHash];
172+
173+
throw new Error(
174+
`useSlot called with invalid slot hash.\n\n${prefabName} has ${
175+
validHashes.length ? `these valid slots: ${JSON.stringify(this.slots, null, 2)}` : 'no available slots.'
176+
}`
177+
);
178+
}
179+
180+
this.prefab.childPrefabs = [
181+
...this.prefab.childPrefabs!.filter(({ parentHash }) => parentHash !== slotHash),
182+
{
183+
parentHash: slotHash,
184+
prefab: { ...childPrefab.prefab }
185+
}
186+
];
187+
188+
return this;
189+
},
190+
191+
toString() {
192+
return createString(this.prefab);
193+
},
194+
195+
print() {
196+
const string = this.toString();
197+
198+
return console.log(string);
199+
}
200+
});

src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export type {
3535
ChildPrefab
3636
} from './decoders';
3737
export type { Component, KnownComponent, UnknownComponent } from './components';
38+
export type { PrefabFactory } from './createPrefab';
3839

3940
/**
4041
* HASHES
@@ -57,5 +58,6 @@ export * from './utils';
5758
/**
5859
* ATT STRING TRANSCODER
5960
*/
61+
export { createPrefab } from './createPrefab';
6062
export { createString } from './createString';
6163
export { decodeString } from './decodeString';

tests/createPrefab.test.ts

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { createPrefab, PrefabHash, PrefabFactory, NetworkRigidbody } from '../build';
2+
3+
let prefabFactory: PrefabFactory;
4+
5+
describe('createPrefab', () => {
6+
beforeEach(() => {
7+
prefabFactory = createPrefab(PrefabHash.Handle_Short);
8+
});
9+
10+
it('creates a prefab factory', () => {
11+
expect(prefabFactory).toHaveProperty(['prefab', 'prefabObject', 'hash'], PrefabHash.Handle_Short);
12+
});
13+
14+
it('sets new position', () => {
15+
expect(prefabFactory.prefab.prefabObject.position).toBe(undefined);
16+
17+
const x = 0,
18+
y = 69,
19+
z = 420,
20+
position = { x, y, z };
21+
22+
prefabFactory.setPosition(x, y, z);
23+
24+
expect(prefabFactory.prefab.prefabObject.position).toStrictEqual(position);
25+
expect((prefabFactory.prefab.components!.NetworkRigidbody as NetworkRigidbody).position).toStrictEqual(position);
26+
});
27+
28+
it('sets new rotation', () => {
29+
expect(prefabFactory.prefab.prefabObject.rotation).toBe(undefined);
30+
31+
const x = 0,
32+
y = 0.69,
33+
z = 0.42,
34+
w = 0.123,
35+
rotation = { x, y, z, w };
36+
37+
prefabFactory.setRotation(x, y, z, w);
38+
39+
expect(prefabFactory.prefab.prefabObject.rotation).toStrictEqual(rotation);
40+
expect((prefabFactory.prefab.components!.NetworkRigidbody as NetworkRigidbody).rotation).toStrictEqual(rotation);
41+
});
42+
43+
it('uses a slot', () => {
44+
expect(prefabFactory.prefab.childPrefabs).toStrictEqual([]);
45+
46+
const slotHash = 6134;
47+
const guardFactory = createPrefab(PrefabHash.Guard);
48+
prefabFactory.useSlot(slotHash, guardFactory);
49+
50+
expect(prefabFactory.prefab.childPrefabs).toStrictEqual([
51+
{
52+
parentHash: slotHash,
53+
prefab: guardFactory.prefab
54+
}
55+
]);
56+
});
57+
58+
it('outputs a string', () => {
59+
expect(prefabFactory.toString()).toEqual('42230,48,42230,0,0,0,0,0,0,1065353216,1065353216,0,0,0,|0,');
60+
});
61+
});

0 commit comments

Comments
 (0)