@jsprismarine/prismarine
Version:
Dedicated Minecraft Bedrock Edition server written in TypeScript
147 lines (144 loc) • 18.4 kB
JavaScript
import { BlockMappings } from '../../block/BlockMappings.es.js';
import BinaryStream from '@jsprismarine/jsbinaryutils';
import { Vector3 } from '@jsprismarine/math';
import SubChunk from './SubChunk.es.js';
const MAX_SUBCHUNKS = 16;
class Chunk {
x;
z;
hasChanged;
subChunks = /* @__PURE__ */ new Map();
static EMPTY_SUBCHUNK = new SubChunk();
constructor(chunkX = 0, chunkZ = 0, _subChunks = /* @__PURE__ */ new Map()) {
this.x = chunkX;
this.z = chunkZ;
this.hasChanged = false;
}
getX() {
return this.x;
}
getZ() {
return this.z;
}
getHasChanged() {
return this.hasChanged;
}
getHeight() {
return this.subChunks.size;
}
/**
* Returns the highest empty sub chunk (so we don't send empty sub chunks).
* @returns {number} The highest empty sub chunk.
*/
getTopEmpty() {
let topEmpty = MAX_SUBCHUNKS - 1;
while (topEmpty >= 0 && !this.subChunks.has(topEmpty) || this.subChunks.has(topEmpty) && this.subChunks.get(topEmpty).isEmpty()) {
topEmpty--;
}
return ++topEmpty;
}
/**
* Returns the Chunk slice at the given layer.
* @param {number} y - The layer to get.
*/
getSubChunk(y) {
if (y < 0 || y > MAX_SUBCHUNKS) {
throw new Error(`Invalid subchunk height: ${y}`);
}
return this.subChunks.get(y) ?? null;
}
getOrCreateSubChunk(y) {
const subChunk = new SubChunk();
this.subChunks.set(y, subChunk);
return subChunk;
}
getSubChunks() {
return this.subChunks;
}
getHighestBlockAt(_x, _z) {
return 100;
}
/**
* Returns block legacy id (DATA) in the corresponding sub chunk.
* Use world to get the actual block instance (this is to keep code clean).
* @param {Vector3 | number} x - block x.
* @param {number} [y=0] - block y.
* @param {number} [z=0] - block z.
* @param {number} [layer=0] - block storage layer (0 for blocks, 1 for liquids).
*/
getBlock(x, y = 0, z = 0, layer = 0) {
if (x instanceof Vector3) {
return this.getBlock(x.getX(), x.getY(), x.getZ(), layer);
}
const subChunk = this.getSubChunk(Math.floor(y / 16));
if (!subChunk) return BlockMappings.getLegacyId(BlockMappings.getRuntimeId("minecraft:air"));
return subChunk.getBlock(x, y & 15, z, layer);
}
/**
* Sets a block into the chunk by its runtime Id.
* @param {number} x - block x
* @param {number} y - block y
* @param {number} z - block z
* @param {Block} block - block to set
* @param {number} [layer=0] - block storage layer (0 for blocks, 1 for liquids)
*/
setBlock(x, y, z, block, layer = 0) {
let subChunk = this.getSubChunk(Math.floor(y / 16));
if (!subChunk) subChunk = this.getOrCreateSubChunk(y >> 4);
subChunk.setBlock(x, y & 15, z, BlockMappings.getRuntimeId(block.getName()), layer);
this.hasChanged = true;
}
/**
* Helper method used to hash into a single 64 bits integer
* both Chunk X and Z coordinates.
* @param {number} chunkX - Target Chunk X coordinate.
* @param {number} chunkZ - Target Chunk Z coordinate.
* @returns {bigint} A 64 bit intger containing a hash of X and Z.
*/
static packXZ(chunkX, chunkZ) {
return (BigInt(chunkX) & 0xffffffffn) << 32n | BigInt(chunkZ) & 0xffffffffn;
}
/**
* Helper method used to decode a 64 bit hash containing
* both Chunk X and Z coordinates.
* @param {bigint} packed - Target Chunk coordinate hash.
* @returns {number[]} An array containing decoded Chunk X and Z coordinates.
*/
static unpackXZ(packed) {
return [Number(BigInt.asIntN(32, packed >> 32n)), Number(BigInt.asIntN(32, packed & 0xffffffffn))];
}
networkSerialize() {
const stream = new BinaryStream();
for (let y = 0; y < 4; ++y) {
stream.writeByte(8);
stream.writeByte(0);
}
for (let y = 0; y < this.getTopEmpty(); ++y) {
(this.subChunks.get(y) ?? Chunk.EMPTY_SUBCHUNK).networkSerialize(stream);
}
for (let i = 0; i < 24; i++) {
stream.writeByte(0);
stream.writeUnsignedVarInt(1 << 1);
}
stream.writeByte(0);
return stream.getBuffer();
}
/**
* Deserialize network stream into chunk
* useful for client applications and/or our Filesystem impl
* @param {BinaryStream} stream - the network stream
* @param {number} [x] - the chunk x coordinate
* @param {number} [z] - the chunk z coordinate
*/
static networkDeserialize(stream, x, z) {
stream.read(8);
const subChunks = /* @__PURE__ */ new Map();
for (let i = 0; i < MAX_SUBCHUNKS; i++) {
subChunks.set(i, SubChunk.networkDeserialize(stream));
}
const chunk = new Chunk(x, z, subChunks);
return chunk;
}
}
export { Chunk as default };
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQ2h1bmsuZXMuanMiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy93b3JsZC9jaHVuay9DaHVuay50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSB7IExlZ2FjeUlkIH0gZnJvbSAnLi4vLi4vYmxvY2svQmxvY2tNYXBwaW5ncyc7XG5pbXBvcnQgeyBCbG9ja01hcHBpbmdzIH0gZnJvbSAnLi4vLi4vYmxvY2svQmxvY2tNYXBwaW5ncyc7XG5cbmltcG9ydCBCaW5hcnlTdHJlYW0gZnJvbSAnQGpzcHJpc21hcmluZS9qc2JpbmFyeXV0aWxzJztcbmltcG9ydCB7IFZlY3RvcjMgfSBmcm9tICdAanNwcmlzbWFyaW5lL21hdGgnO1xuaW1wb3J0IHR5cGUgeyBCbG9jayB9IGZyb20gJy4uLy4uL2Jsb2NrL0Jsb2NrJztcbmltcG9ydCBTdWJDaHVuayBmcm9tICcuL1N1YkNodW5rJztcblxuY29uc3QgTUFYX1NVQkNIVU5LUyA9IDE2O1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBDaHVuayB7XG4gICAgcHJpdmF0ZSB4OiBudW1iZXI7XG4gICAgcHJpdmF0ZSB6OiBudW1iZXI7XG4gICAgcHJpdmF0ZSBoYXNDaGFuZ2VkOiBib29sZWFuO1xuXG4gICAgcHJpdmF0ZSBzdWJDaHVua3M6IE1hcDxudW1iZXIsIFN1YkNodW5rPiA9IG5ldyBNYXAoKTtcbiAgICBwcml2YXRlIHN0YXRpYyByZWFkb25seSBFTVBUWV9TVUJDSFVOSyA9IG5ldyBTdWJDaHVuaygpO1xuXG4gICAgcHVibGljIGNvbnN0cnVjdG9yKGNodW5rWCA9IDAsIGNodW5rWiA9IDAsIF9zdWJDaHVua3M6IE1hcDxudW1iZXIsIFN1YkNodW5rPiA9IG5ldyBNYXAoKSkge1xuICAgICAgICB0aGlzLnggPSBjaHVua1g7XG4gICAgICAgIHRoaXMueiA9IGNodW5rWjtcbiAgICAgICAgdGhpcy5oYXNDaGFuZ2VkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFgoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMueDtcbiAgICB9XG5cbiAgICBwdWJsaWMgZ2V0WigpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy56O1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRIYXNDaGFuZ2VkKCk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5oYXNDaGFuZ2VkO1xuICAgIH1cblxuICAgIHB1YmxpYyBnZXRIZWlnaHQoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3ViQ2h1bmtzLnNpemU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgaGlnaGVzdCBlbXB0eSBzdWIgY2h1bmsgKHNvIHdlIGRvbid0IHNlbmQgZW1wdHkgc3ViIGNodW5rcykuXG4gICAgICogQHJldHVybnMge251bWJlcn0gVGhlIGhpZ2hlc3QgZW1wdHkgc3ViIGNodW5rLlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRUb3BFbXB0eSgpOiBudW1iZXIge1xuICAgICAgICBsZXQgdG9wRW1wdHkgPSBNQVhfU1VCQ0hVTktTIC0gMTtcbiAgICAgICAgd2hpbGUgKFxuICAgICAgICAgICAgKHRvcEVtcHR5ID49IDAgJiYgIXRoaXMuc3ViQ2h1bmtzLmhhcyh0b3BFbXB0eSkpIHx8XG4gICAgICAgICAgICAodGhpcy5zdWJDaHVua3MuaGFzKHRvcEVtcHR5KSAmJiB0aGlzLnN1YkNodW5rcy5nZXQodG9wRW1wdHkpIS5pc0VtcHR5KCkpXG4gICAgICAgICkge1xuICAgICAgICAgICAgdG9wRW1wdHktLTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gKyt0b3BFbXB0eTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBDaHVuayBzbGljZSBhdCB0aGUgZ2l2ZW4gbGF5ZXIuXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHkgLSBUaGUgbGF5ZXIgdG8gZ2V0LlxuICAgICAqL1xuICAgIHB1YmxpYyBnZXRTdWJDaHVuayh5OiBudW1iZXIpOiBTdWJDaHVuayB8IG51bGwge1xuICAgICAgICBpZiAoeSA8IDAgfHwgeSA+IE1BWF9TVUJDSFVOS1MpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgSW52YWxpZCBzdWJjaHVuayBoZWlnaHQ6ICR7eX1gKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5zdWJDaHVua3MuZ2V0KHkpID8/IG51bGw7XG4gICAgfVxuXG4gICAgcHVibGljIGdldE9yQ3JlYXRlU3ViQ2h1bmsoeTogbnVtYmVyKTogU3ViQ2h1bmsge1xuICAgICAgICBjb25zdCBzdWJDaHVuayA9IG5ldyBTdWJDaHVuaygpO1xuICAgICAgICB0aGlzLnN1YkNodW5rcy5zZXQoeSwgc3ViQ2h1bmspO1xuICAgICAgICByZXR1cm4gc3ViQ2h1bms7XG4gICAgfVxuXG4gICAgcHVibGljIGdldFN1YkNodW5rcygpOiBNYXA8bnVtYmVyLCBTdWJDaHVuaz4ge1xuICAgICAgICByZXR1cm4gdGhpcy5zdWJDaHVua3M7XG4gICAgfVxuXG4gICAgcHVibGljIGdldEhpZ2hlc3RCbG9ja0F0KF94OiBudW1iZXIsIF96OiBudW1iZXIpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gMTAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgYmxvY2sgbGVnYWN5IGlkIChEQVRBKSBpbiB0aGUgY29ycmVzcG9uZGluZyBzdWIgY2h1bmsuXG4gICAgICogVXNlIHdvcmxkIHRvIGdldCB0aGUgYWN0dWFsIGJsb2NrIGluc3RhbmNlICh0aGlzIGlzIHRvIGtlZXAgY29kZSBjbGVhbikuXG4gICAgICogQHBhcmFtIHtWZWN0b3IzIHwgbnVtYmVyfSB4IC0gYmxvY2sgeC5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gW3k9MF0gLSBibG9jayB5LlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbej0wXSAtIGJsb2NrIHouXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsYXllcj0wXSAtIGJsb2NrIHN0b3JhZ2UgbGF5ZXIgKDAgZm9yIGJsb2NrcywgMSBmb3IgbGlxdWlkcykuXG4gICAgICovXG4gICAgcHVibGljIGdldEJsb2NrKHg6IFZlY3RvcjMgfCBudW1iZXIsIHk6IG51bWJlciA9IDAsIHo6IG51bWJlciA9IDAsIGxheWVyID0gMCk6IExlZ2FjeUlkIHtcbiAgICAgICAgaWYgKHggaW5zdGFuY2VvZiBWZWN0b3IzKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5nZXRCbG9jayh4LmdldFgoKSwgeC5nZXRZKCksIHguZ2V0WigpLCBsYXllcik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBzdWJDaHVuayA9IHRoaXMuZ2V0U3ViQ2h1bmsoTWF0aC5mbG9vcih5IC8gMTYpKTtcbiAgICAgICAgaWYgKCFzdWJDaHVuaykgcmV0dXJuIEJsb2NrTWFwcGluZ3MuZ2V0TGVnYWN5SWQoQmxvY2tNYXBwaW5ncy5nZXRSdW50aW1lSWQoJ21pbmVjcmFmdDphaXInKSk7XG4gICAgICAgIHJldHVybiBzdWJDaHVuay5nZXRCbG9jayh4LCB5ICYgMHhmLCB6LCBsYXllcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhIGJsb2NrIGludG8gdGhlIGNodW5rIGJ5IGl0cyBydW50aW1lIElkLlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB4IC0gYmxvY2sgeFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB5IC0gYmxvY2sgeVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB6IC0gYmxvY2sgelxuICAgICAqIEBwYXJhbSB7QmxvY2t9IGJsb2NrIC0gYmxvY2sgdG8gc2V0XG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFtsYXllcj0wXSAtIGJsb2NrIHN0b3JhZ2UgbGF5ZXIgKDAgZm9yIGJsb2NrcywgMSBmb3IgbGlxdWlkcylcbiAgICAgKi9cbiAgICBwdWJsaWMgc2V0QmxvY2soeDogbnVtYmVyLCB5OiBudW1iZXIsIHo6IG51bWJlciwgYmxvY2s6IEJsb2NrLCBsYXllciA9IDApOiB2b2lkIHtcbiAgICAgICAgbGV0IHN1YkNodW5rID0gdGhpcy5nZXRTdWJDaHVuayhNYXRoLmZsb29yKHkgLyAxNikpO1xuICAgICAgICBpZiAoIXN1YkNodW5rKSBzdWJDaHVuayA9IHRoaXMuZ2V0T3JDcmVhdGVTdWJDaHVuayh5ID4+IDQpO1xuICAgICAgICBzdWJDaHVuay5zZXRCbG9jayh4LCB5ICYgMHhmLCB6LCBCbG9ja01hcHBpbmdzLmdldFJ1bnRpbWVJZChibG9jay5nZXROYW1lKCkpLCBsYXllcik7XG5cbiAgICAgICAgdGhpcy5oYXNDaGFuZ2VkID0gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIZWxwZXIgbWV0aG9kIHVzZWQgdG8gaGFzaCBpbnRvIGEgc2luZ2xlIDY0IGJpdHMgaW50ZWdlclxuICAgICAqIGJvdGggQ2h1bmsgWCBhbmQgWiBjb29yZGluYXRlcy5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gY2h1bmtYIC0gVGFyZ2V0IENodW5rIFggY29vcmRpbmF0ZS5cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gY2h1bmtaIC0gVGFyZ2V0IENodW5rIFogY29vcmRpbmF0ZS5cbiAgICAgKiBAcmV0dXJucyB7YmlnaW50fSBBIDY0IGJpdCBpbnRnZXIgY29udGFpbmluZyBhIGhhc2ggb2YgWCBhbmQgWi5cbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIHBhY2tYWihjaHVua1g6IG51bWJlciwgY2h1bmtaOiBudW1iZXIpOiBiaWdpbnQge1xuICAgICAgICByZXR1cm4gKChCaWdJbnQoY2h1bmtYKSAmIDB4ZmZmZmZmZmZuKSA8PCAzMm4pIHwgKEJpZ0ludChjaHVua1opICYgMHhmZmZmZmZmZm4pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBtZXRob2QgdXNlZCB0byBkZWNvZGUgYSA2NCBiaXQgaGFzaCBjb250YWluaW5nXG4gICAgICogYm90aCBDaHVuayBYIGFuZCBaIGNvb3JkaW5hdGVzLlxuICAgICAqIEBwYXJhbSB7YmlnaW50fSBwYWNrZWQgLSBUYXJnZXQgQ2h1bmsgY29vcmRpbmF0ZSBoYXNoLlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJbXX0gQW4gYXJyYXkgY29udGFpbmluZyBkZWNvZGVkIENodW5rIFggYW5kIFogY29vcmRpbmF0ZXMuXG4gICAgICovXG4gICAgcHVibGljIHN0YXRpYyB1bnBhY2tYWihwYWNrZWQ6IGJpZ2ludCk6IG51bWJlcltdIHtcbiAgICAgICAgcmV0dXJuIFtOdW1iZXIoQmlnSW50LmFzSW50TigzMiwgcGFja2VkID4+IDMybikpLCBOdW1iZXIoQmlnSW50LmFzSW50TigzMiwgcGFja2VkICYgMHhmZmZmZmZmZm4pKV07XG4gICAgfVxuXG4gICAgcHVibGljIG5ldHdvcmtTZXJpYWxpemUoKTogQnVmZmVyIHtcbiAgICAgICAgY29uc3Qgc3RyZWFtID0gbmV3IEJpbmFyeVN0cmVhbSgpO1xuXG4gICAgICAgIC8vIEZvciBzb21lIHJlYXNvbnMgd2UgbmVlZCB0aGlzIGhhY2sgc2luY2UgMS4xOCxcbiAgICAgICAgLy8gc2VlbXMgbGlrZSB0aGUgY2xpZW50IG5vdyBoYXMgc29tZSBuZWdhdGl2ZSBzcGFjZS5cbiAgICAgICAgLy8gVE9ETzogZmlndXJlIG91dCB3aGF0IGlzIHRoaXNcbiAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCA0OyArK3kpIHtcbiAgICAgICAgICAgIHN0cmVhbS53cml0ZUJ5dGUoOCk7IC8vIHN1YmNodW5rIHZlcnNpb24gOFxuICAgICAgICAgICAgc3RyZWFtLndyaXRlQnl0ZSgwKTsgLy8gMCBsYXllcnMgKGFsbCBhaXIpXG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IHRoaXMuZ2V0VG9wRW1wdHkoKTsgKyt5KSB7XG4gICAgICAgICAgICAodGhpcy5zdWJDaHVua3MuZ2V0KHkpID8/IENodW5rLkVNUFRZX1NVQkNIVU5LKS5uZXR3b3JrU2VyaWFsaXplKHN0cmVhbSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUT0RPOiAzRCBiaW9tZXNcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCAyNDsgaSsrKSB7XG4gICAgICAgICAgICBzdHJlYW0ud3JpdGVCeXRlKDApOyAvLyBmYWtlIGJpb21lIHBhbGV0dGUsIG5vbiBwZXJzaXN0ZW50XG4gICAgICAgICAgICBzdHJlYW0ud3JpdGVVbnNpZ25lZFZhckludCgxIDw8IDEpOyAvLyBwbGFpbnNcbiAgICAgICAgfVxuXG4gICAgICAgIHN0cmVhbS53cml0ZUJ5dGUoMCk7IC8vIGJvcmRlciA/XG5cbiAgICAgICAgLy8gVE9ETzogdGlsZXNcbiAgICAgICAgcmV0dXJuIHN0cmVhbS5nZXRCdWZmZXIoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXNlcmlhbGl6ZSBuZXR3b3JrIHN0cmVhbSBpbnRvIGNodW5rXG4gICAgICogdXNlZnVsIGZvciBjbGllbnQgYXBwbGljYXRpb25zIGFuZC9vciBvdXIgRmlsZXN5c3RlbSBpbXBsXG4gICAgICogQHBhcmFtIHtCaW5hcnlTdHJlYW19IHN0cmVhbSAtIHRoZSBuZXR3b3JrIHN0cmVhbVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBbeF0gLSB0aGUgY2h1bmsgeCBjb29yZGluYXRlXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IFt6XSAtIHRoZSBjaHVuayB6IGNvb3JkaW5hdGVcbiAgICAgKi9cbiAgICBwdWJsaWMgc3RhdGljIG5ldHdvcmtEZXNlcmlhbGl6ZShzdHJlYW06IEJpbmFyeVN0cmVhbSwgeD86IG51bWJlciwgej86IG51bWJlcik6IENodW5rIHtcbiAgICAgICAgc3RyZWFtLnJlYWQoOCk7IC8vIHNraXAgZmFrZSBzdWJjaHVua3NcblxuICAgICAgICBjb25zdCBzdWJDaHVua3M6IE1hcDxudW1iZXIsIFN1YkNodW5rPiA9IG5ldyBNYXAoKTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBNQVhfU1VCQ0hVTktTOyBpKyspIHtcbiAgICAgICAgICAgIHN1YkNodW5rcy5zZXQoaSwgU3ViQ2h1bmsubmV0d29ya0Rlc2VyaWFsaXplKHN0cmVhbSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2h1bmsgPSBuZXcgQ2h1bmsoeCwgeiwgc3ViQ2h1bmtzKTtcbiAgICAgICAgcmV0dXJuIGNodW5rO1xuICAgIH1cbn1cbiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7OztBQVFBLE1BQU0sYUFBZ0IsR0FBQSxFQUFBO0FBRXRCLE1BQXFCLEtBQU0sQ0FBQTtBQUFBLEVBQ2YsQ0FBQTtBQUFBLEVBQ0EsQ0FBQTtBQUFBLEVBQ0EsVUFBQTtBQUFBLEVBRUEsU0FBQSx1QkFBdUMsR0FBSSxFQUFBO0FBQUEsRUFDbkQsT0FBd0IsY0FBaUIsR0FBQSxJQUFJLFFBQVMsRUFBQTtBQUFBLEVBRS9DLFdBQUEsQ0FBWSxTQUFTLENBQUcsRUFBQSxNQUFBLEdBQVMsR0FBRyxVQUFvQyxtQkFBQSxJQUFJLEtBQU8sRUFBQTtBQUN0RixJQUFBLElBQUEsQ0FBSyxDQUFJLEdBQUEsTUFBQTtBQUNULElBQUEsSUFBQSxDQUFLLENBQUksR0FBQSxNQUFBO0FBQ1QsSUFBQSxJQUFBLENBQUssVUFBYSxHQUFBLEtBQUE7QUFBQTtBQUN0QixFQUVPLElBQWUsR0FBQTtBQUNsQixJQUFBLE9BQU8sSUFBSyxDQUFBLENBQUE7QUFBQTtBQUNoQixFQUVPLElBQWUsR0FBQTtBQUNsQixJQUFBLE9BQU8sSUFBSyxDQUFBLENBQUE7QUFBQTtBQUNoQixFQUVPLGFBQXlCLEdBQUE7QUFDNUIsSUFBQSxPQUFPLElBQUssQ0FBQSxVQUFBO0FBQUE7QUFDaEIsRUFFTyxTQUFvQixHQUFBO0FBQ3ZCLElBQUEsT0FBTyxLQUFLLFNBQVUsQ0FBQSxJQUFBO0FBQUE7QUFDMUI7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU1PLFdBQXNCLEdBQUE7QUFDekIsSUFBQSxJQUFJLFdBQVcsYUFBZ0IsR0FBQSxDQUFBO0FBQy9CLElBQUEsT0FDSyxZQUFZLENBQUssSUFBQSxDQUFDLEtBQUssU0FBVSxDQUFBLEdBQUEsQ0FBSSxRQUFRLENBQzdDLElBQUEsSUFBQSxDQUFLLFVBQVUsR0FBSSxDQUFBLFFBQVEsS0FBSyxJ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