worker系统不支持sab回退到普通worker
This commit is contained in:
3
docs/public/_headers
Normal file
3
docs/public/_headers
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/*
|
||||||
|
Cross-Origin-Embedder-Policy: require-corp
|
||||||
|
Cross-Origin-Opener-Policy: same-origin
|
||||||
@@ -19,16 +19,12 @@
|
|||||||
}).observe(document, { childList: true, subtree: true });
|
}).observe(document, { childList: true, subtree: true });
|
||||||
function getFetchOpts(link) {
|
function getFetchOpts(link) {
|
||||||
const fetchOpts = {};
|
const fetchOpts = {};
|
||||||
if (link.integrity)
|
if (link.integrity) fetchOpts.integrity = link.integrity;
|
||||||
fetchOpts.integrity = link.integrity;
|
if (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy;
|
||||||
if (link.referrerPolicy)
|
|
||||||
fetchOpts.referrerPolicy = link.referrerPolicy;
|
|
||||||
if (link.crossOrigin === "use-credentials")
|
if (link.crossOrigin === "use-credentials")
|
||||||
fetchOpts.credentials = "include";
|
fetchOpts.credentials = "include";
|
||||||
else if (link.crossOrigin === "anonymous")
|
else if (link.crossOrigin === "anonymous") fetchOpts.credentials = "omit";
|
||||||
fetchOpts.credentials = "omit";
|
else fetchOpts.credentials = "same-origin";
|
||||||
else
|
|
||||||
fetchOpts.credentials = "same-origin";
|
|
||||||
return fetchOpts;
|
return fetchOpts;
|
||||||
}
|
}
|
||||||
function processPreload(link) {
|
function processPreload(link) {
|
||||||
@@ -1077,28 +1073,14 @@ var LogLevel;
|
|||||||
LogLevel2[LogLevel2["None"] = 5] = "None";
|
LogLevel2[LogLevel2["None"] = 5] = "None";
|
||||||
})(LogLevel || (LogLevel = {}));
|
})(LogLevel || (LogLevel = {}));
|
||||||
const Colors = {
|
const Colors = {
|
||||||
// 基础颜色
|
|
||||||
BLACK: "\x1B[30m",
|
|
||||||
RED: "\x1B[31m",
|
RED: "\x1B[31m",
|
||||||
GREEN: "\x1B[32m",
|
GREEN: "\x1B[32m",
|
||||||
YELLOW: "\x1B[33m",
|
YELLOW: "\x1B[33m",
|
||||||
BLUE: "\x1B[34m",
|
|
||||||
MAGENTA: "\x1B[35m",
|
|
||||||
CYAN: "\x1B[36m",
|
|
||||||
WHITE: "\x1B[37m",
|
|
||||||
// 亮色版本
|
// 亮色版本
|
||||||
BRIGHT_BLACK: "\x1B[90m",
|
BRIGHT_BLACK: "\x1B[90m",
|
||||||
BRIGHT_RED: "\x1B[91m",
|
BRIGHT_RED: "\x1B[91m",
|
||||||
BRIGHT_GREEN: "\x1B[92m",
|
|
||||||
BRIGHT_YELLOW: "\x1B[93m",
|
|
||||||
BRIGHT_BLUE: "\x1B[94m",
|
|
||||||
BRIGHT_MAGENTA: "\x1B[95m",
|
|
||||||
BRIGHT_CYAN: "\x1B[96m",
|
|
||||||
BRIGHT_WHITE: "\x1B[97m",
|
|
||||||
// 特殊
|
// 特殊
|
||||||
RESET: "\x1B[0m",
|
RESET: "\x1B[0m"
|
||||||
BOLD: "\x1B[1m",
|
|
||||||
UNDERLINE: "\x1B[4m"
|
|
||||||
};
|
};
|
||||||
class ConsoleLogger {
|
class ConsoleLogger {
|
||||||
constructor(config = {}) {
|
constructor(config = {}) {
|
||||||
@@ -1403,8 +1385,7 @@ class SoAStorage {
|
|||||||
const value = instance[key];
|
const value = instance[key];
|
||||||
const type = typeof value;
|
const type = typeof value;
|
||||||
if (type === "number") {
|
if (type === "number") {
|
||||||
if (highPrecisionFields.has(key))
|
if (highPrecisionFields.has(key)) ;
|
||||||
;
|
|
||||||
else if (float64Fields.has(key)) {
|
else if (float64Fields.has(key)) {
|
||||||
this.fields.set(key, new Float64Array(this._capacity));
|
this.fields.set(key, new Float64Array(this._capacity));
|
||||||
} else if (int32Fields.has(key)) {
|
} else if (int32Fields.has(key)) {
|
||||||
@@ -11388,12 +11369,20 @@ class WorkerEntitySystem extends EntitySystem {
|
|||||||
*/
|
*/
|
||||||
initializeSharedArrayBuffer() {
|
initializeSharedArrayBuffer() {
|
||||||
try {
|
try {
|
||||||
|
if (!this.isSharedArrayBufferSupported()) {
|
||||||
|
console.warn(`[${this.systemName}] SharedArrayBuffer not supported, falling back to traditional Worker mode`);
|
||||||
|
this.config.useSharedArrayBuffer = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
const bufferSize = this.config.maxEntities * this.config.entityDataSize * 4;
|
const bufferSize = this.config.maxEntities * this.config.entityDataSize * 4;
|
||||||
this.sharedBuffer = new SharedArrayBuffer(bufferSize);
|
this.sharedBuffer = new SharedArrayBuffer(bufferSize);
|
||||||
this.sharedFloatArray = new Float32Array(this.sharedBuffer);
|
this.sharedFloatArray = new Float32Array(this.sharedBuffer);
|
||||||
|
console.log(`[${this.systemName}] SharedArrayBuffer initialized successfully (${bufferSize} bytes)`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`[${this.systemName}] SharedArrayBuffer init failed:`, error);
|
console.warn(`[${this.systemName}] SharedArrayBuffer init failed, falling back to traditional Worker mode:`, error);
|
||||||
this.config.useSharedArrayBuffer = false;
|
this.config.useSharedArrayBuffer = false;
|
||||||
|
this.sharedBuffer = null;
|
||||||
|
this.sharedFloatArray = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -11506,21 +11495,26 @@ class WorkerEntitySystem extends EntitySystem {
|
|||||||
this.isProcessing = true;
|
this.isProcessing = true;
|
||||||
try {
|
try {
|
||||||
if (this.config.enableWorker && this.workerPool) {
|
if (this.config.enableWorker && this.workerPool) {
|
||||||
if (this.config.useSharedArrayBuffer && this.sharedFloatArray) {
|
if (this.config.useSharedArrayBuffer && this.sharedFloatArray && this.isSharedArrayBufferSupported()) {
|
||||||
this.processWithSharedArrayBuffer(entities).finally(() => {
|
this.processWithSharedArrayBuffer(entities).finally(() => {
|
||||||
this.isProcessing = false;
|
this.isProcessing = false;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
if (this.config.useSharedArrayBuffer) {
|
||||||
|
console.log(`[${this.systemName}] Falling back to traditional Worker mode for this frame`);
|
||||||
|
}
|
||||||
this.processWithWorker(entities).finally(() => {
|
this.processWithWorker(entities).finally(() => {
|
||||||
this.isProcessing = false;
|
this.isProcessing = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
console.log(`[${this.systemName}] Worker not available, processing synchronously`);
|
||||||
this.processSynchronously(entities);
|
this.processSynchronously(entities);
|
||||||
this.isProcessing = false;
|
this.isProcessing = false;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.isProcessing = false;
|
this.isProcessing = false;
|
||||||
|
console.error(`[${this.systemName}] Processing failed:`, error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11666,10 +11660,21 @@ class WorkerEntitySystem extends EntitySystem {
|
|||||||
* 获取系统性能信息
|
* 获取系统性能信息
|
||||||
*/
|
*/
|
||||||
getWorkerInfo() {
|
getWorkerInfo() {
|
||||||
|
let currentMode = "sync";
|
||||||
|
if (this.config.enableWorker && this.workerPool) {
|
||||||
|
if (this.config.useSharedArrayBuffer && this.sharedFloatArray && this.isSharedArrayBufferSupported()) {
|
||||||
|
currentMode = "shared-buffer";
|
||||||
|
} else {
|
||||||
|
currentMode = "worker";
|
||||||
|
}
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
enabled: this.config.enableWorker,
|
enabled: this.config.enableWorker,
|
||||||
workerCount: this.config.workerCount,
|
workerCount: this.config.workerCount,
|
||||||
isProcessing: this.isProcessing
|
isProcessing: this.isProcessing,
|
||||||
|
sharedArrayBufferSupported: this.isSharedArrayBufferSupported(),
|
||||||
|
sharedArrayBufferEnabled: this.config.useSharedArrayBuffer,
|
||||||
|
currentMode
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@@ -11800,15 +11805,12 @@ class WebWorkerPool {
|
|||||||
this.busyWorkers.clear();
|
this.busyWorkers.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var __defProp$3 = Object.defineProperty;
|
|
||||||
var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
|
var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
|
||||||
var __decorateClass$3 = (decorators, target, key, kind) => {
|
var __decorateClass$3 = (decorators, target, key, kind) => {
|
||||||
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
|
||||||
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
||||||
if (decorator = decorators[i])
|
if (decorator = decorators[i])
|
||||||
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
result = decorator(result) || result;
|
||||||
if (kind && result)
|
|
||||||
__defProp$3(target, key, result);
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
let Position = class extends Component {
|
let Position = class extends Component {
|
||||||
@@ -11890,15 +11892,12 @@ let Lifetime = class extends Component {
|
|||||||
Lifetime = __decorateClass$3([
|
Lifetime = __decorateClass$3([
|
||||||
ECSComponent("Lifetime")
|
ECSComponent("Lifetime")
|
||||||
], Lifetime);
|
], Lifetime);
|
||||||
var __defProp$2 = Object.defineProperty;
|
|
||||||
var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
|
var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
|
||||||
var __decorateClass$2 = (decorators, target, key, kind) => {
|
var __decorateClass$2 = (decorators, target, key, kind) => {
|
||||||
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
|
||||||
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
||||||
if (decorator = decorators[i])
|
if (decorator = decorators[i])
|
||||||
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
result = decorator(result) || result;
|
||||||
if (kind && result)
|
|
||||||
__defProp$2(target, key, result);
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
||||||
@@ -12004,8 +12003,7 @@ let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
|||||||
const relativeVelocityX = ball2.dx - ball1.dx;
|
const relativeVelocityX = ball2.dx - ball1.dx;
|
||||||
const relativeVelocityY = ball2.dy - ball1.dy;
|
const relativeVelocityY = ball2.dy - ball1.dy;
|
||||||
const velocityAlongNormal = relativeVelocityX * nx + relativeVelocityY * ny;
|
const velocityAlongNormal = relativeVelocityX * nx + relativeVelocityY * ny;
|
||||||
if (velocityAlongNormal > 0)
|
if (velocityAlongNormal > 0) continue;
|
||||||
continue;
|
|
||||||
const restitution = (ball1.bounce + ball2.bounce) * 0.5;
|
const restitution = (ball1.bounce + ball2.bounce) * 0.5;
|
||||||
const impulseScalar = -(1 + restitution) * velocityAlongNormal / (1 / ball1.mass + 1 / ball2.mass);
|
const impulseScalar = -(1 + restitution) * velocityAlongNormal / (1 / ball1.mass + 1 / ball2.mass);
|
||||||
const impulseX = impulseScalar * nx;
|
const impulseX = impulseScalar * nx;
|
||||||
@@ -12072,8 +12070,7 @@ let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
|||||||
*/
|
*/
|
||||||
writeEntityToBuffer(entityData, offset) {
|
writeEntityToBuffer(entityData, offset) {
|
||||||
const sharedArray = this.sharedFloatArray;
|
const sharedArray = this.sharedFloatArray;
|
||||||
if (!sharedArray)
|
if (!sharedArray) return;
|
||||||
return;
|
|
||||||
const currentEntityCount = Math.floor(offset / 9) + 1;
|
const currentEntityCount = Math.floor(offset / 9) + 1;
|
||||||
sharedArray[0] = currentEntityCount;
|
sharedArray[0] = currentEntityCount;
|
||||||
const dataOffset = offset + 9;
|
const dataOffset = offset + 9;
|
||||||
@@ -12099,8 +12096,7 @@ let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
|||||||
*/
|
*/
|
||||||
readEntityFromBuffer(offset) {
|
readEntityFromBuffer(offset) {
|
||||||
const sharedArray = this.sharedFloatArray;
|
const sharedArray = this.sharedFloatArray;
|
||||||
if (!sharedArray)
|
if (!sharedArray) return null;
|
||||||
return null;
|
|
||||||
const dataOffset = offset + 9;
|
const dataOffset = offset + 9;
|
||||||
return {
|
return {
|
||||||
id: sharedArray[dataOffset + 0],
|
id: sharedArray[dataOffset + 0],
|
||||||
@@ -12129,8 +12125,7 @@ let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
|||||||
for (let i = startIndex; i < endIndex && i < actualEntityCount; i++) {
|
for (let i = startIndex; i < endIndex && i < actualEntityCount; i++) {
|
||||||
const offset = i * 9 + 9;
|
const offset = i * 9 + 9;
|
||||||
const id = sharedFloatArray[offset + 0];
|
const id = sharedFloatArray[offset + 0];
|
||||||
if (id === 0)
|
if (id === 0) continue;
|
||||||
continue;
|
|
||||||
let x = sharedFloatArray[offset + 1];
|
let x = sharedFloatArray[offset + 1];
|
||||||
let y = sharedFloatArray[offset + 2];
|
let y = sharedFloatArray[offset + 2];
|
||||||
let dx = sharedFloatArray[offset + 3];
|
let dx = sharedFloatArray[offset + 3];
|
||||||
@@ -12167,8 +12162,7 @@ let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
|||||||
for (let i = startIndex; i < endIndex && i < actualEntityCount; i++) {
|
for (let i = startIndex; i < endIndex && i < actualEntityCount; i++) {
|
||||||
const offset1 = i * 9 + 9;
|
const offset1 = i * 9 + 9;
|
||||||
const id1 = sharedFloatArray[offset1 + 0];
|
const id1 = sharedFloatArray[offset1 + 0];
|
||||||
if (id1 === 0)
|
if (id1 === 0) continue;
|
||||||
continue;
|
|
||||||
let x1 = sharedFloatArray[offset1 + 1];
|
let x1 = sharedFloatArray[offset1 + 1];
|
||||||
let y1 = sharedFloatArray[offset1 + 2];
|
let y1 = sharedFloatArray[offset1 + 2];
|
||||||
let dx1 = sharedFloatArray[offset1 + 3];
|
let dx1 = sharedFloatArray[offset1 + 3];
|
||||||
@@ -12177,12 +12171,10 @@ let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
|||||||
const bounce1 = sharedFloatArray[offset1 + 6];
|
const bounce1 = sharedFloatArray[offset1 + 6];
|
||||||
const radius1 = sharedFloatArray[offset1 + 8];
|
const radius1 = sharedFloatArray[offset1 + 8];
|
||||||
for (let j = 0; j < actualEntityCount; j++) {
|
for (let j = 0; j < actualEntityCount; j++) {
|
||||||
if (i === j)
|
if (i === j) continue;
|
||||||
continue;
|
|
||||||
const offset2 = j * 9 + 9;
|
const offset2 = j * 9 + 9;
|
||||||
const id2 = sharedFloatArray[offset2 + 0];
|
const id2 = sharedFloatArray[offset2 + 0];
|
||||||
if (id2 === 0)
|
if (id2 === 0) continue;
|
||||||
continue;
|
|
||||||
const x2 = sharedFloatArray[offset2 + 1];
|
const x2 = sharedFloatArray[offset2 + 1];
|
||||||
const y2 = sharedFloatArray[offset2 + 2];
|
const y2 = sharedFloatArray[offset2 + 2];
|
||||||
const dx2 = sharedFloatArray[offset2 + 3];
|
const dx2 = sharedFloatArray[offset2 + 3];
|
||||||
@@ -12190,8 +12182,7 @@ let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
|||||||
const mass2 = sharedFloatArray[offset2 + 5];
|
const mass2 = sharedFloatArray[offset2 + 5];
|
||||||
const bounce2 = sharedFloatArray[offset2 + 6];
|
const bounce2 = sharedFloatArray[offset2 + 6];
|
||||||
const radius2 = sharedFloatArray[offset2 + 8];
|
const radius2 = sharedFloatArray[offset2 + 8];
|
||||||
if (isNaN(x2) || isNaN(y2) || isNaN(radius2) || radius2 <= 0)
|
if (isNaN(x2) || isNaN(y2) || isNaN(radius2) || radius2 <= 0) continue;
|
||||||
continue;
|
|
||||||
const deltaX = x2 - x1;
|
const deltaX = x2 - x1;
|
||||||
const deltaY = y2 - y1;
|
const deltaY = y2 - y1;
|
||||||
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
const distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
|
||||||
@@ -12207,8 +12198,7 @@ let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
|||||||
const relativeVelocityX = dx2 - dx1;
|
const relativeVelocityX = dx2 - dx1;
|
||||||
const relativeVelocityY = dy2 - dy1;
|
const relativeVelocityY = dy2 - dy1;
|
||||||
const velocityAlongNormal = relativeVelocityX * nx + relativeVelocityY * ny;
|
const velocityAlongNormal = relativeVelocityX * nx + relativeVelocityY * ny;
|
||||||
if (velocityAlongNormal > 0)
|
if (velocityAlongNormal > 0) continue;
|
||||||
continue;
|
|
||||||
const restitution = (bounce1 + bounce2) * 0.5;
|
const restitution = (bounce1 + bounce2) * 0.5;
|
||||||
const impulseScalar = -(1 + restitution) * velocityAlongNormal / (1 / mass1 + 1 / mass2);
|
const impulseScalar = -(1 + restitution) * velocityAlongNormal / (1 / mass1 + 1 / mass2);
|
||||||
const impulseX = impulseScalar * nx;
|
const impulseX = impulseScalar * nx;
|
||||||
@@ -12231,15 +12221,12 @@ let PhysicsWorkerSystem = class extends WorkerEntitySystem {
|
|||||||
PhysicsWorkerSystem = __decorateClass$2([
|
PhysicsWorkerSystem = __decorateClass$2([
|
||||||
ECSSystem("PhysicsWorkerSystem")
|
ECSSystem("PhysicsWorkerSystem")
|
||||||
], PhysicsWorkerSystem);
|
], PhysicsWorkerSystem);
|
||||||
var __defProp$1 = Object.defineProperty;
|
|
||||||
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
||||||
var __decorateClass$1 = (decorators, target, key, kind) => {
|
var __decorateClass$1 = (decorators, target, key, kind) => {
|
||||||
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
||||||
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
||||||
if (decorator = decorators[i])
|
if (decorator = decorators[i])
|
||||||
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
result = decorator(result) || result;
|
||||||
if (kind && result)
|
|
||||||
__defProp$1(target, key, result);
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
let RenderSystem = class extends EntitySystem {
|
let RenderSystem = class extends EntitySystem {
|
||||||
@@ -12321,15 +12308,12 @@ let RenderSystem = class extends EntitySystem {
|
|||||||
RenderSystem = __decorateClass$1([
|
RenderSystem = __decorateClass$1([
|
||||||
ECSSystem("RenderSystem")
|
ECSSystem("RenderSystem")
|
||||||
], RenderSystem);
|
], RenderSystem);
|
||||||
var __defProp = Object.defineProperty;
|
|
||||||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
||||||
var __decorateClass = (decorators, target, key, kind) => {
|
var __decorateClass = (decorators, target, key, kind) => {
|
||||||
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
||||||
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
||||||
if (decorator = decorators[i])
|
if (decorator = decorators[i])
|
||||||
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
result = decorator(result) || result;
|
||||||
if (kind && result)
|
|
||||||
__defProp(target, key, result);
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
let LifetimeSystem = class extends EntitySystem {
|
let LifetimeSystem = class extends EntitySystem {
|
||||||
@@ -12507,8 +12491,7 @@ class WorkerDemo {
|
|||||||
this.lastWorkerStatusUpdate = 0;
|
this.lastWorkerStatusUpdate = 0;
|
||||||
this.elements = {};
|
this.elements = {};
|
||||||
this.gameLoop = () => {
|
this.gameLoop = () => {
|
||||||
if (!this.isRunning)
|
if (!this.isRunning) return;
|
||||||
return;
|
|
||||||
const currentTime = performance.now();
|
const currentTime = performance.now();
|
||||||
const deltaTime = (currentTime - this.lastTime) / 1e3;
|
const deltaTime = (currentTime - this.lastTime) / 1e3;
|
||||||
this.lastTime = currentTime;
|
this.lastTime = currentTime;
|
||||||
@@ -118,7 +118,7 @@
|
|||||||
color: #ff4a4a;
|
color: #ff4a4a;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<script type="module" crossorigin src="/ecs-framework/demos/worker-system/assets/index-83126548.js"></script>
|
<script type="module" crossorigin src="/ecs-framework/demos/worker-system/assets/index-DRe9rMYY.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|||||||
@@ -53,7 +53,9 @@
|
|||||||
"docs:build": "npm run docs:api && vitepress build docs",
|
"docs:build": "npm run docs:api && vitepress build docs",
|
||||||
"docs:preview": "vitepress preview docs",
|
"docs:preview": "vitepress preview docs",
|
||||||
"docs:api": "typedoc",
|
"docs:api": "typedoc",
|
||||||
"docs:api:watch": "typedoc --watch"
|
"docs:api:watch": "typedoc --watch",
|
||||||
|
"update:worker-demo": "npm run build:core && cd examples/worker-system-demo && npm run build && cd ../.. && npm run copy:worker-demo",
|
||||||
|
"copy:worker-demo": "node scripts/update-worker-demo.js"
|
||||||
},
|
},
|
||||||
"author": "yhh",
|
"author": "yhh",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
|||||||
@@ -246,15 +246,25 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
|
|||||||
*/
|
*/
|
||||||
private initializeSharedArrayBuffer(): void {
|
private initializeSharedArrayBuffer(): void {
|
||||||
try {
|
try {
|
||||||
|
// 检查是否支持SharedArrayBuffer
|
||||||
|
if (!this.isSharedArrayBufferSupported()) {
|
||||||
|
console.warn(`[${this.systemName}] SharedArrayBuffer not supported, falling back to traditional Worker mode`);
|
||||||
|
this.config.useSharedArrayBuffer = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 使用配置的实体数据大小和最大实体数量
|
// 使用配置的实体数据大小和最大实体数量
|
||||||
// 预分配缓冲区:maxEntities * entityDataSize * 4字节
|
// 预分配缓冲区:maxEntities * entityDataSize * 4字节
|
||||||
const bufferSize = this.config.maxEntities * this.config.entityDataSize * 4;
|
const bufferSize = this.config.maxEntities * this.config.entityDataSize * 4;
|
||||||
this.sharedBuffer = new SharedArrayBuffer(bufferSize);
|
this.sharedBuffer = new SharedArrayBuffer(bufferSize);
|
||||||
this.sharedFloatArray = new Float32Array(this.sharedBuffer);
|
this.sharedFloatArray = new Float32Array(this.sharedBuffer);
|
||||||
|
|
||||||
|
console.log(`[${this.systemName}] SharedArrayBuffer initialized successfully (${bufferSize} bytes)`);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn(`[${this.systemName}] SharedArrayBuffer init failed:`, error);
|
console.warn(`[${this.systemName}] SharedArrayBuffer init failed, falling back to traditional Worker mode:`, error);
|
||||||
this.config.useSharedArrayBuffer = false;
|
this.config.useSharedArrayBuffer = false;
|
||||||
|
this.sharedBuffer = null;
|
||||||
|
this.sharedFloatArray = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,23 +387,31 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.config.enableWorker && this.workerPool) {
|
if (this.config.enableWorker && this.workerPool) {
|
||||||
if (this.config.useSharedArrayBuffer && this.sharedFloatArray) {
|
// 检查SharedArrayBuffer是否真正可用
|
||||||
|
if (this.config.useSharedArrayBuffer && this.sharedFloatArray && this.isSharedArrayBufferSupported()) {
|
||||||
// 使用SharedArrayBuffer优化的异步处理
|
// 使用SharedArrayBuffer优化的异步处理
|
||||||
this.processWithSharedArrayBuffer(entities).finally(() => {
|
this.processWithSharedArrayBuffer(entities).finally(() => {
|
||||||
this.isProcessing = false;
|
this.isProcessing = false;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
// 如果配置了SharedArrayBuffer但不可用,记录降级信息
|
||||||
|
if (this.config.useSharedArrayBuffer) {
|
||||||
|
console.log(`[${this.systemName}] Falling back to traditional Worker mode for this frame`);
|
||||||
|
}
|
||||||
// 传统Worker异步处理
|
// 传统Worker异步处理
|
||||||
this.processWithWorker(entities).finally(() => {
|
this.processWithWorker(entities).finally(() => {
|
||||||
this.isProcessing = false;
|
this.isProcessing = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// 同步处理(最后的fallback)
|
||||||
|
console.log(`[${this.systemName}] Worker not available, processing synchronously`);
|
||||||
this.processSynchronously(entities);
|
this.processSynchronously(entities);
|
||||||
this.isProcessing = false;
|
this.isProcessing = false;
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.isProcessing = false;
|
this.isProcessing = false;
|
||||||
|
console.error(`[${this.systemName}] Processing failed:`, error);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -636,11 +654,27 @@ export abstract class WorkerEntitySystem<TEntityData = any> extends EntitySystem
|
|||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
workerCount: number;
|
workerCount: number;
|
||||||
isProcessing: boolean;
|
isProcessing: boolean;
|
||||||
|
sharedArrayBufferSupported: boolean;
|
||||||
|
sharedArrayBufferEnabled: boolean;
|
||||||
|
currentMode: 'shared-buffer' | 'worker' | 'sync';
|
||||||
} {
|
} {
|
||||||
|
let currentMode: 'shared-buffer' | 'worker' | 'sync' = 'sync';
|
||||||
|
|
||||||
|
if (this.config.enableWorker && this.workerPool) {
|
||||||
|
if (this.config.useSharedArrayBuffer && this.sharedFloatArray && this.isSharedArrayBufferSupported()) {
|
||||||
|
currentMode = 'shared-buffer';
|
||||||
|
} else {
|
||||||
|
currentMode = 'worker';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
enabled: this.config.enableWorker,
|
enabled: this.config.enableWorker,
|
||||||
workerCount: this.config.workerCount,
|
workerCount: this.config.workerCount,
|
||||||
isProcessing: this.isProcessing
|
isProcessing: this.isProcessing,
|
||||||
|
sharedArrayBufferSupported: this.isSharedArrayBufferSupported(),
|
||||||
|
sharedArrayBufferEnabled: this.config.useSharedArrayBuffer,
|
||||||
|
currentMode
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
73
scripts/update-worker-demo.js
Normal file
73
scripts/update-worker-demo.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const DEMO_DIST_DIR = 'examples/worker-system-demo/dist';
|
||||||
|
const VITEPRESS_DEMO_DIR = 'docs/public/demos/worker-system';
|
||||||
|
|
||||||
|
function updateWorkerDemo() {
|
||||||
|
console.log('🔄 更新 Worker System Demo 资源...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 清理旧的 JS 文件
|
||||||
|
const assetsDir = path.join(VITEPRESS_DEMO_DIR, 'assets');
|
||||||
|
if (fs.existsSync(assetsDir)) {
|
||||||
|
const files = fs.readdirSync(assetsDir);
|
||||||
|
const jsFiles = files.filter(file => file.startsWith('index-') && file.endsWith('.js'));
|
||||||
|
|
||||||
|
for (const jsFile of jsFiles) {
|
||||||
|
const filePath = path.join(assetsDir, jsFile);
|
||||||
|
fs.unlinkSync(filePath);
|
||||||
|
console.log(`🗑️ 删除旧文件: ${jsFile}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 复制新的资源文件
|
||||||
|
const sourceAssetsDir = path.join(DEMO_DIST_DIR, 'assets');
|
||||||
|
if (!fs.existsSync(sourceAssetsDir)) {
|
||||||
|
throw new Error(`源目录不存在: ${sourceAssetsDir}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保目标目录存在
|
||||||
|
if (!fs.existsSync(assetsDir)) {
|
||||||
|
fs.mkdirSync(assetsDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourceFiles = fs.readdirSync(sourceAssetsDir);
|
||||||
|
const newJsFile = sourceFiles.find(file => file.startsWith('index-') && file.endsWith('.js'));
|
||||||
|
|
||||||
|
if (!newJsFile) {
|
||||||
|
throw new Error('未找到新的 JS 文件');
|
||||||
|
}
|
||||||
|
|
||||||
|
// 复制新的 JS 文件
|
||||||
|
const sourcePath = path.join(sourceAssetsDir, newJsFile);
|
||||||
|
const targetPath = path.join(assetsDir, newJsFile);
|
||||||
|
fs.copyFileSync(sourcePath, targetPath);
|
||||||
|
console.log(`📁 复制新文件: ${newJsFile}`);
|
||||||
|
|
||||||
|
// 3. 更新 index.html 中的引用
|
||||||
|
const indexHtmlPath = path.join(VITEPRESS_DEMO_DIR, 'index.html');
|
||||||
|
if (fs.existsSync(indexHtmlPath)) {
|
||||||
|
let content = fs.readFileSync(indexHtmlPath, 'utf-8');
|
||||||
|
|
||||||
|
// 更新 script 标签中的文件名
|
||||||
|
const scriptRegex = /src="\/ecs-framework\/demos\/worker-system\/assets\/index-[^"]+\.js"/;
|
||||||
|
const newScriptSrc = `/ecs-framework/demos/worker-system/assets/${newJsFile}`;
|
||||||
|
content = content.replace(scriptRegex, `src="${newScriptSrc}"`);
|
||||||
|
|
||||||
|
fs.writeFileSync(indexHtmlPath, content);
|
||||||
|
console.log(`📝 更新 index.html 引用: ${newJsFile}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('✅ Worker System Demo 资源更新完成!');
|
||||||
|
console.log('💡 提示:运行 npm run docs:build 来重新构建文档');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ 更新失败:', error.message);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateWorkerDemo();
|
||||||
Reference in New Issue
Block a user