外观
地形与群系
你的世界从选择地形生成模式的那一刻就开始塑造了。四种模式决定了大陆轮廓、岛屿分布和整体地势风格,是整个地形系统的第一块基石。
阅读提示
本节内容过多且较为复杂,后续编者会增强可读性,让每位玩家都能理解。
地形生成模式
原版游戏提供四种地形生成模式:
| 序号 | 地形类型 | 枚举值 | 描述 | 备注 |
|---|---|---|---|---|
| 1 | 大陆 | Continent | 标准大陆地形,有海洋和陆地 | 原版 |
| 2 | 岛屿 | Island | 独立岛屿地形 | 原版 |
| 3 | 平坦大陆 | FlatContinent | 平坦化的大陆地形 | 原版 |
| 4 | 平坦岛屿 | FlatIsland | 平坦化的岛屿地形 | 原版 |
| 5 | 虚空 | Nihility | 完全空的世界 | 联机版 |
| 6 | 优化地形 | Better | 优化版地形,增加盆地生成 | 联机版 |
| 7 | 极巨化 | Huge | 巨型地形,海平面降低 | 联机版 |
| 8 | 极冻高原256 | Cave | 倒置地形,顶部为基岩 | 联机版 |
| 9 | 空岛 | SkyIsland | 漂浮在空中的岛屿 | 联机版 |
| 10 | 基岩地形 | Bedrock | 低高度基岩骨架大陆 | 联机版 |
| 11 | 石头地形 | Stone | 被石头包围的岛屿地形 | 联机版 |
通俗解释:大陆模式适合喜欢长途探险的玩家,世界理论上无限大;岛屿模式则给你一个有边界的生存空间,适合挑战自我。平坦模式减少了极端地形,更适合建筑党。
世界设置参数
在创建世界时,你可以调整温度、湿度、海平面等参数。这些设置直接影响群系分布和地形外观,是定制化你生存体验的关键旋钮。
以下参数来自 WorldSettings.cs,玩家可在创建世界时调整:
| 参数 | 默认值 | 范围 | 作用 |
|---|---|---|---|
| 海平面高度 | 0 | -64 ~ +191 | 海平面偏移,正值升高海平面 |
| 温度 | 0 | -16 ~ +16 | 温度偏移(-16~+16),正值使世界更热 |
| 湿度 | 0 | -16 ~ +16 | 湿度偏移(-16~+16),正值使世界更湿润 |
| 生物群系大小 | 1.0 | 0.01 ~ +32 | 生物群系缩放因子,越大则群系面积越大 |
| 岛屿大小 | (400, 400) | 1 ~ +2500 | 岛屿模式下岛屿的尺寸 |
| 海岸线粗糙度 | 0.5 | 0 ~ 1 | 平坦或平坦岛屿模式下海岸线粗糙度 |
其中温度偏移和湿度偏移会直接叠加到温湿度计算结果上。例如温度偏移+8会让原本寒冷的区域变得温和,相当于把整个世界的温度带向赤道方向推移。
地形高度计算
每一个方块的 Y 坐标都不是随机的,而是由多层噪声函数叠加而成。理解高度计算,你就能预判哪里有山、哪里是谷、哪里可能藏着河流。
核心机制
高度的基础值为64(即海平面),最终高度被限制在10~251之间。高度的变化由四个因素叠加而成:
clamp(x, min, max):限制函数。若 x 小于 min 则返回 min,若 x 大于 max 则返回 max,否则返回 x 本身。这里把地形高度限制在 10~251 之间,防止出现极端值。
其中各参数含义:
| 参数 | 含义 | 通俗理解 |
|---|---|---|
| 海洋坡度 | 海岸线向深海过渡的坡度(基础值0.006) | 越靠近海岸线,地势越平缓地下降到海平面以下 |
| 丘陵 | 丘陵区域的起伏幅度(强度32) | 起伏较小,适合建造房屋和农田 |
| 山脉 | 山脉区域的起伏幅度(强度220) | 起伏极大,能到达Y=200以上的高度 |
| 河流 | 河谷下切的深度修正(强度1) | 河流会在地形上切出下陷的河谷 |
| 海洋深度 | 离岸越远海床越深 | 控制深海区域的下沉程度 |
地形三档
世界被分为三种地形区域,由"山脉因子"决定,取值0~1。山脉因子由低频噪声生成:
noise(x, z, freq):噪声函数,根据坐标 (x, z) 和频率生成一个看似随机但连续平滑的值(0~1)。相邻坐标的值相近,远离坐标的值差异大,因此能生成自然的起伏地形而非乱码般的锯齿。
频率极低意味着山脉非常庞大,一个山脉区域可以绵延数百格。根据山脉因子的大小,地形被分为三档:
| 山脉因子范围 | 地形类型 | 占比 | 特征 |
|---|---|---|---|
| 0 ~ 0.7 | 平原 | 约70% | 地势平缓,海拔接近海平面 |
| 0.7 ~ 0.87 | 丘陵 | 约17% | 明显起伏,适合建在山坡或山谷中 |
| 0.87 ~ 1 | 山脉 | 约13% | 高耸入云,海拔可达200以上 |
山脉区域虽然只占约13%,但高度增幅高达220,是平原的数倍。所以当你发现地面开始剧烈起伏时,你可能已经踏入了山脉区。
群系大小对地形的影响
群系大小设置会影响地形特征的尺度。群系缩放控制温湿度和山脉噪声的采样频率,直接影响群系的大小:
| 模式 | 基础系数 | 效果 |
|---|---|---|
| 大陆模式 | 1.75 | 群系更大,过渡更平缓,走很远才会换气候 |
| 岛屿模式 | 1.0 | 群系更小,变化更频繁,小范围内就能体验多种气候 |
温度与湿度
温度和湿度是决定群系类型的两大核心变量。它们不是固定值,而是随坐标连续变化的噪声场,在世界的每个角落组合出独特的气候。
温度与湿度计算代码
温度计算
温度取值 0~15,由 CalculateTemperature 方法生成:
csharp
public int CalculateTemperature(float x, float z) => Math.Clamp(
(int)(MathUtils.Saturate(
3f * SimplexNoise.OctavedNoise(x, z, 0.0015f / TGBiomeScaling, 5, 2f, 0.6f)
- 1.1f // 偏向寒冷的偏移量
+ m_worldSettings.TemperatureOffset / 16f // 玩家设置的温度偏移
)
* 16f),
0, 15
);湿度计算
湿度取值 0~15,由 CalculateHumidity 方法生成:
csharp
public int CalculateHumidity(float x, float z) => Math.Clamp(
(int)(MathUtils.Saturate(
3f * SimplexNoise.OctavedNoise(x, z, 0.0012f / TGBiomeScaling, 5, 2f, 0.6f)
- 0.9f // 偏向干燥的偏移量
+ m_worldSettings.HumidityOffset / 16f // 玩家设置的湿度偏移
)
* 16f),
0, 15
);温度
温度取值0~15,数值越高越热。游戏世界的温度分布偏向寒冷,约70%的区域温度不超过7。海拔和季节也会影响实际温度(后面详述)。
温度由噪声采样后经过偏移和映射得到:
- clamp(x, min, max):限制函数。若 x 小于 min 则返回 min,若 x 大于 max 则返回 max,否则返回 x 本身。这里把温度限制在 0~15 之间,防止出现极端值。
- sat(x):饱和函数(同 Saturate)。若 x<0 则返回 0,若 x>1 则返回 1,否则返回 x。作用是把数值限制在 0~1 范围内,防止后续乘法越界
其中:噪声为随坐标变化的随机值(0~1);-1.1是偏移量,使结果偏向寒冷;温度偏移是玩家在创建世界时设置的参数;sat表示将值限制在0~1范围内。
| 温度范围 | 气候描述 |
|---|---|
| 0~3 | 寒带,终年低温,地表常被冰雪覆盖 |
| 4~7 | 温带,四季分明,草地和树木最常见 |
| 8~11 | 暖温带/亚热带,温暖干燥或温暖湿润 |
| 12~15 | 热带,炎热,可能出现沙漠或茂密丛林 |
湿度
湿度取值0~15,数值越高越湿润。游戏世界的湿度分布偏向干燥,约65%的区域湿度不超过7。
湿度计算逻辑与温度类似,只是偏移量不同:
- clamp(x, min, max):限制函数。若 x 小于 min 则返回 min,若 x 大于 max 则返回 max,否则返回 x 本身。这里把湿度限制在 0~15 之间,防止出现极端值。
- sat(x):饱和函数(同 Saturate)。若 x<0 则返回 0,若 x>1 则返回 1,否则返回 x。作用是把数值限制在 0~1 范围内,防止后续乘法越界。
其中:-0.9是偏移量,使结果偏向干燥(比温度的-1.1略小,所以世界整体比"偏冷"更"偏干")。
| 湿度范围 | 气候描述 |
|---|---|
| 0~3 | 极干燥,沙漠或荒原 |
| 4~7 | 中等湿度,草原或温带森林 |
| 8~11 | 湿润,沼泽或热带雨林 |
| 12~15 | 极湿润,常年降水充沛 |
温湿度组合决定群系
温度和湿度共同决定你眼前的景象:
| 温度 | 湿度 | 环境特征 | 典型植被 |
|---|---|---|---|
| 高(>8) | 低(<6) | 沙漠:地表为沙子,昼夜温差大 | 仙人掌 |
| 高(>8) | 高(>8) | 热带丛林:温暖湿润,降水丰富 | 茂密阔叶树 |
| 中(4~8) | 中(4~8) | 温带:四季分明,草地为主 | 普通树木、草丛 |
| 低(<4) | 任意 | 寒带/雪原:地表积雪,植物稀少 | 稀疏针叶树 |
| 任意 | 任意 | 高海拔:海拔越高越冷,山顶终年积雪 | 无植被 |
海拔对温度的影响非常显著。即使地处热带,只要爬得足够高,山顶依然会被冰雪覆盖。反过来,地下深处会温暖得多,深层矿洞永远不会结冰。
地表与地下方块
你脚下踩着的方块,和地底深处的岩石,都不是随机分配的。温度、湿度、海拔和距海距离共同决定了一片区域由什么方块构成。
地下分层
地下岩石分为三层,由浅到深。GenerateTerrain 方法中通过"沙漠标志"判断使用哪种分层:
其中:温度和湿度为当地气候值(0~15);距海距离为该位置到最近海岸线的格数;山脉因子为 0~1 的地形参数(接近 1 表示高山区域)。满足任一条件即判定为沙漠环境。
| 条件 | 浅层 | 中层 | 深层 |
|---|---|---|---|
沙漠或海岸附近(isDesert=true) | 砂岩 | 花岗岩 | 玄武岩 |
普通区域(isDesert=false) | 花岗岩 | 花岗岩 | 玄武岩 |
砂岩只出现在沙漠地下或海岸线附近。如果你在温带地区挖到了砂岩,说明你离海不远了。
地表方块
地表由最上方的覆盖层决定,GenerateSurface 方法按以下优先级判定地表类型:
其中:y为海拔高度;冻结表示该位置有效温度≤0(见后文冰雪章节);砂岩表面指下方岩石为砂岩;水下表示该位置被水覆盖。
| 条件 | 地表方块 | 说明 |
|---|---|---|
| 沙漠区域 | 沙子(7) | 高温低湿环境的典型地表 |
| 温和气候的砂岩表面 | 石灰岩(6) | 比沙子更坚硬的地表 |
| 高海拔冻结区 | 冰雪(62) | 温度降到冰点以下的高山或极地 |
| 水底 | 沉积物(72) | 水下特殊方块 |
| 默认情况 | 草地(2) | 最常见、最温暖的地表 |
地表覆盖层的厚度由海拔和地形起伏共同决定:海拔越高、地形越陡峭,覆盖层越薄,越容易露出下面的岩石。
植被生成
树木、草丛、仙人掌——它们的出现不是随意的,而是被温度、湿度和地表方块严格筛选过的。读懂植被分布规律,你就能从周围的植物反推出此地的气候参数。
树木
- 树木只生长在草地或高草地表上
- 海拔必须高于海平面(≥66)
- 每个区块最多约5棵树
- 树种由当地温度和湿度决定
- 树木周围四格不能有阻挡物
仙人掌
GenerateCacti 方法仅在沙漠环境生成仙人掌,生成条件为:
其中:湿度和温度为当地气候值(0~15);地表为沙子是必要条件,仙人掌只能扎根在沙子上。
- 只出现在高温(>8)且干燥(<6)的区域
- 必须种在沙子上
- 典型的沙漠标志
草与植物
- 由当地温湿度和地表类型共同决定
- 草地方块可能转变为高草变体
- 不同气候带生长不同的野花和草丛
冰雪生成
当温度降至冰点以下,水会结冰、地面会覆雪。冰雪的生成遵循严格的温度阈值,而这个阈值还随海拔变化。
海拔温度修正
海拔对温度的影响如下。SubsystemWeather.cs 中的 GetTemperatureAdjustmentAtHeight 方法定义了修正公式:
round(x):四舍五入取整。把计算结果舍入到最接近的整数,因为温度修正值在游戏中以整数形式生效。
其中:y为海拔高度;64为海平面基准;0.0008和0.1为降温/升温系数。海平面以上按二次方加速降温(越高越冷,Y=200时已降温14度),海平面以下按线性升温(每降低1格升温0.1度,深层矿洞温暖如春)。
| 海拔 | 温度修正 | 通俗解释 |
|---|---|---|
| 海平面(Y=64) | 0 | 无影响 |
| Y=100 | -1 | 略微变冷 |
| Y=150 | -6 | 明显变冷 |
| Y=200 | -14 | 非常寒冷 |
| 最高点(Y=251) | -31 | 极寒 |
| 地下浅层(Y=50) | +1 | 地下反而更暖 |
| 最深处(Y=10) | +5 | 深层矿洞温暖如春 |
海平面以上每升高约35格,温度下降1度。一个原本温度5的温带区域,到了Y=150的高山上,有效温度就变成5-6=-1,已经低于冰点,常年积雪。
冰雪覆盖规则
GenerateSnowAndIce 方法在世界生成时执行。冻结判定由 IsPlaceFrozen 方法决定:
其中:基础温度为该位置的群系温度(0~15);海拔修正为上文的海拔温度修正值。两者相加若≤0,则该处判定为冻结区域。
- 冻结区域的水面会变成冰(62),冰面上可能覆雪(61)
- 冻结区域的方块上方会覆盖雪(61)
- 冰层厚度1~3格,由噪声随机决定
- 雪覆盖层厚度与温度相关:越冷越厚
区块生成步骤
一个16×16的区块从空白到可居住,需要经过四个阶段的流水线处理。每个阶段负责不同的内容,理解这个流程有助于排查地形异常或开发模组。
| 阶段 | 步骤序号 | 生成内容 |
|---|---|---|
| 阶段1 | 1 | 计算上半区块温湿度 |
| 2 | 生成上半区块基础地形 | |
| 阶段2 | 3 | 计算下半区块温湿度 |
| 4 | 生成下半区块基础地形 | |
| 阶段3 | 5 | 生成洞穴 |
| 6 | 生成矿袋(泥土、沙砾等) | |
| 7 | 生成矿物 | |
| 8 | 生成地表方块 | |
| 9 | 流体向下传播 | |
| 阶段4 | 10 | 生成草和植物 |
| 11 | 生成原木 | |
| 12 | 生成树木 | |
| 13 | 生成仙人掌 | |
| 14 | 生成南瓜 | |
| 15 | 生成海带 | |
| 16 | 生成海草 | |
| 17 | 生成底栖植物 | |
| 18 | 生成陷阱 | |
| 19 | 生成藤蔓 | |
| 20 | 生成墓碑 | |
| 21 | 生成石堆 | |
| 22 | 生成冰雪 | |
| 23 | 生成基岩和空气 | |
| 24 | 更新流体顶面状态 |
出生点选择
游戏会根据你选择的难度,在世界上寻找最适合出生的位置。不同难度对温湿度、海拔和地形起伏有不同偏好。
ScoreSpawnPosition 方法为每个候选位置打分,分数越低越不适合出生:
| 惩罚条件 | 简单模式 | 中等模式 | 困难模式 |
|---|---|---|---|
| 距原点>400格 | -0.25 | -0.25 | -0.25 |
| 低于海平面 | -1.5 | -1.5 | -1.5 |
| 山脉因子>0.9 | -1.5 | -1.5 | -1.5 |
| 温度过低 | <7: -1 | <3: -0.5 | >0: -0.5 |
| 温度过高 | — | >6: -1 | >2: -1 |
| 湿度极端 | 2~10: -0.5 | 3~8: -0.5 | >6: -1.5 |
| 海拔过高 | >75: -1 | >80: -1 | >85: -1 |
| 地形起伏大 | >5: -1 | >10: -1 | >15: -1 |
| 地形太平坦 | — | — | <5: -0.5 |
通俗解释:简单模式倾向于把你放在温带平原(温度适中、湿度适中、地势平坦);困难模式则可能把你推向更极端的环境(寒冷或干燥、地形崎岖)。但所有模式都会避免让你在水下或高山顶上出生。
联机版新地形
联机版快照提供了额外的世界生成模板。
基岩大陆 (Bedrock)
核心机制
- 地表高度:固定在第3-7层(基岩大陆优化)
- 世界结构:基岩底层 + 骨架大陆 + 虚空顶部
- 水体:不生成(
TGWater = false) - 地形特征:极低高度,无高山,平坦骨架
矿石生成逻辑
基岩大陆模式:minHeight = 2, maxHeight = 6, 数量倍率 = 0.3
普通模式:minHeight = 50, maxHeight = 61, 数量倍率 = 1.0| 矿石 | 生成高度 | 生成数量公式 | 替换方块 |
|---|---|---|---|
| 煤矿石 | Y=2-6 | (5 + 3 × 山脉因子 × 噪声) × 0.3 | 石头(3) |
| 铁矿石 | Y=2-6 | (6 + 2 × 山脉因子 × 噪声) × 0.3 | 石头(3) |
| 铜矿石 | Y=2-6 | (5 + 2 × 山脉因子 × 噪声) × 0.3 | 石头(3) |
| 硝石 | Y=2-6 | (3 + 3 × 山脉因子 × 噪声) × 0.3 | 石头(3) |
| 硫磺 | Y=2-6 | (3 + 2 × 山脉因子 × 噪声) × 0.3 | 石头(3) |
| 锗矿 | Y=2-6 | (3 + 2 × 山脉因子 × 噪声) × 0.3 | 石头(3) |
石头大陆 (Stone)
核心机制
- 出生平台:固定位置 (-433, 280),21×21大小,结构为基岩(2层)→泥土→草方块
- 世界结构:除出生平台外,整个世界被石头填充,只在岛屿区域有地形
- 岛屿生成:半径20格,高度40格,结构为基岩→石头→泥土→草方块
- 岩浆池:初始岛必生成1-2个岩浆池,其他岛15%概率生成
矿石生成逻辑
石头地形的矿石生成有两种方式:
方式1:标准矿物生成(类似其他地形)方式2:空气填石头时随机生成(5%概率)
| 矿石 | 高度条件 | 概率 | 方块ID |
|---|---|---|---|
| 钻石矿 | Y < 30 | 10% | 112 |
| 锗矿 | Y < 60 | 20% | 148 |
| 铁矿 | Y < 80 | 30% | 39 |
| 铜矿 | Y < 100 | 40% | 41 |
| 硫磺 | - | 50% | 101 |
| 硝石 | - | 70% | 100 |
| 煤矿 | - | 默认 | 16 |
空岛地形 (SkyIsland)
核心机制
- 基准高度:30层(
BaseHeight = 30) - 出生平台:半径128格,连接岛区域,基岩底层防止挖空
- 岛屿生成:基于噪声阈值(0.3)判断,高于阈值生成岛屿
- 地形特征:低空、密集、紧凑的岛屿分布
岩浆池生成
- 概率:8%(每个区块)
- 位置:岛屿内部,不超出岛屿边界
- 尺寸:半径2-4格,深度2-3格
- 生成规则:岩浆顶部 = 岛屿表面下1格,底部 = 表面下N格(不挖穿岛屿)
优化地形 (Better)
核心机制
- 盆地生成:噪声值 < 0.29 的区域生成盆地,深度由噪声计算
- 海平面:64层
- 水体:生成(
TGWater = true) - 河流强度:增强(
TGRiversStrength = 5f)
关键参数对比(与标准地形)
| 参数 | 标准值 | 优化值 |
|---|---|---|
| 河流强度 | 1.0 | 5.0 |
| 山脉高度 | 220 | 250 |
| 山脉频率 | 0.009 | 0.0006 |
| 山区百分比 | 60% | 13% |
| 山丘百分比 | 50% | 15% |
| 密度偏差 | 96 | 55 |
写给开发者
资料暂存
本小节内容暂时存放于此,后续会移动至"MOD开发"章节。
开发概览
如果你计划开发地形模组或自定义世界生成,以下技术细节将帮助你快速理解系统架构。
核心文件索引
| 文件 | 职责 |
|---|---|
TerrainContentsGenerator23.cs | 地形内容生成器主类,包含所有生成方法 |
WorldSettings.cs | 世界生成参数定义 |
TerrainGenerationMode.cs | 地形模式枚举 |
TerrainUpdater.cs | 季节温度曲线和区块状态更新 |
SubsystemWeather.cs | 天气、温度修正、冻结判定 |
SubsystemSeasons.cs | 季节划分和转换 |
Terrain.cs | 地形数据存取,季节温湿度计算 |
Season.cs | 季节枚举(Summer=0, Autumn=1, Winter=2, Spring=3) |
全部 TG 参数速查表
csharp
// 群系缩放(影响温湿度和山脉噪声频率)
TGBiomeScaling = (Island ? 1f : 1.75f) * BiomeSize;
// 海洋
TGOceanSlope = 0.006f;
TGOceanSlopeVariation = 0.004f;
TGIslandsFrequency = 0.01f;
TGShoreFluctuations = Clamp(2f * minIslandSize, 0f, 150f);
TGShoreFluctuationsScaling = Clamp(0.04f * minIslandSize, 0.5f, 3f);
// 高度基准
TGDensityBias = 55f;
TGHeightBias = 1f;
// 河流
TGRiversStrength = 1f;
// 山脉
TGMountainsStrength = 220f;
TGMountainRangeFreq = 0.0006f;
TGMountainsPercentage = 0.13f;
TGMountainsDetailFreq = 0.003f;
TGMountainsDetailOctaves = 3;
TGMountainsDetailPersistence = 0.53f;
// 丘陵
TGHillsPercentage = 0.3f;
TGHillsStrength = 32f;
TGHillsOctaves = 1;
TGHillsFrequency = 0.014f;
TGHillsPersistence = 0.5f;
// 湍流(地形扰动)
TGTurbulenceStrength = 55f;
TGTurbulenceFreq = 0.03f;
TGTurbulenceOctaves = 1;
TGTurbulencePersistence = 0.5f;
TGMinTurbulence = 0.04f;
TGTurbulenceZero = 0.84f;
// 地表
TGSurfaceMultiplier = 2f;
// 开关
TGWater = true; // 生成水
TGExtras = true; // 生成植被和装饰
TGCavesAndPockets = true; // 生成洞穴和矿袋
// 海平面
OceanLevel = 64 + SeaLevelOffset;
// 基岩
MaxBedrockHeight = 4;高度计算完整公式
csharp
public float CalculateHeight(float x, float z) {
// 1. 海洋坡度(控制海岸坡度)
float oceanSlope = TGOceanSlope + TGOceanSlopeVariation * noise;
// 2. 距海距离
float shoreDist = CalculateOceanShoreDistance(x, z);
float shoreFactor = Saturate(2f - 0.05f * Abs(shoreDist));
float islandFactor = Saturate(Sin(TGIslandsFrequency * shoreDist));
float oceanDepth = Saturate(Saturate(-oceanSlope * shoreDist) - 0.85f * islandFactor);
float farFromShore = Saturate(Saturate(0.05f * (-shoreDist - 10f)) - islandFactor);
// 3. 山脉因子
float mountain = CalculateMountainRangeFactor(x, z);
// 4. 丘陵/山脉区域权重
float hillsWeight = (1 - farFromShore) * (1 - shoreFactor) * Squish(mountain, 1 - TGHillsPercentage, 1 - TGMountainsPercentage);
float mountainsWeight = (1 - farFromShore) * Squish(mountain, 1 - TGMountainsPercentage, 1);
// 5. 丘陵噪声
float hillsNoise = SimplexNoise.OctavedNoise(x, z, TGHillsFrequency, TGHillsOctaves, 1.93f, TGHillsPersistence);
float hills = TGHillsStrength * hillsWeight * hillsNoise;
// 6. 山脉噪声
float mountainsNoise = 1.5f * SimplexNoise.OctavedNoise(x, z, TGMountainsDetailFreq, TGMountainsDetailOctaves, 1.98f, persistence) - 0.5f;
float mountains = TGMountainsStrength * mountainsWeight * mountainsNoise;
// 7. 河流
float riverNoise = Saturate(1.5f - riverWidth * Abs(2f * SimplexNoise.OctavedNoise(x, z, 0.001f, 4, 2f, 0.5f) - 1f));
float rivers = TGRiversStrength * riverNoise;
// 8. 组合
float baseHeight = -50f * oceanDepth + TGHeightBias;
float result = baseHeight + Lerp(0, 8, f) + Lerp(0, -6, f2) + mountains + hills;
result = Min(Lerp(result, Lerp(-2, -4, ...), rivers), result);
return Math.Clamp(64f + result, 10f, 251f);
}温湿度计算关键细节
csharp
// 温度:5层八度噪声,频率0.0015/TGBiomeScaling
// 偏移-1.1使结果偏向寒冷(约70%区域温度≤7)
// 最终结果 × 16 后取整,范围0~15
int temperature = Clamp(
(int)(Saturate(3f * noise - 1.1f + tempOffset/16f) * 16f),
0, 15
);
// 湿度:5层八度噪声,频率0.0012/TGBiomeScaling
// 偏移-0.9使结果偏向干燥(约65%区域湿度≤7)
int humidity = Clamp(
(int)(Saturate(3f * noise - 0.9f + humidOffset/16f) * 16f),
0, 15
);地表方块判定完整逻辑
csharp
void GenerateSurface(TerrainChunk chunk) {
// 遍历每个x,z列,从顶向下找到第一个非透明方块
int topBlock = FindTopmostSolidBlock(i, j);
int temperature = terrain.GetTemperature(x, z);
int humidity = terrain.GetHumidity(x, z);
int surfaceBlock;
if (topBlock == 4) { // 砂岩表面
// 温和气候→石灰岩,极端气候→沙子
surfaceBlock = (temperature > 4 && temperature < 7) ? 6 : 7;
} else {
int tempBand = temperature / 4; // 温度带0~3
int blockAbove = GetBlockAbove(topBlock);
surfaceBlock =
// 高海拔冻结→冰雪
(y > 120 && IsPlaceFrozen(temperature, y)) ? 62 :
// 特定条件→玄武岩(罕见)
((y < 66 || y == 84 + tempBand || y == 103 + tempBand) && humidity == 9 && temperature % 6 == 1) ? 66 :
// 水下高湿→沉积物
(blockAbove == 18 && humidity > 8 && humidity % 2 == 0 && temperature % 3 == 0) ? 72 :
// 默认→草地
2;
}
// 覆盖层厚度
int thickness;
if (surfaceBlock == 62) { // 冰雪
thickness = Clamp(-temperature, 1, 7); // 越冷越厚
} else {
// 海拔越高、山脉越陡、湿度越低→覆盖层越薄
float heightFactor = Saturate((y - 100f) * 0.05f);
float f = Saturate(mountainFactor * heightFactor + surfaceMultiplier * heightFactor);
thickness = Random(Int(Lerp(4, 0, f), Lerp(7, 0, f)));
}
// 将覆盖层方块写入区块
ReplaceTopBlocks(surfaceBlock, thickness);
}沙漠标志判定
csharp
// 在 GenerateTerrain 中决定地下方块类型
bool isDesert = (temperatureFast > 8 && humidityFast < 8 && mountainFactor < 0.97f)
|| (Math.Abs(oceanShoreDistance) < 16f && mountainFactor < 0.97f);
// 沙漠/海岸:浅层砂岩(4) → 中层花岗岩(3) → 深层玄武岩(67)
// 普通: 浅层花岗岩(3) → 深层玄武岩(67)
// 沙漠的砂岩层厚度由 mountainFactor 和 humidity 决定:
// thickness1 = Lerp(100, 0, mountainFactor - 0.01 * humidity) // 砂岩层
// thickness2 = Lerp(300, 30, mountainFactor - 0.01 * humidity) // 花岗岩层季节温度曲线数据
csharp
// TerrainUpdater.cs 中的 FloatCurve 定义
public FloatCurve TemperatureCurve = new(
new Vector2(0f, 0f), // 盛夏:无修正
new Vector2(0.125f, 0f), // 仲夏:无修正
new Vector2(0.25f, 0f), // 初秋:无修正
new Vector2(0.375f, -4f), // 中秋:-4
new Vector2(0.5f, -12f), // 初冬:-12
new Vector2(0.625f, -24f), // 隆冬:-24(全年最冷)
new Vector2(0.75f, -12f), // 初春:-12
new Vector2(0.875f, -4f), // 仲春:-4
new Vector2(1f, 0f) // 回到盛夏:0
);
// 湿度不受季节影响
public FloatCurve HumidityCurve = new(
new Vector2(0f, 0f),
new Vector2(1f, 0f) // 全年不变
);季节温度的传递链
WorldSettings.TimeOfYear (0~1)
→ TerrainUpdater.Update()
→ TemperatureCurve.Sample(timeOfYear) → SeasonTemperature
→ Terrain.SeasonTemperature = num
→ Terrain.GetSeasonalTemperature(x, z) = GetTemperature(x, z) + SeasonTemperature
→ SubsystemWeather.IsPlaceFrozen(seasonalTemp, y)
→ 决定降水类型(雪/雨/无)和冰雪生成平坦模式的影响
平坦模式(FlatContinent/FlatIsland)通过降低山脉和丘陵强度来实现平坦效果。虽然源码中 TerrainContentsGenerator23.cs 的 TG 参数在构造函数中统一设置,但平坦模式会在外部调整以下参数:
- 山脉强度大幅降低(地形不会出现Y=200+的高山)
- 丘陵强度降低(地势起伏更平缓)
- 整体高度更接近海平面(Y=64)
方块索引速查
| 索引 | 方块名 | 用途 |
|---|---|---|
| 0 | 空气 | — |
| 1 | 基岩 | 不可破坏,Y=0~4 |
| 2 | 泥土 | 常见地表 |
| 3 | 花岗岩 | 常见地下岩石 |
| 4 | 砂岩 | 沙漠地下岩石 |
| 6 | 石灰岩 | 温和气候地表 |
| 7 | 沙子 | 沙漠地表 |
| 8 | 草地 | 草地 |
| 18 | 水 | 海洋/河流/湖泊 |
| 61 | 雪 | 地面覆雪 |
| 62 | 冰 | 水面冻结 |
| 66 | 玄武岩 | 深层岩石/特殊地表 |
| 67 | 玄武岩 | 深层地下岩石 |
| 72 | 沉积物 | 水底特殊方块 |
| 127 | 仙人掌 | 沙漠植被 |
IyDlnLDlvaLkuI7nvqTns7sKCuS9oOeahOS4lueVjOS7jumAieaLqeWcsOW9oueUn+aIkOaooeW8j+eahOmCo+S4gOWIu+WwseW8gOWni+WhkemAoOS6huOAguWbm+enjeaooeW8j+WGs+WumuS6huWkp+mZhui9ruW7k+OAgeWym+Wxv+WIhuW4g+WSjOaVtOS9k+WcsOWKv+mjjuagvO+8jOaYr+aVtOS4quWcsOW9ouezu+e7n+eahOesrOS4gOWdl+Wfuuefs+OAggoKOjo6IGluZm8g6ZiF6K+75o+Q56S6CuacrOiKguWGheWuuei/h+WkmuS4lOi+g+S4uuWkjeadgu+8jOWQjue7ree8luiAheS8muWinuW8uuWPr+ivu+aAp++8jOiuqeavj+S9jeeOqeWutumDveiDveeQhuino+OAggo6OjoKCiMjIOWcsOW9oueUn+aIkOaooeW8jwoK5Y6f54mI5ri45oiP5o+Q5L6b5Zub56eN5Zyw5b2i55Sf5oiQ5qih5byP77yaCgoKfCDluo/lj7cgfCDlnLDlvaLnsbvlnosgfCDmnprkuL7lgLwgfCDmj4/ov7AgfCDlpIfms6ggfAp8Oi0tLTp8Oi0tLXw6LS0tfDotLS18Oi0tLXwKfCAxIHwg5aSn6ZmGIHwgQ29udGluZW50IHwg5qCH5YeG5aSn6ZmG5Zyw5b2i77yM5pyJ5rW35rSL5ZKM6ZmG5ZywIHwg5Y6f54mIIHwKfCAyIHwg5bKb5bG/IHwgSXNsYW5kIHwg54us56uL5bKb5bG/5Zyw5b2iIHwg5Y6f54mIIHwKfCAzIHwg5bmz5Z2m5aSn6ZmGIHwgRmxhdENvbnRpbmVudCB8IOW5s+WdpuWMlueahOWkp+mZhuWcsOW9oiB8IOWOn+eJiCB8CnwgNCB8IOW5s+WdpuWym+WxvyB8IEZsYXRJc2xhbmQgfCDlubPlnabljJbnmoTlspvlsb/lnLDlvaIgfCDljp/niYggfAp8IDUgfCDomZrnqbogfCBOaWhpbGl0eSB8IOWujOWFqOepuueahOS4lueVjCB8IOiBlOacuueJiCB8CnwgNiB8IOS8mOWMluWcsOW9oiB8IEJldHRlciB8IOS8mOWMlueJiOWcsOW9ou+8jOWinuWKoOebhuWcsOeUn+aIkCB8IOiBlOacuueJiCB8CnwgNyB8IOaegeW3qOWMliB8IEh1Z2UgfCDlt6jlnovlnLDlvaLvvIzmtbflubPpnaLpmY3kvY4gfCDogZTmnLrniYggfAp8IDggfCDmnoHlhrvpq5jljp8yNTYgfCBDYXZlIHwg5YCS572u5Zyw5b2i77yM6aG26YOo5Li65Z+65bKpIHwg6IGU5py654mIIHwKfCA5IHwg56m65bKbIHwgU2t5SXNsYW5kIHwg5ryC5rWu5Zyo56m65Lit55qE5bKb5bG/IHwg6IGU5py654mIIHwKfCAxMCB8IOWfuuWyqeWcsOW9oiB8IEJlZHJvY2sgfCDkvY7pq5jluqbln7rlsqnpqqjmnrblpKfpmYYgfCDogZTmnLrniYggfAp8IDExIHwg55+z5aS05Zyw5b2iIHwgU3RvbmUgfCDooqvnn7PlpLTljIXlm7TnmoTlspvlsb/lnLDlvaIgfCDogZTmnLrniYggfAoKPiAqKumAmuS/l+ino+mHiioq77ya5aSn6ZmG5qih5byP6YCC5ZCI5Zac5qyi6ZW/6YCU5o6i6Zmp55qE546p5a6277yM5LiW55WM55CG6K665LiK5peg6ZmQ5aSn77yb5bKb5bG/5qih5byP5YiZ57uZ5L2g5LiA5Liq5pyJ6L6555WM55qE55Sf5a2Y56m66Ze077yM6YCC5ZCI5oyR5oiY6Ieq5oiR44CC5bmz5Z2m5qih5byP5YeP5bCR5LqG5p6B56uv5Zyw5b2i77yM5pu06YCC5ZCI5bu6562R5YWa44CCCgojIyDkuJbnlYzorr7nva7lj4LmlbAKCj4g5Zyo5Yib5bu65LiW55WM5pe277yM5L2g5Y+v5Lul6LCD5pW05rip5bqm44CB5rm/5bqm44CB5rW35bmz6Z2i562J5Y+C5pWw44CC6L+Z5Lqb6K6+572u55u05o6l5b2x5ZON576k57O75YiG5biD5ZKM5Zyw5b2i5aSW6KeC77yM5piv5a6a5Yi25YyW5L2g55Sf5a2Y5L2T6aqM55qE5YWz6ZSu5peL6ZKu44CCCgrku6XkuIvlj4LmlbDmnaXoh6ogYFdvcmxkU2V0dGluZ3MuY3Ng77yM546p5a625Y+v5Zyo5Yib5bu65LiW55WM5pe26LCD5pW077yaCgp8IOWPguaVsCB8IOm7mOiupOWAvCB8IOiMg+WbtCB8IOS9nOeUqCB8CnwtLS0tLS18LS0tLS0tLS18LS0tLS0tfC0tLS0tLXwKfCDmtbflubPpnaLpq5jluqYgfCAwIHwgLTY0IH4gKzE5MSB8IOa1t+W5s+mdouWBj+enu++8jOato+WAvOWNh+mrmOa1t+W5s+mdoiB8Cnwg5rip5bqmIHwgMCB8IC0xNiB+ICsxNiB8IOa4qeW6puWBj+enu++8iC0xNn4rMTbvvInvvIzmraPlgLzkvb/kuJbnlYzmm7Tng60gfAp8IOa5v+W6piB8IDAgfCAtMTYgfiArMTYgfCDmub/luqblgY/np7vvvIgtMTZ+KzE277yJ77yM5q2j5YC85L2/5LiW55WM5pu05rm/5ramIHwKfCDnlJ/niannvqTns7vlpKflsI8gfCAxLjAgfCAwLjAxIH4gKzMyIHwg55Sf54mp576k57O757yp5pS+5Zug5a2Q77yM6LaK5aSn5YiZ576k57O76Z2i56ev6LaK5aSnIHwKfCDlspvlsb/lpKflsI8gfCAoNDAwLCA0MDApIHwgMSB+ICsyNTAwIHwg5bKb5bG/5qih5byP5LiL5bKb5bG/55qE5bC65a+4IHwKfCDmtbflsrjnur/nspfns5nluqYgfCAwLjUgfCAwIH4gMSB8IOW5s+WdpuaIluW5s+WdpuWym+Wxv+aooeW8j+S4i+a1t+WyuOe6v+eyl+ezmeW6piB8CgrlhbbkuK3muKnluqblgY/np7vlkozmub/luqblgY/np7vkvJrnm7TmjqXlj6DliqDliLDmuKnmub/luqborqHnrpfnu5PmnpzkuIrjgILkvovlpoLmuKnluqblgY/np7srOOS8muiuqeWOn+acrOWvkuWGt+eahOWMuuWfn+WPmOW+l+a4qeWSjO+8jOebuOW9k+S6juaKiuaVtOS4quS4lueVjOeahOa4qeW6puW4puWQkei1pOmBk+aWueWQkeaOqOenu+OAggoKIyMg5Zyw5b2i6auY5bqm6K6h566XCgo+IOavj+S4gOS4quaWueWdl+eahCBZIOWdkOagh+mDveS4jeaYr+maj+acuueahO+8jOiAjOaYr+eUseWkmuWxguWZquWjsOWHveaVsOWPoOWKoOiAjOaIkOOAgueQhuino+mrmOW6puiuoeeul++8jOS9oOWwseiDvemihOWIpOWTqumHjOacieWxseOAgeWTqumHjOaYr+iwt+OAgeWTqumHjOWPr+iDveiXj+edgOays+a1geOAggoKIyMjIOaguOW/g+acuuWItgoK6auY5bqm55qE5Z+656GA5YC85Li6Kio2NCoq77yI5Y2z5rW35bmz6Z2i77yJ77yM5pyA57uI6auY5bqm6KKr6ZmQ5Yi25ZyoKioxMH4yNTEqKuS5i+mXtOOAgumrmOW6pueahOWPmOWMlueUseWbm+S4quWboOe0oOWPoOWKoOiAjOaIkO+8mgoKJCQKXHRleHR76auY5bqmfSA9IFxtYXRocm17Y2xhbXB9XEJpZyhcLDY0ICsgXHRleHR75rW35rSL5Z2h5bqmfSArIFx0ZXh0e+S4mOmZtX0gKyBcdGV4dHvlsbHohIl9ICsgXHRleHR75rKz5rWBfSAtIFx0ZXh0e+a1t+a0i+a3seW6pn0sXCAxMCxcIDI1MVwsXEJpZykKJCQKCj4gKipjbGFtcCh4LCBtaW4sIG1heCkqKu+8mumZkOWItuWHveaVsOOAguiLpSB4IOWwj+S6jiBtaW4g5YiZ6L+U5ZueIG1pbu+8jOiLpSB4IOWkp+S6jiBtYXgg5YiZ6L+U5ZueIG1heO+8jOWQpuWImei/lOWbniB4IOacrOi6q+OAgui/memHjOaKiuWcsOW9oumrmOW6pumZkOWItuWcqCAxMFx+MjUxIOS5i+mXtO+8jOmYsuatouWHuueOsOaegeerr+WAvOOAggoK5YW25Lit5ZCE5Y+C5pWw5ZCr5LmJ77yaCgp8IOWPguaVsCB8IOWQq+S5iSB8IOmAmuS/l+eQhuinoyB8CnwtLS0tLS18LS0tLS0tfC0tLS0tLS0tLS18CnwgKirmtbfmtIvlnaHluqYqKiB8IOa1t+WyuOe6v+WQkea3sea1t+i/h+a4oeeahOWdoeW6pu+8iOWfuuehgOWAvDAuMDA277yJIHwg6LaK6Z2g6L+R5rW35bK457q/77yM5Zyw5Yq/6LaK5bmz57yT5Zyw5LiL6ZmN5Yiw5rW35bmz6Z2i5Lul5LiLIHwKfCAqKuS4mOmZtSoqIHwg5LiY6Zm15Yy65Z+f55qE6LW35LyP5bmF5bqm77yI5by65bqmMzLvvIkgfCDotbfkvI/ovoPlsI/vvIzpgILlkIjlu7rpgKDmiL/lsYvlkozlhpznlLAgfAp8ICoq5bGx6ISJKiogfCDlsbHohInljLrln5/nmoTotbfkvI/luYXluqbvvIjlvLrluqYyMjDvvIkgfCDotbfkvI/mnoHlpKfvvIzog73liLDovr5ZPTIwMOS7peS4iueahOmrmOW6piB8CnwgKirmsrPmtYEqKiB8IOays+iwt+S4i+WIh+eahOa3seW6puS/ruato++8iOW8uuW6pjHvvIkgfCDmsrPmtYHkvJrlnKjlnLDlvaLkuIrliIflh7rkuIvpmbfnmoTmsrPosLcgfAp8ICoq5rW35rSL5rex5bqmKiogfCDnprvlsrjotorov5zmtbfluorotormt7EgfCDmjqfliLbmt7HmtbfljLrln5/nmoTkuIvmsonnqIvluqYgfAoKIyMjIOWcsOW9ouS4ieahowoK5LiW55WM6KKr5YiG5Li65LiJ56eN5Zyw5b2i5Yy65Z+f77yM55SxIuWxseiEieWboOWtkCLlhrPlrprvvIzlj5blgLwwfjHjgILlsbHohInlm6DlrZDnlLHkvY7popHlmarlo7DnlJ/miJDvvJoKCiQkClx0ZXh0e+WxseiEieWboOWtkH0gPSBcbWF0aHJte25vaXNlfSh4LFwgeixcIFx0ZXh0e+mikeeOh309MC4wMDA2L1x0ZXh0e+e+pOezu+e8qeaUvn0pCiQkCgo+ICoqbm9pc2UoeCwgeiwgZnJlcSkqKu+8muWZquWjsOWHveaVsO+8jOagueaNruWdkOaghyAoeCwgeikg5ZKM6aKR546H55Sf5oiQ5LiA5Liq55yL5Ly86ZqP5py65L2G6L+e57ut5bmz5ruR55qE5YC877yIMFx+Me+8ieOAguebuOmCu+WdkOagh+eahOWAvOebuOi/ke+8jOi/nOemu+WdkOagh+eahOWAvOW3ruW8guWkp++8jOWboOatpOiDveeUn+aIkOiHqueEtueahOi1t+S8j+WcsOW9ouiAjOmdnuS5seeggeiIrOeahOmUr+m9v+OAggoK6aKR546H5p6B5L2O5oSP5ZGz552A5bGx6ISJ6Z2e5bi45bqe5aSn77yM5LiA5Liq5bGx6ISJ5Yy65Z+f5Y+v5Lul57u15bu25pWw55m+5qC844CC5qC55o2u5bGx6ISJ5Zug5a2Q55qE5aSn5bCP77yM5Zyw5b2i6KKr5YiG5Li65LiJ5qGj77yaCgp8IOWxseiEieWboOWtkOiMg+WbtCB8IOWcsOW9ouexu+WeiyB8IOWNoOavlCB8IOeJueW+gSB8CnwtLS0tLS0tLS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tfC0tLS0tLXwKfCAwIH4gMC43IHwgKirlubPljp8qKiB8IOe6pjcwJSB8IOWcsOWKv+W5s+e8k++8jOa1t+aLlOaOpei/kea1t+W5s+mdoiB8CnwgMC43IH4gMC44NyB8ICoq5LiY6Zm1KiogfCDnuqYxNyUgfCDmmI7mmL7otbfkvI/vvIzpgILlkIjlu7rlnKjlsbHlnaHmiJblsbHosLfkuK0gfAp8IDAuODcgfiAxIHwgKirlsbHohIkqKiB8IOe6pjEzJSB8IOmrmOiAuOWFpeS6ke+8jOa1t+aLlOWPr+i+vjIwMOS7peS4iiB8Cgo+IOWxseiEieWMuuWfn+iZveeEtuWPquWNoOe6pjEzJe+8jOS9humrmOW6puWinuW5hemrmOi+vjIyMO+8jOaYr+W5s+WOn+eahOaVsOWAjeOAguaJgOS7peW9k+S9oOWPkeeOsOWcsOmdouW8gOWni+WJp+eDiOi1t+S8j+aXtu+8jOS9oOWPr+iDveW3sue7j+i4j+WFpeS6huWxseiEieWMuuOAggoKIyMjIOe+pOezu+Wkp+Wwj+WvueWcsOW9oueahOW9seWTjQoK576k57O75aSn5bCP6K6+572u5Lya5b2x5ZON5Zyw5b2i54m55b6B55qE5bC65bqm44CC576k57O757yp5pS+5o6n5Yi25rip5rm/5bqm5ZKM5bGx6ISJ5Zmq5aOw55qE6YeH5qC36aKR546H77yM55u05o6l5b2x5ZON576k57O755qE5aSn5bCP77yaCgokJApcdGV4dHvnvqTns7vnvKnmlL59ID0gXHRleHR75Z+656GA57O75pWwfSBcdGltZXMgXHRleHR7576k57O75aSn5bCPfQokJAoKfCDmqKHlvI8gfCDln7rnoYDns7vmlbAgfCDmlYjmnpwgfAp8LS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tfAp8ICoq5aSn6ZmG5qih5byPKiogfCAxLjc1IHwg576k57O75pu05aSn77yM6L+H5rih5pu05bmz57yT77yM6LWw5b6I6L+c5omN5Lya5o2i5rCU5YCZIHwKfCAqKuWym+Wxv+aooeW8jyoqIHwgMS4wIHwg576k57O75pu05bCP77yM5Y+Y5YyW5pu06aKR57mB77yM5bCP6IyD5Zu05YaF5bCx6IO95L2T6aqM5aSa56eN5rCU5YCZIHwKCgoKIyMg5rip5bqm5LiO5rm/5bqmCgo+IOa4qeW6puWSjOa5v+W6puaYr+WGs+Wumue+pOezu+exu+Wei+eahOS4pOWkp+aguOW/g+WPmOmHj+OAguWug+S7rOS4jeaYr+WbuuWumuWAvO+8jOiAjOaYr+maj+WdkOagh+i/nue7reWPmOWMlueahOWZquWjsOWcuu+8jOWcqOS4lueVjOeahOavj+S4quinkuiQvee7hOWQiOWHuueLrOeJueeahOawlOWAmeOAggoKCgo8ZGV0YWlscz4KPHN1bW1hcnk+5rip5bqm5LiO5rm/5bqm6K6h566X5Luj56CBPC9zdW1tYXJ5PgoKIyMjIOa4qeW6puiuoeeulwoK5rip5bqm5Y+W5YC8ICoqMH4xNSoq77yM55SxIGBDYWxjdWxhdGVUZW1wZXJhdHVyZWAg5pa55rOV55Sf5oiQ77yaCgpgYGBjc2hhcnAKcHVibGljIGludCBDYWxjdWxhdGVUZW1wZXJhdHVyZShmbG9hdCB4LCBmbG9hdCB6KSA9PiBNYXRoLkNsYW1wKAogICAgKGludCkoTWF0aFV0aWxzLlNhdHVyYXRlKAogICAgICAgICAgICAzZiAqIFNpbXBsZXhOb2lzZS5PY3RhdmVkTm9pc2UoeCwgeiwgMC4wMDE1ZiAvIFRHQmlvbWVTY2FsaW5nLCA1LCAyZiwgMC42ZikKICAgICAgICAgICAgLSAxLjFmICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8g5YGP5ZCR5a+S5Ya355qE5YGP56e76YePCiAgICAgICAgICAgICsgbV93b3JsZFNldHRpbmdzLlRlbXBlcmF0dXJlT2Zmc2V0IC8gMTZmICAvLyDnjqnlrrborr7nva7nmoTmuKnluqblgY/np7sKICAgICAgICApCiAgICAgICAgKiAxNmYpLAogICAgMCwgMTUKKTsKYGBgCgojIyMg5rm/5bqm6K6h566XCgrmub/luqblj5blgLwgKiowfjE1KirvvIznlLEgYENhbGN1bGF0ZUh1bWlkaXR5YCDmlrnms5XnlJ/miJDvvJoKCmBgYGNzaGFycApwdWJsaWMgaW50IENhbGN1bGF0ZUh1bWlkaXR5KGZsb2F0IHgsIGZsb2F0IHopID0+IE1hdGguQ2xhbXAoCiAgICAoaW50KShNYXRoVXRpbHMuU2F0dXJhdGUoCiAgICAgICAgICAgIDNmICogU2ltcGxleE5vaXNlLk9jdGF2ZWROb2lzZSh4LCB6LCAwLjAwMTJmIC8gVEdCaW9tZVNjYWxpbmcsIDUsIDJmLCAwLjZmKQogICAgICAgICAgICAtIDAuOWYgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyDlgY/lkJHlubLnh6XnmoTlgY/np7vph48KICAgICAgICAgICAgKyBtX3dvcmxkU2V0dGluZ3MuSHVtaWRpdHlPZmZzZXQgLyAxNmYgICAgIC8vIOeOqeWutuiuvue9rueahOa5v+W6puWBj+enuwogICAgICAgICkKICAgICAgICAqIDE2ZiksCiAgICAwLCAxNQopOwpgYGAKPC9kZXRhaWxzPgoKIyMjIOa4qeW6pgoK5rip5bqm5Y+W5YC8KiowfjE1KirvvIzmlbDlgLzotorpq5jotorng63jgILmuLjmiI/kuJbnlYznmoTmuKnluqbliIbluIPlgY/lkJHlr5LlhrfvvIznuqY3MCXnmoTljLrln5/muKnluqbkuI3otoXov4c344CC5rW35ouU5ZKM5a2j6IqC5Lmf5Lya5b2x5ZON5a6e6ZmF5rip5bqm77yI5ZCO6Z2i6K+m6L+w77yJ44CCCgrmuKnluqbnlLHlmarlo7Dph4fmoLflkI7nu4/ov4flgY/np7vlkozmmKDlsITlvpfliLDvvJoKCiQkClx0ZXh0e+a4qeW6pn0gPSBcbWF0aHJte2NsYW1wfVxCaWcoXCxcbWF0aHJte3NhdH1cYmlnKDMgXHRpbWVzIFx0ZXh0e+WZquWjsH0gLSAxLjEgKyBcdGZyYWN7XHRleHR75rip5bqm5YGP56e7fX17MTZ9XGJpZykgXHRpbWVzIDE2LFwgMCxcIDE1XCxcQmlnKQokJAoKPiAtICoqY2xhbXAoeCwgbWluLCBtYXgpKirvvJrpmZDliLblh73mlbDjgILoi6UgeCDlsI/kuo4gbWluIOWImei/lOWbniBtaW7vvIzoi6UgeCDlpKfkuo4gbWF4IOWImei/lOWbniBtYXjvvIzlkKbliJnov5Tlm54geCDmnKzouqvjgILov5nph4zmiormuKnluqbpmZDliLblnKggMFx+MTUg5LmL6Ze077yM6Ziy5q2i5Ye6546w5p6B56uv5YC844CCCj4gLSAqKnNhdCh4KSoq77ya6aWx5ZKM5Ye95pWw77yI5ZCMIFNhdHVyYXRl77yJ44CC6IulIHg8MCDliJnov5Tlm54gMO+8jOiLpSB4PjEg5YiZ6L+U5ZueIDHvvIzlkKbliJnov5Tlm54geOOAguS9nOeUqOaYr+aKiuaVsOWAvOmZkOWItuWcqCAwXH4xIOiMg+WbtOWGhe+8jOmYsuatouWQjue7reS5mOazlei2iueVjAoK5YW25Lit77ya5Zmq5aOw5Li66ZqP5Z2Q5qCH5Y+Y5YyW55qE6ZqP5py65YC877yIMH4x77yJ77ybKiotMS4xKirmmK/lgY/np7vph4/vvIzkvb/nu5PmnpzlgY/lkJHlr5LlhrfvvJsqKua4qeW6puWBj+enuyoq5piv546p5a625Zyo5Yib5bu65LiW55WM5pe26K6+572u55qE5Y+C5pWw77ybYHNhdGDooajnpLrlsIblgLzpmZDliLblnKgwfjHojIPlm7TlhoXjgIIKCnwg5rip5bqm6IyD5Zu0IHwg5rCU5YCZ5o+P6L+wIHwKfC0tLS0tLS0tLS18LS0tLS0tLS0tLXwKfCAwfjMgfCDlr5LluKbvvIznu4jlubTkvY7muKnvvIzlnLDooajluLjooqvlhrDpm6ropobnm5YgfAp8IDR+NyB8IOa4qeW4pu+8jOWbm+Wto+WIhuaYju+8jOiNieWcsOWSjOagkeacqOacgOW4uOingSB8CnwgOH4xMSB8IOaalua4qeW4pi/kuprng63luKbvvIzmuKnmmpblubLnh6XmiJbmuKnmmpbmub/mtqYgfAp8IDEyfjE1IHwg54Ot5bim77yM54KO54Ot77yM5Y+v6IO95Ye6546w5rKZ5ryg5oiW6IyC5a+G5Lib5p6XIHwKCiMjIyDmub/luqYKCua5v+W6puWPluWAvCoqMH4xNSoq77yM5pWw5YC86LaK6auY6LaK5rm/5ram44CC5ri45oiP5LiW55WM55qE5rm/5bqm5YiG5biD5YGP5ZCR5bmy54el77yM57qmNjUl55qE5Yy65Z+f5rm/5bqm5LiN6LaF6L+HN+OAggoK5rm/5bqm6K6h566X6YC76L6R5LiO5rip5bqm57G75Ly877yM5Y+q5piv5YGP56e76YeP5LiN5ZCM77yaCgokJApcdGV4dHvmub/luqZ9ID0gXG1hdGhybXtjbGFtcH1cQmlnKFwsXG1hdGhybXtzYXR9XGJpZygzIFx0aW1lcyBcdGV4dHvlmarlo7B9IC0gMC45ICsgXHRmcmFje1x0ZXh0e+a5v+W6puWBj+enu319ezE2fVxiaWcpIFx0aW1lcyAxNixcIDAsXCAxNVwsXEJpZykKJCQKCj4gLSAqKmNsYW1wKHgsIG1pbiwgbWF4KSoq77ya6ZmQ5Yi25Ye95pWw44CC6IulIHgg5bCP5LqOIG1pbiDliJnov5Tlm54gbWlu77yM6IulIHgg5aSn5LqOIG1heCDliJnov5Tlm54gbWF477yM5ZCm5YiZ6L+U5ZueIHgg5pys6Lqr44CC6L+Z6YeM5oqK5rm/5bqm6ZmQ5Yi25ZyoIDBcfjE1IOS5i+mXtO+8jOmYsuatouWHuueOsOaegeerr+WAvOOAggo+IC0gKipzYXQoeCkqKu+8mumlseWSjOWHveaVsO+8iOWQjCBTYXR1cmF0Ze+8ieOAguiLpSB4PDAg5YiZ6L+U5ZueIDDvvIzoi6UgeD4xIOWImei/lOWbniAx77yM5ZCm5YiZ6L+U5ZueIHjjgILkvZznlKjmmK/miormlbDlgLzpmZDliLblnKggMFx+MSDojIPlm7TlhoXvvIzpmLLmraLlkI7nu63kuZjms5XotornlYzjgIIKCuWFtuS4re+8mioqLTAuOSoq5piv5YGP56e76YeP77yM5L2/57uT5p6c5YGP5ZCR5bmy54el77yI5q+U5rip5bqm55qELTEuMeeVpeWwj++8jOaJgOS7peS4lueVjOaVtOS9k+avlCLlgY/lhrci5pu0IuWBj+W5siLvvInjgIIKCnwg5rm/5bqm6IyD5Zu0IHwg5rCU5YCZ5o+P6L+wIHwKfC0tLS0tLS0tLS18LS0tLS0tLS0tLXwKfCAwfjMgfCDmnoHlubLnh6XvvIzmspnmvKDmiJbojZLljp8gfAp8IDR+NyB8IOS4reetiea5v+W6pu+8jOiNieWOn+aIlua4qeW4puajruaelyB8CnwgOH4xMSB8IOa5v+a2pu+8jOayvOazveaIlueDreW4pumbqOaelyB8CnwgMTJ+MTUgfCDmnoHmub/mtqbvvIzluLjlubTpmY3msLTlhYXmspsgfAoKIyMjIOa4qea5v+W6pue7hOWQiOWGs+Wumue+pOezuwoK5rip5bqm5ZKM5rm/5bqm5YWx5ZCM5Yaz5a6a5L2g55y85YmN55qE5pmv6LGh77yaCgp8IOa4qeW6piB8IOa5v+W6piB8IOeOr+Wig+eJueW+gSB8IOWFuOWei+akjeiiqyB8CnwtLS0tLS18LS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tLS0tLXwKfCDpq5jvvIg+OO+8iSB8IOS9ju+8iDw277yJIHwgKirmspnmvKAqKu+8muWcsOihqOS4uuaymeWtkO+8jOaYvOWknOa4qeW3ruWkpyB8IOS7meS6uuaOjCB8Cnwg6auY77yIPjjvvIkgfCDpq5jvvIg+OO+8iSB8ICoq54Ot5bim5Lib5p6XKirvvJrmuKnmmpbmub/mtqbvvIzpmY3msLTkuLDlr4wgfCDojILlr4bpmJTlj7bmoJEgfAp8IOS4re+8iDR+OO+8iSB8IOS4re+8iDR+OO+8iSB8ICoq5rip5bimKirvvJrlm5vlraPliIbmmI7vvIzojYnlnLDkuLrkuLsgfCDmma7pgJrmoJHmnKjjgIHojYnkuJsgfAp8IOS9ju+8iDw077yJIHwg5Lu75oSPIHwgKirlr5LluKYv6Zuq5Y6fKirvvJrlnLDooajnp6/pm6rvvIzmpI3niannqIDlsJEgfCDnqIDnlo/pkojlj7bmoJEgfAp8IOS7u+aEjyB8IOS7u+aEjyB8ICoq6auY5rW35ouUKirvvJrmtbfmi5Totorpq5jotorlhrfvvIzlsbHpobbnu4jlubTnp6/pm6ogfCDml6DmpI3ooqsgfAoKPiDmtbfmi5Tlr7nmuKnluqbnmoTlvbHlk43pnZ7luLjmmL7okZfjgILljbPkvb/lnLDlpITng63luKbvvIzlj6ropoHniKzlvpfotrPlpJ/pq5jvvIzlsbHpobbkvp3nhLbkvJrooqvlhrDpm6ropobnm5bjgILlj43ov4fmnaXvvIzlnLDkuIvmt7HlpITkvJrmuKnmmpblvpflpJrvvIzmt7HlsYLnn7/mtJ7msLjov5zkuI3kvJrnu5PlhrDjgIIKCiMjIOWcsOihqOS4juWcsOS4i+aWueWdlwoKPiDkvaDohJrkuIvouKnnnYDnmoTmlrnlnZfvvIzlkozlnLDlupXmt7HlpITnmoTlsqnnn7PvvIzpg73kuI3mmK/pmo/mnLrliIbphY3nmoTjgILmuKnluqbjgIHmub/luqbjgIHmtbfmi5Tlkozot53mtbfot53nprvlhbHlkIzlhrPlrprkuobkuIDniYfljLrln5/nlLHku4DkuYjmlrnlnZfmnoTmiJDjgIIKCiMjIyDlnLDkuIvliIblsYIKCuWcsOS4i+Wyqeefs+WIhuS4uuS4ieWxgu+8jOeUsea1heWIsOa3seOAgmBHZW5lcmF0ZVRlcnJhaW5gIOaWueazleS4remAmui/hyLmspnmvKDmoIflv5ci5Yik5pat5L2/55So5ZOq56eN5YiG5bGC77yaCgokJApcdGV4dHvmspnmvKB9ID0gXEJpZyhcLFx0ZXh0e+a4qeW6pn0gPiA4XCBcdGV4dHvkuJR9XCBcdGV4dHvmub/luqZ9IDwgOFwsXEJpZylcIFx0ZXh0e+aIln1cIFxCaWcoXCx8XHRleHR76Led5rW36Led56a7fXwgPCAxNlwsXEJpZynvvIxccXVhZCBcdGV4dHvkuJR9XCBcdGV4dHvlsbHohInlm6DlrZB9IDwgMC45NwokJAoK5YW25Lit77yaKirmuKnluqYqKuWSjCoq5rm/5bqmKirkuLrlvZPlnLDmsJTlgJnlgLzvvIgwXH4xNe+8ie+8myoq6Led5rW36Led56a7KirkuLror6XkvY3nva7liLDmnIDov5Hmtbflsrjnur/nmoTmoLzmlbDvvJsqKuWxseiEieWboOWtkCoq5Li6IDBcfjEg55qE5Zyw5b2i5Y+C5pWw77yI5o6l6L+RIDEg6KGo56S66auY5bGx5Yy65Z+f77yJ44CC5ruh6Laz5Lu75LiA5p2h5Lu25Y2z5Yik5a6a5Li65rKZ5ryg546v5aKD44CCCgp8IOadoeS7tiB8IOa1heWxgiB8IOS4reWxgiB8IOa3seWxgiB8CnwtLS0tLS18LS0tLS0tfC0tLS0tLXwtLS0tLS18CnwgKirmspnmvKDmiJbmtbflsrjpmYTov5EqKu+8iGBpc0Rlc2VydD10cnVlYO+8iSB8IOegguWyqSB8IOiKseWyl+WyqSB8IOeOhOatpuWyqSB8CnwgKirmma7pgJrljLrln58qKu+8iGBpc0Rlc2VydD1mYWxzZWDvvIkgfCDoirHlspflsqkgfCDoirHlspflsqkgfCDnjoTmrablsqkgfAoKPiDnoILlsqnlj6rlh7rnjrDlnKjmspnmvKDlnLDkuIvmiJbmtbflsrjnur/pmYTov5HjgILlpoLmnpzkvaDlnKjmuKnluKblnLDljLrmjJbliLDkuobnoILlsqnvvIzor7TmmI7kvaDnprvmtbfkuI3ov5zkuobjgIIKCiMjIyDlnLDooajmlrnlnZcKCuWcsOihqOeUseacgOS4iuaWueeahOimhuebluWxguWGs+Wumu+8jGBHZW5lcmF0ZVN1cmZhY2VgIOaWueazleaMieS7peS4i+S8mOWFiOe6p+WIpOWumuWcsOihqOexu+Wei++8mgoKJCQKXHRleHR75Zyw6KGofSA9IFxiZWdpbntjYXNlc30gXHRleHR75Yaw6ZuqfSAmIFx0ZXh0e+iLpX1cIHkgPiAxMjBcIFx0ZXh0e+S4lOivpeWkhOWGu+e7k30gXFwgXHRleHR755+z54Gw5bKpfSAmIFx0ZXh0e+iLpeegguWyqeihqOmdouS4lOa4qeW6pn0gXGluIFs1LDZdIFxcIFx0ZXh0e+aymeWtkH0gJiBcdGV4dHvoi6XnoILlsqnooajpnaLkuJTmuKnluqZ9IFxub3RpbiBbNSw2XSBcXCBcdGV4dHvmsonnp6/nial9ICYgXHRleHR76Iul5Zyo5rC05LiL5LiU5rm/5bqmfSA+IDggXFwgXHRleHR76I2J5ZywfSAmIFx0ZXh0e+WFtuS7luaDheWGte+8iOm7mOiupO+8iX0gXGVuZHtjYXNlc30KJCQKCuWFtuS4re+8mioqeSoq5Li65rW35ouU6auY5bqm77ybKirlhrvnu5MqKuihqOekuuivpeS9jee9ruacieaViOa4qeW6puKJpDDvvIjop4HlkI7mloflhrDpm6rnq6DoioLvvInvvJsqKuegguWyqeihqOmdoioq5oyH5LiL5pa55bKp55+z5Li656CC5bKp77ybKirmsLTkuIsqKuihqOekuuivpeS9jee9ruiiq+awtOimhuebluOAggoKfCDmnaHku7YgfCDlnLDooajmlrnlnZcgfCDor7TmmI4gfAp8LS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tfAp8IOaymea8oOWMuuWfnyB8IOaymeWtkO+8iDfvvIkgfCDpq5jmuKnkvY7mub/njq/looPnmoTlhbjlnovlnLDooaggfAp8IOa4qeWSjOawlOWAmeeahOegguWyqeihqOmdoiB8IOefs+eBsOWyqe+8iDbvvIkgfCDmr5TmspnlrZDmm7TlnZrnoaznmoTlnLDooaggfAp8IOmrmOa1t+aLlOWGu+e7k+WMuiB8IOWGsOmbqu+8iDYy77yJIHwg5rip5bqm6ZmN5Yiw5Yaw54K55Lul5LiL55qE6auY5bGx5oiW5p6B5ZywIHwKfCDmsLTlupUgfCDmsonnp6/nianvvIg3Mu+8iSB8IOawtOS4i+eJueauiuaWueWdlyB8Cnwg6buY6K6k5oOF5Ya1IHwg6I2J5Zyw77yIMu+8iSB8IOacgOW4uOingeOAgeacgOa4qeaalueahOWcsOihqCB8CgrlnLDooajopobnm5blsYLnmoTljprluqbnlLHmtbfmi5TlkozlnLDlvaLotbfkvI/lhbHlkIzlhrPlrprvvJrmtbfmi5Totorpq5jjgIHlnLDlvaLotorpmaHls63vvIzopobnm5blsYLotoroloTvvIzotorlrrnmmJPpnLLlh7rkuIvpnaLnmoTlsqnnn7PjgIIKCiMjIOakjeiiq+eUn+aIkAoKPiDmoJHmnKjjgIHojYnkuJvjgIHku5nkurrmjozigJTigJTlroPku6znmoTlh7rnjrDkuI3mmK/pmo/mhI/nmoTvvIzogIzmmK/ooqvmuKnluqbjgIHmub/luqblkozlnLDooajmlrnlnZfkuKXmoLznrZvpgInov4fnmoTjgILor7vmh4LmpI3ooqvliIbluIPop4TlvovvvIzkvaDlsLHog73ku47lkajlm7TnmoTmpI3nianlj43mjqjlh7rmraTlnLDnmoTmsJTlgJnlj4LmlbDjgIIKCiMjIyDmoJHmnKgKCi0g5qCR5pyo5Y+q55Sf6ZW/5ZyoKirojYnlnLAqKuaIlioq6auY6I2JKirlnLDooajkuIoKLSDmtbfmi5Tlv4XpobsqKumrmOS6jua1t+W5s+mdoioq77yI4omlNjbvvIkKLSDmr4/kuKrljLrlnZfmnIDlpJrnuqY15qO15qCRCi0g5qCR56eN55Sx5b2T5Zyw5rip5bqm5ZKM5rm/5bqm5Yaz5a6aCi0g5qCR5pyo5ZGo5Zu05Zub5qC85LiN6IO95pyJ6Zi75oyh54mpCgojIyMg5LuZ5Lq65o6MCgpgR2VuZXJhdGVDYWN0aWAg5pa55rOV5LuF5Zyo5rKZ5ryg546v5aKD55Sf5oiQ5LuZ5Lq65o6M77yM55Sf5oiQ5p2h5Lu25Li677yaCgokJApcdGV4dHvnlJ/miJDku5nkurrmjox9IFxpZmYgXHRleHR75rm/5bqmfSA8IDZcIFx0ZXh0e+S4lH1cIFx0ZXh0e+a4qeW6pn0gPiA4XCBcdGV4dHvkuJR9XCBcdGV4dHvlnLDooajkuLrmspnlrZB9CiQkCgrlhbbkuK3vvJoqKua5v+W6pioq5ZKMKirmuKnluqYqKuS4uuW9k+WcsOawlOWAmeWAvO+8iDBcfjE177yJ77ybKirlnLDooajkuLrmspnlrZAqKuaYr+W/heimgeadoeS7tu+8jOS7meS6uuaOjOWPquiDveaJjuagueWcqOaymeWtkOS4iuOAggoKLSDlj6rlh7rnjrDlnKg8c3Ryb25nPumrmOa4qe+8iCZndDs477yJ5LiU5bmy54el77yIJmx0OzbvvIk8L3N0cm9uZz7nmoTljLrln58KLSDlv4Xpobvnp43lnKgqKuaymeWtkCoq5LiKCi0g5YW45Z6L55qE5rKZ5ryg5qCH5b+XCgojIyMg6I2J5LiO5qSN54mpCgotIOeUseW9k+WcsOa4qea5v+W6puWSjOWcsOihqOexu+Wei+WFseWQjOWGs+WumgotIOiNieWcsOaWueWdl+WPr+iDvei9rOWPmOS4uumrmOiNieWPmOS9kwotIOS4jeWQjOawlOWAmeW4pueUn+mVv+S4jeWQjOeahOmHjuiKseWSjOiNieS4mwoKIyMg5Yaw6Zuq55Sf5oiQCgo+IOW9k+a4qeW6pumZjeiHs+WGsOeCueS7peS4i++8jOawtOS8mue7k+WGsOOAgeWcsOmdouS8muimhumbquOAguWGsOmbqueahOeUn+aIkOmBteW+quS4peagvOeahOa4qeW6pumYiOWAvO+8jOiAjOi/meS4qumYiOWAvOi/mOmaj+a1t+aLlOWPmOWMluOAggoKIyMjIOa1t+aLlOa4qeW6puS/ruatowoK5rW35ouU5a+55rip5bqm55qE5b2x5ZON5aaC5LiL44CCYFN1YnN5c3RlbVdlYXRoZXIuY3NgIOS4reeahCBgR2V0VGVtcGVyYXR1cmVBZGp1c3RtZW50QXRIZWlnaHRgIOaWueazleWumuS5ieS6huS/ruato+WFrOW8j++8mgoKJCQKXHRleHR75rW35ouU5L+u5q2jfSA9IFxiZWdpbntjYXNlc30gLVxtYXRocm17cm91bmR9XGJpZygwLjAwMDggXHRpbWVzICh5IC0gNjQpXjJcYmlnKSAmIFx0ZXh0e+iLpX1cIHkgPiA2NFwgXHRleHR777yI5rW35bmz6Z2i5Lul5LiK77yM5LqM5qyh5pa56ZmN5rip77yJfSBcXFs2cHRdIFxtYXRocm17cm91bmR9XGJpZygwLjEgXHRpbWVzICg2NCAtIHkpXGJpZykgJiBcdGV4dHvoi6V9XCB5IDwgNjRcIFx0ZXh0e++8iOa1t+W5s+mdouS7peS4i++8jOe6v+aAp+WNh+a4qe+8iX0gXGVuZHtjYXNlc30KJCQKCj4gKipyb3VuZCh4KSoq77ya5Zub6IiN5LqU5YWl5Y+W5pW044CC5oqK6K6h566X57uT5p6c6IiN5YWl5Yiw5pyA5o6l6L+R55qE5pW05pWw77yM5Zug5Li65rip5bqm5L+u5q2j5YC85Zyo5ri45oiP5Lit5Lul5pW05pWw5b2i5byP55Sf5pWI44CCCgrlhbbkuK3vvJoqKnkqKuS4uua1t+aLlOmrmOW6pu+8myoqNjQqKuS4uua1t+W5s+mdouWfuuWHhu+8myoqMC4wMDA4KirlkowqKjAuMSoq5Li66ZmN5ripL+WNh+a4qeezu+aVsOOAgua1t+W5s+mdouS7peS4iuaMieS6jOasoeaWueWKoOmAn+mZjea4qe+8iOi2iumrmOi2iuWGt++8jFk9MjAw5pe25bey6ZmN5ripMTTluqbvvInvvIzmtbflubPpnaLku6XkuIvmjInnur/mgKfljYfmuKnvvIjmr4/pmY3kvY4x5qC85Y2H5ripMC4x5bqm77yM5rex5bGC55+/5rSe5rip5pqW5aaC5pil77yJ44CCCgp8IOa1t+aLlCB8IOa4qeW6puS/ruatoyB8IOmAmuS/l+ino+mHiiB8CnwtLS0tLS18LS0tLS0tLS0tLXwtLS0tLS0tLS0tfAp8IOa1t+W5s+mdou+8iFk9NjTvvIkgfCAwIHwg5peg5b2x5ZONIHwKfCBZPTEwMCB8IC0xIHwg55Wl5b6u5Y+Y5Ya3IHwKfCBZPTE1MCB8IC02IHwg5piO5pi+5Y+Y5Ya3IHwKfCBZPTIwMCB8IC0xNCB8IOmdnuW4uOWvkuWGtyB8Cnwg5pyA6auY54K577yIWT0yNTHvvIkgfCAtMzEgfCDmnoHlr5IgfAp8IOWcsOS4i+a1heWxgu+8iFk9NTDvvIkgfCArMSB8IOWcsOS4i+WPjeiAjOabtOaaliB8Cnwg5pyA5rex5aSE77yIWT0xMO+8iSB8ICs1IHwg5rex5bGC55+/5rSe5rip5pqW5aaC5pilIHwKCj4g5rW35bmz6Z2i5Lul5LiK5q+P5Y2H6auY57qmMzXmoLzvvIzmuKnluqbkuIvpmY0x5bqm44CC5LiA5Liq5Y6f5pys5rip5bqmNeeahOa4qeW4puWMuuWfn++8jOWIsOS6hlk9MTUw55qE6auY5bGx5LiK77yM5pyJ5pWI5rip5bqm5bCx5Y+Y5oiQNS02PS0x77yM5bey57uP5L2O5LqO5Yaw54K577yM5bi45bm056ev6Zuq44CCCgojIyMg5Yaw6Zuq6KaG55uW6KeE5YiZCgpgR2VuZXJhdGVTbm93QW5kSWNlYCDmlrnms5XlnKjkuJbnlYznlJ/miJDml7bmiafooYzjgILlhrvnu5PliKTlrprnlLEgYElzUGxhY2VGcm96ZW5gIOaWueazleWGs+Wumu+8mgoKJCQKXHRleHR75Ya757uTfSBcaWZmIFx0ZXh0e+acieaViOa4qeW6pn0gXGxlIDAKJCQKCiQkClx0ZXh0e+acieaViOa4qeW6pn0gPSBcdGV4dHvln7rnoYDmuKnluqZ9ICsgXHRleHR75rW35ouU5L+u5q2jfQokJAoK5YW25Lit77yaKirln7rnoYDmuKnluqYqKuS4uuivpeS9jee9rueahOe+pOezu+a4qeW6pu+8iDBcfjE177yJ77ybKirmtbfmi5Tkv67mraMqKuS4uuS4iuaWh+eahOa1t+aLlOa4qeW6puS/ruato+WAvOOAguS4pOiAheebuOWKoOiLpeKJpDDvvIzliJnor6XlpITliKTlrprkuLrlhrvnu5PljLrln5/jgIIKCi0g5Ya757uT5Yy65Z+f55qE5rC06Z2i5Lya5Y+Y5oiQKirlhrAqKu+8iDYy77yJ77yM5Yaw6Z2i5LiK5Y+v6IO96KaG6Zuq77yINjHvvIkKLSDlhrvnu5PljLrln5/nmoTmlrnlnZfkuIrmlrnkvJropobnm5YqKumbqioq77yINjHvvIkKLSDlhrDlsYLljprluqYxfjPmoLzvvIznlLHlmarlo7Dpmo/mnLrlhrPlrpoKLSDpm6ropobnm5blsYLljprluqbkuI7muKnluqbnm7jlhbPvvJrotorlhrfotorljpoKCgojIyDljLrlnZfnlJ/miJDmraXpqqQKCj4g5LiA5LiqMTbDlzE255qE5Yy65Z2X5LuO56m655m95Yiw5Y+v5bGF5L2P77yM6ZyA6KaB57uP6L+H5Zub5Liq6Zi25q6155qE5rWB5rC057q/5aSE55CG44CC5q+P5Liq6Zi25q616LSf6LSj5LiN5ZCM55qE5YaF5a6577yM55CG6Kej6L+Z5Liq5rWB56iL5pyJ5Yqp5LqO5o6S5p+l5Zyw5b2i5byC5bi45oiW5byA5Y+R5qih57uE44CCCgp8IOmYtuautSB8IOatpemqpOW6j+WPtyB8IOeUn+aIkOWGheWuuSB8CnwtLS0tLS18LS18LS0tLS0tLS0tLXwKfCAqKumYtuautTEqKiB8IDEgfCDorqHnrpfkuIrljYrljLrlnZfmuKnmub/luqYgfAp8IHwgMiB8IOeUn+aIkOS4iuWNiuWMuuWdl+WfuuehgOWcsOW9oiB8CnwgKirpmLbmrrUyKiogfCAzIHwg6K6h566X5LiL5Y2K5Yy65Z2X5rip5rm/5bqmIHwKfCB8IDQgfCDnlJ/miJDkuIvljYrljLrlnZfln7rnoYDlnLDlvaIgfAp8ICoq6Zi25q61MyoqIHwgNSB8IOeUn+aIkOa0nueptCB8CnwgfCA2IHwg55Sf5oiQ55+/6KKL77yI5rOl5Zyf44CB5rKZ56C+562J77yJIHwKfCB8IDcgfCDnlJ/miJDnn7/niakgfAp8IHwgOCB8IOeUn+aIkOWcsOihqOaWueWdlyB8CnwgfCA5IHwg5rWB5L2T5ZCR5LiL5Lyg5pKtIHwKfCAqKumYtuautTQqKiB8IDEwIHwg55Sf5oiQ6I2J5ZKM5qSN54mpIHwKfCB8IDExIHwg55Sf5oiQ5Y6f5pyoIHwKfCB8IDEyIHwg55Sf5oiQ5qCR5pyoIHwKfCB8IDEzIHwg55Sf5oiQ5LuZ5Lq65o6MIHwKfCB8IDE0IHwg55Sf5oiQ5Y2X55OcIHwKfCB8IDE1IHwg55Sf5oiQ5rW35bimIHwKfCB8IDE2IHwg55Sf5oiQ5rW36I2JIHwKfCB8IDE3IHwg55Sf5oiQ5bqV5qCW5qSN54mpIHwKfCB8IDE4IHwg55Sf5oiQ6Zm36ZixIHwKfCB8IDE5IHwg55Sf5oiQ6Jek6JSTIHwKfCB8IDIwIHwg55Sf5oiQ5aKT56KRIHwKfCB8IDIxIHwg55Sf5oiQ55+z5aCGIHwKfCB8IDIyIHwg55Sf5oiQ5Yaw6ZuqIHwKfCB8IDIzIHwg55Sf5oiQ5Z+65bKp5ZKM56m65rCUIHwKfCB8IDI0IHwg5pu05paw5rWB5L2T6aG26Z2i54q25oCBIHwKCiMjIOWHuueUn+eCuemAieaLqQoKPiDmuLjmiI/kvJrmoLnmja7kvaDpgInmi6nnmoTpmr7luqbvvIzlnKjkuJbnlYzkuIrlr7vmib7mnIDpgILlkIjlh7rnlJ/nmoTkvY3nva7jgILkuI3lkIzpmr7luqblr7nmuKnmub/luqbjgIHmtbfmi5TlkozlnLDlvaLotbfkvI/mnInkuI3lkIzlgY/lpb3jgIIKCmBTY29yZVNwYXduUG9zaXRpb25gIOaWueazleS4uuavj+S4quWAmemAieS9jee9ruaJk+WIhu+8jOWIhuaVsOi2iuS9jui2iuS4jemAguWQiOWHuueUn++8mgoKfCDmg6nnvZrmnaHku7YgfCDnroDljZXmqKHlvI8gfCDkuK3nrYnmqKHlvI8gfCDlm7Dpmr7mqKHlvI8gfAp8LS0tLS0tLS0tLXwtLS0tLS0tLS0tfC0tLS0tLS0tLS18LS0tLS0tLS0tLXwKfCDot53ljp/ngrk+NDAw5qC8IHwgLTAuMjUgfCAtMC4yNSB8IC0wLjI1IHwKfCDkvY7kuo7mtbflubPpnaIgfCAtMS41IHwgLTEuNSB8IC0xLjUgfAp8IOWxseiEieWboOWtkD4wLjkgfCAtMS41IHwgLTEuNSB8IC0xLjUgfAp8IOa4qeW6pui/h+S9jiB8IDw3OiAtMSB8IFw8MzogLTAuNSB8ID4wOiAtMC41IHwKfCDmuKnluqbov4fpq5ggfCDigJQgfCA+NjogLTEgfCA+MjogLTEgfAp8IOa5v+W6puaegeerryB8IDJ+MTA6IC0wLjUgfCAzfjg6IC0wLjUgfCA+NjogLTEuNSB8Cnwg5rW35ouU6L+H6auYIHwgPjc1OiAtMSB8ID44MDogLTEgfCA+ODU6IC0xIHwKfCDlnLDlvaLotbfkvI/lpKcgfCA+NTogLTEgfCA+MTA6IC0xIHwgPjE1OiAtMSB8Cnwg5Zyw5b2i5aSq5bmz5Z2mIHwg4oCUIHwg4oCUIHwgPDU6IC0wLjUgfAoKPiAqKumAmuS/l+ino+mHiioq77ya566A5Y2V5qih5byP5YC+5ZCR5LqO5oqK5L2g5pS+5Zyo5rip5bim5bmz5Y6f77yI5rip5bqm6YCC5Lit44CB5rm/5bqm6YCC5Lit44CB5Zyw5Yq/5bmz5Z2m77yJ77yb5Zuw6Zq+5qih5byP5YiZ5Y+v6IO95oqK5L2g5o6o5ZCR5pu05p6B56uv55qE546v5aKD77yI5a+S5Ya35oiW5bmy54el44CB5Zyw5b2i5bSO5bKW77yJ44CC5L2G5omA5pyJ5qih5byP6YO95Lya6YG/5YWN6K6p5L2g5Zyo5rC05LiL5oiW6auY5bGx6aG25LiK5Ye655Sf44CCCgojIyDogZTmnLrniYjmlrDlnLDlvaIKCuiBlOacuueJiOW/q+eFp+aPkOS+m+S6humineWklueahOS4lueVjOeUn+aIkOaooeadv+OAggoKIyMjIOWfuuWyqeWkp+mZhiAoQmVkcm9jaykKCiMjIyMg5qC45b+D5py65Yi2Ci0gKirlnLDooajpq5jluqYqKu+8muWbuuWumuWcqOesrDMtN+Wxgu+8iOWfuuWyqeWkp+mZhuS8mOWMlu+8iQotICoq5LiW55WM57uT5p6EKirvvJrln7rlsqnlupXlsYIgKyDpqqjmnrblpKfpmYYgKyDomZrnqbrpobbpg6gKLSAqKuawtOS9kyoq77ya5LiN55Sf5oiQ77yIYFRHV2F0ZXIgPSBmYWxzZWDvvIkKLSAqKuWcsOW9oueJueW+gSoq77ya5p6B5L2O6auY5bqm77yM5peg6auY5bGx77yM5bmz5Z2m6aqo5p62CgojIyMjIOefv+efs+eUn+aIkOmAu+i+kQpgYGAK5Z+65bKp5aSn6ZmG5qih5byP77yabWluSGVpZ2h0ID0gMiwgbWF4SGVpZ2h0ID0gNiwg5pWw6YeP5YCN546HID0gMC4zCuaZrumAmuaooeW8j++8mm1pbkhlaWdodCA9IDUwLCBtYXhIZWlnaHQgPSA2MSwg5pWw6YeP5YCN546HID0gMS4wCmBgYAoKfCDnn7/nn7MgfCDnlJ/miJDpq5jluqYgfCDnlJ/miJDmlbDph4/lhazlvI8gfCDmm7/mjaLmlrnlnZcgfAp8Oi0tLXw6LS0tfDotLS18Oi0tLXwKfCDnhaTnn7/nn7MgfCBZPTItNiB8ICg1ICsgMyDDlyDlsbHohInlm6DlrZAgw5cg5Zmq5aOwKSDDlyAwLjMgfCDnn7PlpLQoMykgfAp8IOmTgeefv+efsyB8IFk9Mi02IHwgKDYgKyAyIMOXIOWxseiEieWboOWtkCDDlyDlmarlo7ApIMOXIDAuMyB8IOefs+WktCgzKSB8Cnwg6ZOc55+/55+zIHwgWT0yLTYgfCAoNSArIDIgw5cg5bGx6ISJ5Zug5a2QIMOXIOWZquWjsCkgw5cgMC4zIHwg55+z5aS0KDMpIHwKfCDnoZ3nn7MgfCBZPTItNiB8ICgzICsgMyDDlyDlsbHohInlm6DlrZAgw5cg5Zmq5aOwKSDDlyAwLjMgfCDnn7PlpLQoMykgfAp8IOehq+ejuiB8IFk9Mi02IHwgKDMgKyAyIMOXIOWxseiEieWboOWtkCDDlyDlmarlo7ApIMOXIDAuMyB8IOefs+WktCgzKSB8Cnwg6ZSX55+/IHwgWT0yLTYgfCAoMyArIDIgw5cg5bGx6ISJ5Zug5a2QIMOXIOWZquWjsCkgw5cgMC4zIHwg55+z5aS0KDMpIHwKCiMjIyDnn7PlpLTlpKfpmYYgKFN0b25lKQoKIyMjIyDmoLjlv4PmnLrliLYKLSAqKuWHuueUn+W5s+WPsCoq77ya5Zu65a6a5L2N572uICgtNDMzLCAyODAp77yMMjHDlzIx5aSn5bCP77yM57uT5p6E5Li65Z+65bKpKDLlsYIp4oaS5rOl5Zyf4oaS6I2J5pa55Z2XCi0gKirkuJbnlYznu5PmnoQqKu+8mumZpOWHuueUn+W5s+WPsOWklu+8jOaVtOS4quS4lueVjOiiq+efs+WktOWhq+WFhe+8jOWPquWcqOWym+Wxv+WMuuWfn+acieWcsOW9ogotICoq5bKb5bG/55Sf5oiQKirvvJrljYrlvoQyMOagvO+8jOmrmOW6pjQw5qC877yM57uT5p6E5Li65Z+65bKp4oaS55+z5aS04oaS5rOl5Zyf4oaS6I2J5pa55Z2XCi0gKirlsqnmtYbmsaAqKu+8muWIneWni+Wym+W/heeUn+aIkDEtMuS4quWyqea1huaxoO+8jOWFtuS7luWymzE1JeamgueOh+eUn+aIkAoKIyMjIyDnn7/nn7PnlJ/miJDpgLvovpEK55+z5aS05Zyw5b2i55qE55+/55+z55Sf5oiQ5pyJ5Lik56eN5pa55byP77yaCgoqKuaWueW8jzHvvJrmoIflh4bnn7/niannlJ/miJDvvIjnsbvkvLzlhbbku5blnLDlvaLvvIkqKgoqKuaWueW8jzLvvJrnqbrmsJTloavnn7PlpLTml7bpmo/mnLrnlJ/miJAqKu+8iDUl5qaC546H77yJCgp8IOefv+efsyB8IOmrmOW6puadoeS7tiB8IOamgueOhyB8IOaWueWdl0lEIHwKfDotLS18Oi0tLXw6LS0tfDotLS18Cnwg6ZK755+z55+/IHwgWSA8IDMwIHwgMTAlIHwgMTEyIHwKfCDplJfnn78gfCBZIDwgNjAgfCAyMCUgfCAxNDggfAp8IOmTgeefvyB8IFkgPCA4MCB8IDMwJSB8IDM5IHwKfCDpk5znn78gfCBZIDwgMTAwIHwgNDAlIHwgNDEgfAp8IOehq+ejuiB8IC0gfCA1MCUgfCAxMDEgfAp8IOehneefsyB8IC0gfCA3MCUgfCAxMDAgfAp8IOeFpOefvyB8IC0gfCDpu5jorqQgfCAxNiB8CgojIyMg56m65bKb5Zyw5b2iIChTa3lJc2xhbmQpCgojIyMjIOaguOW/g+acuuWItgotICoq5Z+65YeG6auY5bqmKirvvJozMOWxgu+8iGBCYXNlSGVpZ2h0ID0gMzBg77yJCi0gKirlh7rnlJ/lubPlj7AqKu+8muWNiuW+hDEyOOagvO+8jOi/nuaOpeWym+WMuuWfn++8jOWfuuWyqeW6leWxgumYsuatouaMluepugotICoq5bKb5bG/55Sf5oiQKirvvJrln7rkuo7lmarlo7DpmIjlgLwoMC4zKeWIpOaWre+8jOmrmOS6jumYiOWAvOeUn+aIkOWym+WxvwotICoq5Zyw5b2i54m55b6BKirvvJrkvY7nqbrjgIHlr4bpm4bjgIHntKflh5HnmoTlspvlsb/liIbluIMKCiMjIyMg5bKp5rWG5rGg55Sf5oiQCi0gKirmpoLnjocqKu+8mjgl77yI5q+P5Liq5Yy65Z2X77yJCi0gKirkvY3nva4qKu+8muWym+Wxv+WGhemDqO+8jOS4jei2heWHuuWym+Wxv+i+ueeVjAotICoq5bC65a+4KirvvJrljYrlvoQyLTTmoLzvvIzmt7HluqYyLTPmoLwKLSAqKueUn+aIkOinhOWImSoq77ya5bKp5rWG6aG26YOoID0g5bKb5bG/6KGo6Z2i5LiLMeagvO+8jOW6lemDqCA9IOihqOmdouS4i07moLzvvIjkuI3mjJbnqb/lspvlsb/vvIkKCiMjIyDkvJjljJblnLDlvaIgKEJldHRlcikKCiMjIyMg5qC45b+D5py65Yi2Ci0gKirnm4blnLDnlJ/miJAqKu+8muWZquWjsOWAvCA8IDAuMjkg55qE5Yy65Z+f55Sf5oiQ55uG5Zyw77yM5rex5bqm55Sx5Zmq5aOw6K6h566XCi0gKirmtbflubPpnaIqKu+8mjY05bGCCi0gKirmsLTkvZMqKu+8mueUn+aIkO+8iGBUR1dhdGVyID0gdHJ1ZWDvvIkKLSAqKuays+a1geW8uuW6pioq77ya5aKe5by677yIYFRHUml2ZXJzU3RyZW5ndGggPSA1ZmDvvIkKCiMjIyMg5YWz6ZSu5Y+C5pWw5a+55q+U77yI5LiO5qCH5YeG5Zyw5b2i77yJCnwg5Y+C5pWwIHwg5qCH5YeG5YC8IHwg5LyY5YyW5YC8IHwKfDotLS18Oi0tLXw6LS0tfAp8IOays+a1geW8uuW6piB8IDEuMCB8ICoqNS4wKiogfAp8IOWxseiEiemrmOW6piB8IDIyMCB8ICoqMjUwKiogfAp8IOWxseiEiemikeeOhyB8IDAuMDA5IHwgKiowLjAwMDYqKiB8Cnwg5bGx5Yy655m+5YiG5q+UIHwgNjAlIHwgKioxMyUqKiB8Cnwg5bGx5LiY55m+5YiG5q+UIHwgNTAlIHwgKioxNSUqKiB8Cnwg5a+G5bqm5YGP5beuIHwgOTYgfCAqKjU1KiogfAoKCiMjIOWGmee7meW8gOWPkeiAhQoKOjo6IGluZm8g6LWE5paZ5pqC5a2YCuacrOWwj+iKguWGheWuueaaguaXtuWtmOaUvuS6juatpO+8jOWQjue7reS8muenu+WKqOiHsyJNT0TlvIDlj5Ei56ug6IqC44CCCjo6OgoKPGRldGFpbHM+CjxzdW1tYXJ5PuW8gOWPkeamguiniDwvc3VtbWFyeT4KCgo+IOWmguaenOS9oOiuoeWIkuW8gOWPkeWcsOW9ouaooee7hOaIluiHquWumuS5ieS4lueVjOeUn+aIkO+8jOS7peS4i+aKgOacr+e7huiKguWwhuW4ruWKqeS9oOW/q+mAn+eQhuino+ezu+e7n+aetuaehOOAggoKIyMjIOaguOW/g+aWh+S7tue0ouW8lQoKfCDmlofku7YgfCDogYzotKMgfAp8LS0tLS0tfC0tLS0tLXwKfCBgVGVycmFpbkNvbnRlbnRzR2VuZXJhdG9yMjMuY3NgIHwg5Zyw5b2i5YaF5a6555Sf5oiQ5Zmo5Li757G777yM5YyF5ZCr5omA5pyJ55Sf5oiQ5pa55rOVIHwKfCBgV29ybGRTZXR0aW5ncy5jc2AgfCDkuJbnlYznlJ/miJDlj4LmlbDlrprkuYkgfAp8IGBUZXJyYWluR2VuZXJhdGlvbk1vZGUuY3NgIHwg5Zyw5b2i5qih5byP5p6a5Li+IHwKfCBgVGVycmFpblVwZGF0ZXIuY3NgIHwg5a2j6IqC5rip5bqm5puy57q/5ZKM5Yy65Z2X54q25oCB5pu05pawIHwKfCBgU3Vic3lzdGVtV2VhdGhlci5jc2AgfCDlpKnmsJTjgIHmuKnluqbkv67mraPjgIHlhrvnu5PliKTlrpogfAp8IGBTdWJzeXN0ZW1TZWFzb25zLmNzYCB8IOWto+iKguWIkuWIhuWSjOi9rOaNoiB8CnwgYFRlcnJhaW4uY3NgIHwg5Zyw5b2i5pWw5o2u5a2Y5Y+W77yM5a2j6IqC5rip5rm/5bqm6K6h566XIHwKfCBgU2Vhc29uLmNzYCB8IOWto+iKguaemuS4vu+8iFN1bW1lcj0wLCBBdXR1bW49MSwgV2ludGVyPTIsIFNwcmluZz0z77yJIHwKCiMjIyDlhajpg6ggVEcg5Y+C5pWw6YCf5p+l6KGoCgpgYGBjc2hhcnAKLy8g576k57O757yp5pS+77yI5b2x5ZON5rip5rm/5bqm5ZKM5bGx6ISJ5Zmq5aOw6aKR546H77yJClRHQmlvbWVTY2FsaW5nID0gKElzbGFuZCA/IDFmIDogMS43NWYpICogQmlvbWVTaXplOwoKLy8g5rW35rSLClRHT2NlYW5TbG9wZSA9IDAuMDA2ZjsKVEdPY2VhblNsb3BlVmFyaWF0aW9uID0gMC4wMDRmOwpUR0lzbGFuZHNGcmVxdWVuY3kgPSAwLjAxZjsKVEdTaG9yZUZsdWN0dWF0aW9ucyA9IENsYW1wKDJmICogbWluSXNsYW5kU2l6ZSwgMGYsIDE1MGYpOwpUR1Nob3JlRmx1Y3R1YXRpb25zU2NhbGluZyA9IENsYW1wKDAuMDRmICogbWluSXNsYW5kU2l6ZSwgMC41ZiwgM2YpOwoKLy8g6auY5bqm5Z+65YeGClRHRGVuc2l0eUJpYXMgPSA1NWY7ClRHSGVpZ2h0QmlhcyA9IDFmOwoKLy8g5rKz5rWBClRHUml2ZXJzU3RyZW5ndGggPSAxZjsKCi8vIOWxseiEiQpUR01vdW50YWluc1N0cmVuZ3RoID0gMjIwZjsKVEdNb3VudGFpblJhbmdlRnJlcSA9IDAuMDAwNmY7ClRHTW91bnRhaW5zUGVyY2VudGFnZSA9IDAuMTNmOwpUR01vdW50YWluc0RldGFpbEZyZXEgPSAwLjAwM2Y7ClRHTW91bnRhaW5zRGV0YWlsT2N0YXZlcyA9IDM7ClRHTW91bnRhaW5zRGV0YWlsUGVyc2lzdGVuY2UgPSAwLjUzZjsKCi8vIOS4mOmZtQpUR0hpbGxzUGVyY2VudGFnZSA9IDAuM2Y7ClRHSGlsbHNTdHJlbmd0aCA9IDMyZjsKVEdIaWxsc09jdGF2ZXMgPSAxOwpUR0hpbGxzRnJlcXVlbmN5ID0gMC4wMTRmOwpUR0hpbGxzUGVyc2lzdGVuY2UgPSAwLjVmOwoKLy8g5rmN5rWB77yI5Zyw5b2i5omw5Yqo77yJClRHVHVyYnVsZW5jZVN0cmVuZ3RoID0gNTVmOwpUR1R1cmJ1bGVuY2VGcmVxID0gMC4wM2Y7ClRHVHVyYnVsZW5jZU9jdGF2ZXMgPSAxOwpUR1R1cmJ1bGVuY2VQZXJzaXN0ZW5jZSA9IDAuNWY7ClRHTWluVHVyYnVsZW5jZSA9IDAuMDRmOwpUR1R1cmJ1bGVuY2VaZXJvID0gMC44NGY7CgovLyDlnLDooagKVEdTdXJmYWNlTXVsdGlwbGllciA9IDJmOwoKLy8g5byA5YWzClRHV2F0ZXIgPSB0cnVlOyAgICAgICAgLy8g55Sf5oiQ5rC0ClRHRXh0cmFzID0gdHJ1ZTsgICAgICAgLy8g55Sf5oiQ5qSN6KKr5ZKM6KOF6aWwClRHQ2F2ZXNBbmRQb2NrZXRzID0gdHJ1ZTsgIC8vIOeUn+aIkOa0nueptOWSjOefv+iiiwoKLy8g5rW35bmz6Z2iCk9jZWFuTGV2ZWwgPSA2NCArIFNlYUxldmVsT2Zmc2V0OwoKLy8g5Z+65bKpCk1heEJlZHJvY2tIZWlnaHQgPSA0OwpgYGAKCiMjIyDpq5jluqborqHnrpflrozmlbTlhazlvI8KCmBgYGNzaGFycApwdWJsaWMgZmxvYXQgQ2FsY3VsYXRlSGVpZ2h0KGZsb2F0IHgsIGZsb2F0IHopIHsKICAgIC8vIDEuIOa1t+a0i+WdoeW6pu+8iOaOp+WItua1t+WyuOWdoeW6pu+8iQogICAgZmxvYXQgb2NlYW5TbG9wZSA9IFRHT2NlYW5TbG9wZSArIFRHT2NlYW5TbG9wZVZhcmlhdGlvbiAqIG5vaXNlOwoKICAgIC8vIDIuIOi3nea1t+i3neemuwogICAgZmxvYXQgc2hvcmVEaXN0ID0gQ2FsY3VsYXRlT2NlYW5TaG9yZURpc3RhbmNlKHgsIHopOwogICAgZmxvYXQgc2hvcmVGYWN0b3IgPSBTYXR1cmF0ZSgyZiAtIDAuMDVmICogQWJzKHNob3JlRGlzdCkpOwogICAgZmxvYXQgaXNsYW5kRmFjdG9yID0gU2F0dXJhdGUoU2luKFRHSXNsYW5kc0ZyZXF1ZW5jeSAqIHNob3JlRGlzdCkpOwogICAgZmxvYXQgb2NlYW5EZXB0aCA9IFNhdHVyYXRlKFNhdHVyYXRlKC1vY2VhblNsb3BlICogc2hvcmVEaXN0KSAtIDAuODVmICogaXNsYW5kRmFjdG9yKTsKICAgIGZsb2F0IGZhckZyb21TaG9yZSA9IFNhdHVyYXRlKFNhdHVyYXRlKDAuMDVmICogKC1zaG9yZURpc3QgLSAxMGYpKSAtIGlzbGFuZEZhY3Rvcik7CgogICAgLy8gMy4g5bGx6ISJ5Zug5a2QCiAgICBmbG9hdCBtb3VudGFpbiA9IENhbGN1bGF0ZU1vdW50YWluUmFuZ2VGYWN0b3IoeCwgeik7CgogICAgLy8gNC4g5LiY6Zm1L+WxseiEieWMuuWfn+adg+mHjQogICAgZmxvYXQgaGlsbHNXZWlnaHQgPSAoMSAtIGZhckZyb21TaG9yZSkgKiAoMSAtIHNob3JlRmFjdG9yKSAqIFNxdWlzaChtb3VudGFpbiwgMSAtIFRHSGlsbHNQZXJjZW50YWdlLCAxIC0gVEdNb3VudGFpbnNQZXJjZW50YWdlKTsKICAgIGZsb2F0IG1vdW50YWluc1dlaWdodCA9ICgxIC0gZmFyRnJvbVNob3JlKSAqIFNxdWlzaChtb3VudGFpbiwgMSAtIFRHTW91bnRhaW5zUGVyY2VudGFnZSwgMSk7CgogICAgLy8gNS4g5LiY6Zm15Zmq5aOwCiAgICBmbG9hdCBoaWxsc05vaXNlID0gU2ltcGxleE5vaXNlLk9jdGF2ZWROb2lzZSh4LCB6LCBUR0hpbGxzRnJlcXVlbmN5LCBUR0hpbGxzT2N0YXZlcywgMS45M2YsIFRHSGlsbHNQZXJzaXN0ZW5jZSk7CiAgICBmbG9hdCBoaWxscyA9IFRHSGlsbHNTdHJlbmd0aCAqIGhpbGxzV2VpZ2h0ICogaGlsbHNOb2lzZTsKCiAgICAvLyA2LiDlsbHohInlmarlo7AKICAgIGZsb2F0IG1vdW50YWluc05vaXNlID0gMS41ZiAqIFNpbXBsZXhOb2lzZS5PY3RhdmVkTm9pc2UoeCwgeiwgVEdNb3VudGFpbnNEZXRhaWxGcmVxLCBUR01vdW50YWluc0RldGFpbE9jdGF2ZXMsIDEuOThmLCBwZXJzaXN0ZW5jZSkgLSAwLjVmOwogICAgZmxvYXQgbW91bnRhaW5zID0gVEdNb3VudGFpbnNTdHJlbmd0aCAqIG1vdW50YWluc1dlaWdodCAqIG1vdW50YWluc05vaXNlOwoKICAgIC8vIDcuIOays+a1gQogICAgZmxvYXQgcml2ZXJOb2lzZSA9IFNhdHVyYXRlKDEuNWYgLSByaXZlcldpZHRoICogQWJzKDJmICogU2ltcGxleE5vaXNlLk9jdGF2ZWROb2lzZSh4LCB6LCAwLjAwMWYsIDQsIDJmLCAwLjVmKSAtIDFmKSk7CiAgICBmbG9hdCByaXZlcnMgPSBUR1JpdmVyc1N0cmVuZ3RoICogcml2ZXJOb2lzZTsKCiAgICAvLyA4LiDnu4TlkIgKICAgIGZsb2F0IGJhc2VIZWlnaHQgPSAtNTBmICogb2NlYW5EZXB0aCArIFRHSGVpZ2h0QmlhczsKICAgIGZsb2F0IHJlc3VsdCA9IGJhc2VIZWlnaHQgKyBMZXJwKDAsIDgsIGYpICsgTGVycCgwLCAtNiwgZjIpICsgbW91bnRhaW5zICsgaGlsbHM7CiAgICByZXN1bHQgPSBNaW4oTGVycChyZXN1bHQsIExlcnAoLTIsIC00LCAuLi4pLCByaXZlcnMpLCByZXN1bHQpOwoKICAgIHJldHVybiBNYXRoLkNsYW1wKDY0ZiArIHJlc3VsdCwgMTBmLCAyNTFmKTsKfQpgYGAKCiMjIyDmuKnmub/luqborqHnrpflhbPplK7nu4boioIKCmBgYGNzaGFycAovLyDmuKnluqbvvJo15bGC5YWr5bqm5Zmq5aOw77yM6aKR546HMC4wMDE1L1RHQmlvbWVTY2FsaW5nCi8vIOWBj+enuy0xLjHkvb/nu5PmnpzlgY/lkJHlr5LlhrfvvIjnuqY3MCXljLrln5/muKnluqbiiaQ377yJCi8vIOacgOe7iOe7k+aenCDDlyAxNiDlkI7lj5bmlbTvvIzojIPlm7QwfjE1CmludCB0ZW1wZXJhdHVyZSA9IENsYW1wKAogICAgKGludCkoU2F0dXJhdGUoM2YgKiBub2lzZSAtIDEuMWYgKyB0ZW1wT2Zmc2V0LzE2ZikgKiAxNmYpLAogICAgMCwgMTUKKTsKCi8vIOa5v+W6pu+8mjXlsYLlhavluqblmarlo7DvvIzpopHnjocwLjAwMTIvVEdCaW9tZVNjYWxpbmcKLy8g5YGP56e7LTAuOeS9v+e7k+aenOWBj+WQkeW5sueHpe+8iOe6pjY1JeWMuuWfn+a5v+W6puKJpDfvvIkKaW50IGh1bWlkaXR5ID0gQ2xhbXAoCiAgICAoaW50KShTYXR1cmF0ZSgzZiAqIG5vaXNlIC0gMC45ZiArIGh1bWlkT2Zmc2V0LzE2ZikgKiAxNmYpLAogICAgMCwgMTUKKTsKYGBgCgojIyMg5Zyw6KGo5pa55Z2X5Yik5a6a5a6M5pW06YC76L6RCgpgYGBjc2hhcnAKdm9pZCBHZW5lcmF0ZVN1cmZhY2UoVGVycmFpbkNodW5rIGNodW5rKSB7CiAgICAvLyDpgY3ljobmr4/kuKp4LHrliJfvvIzku47pobblkJHkuIvmib7liLDnrKzkuIDkuKrpnZ7pgI/mmI7mlrnlnZcKICAgIGludCB0b3BCbG9jayA9IEZpbmRUb3Btb3N0U29saWRCbG9jayhpLCBqKTsKICAgIGludCB0ZW1wZXJhdHVyZSA9IHRlcnJhaW4uR2V0VGVtcGVyYXR1cmUoeCwgeik7CiAgICBpbnQgaHVtaWRpdHkgPSB0ZXJyYWluLkdldEh1bWlkaXR5KHgsIHopOwoKICAgIGludCBzdXJmYWNlQmxvY2s7CiAgICBpZiAodG9wQmxvY2sgPT0gNCkgeyAgLy8g56CC5bKp6KGo6Z2iCiAgICAgICAgLy8g5rip5ZKM5rCU5YCZ4oaS55+z54Gw5bKp77yM5p6B56uv5rCU5YCZ4oaS5rKZ5a2QCiAgICAgICAgc3VyZmFjZUJsb2NrID0gKHRlbXBlcmF0dXJlID4gNCAmJiB0ZW1wZXJhdHVyZSA8IDcpID8gNiA6IDc7CiAgICB9IGVsc2UgewogICAgICAgIGludCB0ZW1wQmFuZCA9IHRlbXBlcmF0dXJlIC8gNDsgIC8vIOa4qeW6puW4pjB+MwogICAgICAgIGludCBibG9ja0Fib3ZlID0gR2V0QmxvY2tBYm92ZSh0b3BCbG9jayk7CgogICAgICAgIHN1cmZhY2VCbG9jayA9CiAgICAgICAgICAgIC8vIOmrmOa1t+aLlOWGu+e7k+KGkuWGsOmbqgogICAgICAgICAgICAoeSA+IDEyMCAmJiBJc1BsYWNlRnJvemVuKHRlbXBlcmF0dXJlLCB5KSkgPyA2MiA6CiAgICAgICAgICAgIC8vIOeJueWumuadoeS7tuKGkueOhOatpuWyqe+8iOe9leinge+8iQogICAgICAgICAgICAoKHkgPCA2NiB8fCB5ID09IDg0ICsgdGVtcEJhbmQgfHwgeSA9PSAxMDMgKyB0ZW1wQmFuZCkgJiYgaHVtaWRpdHkgPT0gOSAmJiB0ZW1wZXJhdHVyZSAlIDYgPT0gMSkgPyA2NiA6CiAgICAgICAgICAgIC8vIOawtOS4i+mrmOa5v+KGkuayieenr+eJqQogICAgICAgICAgICAoYmxvY2tBYm92ZSA9PSAxOCAmJiBodW1pZGl0eSA+IDggJiYgaHVtaWRpdHkgJSAyID09IDAgJiYgdGVtcGVyYXR1cmUgJSAzID09IDApID8gNzIgOgogICAgICAgICAgICAvLyDpu5jorqTihpLojYnlnLAKICAgICAgICAgICAgMjsKICAgIH0KCiAgICAvLyDopobnm5blsYLljprluqYKICAgIGludCB0aGlja25lc3M7CiAgICBpZiAoc3VyZmFjZUJsb2NrID09IDYyKSB7ICAvLyDlhrDpm6oKICAgICAgICB0aGlja25lc3MgPSBDbGFtcCgtdGVtcGVyYXR1cmUsIDEsIDcpOyAgLy8g6LaK5Ya36LaK5Y6aCiAgICB9IGVsc2UgewogICAgICAgIC8vIOa1t+aLlOi2iumrmOOAgeWxseiEiei2iumZoeOAgea5v+W6pui2iuS9juKGkuimhuebluWxgui2iuiWhAogICAgICAgIGZsb2F0IGhlaWdodEZhY3RvciA9IFNhdHVyYXRlKCh5IC0gMTAwZikgKiAwLjA1Zik7CiAgICAgICAgZmxvYXQgZiA9IFNhdHVyYXRlKG1vdW50YWluRmFjdG9yICogaGVpZ2h0RmFjdG9yICsgc3VyZmFjZU11bHRpcGxpZXIgKiBoZWlnaHRGYWN0b3IpOwogICAgICAgIHRoaWNrbmVzcyA9IFJhbmRvbShJbnQoTGVycCg0LCAwLCBmKSwgTGVycCg3LCAwLCBmKSkpOwogICAgfQoKICAgIC8vIOWwhuimhuebluWxguaWueWdl+WGmeWFpeWMuuWdlwogICAgUmVwbGFjZVRvcEJsb2NrcyhzdXJmYWNlQmxvY2ssIHRoaWNrbmVzcyk7Cn0KYGBgCgojIyMg5rKZ5ryg5qCH5b+X5Yik5a6aCgpgYGBjc2hhcnAKLy8g5ZyoIEdlbmVyYXRlVGVycmFpbiDkuK3lhrPlrprlnLDkuIvmlrnlnZfnsbvlnosKYm9vbCBpc0Rlc2VydCA9ICh0ZW1wZXJhdHVyZUZhc3QgPiA4ICYmIGh1bWlkaXR5RmFzdCA8IDggJiYgbW91bnRhaW5GYWN0b3IgPCAwLjk3ZikKICAgICAgICAgICAgIHx8IChNYXRoLkFicyhvY2VhblNob3JlRGlzdGFuY2UpIDwgMTZmICYmIG1vdW50YWluRmFjdG9yIDwgMC45N2YpOwoKLy8g5rKZ5rygL+a1t+WyuO+8mua1heWxguegguWyqSg0KSDihpIg5Lit5bGC6Iqx5bKX5bKpKDMpIOKGkiDmt7HlsYLnjoTmrablsqkoNjcpCi8vIOaZrumAmu+8miAgICDmtYXlsYLoirHlspflsqkoMykg4oaSIOa3seWxgueOhOatpuWyqSg2NykKLy8g5rKZ5ryg55qE56CC5bKp5bGC5Y6a5bqm55SxIG1vdW50YWluRmFjdG9yIOWSjCBodW1pZGl0eSDlhrPlrprvvJoKLy8gICB0aGlja25lc3MxID0gTGVycCgxMDAsIDAsIG1vdW50YWluRmFjdG9yIC0gMC4wMSAqIGh1bWlkaXR5KSAgLy8g56CC5bKp5bGCCi8vICAgdGhpY2tuZXNzMiA9IExlcnAoMzAwLCAzMCwgbW91bnRhaW5GYWN0b3IgLSAwLjAxICogaHVtaWRpdHkpICAvLyDoirHlspflsqnlsYIKYGBgCgojIyMg5a2j6IqC5rip5bqm5puy57q/5pWw5o2uCgpgYGBjc2hhcnAKLy8gVGVycmFpblVwZGF0ZXIuY3Mg5Lit55qEIEZsb2F0Q3VydmUg5a6a5LmJCnB1YmxpYyBGbG9hdEN1cnZlIFRlbXBlcmF0dXJlQ3VydmUgPSBuZXcoCiAgICBuZXcgVmVjdG9yMigwZiwgMGYpLCAgICAgICAvLyDnm5vlpI/vvJrml6Dkv67mraMKICAgIG5ldyBWZWN0b3IyKDAuMTI1ZiwgMGYpLCAgIC8vIOS7suWkj++8muaXoOS/ruatowogICAgbmV3IFZlY3RvcjIoMC4yNWYsIDBmKSwgICAgLy8g5Yid56eL77ya5peg5L+u5q2jCiAgICBuZXcgVmVjdG9yMigwLjM3NWYsIC00ZiksICAvLyDkuK3np4vvvJotNAogICAgbmV3IFZlY3RvcjIoMC41ZiwgLTEyZiksICAgLy8g5Yid5Yas77yaLTEyCiAgICBuZXcgVmVjdG9yMigwLjYyNWYsIC0yNGYpLCAvLyDpmoblhqzvvJotMjTvvIjlhajlubTmnIDlhrfvvIkKICAgIG5ldyBWZWN0b3IyKDAuNzVmLCAtMTJmKSwgIC8vIOWIneaYpe+8mi0xMgogICAgbmV3IFZlY3RvcjIoMC44NzVmLCAtNGYpLCAgLy8g5Luy5pil77yaLTQKICAgIG5ldyBWZWN0b3IyKDFmLCAwZikgICAgICAgIC8vIOWbnuWIsOebm+Wkj++8mjAKKTsKCi8vIOa5v+W6puS4jeWPl+Wto+iKguW9seWTjQpwdWJsaWMgRmxvYXRDdXJ2ZSBIdW1pZGl0eUN1cnZlID0gbmV3KAogICAgbmV3IFZlY3RvcjIoMGYsIDBmKSwKICAgIG5ldyBWZWN0b3IyKDFmLCAwZikgIC8vIOWFqOW5tOS4jeWPmAopOwpgYGAKCiMjIyDlraPoioLmuKnluqbnmoTkvKDpgJLpk74KCmBgYApXb3JsZFNldHRpbmdzLlRpbWVPZlllYXIgKDB+MSkKICAgIOKGkiBUZXJyYWluVXBkYXRlci5VcGRhdGUoKQogICAg4oaSIFRlbXBlcmF0dXJlQ3VydmUuU2FtcGxlKHRpbWVPZlllYXIpIOKGkiBTZWFzb25UZW1wZXJhdHVyZQogICAg4oaSIFRlcnJhaW4uU2Vhc29uVGVtcGVyYXR1cmUgPSBudW0KICAgIOKGkiBUZXJyYWluLkdldFNlYXNvbmFsVGVtcGVyYXR1cmUoeCwgeikgPSBHZXRUZW1wZXJhdHVyZSh4LCB6KSArIFNlYXNvblRlbXBlcmF0dXJlCiAgICDihpIgU3Vic3lzdGVtV2VhdGhlci5Jc1BsYWNlRnJvemVuKHNlYXNvbmFsVGVtcCwgeSkKICAgIOKGkiDlhrPlrprpmY3msLTnsbvlnovvvIjpm6ov6ZuoL+aXoO+8ieWSjOWGsOmbqueUn+aIkApgYGAKCiMjIyDlubPlnabmqKHlvI/nmoTlvbHlk40KCuW5s+WdpuaooeW8j++8iEZsYXRDb250aW5lbnQvRmxhdElzbGFuZO+8iemAmui/h+mZjeS9juWxseiEieWSjOS4mOmZteW8uuW6puadpeWunueOsOW5s+WdpuaViOaenOOAguiZveeEtua6kOeggeS4rSBgVGVycmFpbkNvbnRlbnRzR2VuZXJhdG9yMjMuY3NgIOeahCBURyDlj4LmlbDlnKjmnoTpgKDlh73mlbDkuK3nu5/kuIDorr7nva7vvIzkvYblubPlnabmqKHlvI/kvJrlnKjlpJbpg6josIPmlbTku6XkuIvlj4LmlbDvvJoKCi0g5bGx6ISJ5by65bqm5aSn5bmF6ZmN5L2O77yI5Zyw5b2i5LiN5Lya5Ye6546wWT0yMDAr55qE6auY5bGx77yJCi0g5LiY6Zm15by65bqm6ZmN5L2O77yI5Zyw5Yq/6LW35LyP5pu05bmz57yT77yJCi0g5pW05L2T6auY5bqm5pu05o6l6L+R5rW35bmz6Z2i77yIWT02NO+8iQoKPC9kZXRhaWxzPgoKIyMjIOaWueWdl+e0ouW8lemAn+afpQoKfCDntKLlvJUgfCDmlrnlnZflkI0gfCDnlKjpgJQgfAp8LS0tLS0tfC0tLS0tLS0tfC0tLS0tLXwKfCAwIHwg56m65rCUIHwg4oCUIHwKfCAxIHwg5Z+65bKpIHwg5LiN5Y+v56C05Z2P77yMWT0wfjQgfAp8IDIgfCDms6XlnJ8gfCDluLjop4HlnLDooaggfAp8IDMgfCDoirHlspflsqkgfCDluLjop4HlnLDkuIvlsqnnn7MgfAp8IDQgfCDnoILlsqkgfCDmspnmvKDlnLDkuIvlsqnnn7MgfAp8IDYgfCDnn7PngbDlsqkgfCDmuKnlkozmsJTlgJnlnLDooaggfAp8IDcgfCDmspnlrZAgfCDmspnmvKDlnLDooaggfAp8IDggfCDojYnlnLAgfCDojYnlnLAgfAp8IDE4IHwg5rC0IHwg5rW35rSLL+ays+a1gS/muZbms4ogfAp8IDYxIHwg6ZuqIHwg5Zyw6Z2i6KaG6ZuqIHwKfCA2MiB8IOWGsCB8IOawtOmdouWGu+e7kyB8CnwgNjYgfCDnjoTmrablsqkgfCDmt7HlsYLlsqnnn7Mv54m55q6K5Zyw6KGoIHwKfCA2NyB8IOeOhOatpuWyqSB8IOa3seWxguWcsOS4i+WyqeefsyB8CnwgNzIgfCDmsonnp6/niakgfCDmsLTlupXnibnmrormlrnlnZcgfAp8IDEyNyB8IOS7meS6uuaOjCB8IOaymea8oOakjeiiqyB8Cg==
