Needle Engine

Changes between version 3.28.7 and 3.28.8
Files changed (8) hide show
  1. plugins/vite/defines.js +1 -0
  2. plugins/common/version.js +9 -0
  3. src/engine/engine_context.ts +3 -3
  4. src/engine/engine_element_loading.ts +1 -1
  5. src/engine/engine_element.ts +3 -0
  6. src/engine/engine_gltf_builtin_components.ts +30 -4
  7. src/engine/engine_networking_auto.ts +3 -4
  8. src/engine/engine_networking.ts +2 -1
plugins/vite/defines.js CHANGED
@@ -26,6 +26,7 @@
26
26
  // console.log("Update vite defines -------------------------------------------");
27
27
  if (!viteConfig.define) viteConfig.define = {};
28
28
  const version = tryGetNeedleEngineVersion();
29
+ console.log("Needle Engine Version:", version, needleEngineConfig?.generator);
29
30
  if (version)
30
31
  viteConfig.define.NEEDLE_ENGINE_VERSION = "\"" + version + "\"";
31
32
  if (needleEngineConfig)
plugins/common/version.js CHANGED
@@ -8,5 +8,14 @@
8
8
  const version = json.version;
9
9
  return version;
10
10
  }
11
+ // check if we're in the needle engine package directory (for a release)
12
+ const packageJsonPath = process.cwd() + "/package.json";
13
+ if (existsSync(packageJsonPath)) {
14
+ const json = JSON.parse(readFileSync(packageJsonPath));
15
+ if (json.name === "@needle-tools/engine") {
16
+ const version = json.version;
17
+ return version;
18
+ }
19
+ }
11
20
  return null;
12
21
  }
src/engine/engine_context.ts CHANGED
@@ -880,8 +880,8 @@
880
880
  }
881
881
 
882
882
  const loader = getLoader();
