UNPKG

@javelin/net

Version:

Networking protocol and utilities for Javelin ECS.

152 lines 6.64 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createMessageProducer = void 0; const ecs_1 = require("@javelin/ecs"); const entity_map_1 = require("./entity_map"); const entity_priority_queue_1 = __importDefault(require("./entity_priority_queue")); const Message = __importStar(require("./message")); const MessageOp = __importStar(require("./message_op")); function createMessageProducer(options = {}) { const { maxByteLength = Infinity } = options; const queue = [Message.createMessage()]; const entityPriorities = new entity_priority_queue_1.default(); const entityUpdates = entity_map_1.createEntityMap(); const entityPatches = entity_map_1.createEntityMap(); let previousModel = null; function amplify(entity, priority) { var _a; entityPriorities.changePriority(entity, ((_a = entityPriorities.getPriority(entity)) !== null && _a !== void 0 ? _a : 0) + priority); } function enqueue(op, kind) { let message = queue[0]; // calculate the new message length. if we exceed the maxByteLength threshold, // create an enqueue a new message if (message === undefined || op.byteLength + message.byteLength > maxByteLength) { message = Message.createMessage(); queue.unshift(message); } Message.insert(message, kind, op); return message; } function attach(entity, components) { enqueue(MessageOp.snapshot(Message.getEnhancedModel(), entity, components), Message.MessagePartKind.Attach); } function update(entity, components, priority = 1) { let updates = entityUpdates[entity]; if (updates === undefined) { updates = entityUpdates[entity] = new Map(); } // overwrite existing component updates with latest component, in case it // changed (i.e. the original component was detached and a new instance // was attached) for (let i = 0; i < components.length; i++) { const component = components[i]; updates.set(ecs_1.getSchemaId(component), component); } amplify(entity, priority); } function patch(entity, component, priority = 1) { var _a; const id = ecs_1.getSchemaId(component); const patches = ((_a = entityPatches[entity]) !== null && _a !== void 0 ? _a : (entityPatches[entity] = new Map())); const patch = patches.get(id); if (patch === undefined) { patches.set(id, ecs_1.createPatch(component)); } else { ecs_1.createPatch(component, patch); } amplify(entity, priority); } function detach(entity, components) { enqueue(MessageOp.detach(entity, components.map(ecs_1.getSchemaId)), Message.MessagePartKind.Detach); } function destroy(entity) { enqueue(MessageOp.destroy(entity), Message.MessagePartKind.Destroy); // remove any planned patches or updates since the entity was destroyed delete entityPatches[entity]; delete entityUpdates[entity]; entityPriorities.remove(entity); } function take(includeModel = previousModel !== ecs_1.UNSAFE_internals.model) { const message = queue.pop() || Message.createMessage(); // insert a new model automatically if it has changed. otherwise, the // caller can pass `true` to force model inclusion if (includeModel) { Message.model(message); previousModel = ecs_1.UNSAFE_internals.model; } const model = Message.getEnhancedModel(); while (true) { // take the next-highest priority entity out of the priority queue const entity = entityPriorities.poll(); if (entity === null || entity === undefined) { break; } const updates = entityUpdates[entity]; const patches = entityPatches[entity]; // include component updates if (updates && updates.size > 0) { const components = Array.from(updates.values()); const op = MessageOp.snapshot(model, entity, components); // message would exceed max byte length if (op.byteLength + (message === null || message === void 0 ? void 0 : message.byteLength) >= maxByteLength) { break; } Message.insert(message, Message.MessagePartKind.Snapshot, op); updates.clear(); } // include component patches if (patches && patches.size > 0) { for (const patch of patches.values()) { if (patch.changes.size === 0) { continue; } const op = MessageOp.patch(model, entity, patch); // message would exceed max byte length if (op.byteLength + (message === null || message === void 0 ? void 0 : message.byteLength) >= maxByteLength) { break; } Message.insert(message, Message.MessagePartKind.Patch, op); // reset the patch since it was incorporated into a message ecs_1.resetPatch(patch); } } } return message; } return { amplify, attach, update, patch, detach, destroy, take, }; } exports.createMessageProducer = createMessageProducer; //# sourceMappingURL=message_producer.js.map