Skip to content

Commit 00dea08

Browse files
fix: loading composite file system (#530)
Co-authored-by: Gon Pombo <[email protected]>
1 parent a6aff2b commit 00dea08

38 files changed

+276
-125
lines changed

packages/@dcl/ecs/src/composite/instance.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,16 @@ export function getComponentDefinition(
7575
const existingComponentDefinition = engine.getComponentOrNull(component.name)
7676

7777
if (!existingComponentDefinition) {
78-
if (component.jsonSchema) {
79-
return engine.defineComponentFromSchema(component.name, Schemas.fromJson(component.jsonSchema))
80-
} else if (component.name.startsWith('core::')) {
78+
if (component.name.startsWith('core::')) {
8179
if (component.name in componentDefinitionByName) {
8280
return (componentDefinitionByName as any)[component.name](
8381
engine
8482
) as LastWriteWinElementSetComponentDefinition<unknown>
8583
} else {
8684
throw new Error(`The core component ${component.name} was not found.`)
8785
}
86+
} else if (component.jsonSchema) {
87+
return engine.defineComponentFromSchema(component.name, Schemas.fromJson(component.jsonSchema))
8888
} else {
8989
throw new Error(`${component.name} is not defined and there is no schema to define it.`)
9090
}

packages/@dcl/inspector/src/lib/data-layer/client/feeded-local-fs.ts

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,130 @@
11
import { createFsInMemory } from '../../logic/in-memory-storage'
22

3+
export const minimalComposite = {
4+
version: 1,
5+
components: [
6+
{
7+
name: 'core::Transform',
8+
data: {
9+
'512': {
10+
$case: 'json',
11+
json: {
12+
position: {
13+
x: 8,
14+
y: 1,
15+
z: 8
16+
}
17+
}
18+
}
19+
}
20+
},
21+
{
22+
name: 'core::MeshRenderer',
23+
data: {
24+
'512': {
25+
$case: 'json',
26+
json: {
27+
mesh: {
28+
$case: 'box',
29+
box: {
30+
uvs: []
31+
}
32+
}
33+
}
34+
}
35+
}
36+
},
37+
{
38+
name: 'core::MeshCollider',
39+
data: {
40+
'512': {
41+
$case: 'json',
42+
json: {
43+
mesh: {
44+
$case: 'box',
45+
box: {}
46+
}
47+
}
48+
}
49+
}
50+
},
51+
{
52+
name: 'cube-id',
53+
jsonSchema: {
54+
type: 'object',
55+
properties: {},
56+
serializationType: 'map'
57+
},
58+
data: {
59+
'512': {
60+
$case: 'json',
61+
json: {}
62+
}
63+
}
64+
},
65+
{
66+
name: 'inspector::Scene',
67+
jsonSchema: {
68+
type: 'object',
69+
properties: {
70+
layout: {
71+
type: 'object',
72+
properties: {
73+
base: {
74+
type: 'object',
75+
properties: {
76+
x: {
77+
type: 'integer'
78+
},
79+
y: {
80+
type: 'integer'
81+
}
82+
}
83+
},
84+
parcels: {
85+
type: 'array',
86+
item: {
87+
type: 'object',
88+
properties: {
89+
x: {
90+
type: 'integer'
91+
},
92+
y: {
93+
type: 'integer'
94+
}
95+
}
96+
}
97+
}
98+
}
99+
}
100+
},
101+
serializationType: 'map'
102+
},
103+
data: {
104+
'0': {
105+
$case: 'json',
106+
json: {
107+
layout: {
108+
base: {
109+
x: 0,
110+
y: 0
111+
},
112+
parcels: [
113+
{
114+
x: 0,
115+
y: 0
116+
}
117+
]
118+
}
119+
}
120+
}
121+
}
122+
}
123+
]
124+
}
125+
3126
export const mainComposite = {
4-
id: 'main',
127+
version: 1,
5128
components: [
6129
{
7130
name: 'core::Transform',
@@ -229,6 +352,6 @@ export async function feededFileSystem(mappings: Record<string, string> = builde
229352

230353
return createFsInMemory({
231354
...fileContent,
232-
'main.composite.json': Buffer.from(JSON.stringify(mainComposite), 'utf-8')
355+
'main.composite': Buffer.from(JSON.stringify(mainComposite), 'utf-8')
233356
})
234357
}

packages/@dcl/inspector/src/lib/data-layer/host/rpc-methods.ts

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,31 @@ import { dumpEngineToComposite } from './utils/engine-to-composite'
66
import { createFsCompositeProvider } from './utils/fs-composite-provider'
77
import { stream } from './stream'
88
import { initUndoRedo } from './undo-redo'
9+
import { minimalComposite } from '../client/feeded-local-fs'
910

1011
export async function initRpcMethods(
1112
fs: FileSystemInterface,
1213
engine: IEngine,
1314
onChanges: OnChangeFunction[]
1415
): Promise<DataLayerRpcServer> {
1516
// Look for a composite
16-
const compositeProvider = await createFsCompositeProvider(fs)
17-
const mainComposite = compositeProvider.getCompositeOrNull('main.composite.json')
17+
const currentCompositeResourcePath = 'main.composite'
18+
19+
if (!(await fs.existFile(currentCompositeResourcePath))) {
20+
await fs.writeFile(currentCompositeResourcePath, Buffer.from(JSON.stringify(minimalComposite), 'utf-8'))
21+
}
1822

23+
const compositeProvider = await createFsCompositeProvider(fs)
24+
const mainComposite = compositeProvider.getCompositeOrNull(currentCompositeResourcePath)
1925
if (mainComposite) {
2026
Composite.instance(engine, mainComposite, compositeProvider, {
2127
entityMapping: {
2228
type: EntityMappingMode.EMM_DIRECT_MAPPING,
2329
getCompositeEntity: (entity: number | Entity) => entity as Entity
2430
}
2531
})
32+
} else {
33+
// TODO: log the error
2634
}
2735

2836
let dirty = false
@@ -51,7 +59,9 @@ export async function initRpcMethods(
5159
onChanges.push(undoRedo.onChange)
5260
}
5361

54-
// compositeProvider.save(composite, 'json').catch((err) => console.error(`Save composite fails: `, err))
62+
compositeProvider
63+
.save({ src: currentCompositeResourcePath, composite }, 'json')
64+
.catch((err) => console.error(`Save composite ${currentCompositeResourcePath} fails: `, err))
5565
}
5666
}, -1_000_000_000)
5767

@@ -80,7 +90,7 @@ export async function initRpcMethods(
8090
throw new Error("Couldn't find the asset " + req.path)
8191
},
8292
async getAssetCatalog() {
83-
const extensions = ['.glb', '.png', '.composite', '.composite.json', '.gltf', '.jpg']
93+
const extensions = ['.glb', '.png', '.composite', '.composite.bin', '.gltf', '.jpg']
8494
const ignore = ['.git', 'node_modules']
8595

8696
const files = (await getFilesInDirectory(fs, '', [], true, ignore)).filter((item) => {

packages/@dcl/inspector/src/lib/data-layer/host/utils/fs-composite-provider.ts

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,25 @@ export type CompositeManager = Composite.Provider & {
77
}
88

99
export async function createFsCompositeProvider(fs: FileSystemInterface): Promise<CompositeManager> {
10-
const compositePaths = (await getFilesInDirectory(fs, '', [], true))
11-
.filter((item) => item.endsWith('.composite.json') || item.endsWith('.composite'))
10+
const files = await getFilesInDirectory(fs, '', [], true)
11+
const compositePaths = files
12+
.filter((item) => item.endsWith('.composite') || item.endsWith('.composite.bin'))
1213
.map((item) => item)
1314

1415
const compositePromises = compositePaths.map(async (itemPath) => {
1516
const src = itemPath.toLowerCase()
1617
try {
17-
if (itemPath.endsWith('.json')) {
18-
const compositeContent = (await fs.readFile(itemPath)).toString()
19-
const json = JSON.parse(compositeContent)
20-
const composite = Composite.fromJson(json)
18+
if (itemPath.endsWith('.bin')) {
19+
const compositeContent = new Uint8Array(await fs.readFile(itemPath))
20+
const composite = Composite.fromBinary(compositeContent)
2121
return {
2222
src,
2323
composite
2424
}
2525
} else {
26-
const compositeContent = new Uint8Array(await fs.readFile(itemPath))
27-
const composite = Composite.fromBinary(compositeContent)
26+
const compositeContent = (await fs.readFile(itemPath)).toString()
27+
const json = JSON.parse(compositeContent)
28+
const composite = Composite.fromJson(json)
2829
return {
2930
src,
3031
composite
@@ -45,13 +46,29 @@ export async function createFsCompositeProvider(fs: FileSystemInterface): Promis
4546
// a lot of questions with this method, it's temporal
4647
// => what should they be the params?, it overides? it's a save&replace, save as..., etc
4748
save: async (composite: Composite.Resource, type: 'json' | 'binary') => {
49+
let compositeDefinition: Composite.Definition
4850
if (type === 'binary') {
49-
await fs.writeFile(composite.src, Buffer.from(Composite.toBinary(composite.composite)))
51+
const bytes = Buffer.from(Composite.toBinary(composite.composite))
52+
await fs.writeFile(composite.src, bytes)
53+
54+
// deep clone (*)
55+
compositeDefinition = Composite.fromBinary(bytes)
5056
} else {
51-
await fs.writeFile(
52-
composite.src,
53-
Buffer.from(JSON.stringify(Composite.toJson(composite.composite), null, 2), 'utf-8')
54-
)
57+
const text = JSON.stringify(Composite.toJson(composite.composite), null, 2)
58+
await fs.writeFile(composite.src, Buffer.from(text, 'utf-8'))
59+
60+
// deep clone (*)
61+
compositeDefinition = Composite.fromJson(JSON.parse(text))
62+
}
63+
64+
// (*) deep clone: the `composite.composite` could be used, but this would assign
65+
// the reference and at this point we don't have control about it
66+
67+
// If the composite resource exists in our list, we replaced the definition
68+
// with a cloned definition
69+
const existingComposite = composites.find((item) => item.src === composite.src)
70+
if (existingComposite) {
71+
existingComposite.composite = compositeDefinition
5572
}
5673
}
5774
}

packages/@dcl/sdk-commands/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"allowJs": true,
1212
"resolveJsonModule": true,
1313
"strict": true,
14+
"sourceMap": true,
1415
"types": [
1516
"node",
1617
],

packages/@dcl/sdk/src/composite-provider.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ export async function createContentFetchCompositeProvider(): Promise<Composite.P
66
const scene = await getSceneInfo({})
77
const compositesContent = scene.contents.filter((item) => {
88
const path = item.file.toLowerCase()
9-
return path.endsWith('.composite') || path.endsWith('.composite.json')
9+
return path.endsWith('.composite') || path.endsWith('.composite.bin')
1010
})
1111

1212
async function fetchComposite(item: { hash: string; file: string }): Promise<Composite.Resource | null> {
1313
const src = item.file.toLowerCase()
1414
const compositeUrl = `${scene.baseUrl}${item.hash}`
1515
try {
1616
const response = await fetch(compositeUrl)
17-
if (item.file.endsWith('.json')) {
18-
const compositeJson = await response.json()
19-
const composite = Composite.fromJson(compositeJson)
20-
return { src, composite }
21-
} else {
17+
if (item.file.endsWith('.bin')) {
2218
const compositeBinaryData: Uint8Array = await (response as any).arrayBuffer()
2319
const composite = Composite.fromBinary(compositeBinaryData)
2420
return { src, composite }
21+
} else {
22+
const compositeJson = await response.json()
23+
const composite = Composite.fromJson(compositeJson)
24+
return { src, composite }
2525
}
2626
} catch (err) {
2727
console.error(`Error loading composite ${compositeUrl}: ${(err as any).toString()}`)

packages/@dcl/sdk/src/with-composite.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const onUpdate = basicOnUpdate
1010
*/
1111
/* @__PURE__ */ export async function onStart() {
1212
const compositeProvider = await createContentFetchCompositeProvider()
13-
const mainComposite = compositeProvider.getCompositeOrNull('main.composite.json')
13+
const mainComposite = compositeProvider.getCompositeOrNull('main.composite')
1414
if (mainComposite) {
1515
Composite.instance(engine, mainComposite, compositeProvider)
1616
}

0 commit comments

Comments
 (0)