883
- let loadingHash = 0;
884
- if (this.hash) loadingHash = Number.parseInt(this.hash) ?? 0;
883
+ // this hash should be constant since it is used to initialize the UIDProvider per initially loaded scene
884
+ const loadingHash = 0;
885
885
  for (let i = 0; i < files.length; i++) {
886
886
  // abort loading if the create id has changed
887
887
  if (createId !== this._createId) {
@@ -889,7 +889,6 @@
889
889
  break;
890
890
  }
891
891
  const file = files[i];
892
-
893
892
  if (!file.includes(".glb") && !file.includes(".gltf")) {
894
893
  const warning = `Needle Engine: found suspicious src "${file}"`;
895
894
  console.warn(warning);
@@ -897,6 +896,7 @@
897
896
  }
898
897
 
899
898
  args?.onLoadingStart?.call(this, i, file);
899
+ if(debug) console.log("Context Load " + file);
900
900
  const res = await loader.loadSync(this, file, file, loadingHash, prog => {
901
901
  progressArg.name = file;
902
902
  progressArg.progress = prog;
src/engine/engine_element_loading.ts CHANGED
@@ -203,6 +203,7 @@
203
203
  this._loadingElement.style.flexDirection = "column";
204
204
  this._loadingElement.style.pointerEvents = "none";
205
205
  this._loadingElement.style.color = "white";
206
+ this._loadingElement.style.fontFamily = "Roboto, sans-serif, Arial";
206
207
  if (loadingStyle === "light")
207
208
  this._loadingElement.style.color = "rgba(0,0,0,.8)";
208
209
  else
@@ -300,7 +301,6 @@
300
301
  messageContainer.style.fontSize = ".8em";
301
302
  messageContainer.style.paddingTop = ".5em";
302
303
  messageContainer.style.fontWeight = "200";
303
- messageContainer.style.fontFamily = "Roboto, sans-serif, Arial";
304
304
  // messageContainer.style.border = "1px solid rgba(255,255,255,.1)";
305
305
  messageContainer.style.justifyContent = "center";
306
306
  this._loadingElement.appendChild(messageContainer);
src/engine/engine_element.ts CHANGED
@@ -171,12 +171,15 @@
171
171
 
172
172
  if (!this.getAttribute("src")) {
173
173
  const global = globalThis["needle:codegen_files"] as unknown as string;
174
+ if(debug) console.log("src is null, trying to load from globalThis[\"needle:codegen_files\"]", global);
174
175
  if (global) {
175
176
  if (debug) console.log("globalThis[\"needle:codegen_files\"]", global);
176
177
  this.setAttribute("src", global);
177
178
  }
178
179
  }
179
180
 
181
+ if(debug) console.log("src", this.getAttribute("src"));
182
+
180
183
  // we have to wait because codegen does set the src attribute when it's loaded
181
184
  // which might happen after the element is connected
182
185
  // if the `src` is then still null we want to initialize the default scene
src/engine/engine_gltf_builtin_components.ts CHANGED
@@ -114,6 +114,16 @@
114
114
  resolveGuids: (guidsMap: GuidsMap) => void;
115
115
  }
116
116
 
117
+ const originalComponentNameKey = Symbol("original-component-name");
118
+
119
+ /**
120
+ * We want to create one id provider per component
121
+ * If a component is used multiple times we want to create a new id provider for each instance
122
+ * That way the order of components in the scene doesnt affect the result GUID
123
+ */
124
+ // TODO: clear this when re-loading the context
125
+ const componentIdProviderCache = new Map<string, InstantiateIdProvider>();
126
+
117
127
  function recursiveCreateGuids(obj: IGameObject, idProvider: UIDProvider | null, guidsMap: GuidsMap, resolveGuids: IHasResolveGuids[]) {
118
128
  if (idProvider === null) return;
119
129
  if (!obj) return;
@@ -125,8 +135,21 @@
125
135
  if (obj && obj.userData && obj.userData.components) {
126
136
  for (const comp of obj.userData.components) {
127
137
  if (comp === null) continue;
138
+
139
+ // by default we use the component guid as a key - order of the components in the scene doesnt matter with this approach
140
+ // this is to prevent cases where multiple GLBs are loaded with the same component guid
141
+ const idProviderKey = comp.guid;
142
+ if (idProviderKey) {
143
+ if (!componentIdProviderCache.has(idProviderKey)) {
144
+ if (debug) console.log("Creating InstanceIdProvider with key \"" + idProviderKey + "\" for component " + comp[originalComponentNameKey]);
145
+ componentIdProviderCache.set(idProviderKey, new InstantiateIdProvider(idProviderKey));
146
+ }
147
+ }
148
+ else if(debug) console.warn("Can not create IdProvider: component " + comp[originalComponentNameKey] + " has no guid", comp.guid);
149
+ const componentIdProvider = componentIdProviderCache.get(idProviderKey) || idProvider
150
+
128
151
  const prev = comp.guid;
129
- comp.guid = idProvider.generateUUID();
152
+ comp.guid = componentIdProvider.generateUUID();
130
153
  if (prev && prev !== "invalid")
131
154
  guidsMap[prev] = comp.guid;
132
155
  if (comp.resolveGuids)
@@ -181,11 +204,14 @@
181
204
 
182
205
  // assign basic fields
183
206
  assign(instance, compData, context.implementationInformation);
184
-
207
+
185
208
  // assign the guid of the original instance
186
- if("guid" in compData)
209
+ if ("guid" in compData)
187
210
  instance[editorGuidKeyName] = compData.guid;
188
-
211
+
212
+ // we store the original component name per component which will later be used to get or initialize the InstanceIdProvider
213
+ instance[originalComponentNameKey] = compData.name;
214
+
189
215
  // Object.assign(instance, compData);
190
216
  // dont call awake here because some references might not be resolved yet and components that access those fields in awake will throw
191
217
  // for example Duplicatable reference to object might still be { node: id }
src/engine/engine_networking_auto.ts CHANGED
@@ -44,9 +44,7 @@
44
44
  private _handleReceivingMethod?: Function;
45
45
 
46
46
  get networkingKey(): string {
47
- const obj = this.comp as object;
48
- const key = obj.constructor.name;
49
- return key;
47
+ return this.comp.guid;
50
48
  }
51
49
 
52
50
  /** is set to true in on receive call to avoid circular sending */
@@ -81,7 +79,7 @@
81
79
 
82
80
  notifyChanged(propertyName: string, value: any) {
83
81
  if (this._isReceiving) return;
84
- // console.log("Property changed: " + propertyName, value);
82
+ if(debug) console.log("Property changed: " + propertyName, value);
85
83
  this.hasChanges = true;
86
84
  this.changedProperties[propertyName] = value;
87
85
  }
@@ -111,6 +109,7 @@
111
109
  }
112
110
 
113
111
  private onHandleReceiving(val) {
112
+ if(debug) console.log("RECEIVE", this.comp.name, this.comp.guid, val);
114
113
  if (!this._isInit) return;
115
114
  if (!this.comp) return;
116
115
  const guid = val.guid;
src/engine/engine_networking.ts CHANGED
@@ -660,7 +660,8 @@
660
660
  const model = message.data as unknown as UserJoinedOrLeftRoomModel;
661
661
  const index = this._currentInRoom.indexOf(model.userId);
662
662
  if (index >= 0) {
663
- console.log(model.userId + " left", this.context.alias ?? "");
663
+ if (debugNet)
664
+ console.log(model.userId + " left", "now in room:", this._currentInRoom);
664
665
  this._currentInRoom.splice(index, 1);
665
666
  }
666
667
  if (model.userId === this.connectionId) {