/******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ "./node_modules/eventemitter3/index.js": /*!*********************************************!*\ !*** ./node_modules/eventemitter3/index.js ***! \*********************************************/ /***/ ((module) => { var has = Object.prototype.hasOwnProperty , prefix = '~'; /** * Constructor to create a storage for our `EE` objects. * An `Events` instance is a plain object whose properties are event names. * * @constructor * @private */ function Events() {} // // We try to not inherit from `Object.prototype`. In some engines creating an // instance in this way is faster than calling `Object.create(null)` directly. // If `Object.create(null)` is not supported we prefix the event names with a // character to make sure that the built-in object properties are not // overridden or used as an attack vector. // if (Object.create) { Events.prototype = Object.create(null); // // This hack is needed because the `__proto__` property is still inherited in // some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5. // if (!new Events().__proto__) prefix = false; } /** * Representation of a single event listener. * * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} [once=false] Specify if the listener is a one-time listener. * @constructor * @private */ function EE(fn, context, once) { this.fn = fn; this.context = context; this.once = once || false; } /** * Add a listener for a given event. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} context The context to invoke the listener with. * @param {Boolean} once Specify if the listener is a one-time listener. * @returns {EventEmitter} * @private */ function addListener(emitter, event, fn, context, once) { if (typeof fn !== 'function') { throw new TypeError('The listener must be a function'); } var listener = new EE(fn, context || emitter, once) , evt = prefix ? prefix + event : event; if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++; else if (!emitter._events[evt].fn) emitter._events[evt].push(listener); else emitter._events[evt] = [emitter._events[evt], listener]; return emitter; } /** * Clear event by name. * * @param {EventEmitter} emitter Reference to the `EventEmitter` instance. * @param {(String|Symbol)} evt The Event name. * @private */ function clearEvent(emitter, evt) { if (--emitter._eventsCount === 0) emitter._events = new Events(); else delete emitter._events[evt]; } /** * Minimal `EventEmitter` interface that is molded against the Node.js * `EventEmitter` interface. * * @constructor * @public */ function EventEmitter() { this._events = new Events(); this._eventsCount = 0; } /** * Return an array listing the events for which the emitter has registered * listeners. * * @returns {Array} * @public */ EventEmitter.prototype.eventNames = function eventNames() { var names = [] , events , name; if (this._eventsCount === 0) return names; for (name in (events = this._events)) { if (has.call(events, name)) names.push(prefix ? name.slice(1) : name); } if (Object.getOwnPropertySymbols) { return names.concat(Object.getOwnPropertySymbols(events)); } return names; }; /** * Return the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Array} The registered listeners. * @public */ EventEmitter.prototype.listeners = function listeners(event) { var evt = prefix ? prefix + event : event , handlers = this._events[evt]; if (!handlers) return []; if (handlers.fn) return [handlers.fn]; for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) { ee[i] = handlers[i].fn; } return ee; }; /** * Return the number of listeners listening to a given event. * * @param {(String|Symbol)} event The event name. * @returns {Number} The number of listeners. * @public */ EventEmitter.prototype.listenerCount = function listenerCount(event) { var evt = prefix ? prefix + event : event , listeners = this._events[evt]; if (!listeners) return 0; if (listeners.fn) return 1; return listeners.length; }; /** * Calls each of the listeners registered for a given event. * * @param {(String|Symbol)} event The event name. * @returns {Boolean} `true` if the event had listeners, else `false`. * @public */ EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return false; var listeners = this._events[evt] , len = arguments.length , args , i; if (listeners.fn) { if (listeners.once) this.removeListener(event, listeners.fn, undefined, true); switch (len) { case 1: return listeners.fn.call(listeners.context), true; case 2: return listeners.fn.call(listeners.context, a1), true; case 3: return listeners.fn.call(listeners.context, a1, a2), true; case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true; case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true; case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true; } for (i = 1, args = new Array(len -1); i < len; i++) { args[i - 1] = arguments[i]; } listeners.fn.apply(listeners.context, args); } else { var length = listeners.length , j; for (i = 0; i < length; i++) { if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true); switch (len) { case 1: listeners[i].fn.call(listeners[i].context); break; case 2: listeners[i].fn.call(listeners[i].context, a1); break; case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break; case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break; default: if (!args) for (j = 1, args = new Array(len -1); j < len; j++) { args[j - 1] = arguments[j]; } listeners[i].fn.apply(listeners[i].context, args); } } } return true; }; /** * Add a listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.on = function on(event, fn, context) { return addListener(this, event, fn, context, false); }; /** * Add a one-time listener for a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn The listener function. * @param {*} [context=this] The context to invoke the listener with. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.once = function once(event, fn, context) { return addListener(this, event, fn, context, true); }; /** * Remove the listeners of a given event. * * @param {(String|Symbol)} event The event name. * @param {Function} fn Only remove the listeners that match this function. * @param {*} context Only remove the listeners that have this context. * @param {Boolean} once Only remove one-time listeners. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) { var evt = prefix ? prefix + event : event; if (!this._events[evt]) return this; if (!fn) { clearEvent(this, evt); return this; } var listeners = this._events[evt]; if (listeners.fn) { if ( listeners.fn === fn && (!once || listeners.once) && (!context || listeners.context === context) ) { clearEvent(this, evt); } } else { for (var i = 0, events = [], length = listeners.length; i < length; i++) { if ( listeners[i].fn !== fn || (once && !listeners[i].once) || (context && listeners[i].context !== context) ) { events.push(listeners[i]); } } // // Reset the array, or remove it completely if we have no more listeners. // if (events.length) this._events[evt] = events.length === 1 ? events[0] : events; else clearEvent(this, evt); } return this; }; /** * Remove all listeners, or those of the specified event. * * @param {(String|Symbol)} [event] The event name. * @returns {EventEmitter} `this`. * @public */ EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) { var evt; if (event) { evt = prefix ? prefix + event : event; if (this._events[evt]) clearEvent(this, evt); } else { this._events = new Events(); this._eventsCount = 0; } return this; }; // // Alias methods names because people roll like that. // EventEmitter.prototype.off = EventEmitter.prototype.removeListener; EventEmitter.prototype.addListener = EventEmitter.prototype.on; // // Expose the prefix. // EventEmitter.prefixed = prefix; // // Allow `EventEmitter` to be imported as module namespace. // EventEmitter.EventEmitter = EventEmitter; // // Expose the module. // if (true) { module.exports = EventEmitter; } /***/ }), /***/ "./src/extensions/formTypeEx.ts": /*!**************************************!*\ !*** ./src/extensions/formTypeEx.ts ***! \**************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ FormTypeEx: () => (/* binding */ FormTypeEx) /* harmony export */ }); var FormTypeEx = /** @class */ (function () { function FormTypeEx() { } FormTypeEx.isItem = function (type) { return type === 42 /* FormType.Ammo */ || type === 26 /* FormType.Armor */ || type === 27 /* FormType.Book */ || type === 30 /* FormType.Ingredient */ || type === 31 /* FormType.Light */ || type === 46 /* FormType.Potion */ || type === 23 /* FormType.ScrollItem */ || type === 52 /* FormType.SoulGem */ || type === 41 /* FormType.Weapon */ || type === 32 /* FormType.Misc */; }; return FormTypeEx; }()); /***/ }), /***/ "./src/extensions/objectReferenceEx.ts": /*!*********************************************!*\ !*** ./src/extensions/objectReferenceEx.ts ***! \*********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ObjectReferenceEx: () => (/* binding */ ObjectReferenceEx) /* harmony export */ }); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _formTypeEx__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./formTypeEx */ "./src/extensions/formTypeEx.ts"); var ObjectReferenceEx = /** @class */ (function () { function ObjectReferenceEx() { } ObjectReferenceEx.getWorldOrCell = function (self) { var world = self.getWorldSpace(); if (world) { return world.getFormID(); } var cell = self.getParentCell(); if (cell) { return cell.getFormID(); } return 0; }; ObjectReferenceEx.getPos = function (self) { return [self.getPositionX(), self.getPositionY(), self.getPositionZ()]; }; ; ObjectReferenceEx.getDistance = function (a, b) { var deltaX = a[0] - b[0]; var deltaY = a[1] - b[1]; var deltaZ = a[2] - b[2]; return Math.sqrt(deltaX * deltaX + deltaY * deltaY + deltaZ * deltaZ); }; ; ObjectReferenceEx.getDistanceNoZ = function (a, b) { var deltaX = a[0] - b[0]; var deltaY = a[1] - b[1]; return Math.sqrt(deltaX * deltaX + deltaY * deltaY); }; ; ObjectReferenceEx.dealWithRef = function (self, base) { var _a, _b; var t = base.getType(); var isItem = _formTypeEx__WEBPACK_IMPORTED_MODULE_1__.FormTypeEx.isItem(t); // BlackFallsBarrow02, door isn't opening via SetOpen so we're hacking it. // Not blocking activation & asking parent to activate until will be in the correct state // See also modelApplyUtils.ts var caveGSecretDoor01 = 0x6f703; // You can also block for t === FormType.Flora || t === FormType.Tree, but I don't think it's necessary. if (t === 40 /* FormType.Furniture */ || t === 24 /* FormType.Activator */ || t === 28 /* FormType.Container */ || isItem || t === 43 /* FormType.NPC */ || (t === 29 /* FormType.Door */ && ((_a = self.getBaseObject()) === null || _a === void 0 ? void 0 : _a.getFormID()) !== caveGSecretDoor01)) { self.blockActivation(true); } else { self.blockActivation(false); } if (self.isLocked()) { self.lock(false, false); } if (isItem) { self.setMotionType(4 /* MotionType.Keyframed */, false); } // https://github.com/skyrim-multiplayer/issue-tracker/issues/36 if (t === 39 /* FormType.Flora */ && ((_b = skyrimPlatform__WEBPACK_IMPORTED_MODULE_0__.Flora.from(base)) === null || _b === void 0 ? void 0 : _b.getIngredient())) { self.setMotionType(4 /* MotionType.Keyframed */, false); } }; return ObjectReferenceEx; }()); /***/ }), /***/ "./src/features/authModel.ts": /*!***********************************!*\ !*** ./src/features/authModel.ts ***! \***********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ authGameDataStorageKey: () => (/* binding */ authGameDataStorageKey) /* harmony export */ }); ; ; ; var authGameDataStorageKey = "authGameData"; /***/ }), /***/ "./src/lib/errors.ts": /*!***************************!*\ !*** ./src/lib/errors.ts ***! \***************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ NeverError: () => (/* binding */ NeverError), /* harmony export */ RespawnNeededError: () => (/* binding */ RespawnNeededError) /* harmony export */ }); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var RespawnNeededError = /** @class */ (function (_super) { __extends(RespawnNeededError, _super); function RespawnNeededError(message) { var _this = _super.call(this, message) || this; Object.setPrototypeOf(_this, RespawnNeededError.prototype); return _this; } return RespawnNeededError; }(Error)); var NeverError = /** @class */ (function (_super) { __extends(NeverError, _super); function NeverError(message) { var _this = _super.call(this, "NeverError: ".concat(JSON.stringify(message))) || this; Object.setPrototypeOf(_this, NeverError.prototype); return _this; } return NeverError; }(Error)); /***/ }), /***/ "./src/lib/functionInfo.ts": /*!*********************************!*\ !*** ./src/lib/functionInfo.ts ***! \*********************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ FunctionInfo: () => (/* binding */ FunctionInfo) /* harmony export */ }); var FunctionInfo = /** @class */ (function () { function FunctionInfo(f) { this.f = f; } Object.defineProperty(FunctionInfo.prototype, "text", { get: function () { // this part is different to functionInfo.ts used in skymp5-functions-lib return this.getTextWithoutErrorHandling(); }, enumerable: false, configurable: true }); FunctionInfo.prototype.getText = function (args) { if (!args) { return this.text; } return "(function(){const {".concat(Object.keys(args).join(','), "} = ").concat(JSON.stringify(args), ";").concat(this.text, "})()"); }; FunctionInfo.prototype.getTextWithoutErrorHandling = function () { var funcString = this.f.toString().substring(0, this.f.toString().length - 1); return funcString.replace(new RegExp('^.+?{', 'm'), '').trim(); }; return FunctionInfo; }()); /***/ }), /***/ "./src/lib/idManager.ts": /*!******************************!*\ !*** ./src/lib/idManager.ts ***! \******************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ IdManager: () => (/* binding */ IdManager) /* harmony export */ }); var IdManager = /** @class */ (function () { function IdManager() { this.idByValue = new Array(); this.valueById = new Array(); this.minimumUnusedId = 0; } IdManager.prototype.allocateIdFor = function (value) { if (this.idByValue.length <= value) { this.idByValue.length = value + 1; } this.idByValue[value] = this.minimumUnusedId; if (this.valueById.length <= this.minimumUnusedId) { this.valueById.length = this.minimumUnusedId + 1; } this.valueById[this.minimumUnusedId] = value; var res = this.minimumUnusedId; this.minimumUnusedId++; while (this.valueById.length > this.minimumUnusedId && typeof this.valueById[this.minimumUnusedId] === "number") { this.minimumUnusedId++; } return res; }; IdManager.prototype.freeIdFor = function (value) { var id = this.idByValue[value]; if (id < this.minimumUnusedId) { this.minimumUnusedId = id; } this.idByValue[value] = undefined; this.valueById[id] = undefined; return; }; IdManager.prototype.getId = function (value) { var r = this.idByValue[value]; return typeof r === "number" ? r : -1; }; IdManager.prototype.getValueById = function (id) { return this.valueById[id]; }; return IdManager; }()); /***/ }), /***/ "./src/lib/nameof.ts": /*!***************************!*\ !*** ./src/lib/nameof.ts ***! \***************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ nameof: () => (/* binding */ nameof) /* harmony export */ }); function nameof(key) { return key; } /***/ }), /***/ "./src/logging.ts": /*!************************!*\ !*** ./src/logging.ts ***! \************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ logError: () => (/* binding */ logError), /* harmony export */ logTrace: () => (/* binding */ logTrace) /* harmony export */ }); /* harmony import */ var _skyrim_platform_skyrim_platform__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @skyrim-platform/skyrim-platform */ "skyrimPlatform"); /* harmony import */ var _skyrim_platform_skyrim_platform__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_skyrim_platform_skyrim_platform__WEBPACK_IMPORTED_MODULE_0__); var __spreadArray = (undefined && undefined.__spreadArray) || function (to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); }; // TODO: redirect this to spdlog function logError(service) { var rest = []; for (var _i = 1; _i < arguments.length; _i++) { rest[_i - 1] = arguments[_i]; } var restProcessed = rest.map(function (item) { if (item instanceof Error) { return item.stack || item.message; } return item; }); _skyrim_platform_skyrim_platform__WEBPACK_IMPORTED_MODULE_0__.printConsole.apply(void 0, __spreadArray(["Error in ".concat(typeof service !== "string" ? service.constructor.name : service, ":")], restProcessed, false)); } // TODO: redirect this to spdlog function logTrace(service) { var rest = []; for (var _i = 1; _i < arguments.length; _i++) { rest[_i - 1] = arguments[_i]; } var restProcessed = rest.map(function (item) { if (item instanceof Error) { return item.stack || item.message; } return item; }); _skyrim_platform_skyrim_platform__WEBPACK_IMPORTED_MODULE_0__.printConsole.apply(void 0, __spreadArray(["Trace in ".concat(typeof service !== "string" ? service.constructor.name : service, ":")], restProcessed, false)); } /***/ }), /***/ "./src/messages.ts": /*!*************************!*\ !*** ./src/messages.ts ***! \*************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MsgType: () => (/* binding */ MsgType) /* harmony export */ }); var MsgType; (function (MsgType) { MsgType[MsgType["CustomPacket"] = 1] = "CustomPacket"; MsgType[MsgType["UpdateMovement"] = 2] = "UpdateMovement"; MsgType[MsgType["UpdateAnimation"] = 3] = "UpdateAnimation"; MsgType[MsgType["UpdateAppearance"] = 4] = "UpdateAppearance"; MsgType[MsgType["UpdateEquipment"] = 5] = "UpdateEquipment"; MsgType[MsgType["Activate"] = 6] = "Activate"; MsgType[MsgType["UpdateProperty"] = 7] = "UpdateProperty"; MsgType[MsgType["PutItem"] = 8] = "PutItem"; MsgType[MsgType["TakeItem"] = 9] = "TakeItem"; MsgType[MsgType["FinishSpSnippet"] = 10] = "FinishSpSnippet"; MsgType[MsgType["OnEquip"] = 11] = "OnEquip"; MsgType[MsgType["ConsoleCommand"] = 12] = "ConsoleCommand"; MsgType[MsgType["CraftItem"] = 13] = "CraftItem"; MsgType[MsgType["Host"] = 14] = "Host"; MsgType[MsgType["CustomEvent"] = 15] = "CustomEvent"; MsgType[MsgType["ChangeValues"] = 16] = "ChangeValues"; MsgType[MsgType["OnHit"] = 17] = "OnHit"; MsgType[MsgType["DeathStateContainer"] = 18] = "DeathStateContainer"; MsgType[MsgType["DropItem"] = 19] = "DropItem"; MsgType[MsgType["Teleport"] = 20] = "Teleport"; MsgType[MsgType["OpenContainer"] = 21] = "OpenContainer"; MsgType[MsgType["PlayerBowShot"] = 22] = "PlayerBowShot"; MsgType[MsgType["SpellCast"] = 23] = "SpellCast"; MsgType[MsgType["UpdateAnimVariables"] = 24] = "UpdateAnimVariables"; // ex-strings MsgType[MsgType["DestroyActor"] = 25] = "DestroyActor"; MsgType[MsgType["HostStart"] = 26] = "HostStart"; MsgType[MsgType["HostStop"] = 27] = "HostStop"; MsgType[MsgType["SetInventory"] = 28] = "SetInventory"; MsgType[MsgType["SetRaceMenuOpen"] = 29] = "SetRaceMenuOpen"; MsgType[MsgType["SpSnippet"] = 30] = "SpSnippet"; MsgType[MsgType["Teleport2"] = 31] = "Teleport2"; MsgType[MsgType["UpdateGamemodeData"] = 32] = "UpdateGamemodeData"; MsgType[MsgType["CreateActor"] = 33] = "CreateActor"; })(MsgType || (MsgType = {})); /***/ }), /***/ "./src/services/events/events.ts": /*!***************************************!*\ !*** ./src/services/events/events.ts ***! \***************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EventEmitterFactory: () => (/* binding */ EventEmitterFactory) /* harmony export */ }); /* harmony import */ var eventemitter3__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! eventemitter3 */ "./node_modules/eventemitter3/index.mjs"); var EventEmitterFactory = /** @class */ (function () { function EventEmitterFactory() { } EventEmitterFactory.makeEventEmitter = function () { return (new eventemitter3__WEBPACK_IMPORTED_MODULE_0__.EventEmitter()); }; return EventEmitterFactory; }()); /***/ }), /***/ "./src/services/services/activationService.ts": /*!****************************************************!*\ !*** ./src/services/services/activationService.ts ***! \****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ActivationService: () => (/* binding */ ActivationService) /* harmony export */ }); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _sync_inventory__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../sync/inventory */ "./src/sync/inventory.ts"); /* harmony import */ var _view_worldViewMisc__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../view/worldViewMisc */ "./src/view/worldViewMisc.ts"); /* harmony import */ var _lastInvService__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./lastInvService */ "./src/services/services/lastInvService.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _extensions_formTypeEx__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../../extensions/formTypeEx */ "./src/extensions/formTypeEx.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // TODO: refactor this out var ActivationService = /** @class */ (function (_super) { __extends(ActivationService, _super); function ActivationService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.controller.on("activate", function (e) { return _this.onActivate(e); }); return _this; } ActivationService.prototype.onActivate = function (e) { var lastInvService = this.controller.lookupListener(_lastInvService__WEBPACK_IMPORTED_MODULE_4__.LastInvService); lastInvService.lastInv = (0,_sync_inventory__WEBPACK_IMPORTED_MODULE_2__.getInventory)(this.sp.Game.getPlayer()); var caster = e.caster ? e.caster.getFormID() : 0; var target = e.target ? e.target.getFormID() : 0; if (!target || !caster) { return; } // Bloquear el "agarre" de items sueltos del mundo: si el target es // un item (clutter de la ciudad, etc.), no mandamos el Activate al // server, asi nunca pasa al inventario. La activacion vanilla ya // esta bloqueada por ObjectReferenceEx.dealWithRef, asi que apretar // E sobre el item no hace nada. Puertas / contenedores / NPCs no se // ven afectados — solo los FormType de item (FormTypeEx.isItem). var targetBase = e.target ? e.target.getBaseObject() : null; if (targetBase && _extensions_formTypeEx__WEBPACK_IMPORTED_MODULE_6__.FormTypeEx.isItem(targetBase.getType())) { return; } // Actors never have non-ff ids locally in skymp if (caster !== 0x14 && caster < 0xff000000) { return; } target = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_3__.localIdToRemoteId)(target); if (!target) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logError)(this, 'localIdToRemoteId returned 0 (target) in on(\'activate\')'); return; } caster = (0,_view_worldViewMisc__WEBPACK_IMPORTED_MODULE_3__.localIdToRemoteId)(caster); if (!caster) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logError)(this, 'localIdToRemoteId returned 0 (caster) in on(\'activate\')'); return; } var openState = e.target.getOpenState(); if (openState === 2 /* OpenState.Opening */ || openState === 4 /* OpenState.Closing */) { (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logTrace)(this, "Ignoring activation of door because it's already opening or closing"); return; } this.controller.emitter.emit("sendMessage", { message: { t: _messages__WEBPACK_IMPORTED_MODULE_1__.MsgType.Activate, data: { caster: caster, target: target, isSecondActivation: false } }, reliability: "reliable" }); (0,_logging__WEBPACK_IMPORTED_MODULE_5__.logTrace)(this, "Sent activation for caster=", caster.toString(16), "and target=", target.toString(16)); }; return ActivationService; }(_clientListener__WEBPACK_IMPORTED_MODULE_0__.ClientListener)); ; /***/ }), /***/ "./src/services/services/animDebugService.ts": /*!***************************************************!*\ !*** ./src/services/services/animDebugService.ts ***! \***************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnimDebugService: () => (/* binding */ AnimDebugService) /* harmony export */ }); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_2__); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __assign = (undefined && undefined.__assign) || function () { __assign = Object.assign || function(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; var playerId = 0x14; var AnimDebugService = /** @class */ (function (_super) { __extends(AnimDebugService, _super); function AnimDebugService(sp, controller) { var _this = this; var _a; _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.settings = _this.sp.settings["skymp5-client"]["animDebug"]; // clear previous texts in case of hotreload if (_this.sp.storage[AnimQueueCollection.Name] && _this.sp.storage[AnimQueueCollection.Name].clearSPText) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logTrace)(_this, "Destroying old AnimQueueCollection"); try { _this.sp.storage[AnimQueueCollection.Name].clearSPText(); } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_0__.logError)(_this, "Failed to destroy old AnimQueueCollection:", e); } } var self = _this; _this.sp.hooks.sendAnimationEvent.add({ enter: function (ctx) { }, leave: function (ctx) { self.onSendAnimationEventLeave(ctx); } }, playerId, playerId); if (!_this.settings || !_this.settings.isActive) { return _this; } if ((_a = _this.settings.textOutput) === null || _a === void 0 ? void 0 : _a.isActive) { _this.queue = new AnimQueueCollection(_this.sp, _this.settings); _this.sp.storage[AnimQueueCollection.name] = _this.queue; } return _this; } AnimDebugService.prototype.onSendAnimationEventLeave = function (ctx) { if (this.queue === undefined) { return; } this.queue.push(ctx.animEventName, ctx.animationSucceeded ? animationSucceededTextColor : animationNotSucceededTextColor); }; return AnimDebugService; }(_clientListener__WEBPACK_IMPORTED_MODULE_1__.ClientListener)); var animationSucceededTextColor = [255, 255, 255, 1]; var animationNotSucceededTextColor = [255, 0, 0, 1]; var AnimQueueCollection = /** @class */ (function () { function AnimQueueCollection(sp, settings) { var _a, _b, _c, _d, _e, _f; this.sp = sp; var arrayLength = (_b = (_a = settings === null || settings === void 0 ? void 0 : settings.textOutput) === null || _a === void 0 ? void 0 : _a.itemCount) !== null && _b !== void 0 ? _b : 5; var startPos = (_d = (_c = settings === null || settings === void 0 ? void 0 : settings.textOutput) === null || _c === void 0 ? void 0 : _c.startPos) !== null && _d !== void 0 ? _d : { x: 650, y: 600 }; ; var yPosDelta = (_f = (_e = settings === null || settings === void 0 ? void 0 : settings.textOutput) === null || _e === void 0 ? void 0 : _e.yPosDelta) !== null && _f !== void 0 ? _f : 32; var y = startPos.y; this.list = new Array(arrayLength); for (var idx = 0; idx < arrayLength; ++idx) { this.list[idx] = { name: "", textId: sp.createText(startPos.x, y, "", animationSucceededTextColor), color: animationSucceededTextColor }; (0,skyrimPlatform__WEBPACK_IMPORTED_MODULE_2__.setTextSize)(this.list[idx].textId, 0.5); y += yPosDelta; } } AnimQueueCollection.prototype.clearSPText = function () { var _this = this; if (this.list.length === 0) { return; } this.list.forEach(function (item) { return _this.sp.destroyText(item.textId); }); }; AnimQueueCollection.prototype.push = function (animName, color) { var prevItem = null; for (var idx = this.list.length - 1; idx >= 0; --idx) { var item = this.list[idx]; prevItem = __assign({}, item); item.name = animName; item.color = color; this.sp.setTextString(item.textId, item.name); this.sp.setTextColor(item.textId, item.color); animName = prevItem.name; color = prevItem.color; } }; AnimQueueCollection.Name = "AnimQueueCollection"; return AnimQueueCollection; }()); /***/ }), /***/ "./src/services/services/authBranding.ts": /*!***********************************************!*\ !*** ./src/services/services/authBranding.ts ***! \***********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ELDERVALE_LOGO_DATA_URI: () => (/* binding */ ELDERVALE_LOGO_DATA_URI), /* harmony export */ ELDERVALE_THEME: () => (/* binding */ ELDERVALE_THEME) /* harmony export */ }); // Eldervale Realm — branding assets for the authorization window. // The emblem is inlined as a base64 data URI so the auth theme requires no // extra files distributed through the launcher manifest (everything ships // inside skymp5-client.js). Source: skymp-admin/public/brand/emblem.png, // downscaled to 160px. Regenerate with: // convert emblem.png -resize 160x160 -strip out.png && base64 -w0 out.png var ELDERVALE_LOGO_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAH0AAACgCAYAAAAhIGPUAABgeUlEQVR42u19Z5xdVfX22uWUW6dPZiaZSe+NhIReQpGmgAgoYgNUsCsqAlZExYKgolIFKULoHQKBQBJCCOlt0pPpfW4/fbf3w7njX8gEAqQovM+PfCC5u66z2yrPQvARw+233wnDhtYZZeWlR6VSqaXtHR3+1y677GB364CCHuwOHGhMnz4VdF1PVFSUnxaNRRtramt6D3afDjQ+ckIfNmwoCC6GlZaWniqlfJRq2kdO6Phgd+BAo7a2FgChCQjjkZqmTxpaV3ewu3TA8ZES+jU/+SUghEDTtKkIIKrr2syhDXX49jtuO9hd+//YX1izei2seHNFST6Xf8nzPJXL5V5bt35dxYaNGw521w4oPlJnenV1Ffi+P5JqdCIhBDRNH1VWWlZPKEkd7L4dSHyktve6oXUQjUZnAqAKIQRDCJURSibV1X60zvWPjNAfefgx+M63LieGYRyOMdI5F0wqSQ3dmI0Qwvfed9/B7uIBw0dme58wYTyMGTumDGM8BSEEhBCCMSKGYcxeu3ZtKSEkfbD7eKDwkRF6dXU1uK47EhM8nBCCCAEdABAhZFQimRhuGuZHRugfme29ekgVRGPRGZqmVSmlJAAAAqQAoDQaic6o+wi91z8SQn/i8SfhT3/8MyWEHA6AqBBCcMYDKaXUNC0SjUaO/eMfr6dPPvnEwe7qAcFHYnsfM2YMjBgxoooQPA0hAIwpZSzwQYKghBKE8PSTTjppiKZpHQe7rwcCHwmhDx1aB4VCYZyu6yMJoRhAKU3TdAAALjiTUtYlS5LjS0tKPxJC/9Bv71OmzoSy8jIwI+YspSDm+74jhBQAAFJKqRRISrWSRDx5REVFJXzu85872F3e70AHuwP7G8veeBN8348cMmP6A4ZhnCmE9JWUChBShGBKMKGAgDqO89yGxo0X6JpuHX7YYQe72/sVH/rtfUhNNQguhmmaNhVjjJQCIkEJx3H6EolETfjZI0kImVBXW1dPCNl8sPu8v/Gh396H1tVBJBKZLqWslFIKQjE1DCNSWlpaTwjRpFQyCALbtm1No3TasKFDD3aX9zs+1EJ//OHH4JLPX4JN0ziWEhJHCCOCCUEIIYwxQQhjSolm21ZaKYUNQz/29ttuofPmPX+wu75f8aE+0zc1bgLOee3wEcOfisVis6WUHGOMpZQKFIACUJwzP51OdZSVldcDqO0dHR2fwIS0jR0z9mB3f7/hQ32mDx8xHNKp9DSq0TEAoDAmhHPGlALp+163rtFK13Ec04wkMSEYlBoRiycOqSgvbzvYfd+f+NBu77+59rcQjUbBNCNHU0yTUoLgjDHGWCAED2zbXgoI+7phRGKxWClGBCOEooauHxeJRNBdd911sIew3/ChXeknn3IyLH39jZIJEyYcLpVSWCkFCMAwDJMxVuCcNwFAoGl6glJKEEJYSgBd149evWZNFaX0Q+sw+aFd6WPGjoKhQ+smGqY+lXPuA0jAGBOMMUUIMaXULs55gRBCAQCUVFIKyRBCYyrKy2eMHjX6YA9hv+FDKfSfXf1TKC8vh2g0ehIhpCKXy/Z6nucopaSUUkgpLdu2dyqlMkopkFIpqaQMWODlclmHYHxsLBZFf7npLwd7KPsFH8rt/axPng3Lly0vHTl65NGMMZ5MJssEFwJjTJRSCJRKO7bdKrhI/fv5BoBszjMAIM1I5LjVa9ZUE4x7DvZY9gc+lCt9+IjhUD2keoJhGFMpodg0zDgPr3E+AEJCiP6Ozs6UbhhpAEBSSsGECBjjoqysfEg0Gp1WXVU1e9z48Qd7KPsFHzqh//H6G6Gqugoi0ejHNE2vJuElDZUkS8oppVQILrgQO84+++w8Y0GrCP+Cc8ZYNBpNaJquE0KSkUjkE4888oj26qsLD/aQ9jk+dNv7aaedCmvXrqsaNWrkKZpGdYz//V0TAFCc88D3vEYAANf1Num64WsaNUEAwhhjQglRUoKu6yccefgRIwkh2w72mPY1PnQrfdz4sVBdVXWEpmlTEEJKSSWFkCL8IyTnPG/Z9tbe3j6QUjYBKLt4rmMhhGBBEBTdo4dGY9HjR44aCaUV0YM9rH2KD5XQl762BF6Z/3IkEolcgDFOuI5rMcaCIAg8wTkTQgjOeXdfX9+unp4esG27DSGUUlIBKFBKKel5ns25YBqlkUQiftYby5bGF7y0+GAPbZ/ioG3vd999NxBCcTabAUqp/PrXv/6B6xxaXw81daKeUjKLcx4AQkAopRRAQxhhKSQghFoCHvTncjkQXKSqq6q2KkONplRDlFANm4RIKQTCWGFMplVWVo00DXOfxD1d88trgHOBk8kkCCHk1VdddVDm/qCs9DeXL4ex48YnR40addiwYcNitTW1H7jOG/5wIzQMbwAzYp5KKB0KgJRhGBGCMSGUEIQRAgTID/y1c46bY69cuRyOn3Oc43neSoQQIiT8HaWE6rpuAICSUpYKzmfX19fvk3HXD6uHkSNGmIfNnj1zzpw5pWvWrDkY03/ghZ7NZCERTzRUlJV/wdB175xzzrHisQ9+Zp5+xmmwYd2Gmlg0doGmaVFd1w2MMVYAIISUnHHOOU8HfrDIsiy4/PLvQy6XAz/wFyGEskqpAYsjAgBkWVa+v7//qfaODnfp669Xv7ls2QfuY1VVFVxyySVOIp7wykpLv2iYxnilFFx/w/UHVAYHTOgPPvggAADq7e2dVVpS8guqkV2Hzjp07TNPPq1OPuWUD1T3aXNOhYmTJ0JFZcVpCONJCCGlVKhnU0qp4lkuPc9b09PTvXrnjh0AALB923Zoa21f63neUiklKKUAY4wAQEkhfCVU2aQJky4dMWLEpw47/HC47rrrPlA/zzrrLHju6Wdg5qEzN2KE15eWlP68qWnXx1p2NuFHHn74QIniwOCllxbAP/5xF23a1fTJ/v7+pW1tbV+78qqr8KsLF+6T+hs3boR1a9bW5LK5hel0Op3qT3UXCoVcoVDICSEkY0y4rut3d3d/XykFV/346n+XVUpBV1fXRb7ne4EfsMAPmG3ZVm9PT6tjOa7v+TKXzy1vbGwc2dq6byyuL8ybBwCAWlpazu/v71/R1tZ22csvvxR5442lB144+wOLFi6Gp5582mhrbft6JpNp7urq+tPzz8+LLFny+j6p/4H7HwClFHR3d3/XdV0nny/kU6lUb6FgFTKZbCrwA8Y5V5Zlbdy6deuYtra3Cm7H9h2wbcvW+lwutyKfL9hWwSr09fX15PP5AmOMF3eIoKen55eXXvo1/OL8+fuk388//zxc95tf067OrqtzuVx3V1fXL155ZUFy27b/cbXAsqVvwPwX5psdHZ0/zOVy/X19fc+sXrW6dsf2Hfusja6uLtiyecukfD6/gXOuOOcym81lMulMynFcx/eDwHVdr6e7+yoAQI889uhbyt91xz9AKQW7du28PNWf6s9kMulCoZAPgoBzzgVnXAR+wPOFws7tO7bP7uvv22d9X79+PaxYvqK0r6/vvkKhUOjp6fnT0qVLy5ubmg6UiPYt1q5ZD28uWxHt6Oi4KpfLp9LpzOZt27bP7u7edzaMxQsXw6MPP2r0dPfc5DpuUFyZIpPJ9loFK5/PF3K+7/N8vrBu06ZNo5p2DT6ZO3fshI0bNo7L5/ObfN/nnHPJOZdBwLjnep7juK7neTyV6r9vwYIF8TfffHOfjaG7uxs2bd48KZ/Pr3Nd1+/t7f3bG0uXlu/Yse8WxgHB+vUb4M1lb8b6evuucV03b1tWvqOj4xsAgObNe2GftPGve/4FSilobW09r1AodPuez3zfZ5xzKYRQnHHhuq7nuZ7T09NzuVIKHnvssUHreumll+DSr3wVp1Kpa33fD4KA88BnzPeDwLJs2/M8nzEmXMfNtrW1fV4pBX/605/3yTjuvedeUEpBe3v7Zy3L6rcsy+rp6fnbyhUrKv5nVvxri1+DJx57wujq6r7Kcdy85/kinU7PXfrGGyVr1u67d2k+m4NtW7ZOz+fz6xhjKggCxjkT4WoX0vM8v1Ao2PlcfuWmxs31W7e881m5fdt22Lply9h0Or3OcVzf9/3A9/3Atm2bMSZ83w8cx/Hz+fyaTZs2TUql9h1jyRtvvAHPP/+c2dvb+zfbdnzP87xUqv/vK1asKN25c+c+l9E+fbK98fob0NbaTo86+qhLE4n4DwHA9H1/RzqduWHM6NG5GYfM2GdtJUqSoOn6SIxxjVJKCiG4EEqEEamMSSklxhhRjdaVlJbMHDd+LLww78VB61r4ykL46pe+ikpLy48xDKOWUkIwxoQQQjRN08O6w6oBoJJSbXh5efk+G8uRRx4JM2Yc6mXS2Zs5Z1sQwlo0Grt4+IjhP+rq7oqu3YeLZZ/isUcfBQBA7W3tn7Ydp8d1vcCyLKu7u+tHlUNr0Ysv7Ztb7wAWL14Mjzz6iNba2vqlQqHQ7vsBDwLGPc/3LcuybNu2Xdf1goBJy7I2NjU1H5pOZwetK5fLQXNT8xGWZe1kjMkgCBhnXARBwBhjIjzfA5Ev5FtaW1ovvPWW2+jLLy3Yp+OZe/9cUEpBR3vH12zbzhfnL9Pd3XX57bfdShctWrhf5Pa+8cufXwtKKWhrbT2ukM9vcV0vsG3by2QyixobG2u3bt26X9p97rln4ac//QlpbW27yLbsbs658n0/KBThuq7HAsYDP5DZbPap9es3VGzZsuUtdSx/czm8uuDVRH9f//2e53PP83zbtu0Bgfu+79u27TiO09ve1v6l737nW+T5557dL+Np3LgJ1q1dV5HJZJ51HCfwPC+wLKuzva3tHKUUPDj3gf3S7vtCT08vbN2ybXShUFgaBIH0fZ85jlPo6Oi8WCkFF372i/ut7VcWvAK33nIL7e7u/p7jODnHcbxCoVCwLdvy/SBgTAgWXursrq6uryql4J93h+7NX7/0soFL1IWO4+aCgPEgCLjv+X6oqPGZbdtONpvt6enp+c5f//o3+vLL+3aFvx227UBLc+snc7lcr2VZtuO4fj6fX9vU1DStfx8+Fz8QVq1cBQtfWRjr7+u/1Ss+d3zfF9lsdsGatWuqNjZu3O99WLNmDSxZsiTW19f3J8dxnIEtmTHOg4Bz3w8Cx3b8TCazbFPjphEDT7ft27bDlk2b6/L5/GtBEEjOuRjQ4HEuJGNc2Lbt9PT2/v7VV1+NrFy5cr+PZcP6DbBqxcqSbDb7dBAEkjHGgyCQ6XT6oVWrVpdt2LD/5/Md8czTzwAAoJ7unksdx8natuP6vh9YlpVva2u9SCkFn/nsZw5IX7Zt2warVq0ckkqlnvZ8X/g+CwKfMatgFWzbtn3PDxzH8bq7u68GAPTkE0+CUgp6e3q/O/AkcxzbcWzbcR3H9T0WuK7PUun0U6vXrB6yq2nXAZtXpRR0d3ada1t22nYcx3YcN5vNpdvb2y+/8sdX4sVLXvtA9X+gWLbe3j4o5AuHVlVXPmAYxmghJCME64EfrGppaTmHUNIxceLEAzZZ2UwWCoXC8aWlpfdSTa8lBCHOOSOYEEwwVUoBY2xrd3f32Rjh7dlctnr06NGP67p+BAIQXAQ8dKFTwjAiUSFFZyrV/7lEMvlGxT68rb8bNm7YCIzxsqHD6u6JRqMfY4y7AEAwRn35fP6isrKyJfF4/H3X/76fbI0bG6G9ta2korL8CkrpCAUglVKKM+7bjv3o5CmTO95YemANCBs3boTnn33udcd17lFKCAAAUfR8ZIwFxQDGkZFo5IQRI0fAkCE1xxJCpoBSHGGMNc3QNc3QlZRCSM5cz/3njX+58c3169cd0HFMmToFDpkxPcMC9hxCSJqmEY1GI5FoNDo6mUz+cOfOneWbNx/gMPqHHnx4wMjxNc/zbMZCpYjjOF4mk9m8ZeuWSS2trQe2U0W0trbCpk2bRuTzhRWMMVUoFPKZbDbjOK5r27adzWYLra2t//jXff+KZrLZWxljigUBF+EjXwVBwDKpdCbV379gw8aNdTv2g3Jkb9C0qwm2b9s+xioUNg3YFAQXyvN8p6en51KlFNx2263vq+73tdKPPuZo2Lx5y9hYLPZ1hJChlJIIIUwI0Rljb2zYuGHH9h0Hx1r02KOPw8SJE5tty7rT9zwLY0JNMxLRNE3XNE1HCIFhGNMPPXTmLILxLKVAhVHLoBBCAEophMCzLOuWKZMnd/7i5784KONo3NgITzz2RLPvB4s45xIAwPM9RwiBdV3/ysaNG0ad8rEP5oew11iy6DW487Y7aE93929t2/Ecx3Ed23EGLnBbt279tOf7B2WiBrCpsREaN26s3bF92229vb07BgwoxZswt2073dbWdnuhUOhxXc/3PT+wrPBt7vu+SPX3P/baksXJ5Sv2nWHl/SAIAujs7DzHdd18EATccV03n8/nM5lMZv369d8FAPzA/ffv/45k0hlobWk9LJ8v7LJt1y0UCoV8oVBwHNcvFArbt23bNqHpIBsKLv7yRaCkhNeXLDk2l8u2+r7PLMuyPC98uQe+H9iW1eu6rut5vu844WTm87mCZVmZzs7OTyulDuoYAAC2bt0GmzZtHpZKpZYXCgXbKlhWLpfL5XP5Qn9//4adO3fM7ut772/397S9L1myFF59dZEeT8S/rBvG8KJrEeiaphOCNSnl2l27mprb2w8uHds/77wbWtvaoLKyqhNjUrCsQsFxHJsxFigpFUIYm2akStd1U6NUI4RQQggRnEvHsVf19PYu3NjYeFDHAACwc/tOWPjKom4p1VoAwFxwrpTilFISi8UmlpWVf3nBggX6okWL9l8n0ukMtLa2Hea6bgfnXDHGOGOMF1WfVkdHx3eUUlBTV32w5wuefPxJuPuue8muXbt+1Nzc1JjL5XK+7wee5/mh+TRgxQgIVVQosf6+vq3btm45UykFP/7J1R+8E/sA4YW559JCoWDZtu20t7U35rK5fs/zmWVZbc3NzUdmMpn3VOder/QnHn0CLrvoUowQ+gTjvKTobygGOgYIOY7rru3t64XuzoMfz//JT30Sph8yVbS2tD5pGBHXMIwoxpiE/QVQSqmiAk4oBQpjTAzTdBzXW7WpsRGu+81v33ObF118CVx08SWo+GefjKOvrw88z21ECNkYY1JSWjIsX8hnOGcexrg6Go1+9plnnqOLFu19QMZeBzvMnDUTJkyaMDYSMc+yClZOCsl0XTOKW6MmpcwIwVsL+cI+Geytt90KoCBaW1uXPO3003v+9a/71JcveW8TSakGyWRJKhaLOYQQigBJhBCSUgoEmAgpuFJSYoyJlJIGQbA9k8lkTdN8z/199pnnoKSkFKcz6YaW1pZupaR39z8/+Dz09fYC57y5tLS0U9f1Sk3TEp7n5jnjQTQaiUQikY8fddQRd0Sjsb0OyNirlf7ra6+DhuENUF5e/olIJDLOMAzd8zxHCCmFEDx0M+ZthXw+lctlP/hIAaAkWQKGaYoRI4af1NLcNOWSiy9+z3UsWrwIZsw8JBUE/mtcCC6VkiQ0k1NMMKaUUIwJdV3X6uvre6int/fWOXPmOEceeeR7aufvf70FPv6JM6C8vOzoYfXDZvf0dLH38+EMhmwmC6n+VFoK2aKUQlJKkUgkqwklOsIYaZpWH4lETq+trYHf/v53+6RNAABYv24DrFyxqrKQLyzmjKsgYKy3t681ny/kbNtxLMvy+vv7br/iisvJPffug8+7iM6OTti8afPhPT099+/ctWtSOv3eefht24aO9o5PFgqFjGM7DuehndzzPD8I/q1Q6l+xYvnP/n7zX+MPPvjenkDXXXsdKKVg27btx3Z2dj24bt36cdv3oePnT67+CQAA6uvr+5Prusz3A+b7gV8oFNqCIPBd1w16enpeenPZssq1exkxs1crfeSokVBVXTUTYTRJASiEAFFKTE2jOoKQWJcz3vyHP9wovvTF974i94S169bBkiWvr0EIOcl44vc7tm+v27btvdnmc7kcSCV3UEItBQp5nucKIQRjLBCcMwCQETNSMnLkqDOnT5ueGDXyvXHNXPqNS2H71u2Tqyorr1dKbp8+fdr2l15+aZ/NwW9++xtQSinGeJtSIAnBGAB4b2/vi57np5RSPJlMzq6tq9trEoV3Ffq9/7wPEok4Mg3zRFAQCwLfzeezGaUk0ijVCSWUEKK44F37bKRFnHHG6fDpz5wfZDPZuRij6cPq66/q6e6Nr1i+Yq/ryGSykMlku4SUrSH9CADjnCEUBq5jjAkmmFBKuwImcgHne113065d0Lyrubq0rPQahGBILpd7oqurS31jHwRjvh0Y4y4AxYUQUkqJKKUjEEImwYQihOKxWOyUIw47DD/6yCPvXte7/WDmrBmwbs26IYahH6+UkkHAfBYwnxCiSaVkeJGjoBtGf8HaN5e4/8TaNWuhpbl5FRdifTwe/9LoMaO/tmDBK/Tp0Kz7rliy+HW4/ZZ/ZD3PbZQyvLbrmq4XAxYpDoWPpJTbTpgzx/nnP+/eq3pfWfAqLHltqVHfUH95LB47K2Ds9WVvvrFpxYrl+3wOujq7wHPdPiGEhxFGAICTyeQMjdJoeEUhRNO0o+++957qcePHffAGrUIB2traTvZcN+O6rmcVrEI+n88X8vl8eC4GPJfL9W3ZsuXE1v1gZDnpxJOLrs5t33ccx7csq6upqenjSin4wuc/v1d1KKWgq7PrO47jeJZlWYwxzoJQx2Dbtm1ZltPd3XXZ3mrhfv6zX4BSClqaW863LKvPsm2rpbXli/tLi7dzx07Y1LhpVqFQ6OQ8vFO5rudxxsWAnqFQKPTt3LX95FS6/13re8eVfsYpn4BYPA4a1WYDwglKKTUjZhQhjDRd1wmhVEopFYBkjLHis32fYsErL0N3dw84jrNMSpWllFaXlZVduXr16mG/uOaXe1VHLpsDz/N2KKU8TdeNgdDG4j8jKaVr2Xbr3l4UL774Yli7Zt3IkpKSH2iaViE478pls8v3l7nTNE2IRqOcEKKUUgoUAGfM4+GdBJQCRQgpicUSh5WXVcARR73z6+Mdhf7DK38IL7/0SgQQTOeccyFAsoAFjmNlAQAwDnlacBj7DQjtH37h5qZm6O3t3RkE/k6llDAM4/Da2tqv/P2vN5Fnn3n3bd7zPdA0rRch5A50M7SohWe6VNICpbr25nh6/tnn4aG5c2ltbc2lmq5NgzCOfeeOnTs7mpr3j80BEwyYYABQIMNXsujr711v23aP7/melEIQQqmhGzOenzfP/M2vfv3O9b3TPw4dVgd1Q+uqTTMykVJCEJLID/xsJp3aFAS+z5hgnAuGAGGCSfG42fdY9sYb8ODch9IsYJvDjQUgHo9/8Wvf/OasI/biTZ3JZCGdTqeEELkw8olzAIUYZ0xKqRDgbD5f6LcK1rvWddQxR8G55597RCKZ+KJuGKZSSvm+v+FT53zKevihh/bL+AM/AN/ziRAShBACEFK+56UhdFyRSirJOQ8wxmNHjhhRNWzYsHes7x01chUV5WBZ9ghd1+oppRQhBKZpmuXlFbUACBWfbhQhMCoqK+LFXDj7HJf/4HJQSrGuru4dxcAGSSkdVl5W9o3FixdvePWVV50TTjxhj+UNwwDDMPKci36l2BBN0yghhISZmwjlnGeF5AXXe+eb+3PPPg+PPPyoec6nPvkVSmktRgiYlMz13EallNpfOx3GGDDCSSmVruuEYIxVRWVVTTwRr8QYm5xzH2OENU0bFo/HR0QikXeMqX4XoVcAC9h4pZQpJXAplWQBJyUlZRMQRmiAbREAdFBQVlZaul8GDQAACoAFQYvgwtN0zaSU4mg0evrUqVMPr6qufvWdim7atAkwxu6hhx7aE4/HZxuGThEgJDEmCCEcBEFmzZo1vqEb79iFo485Gnp7e2ebpnmKUooHQSCVUi7nvC2bfW9Gj/eCYcOGQld3dyUh2CSEYIQQLi8vPwwAIcvKd2czmWxJaVl1JBKJa5o2qrKy8h09J/e4vX/rm98EhBDSdG0SQohKKaTn2VbAAk+BKlJ1CcE5Z47j+Iyxmv02agBIZ9Lg+V63kNITXPBivtSKkpKSCx975BF9XhjoPygqKiugYfjwQNNohnMWAABIJaVSShYdLHpeeWVB8E6hSvNfeBGeePRRvbys7Iu6rteG+WCUklK6nPNMOr3/hA4IAQtYLedcSamU4IIzxgOllDTNSGll1ZBhum6YSipCKX1X7dIehR6LxQY0Qe1KAQdQoOtapKQkWUEppYAAcS647/kuIUQzDGPUZZdeQu7+5/7hSQ98HyghHqUEoSIjIKUURyKRk4844ogJkydP3mPZTDoL5573WcE5d4r8sIpzznjo+8o8z+uc+8BD8r4H9pxZefKUKXDkUUdP1g39ZKUUBwAghGgA4Bby+YK1H3QUAAC33XobXHXF1QQTPNKyrHw2m+7zA98jBBOEACGMqaZRAyHAXAiLc7793erco9B//4c/wK6duyCXzT4UBP7aIAi4lMVMZgCAivd2QgjVdd00TXPCV75yWWzK1Kn7ZfCBH4AQgoMCSSmhIlRNcUJJXWlZ6an19fXwne9+a9CyP7nqKtiyaa1iAcsjhLHv+x5CmGCMMMIIopFoFgDg4bmDa7OuvuJqqBtaB4lk/GOU0joABMUzHAGAjxDyEdo/9D2zZx0Kn/7MuSWGrk82DMMghFJN0/Tixyt5yJPnAwAJgmBhc1PL02vWrH3HOt+xp88/Nw/GTxjf5jrufQQTCQqBFFIMDJjzIChYhUyhUGjM5/MOYzweBGy/DF5ICapI8CellEJI4fuBzxjnhJDjX1mwoOS8T50/aNk168NJiEQieVBKhmOQA2ZW6XquI/iedQxnf+qT8NriJeWRaOxUhDGB8AJIEMIYIUSVUnR/KWZqamuhrLxiZCQanRSNRmMRMxIDQCClkhhjrOu6QSnVAMBlLJh72GGzcjNnvnN08DsK/dvf/RZs37odctnc05zzRkAKKyjyNkkhQAnwXDvT29u7JJ/P56qHDDls3Lj9w5wcj8dBo9QMJxlB0Q6ODV2n8XhidsOIEdMnT5myx/KcCzAjEZ9qlBJC6IAHL0IIPN9nhJA9lh0/YTzU1tUeEomYMzRKsRxQgIfOswalmknw/lnptXV1oBv6TCllIrw5IwyggLHAHxA8Roj6vr+qvaP9lY2b3t3N6117unzFCpgwaUKH7wePACCJMcIIAQjOue8HbiJZUj169OiLR44c+emKiopPv7lsmbl48QcLuxkMsVgMhJRlXHDMWOAjhJCuh27NmqZVxmOx48vLy+G73/3OoOUpJZDNZiyllNSK5QghGAAEZ8zZU7u//MUvobS0BBLx+HEIoWS4w/FgYMPBGEfiiXiitLxsn495yWuvw/wXXjINw5yDMdYRQogWffp83/c4ZwwAkFSKu6772KEzD+2/9eab37XedxX657/wOWhuaoF0Ov2klLIZALAQUoSaIcHjsXgppVQnhBJN044ZP37c1Anj9oHS/22IxqIQjUbHaroeD9maqRZ6vIS50HVdP2LevHnxM888a/AKlALHtj0ppShuy2jglCpJlmQ83xu02AknzIGX57+UjEQjxxBCiFKgNE03lAJVvEGbGOMhZWX7Puxp/PhxMGbs6MmRiHmspmlh2hGllAq1gNx1XVtKqZRSrb7vv9TW3g633Hrbu9aLv/3tb6Fvf/tb7/ijpl3N8MqCRS1KyqUIIUIp0RDBWAgRyDAGSCglhaZptcmSkjOra4agf9515z4b/N/++nf4xmXfoFTTJiAATCnRUHECMA6vlIZhjK+vrx86dNgeMigiBJgQwAhjxoIg/HCVQAipZEmS7UmxMqSmBmpqa4ZhjEdLKXmRjQLCBCBSKKWooRujopHIPhX4lVdcAZVVlaDp2ikAUCmECMLkQlKAUgqHjj+aEEI6jvv8/Pkv72xpbnnHOs8+80w4+8wzEf3c579wVDwWX3buueeLOXOOH/THJ548B3zf5/19/U9pun4+ISSuFChAUPwPACGEpVKBlPLExsbG+5LJ5Ls+HfYWMw+dCVOnTS3TKJ2k6ZqGEYYgCDyllCI4tEJgTKqjsdiYqqrqPXpZYBweTixgvu/7ghCqYYIFSKn2FMpZU1sL/f39owGgVAjJUZFPnAXMNwzDBASaaZrTr/jRFdrtt9/OLr300n0y5ksvvQw2rN8wsqy87GOFfCGjaRqNxWMlhITUKLF4PIkAkBAi67rOkxdeeIFIJBJ7rO/FF+aDpmsaAEzHdbV1F5aUJE86/vjj4M5/7PmNvW3bdujp7X0jCIJVnHOJEcLRaKwUk5ChRSmlHNvOIISGV1RUfuFfcx8ki19bsk8moK62FiorKxsIIfUEExwS+BJKKdWkUpIxzqQU1ND1iYl4bNA6hBCgaVpaKRUQSjRUNA8pKaXnedLfQ1ROMpkAXdfGYYwjGId5AJRSkgvOVOhPgE3DnP6pcz5VNWPmvuHUefWVhXDD9X/CNTU1X6iqqjq6tKysPJFMllGqaUUvXgahawDyfX9lZ2fHmu3b9xxGtuDll+DU005BY8eOOXP48IZTMaWkKRqN/nrr1q1HXfLli+Efd94xaME/Xn8jzJhxSNrz3OcxRkAp1QM/SHuum5FCSsaYH4lESuOxeKVpGBdecP55R0x9h9v03mL8mHEwfMRwMA1jNuMsMkD6E15aQ/1/+J4ARCkdd9IpHyO/HoTD1fd90HXdY4x5gguh6ZqBMSaglPB8Lwj8YLcy3/j6tyCM0aPDizd9jDHClFItWZIsJ5RonPNAgRpaUVk5ceTIkftE6FOnToUfXPGD2YZpfBFjrBWTTDElpeSc8yDwfc4Z45z7nuc+e9hhh+d+ctXPBq3rzWXL4aSTP4ba29pOjUajVxJCNuJcNjuPEBKrq6u7tbWt9cSvfPmraMXK3d2R7rn3Lujv6wff818FgF4ppezp6dppWYU046GPkZJKYoKRGTFHlJWVfb+lubls86YPZmP+x113wisvLygtKSk5k1JqcM4DIQTnQnAppQRAiFJKDUM3TNMccfWPfhQ9ZhB7MsEYQtvQwO8NQzd0AxGipFRcDvLOPvOsT8ATTzxpGoYxnFKq4fBdpjAmBIUJgEQQMI9zbiCA6RXlFR9Y4JsaG6Gjo62itLT0CilUpWVZGSklUEINBQpsq9AspXAIIZoQoiWXy8/ftWsXzJu/e1Lgl+a/DGvXrKXt7e3nJ5LJvwGA1dXVuRTPfeDBrULIBZpGJ5eWlPytvb39gnQmbWzZtmW3SjZv3gxr167b5DjOq57nZXzf7zVMMzFAvUVo+AbGGINhGKfV1tZ+fsLECXDH7e9+oxyAUgp2bN8xvq+v7wvt7e3nV9dUnzhm3NhzItHIYbqua6G7tRScMeZ5nsMC3wcECGOMCCF1kUg0GTF3v1RRTQMpJSaUUKVggBmaY4TMRCIRi8V2PxYS8TiUlZbqhOByjDEgKO4toV1bKqVk+PSjpLSs9LTGxo3Ttm3fNrGpqenErq6uC5uamo7/+S9+hv/+97/t1dhv+vNNMGnyZFRVXf0FhNWx/am+dsd2CqBAccF5kdiso6+37xUuuOScv/rss8/t2rFj93Dqxo2NAKDMM8/6xJfLysr+YhjG8CAInj7iiCP76OU/uJxns9kHKSVna5o+pqys7KZZM2cd0dvX99chdXU7//7Xm9R5554HAADHHX8cZLM5P51OPcIZG1NbO/SQRCJZjUNdeEizzQVHGCGlgBJCLtqwYcObJ510cnLb9m1Wa0vr+pNOOsl5NxOkpmknGoZxfSwWwxUVFUwpJRCgqAIlgyDwKKU6JZRywblQSijOEWNsu+d5i3Rd96m2u/GQEAKe59JYPEaCIPCE4FgphRFCjLFA4kHUqOl0BgqFgj9h4oQFuq6PIoTWKCW5KqrfBiJmDEPXNY0eY9QbD0mlKCWkFABiSql7Xpj3wpJzzz33HT/yVxa8Eh81etShUkpz6vSpbQBwPuNcGrphJktKyg0ztNsLEDIai43v6Oh8Ttf1WqnUY1++5GJeWvZ/OoJ77r4XfvGza5CmaeNmzDjkm5Fo7POE4KTv+425XO45PwhCftW5D8zV+/v7b3ZdlxVDeoVlWeu6ursuW71mdXXDhGHo1jtuAQCAha8uhFdefqWiq7Nznm3bHgvDewPP8/1sNpPt7e3pKRQKBcdxXMdx3XQqvbKQz7c5jtOdyWQebWtru2DNmjXVAIDuufvuQSehpbnla1bBcnzfD4rxcmKAIy6byaYcJwyN9lzPKxQKdiqVnr9169aZ/3rgfn1P6lClFDQ3N5/luV4hCALu+37Q39/f39LSvHH9unWzGjcOTuCzfft2mD9/vt7c3HxUJpN5xrEdx/M833Ecx3Vdz3Ec1/cDVuwTd2zHtSzbLhQKbnt7+zVKKRj3Nr3FvffeB8cffyJau3ZddVtb+wWZTOZxx3H6ent7t3R0dLyUyWTSQRCwfD6fKxQKBcYYF0KogDHueR7r6Oi4+cUX5n160auvJhe++goAAFzzy9Bvb9Xq1dVd3d3ftCxrQxAEosj05XZ1df0YAND9c+eGD5VUKgWZTHZGTU3NI4ZhjC4GowJjzLUsa1FfX+9DCJH1bW2tu+648x/5h+Y+KNta275dWVX5e0qpJoQQCCEU+J5XyOdTydKyykgkEh+YbABQCGEccr4Edr6Qf3T1qlXfMnTDOunkk3cTTlNT01eHDBlyk67pWsgZgBAuLsWiz7qvpJQIYyqE3NXR0fG5svKydbU1e7buKqmgu6f7jNLS0geLjgdcCCG6u7vWNDY2XmQYxq4zzvj4Hss3NTWBY9tjhg4b9pCmaZOVAk4p0Ytmp6LDGCjGOAsC30cAuL+//7sjRo688+072+ZNmyEIgtr6hobbotHISZTSKMD/HTlKKQEA4LquzRgLysvLi7spQkpJsG17+Usvvfi52bMPbzr99DPQtb+8xhw3blxdIpk4qqKi8qJoNHo0pdRACIGUEhzHWdnW1nZ+PB5vHj58eOhEsWb1Grj22l+te/iRh26jlFwrJaZSSsE5U4Lz6srK6u9Fo5Hq2tqardOmTVu5a9eup9Kp1NJINLIzEomMJoTg0LPGjORy+cCx7ZxpRmIYIyyEZFIKCYCAc84xwZqmaWM0TdNDv6/d4ft+G2e8R9O0+pApQkqkMOKcM4wxZkEQIIwxxQQopclEMjFt5coVW1asXOHPnjV7cKGH6ZgGcq1yxlhACNFqhtSMiEVj5VSje6SPamzcDE1NzfFJkyZ+glJaxzn3dd0YmFQRGm7C5xshWFMAQcDYFstxNuby+d3qi0ajQCkt0TVtGkLYBABZ/LSBMeZ7nmdTSjXOGBvwW8AIYwVSWpZlcc47a2rqPCHESYsWLfyYYRiTMMZjhBBVCCGDMS4wxgIhRBhjecuybpo0aVLzn274MwAUPWdO/tjJsHXLFpnq77+LEDrL0I2Pe75bwBiTaDQ2woyYCYyxBgC10Wh0Tjwev7CsrKwNYzIEACRCiECon0GJZLKqUCjkWBD4hFLKGGNhnCgA5yxAAkvOOCCE6GDkVuvWrIPunu5XKKVfLCsr+0YsFvsEIcQUnDPPdR1d143Q1T6MKQcFNeVlZX+aPXv29O7unr8TipvvuvOf6ktf+tJb6kUIgeO4sUQigYQQAQAoISVHADEueH3d0KG7kcTd8Mcb4fs/uBzWr98watq0qVfFYrHPYoIjiCEflFIYESxBqXCBcKaU1KVUed/37+rt7b3j8See2DFmzJjdxihDcyHlgksVKJdSShWAImEwhiKYaLqum+GTEhRGGGGCiRBCKKm4ruvTZ8yY8SildDSltLpoLeQYIeQHgSeF4J7rSUKJ7rru3C1btz7e0dkJ3//h5f8ndACA8RMmQE9XdyqTTv2msrJqlGmaE+mAxwLGWjFzGRQT1VUgQHEphQAg/7f1csE550LXddPzPY8KShEqMusSTAkhlHMuMMbRsrIyo3gPegsOmXkIAECwc+eOxVu3bF4/ctTor5SUlPwQIVQKCCGMCdY0Pco4Z74feAAAhmEky0rLLteoNuHZZ577kmEYu1E0K6UgkYiXE0JMIYQzMKmMMSYVJAdb4VOnToGnn3wqdtQxR/8mmUx+BiGkwohXhFRREYsQQkIoqaRCju3sKtjWL9euXvNoaVlZ8IufDf525owB5yxKCImoIjAOj79CIdeOEdYVqNKiEopwwTmRlGKMESaEmIZZTzU6BmMMxeLCDwJH07TQzEpBE0KA67qLu7q6fjd+3Dh76ND/U0+/ZX9dsGgBjB03br1lWdcSQjK6rpuaRjVVtGILIVi4T4JUUrLA971Q901JkXFZI4RQUAq5jmMxxvzQ+TDUGSullBSh7hghjAjZs71n9Ogx4Hpe9oV5z/05lUpdzgLWSQjVAIWnJ6WEGoZu6qGSBWOMMaU0aRiG0DRtt/oQQhCJRBKEEC0ej5cihHH47JIqYprGYD77hmFALB5HlGrlqIgw5jXUBobv9MBzXdcLGGtPZ7M/+uSnzp4rEQTHHXfcHseGCQaMMQUAIqUUvu97oc4BQHDeqBuGFY1GE7qu6yxgAWechV7bCFEaRtwqpbgMzcNQLOcPzANCiHLOt6RSqZ9Mnjy5+bhjjnlr+//5Pxde8Dl47tln4dab//Z8KpX6ked5rQCAFCjFOedSKonCBysYphExDN1EgIiSUhaJcy2llCKU4v6+vhWp/v5tAIBU0UW/qE3jmOB4LB6dvHTZUvrc83sm1z355I9BQ8Nw/oufXPVQLpe9VilZwBiRoscOwZgQjDGWUggWHobNzz7/jL16zaq31DOyIdSU+b5fUpQdUEooKFChpg0ig9nTl7z+BvzrX3P9wPe7hZBSgVJFFi1S1IHj3t7e1taWlsf7U/3fWbB44TO//d0f1SfPOnuPY+pPpaGzq6uitLTsDF3XE5RqmqZpWrjSpUSYDI1Gow2apmmGYUQM04xQjWoQXhSRrutm+BFjLPj/Qdf1aNH2RH3f357JZH44duzY5XMffAB27g0H0NwHHoDzzjsXNzU1faKQLzQWw4ks3wuCIGAsDKtxva7OjsYd27fNT6VSvel0OpXL5XO2ZdupVKpzxYrl92/YsP5Fz/dYyDMXZloo0nK7lmW1d3Z2/mr5ihV17+Z1svDVRXD3P+/RW1paLnccxy4m0/Ed13HDp6HjWpbldXZ2XquUgpmHznxL+XvuvgcAAKfT6Vscxwl8P2CO7TiFgmVZBcvt7Oz8nVIKbvrbX99S7pSPnQpKKejp6f2t7/sypFoJmOf7QeAHzPO8oK+vb8srCxZMX7funQkGX3j+BQAAtHXL1tmpVOrpkAOHi4GQ6YAx7rqul8/nswNpSWzHdnO5bD6byWSsglVwXdcbSD4wMAesWK74gmS5fH5tc0vLyQCAFuyBvHjQ/fWzF14Il371Ujly5Mjnuru7vmzb9iIhhAKkEEKAAQBhjIlhmPGm5qZne3q6V+m6HjFNM0o1qum6HqupqTkCAMVBgQxdpREO7wXhLVXX9ZqKioqrxowefdeOHTuOOudT5+CHHh48WGDOCcfDITOmB93dXfe6rjtfCKGkVFJJUAOrDiEkgsDfCQCwetXqt5SnhMB9996ng4JqKaRgnAVFLR4GADAMc8hNf7uJVlVUvaXc/JfCpABB4DcLIYKiKVtxxgIe5m6VGON1CKEm19mjHwa8NP8l6OzsoE27ms+uqam5MxqNnh46VSolhOQASqFifwzDiBW5cGQ+m20u5HI7uOBcqmLiOAUKAIAxFuCiCzcqOug5jj2/o6PjkuENDS/fcdc/1Eknn7T3QgcAOOXUU+Hkk05QY8aOXdbe3vZV3/fvk1I6AAiHPmKYxOLxYePHT7wEY1IaOusVb32aZsaisRJKiBn4gRNq6iQDiRTGBCslZZGzFcdisY/V1NTc8+c///kC0zS1pXvITXbIIYfAqFGjU5l05re+7+8ioReoBgAghJJcyLzruTs6Ondntpo2fTpMmzYtAggqAYXx9EV9KiCMMMaobvyY8Wb5IN4vvb294DjudiGEFT5QMNZ13aSU6ozzplQqff2UqVPze4q0eW3xErBtxzj19NO+UlVd+Xfd0CcghCRAMa4/9H4BUADFIwMhhEAIIX3f702lUhsYY4FjOxYmRFOgSFFuiDEehAGMIp8vFP7e0trylYkTJqxGCMFXL/nKHj/Cd/SceXnBqxBGtURbVq1c+cO+3t5vOY69jjPm+b7f7XneNtM0RTQaUb7vdwsuAiklAhU+38orKmoGbrgKJIjwi1WEEBr+nVIEE9B1Y1RZWfkfZ8+adXE61actWza44FeuWAWfOuvclbZl3y6VZEII4Xm+GwR+IKXotQpWa1/v7iRHUinw/SCBES4duIcN2NY5Yz7GuHzosLp4wyA5Vbu7u8EqFFqklH1SCqmklAgAhBTMdZw7xo0bu2r5HuLl31y2HDjn0VmzZn0nkUheizGuUEpxhBAuXgJ9KaRUUikuxEAwYjh5ACoSjU4YMWr0J0uSJQnP9zrz+fwK13Nfd113DWOsXQjuuq67OpXq/+bqlat+GjGjXXsTZbNXREMTJ06Auff/yznvrDP+9c8HHl5pmuZE3/fbHMfuz2QyzDAMXFqaq4onEhOjkcgRkUjkWClFeTweLyOE6AAD27CgxcsQ4owxpZTSNF1HCKmIadYQjH8zc+Ys+Yff//Gfzzz9jDjzrDPf0o/TzzgNGhsbZW9f7z2U0uOoph2naZQAAPV9f2dra1u/ae4epVJaUgJBNCgHBCXFS5wmhBCUUp2F+ddKDcOoJIR0v71sZ3sneJ7bNWLkiK2apo3mnHsYIRowtrSrq+v+DRs2qKmDuH0vW/omFPKF6JRpU65MJOLfxRhHECAQUoIoeuB4YcwAQRghDVMdIUAIKakUIKXAxQhvsB17qe/5q/O5/I6t27b2EYp9IaVRO6S2LBaNjfJ9f9ukSZN23n33PeqMj5+xN+Lct1i1ejVc88tf0rVr1w5vbmq6JJvNLixYVs51vcBxHDdbRC6Xy/X39/dl0pm07/m+4EIGoY5dWZbVvmvXrk8opeAP1/9h0HZYwGDnjp0fz+Vy3bZtu77v8+7u7p8opeBrg7BAuK4LHR0dZ3ueb4cXH8/zXM8LgoC5rutbtpVpa287PT+I9uySSy4BpRR0dnZeWbyA2rlcrqelpeVTSimYddihu5WZ/+J8uPy738Ptbe3fdhwnzxiTAQsvawMx/Z7n+el0OmVblh34QTHSWyjHcVKpVP+DzU3NZy5ctKhi5oxp6EdX/PDAC/O94oYb/wgAgJa9uay6tbX1slw2ty6fz1uFQsEq3jSdTDqT6uvt6xkg8bNt2/E9P3Bdl2UymTfXrF0zrqW1FU45fvf37pLFS+DFeS/EU/2phwqFgmsVrN4dO3ackE4NHl9eJOD7nud5jDHGM+l0v23ZdtGgI4LA5/2p/u/t6RWRzmRg+/YdJ9q23e+6Luvr67//xRdejO8pdWg2m4Pt27cfnS/kmzzPC3zfD1zX9Yq53VzP9XzXcdxUKtWXzxfyxVwx3LKsZe3t7ecueGVBbPv2feZtthv2i7P2D77/QwAA1dHe3jt+3Kjb+1N9n2eMPUsIQaEjK9UM04gSGpIaCCEkIYQoUAojrDRKppaXllzQUF8PDWN2D8065rhj4Lg5c6yCVbgPALkBC3Z2dXU1bh0kT+m1v7oOhtWPxhijsSrUKApN100cOnbyMLAfEYLJhCG1tfiGG2/crY7mXU2QyWQ2BwFrZoxlLKtwzzHHHmMdc8zRu/324QcfhLkP3B+PRqOXmYY5PHx/h5oVpZT0A99zPdcOWKh08cMv0S4UCre1tbV9dujQoY8tfXOZPXbs2P0m9L0mD3w/ODe0wytN0zZ0tLd9c8iQ2pZkSfKbGGMjnPAgsAoinUgkyotPD8Q5D3zfyxcKhYqNGzYee8c/7noNEQ3uuP32t9S9ft068H1/STJZsoIFbNuXL/5y/5VXXbVbHw6ZPg1u/ttf4tlsrkLXdTsSiURD/T0hRXoxz/eDgHMx4rFHH0kQTHJvr2PjhkZYvXJ1349+fMUKQkjb9u3b32hvb9+trXvvuQfO/8xnYM3qNZ/o6elpIBh3xhOJUoQw0jSqKwWgaboROv4IEYmYCSFlvlAo/HH9unU319fXW/sr3Pk/sf9bKGL1qtWQSafjU6ZO/WkymfyOlBKnUr0d0VgiHolE4oYeOgpwznlPT8cOTTchGo3ldu7c+dlEItE6/m10WRVlZdCfTsOOHTs+xznP1Aypeb5skCfXhvUbQAgxmWr0Ro3SiuEjRkwtxtpjxhgLgsDjXAgA1d3X23cOIWTLmLG7G0kK+QK0tbWdqWmaNnLkyMcHc9ToaO+AVDo9qaGhfi7nvDYIAj8ajcYpoZpUUmCMB5L7Cd/zGabEtm37V5s3b/pHSUlpMOvQ3e8H+wP7daX/J2YeOhN27dxptbW1/n7EiJEaY/703t6enpEjE6cAAOKCc4wJxhjj6iF1IwkhFABwTU3NZ4YOHXr9H/7we/jRj678d32pTAZemDcPCCFP5nJ5tWXzlkHbnTJ1CnR2ds5OliSPdGwnHQSBhzGOhi9GUEV9OtYoHZZIJqZWV1cPWtEzTz0DAGoBIAQr3tz9ifbow4/C7677Hbn6J1d/0dCNiYZhSMMwWHFbV0EQ+Lqum0GYrrmtP9X/MsZk8fZdO58yDfOACRzgAK70AezauRO6ujrNrVs3l8yZc9KPqocM+QbBZEDvgQEUUBoaeaSUYNvOyu07tn3KMIz26dOmv6e2nnzsCVj2xjLyox9f+fdYLHapUirU/YcOCcA55wgBUEop5xwcx7m2qqrquvezxba2tEI+l582tH7oI0qpaowxUEo1SqkWUqoKQQmlChRxHOeFv/71pq9cd91vcwdiO3879k/U3Ttg1OjRQKnuTZgwRZSWlR9W9DKlhGDi+54LEHrHhLSzIkj198muzo4a+R5I/QYwdvxY+PyXPl9OCDmEMeZzztnA6sYYEV3XDcMwTIwxxRgjSun0ec8/F120cOF7aud3v/4NNAxvQMmS5Nmc8TIpJRvwyw9D/xBEo9EYoaFSStf1qlNPOYUu+YCptt4vDrjQAQDy+TysWrU6F/j+6wPeLAAAlNIB0hqFEEKu6+Rtu8CHDas/taevL/7Se8zX2t/fB61trUZfX2+uqP0qkn2LYkjTgHMjgiKb9aiS0tK4YRrvqZ3TP34GrF65aihCMAcQYF03IsWNiwQs8ENH0YGYIBC2bT92/JwTUjv2IYfse8GB31uKaGlphXw+P3ZIdfW9jLGhyZKSMkqpFgSBR8gA6YAQUkpFCPG6uro+W1FZsbi6au8SCNzy99vga9+4FFpb276dy2XOcWw7O27c+KPMSKQEIHxCUUopxpgEAfMAFBJCFPpT/d8Z3jB87lU//jH8/rd7x/mulIL2tvaLKysr/saFUBiT8JgilAYs8DHG2HVdt1Ao7PL94MlcLn87xrh/9uz3f47/+Npr/1N+6rqf/3yvy76nlX7NNT+H22+7FS99/fWGVStXme/GePBOeO7ZZ2Dq1Ck7OjraH5JSCN/3vCDwfSE4R0WqB13TjWg0GtN1vSqZTJ5SXVWNfr6X2ZOOO+4YWLdmfVVJSfLTI0aMnCWk2Om67jZN04z/CORHobWMi+J7PZGIJy5cvHhx/JNnnbVX7Tz/7PPw8IMPx8yI+QlKtWgkEonQAVcuBKCkUlJIyYKgt6ur89HlK5bfx7j/gQS+ePESOPnY4+NHzphZ95uf/Uy99uqr76n8exK6UgBfvfQyWVlZOamyqvK8zo52uuS193cufeOb34Suri6lG8bqeCKhm6YZpZRSAFAII9AN3dQN3aRhAAUhhBwx/6X55e9EHfafaBjRAKXlJYcSQiYYhhEbP27C6f2pvlwq1d8RBEEhm80ullJ6SimF/r1ilFBKja2qqhyxt/nRJ0+ZDJOnTJ4QiUQOl0oKJUFJOZDPXXAuOMsXctlUKpWqqqo+asqUKZV7u1sNhsWLl4DgPFI/bNgFDQ0NQzs6OmHze8w3856E/stfXgtbt2wBwcXqiBk5e/ohh3wlnckaS157/b1U82+0NLdAJp3ZLoRoRwhhpZQyTTMuhJBFezUv3uJZJBKZOLSubtzYMe9Ozf3EY0/AFz77BWwa5kkYkyQCIhOJ5LiGhhFH5bK5Htuy2jOZzL983+8TQkg8EKETmjarSkvLThg3bhzccMMN79pWw/AGSCQSMyilVZRSgnDoOxAEgW/btiWEEIZuGuUVFWMSiUQ0nUo1t7W1vWu9g2Hd2vUgpYiNGTv6+/FE7OjA9zb19HRDf+97S5/yni9yf77xzzBh0sRextjL8Xj8Z7Nnz/4RIlC6a9d7T0C7bds22LJla6pQKGxo2rVz/dYtm+cLwb0gCALBhQgpvwSXUglKtfJEIjl96NBh71rv+Anj4drfXFtnmMac0LkzpBUyTTM2ZMiQ0YZp5jKZzFIlVTtCCEshBS4SFUSj0ZJYLHZhY+OmoR//+MffsZ3vfuvbgBDCmq5NkVJhzgWTQkrf913fc11d0/REIlGSSCZKY/F4kjG25fzzzs299tre51sZQGtLG7AgqJwwYcLPS0tLv8U5f+aQGTOsQ9/H+/49C/3WO26D7du2Qy6Xe5oQ0lxSkvzxuLHj/mRZ1iilFFz+/e/tdV333H03fPkrlwS6rvcOq28YV1lZ2ZDP5Ts81+tlnOUJpTomoXcIpcQwDGPGqDGjyU/34GUKAHDumZ+CiZMmQrKk5CghxFClpACkkBBSIEBgmGacMbb+d9f9djsArKKU6pquGQAAvu+7SilOCJ1SVlZ62vjx42Hm9D3rBo457ni4//65EU3TRkMY9SwVSOV7npvNZlIQummAlEqSMIKkOZ3Jymv2ksgYAOCpp54DAECO60xrGDH874ZhfE0I8XpXZ+fL75eA+H092e6+658wcdLErnwuf4uSyjcM47y6uro7W9taTz3hhBP19RvW71U9C4ohOaCgyzTNeFX1kMmAUNRx7G5KqRi40CklVTHQof63v7kuesghexbEtb/9Faxbs666rKz0sogZKWWMBUJwTkhI5i+E8BzHWfzgww/xfL7wiuu6/UHAfMYZo4RqGBNMCDYjpnn+ypUry++65549ttUwvB6GD68v03W9ASEAKYVUKlT26Iaph+7R/6atkn7gv6d9eOeunRCPm9G2trYLa2tr7jNN4xNKyZxlWbdPnDQpP23atPcl9Pelhr3u97+Fz3z2AnBd9+loLPZxAHWabuiHRaPRe4468qgH0+n0Hdf99rrNY8eMleeff/671scYc4UQnBCCS0vLapLJZAUAYFH0JpEh4S0TUpaVVZTHdU0flKnvrFPPgkmTJ0F3V/cndE0/XNN1UwjOg4AFUkohQnbInYV8/o1cNgee661EGG1KJhIzNV3TBnxsAUBSTZtZW1NzeFlZ2R6pKEtKSoBzHhNCmEVaEglKKUwIjUVjJQgQhmKELEIIBsKV3g0LFy2CfC5PpVBTp0yZ8g2M8akIUFmR/uTpNWvWLK6oeP9h0e9bOTP9kOkwceLEfD6fvwFj3AUKAUKoLBaLfaOysvKBiy+6+CdTp02d/PhTj+vrN76zpyjG2Bhw+B9wYXdd1/Z93yuejw5jQQBKUY1SOpixAwDgl7/9JSxf9ma5GTEvGGChKqpbAxawoOh3tmjeC/Padu7YAb++5lfdpmmu0g09MmD6DAOCOZNCmGYkcv7rS5eab765bND2ioKMUEIjhFCia6H1DpRSfhB4CCOkIGRoDoIgQIDIO82DUgrmz58fqx827MjDDz/sutKykvui0ejnpJBa0ZmzOZVK//3QQ2d5Rx111PsW+gcyuCxavBDOOuvsVR3tHTfG4vHrOOdRhJASQtYkEsmrzUjkwvLy8tc4Fws2b968NpvJ9uim4TY2Nqp0OiVWLVstAAAIpUMxxqFtXYpwcfq+HTHNaMA4E1JKHMYZCM44w3vQKR0y4xBobWk9WdO02VIpwTkHShEiGGGpFGi6zguWNe/rX/8Gj0ajkE6nRaFQeMI0jQs459HwNAl91qSUQjf0UydOnHRMRUX5y4MKSSoABUKBkgBF5zaCiVRKRKPRKA0ZsLCUnuP7nGmU/meme/TZCy/E3/j61zVN1+OlpaX1HR0ds2bPnnWapulH+L5vOo5j65oeIIyQrutgWdZfxo8ft/n+uQ98ELF9MKGfddbZsG7tOtXW1vbgyJEjZyWSiYsxJigepxpCgAqFvJ5MJj9HKf1CMpHorK+v71RK9Q5vaPCFEKmPn/Hx22ceMnPTC/PmDQEJyme+F/LRsgAV46F0hAzTNKJCCOX7fn86nS4MFsGyccNGWLtmbVVNbc0XAMAkGKtiuAemmqYXQ7Bf7+ruerM/Faa82LBuPeRyuZVHHX3Uy7phnCukCAAAIYwQJRQ0qpVGo9FL16xZs3z1qtX5t/vTM86AceYCgE8p1YoGNWWaZqyYoFsFAfNZGG8dKIBKAIBdO5tmRWORswGgMhaL1SilahFCda7jItOM1gjBGULIJYQg3w88hBD2PO+h1tbWh3p7e+HzF37u4AkdINzm29rarHQ6db1hGpOi0egxGBNwHCebTvX3lJSU1FBKTULIKCnlSN/3/WgkQhDCSNf0GQ889MCvmODxgAfBQDRpPB5PRqPRuFKhW60QkhcJ7lsvuOAC93vf/+5b+vDk40/ClKlTUE93z+fiifgJoEASQoiUUgolFIRRNoFjO/fPnjU7c+yJcwAA4PgT5oBt2W46nX7QMMzTTMNMIoSQ4ILrhm4IIYSm0RPrhw37RH1DwwPf+sbX4W833/LvdrOZLASM5QEgB6GCR0FIzhBGs4JEge97nus4jLEgX7AyW7ZsnVNTM+R6SunU4qWRKKUEQhggCjaAErqua4Zh6IZhmkEQBEHgL0v19/++tqbGbhg+/IOKbN8YXP51zz0wYeLEnfl8/mrf97dIKUFwrlpbmjf0dHdvYIwxpUByzn3HcTKMcUcqyQxDn1VXW3t7JBI5QnDuB77vaVTTKKWaRjWdscAvXvAoxgj5vr9TKSX/fONf3tL+YUccBls2b5kUi8cupZoWUaCU53luPpfLSCEFxliTUm7s7u6ev2HDBljy6v9lIV65chVsaty0xPXcpYQU481JGOcWBIEvhNQ0Tf/Kpk2bRl39k5++pd2u7i5obW0pcM47wrjycIcHAOV7nieE4IZhRErLyiuqh9TU1dfXf6m6uuoWjPGEovKRs4A5nHNfCsE1TY8KIbnneU6RETOqaVqX53nXTpw0qeXyq36wL8S1b4R+9U9/Cv/617+gvr7+9XQqdYXv+U2apkXqhg4drhtGspjlBdBANAT5dzgYElzE/TCqmbqh3ZnDQIgsIMhm0t2MBQFCyC9SaLyl7aVL3oBVy1eb5RUVX8cYjw4zswASnHOEEPI811ZKBZ7nPTBj5ozuRx5/7C3lP3f+hXDKaafklVJPCSFczjkPjTCBjxDGhmHoydKSo6qrq7+5aOFCffF/JLJ97NHH4KKLLnI9z1sbZpzg3HFdK5/PZzzfdxBCOLztAQAAisfjs6LR6AilFFNKSUo1jVA6kCYMXNe1Pc91RcjWJTzP25VOp69oaGh44/4HHoLH5j66T4ROPngVIZ544gk49WMfg9/84uc7Tj71tA7TNI4rLSsbH48nKgciPtWAYz/jgWEYJuOcDYgfICT3k1IoTQ+praUUIptO9XDGOMKks7Oz62+ZTCZ/xx0h7dl11/4aPvv5C0E39DPj8dgPCCbmgJ+druumbhgGAGAp5fKurq7fpDMZ+9PnvfUJmXfycMEFF4BtW126bhyulKoRQjClQBm6bhajgwmldFxVVdWmqdOmbmVMwGuvLYbGxkb4zne+A9lMFkcikdNt2/aFEJxSSgv5fJZSjRqmEfl3LD0ACCEC13GsaDSaHEgUULwAYikFD0mb9AjnvKNQKFxx/Y3XPVNeVgFnnH76vhLVvrWnH3XMMXD5lVerxx594vFCwfohAOoL7RmABOdCgYKimdFSUgnTNKOmaUYMw4goUKq4UvKMsYAx5jPGWWl5Za0ZiSZ833/1xz//Wdf6Df/HDfOVyy6F7dt2TiotK72KUlpeZHBHkUgkRgilSinQqMZy2dzfp0yZ0vO5z31p0H7fcvPNMGnS5B7bdu5GAL5GNd00zSihhLiuZzuOU8AYlyeSyas2b94y6lvf/Ma/y27csBHa29rWuI6zsjg8ghAi0WgsYdlWjjHmCyGCMOpXCkKpbhhGVAjBQosMC4ocLajInR9VSnbYtv3DG66/6clPf+rz6ojD31vC33fDfrGnv7JgAbS3t+EjDj/y1IrKyl9FIpGpQgqu67oWOgV6jm7opqbp+gBDk+u6tm3bBc/z7MrKylqEMS5av5Dnel1d3d2fragoX1ZT5JV5af5LkMvl4nPmzLk1Fo99WgjJBk6P4saClVLIsuyXN2zY8Bld17NHvUO+sk2Nm0BKWV89pPqRWCw23TRNs+h4IaSUMmCBTyk1HNu++S833fSTWYfO4uedf96/HTSbm5svqq6q+isXIdWKYeimEIIHQeB6rmuVlpYNgeL1PkypRchAeFORP58IIYK+vr75gNDNTzz2+MLZh82Wxx9//F7N+XvBfvGcOfGkkyAWi8s777jjha7uri/l8tkbhRDtAIhomqYDQryledea/r7uLtuy8rlstt91XTuZSJZGo9GEEIITjAkLgjDhHALN0LWKIUOG/LsNBQry+XzAOFsrlbIJJdqAEyLnnHmuZ/ueb2saHdswvP6QI488Yo/9ve2WO2DipIlQWlY2JxqNjgnFEvrECymEAiUJxhQhlPKDYMXvfvc74RdZo//0p5vCXDeaVkEI1TSqaTxMt+AjQCgajZWUlpXVSCUVKfr8U6rpEPpx4KI7tsZYsKNg5X/f3d313VEjR77ywyt+uF8EDnAAPGeeeeYpSKfT9NBDZ02qqqq+KBaLfcb3fHvjxrUPjxkz9nOmGU1IpUQ8Hk/qum56nuf4vu8bhmEOmFYRAHFs5+Wt27d+2dCN1ECE6Jtvvgm5XM6cNm3aD5PJkiupRqKc8UBIKVzHtXVN0zVdiwohXuvo6PiCYRhdo0aN2q2P7a1t4LjuqCE1Qx7SNG1aEAROMYcspTSkTPF9v7dQKFx97bXXzj377LPlmWeGcXbtbW2QTmcmNwxveAgBaggTTLNA0zQ9FosllCqmOSryjIf6eMEKhUIqmUzWSKn6bNua29vbe+eLL764bfjw4eK8887brzLZ7z5yZ555NnzpSxfz/v7U+kWLFl3Z0dHx2Z6ervuVQhti8aQRiUbj8USiJLy4hXwuRX01BwBgAQsy2UyP4zqjGxqGn334EUfAz4reM4cffjgMGTLEa9q168+2bd3DmWAIcNG2NUANjpWu68dWVFRcdMxxR6OXX36rcu2FeS/AUYcdiSsqKr5gGMZ0jAkihFLOeRC+IZRSSgWu6/71yaefeegzF3z23wJ/9uln4bZbb6dDhlRfpOv6WAAlwvh1HmCE0YDOHwBggG1ioGvZbGZ5Npd9sLOz44LFi5dc3dPTu/kHP/jBfhc4wEHwkXvgvnuht6/bOOLIYyeMnzDhPtM0J2KMFcIYF5mNFWNB4Pu+7dhOHhNsYIQhGosmpJRbmpqaztc0re0/I0VbW9ogl8vU19UNvSMaiZ1AKMaMs2DgPDYMIxqwoKmnu+fTiUR8XU1t7b/LdnV2QaFQmDqkZsjDpmmOpZQSKaVgnDPmB76maabt2HN37tz1PcM0cjMOOeTfZXfu3Am2bU8eOXLk04ZhjJBSCsdxC1ahkC6vqKgNrW5KGYZpahrVw3c/V4zx1Vu3brmsu7NrV319vXPo7NnvZQo/MA64N+yFX/gijJ0w2f/L327akM1kvu/7/jqlFBIheHFLlwgh5PmeHYlEohWVFbWxWCxpGMa0ioqK06ZMmQINIxr+XWfD8HqYNHFyW19f3zUBD1oYDxjGmOiGbspQresrBUOjsegXFy5apC1aFCpnlr2xDJa89rpWUVF+CSFkhOs6ecZYMECsxDjjvu+v6U/1/27EiOFvEfhFX7oYRo0aBaYZPRYAqjEmiGqaplGKNU3DGqU6LRLKAIRu3QELuOf5S3t6er97+OFHbFy/ccMBF/hBxc1//ysopWDrli3T06n0s47j+p7n+yEXTIiOjo5mx3EcxphwHMfJ5/N2d3f3ky/Mm5d89W3OgPNfnA8zpx+Ke3p6rsrn8znbcZwwPDqXTaVS/d3d3d3pdHpnW1vbMflcGJKcyWSgtaXlCMsqtLiu4/f19XWmUqke3/eDYtrt3paW1nOUUnDDH69/S3tLlyyFha8srOjr7Xsxn8/btuM4jHNRpPbMcc6l7/mBU+yH53peT0/Pvzas3zBWKQWXXPLVgzb3B80FegAd7R3Q09vTUF9f/9tYLHYuQhiBCg3HuVyup6SkpMowjIjjuLbvex6l1O/r6/tCRUXF4qqqt3LEbNu6DTzPq6mprflnNBqdoxQIP/BdXdP0YrSJWSgUblu8ZNF3hlTVsJ07dtLTTj/txlgs9jWMiQrzSXJmmEYEAIjjuvcsW7b8W+VlZe4RRxz2lrYCP4DOzo6zq6qq7lYAGiWUYoKJbduFSCQSJYRonAsmpZAKQDmWfU9HR+cvSktL+0aOGnFQ5/ygBDv8J4YOGwpDhgxp7ezo+IHn+XMBlBrg2AYIXZgc27FESJtlRCKR2tLS0jOrqqrwHXf+4y11HXnEUTB12tTuwPfvUEpZhGAai0bjmqYZSinlup6NMT5p7Kixk0aOHAlHHHnkNMMwPq6k4gjCXGsKQFkFK884b8lmMrccftis3QT+xOOPw4033KBFY7EzNV0vHUiOJ0WYRUcVcx1zzrhSSrqO+0BHZ+fPKyorDrrAAQ5gAOM7YejQodDW1tbd1dl5ZU1tjTAM44JibnMqOOeUUkPXdQOFmYO1SCRy4rJly2o0Tev8z3pSmX5Yt3YduK77UjyeeFUIcZqu6xoUaclt28pxxoxYLPbx4fUjNnb1dH3GNMwRCIdfGQEESkph25YVsODeBx6Yu+boo3d3Vpg0aTKMHDlqFMb4cCklC3MXhVZ4SqimQAEXnFNKqe04D3V2dv60oqK8v6Ghfm+nZL/ioG/v/4nm5hbIZrNVQ4fWXUcpPdd1XSsRT5Rqum5ghHBQzMemlAp6enouqa+vf0LXd0/fbRUKkE5nTk2WJO/EGJcoBRJjRGzbzrEg4PF4vLO/P3VlTW3NXymlE4uRTYgWaUxzudz63r6+CxPx+JbhbzNl6sQAn3vQ1tp+WUlpye/DY4Novu97+Xw+E41GY5RSQ0ohGeNPdXV1X1lZWdlVV1e7t9Ow33HQt/f/xIgRw6Ekmezr6uj6mWVZT8ZisRLDMCIYY6JAKS44d13XUUoZsVjsjFtuuVl/4onHdqtnw/oNsHXLltcEF69KIZUUXDDG/Fgslkwkk0ndMCaUlJZcoZQaallWzvc8z3Nc2/M8hzHGMMYv/+73v9m2sXHDbnU//sTj8NDch6ORaOQUXdfjA0xZkUgkmkwmSxhjvmVZadf1nm9tbf9xIpn8rxI4wH/ZSh9Aa2srpFKphuENDX+PxeNnIISVlIIXCoVcLptNRyKRmKbr+a6uzk+bhrlp/IQJu9VhWRb09/efUllReb8f+DgIAi8ajcYGmF1xkUbOcRwLDwTGI0S5FF2p/tSnS0pKVg7mfLhzx06wCoVpDSOGP26YZr1GKRnI4KQAwPe8IJfLPdPR0XFFVVVVy75K5rMv8V9xpr8dDQ0N0N/X39qfSl2FCak0TXO2UgpC5yeMAGHQNL2utKzs8Ib6hk2D1bFt2zYQXLwRiUSe8Vz3qNKystpIJBILAubzkG2RajTkXw1pu5WSAC7n4pmtW7euLy0t2a3OY445FkaNHgXt7e3HE0KqQYHgjEtCyQBDEeFcrLZt+5rhI0a0DKl+/+FLH0lcddVVA0l8js2kM+v7+/v706lUfy6Xy2Wzuaxt235vb+/dN/75T/qe6EWVUvD88/MqW5pbbisUCo5th69313XdAY5Vx3GcIk1Yurm5+YpFixeXN7cMnsnwxRdehMcfezyeyWSeDYJA5XL5bF9vX5fnup7neTybyzVu2br1aKUUfO973z/YU7hH/FeudACA3/3ud3D4YYfBJ88557Utm7f8LB6P/ToWi9X5fuARggkAeJRqM0464cRhGONBY6rmvzgfWBAUdEM3BedCIiwAATIMo+hswVjRp55jjHXTNIzjjj02vSd2iLFjx4LruqMwxpMZY55SUum6HuFhyHtPNpP55fhx415/5qln4M9/vhH+W/FfdZF7O8751Kfgmaefhnvvuec5hPD9umHqhGBadL9SmkZHlJaWHjtlD0n/tm3bBmedfZavlNqEMEZEoxqlmiaE4I5t5Xu6OtsKhXw2jIIRQgiZBQCYPWvWoPWNHDUSorHY4RjjSqWUMAwjIqTgUoggn8//7cX5Lzzx8oKX4axP7l2Y88HCf+VF7u1Yu2YdBIFfPnLUyFt0TTsDAAmqUV1JhRzXeeypp576clVVpf/JT56zW9mO9nbIFwpjq6ur/6Tp+tEIkMY5C2yrkBeCc8OIRAzTjAghX+vt6fl2IpForR/kPT3/xZfAse3YkUcf+c/S0tLzMMZKSCl8z3Nt236so6PjB4ZhZN5vqNH/xyDo6+uFrVu3zsjlchs8z+O2bds9PT3dnZ2dK1evXjV6T3zrF15wAXAuYeWKleO6u7uXZzKZXDabyxYKhUImnU7l8/lCX1/fxi1bth4yGDfcANpa22DLps0zrILVGgSBcF3PsyzLzWazy9etXzeutbX1YE/RXuO/env/Tzz++OMwbty4Nfl8/reu6/Y4tmMrqaSm6/Vl5eVH7mmFPfDggwAgobKycjJGeEiYuNF1GGMBwhhzzgPDMMp0nZqGoQ9ax5RJk2BY/TCIxmNHKVDlfhC4tm1Zvu93p1PpX0+bOm3bXff882BP0V7jf0bol132NXht8WJYtWLlY1bBusvzPMfzXNvQ9XgsGjvx5ltv1h574vFByyKEgGpUM0wjoWmaPvAnTIqBCSDQpJQmJoM7B1//xxvg6SefjhJCjgmCgAWe7wkhuG07d86b9+K8F+a9CNf8bO9oUf4b8F97ex8Mxx1/POzYvsPv7+u/pW5o3cxItOQ4TdOokHLWMUcdM5QQ0jxYuV07d4EQYl3EjHQhjOqKVKEmY8z3fT/gjHe4rtPkdw2eTnvc+HHgud6oSCQys5iOBiul3ujp7bnjpJNPYBMGUQ79N+N/SugAAFMOmQSu5Xc27Wq6wYxEpiilaiilw0tKSg5vaGhoHqxMV1cXcCHaq6qqdlBKR3AhuKaUKlrHDMdxdjU2buqJRCKDtjlq1Cjo6Og4OhKJDCeEaL7vt2Wz2RsnTpjQE4/H4X8N/zPb+wA8O4CX578Ejz708GLPc++SUjIhBNF1fc6vr/0lnfvA7hGdL89/GU44YY6NMNqoaZqOiqxSAQt92LjgGz/zmQu8wai8578wHx5/9PFINBo9GWOsCyGYbdv/uOMfdy598803D/Z0vC/8TzzZBsP2bdvA870hyWTJTWYkchIlpLWlpfmThJDW6dMP2e33Sino6+v7XCKRvAMhIAghFDAWgFIsl8teXFFe8WQkGt2t3JbNW4BzPqG2ru4JjNEwBerN1pbWL0Sj0a63J879X8H/3PY+gLHjxkFfX39Pb0/PLfF4/DBd10eVlZfPrK2pHfTt1NfbB0EQbBdRnkUIlwkRZlsCgJTjODsCPxi0nZGjR0FHe8dMKUWF57FWyypcN3369K5R496d5eq/Ff9z2/t/YuvmzbCpsXEpY+wxADAjZuRY0zTx7W/jhgcAyGSzYFlWW+AH7Y5j22GKK0Ixwj2O63YVbGu3Mo8++ijc9Oe/0IhpHqfpehxj9OySJa8vfvXVhdC0/b2zaf234H92pQMAHHPcsdDZ2RlkMplbNU07jhDtyDeWLqsilPS8/bc93T3AOc9UD6lu1XV9EmPMoZRojLGdO3bsyA9GFjh+3HgYPWrMUMM0jgSltmdzubtOO/1UPrRu6F717/9jP+Eft/8DlFLQ0tz6+d7e/h3btm37WH9qt/y68NOf/ByUUpBJZ/7g+74s5lUJent7f6CUglNOP223Mq7rQktzy9nZXK6rvb39y0opuPe++w72kP8/AABWLl8Bi15dGO/vTz3Q09PzewBAN1x//W6/CxP4dH/ZDm2srud5+c6uzjNc193tt3PvfwBOPu4k3NPd85f+/v5H3ly+vOTdUmv+r+B/ensfwKzDZkM+l7fy+fzNhml8e/ny5RVKqf63/66/vx98z98Si8UKUsooQqjXtu1dvre7Umbc+Anw+z9dX40xGuHY9o3jx43LlZaWHuyh7hN8KIQOEMaJg1JvDm2oPzoWi09IJOJL3v6bXDYHQoh2BChFKS1nQdCZy2R78SApvWtqaiCTzYx3HPf1TVs2LQ1d4T8c+J++vf8njjrmKBhSV8ty2dwTjLEhcx98AM+dO/ctv0mlUpBK9ae54K0AgBnn25e8vqSwa9dbU00/8eST8NKClzBnvCKbzT02dvQ4dsIJcw72EPcZPjQrHQBg+9ZtEI1GdxbsAh02bJjhBW89rF9duBD+dMON9sZNG3dQSk+WUu747ne/x97uKWPZNpiRiNHV07XZ1CPNTXuTf/x/CB8qoZ92xmnw05//RADAFgCkAN6aUfGqq64EpZTs7OzcaRiGCwC7Bsu6uGnTJgAEnlJqKwDI3/3muoM9tP+PD4JsLgcdHR2fzGazza0tLYd3d3Ud7C4dcHyoVvrewLZs4Jx3cs5b8oV878FIkXWw8ZETej6XA4RQStf0rVLIrFfkjvko4SMndNu2Qdf1jOPYKzLZjNvc3Hywu3TA8ZET+ksvvQwVlRX2sPphy+tqa9msWR8hJogi/h/tLHbeZtFCOQAAAABJRU5ErkJggg=="; // Eldervale palette (silver emblem + warm gold accents) matching the admin panel. var ELDERVALE_THEME = { gold: "#d8c08a", goldBright: "#e8d09a", goldLine: "#c9a86a", glow: "rgba(201, 168, 106, 0.20)", glowStrong: "rgba(201, 168, 106, 0.55)", logoWidth: 108, logoHeight: 138, }; /***/ }), /***/ "./src/services/services/authService.ts": /*!**********************************************!*\ !*** ./src/services/services/authService.ts ***! \**********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AuthService: () => (/* binding */ AuthService) /* harmony export */ }); /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! crypto */ "crypto"); /* harmony import */ var crypto__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(crypto__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! fs */ "fs"); /* harmony import */ var fs__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(fs__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _features_authModel__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../features/authModel */ "./src/features/authModel.ts"); /* harmony import */ var _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../lib/functionInfo */ "./src/lib/functionInfo.ts"); /* harmony import */ var _clientListener__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./clientListener */ "./src/services/services/clientListener.ts"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! skyrimPlatform */ "skyrimPlatform"); /* harmony import */ var skyrimPlatform__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(skyrimPlatform__WEBPACK_IMPORTED_MODULE_5__); /* harmony import */ var _timersService__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./timersService */ "./src/services/services/timersService.ts"); /* harmony import */ var _logging__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../../logging */ "./src/logging.ts"); /* harmony import */ var _networkingService__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./networkingService */ "./src/services/services/networkingService.ts"); /* harmony import */ var _messages__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ../../messages */ "./src/messages.ts"); /* harmony import */ var _settingsService__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./settingsService */ "./src/services/services/settingsService.ts"); /* harmony import */ var _authBranding__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./authBranding */ "./src/services/services/authBranding.ts"); var __extends = (undefined && undefined.__extends) || (function () { var extendStatics = function (d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; return function (d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); // Module-scope aliases (NOT the imported names) used by eldervaleThemeSetter. // The widget setters are serialized via FunctionInfo.toString() and re-run in // the browser; their free variables are re-supplied by getText() keyed by name. // Imported bindings get rewritten by webpack to namespace accesses // (authBranding_1.ELDERVALE_*), which would not match the destructured keys, so // we reference plain local consts here — same convention as events/strings. var logo = _authBranding__WEBPACK_IMPORTED_MODULE_11__.ELDERVALE_LOGO_DATA_URI; var theme = _authBranding__WEBPACK_IMPORTED_MODULE_11__.ELDERVALE_THEME; // Constants used on both client and browser side (see browsersideWidgetSetter) var events = { openDiscordOauth: 'openDiscordOauth', authAttempt: 'authAttemptEvent', openGithub: 'openGithub', openPatreon: 'openPatreon', clearAuthData: 'clearAuthData', updateRequired: 'updateRequired', backToLogin: 'backToLogin', joinDiscord: 'joinDiscord' }; // Vaiables used on both client and browser side (see browsersideWidgetSetter) var browserState = { comment: '', failCount: 9000, loginFailedReason: '', }; var authData = null; var translations = { "ru": { loginViaDiscord: 'войдите через discord', joinDiscordServer: 'вступите в discord сервер', banned: 'вы забанены', whatWasThat: 'что это было?', openingBrowser: 'открываем браузер...', loginFirst: 'сначала войдите', linkedSuccessfully: 'привязан успешно', connecting: 'подключение', technicalIssues: 'технические шоколадки\nпопробуйте еще раз\nпожалуйста\nили напишите нам в discord', authorization: 'Авторизация', notAuthorized: 'не авторизирован', changeAccount: 'сменить аккаунт', loginViaSkymp: 'войти через skymp', play: 'Играть', loginOrChangeHint: 'Вы можете войти или поменять аккаунт', connectToServer: 'Подключиться к игровому серверу', updateCaption: 'новинка', updateAvailable: 'ура! вышло обновление', downloadAt: 'спешите скачать на', openSkympNet: 'открыть skymp.net', updateDownloadHint: 'Перейти на страницу скачивания обновления', oops: 'упс', join: 'вступить', back: 'назад', }, // Eldervale Realm — textos de la ventana de autorización (locale activo "en"). "en": { loginViaDiscord: 'inicia sesión con Discord', joinDiscordServer: 'únete al servidor de Discord', banned: 'estás baneado', whatWasThat: '¿qué fue eso?', openingBrowser: 'abriendo el navegador...', loginFirst: 'inicia sesión primero', linkedSuccessfully: 'cuenta vinculada', connecting: 'conectando', technicalIssues: 'problemas técnicos\nintenta de nuevo\no escríbenos en Discord', authorization: 'Eldervale Realm', notAuthorized: 'sin iniciar sesión', changeAccount: 'cambiar cuenta', loginViaSkymp: 'iniciar sesión', play: 'Entrar al mundo', loginOrChangeHint: 'Inicia sesión o cambia de cuenta', connectToServer: 'Conectar al servidor', updateCaption: 'Actualización', updateAvailable: '¡hay una nueva actualización!', downloadAt: 'descárgala en', openSkympNet: 'abrir página de descarga', updateDownloadHint: 'Ir a la página de descarga', oops: 'ups', join: 'unirse', back: 'volver', }, }; var strings = translations['en']; try { var lang = fs__WEBPACK_IMPORTED_MODULE_1__.readFileSync('./Data/Platform/Distribution/locale', 'utf8').trim(); if (lang in translations) { strings = translations[lang]; var src = "window.setLanguage(".concat(lang, ")"); skyrimPlatform__WEBPACK_IMPORTED_MODULE_5__.browser.executeJavaScript(src); } } catch (_a) { // locale file not found or unreadable, default to 'en' } var AuthService = /** @class */ (function (_super) { __extends(AuthService, _super); function AuthService(sp, controller) { var _this = _super.call(this) || this; _this.sp = sp; _this.controller = controller; _this.eldervaleThemeSetter = function () { var id = 'eldervale-auth-theme'; if (document.getElementById(id)) { return; } var style = document.createElement('style'); style.id = id; style.textContent = "\n .login-form {\n filter: drop-shadow(0 0 26px ".concat(theme.glow, ");\n }\n .login-form--content_header {\n position: relative !important;\n margin-top: 16px !important;\n padding-top: ").concat(theme.logoHeight + 16, "px !important;\n font-size: 26px !important;\n letter-spacing: 6px !important;\n text-transform: uppercase !important;\n white-space: nowrap !important;\n color: ").concat(theme.gold, " !important;\n text-shadow: 0 0 10px ").concat(theme.glow, ", 0 2px 4px rgba(0,0,0,0.65) !important;\n }\n .login-form--content_header::before {\n content: '';\n position: absolute;\n top: 0;\n left: 50%;\n transform: translateX(-50%);\n width: ").concat(theme.logoWidth, "px;\n height: ").concat(theme.logoHeight, "px;\n background: url(\"").concat(logo, "\") center / contain no-repeat;\n filter: drop-shadow(0 0 9px ").concat(theme.glowStrong, ");\n }\n .login-form--content_header::after {\n content: '';\n display: block;\n width: 72%;\n height: 2px;\n margin: 14px auto 0;\n background: linear-gradient(90deg, transparent, ").concat(theme.goldLine, ", transparent);\n }\n .skymp-button .button-middle * {\n color: ").concat(theme.goldBright, " !important;\n text-shadow: 0 0 8px ").concat(theme.glowStrong, " !important;\n }\n "); document.head.appendChild(style); }; _this.deniedWidgetSetter = function () { var widget = { type: "form", id: 2, caption: strings.updateCaption, elements: [ { type: "text", text: strings.updateAvailable, tags: [] }, { type: "text", text: strings.downloadAt, tags: [] }, { type: "text", text: "skymp.net", tags: [] }, { type: "button", text: strings.openSkympNet, tags: ["ELEMENT_STYLE_MARGIN_EXTENDED"], click: function () { return window.skyrimPlatform.sendMessage(events.updateRequired); }, hint: strings.updateDownloadHint, } ] }; window.skyrimPlatform.widgets.set([widget]); // Make sure gamemode will not be able to update widgets anymore window.skyrimPlatform.widgets = null; }; _this.loginFailedWidgetSetter = function () { var splitParts = browserState.loginFailedReason.split('\n'); var textElements = splitParts.map(function (part) { return ({ type: "text", text: part, tags: [], }); }); var widget = { type: "form", id: 2, caption: strings.oops, elements: new Array() }; textElements.forEach(function (element) { return widget.elements.push(element); }); if (browserState.loginFailedReason === strings.joinDiscordServer) { widget.elements.push({ type: "button", text: strings.join, tags: ["ELEMENT_STYLE_MARGIN_EXTENDED"], click: function () { return window.skyrimPlatform.sendMessage(events.joinDiscord); }, hint: null }); } widget.elements.push({ type: "button", text: strings.back, tags: ["ELEMENT_STYLE_MARGIN_EXTENDED"], click: function () { return window.skyrimPlatform.sendMessage(events.backToLogin); }, hint: undefined }); window.skyrimPlatform.widgets.set([widget]); }; _this.browsersideWidgetSetter = function () { var loginWidget = { type: "form", id: 1, caption: strings.authorization, elements: [ // { // type: "button", // tags: ["BUTTON_STYLE_GITHUB"], // hint: "get a colored nickname and mention in news", // click: () => window.skyrimPlatform.sendMessage(events.openGithub), // }, // { // type: "button", // tags: ["BUTTON_STYLE_PATREON", "ELEMENT_SAME_LINE", "HINT_STYLE_RIGHT"], // hint: "get a colored nickname and other bonuses for patrons", // click: () => window.skyrimPlatform.sendMessage(events.openPatreon), // }, // { // type: "icon", // text: "username", // tags: ["ICON_STYLE_SKYMP"], // }, // { // type: "icon", // text: "", // tags: ["ICON_STYLE_DISCORD"], // }, { type: "text", text: (authData ? (authData.discordUsername ? "".concat(authData.discordUsername) : "id: ".concat(authData.masterApiId)) : strings.notAuthorized), tags: [ /*"ELEMENT_SAME_LINE", "ELEMENT_STYLE_MARGIN_EXTENDED"*/], }, // { // type: "icon", // text: "discord", // tags: ["ICON_STYLE_DISCORD"], // }, { type: "button", text: authData ? strings.changeAccount : strings.loginViaSkymp, tags: [ /*"ELEMENT_SAME_LINE"*/], click: function () { return window.skyrimPlatform.sendMessage(events.openDiscordOauth); }, hint: strings.loginOrChangeHint, }, { type: "button", text: strings.play, tags: ["BUTTON_STYLE_FRAME", "ELEMENT_STYLE_MARGIN_EXTENDED"], click: function () { return window.skyrimPlatform.sendMessage(events.authAttempt); }, hint: strings.connectToServer, }, { type: "text", text: browserState.comment, tags: [], }, ] }; window.skyrimPlatform.widgets.set([loginWidget]); }; _this._isListenBrowserMessage = false; _this.trigger = { authNeededFired: false, browserWindowLoadedFired: false, get conditionMet() { return this.authNeededFired && this.browserWindowLoadedFired; } }; _this.discordAuthState = crypto__WEBPACK_IMPORTED_MODULE_0__.randomBytes(32).toString('hex'); _this.authDialogOpen = false; _this.loggingStartMoment = 0; _this.authAttemptProgressIndicator = false; _this.authAttemptProgressIndicatorCounter = 0; _this.playerEverSawActualGameplay = false; _this.githubUrl = "https://github.com/skyrim-multiplayer/skymp"; _this.patreonUrl = "https://www.patreon.com/skymp"; _this.pluginAuthDataName = "auth-data-no-load"; _this.controller.emitter.on("authNeeded", function (e) { return _this.onAuthNeeded(e); }); _this.controller.emitter.on("browserWindowLoaded", function (e) { return _this.onBrowserWindowLoaded(e); }); _this.controller.emitter.on("createActorMessage", function (e) { return _this.onCreateActorMessage(e); }); _this.controller.emitter.on("connectionAccepted", function () { return _this.handleConnectionAccepted(); }); _this.controller.emitter.on("connectionDenied", function (e) { return _this.handleConnectionDenied(e); }); _this.controller.emitter.on("customPacketMessage", function (e) { return _this.onCustomPacketMessage(e); }); _this.controller.on("browserMessage", function (e) { return _this.onBrowserMessage(e); }); _this.controller.on("tick", function () { return _this.onTick(); }); _this.controller.once("update", function () { return _this.onceUpdate(); }); return _this; } AuthService.prototype.onAuthNeeded = function (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Received authNeeded event"); var settingsGameData = this.sp.settings["skymp5-client"]["gameData"]; var isOfflineMode = Number.isInteger(settingsGameData === null || settingsGameData === void 0 ? void 0 : settingsGameData.profileId); if (isOfflineMode) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Offline mode detected in settings, emitting auth event with authGameData.local"); this.controller.emitter.emit("authAttempt", { authGameData: { local: { profileId: settingsGameData.profileId } } }); } else { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "No offline mode detectted in settings, regular auth needed"); this.setListenBrowserMessage(true, 'authNeeded event received'); this.trigger.authNeededFired = true; if (this.trigger.conditionMet) { this.onBrowserWindowLoadedAndOnlineAuthNeeded(); } } }; AuthService.prototype.onBrowserWindowLoaded = function (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Received browserWindowLoaded event"); this.trigger.browserWindowLoadedFired = true; if (this.trigger.conditionMet) { this.onBrowserWindowLoadedAndOnlineAuthNeeded(); } }; AuthService.prototype.onCreateActorMessage = function (e) { if (e.message.isMe) { if (this.authDialogOpen) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Received createActorMessage for self, resetting widgets"); this.sp.browser.executeJavaScript('window.skyrimPlatform.widgets.set([]);'); this.authDialogOpen = false; } else { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Received createActorMessage for self, but auth dialog was not open so not resetting widgets"); } } this.loggingStartMoment = 0; this.authAttemptProgressIndicator = false; }; AuthService.prototype.onCustomPacketMessage = function (event) { var msg = event.message; var msgContent = {}; try { msgContent = JSON.parse(msg.contentJsonDump); } catch (e) { if (e instanceof SyntaxError) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logError)(this, "onCustomPacketMessage failed to parse JSON", e.message, "json:", msg.contentJsonDump); return; } else { throw e; } } switch (msgContent["customPacketType"]) { // case 'loginRequired': // logTrace(this, 'loginRequired received'); // this.loginWithSkympIoCredentials(); // break; case 'loginFailedNotLoggedViaDiscord': this.authAttemptProgressIndicator = false; this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).close(); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'loginFailedNotLoggedViaDiscord received'); browserState.loginFailedReason = strings.loginViaDiscord; browserState.comment = ''; this.setListenBrowserMessage(true, 'loginFailedNotLoggedViaDiscord received'); this.loggingStartMoment = 0; this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.loginFailedWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); break; case 'loginFailedNotInTheDiscordServer': this.authAttemptProgressIndicator = false; this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).close(); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'loginFailedNotInTheDiscordServer received'); browserState.loginFailedReason = strings.joinDiscordServer; browserState.comment = ''; this.setListenBrowserMessage(true, 'loginFailedNotInTheDiscordServer received'); this.loggingStartMoment = 0; this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.loginFailedWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); break; case 'loginFailedBanned': this.authAttemptProgressIndicator = false; this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).close(); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'loginFailedBanned received'); browserState.loginFailedReason = strings.banned; browserState.comment = ''; this.setListenBrowserMessage(true, 'loginFailedBanned received'); this.loggingStartMoment = 0; this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.loginFailedWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); break; case 'loginFailedIpMismatch': this.authAttemptProgressIndicator = false; this.controller.lookupListener(_networkingService__WEBPACK_IMPORTED_MODULE_8__.NetworkingService).close(); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, 'loginFailedIpMismatch received'); browserState.loginFailedReason = strings.whatWasThat; browserState.comment = ''; this.setListenBrowserMessage(true, 'loginFailedIpMismatch received'); this.loggingStartMoment = 0; this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.loginFailedWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); break; } }; AuthService.prototype.onBrowserWindowLoadedAndOnlineAuthNeeded = function () { var _this = this; if (!this.isListenBrowserMessage) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logError)(this, "isListenBrowserMessage was false for some reason, aborting auth"); return; } (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Showing widgets and starting loop"); authData = this.readAuthDataFromDisk(); this.refreshWidgets(); this.sp.browser.setVisible(true); this.sp.browser.setFocused(true); var timersService = this.controller.lookupListener(_timersService__WEBPACK_IMPORTED_MODULE_6__.TimersService); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Calling setTimeout for testing"); try { timersService.setTimeout(function () { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(_this, "Test timeout fired"); }, 1); } catch (e) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logError)(this, "Failed to call setTimeout"); } }; AuthService.prototype.onBrowserMessage = function (e) { if (!this.isListenBrowserMessage) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "onBrowserMessage: isListenBrowserMessage was false, ignoring message", JSON.stringify(e.arguments)); return; } var settingsService = this.controller.lookupListener(_settingsService__WEBPACK_IMPORTED_MODULE_10__.SettingsService); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "onBrowserMessage:", JSON.stringify(e.arguments)); var eventKey = e.arguments[0]; switch (eventKey) { case events.openDiscordOauth: browserState.comment = strings.openingBrowser; this.refreshWidgets(); this.sp.win32.loadUrl("".concat(settingsService.getMasterUrl(), "/api/users/login-discord?state=").concat(this.discordAuthState)); // Launch checkLoginState loop this.checkLoginState(); break; case events.authAttempt: if (authData === null) { browserState.comment = strings.loginFirst; this.refreshWidgets(); break; } this.writeAuthDataToDisk(authData); this.controller.emitter.emit("authAttempt", { authGameData: { remote: authData } }); this.authAttemptProgressIndicator = true; break; case events.clearAuthData: // Doesn't seem to be used this.writeAuthDataToDisk(null); break; case events.openGithub: this.sp.win32.loadUrl(this.githubUrl); break; case events.openPatreon: this.sp.win32.loadUrl(this.patreonUrl); break; case events.updateRequired: this.sp.win32.loadUrl("https://skymp.net/UpdInstall"); break; case events.backToLogin: this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.browsersideWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); break; case events.joinDiscord: this.sp.win32.loadUrl("https://discord.gg/9KhSZ6zjGT"); break; default: break; } }; AuthService.prototype.createPlaySession = function (token, callback) { var settingsService = this.controller.lookupListener(_settingsService__WEBPACK_IMPORTED_MODULE_10__.SettingsService); var client = new this.sp.HttpClient(settingsService.getMasterUrl()); var route = "/api/users/me/play/".concat(settingsService.getServerMasterKey()); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Creating play session ".concat(route)); client.post(route, { body: '{}', contentType: 'application/json', headers: { 'authorization': token, }, // @ts-ignore }, function (res) { if (res.status != 200) { callback('', 'status code ' + res.status); } else { // TODO: handle JSON.parse failure? callback(JSON.parse(res.body).session, ''); } }); }; AuthService.prototype.checkLoginState = function () { var _this = this; if (!this.isListenBrowserMessage) { (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "checkLoginState: isListenBrowserMessage was false, aborting check"); return; } var settingsService = this.controller.lookupListener(_settingsService__WEBPACK_IMPORTED_MODULE_10__.SettingsService); var timersService = this.controller.lookupListener(_timersService__WEBPACK_IMPORTED_MODULE_6__.TimersService); // Social engineering protection, don't show the full state var halfDiscordAuthState = this.discordAuthState.slice(0, 16); (0,_logging__WEBPACK_IMPORTED_MODULE_7__.logTrace)(this, "Checking login state", halfDiscordAuthState, '...'); new this.sp.HttpClient(settingsService.getMasterUrl()) .get("/api/users/login-discord/status?state=" + this.discordAuthState, undefined, // @ts-ignore function (response) { switch (response.status) { case 200: var _a = JSON.parse(response.body), token = _a.token, masterApiId_1 = _a.masterApiId, discordUsername_1 = _a.discordUsername, discordDiscriminator_1 = _a.discordDiscriminator, discordAvatar_1 = _a.discordAvatar; browserState.failCount = 0; _this.createPlaySession(token, function (playSession, error) { if (error) { browserState.failCount = 0; browserState.comment = (error); timersService.setTimeout(function () { return _this.checkLoginState(); }, Math.floor((1.5 + Math.random() * 2) * 1000)); _this.refreshWidgets(); return; } authData = { session: playSession, masterApiId: masterApiId_1, discordUsername: discordUsername_1, discordDiscriminator: discordDiscriminator_1, discordAvatar: discordAvatar_1, }; browserState.comment = strings.linkedSuccessfully; _this.refreshWidgets(); }); break; case 401: // Unauthorized browserState.failCount = 0; browserState.comment = ''; //(`Still waiting...`); timersService.setTimeout(function () { return _this.checkLoginState(); }, Math.floor((1.5 + Math.random() * 2) * 1000)); break; case 403: // Forbidden case 404: // Not found browserState.failCount = 9000; browserState.comment = ("Fail: ".concat(response.body)); break; default: ++browserState.failCount; browserState.comment = "Server returned ".concat(response.status.toString() || "???", " \"").concat(response.body || response.error, "\""); timersService.setTimeout(function () { return _this.checkLoginState(); }, Math.floor((1.5 + Math.random() * 2) * 1000)); } }); }; ; AuthService.prototype.refreshWidgets = function () { this.applyEldervaleTheme(); this.sp.browser.executeJavaScript(new _lib_functionInfo__WEBPACK_IMPORTED_MODULE_3__.FunctionInfo(this.browsersideWidgetSetter).getText({ events: events, browserState: browserState, authData: authData, strings: strings })); this.authDialogOpen = true; }; ; // Injects the Eldervale Realm look (silver emblem + warm gold accents) as a // persistent