entangled-worlds-orbiters-shared 1.0.2 → 1.0.4

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,6 +1,6 @@
1
1
  {
2
2
  "name": "entangled-worlds-orbiters-shared",
3
- "version": "1.0.2",
3
+ "version": "1.0.4",
4
4
  "description": "Shared library for entangled worlds orbiters - contains core world rendering, moons system, and UI components",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -1,38 +1,41 @@
1
1
  /**
2
2
  * Texture Configuration Loader
3
- * Loads texture definitions from local config file or remote endpoint
3
+ * Loads texture definitions from remote endpoint or uses passed config
4
4
  */
5
5
  import { resolvePublicUrl } from './env.js';
6
6
 
7
- const DEFAULT_CONFIG_URL = '/config/textures.json';
8
- const FALLBACK_CONFIG_URL = 'https://api.entangled-worlds.com/config/textures.json'; // Future endpoint
9
-
10
7
  let cachedConfig = null;
11
8
  let configPromise = null;
9
+ let lastConfigUrl = null;
12
10
 
13
11
  /**
14
- * Load texture configuration from local file or remote endpoint
15
- * @param {string} configUrl - Override default config URL
12
+ * Load texture configuration from remote endpoint or use passed config
13
+ * @param {string} configUrl - Override config URL
16
14
  * @param {boolean} useCache - Whether to use cached config if available
17
15
  * @returns {Promise<Object>} Texture configuration object
18
16
  */
19
- export async function loadTextureConfig(configUrl = DEFAULT_CONFIG_URL, useCache = true) {
17
+ export async function loadTextureConfig(configUrl = null, useCache = true) {
20
18
  if (useCache && cachedConfig) {
21
- console.log('[TextureConfig] Using cached config');
22
19
  return cachedConfig;
23
20
  }
24
21
 
25
22
  if (configPromise) {
26
- console.log('[TextureConfig] Using in-flight request');
27
23
  return configPromise;
28
24
  }
29
25
 
26
+ if (configUrl) {
27
+ lastConfigUrl = configUrl;
28
+ }
29
+
30
+ const targetUrl = configUrl || lastConfigUrl;
31
+
30
32
  configPromise = (async () => {
31
33
  try {
32
- // Resolve config URL against public base if it's a relative path
33
- const resolvedConfigUrl = /^https?:\/\//i.test(configUrl) ? configUrl : resolvePublicUrl(configUrl);
34
- console.log('[TextureConfig] Loading from:', resolvedConfigUrl);
35
- const response = await fetch(resolvedConfigUrl);
34
+ if (!targetUrl) {
35
+ throw new Error('No texture config URL provided');
36
+ }
37
+
38
+ const response = await fetch(targetUrl);
36
39
 
37
40
  if (!response.ok) {
38
41
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
@@ -46,29 +49,13 @@ export async function loadTextureConfig(configUrl = DEFAULT_CONFIG_URL, useCache
46
49
  }
47
50
 
48
51
  cachedConfig = config;
49
- console.log('[TextureConfig] Loaded successfully:', {
50
- version: config.version,
51
- categories: Object.keys(config.textures),
52
- lastUpdated: config.lastUpdated
53
- });
54
-
55
52
  return config;
56
53
  } catch (error) {
57
54
  console.error('[TextureConfig] Failed to load config:', error);
58
-
59
- // If primary URL fails and it's not already the fallback, try fallback
60
- if (configUrl !== FALLBACK_CONFIG_URL) {
61
- console.log('[TextureConfig] Trying fallback endpoint...');
62
- try {
63
- return await loadTextureConfig(FALLBACK_CONFIG_URL, false);
64
- } catch (fallbackError) {
65
- console.error('[TextureConfig] Fallback also failed:', fallbackError);
66
- }
67
- }
68
-
69
- // Return minimal fallback configuration
55
+ // Return minimal fallback configuration when loading fails
70
56
  console.warn('[TextureConfig] Using hardcoded fallback config');
71
- return getHardcodedFallback();
57
+ cachedConfig = getHardcodedFallback();
58
+ return cachedConfig;
72
59
  } finally {
73
60
  configPromise = null;
74
61
  }
@@ -277,10 +264,10 @@ function getHardcodedFallback() {
277
264
  * @param {string} configUrl - Override config URL
278
265
  * @returns {Promise<Object>} Fresh configuration object
279
266
  */
280
- export async function reloadTextureConfig(configUrl = DEFAULT_CONFIG_URL) {
267
+ export async function reloadTextureConfig(configUrl = null) {
281
268
  cachedConfig = null;
282
269
  configPromise = null;
283
- return loadTextureConfig(configUrl, false);
270
+ return loadTextureConfig(configUrl || lastConfigUrl, false);
284
271
  }
285
272
 
286
273
  /**
@@ -51,7 +51,6 @@ export async function loadGLB(url, { retries = 3, signal, onProgress, applyFlags
51
51
  child.material.emissive.setHex(0x888888);
52
52
  child.material.emissiveMap = child.material.map;
53
53
  child.material.emissiveIntensity = 1.0;
54
- console.log('✅ KTX2 texture loaded:', child.material.map.constructor.name, `${child.material.map.image.width}x${child.material.map.image.height}`);
55
54
  }
56
55
  child.material.needsUpdate = true;
57
56
  child.castShadow = false;
@@ -64,16 +64,6 @@ export async function generateMoons({
64
64
  return Math.random(); // Use regular random if no seed
65
65
  };
66
66
 
67
- // Log the seed being used for debugging
68
- if (debug) {
69
- console.log('[Moons] Using seed for deterministic positioning:', {
70
- originalSeed: seed,
71
- seedValue: seedValue,
72
- seedType: typeof seed,
73
- isSeeded: seedValue !== null
74
- });
75
- }
76
-
77
67
  const moonGeometry = new THREE.SphereGeometry(0.1, geometryWidthSegments, geometryHeightSegments);
78
68
 
79
69
  // Optional UV grid override
@@ -106,20 +96,16 @@ export async function generateMoons({
106
96
  // Resolve textureKey to absolute URL if it's relative
107
97
  if (textureKey && textureKey.startsWith('/')) {
108
98
  primaryTexture = `${HERBARIUM_BASE}${textureKey}`;
109
- if (debug) console.log('[Moons] Using custom texture key:', textureKey, '-> resolved:', primaryTexture);
110
99
  } else if (textureKey) {
111
100
  primaryTexture = textureKey; // already absolute
112
- if (debug) console.log('[Moons] Using absolute texture URL:', primaryTexture);
113
101
  }
114
102
 
115
103
  try {
116
104
  sharedTexture = await loadTexture(primaryTexture);
117
- if (debug) console.log('[Moons] Loaded texture from:', primaryTexture);
118
105
  } catch (eKTX) {
119
106
  if (debug) console.warn('[Moons] Primary texture failed, trying fallback:', eKTX);
120
107
  try {
121
108
  sharedTexture = await loadTexture(fallbackTexture);
122
- if (debug) console.log('[Moons] Fallback texture loaded from:', fallbackTexture);
123
109
  } catch (ePNG) {
124
110
  if (debug) console.warn('[Moons] Both primary and fallback texture loading failed');
125
111
  }
@@ -16,13 +16,11 @@ export class WorldManager {
16
16
  }
17
17
 
18
18
  setFlags(flags) {
19
- console.log('[WorldManager] setFlags:', flags);
20
19
  this.flags = { ...this.flags, ...flags };
21
20
  }
22
21
 
23
22
  disposeCurrent() {
24
23
  if (this.current) {
25
- console.log('[WorldManager] disposeCurrent:', this.current?.name || this.current);
26
24
  disposeObject3D(this.current);
27
25
  this.scene.remove(this.current);
28
26
  this.current = null;
@@ -36,39 +34,31 @@ export class WorldManager {
36
34
 
37
35
  async setMode(mode, args = {}) {
38
36
  const myToken = ++this.token;
39
- console.log('[WorldManager] setMode request:', { mode, args });
40
37
  this.onLoadStart?.();
41
38
  try {
42
39
  let obj;
43
40
 
44
41
  // Check for custom creators first
45
42
  if (this.customCreators.has(mode)) {
46
- console.log(`[WorldManager] -> custom creator for mode ${mode}`);
47
43
  obj = await this.customCreators.get(mode)({ flags: this.flags, ...args });
48
44
  } else if (mode === 2) {
49
- console.log('[WorldManager] -> makeGLB');
50
45
  obj = await makeGLB({ modelUrl: args.modelUrl, flags: this.flags });
51
46
  } else if (mode === 3) {
52
- console.log('[WorldManager] -> makeNormalSphere');
53
47
  obj = await makeNormalSphere({ flags: this.flags, ...args });
54
48
  } else {
55
- console.log('[WorldManager] -> makeSphere (textured)');
56
49
  obj = await makeSphere({ textureUrl: args.textureUrl, flags: this.flags, ...args });
57
50
  }
58
51
 
59
52
  if (this.token !== myToken) {
60
- console.log('[WorldManager] setMode superseded, abandoning result');
61
53
  return;
62
54
  }
63
55
  this.disposeCurrent();
64
56
  this.scene.add(obj);
65
57
  this.current = obj;
66
- console.log('[WorldManager] setMode applied. current:', obj?.name || obj);
67
58
 
68
59
  // If the object exposes a frame updater, run a render-time loop
69
60
  if (obj && obj.userData && typeof obj.userData.update === 'function' && window.__EW_RENDERER) {
70
61
  const updater = obj.userData.update;
71
- console.log('[WorldManager] update loop started for', obj.name || obj);
72
62
  const tick = () => {
73
63
  if (this.current === obj) {
74
64
  try {
@@ -77,8 +67,6 @@ export class WorldManager {
77
67
  console.warn('[WorldManager] update loop error:', e);
78
68
  }
79
69
  requestAnimationFrame(tick);
80
- } else {
81
- console.log('[WorldManager] update loop stopped (object replaced)');
82
70
  }
83
71
  };
84
72
  requestAnimationFrame(tick);
@@ -109,10 +109,15 @@ export async function makeSphere({
109
109
  try {
110
110
  const tex = await loadTexture(chosenTexture);
111
111
  tex.colorSpace = THREE.SRGBColorSpace;
112
- tex.generateMipmaps = true;
113
112
  tex.anisotropy = 8;
114
113
  if (typeof flipY === 'boolean') tex.flipY = flipY;
115
114
 
115
+ // Only enable mipmaps for non-compressed, power-of-two textures
116
+ const isCompressed = tex.isCompressedTexture;
117
+ const img = tex.image;
118
+ const isPowerOfTwo = img && ((img.width & (img.width - 1)) === 0) && ((img.height & (img.height - 1)) === 0);
119
+ tex.generateMipmaps = !isCompressed && isPowerOfTwo;
120
+
116
121
  // Decide mapping approach
117
122
  let shouldMirrorDuplicate = mirrorDuplicateX;
118
123
  if (tex.image) {