@hastearcade/snowglobe
Version:
A TypeScript port of CrystalOrb, a high-level Rust game networking library
1,385 lines (1,360 loc) • 76.7 kB
JavaScript
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJS = (cb, mod) => function __require() {
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
};
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// node_modules/csv-writer/dist/lib/csv-stringifiers/abstract.js
var require_abstract = __commonJS({
"node_modules/csv-writer/dist/lib/csv-stringifiers/abstract.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var DEFAULT_RECORD_DELIMITER = "\n";
var VALID_RECORD_DELIMITERS = [DEFAULT_RECORD_DELIMITER, "\r\n"];
var CsvStringifier = (
/** @class */
function() {
function CsvStringifier2(fieldStringifier, recordDelimiter) {
if (recordDelimiter === void 0) {
recordDelimiter = DEFAULT_RECORD_DELIMITER;
}
this.fieldStringifier = fieldStringifier;
this.recordDelimiter = recordDelimiter;
_validateRecordDelimiter(recordDelimiter);
}
CsvStringifier2.prototype.getHeaderString = function() {
var headerRecord = this.getHeaderRecord();
return headerRecord ? this.joinRecords([this.getCsvLine(headerRecord)]) : null;
};
CsvStringifier2.prototype.stringifyRecords = function(records) {
var _this = this;
var csvLines = Array.from(records, function(record) {
return _this.getCsvLine(_this.getRecordAsArray(record));
});
return this.joinRecords(csvLines);
};
CsvStringifier2.prototype.getCsvLine = function(record) {
var _this = this;
return record.map(function(fieldValue) {
return _this.fieldStringifier.stringify(fieldValue);
}).join(this.fieldStringifier.fieldDelimiter);
};
CsvStringifier2.prototype.joinRecords = function(records) {
return records.join(this.recordDelimiter) + this.recordDelimiter;
};
return CsvStringifier2;
}()
);
exports.CsvStringifier = CsvStringifier;
function _validateRecordDelimiter(delimiter) {
if (VALID_RECORD_DELIMITERS.indexOf(delimiter) === -1) {
throw new Error("Invalid record delimiter `" + delimiter + "` is specified");
}
}
}
});
// node_modules/csv-writer/dist/lib/csv-stringifiers/array.js
var require_array = __commonJS({
"node_modules/csv-writer/dist/lib/csv-stringifiers/array.js"(exports) {
"use strict";
var __extends = exports && exports.__extends || function() {
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
d2.__proto__ = b2;
} || function(d2, b2) {
for (var p in b2)
if (b2.hasOwnProperty(p))
d2[p] = b2[p];
};
return extendStatics(d, b);
};
return function(d, b) {
extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
}();
Object.defineProperty(exports, "__esModule", { value: true });
var abstract_1 = require_abstract();
var ArrayCsvStringifier = (
/** @class */
function(_super) {
__extends(ArrayCsvStringifier2, _super);
function ArrayCsvStringifier2(fieldStringifier, recordDelimiter, header) {
var _this = _super.call(this, fieldStringifier, recordDelimiter) || this;
_this.header = header;
return _this;
}
ArrayCsvStringifier2.prototype.getHeaderRecord = function() {
return this.header;
};
ArrayCsvStringifier2.prototype.getRecordAsArray = function(record) {
return record;
};
return ArrayCsvStringifier2;
}(abstract_1.CsvStringifier)
);
exports.ArrayCsvStringifier = ArrayCsvStringifier;
}
});
// node_modules/csv-writer/dist/lib/field-stringifier.js
var require_field_stringifier = __commonJS({
"node_modules/csv-writer/dist/lib/field-stringifier.js"(exports) {
"use strict";
var __extends = exports && exports.__extends || function() {
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
d2.__proto__ = b2;
} || function(d2, b2) {
for (var p in b2)
if (b2.hasOwnProperty(p))
d2[p] = b2[p];
};
return extendStatics(d, b);
};
return function(d, b) {
extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
}();
Object.defineProperty(exports, "__esModule", { value: true });
var DEFAULT_FIELD_DELIMITER = ",";
var VALID_FIELD_DELIMITERS = [DEFAULT_FIELD_DELIMITER, ";"];
var FieldStringifier = (
/** @class */
function() {
function FieldStringifier2(fieldDelimiter) {
this.fieldDelimiter = fieldDelimiter;
}
FieldStringifier2.prototype.isEmpty = function(value) {
return typeof value === "undefined" || value === null || value === "";
};
FieldStringifier2.prototype.quoteField = function(field) {
return '"' + field.replace(/"/g, '""') + '"';
};
return FieldStringifier2;
}()
);
exports.FieldStringifier = FieldStringifier;
var DefaultFieldStringifier = (
/** @class */
function(_super) {
__extends(DefaultFieldStringifier2, _super);
function DefaultFieldStringifier2() {
return _super !== null && _super.apply(this, arguments) || this;
}
DefaultFieldStringifier2.prototype.stringify = function(value) {
if (this.isEmpty(value))
return "";
var str = String(value);
return this.needsQuote(str) ? this.quoteField(str) : str;
};
DefaultFieldStringifier2.prototype.needsQuote = function(str) {
return str.includes(this.fieldDelimiter) || str.includes("\n") || str.includes('"');
};
return DefaultFieldStringifier2;
}(FieldStringifier)
);
var ForceQuoteFieldStringifier = (
/** @class */
function(_super) {
__extends(ForceQuoteFieldStringifier2, _super);
function ForceQuoteFieldStringifier2() {
return _super !== null && _super.apply(this, arguments) || this;
}
ForceQuoteFieldStringifier2.prototype.stringify = function(value) {
return this.isEmpty(value) ? "" : this.quoteField(String(value));
};
return ForceQuoteFieldStringifier2;
}(FieldStringifier)
);
function createFieldStringifier(fieldDelimiter, alwaysQuote) {
if (fieldDelimiter === void 0) {
fieldDelimiter = DEFAULT_FIELD_DELIMITER;
}
if (alwaysQuote === void 0) {
alwaysQuote = false;
}
_validateFieldDelimiter(fieldDelimiter);
return alwaysQuote ? new ForceQuoteFieldStringifier(fieldDelimiter) : new DefaultFieldStringifier(fieldDelimiter);
}
exports.createFieldStringifier = createFieldStringifier;
function _validateFieldDelimiter(delimiter) {
if (VALID_FIELD_DELIMITERS.indexOf(delimiter) === -1) {
throw new Error("Invalid field delimiter `" + delimiter + "` is specified");
}
}
}
});
// node_modules/csv-writer/dist/lib/lang/object.js
var require_object = __commonJS({
"node_modules/csv-writer/dist/lib/lang/object.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isObject = function(value) {
return Object.prototype.toString.call(value) === "[object Object]";
};
}
});
// node_modules/csv-writer/dist/lib/csv-stringifiers/object.js
var require_object2 = __commonJS({
"node_modules/csv-writer/dist/lib/csv-stringifiers/object.js"(exports) {
"use strict";
var __extends = exports && exports.__extends || function() {
var extendStatics = function(d, b) {
extendStatics = Object.setPrototypeOf || { __proto__: [] } instanceof Array && function(d2, b2) {
d2.__proto__ = b2;
} || function(d2, b2) {
for (var p in b2)
if (b2.hasOwnProperty(p))
d2[p] = b2[p];
};
return extendStatics(d, b);
};
return function(d, b) {
extendStatics(d, b);
function __() {
this.constructor = d;
}
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
}();
Object.defineProperty(exports, "__esModule", { value: true });
var abstract_1 = require_abstract();
var object_1 = require_object();
var ObjectCsvStringifier = (
/** @class */
function(_super) {
__extends(ObjectCsvStringifier2, _super);
function ObjectCsvStringifier2(fieldStringifier, header, recordDelimiter, headerIdDelimiter) {
var _this = _super.call(this, fieldStringifier, recordDelimiter) || this;
_this.header = header;
_this.headerIdDelimiter = headerIdDelimiter;
return _this;
}
ObjectCsvStringifier2.prototype.getHeaderRecord = function() {
if (!this.isObjectHeader)
return null;
return this.header.map(function(field) {
return field.title;
});
};
ObjectCsvStringifier2.prototype.getRecordAsArray = function(record) {
var _this = this;
return this.fieldIds.map(function(fieldId) {
return _this.getNestedValue(record, fieldId);
});
};
ObjectCsvStringifier2.prototype.getNestedValue = function(obj, key) {
if (!this.headerIdDelimiter)
return obj[key];
return key.split(this.headerIdDelimiter).reduce(function(subObj, keyPart) {
return (subObj || {})[keyPart];
}, obj);
};
Object.defineProperty(ObjectCsvStringifier2.prototype, "fieldIds", {
get: function() {
return this.isObjectHeader ? this.header.map(function(column) {
return column.id;
}) : this.header;
},
enumerable: true,
configurable: true
});
Object.defineProperty(ObjectCsvStringifier2.prototype, "isObjectHeader", {
get: function() {
return object_1.isObject(this.header && this.header[0]);
},
enumerable: true,
configurable: true
});
return ObjectCsvStringifier2;
}(abstract_1.CsvStringifier)
);
exports.ObjectCsvStringifier = ObjectCsvStringifier;
}
});
// node_modules/csv-writer/dist/lib/csv-stringifier-factory.js
var require_csv_stringifier_factory = __commonJS({
"node_modules/csv-writer/dist/lib/csv-stringifier-factory.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var array_1 = require_array();
var field_stringifier_1 = require_field_stringifier();
var object_1 = require_object2();
var CsvStringifierFactory = (
/** @class */
function() {
function CsvStringifierFactory2() {
}
CsvStringifierFactory2.prototype.createArrayCsvStringifier = function(params) {
var fieldStringifier = field_stringifier_1.createFieldStringifier(params.fieldDelimiter, params.alwaysQuote);
return new array_1.ArrayCsvStringifier(fieldStringifier, params.recordDelimiter, params.header);
};
CsvStringifierFactory2.prototype.createObjectCsvStringifier = function(params) {
var fieldStringifier = field_stringifier_1.createFieldStringifier(params.fieldDelimiter, params.alwaysQuote);
return new object_1.ObjectCsvStringifier(fieldStringifier, params.header, params.recordDelimiter, params.headerIdDelimiter);
};
return CsvStringifierFactory2;
}()
);
exports.CsvStringifierFactory = CsvStringifierFactory;
}
});
// node_modules/csv-writer/dist/lib/lang/promise.js
var require_promise = __commonJS({
"node_modules/csv-writer/dist/lib/lang/promise.js"(exports) {
"use strict";
var __spreadArrays = exports && exports.__spreadArrays || function() {
for (var s = 0, i = 0, il = arguments.length; i < il; i++)
s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
Object.defineProperty(exports, "__esModule", { value: true });
function promisify(fn) {
return function() {
var args = [];
for (var _i = 0; _i < arguments.length; _i++) {
args[_i] = arguments[_i];
}
return new Promise(function(resolve, reject) {
var nodeCallback = function(err, result) {
if (err)
reject(err);
else
resolve(result);
};
fn.apply(null, __spreadArrays(args, [nodeCallback]));
});
};
}
exports.promisify = promisify;
}
});
// node_modules/csv-writer/dist/lib/file-writer.js
var require_file_writer = __commonJS({
"node_modules/csv-writer/dist/lib/file-writer.js"(exports) {
"use strict";
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = exports && exports.__generator || function(thisArg, body) {
var _ = { label: 0, sent: function() {
if (t[0] & 1)
throw t[1];
return t[1];
}, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
return this;
}), g;
function verb(n) {
return function(v) {
return step([n, v]);
};
}
function step(op) {
if (f)
throw new TypeError("Generator is already executing.");
while (_)
try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
return t;
if (y = 0, t)
op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return { value: op[1], done: false };
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2])
_.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
} catch (e) {
op = [6, e];
y = 0;
} finally {
f = t = 0;
}
if (op[0] & 5)
throw op[1];
return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var promise_1 = require_promise();
var fs_1 = require("fs");
var writeFilePromise = promise_1.promisify(fs_1.writeFile);
var DEFAULT_ENCODING = "utf8";
var FileWriter = (
/** @class */
function() {
function FileWriter2(path, append, encoding) {
if (encoding === void 0) {
encoding = DEFAULT_ENCODING;
}
this.path = path;
this.append = append;
this.encoding = encoding;
}
FileWriter2.prototype.write = function(string) {
return __awaiter(this, void 0, void 0, function() {
return __generator(this, function(_a) {
switch (_a.label) {
case 0:
return [4, writeFilePromise(this.path, string, this.getWriteOption())];
case 1:
_a.sent();
this.append = true;
return [
2
/*return*/
];
}
});
});
};
FileWriter2.prototype.getWriteOption = function() {
return {
encoding: this.encoding,
flag: this.append ? "a" : "w"
};
};
return FileWriter2;
}()
);
exports.FileWriter = FileWriter;
}
});
// node_modules/csv-writer/dist/lib/csv-writer.js
var require_csv_writer = __commonJS({
"node_modules/csv-writer/dist/lib/csv-writer.js"(exports) {
"use strict";
var __awaiter = exports && exports.__awaiter || function(thisArg, _arguments, P, generator) {
function adopt(value) {
return value instanceof P ? value : new P(function(resolve) {
resolve(value);
});
}
return new (P || (P = Promise))(function(resolve, reject) {
function fulfilled(value) {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
}
function rejected(value) {
try {
step(generator["throw"](value));
} catch (e) {
reject(e);
}
}
function step(result) {
result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected);
}
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = exports && exports.__generator || function(thisArg, body) {
var _ = { label: 0, sent: function() {
if (t[0] & 1)
throw t[1];
return t[1];
}, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() {
return this;
}), g;
function verb(n) {
return function(v) {
return step([n, v]);
};
}
function step(op) {
if (f)
throw new TypeError("Generator is already executing.");
while (_)
try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done)
return t;
if (y = 0, t)
op = [op[0] & 2, t.value];
switch (op[0]) {
case 0:
case 1:
t = op;
break;
case 4:
_.label++;
return { value: op[1], done: false };
case 5:
_.label++;
y = op[1];
op = [0];
continue;
case 7:
op = _.ops.pop();
_.trys.pop();
continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
_ = 0;
continue;
}
if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
_.label = op[1];
break;
}
if (op[0] === 6 && _.label < t[1]) {
_.label = t[1];
t = op;
break;
}
if (t && _.label < t[2]) {
_.label = t[2];
_.ops.push(op);
break;
}
if (t[2])
_.ops.pop();
_.trys.pop();
continue;
}
op = body.call(thisArg, _);
} catch (e) {
op = [6, e];
y = 0;
} finally {
f = t = 0;
}
if (op[0] & 5)
throw op[1];
return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var file_writer_1 = require_file_writer();
var DEFAULT_INITIAL_APPEND_FLAG = false;
var CsvWriter = (
/** @class */
function() {
function CsvWriter2(csvStringifier, path, encoding, append) {
if (append === void 0) {
append = DEFAULT_INITIAL_APPEND_FLAG;
}
this.csvStringifier = csvStringifier;
this.append = append;
this.fileWriter = new file_writer_1.FileWriter(path, this.append, encoding);
}
CsvWriter2.prototype.writeRecords = function(records) {
return __awaiter(this, void 0, void 0, function() {
var recordsString, writeString;
return __generator(this, function(_a) {
switch (_a.label) {
case 0:
recordsString = this.csvStringifier.stringifyRecords(records);
writeString = this.headerString + recordsString;
return [4, this.fileWriter.write(writeString)];
case 1:
_a.sent();
this.append = true;
return [
2
/*return*/
];
}
});
});
};
Object.defineProperty(CsvWriter2.prototype, "headerString", {
get: function() {
var headerString = !this.append && this.csvStringifier.getHeaderString();
return headerString || "";
},
enumerable: true,
configurable: true
});
return CsvWriter2;
}()
);
exports.CsvWriter = CsvWriter;
}
});
// node_modules/csv-writer/dist/lib/csv-writer-factory.js
var require_csv_writer_factory = __commonJS({
"node_modules/csv-writer/dist/lib/csv-writer-factory.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var csv_writer_1 = require_csv_writer();
var CsvWriterFactory = (
/** @class */
function() {
function CsvWriterFactory2(csvStringifierFactory) {
this.csvStringifierFactory = csvStringifierFactory;
}
CsvWriterFactory2.prototype.createArrayCsvWriter = function(params) {
var csvStringifier = this.csvStringifierFactory.createArrayCsvStringifier({
header: params.header,
fieldDelimiter: params.fieldDelimiter,
recordDelimiter: params.recordDelimiter,
alwaysQuote: params.alwaysQuote
});
return new csv_writer_1.CsvWriter(csvStringifier, params.path, params.encoding, params.append);
};
CsvWriterFactory2.prototype.createObjectCsvWriter = function(params) {
var csvStringifier = this.csvStringifierFactory.createObjectCsvStringifier({
header: params.header,
fieldDelimiter: params.fieldDelimiter,
recordDelimiter: params.recordDelimiter,
headerIdDelimiter: params.headerIdDelimiter,
alwaysQuote: params.alwaysQuote
});
return new csv_writer_1.CsvWriter(csvStringifier, params.path, params.encoding, params.append);
};
return CsvWriterFactory2;
}()
);
exports.CsvWriterFactory = CsvWriterFactory;
}
});
// node_modules/csv-writer/dist/index.js
var require_dist = __commonJS({
"node_modules/csv-writer/dist/index.js"(exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var csv_stringifier_factory_1 = require_csv_stringifier_factory();
var csv_writer_factory_1 = require_csv_writer_factory();
var csvStringifierFactory = new csv_stringifier_factory_1.CsvStringifierFactory();
var csvWriterFactory = new csv_writer_factory_1.CsvWriterFactory(csvStringifierFactory);
exports.createArrayCsvStringifier = function(params) {
return csvStringifierFactory.createArrayCsvStringifier(params);
};
exports.createObjectCsvStringifier = function(params) {
return csvStringifierFactory.createObjectCsvStringifier(params);
};
exports.createArrayCsvWriter = function(params) {
return csvWriterFactory.createArrayCsvWriter(params);
};
exports.createObjectCsvWriter = function(params) {
return csvWriterFactory.createObjectCsvWriter(params);
};
}
});
// lib/dist/esm/index.js
var esm_exports = {};
__export(esm_exports, {
CLOCK_SYNC_MESSAGE_TYPE_ID: () => CLOCK_SYNC_MESSAGE_TYPE_ID,
COMMAND_MESSAGE_TYPE_ID: () => COMMAND_MESSAGE_TYPE_ID,
Client: () => Client,
SNAPSHOT_MESSAGE_TYPE_ID: () => SNAPSHOT_MESSAGE_TYPE_ID,
Server: () => Server,
StageState: () => StageState,
TweeningMethod: () => TweeningMethod,
getTimestamp: () => get,
makeConfig: () => makeConfig,
setTimestamp: () => set
});
module.exports = __toCommonJS(esm_exports);
// lib/dist/esm/analytics.js
var csv = __toESM(require_dist(), 1);
var AnalyticType;
(function(AnalyticType2) {
AnalyticType2[AnalyticType2["currentworld"] = 0] = "currentworld";
AnalyticType2[AnalyticType2["recvcommand"] = 1] = "recvcommand";
AnalyticType2[AnalyticType2["issuecommand"] = 2] = "issuecommand";
AnalyticType2[AnalyticType2["snapshotapplied"] = 3] = "snapshotapplied";
AnalyticType2[AnalyticType2["snapshotgenerated"] = 4] = "snapshotgenerated";
AnalyticType2[AnalyticType2["worldhistory"] = 5] = "worldhistory";
})(AnalyticType || (AnalyticType = {}));
var Analytics = class {
id;
data;
// tick number, map of analytic to data value
// we need to store for every tick
// a list of commands to process
// any snapshots generated
// any snapshots applied
// world history at that tick
// current world at that tick
// Data structure
// { tick0: {commands: string, snapshotsapplied: string, snapshotsgenerated: string, worldhistory: string, currentworld: string }}
constructor(id) {
this.id = id;
this.data = /* @__PURE__ */ new Map();
}
store(tickNumber, type, data) {
if (!this.data.has(tickNumber)) {
this.data.set(tickNumber, ["", "", "", "", ""]);
}
const dataStore = this.data.get(tickNumber);
dataStore[type] = data;
}
async flush() {
const csvWriter = csv.createArrayCsvWriter({
path: `${this.id}-${Date.now()}.csv`,
header: [
"tick",
"currentworld",
"recvcommand",
"issuecommand",
"snapshotapplied",
"snapshotgenerated",
"worldhistory"
]
});
const data = [];
this.data.forEach((val, key) => {
data.push([key.toString()].concat(val));
});
await csvWriter.writeRecords(data);
}
};
// lib/dist/esm/lib.js
function makeConfig(config = {}) {
return Object.assign({
serverTimeDelayLatency: 0.3,
blendLatency: 0.1,
timestepSeconds: 1 / 60,
clockSyncNeededSampleCount: 8,
clockSyncRequestPeriod: 0.2,
clockSyncAssumedOutlierRate: 0.2,
maxTolerableClockDeviation: 0.1,
snapshotSendPeriod: 0.1,
updateDeltaSecondsMax: 0.25,
timestampSkipThresholdSeconds: 1,
fastForwardMaxPerStep: 10,
tweeningMethod: TweeningMethod.Interpolated,
serverCommandHistoryFrameBufferSize: 60,
lagCompensateCommands: false
// this variable is used to delay commands for "other" players in the system so they see everything in the past
}, config);
}
var TweeningMethod;
(function(TweeningMethod2) {
TweeningMethod2[TweeningMethod2["MostRecentlyPassed"] = 0] = "MostRecentlyPassed";
TweeningMethod2[TweeningMethod2["Nearest"] = 1] = "Nearest";
TweeningMethod2[TweeningMethod2["Interpolated"] = 2] = "Interpolated";
})(TweeningMethod || (TweeningMethod = {}));
function shapeInterpolationT(method, t) {
switch (method) {
case TweeningMethod.MostRecentlyPassed:
return Math.floor(t);
case TweeningMethod.Nearest:
return Math.round(t);
case TweeningMethod.Interpolated:
return t;
}
}
function serverTimeDelayFrameCount(config) {
return Math.round(config.serverTimeDelayLatency / (1 / 60));
}
function clockSyncSamplesToDiscardPerExtreme(config) {
return Math.ceil(Math.max(config.clockSyncNeededSampleCount * config.clockSyncAssumedOutlierRate / 2, 1));
}
function clockSyncSamplesNeededToStore(config) {
return config.clockSyncNeededSampleCount + clockSyncSamplesToDiscardPerExtreme(config) * 2;
}
function blendProgressPerFrame(config) {
return config.timestepSeconds / config.blendLatency;
}
// lib/dist/esm/message.js
var nextTypeId = 0;
function makeTypeId() {
return nextTypeId++;
}
var CLOCK_SYNC_MESSAGE_TYPE_ID = makeTypeId();
var COMMAND_MESSAGE_TYPE_ID = makeTypeId();
var SNAPSHOT_MESSAGE_TYPE_ID = makeTypeId();
var NetworkMessageType;
(function(NetworkMessageType2) {
NetworkMessageType2[NetworkMessageType2["ClockSyncMessage"] = CLOCK_SYNC_MESSAGE_TYPE_ID] = "ClockSyncMessage";
NetworkMessageType2[NetworkMessageType2["CommandMessage"] = COMMAND_MESSAGE_TYPE_ID] = "CommandMessage";
NetworkMessageType2[NetworkMessageType2["SnapshotMessage"] = SNAPSHOT_MESSAGE_TYPE_ID] = "SnapshotMessage";
})(NetworkMessageType || (NetworkMessageType = {}));
// lib/dist/esm/clock_sync.js
var ClockSyncer = class {
_config;
_serverSecondsOffset;
_serverSecondsOffsetSamples = [];
_secondsSinceLastRequestSent = 0;
_clientId;
_pingArr;
_latestPing;
constructor(_config) {
this._config = _config;
this._pingArr = [];
this._latestPing = 30;
}
update(deltaSeconds, secondsSinceStartup, net) {
var _a;
this._secondsSinceLastRequestSent += deltaSeconds;
if (this._secondsSinceLastRequestSent > this._config.clockSyncRequestPeriod) {
this._secondsSinceLastRequestSent = 0;
net.broadcastMessage(CLOCK_SYNC_MESSAGE_TYPE_ID, {
clientPing: this._latestPing,
clientSendSecondsSinceStartup: secondsSinceStartup,
serverSecondsSinceStartup: 0,
clientId: 0
});
}
let latestServerSecondsOffset;
for (const [, connection] of net.connections()) {
let sync;
while ((sync = connection.recvClockSync()) != null) {
const { clientId, clientSendSecondsSinceStartup, serverSecondsSinceStartup } = sync;
const receivedTime = secondsSinceStartup;
const ping = Math.round(Math.max(0, (receivedTime - clientSendSecondsSinceStartup) / 2 * 1e3));
this._pingArr.push(ping);
if (this._pingArr.length > 10) {
const averagePingForLastTwenty = this._pingArr.map((p) => p).reduce((p, c) => p += c) / 10;
connection.setPing(Math.ceil(averagePingForLastTwenty));
this._latestPing = Math.ceil(averagePingForLastTwenty);
this._pingArr = [];
}
const correspondingClientTime = (clientSendSecondsSinceStartup + receivedTime) / 2;
const offset = serverSecondsSinceStartup - correspondingClientTime;
latestServerSecondsOffset = offset;
const existingId = (_a = this._clientId) != null ? _a : this._clientId = clientId;
console.assert(existingId === clientId, "The clock sync client ids should be the same");
}
}
if (latestServerSecondsOffset !== void 0) {
this.addSample(latestServerSecondsOffset);
}
}
isReady() {
return this._serverSecondsOffset !== void 0 && this._clientId !== void 0;
}
sampleCount() {
return this._serverSecondsOffsetSamples.length;
}
samplesNeeded() {
return clockSyncSamplesNeededToStore(this._config);
}
clientId() {
return this._clientId;
}
serverSecondsOffset() {
return this._serverSecondsOffset;
}
serverSecondsSinceStartup(clientSecondsSinceStartup) {
return this._serverSecondsOffset !== void 0 ? this._serverSecondsOffset + clientSecondsSinceStartup : this._serverSecondsOffset;
}
addSample(measuredSecondsOffset) {
this._serverSecondsOffsetSamples.unshift(measuredSecondsOffset);
console.assert(this._serverSecondsOffsetSamples.length <= clockSyncSamplesNeededToStore(this._config), "You offset samples are too high");
if (this._serverSecondsOffsetSamples.length >= clockSyncSamplesNeededToStore(this._config)) {
const rollingMeanOffsetSeconds = this.rollingMeanOffsetSeconds();
const isInitialSync = this._serverSecondsOffset === void 0;
const hasDesynced = this._serverSecondsOffset !== void 0 ? Math.abs(rollingMeanOffsetSeconds - this._serverSecondsOffset) > this._config.maxTolerableClockDeviation : false;
if (isInitialSync || hasDesynced) {
this._serverSecondsOffset = rollingMeanOffsetSeconds;
}
this._serverSecondsOffsetSamples.pop();
}
}
rollingMeanOffsetSeconds() {
const samples = this._serverSecondsOffsetSamples.slice();
samples.sort((a, b) => a - b);
const samplesWithoutOutliers = samples.slice(clockSyncSamplesToDiscardPerExtreme(this._config), samples.length - clockSyncSamplesToDiscardPerExtreme(this._config));
return samplesWithoutOutliers.reduce((sum, sample) => sum + sample, 0) / samplesWithoutOutliers.length;
}
};
// lib/dist/esm/math.js
function remEuclid(lhs, rhs) {
const r = lhs % rhs;
return r < 0 ? r + Math.abs(rhs) : r;
}
function clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
// lib/dist/esm/timestamp.js
var MAX = 32767;
var i16 = new Int16Array(1);
function make(value = 0) {
i16[0] = value;
return i16[0];
}
function fromSeconds(seconds, timestampSeconds) {
return make(makeFromSecondsFloat(seconds, timestampSeconds));
}
function comparableRangeWithMidpoint(timestamp) {
const maxDistanceFromMidpoint = MAX / 2;
return {
min: make(timestamp - maxDistanceFromMidpoint),
max: make(timestamp + maxDistanceFromMidpoint)
};
}
function acceptableTimestampRange(baseline, timestamp) {
const { min, max } = comparableRangeWithMidpoint(baseline);
return cmp(timestamp, min) >= 0 && cmp(timestamp, max) < 0;
}
function asSeconds(timestamp, timestampSeconds) {
return timestamp * timestampSeconds;
}
function add(timestamp, rhs) {
return make(timestamp + rhs);
}
function sub(timestamp, rhs) {
return make(timestamp - rhs);
}
function cmp(timestamp1, timestamp2) {
const difference = sub(timestamp1, timestamp2);
if (difference < 0) {
return -1;
}
if (difference === 0) {
return 0;
}
return 1;
}
function toFloat(timestamp) {
return +timestamp;
}
function makeFromUnwrappedFloat(frames) {
return remEuclid(frames + Math.pow(2, 15), Math.pow(2, 16)) - Math.pow(2, 15);
}
function makeFromSecondsFloat(seconds, timestampSeconds) {
return makeFromUnwrappedFloat(seconds / timestampSeconds);
}
function ceil(timestamp) {
return make(Math.ceil(timestamp));
}
function floor(timestamp) {
return make(Math.floor(timestamp));
}
function subFloat(timestamp, rhs) {
return makeFromUnwrappedFloat(timestamp - rhs);
}
function set(timestamped, timestamp) {
;
timestamped.timestamp = timestamp;
return timestamped;
}
function get(timestamped) {
return timestamped.timestamp;
}
// lib/dist/esm/command.js
var CommandBuffer = class {
map;
_timestamp;
constructor(map = /* @__PURE__ */ new Map(), _timestamp = make()) {
this.map = map;
this._timestamp = _timestamp;
}
timestamp() {
return this._timestamp;
}
filterStaleTimestamps(timestamp, before) {
if (timestamp != null) {
this.map.forEach((value, key) => {
if (cmp(key, timestamp) === (before ? -1 : 1)) {
this.map.delete(key);
}
});
}
}
updateTimestamp(timestamp) {
this._timestamp = timestamp;
const acceptableRange = comparableRangeWithMidpoint(this._timestamp);
this.filterStaleTimestamps(acceptableRange.min, true);
this.filterStaleTimestamps(acceptableRange.max, false);
}
drainAll() {
const sortedCommands = [...this.map.entries()].sort((a, b) => cmp(a[0], b[0]));
this.map.clear();
return sortedCommands.map((tc) => tc[1]).flat();
}
drainUpTo(timestamp) {
const sortedCommands = [...this.map.entries()].sort((a, b) => cmp(a[0], b[0]));
const filteredCommands = sortedCommands.filter((tc) => cmp(tc[0], timestamp) <= 0);
for (const [timestamp2] of filteredCommands) {
this.map.delete(timestamp2);
}
return filteredCommands.map((tc) => tc[1]).flat();
}
insert(timestampedCommand) {
const incomingTimestamp = get(timestampedCommand);
if (acceptableTimestampRange(this._timestamp, incomingTimestamp)) {
const commandsExist = this.map.get(incomingTimestamp);
if (commandsExist == null) {
this.map.set(incomingTimestamp, [timestampedCommand]);
} else {
this.map.set(incomingTimestamp, [...commandsExist, timestampedCommand]);
}
} else {
console.warn("The command's timestamp is outside the acceptable range and will be ignored");
}
}
commandsAt(timestamp) {
return this.map.get(timestamp);
}
length() {
return this.map.size;
}
[Symbol.iterator]() {
return this.map.entries();
}
clone() {
return new CommandBuffer(new Map(Array.from(this.map.entries()).map(([timestamp, commands]) => [
timestamp,
commands.map((command) => set(command.clone(), timestamp))
])), make(this._timestamp));
}
};
// lib/dist/esm/display_state.js
var Tweened = class {
_displayState;
timestamp;
constructor(_displayState, timestamp) {
this._displayState = _displayState;
this.timestamp = timestamp;
}
displayState() {
return this._displayState;
}
floatTimestamp() {
return this.timestamp;
}
clone() {
return new Tweened(this._displayState.clone(), this.timestamp);
}
};
function timestampedFromInterpolation(state1, state2, t, fromInterpolation) {
if (t === 0) {
return set(state1.clone(), get(state1));
} else if (Math.abs(t - 1) < Number.EPSILON) {
return set(state2.clone(), get(state2));
} else {
console.assert(get(state1) === get(state2), "The timestamps for interpolation do not match");
return set(fromInterpolation(state1, state2, t), get(state1));
}
}
function tweenedFromInterpolation(state1, state2, t, fromInterpolation) {
const timestampDifference = sub(get(state2), get(state1));
const timestampOffset = t * timestampDifference;
const timestampInterpolated = get(state1) + timestampOffset;
const results = fromInterpolation(state1, state2, t);
state1.dispose();
return new Tweened(results, timestampInterpolated);
}
// lib/dist/esm/fixed_timestepper.js
var TerminationCondition;
(function(TerminationCondition2) {
TerminationCondition2[TerminationCondition2["LastUndershoot"] = 0] = "LastUndershoot";
TerminationCondition2[TerminationCondition2["FirstOvershoot"] = 1] = "FirstOvershoot";
})(TerminationCondition || (TerminationCondition = {}));
function decomposeFloatTimestamp(condition, floatTimestamp, timestepSeconds) {
let timestamp;
switch (condition) {
case TerminationCondition.LastUndershoot:
timestamp = floor(floatTimestamp);
break;
case TerminationCondition.FirstOvershoot:
timestamp = ceil(floatTimestamp);
break;
}
const overshootSeconds = asSeconds(subFloat(toFloat(timestamp), floatTimestamp), timestepSeconds);
return [timestamp, overshootSeconds];
}
function shouldTerminate(condition, currentOvershootSeconds, nextOvershootSeconds) {
switch (condition) {
case TerminationCondition.LastUndershoot:
return nextOvershootSeconds > 0;
case TerminationCondition.FirstOvershoot:
return currentOvershootSeconds >= 0;
}
}
var TimeKeeper = class {
stepper;
terminationCondition;
timestepOvershootSeconds = 0;
config;
constructor(stepper, config, terminationCondition = TerminationCondition.LastUndershoot) {
this.stepper = stepper;
this.config = config;
this.terminationCondition = terminationCondition;
}
update(deltaSeconds, serverSecondsSinceStartup) {
const startTime = Date.now();
const compensateStart = Date.now();
const compensatedDeltaSeconds = this.deltaSecondsCompensateForDrift(deltaSeconds, serverSecondsSinceStartup);
const compensateEnd = Date.now();
const stepStart = Date.now();
const stepCount = this.advanceStepper(compensatedDeltaSeconds);
const stepEnd = Date.now();
const skipStart = Date.now();
this.timeskipIfNeeded(serverSecondsSinceStartup);
const skipEnd = Date.now();
const postStart = Date.now();
if (stepCount > 0)
this.stepper.postUpdate(this.timestepOvershootSeconds);
const postEnd = Date.now();
if (Date.now() - startTime > 15) {
console.log(`updating timekeeper took too long: ${Date.now() - startTime}`);
console.log(`updating drift took too long: ${compensateEnd - compensateStart}`);
console.log(`updating step took too long: ${stepEnd - stepStart}`);
console.log(`updating timeskip took too long: ${skipEnd - skipStart}`);
console.log(`updating postUpdate took too long: ${postEnd - postStart}`);
}
}
currentLogicalTimestamp() {
return subFloat(toFloat(this.stepper.lastCompletedTimestamp()), makeFromSecondsFloat(this.timestepOvershootSeconds, this.config.timestepSeconds));
}
targetLogicalTimestamp(serverSecondsSinceStartup) {
return makeFromSecondsFloat(serverSecondsSinceStartup, 1 / 60);
}
timestampDriftSeconds(serverSecondsSinceStartup) {
const frameDrift = subFloat(this.currentLogicalTimestamp(), this.targetLogicalTimestamp(serverSecondsSinceStartup));
const secondsDrift = asSeconds(frameDrift, this.config.timestepSeconds);
return secondsDrift;
}
deltaSecondsCompensateForDrift(deltaSeconds, serverSecondsSinceStartup) {
let timestampDriftSeconds;
const drift = this.timestampDriftSeconds(serverSecondsSinceStartup - deltaSeconds);
if (Math.abs(drift) < this.config.timestepSeconds * 0.5) {
timestampDriftSeconds = 0;
} else {
timestampDriftSeconds = drift;
}
const uncappedCompensatedDeltaSeconds = Math.max(deltaSeconds - timestampDriftSeconds, 0);
const compensatedDeltaSeconds = (
// Attempted to advance more than the allowed delta seconds. This should not happen too often.
uncappedCompensatedDeltaSeconds > this.config.updateDeltaSecondsMax ? this.config.updateDeltaSecondsMax : uncappedCompensatedDeltaSeconds
);
return compensatedDeltaSeconds;
}
advanceStepper(deltaSeconds) {
let stepCount = 0;
this.timestepOvershootSeconds -= deltaSeconds;
while (true) {
const nextOvershootSeconds = this.timestepOvershootSeconds + this.config.timestepSeconds;
if (shouldTerminate(this.terminationCondition, this.timestepOvershootSeconds, nextOvershootSeconds)) {
break;
}
this.stepper.step();
stepCount++;
this.timestepOvershootSeconds = nextOvershootSeconds;
}
return stepCount;
}
timeskipIfNeeded(serverSecondsSinceStartup) {
const driftSeconds = this.timestampDriftSeconds(serverSecondsSinceStartup);
if (Math.abs(driftSeconds) >= this.config.timestampSkipThresholdSeconds) {
const [correctedTimestamp, correctedOvershootSeconds] = decomposeFloatTimestamp(this.terminationCondition, this.targetLogicalTimestamp(serverSecondsSinceStartup), this.config.timestepSeconds);
this.stepper.resetLastCompletedTimestamp(correctedTimestamp);
this.timestepOvershootSeconds = correctedOvershootSeconds;
}
}
};
// lib/dist/esm/old_new.js
var OldNewState;
(function(OldNewState2) {
OldNewState2[OldNewState2["LeftOldRightNew"] = 0] = "LeftOldRightNew";
OldNewState2[OldNewState2["LeftNewRightOld"] = 1] = "LeftNewRightOld";
})(OldNewState || (OldNewState = {}));
var OldNew = class {
left;
right;
state = OldNewState.LeftNewRightOld;
constructor(left, right) {
this.left = left;
this.right = right;
}
setNew(value) {
if (this.state === OldNewState.LeftNewRightOld) {
this.left = value;
} else {
this.right = value;
}
}
get() {
if (this.state === OldNewState.LeftNewRightOld) {
return { old: this.right, new: this.left };
} else {
return { old: this.left, new: this.right };
}
}
swap() {
if (this.state === OldNewState.LeftNewRightOld) {
this.state = OldNewState.LeftOldRightNew;
} else {
this.state = OldNewState.LeftNewRightOld;
}
}
};
// lib/dist/esm/simulation.js
var InitializationType;
(function(InitializationType2) {
InitializationType2[InitializationType2["PreInitialized"] = 0] = "PreInitialized";
InitializationType2[InitializationType2["NeedsInitialization"] = 1] = "NeedsInitialization";
})(InitializationType || (InitializationType = {}));
var Simulation = class {
world;
commandBuffer = new CommandBuffer();
hasInitialized;
constructor(world, initializationType) {
this.world = world;
this.hasInitialized = initializationType === InitializationType.PreInitialized;
}
step(endingTimestamp = this.simulatingTimestamp()) {
const startTime = Date.now();
const commands = this.commandBuffer.drainUpTo(endingTimestamp);
for (const command of commands) {
this.world.applyCommand(command);
}
this.world.step();
this.commandBuffer.updateTimestamp(add(this.lastCompletedTimestamp(), 1));
const endTime = Date.now();
if (endTime - startTime > 15) {
console.log(`
simulation step took ${endTime - startTime}`);
}
}
getWorld() {
return this.world;
}
simulatingTimestamp() {
return add(this.lastCompletedTimestamp(), 1);
}
scheduleCommand(command) {
this.commandBuffer.insert(command);
}
tryCompletingSimulationsUpTo(targetCompletedTimestamp, maxSteps) {
for (let i = 0; i < maxSteps; i++) {
if (cmp(this.lastCompletedTimestamp(), targetCompletedTimestamp) > -1) {
break;
}
this.step();
}
}
applyCompletedSnapshot(completedSnapshot, rewoundCommandBuffer) {
this.world.applySnapshot(set(completedSnapshot, completedSnapshot.timestamp));
this.commandBuffer = rewoundCommandBuffer;
this.commandBuffer.updateTimestamp(get(completedSnapshot));
this.hasInitialized = true;
}
lastCompletedSnapshot() {
return set(this.world.snapshot(), this.lastCompletedTimestamp());
}
lastCompletedTimestamp() {
return this.commandBuffer.timestamp();
}
resetLastCompletedTimestamp(timestamp) {
const oldTimestamp = this.lastCompletedTimestamp();
this.commandBuffer.updateTimestamp(timestamp);
if (cmp(timestamp, oldTimestamp) === -1) {
const commands = this.commandBuffer.drainAll();
for (const command of commands) {
this.world.applyCommand(command);
}
}
}
displayState() {
if (this.hasInitialized) {
return set(this.world.displayState(), this.lastCompletedTimestamp());
}
return void 0;
}
bufferedCommands() {
return this.commandBuffer[Symbol.iterator]();
}
postUpdate() {
}
};
// lib/dist/esm/client.js
var StageState;
(function(StageState2) {
StageState2[StageState2["SyncingClock"] = 0] = "SyncingClock";
StageState2[StageState2["SyncingInitialState"] = 1] =