Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 33 additions & 7 deletions frontend/components/game/core/useAssetPipeline.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import { useCallback } from "react";
import {
mapWithConcurrency,
selectPrefetchMapTargets,
shouldSkipNearbyMapPrefetch,
} from "../../../lib/clientPerf";
import { Assets, Rectangle, Texture } from "pixi.js";
import type { CharacterSnapshot } from "../../../lib/aowProtocol";
import type { GraphicData } from "../../../types/game";
Expand Down Expand Up @@ -482,9 +487,29 @@ export function useAssetPipeline({
return;
}

const nearbyMaps = collectAdjacentMapNumbers(
engine.mapData,
engine.mapNumber,
const connection =
typeof navigator !== "undefined"
? (
navigator as Navigator & {
connection?: {
saveData?: boolean;
effectiveType?: string;
};
}
).connection
: undefined;

if (shouldSkipNearbyMapPrefetch(connection)) {
updateLoadingProgress(
"Precargando alrededores",
100,
"Prefetch omitido por ahorro de datos o conexion lenta.",
);
return;
}

const nearbyMaps = selectPrefetchMapTargets(
collectAdjacentMapNumbers(engine.mapData, engine.mapNumber),
);
if (!nearbyMaps.length) {
return;
Expand All @@ -496,12 +521,12 @@ export function useAssetPipeline({
`Analizando ${nearbyMaps.length} mapas cercanos...`,
);

for (let index = 0; index < nearbyMaps.length; index++) {
let completed = 0;
await mapWithConcurrency(nearbyMaps, 2, async (targetMap) => {
if (engine.isDestroyed) {
return;
}

const targetMap = nearbyMaps[index];
try {
const nextMapData = await loadMapData(targetMap);
const nextMapDimensions = getMapDimensions(
Expand All @@ -521,9 +546,10 @@ export function useAssetPipeline({
},
),
);
completed += 1;
updateLoadingProgress(
"Precargando alrededores",
88 + Math.round(((index + 1) / nearbyMaps.length) * 12),
88 + Math.round((completed / nearbyMaps.length) * 12),
`Mapa ${targetMap} listo para transicion rapida.`,
);
} catch (error) {
Expand All @@ -532,7 +558,7 @@ export function useAssetPipeline({
error,
);
}
}
});
},
[preloadGraphicIds, updateLoadingProgress],
);
Expand Down
191 changes: 135 additions & 56 deletions frontend/components/game/core/useRendererBootstrap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
/* eslint-disable react-hooks/immutability */
import { useEffect, type RefObject } from "react";
import {
expandBoundsByRadius,
isLowEndClient,
resolveClientMaxFps,
splitRowChunks,
waitForIdle,
} from "../../../lib/clientPerf";
import {
Application,
Container,
Expand Down Expand Up @@ -349,6 +356,26 @@ export function useRendererBootstrap(options: UseRendererBootstrapOptions) {
),
autoDensity: true,
});
const connection =
typeof navigator !== "undefined"
? (
navigator as Navigator & {
connection?: {
saveData?: boolean;
effectiveType?: string;
};
}
).connection
: undefined;
const batterySaver =
typeof window !== "undefined" &&
window.localStorage?.getItem(
"openao.perf.batterySaver",
) === "1";
app.ticker.maxFPS = resolveClientMaxFps({
batterySaver,
connection,
});
return app;
} catch (error) {
app.destroy({ removeView: true }, { children: true });
Expand Down Expand Up @@ -776,11 +803,12 @@ export function useRendererBootstrap(options: UseRendererBootstrapOptions) {
fill: 0xffffff,
stroke: { color: 0x000000, width: 1.5 },
});
const hudTextResolution = app.renderer.resolution || 1;
const fpsText = new Text({
text: options.fpsDisplayTextRef.current,
style: fpsStyle,
});
fpsText.resolution = 1;
fpsText.resolution = hudTextResolution;
fpsText.x = 10;
fpsText.y = 8;
fpsText.zIndex = 1000;
Expand All @@ -790,7 +818,7 @@ export function useRendererBootstrap(options: UseRendererBootstrapOptions) {
text: options.pingDisplayTextRef.current,
style: fpsStyle,
});
pingText.resolution = 1;
pingText.resolution = hudTextResolution;
pingText.x = 10;
pingText.y = 22;
pingText.zIndex = 1000;
Expand All @@ -800,7 +828,7 @@ export function useRendererBootstrap(options: UseRendererBootstrapOptions) {
text: "",
style: getHudStatusTextStyle(0xff3b30),
});
seguroText.resolution = 1;
seguroText.resolution = hudTextResolution;
seguroText.x = 10;
seguroText.y = 36;
seguroText.zIndex = 1000;
Expand All @@ -810,7 +838,7 @@ export function useRendererBootstrap(options: UseRendererBootstrapOptions) {
text: "",
style: getHudStatusTextStyle(0xff3b30),
});
clanSeguroText.resolution = 1;
clanSeguroText.resolution = hudTextResolution;
clanSeguroText.x = 10;
clanSeguroText.y = 50;
clanSeguroText.zIndex = 1000;
Expand All @@ -825,7 +853,7 @@ export function useRendererBootstrap(options: UseRendererBootstrapOptions) {
stroke: { color: 0x000000, width: 1.5 },
}),
});
debugCombatText.resolution = 1;
debugCombatText.resolution = hudTextResolution;
debugCombatText.x = 10;
debugCombatText.y = 50;
debugCombatText.zIndex = 1000;
Expand Down Expand Up @@ -883,66 +911,117 @@ export function useRendererBootstrap(options: UseRendererBootstrapOptions) {
);
}

window.setTimeout(() => {
if (!engine.isDestroyed) {
const pendingSnapshot =
options.pendingUserSnapshotRef.current?.map ===
options.mapNumber
? options.pendingUserSnapshotRef.current
: null;

if (pendingSnapshot) {
void options
.applyOwnCharacterSnapshot(
engine,
pendingSnapshot,
)
.catch((error) => {
console.warn(
"Failed to sync own character snapshot after base scene render:",
error,
);
});
}
void (async () => {
await waitForIdle();
if (engine.isDestroyed) {
return;
}

options.updateLoadingProgress(
"Renderizando mundo",
82,
"Completando resto del mapa actual...",
);
const pendingSnapshot =
options.pendingUserSnapshotRef.current?.map ===
options.mapNumber
? options.pendingUserSnapshotRef.current
: null;

options
.renderMap(engine, {
includeLayers: ["1", "2"],
includeObjects: false,
excludeBounds:
initialVisibleBounds ?? undefined,
})
.then(() =>
options.renderMap(engine, {
includeLayers: ["3", "4"],
includeObjects: true,
excludeBounds:
initialVisibleBounds ?? undefined,
}),
)
.then(() =>
options.warmCommonCharacterAssets(engine),
if (pendingSnapshot) {
void options
.applyOwnCharacterSnapshot(
engine,
pendingSnapshot,
)
.then(() => options.prefetchNearbyMaps(engine))
.catch((error) => {
console.warn(
"Failed to finish deferred scene enhancement:",
"Failed to sync own character snapshot after base scene render:",
error,
);
})
.finally(() => {
if (!engine.isDestroyed) {
options.clearLoadingProgress();
}
});
}
}, 0);

options.updateLoadingProgress(
"Renderizando mundo",
82,
"Completando resto del mapa actual...",
);

try {
const mapWidth = engine.mapDimensions?.width ?? 100;
const mapHeight = engine.mapDimensions?.height ?? 100;
const lowEnd = isLowEndClient(
typeof navigator !== "undefined"
? (navigator as Navigator & {
deviceMemory?: number;
hardwareConcurrency?: number;
})
: null,
);

const groundChunks = splitRowChunks(1, mapHeight);
for (const chunk of groundChunks) {
if (engine.isDestroyed) return;
await waitForIdle();
await options.renderMap(engine, {
includeLayers: ["1", "2"],
includeObjects: false,
bounds: {
minX: 1,
maxX: mapWidth,
minY: chunk.minY,
maxY: chunk.maxY,
},
excludeBounds:
initialVisibleBounds ?? undefined,
});
}

const upperBounds =
lowEnd && initialVisibleBounds
? expandBoundsByRadius(
initialVisibleBounds,
12,
mapWidth,
mapHeight,
)
: {
minX: 1,
maxX: mapWidth,
minY: 1,
maxY: mapHeight,
};

const upperChunks = splitRowChunks(
upperBounds.minY,
upperBounds.maxY,
);
for (const chunk of upperChunks) {
if (engine.isDestroyed) return;
await waitForIdle();
await options.renderMap(engine, {
includeLayers: ["3", "4"],
includeObjects: true,
bounds: {
minX: upperBounds.minX,
maxX: upperBounds.maxX,
minY: chunk.minY,
maxY: chunk.maxY,
},
excludeBounds:
initialVisibleBounds ?? undefined,
});
}

await options.warmCommonCharacterAssets(engine);
await options.prefetchNearbyMaps(engine);
} catch (error) {
console.warn(
"Failed to finish deferred scene enhancement:",
error,
);
} finally {
if (!engine.isDestroyed) {
options.clearLoadingProgress();
}
}
})();
} catch (err) {
if (isDisposed) {
return;
Expand Down
Loading