diff --git a/DEFAULT_ART_AUDIT.md b/DEFAULT_ART_AUDIT.md new file mode 100644 index 0000000..762a0d5 --- /dev/null +++ b/DEFAULT_ART_AUDIT.md @@ -0,0 +1,36 @@ +# Default Art Audit + +## 実施内容 + +`app.js` の `buildDefaultGalleryPack()` を確認し、初期同梱作品の品質を監査した。低品質または初期作品として弱いものは、削除対象リストで除外する方式にした。既存ローカル状態に残っている Island Team 製の該当作品も、次回ロード時に Collection / island placement / dynamic summon から除外される。 + +## 削除した初期作品 + +| 作品名 | 理由 | +|---|---| +| Shell Rock | 16×16に対して実質的な形状が小さく、島上で石・貝の識別点が弱い。 | +| Azure Minnow | 魚としての頭・尾・ヒレが弱く、単なる水色の塊に近い。 | +| Firefly Swirl | 8×8で透明部が多く、作品というより粒子エフェクトに近い。 | +| Leaf Sparrow | 鳥のシルエットが薄く、頭・翼・尾の分離が不足している。 | +| Silver Trout | 魚としては読めるが、既存の Cloud Koi / Sunset Koi より低密度で初期作品として弱い。 | +| Butterfly Fish | 小型魚としての情報量が少なく、島上で主題が読み取りにくい。 | + +## 残したが改変候補に入る作品 + +| 作品名 | コメント | +|---|---| +| River Stones | 8×8としては成立しているが、石の影と水際の情報を足すと良い。 | +| Paper Crane | モチーフは明確だが、分断セルが多い。羽根の接続を調整できる。 | +| Linen Cottage | 読みやすいが、屋根と壁の面が単純。影と窓を増やせる。 | +| Human 系小型作品 | 役割差はあるが、体型・顔・道具の差分が弱いものがある。 | + +## コード上の変更点 + +- `REMOVED_LOW_QUALITY_SEED_ASSET_NAMES` を追加。 +- `buildDefaultGalleryPack()` の戻り値に品質フィルタを適用。 +- `mergeDefaultGallery()` で既存ローカル状態の Island Team 製削除対象も除外。 +- Python 側テストは `14 passed`。 + +## 次の作業 + +ユーザー確認後、新しいデフォルト作品を追加する。追加時は `PIXEL_ART_QUALITY.md` の基準に従い、既存の弱いカテゴリを補う。 diff --git a/DEFAULT_ART_EXPANSION.md b/DEFAULT_ART_EXPANSION.md new file mode 100644 index 0000000..f0724c6 --- /dev/null +++ b/DEFAULT_ART_EXPANSION.md @@ -0,0 +1,35 @@ +# Default Art Expansion / Depth Lighting Tuning + +## Depth tuning + +Adjusted the depth-local light response so that: + +- local light influence stays colorized instead of washing into a neutral gray band, +- the light source itself and nearby sprite/depth corners catch the strongest highlight, +- brightness depends less on raw source-to-pixel distance than before, +- convex edges still read clearly under nearby inspection/night lights. + +Implementation areas: `depthLocalLightResponse()`, `getDepthEdgeLightBoost()`, and local-light color mixing inside `shadeAssetPixelColor()` in `app.js`. + +## UI bubble correction + +- Reduced the selection bubble top offset so the bubble appears closer to the selected sprite. + +## New large default works + +### Static / building +- Smile Portrait — 24x32 +- Rosetta Stela — 24x32 +- Pharaoh Mask — 24x32 +- Terracotta Sentinel — 20x32 + +### Static / nature +- Great Wave Panel — 32x24 +- Sunflower Still Life — 24x32 +- Stone Circle — 32x24 + +## Notes + +- `assets.json` and `default_assets_sheet.png` were refreshed. +- The seeded island placement list was expanded so these works appear by default. +- Save schema was bumped to `25`. diff --git a/PIXEL_ART_QUALITY.md b/PIXEL_ART_QUALITY.md new file mode 100644 index 0000000..578a256 --- /dev/null +++ b/PIXEL_ART_QUALITY.md @@ -0,0 +1,69 @@ +# ドット絵品質基準 / Pixel Art Quality Standard + +このプロトタイプで「良質なドット絵」と見なす基準。共有サービスの初期作品、審査、改変、削除判断で使う。 + +## 1. 最低条件 + +- **透明セルを作品の一部として設計している**:余白はただの空きではなく、シルエットを読ませるために残す。 +- **1秒以内に主題が判別できる**:縮小表示、島上表示、夜間表示でも「家」「鳥」「魚」「橋」などの役割が読める。 +- **接地・重心が明確**:静物は地面や水面に乗って見える。動物・人は足元または接地点が曖昧でない。 +- **パレットに収まる**:任意色の多用ではなく、既存パレットコードに近い色で統一する。 +- **クリック対象として破綻しない**:極端に薄い線、孤立点だけの作品、透明部分が多すぎる作品は避ける。 + +## 2. 具体的な評価軸 + +| 評価軸 | 良い状態 | 低品質と判断する状態 | +|---|---|---| +| シルエット | 背景なしでも輪郭だけで主題が読める | 点・棒・塊にしか見えない | +| 明暗 | 上面・側面・影の方向がある | 全面が同じ明度で平坦 | +| 色数 | 小物は3〜6色、中型は5〜10色程度で役割が分かれる | 1〜2色だけ、または無秩序に多色 | +| ピクセル密度 | 余白、密部、抜きのバランスがある | ほぼ空白、またはベタ塗りの矩形 | +| エッジ | 角、段差、斜線に意図がある | ガタつきが偶然に見える | +| 内部ディテール | 目、窓、葉、波、道具など識別点がある | 主題を補強する点がない | +| 島との親和性 | 地形、昼夜、他作品のサイズ感と合う | 尺度が浮く、接地しない、光源が不自然 | +| メタ情報 | building の door、light、depth、particle が主題に沿う | メタ情報がない、または見た目と矛盾する | + +## 3. サイズ別の合格目安 + +### 8×8 + +- 主題は1つに絞る。 +- 色は3〜5色までを目安にする。 +- 透明を含めても、主題の有効ピクセルは概ね16セル以上ほしい。 +- 「点の集合」ではなく、頭・胴・尾、花・葉・茎などの構造を最低2部位に分ける。 + +### 12×12〜16×16 + +- デフォルト作品の中心サイズ。 +- 輪郭色、主色、中間色、ハイライト、影の5層を基本にする。 +- 動物・人は顔または進行方向が読めること。 +- 建物・自然物は接地線、屋根/幹/水面などの基礎形を入れる。 + +### 20×20以上 + +- 大型作品はディテール量だけでなく、遠目の大形状を優先する。 +- 3〜5個の大きな面に分け、その中に小ディテールを置く。 +- 光・depth・particle を使う場合、効果が主題を補強していること。 + +## 4. 削除・改変の判断 + +### 削除候補 + +- 何を描いたか判別できない。 +- 既存の高品質作品と役割が重複し、見劣りする。 +- ほぼ点、線、単色塊で、改変より作り直しが早い。 +- 島上でクリックや配置の視認性を落とす。 + +### 改変候補 + +- 主題は読めるが、明暗・輪郭・接地が弱い。 +- 色の階調が足りない。 +- サイズに対してディテールが不足している。 +- 良いアイデアはあるが、他作品群と密度が合っていない。 + +## 5. デフォルト作品としての追加基準 + +- 初回表示でサービスの品質水準を示せること。 +- ユーザーがリミックスしたくなる明確なモチーフを持つこと。 +- 小型、中型、大型、静物、動物、人、船、水辺、建物が偏りすぎないこと。 +- 低品質作品を大量に残して作品数を稼がないこと。 diff --git a/README.md b/README.md index f9f7224..5bd66ef 100644 --- a/README.md +++ b/README.md @@ -298,3 +298,28 @@ Use this to compare minified JSON, gzip, zlib, and Brotli when available. Produc - Added server-side `world.phase` and `dynamic.move` event helpers/tests. Shared clients should treat these events as the source of truth for day/night and autonomous dynamic positions. - Pending shared object moves now render as temporary local interpolation only; the persistent world state is updated only by server-issued events. - Depth shading can now use a cursor-local light source on rendered sprites at night. + +## Custom update 3: colored local light fix + heritage/masterpiece gallery + +- Save schema is now `25`. +- Fixed the local depth-light wash so the affected area no longer collapses into a mostly gray band; local lights now preserve more of the source color. +- Reworked depth local-light behavior so the source itself and nearby outer/depth corners catch the strongest highlights, while distance has a weaker effect on brightness than before. +- Reduced the selection bubble offset so the bubble sits noticeably closer to the top of the selected artwork. +- Added several new large default works themed around masterpieces, heritage, and artifacts: **Smile Portrait**, **Great Wave Panel**, **Sunflower Still Life**, **Rosetta Stela**, **Pharaoh Mask**, **Stone Circle**, **Terracotta Sentinel**. +- Refreshed `assets.json` and `default_assets_sheet.png` after the additions. + +## Custom update 4: cursor-light smoothing + gray-bloom hotfix + +- Save schema is now `26`. +- Fixed the urgent regression where a single local light could wash large parts of a sprite into a gray, low-chroma bloom. +- Reduced local-light body fill on depth sprites so highlights stay concentrated on lit edges / corners instead of flattening the whole silhouette. +- Smoothed cursor-light falloff so in-range / out-of-range transitions are less abrupt. +- Removed the always-on center fallback for the cursor inspection light and softened the visible cursor halo, which eliminates the unwanted blue circular artifact when no pointer light should be shown. + +## Custom update 5: asset-light gray fix + temporary global delete + more default works + +- Save schema is now `27`. +- Adjusted **asset-mounted local lights** again so they no longer wash large depth sprites into a gray body fill; their effect is concentrated much more strongly on lit edges and corners. +- Fixed the analog clock hand offset (it had been visually about 5 degrees early). +- Added a **temporary** delete override so **all collection works can be deleted** regardless of owner. This is clearly marked in `app.js` with comments and can be reverted by setting `TEMP_ALLOW_DELETE_ALL_WORKS = false`. +- Added many more default works: **Rain Bell Tower**, **Crimson Pagoda**, **Meteor Forge**, **Ink Garden Screen**, **Meadow Totem**, **Twilight Caravan**, **Pepper Fox**, **Glass Manta**, **Festival Drummer**, **Bloom Sprite**. diff --git a/app.js b/app.js index 9859b1d..af460ca 100644 --- a/app.js +++ b/app.js @@ -5,7 +5,7 @@ const STORAGE_KEY = 'pixel-island-summoner:phase6b'; const LEGACY_STORAGE_KEYS = ['pixel-island-summoner:phase6a']; - const SAVE_SCHEMA = 23; + const SAVE_SCHEMA = 27; const WORLD_W = 144; const WORLD_H = 112; const TILE_W = 32; @@ -23,6 +23,10 @@ const MAX_DYNAMIC_STEPS_PER_FRAME = 3; const MAX_SPRITE_CACHE_ENTRIES = 260; const DEPTH_LOCAL_LIGHT_RESPONSE_MULTIPLIER = 5; + // TEMPORARY MODERATION / ADMIN EASEMENT: + // While this flag is true, every collection work can be deleted regardless of owner. + // Set back to false to restore the original owner-only deletion rule in shared worlds. + const TEMP_ALLOW_DELETE_ALL_WORKS = true; const COLOR_CODES = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; const PALETTE = buildPalette(); @@ -36,6 +40,14 @@ const EDITOR_HISTORY_LIMIT = 80; const MAX_EDITOR_DIMENSION = 64; const PHASE5_GUARDRAILS = { maxAssets: 220, maxWorldObjects: 1000, maxReports: 200, defaultDisplayLimit: 250, newArrivalSlots: 150, revivalSlots: 100, publishLimitFirstDay: 5, publishLimitTrusted: 10, upvoteDelaySlots: 20, downvoteAdvanceSlots: 25, upvoteRankCap: 50, maxParticles: 200, particleMinZoom: 0.72 }; + const REMOVED_LOW_QUALITY_SEED_ASSET_NAMES = new Set([ + 'Shell Rock', + 'Azure Minnow', + 'Firefly Swirl', + 'Leaf Sparrow', + 'Silver Trout', + 'Butterfly Fish' + ]); const editorActions = () => MODULES.EditorActions || null; @@ -1137,6 +1149,9 @@ } function canCurrentAccountDeleteAsset(asset, showToast = true) { + // Temporary measure: allow deleting any work so the collection can be cleaned up quickly. + // Revert by setting TEMP_ALLOW_DELETE_ALL_WORKS back to false above. + if (TEMP_ALLOW_DELETE_ALL_WORKS) return true; if (!isSharedWorld()) return true; const actor = currentAccountId(); if (!actor) { @@ -3453,10 +3468,11 @@ }) : null; const del = makeButton('Delete', (event) => { event?.stopPropagation?.(); deleteAsset(asset); }); del.classList.add('danger'); + const canDeleteAny = TEMP_ALLOW_DELETE_ALL_WORKS || isMine; actions.append(up, down, hide, remix); if (edit) actions.append(edit); if (move) actions.append(move); - if (isMine) actions.append(del); + if (canDeleteAny) actions.append(del); meta.append(actions); } else { const mini = document.createElement('span'); @@ -4015,7 +4031,7 @@ function updateClock() { const phase = getPhase(); const progress = phase.progress || 0; - const degrees = progress * 360 - 5; + const degrees = progress * 360; if (els.analogClockHand) els.analogClockHand.style.transform = `translate(-50%, -100%) rotate(${degrees.toFixed(2)}deg)`; if (els.analogClock) { els.analogClock.style.setProperty('--clock-rotate', `${degrees.toFixed(2)}deg`); @@ -4349,18 +4365,19 @@ function drawNightCursorGlow(time, phase) { - if (!areNightLightsActive(phase)) return; + if (!areNightLightsActive(phase) || !cursorScreen.active) return; const cursorPoint = getCursorLightScreenPoint(phase); if (!cursorPoint) return; const sx = cursorPoint.x; const sy = cursorPoint.y; - const pulse = 0.86 + Math.sin(time / 420) * 0.14; - const radius = Math.max(52, 86 * view.zoom) * pulse; + const pulse = 0.9 + Math.sin(time / 420) * 0.1; + const radius = Math.max(28, 54 * view.zoom) * pulse; ctx.save(); ctx.globalCompositeOperation = 'lighter'; const glow = ctx.createRadialGradient(sx, sy, 0, sx, sy, radius); - glow.addColorStop(0, 'rgba(142, 218, 255, .30)'); - glow.addColorStop(0.32, 'rgba(142, 218, 255, .13)'); + glow.addColorStop(0, 'rgba(198, 236, 255, .16)'); + glow.addColorStop(0.22, 'rgba(170, 225, 255, .09)'); + glow.addColorStop(0.6, 'rgba(142, 218, 255, .035)'); glow.addColorStop(1, 'rgba(142, 218, 255, 0)'); ctx.fillStyle = glow; ctx.beginPath(); @@ -4538,15 +4555,12 @@ function getCursorLightScreenPoint(phase) { if (cursorScreen.active) return { x: cursorScreen.x, y: cursorScreen.y }; - if (areNightLightsActive(phase)) return { x: cw / 2, y: ch / 2 }; return null; } function getLocalSpriteLights(info, phase) { if (visualSettings().enableLights === false || !info?.asset) return []; const lights = areNightLightsActive(phase) ? getAssetLightPointsForSide(info.asset, info.side) : []; - // The cursor is a local inspection light. It must affect depth shading when active, - // and at night it should also follow the blue-white center glow even before the mouse moves. const cursorPoint = getCursorLightScreenPoint(phase); if (cursorPoint) { const worldX = (cursorPoint.x - view.x) / view.zoom; @@ -4555,9 +4569,16 @@ const scale = info.asset.category === 'static' ? STATIC_SCALE : DYNAMIC_SCALE; const lx = local.x / scale - .5; const ly = local.y / scale - .5; - const reach = Math.max(3.5, Math.max(assetWidth(info.asset), assetHeight(info.asset)) * .72); - if (lx >= -reach && ly >= -reach && lx <= assetWidth(info.asset) + reach && ly <= assetHeight(info.asset) + reach) { - lights.push({ x: lx, y: ly, c: '#8edaff', cursor: true, intensity: 1.35 }); + const w = assetWidth(info.asset); + const h = assetHeight(info.asset); + const reach = Math.max(4.5, Math.max(w, h) * 0.86); + const margin = reach * 1.35; + const nearestX = clamp(lx, 0, Math.max(0, w - 1)); + const nearestY = clamp(ly, 0, Math.max(0, h - 1)); + const distToBounds = Math.hypot(lx - nearestX, ly - nearestY); + const spriteProximity = Math.pow(clamp(1 - distToBounds / Math.max(1, margin), 0, 1), 1.85); + if (spriteProximity > 0.01) { + lights.push({ x: lx, y: ly, c: '#d6ecff', cursor: true, intensity: 0.3 + spriteProximity * 0.82 }); } } return lights; @@ -4622,7 +4643,9 @@ const scale = asset.category === 'static' ? STATIC_SCALE : DYNAMIC_SCALE; const sprite = info.sprite; const sources = []; + const selfOwnerId = item.source?.id || asset.id; for (const source of lightSources) { + if (source.ownerId && source.ownerId === selfOwnerId) continue; const local = spriteLocalPoint(info, source.x, source.y); const dx = local.x - sprite.width / 2; const dy = local.y - sprite.height / 2; @@ -5029,13 +5052,13 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { const item = getSelectedDrawableItem(time); if (item) { const info = getSpriteDrawInfo(item, time, false); - const topPad = Math.max(14, Math.min(28, info.sprite.height * 0.18)); + const topPad = Math.max(6, Math.min(14, info.sprite.height * 0.1)); const baseY = info.pos.y + info.anchorY - info.sprite.height; return { x: info.drawX + info.sprite.width / 2, y: baseY - topPad, asset: item.asset, objectId: item.source?.id || selectedObject.id }; } const cached = lastRenderedSpriteInfo.get(selectedObject.id); if (!cached) return null; - const topPad = Math.max(14, Math.min(28, cached.sprite.height * 0.18)); + const topPad = Math.max(6, Math.min(14, cached.sprite.height * 0.1)); const baseY = cached.pos && Number.isFinite(cached.anchorY) ? cached.pos.y + cached.anchorY - cached.sprite.height : cached.drawY; return { x: cached.drawX + cached.sprite.width / 2, y: baseY - topPad, asset: cached.asset, objectId: selectedObject.id }; } @@ -5324,11 +5347,12 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { const auraRadius = radius * 1.12; if (sx < -auraRadius || sy < -auraRadius || sx > cw + auraRadius || sy > ch + auraRadius) continue; - // Light cores are drawn after the night overlay and do not inherit night darkness. - ctx.globalCompositeOperation = 'source-over'; + // Light cores are additive so they brighten art like the cursor glow instead of + // laying a flat translucent disk over the sprite. + ctx.globalCompositeOperation = 'lighter'; const core = ctx.createRadialGradient(sx, sy, 0, sx, sy, Math.max(3, radius * 0.48)); - core.addColorStop(0, hexToRgba(source.color, .48 * intensity)); - core.addColorStop(.34, hexToRgba(source.color, .22 * intensity)); + core.addColorStop(0, hexToRgba(source.color, .36 * intensity)); + core.addColorStop(.28, hexToRgba(source.color, .18 * intensity)); core.addColorStop(1, hexToRgba(source.color, .00)); ctx.fillStyle = core; ctx.beginPath(); @@ -5721,7 +5745,7 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { if (expanded && Array.isArray(expanded.assets)) { const loadedSchema = Number(expanded.schema || 0); // v16 reset local art because the palette code mapping and seed artwork were intentionally rebuilt. - // v17 expanded the default gallery. v18 added more nature-themed defaults. v19 added giant showcase objects. v20 added more animals, fish, and birds. v21 added human and artificial-object defaults. v22 widened small-sprite hitboxes and fixed night cursor depth light. v23 strengthens multi-light depth response and upgrades lower-quality seed art while preserving v16+ user state. + // v17 expanded the default gallery. v18 added more nature-themed defaults. v19 added giant showcase objects. v20 added more animals, fish, and birds. v21 added human and artificial-object defaults. v22 widened small-sprite hitboxes and fixed night cursor depth light. v23 strengthens multi-light depth response and upgrades lower-quality seed art while preserving v16+ user state. v24 sharpens near-light depth reflection falloff and expands the outlined default gallery. v25 fixes gray local-light wash, brings the selection bubble closer to sprite tops, and adds large heritage/masterpiece default works. v26 removes the single-light gray bloom regression, smooths cursor-light falloff, and removes the unwanted blue cursor halo artifact. v27 reduces gray bloom from asset-mounted lights, fixes the clock-hand offset, temporarily enables delete-for-all works, and expands the default gallery again. if (loadedSchema < 16) return seedState(); return mergeDefaultGallery(normalizeState(expanded)); } @@ -6178,10 +6202,150 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { lightPixels: [{ x: 13, y: 12 }, { x: 14, y: 12 }, { x: 12, y: 13 }, { x: 15, y: 13 }], lightColor: '#ffe99a', door: { x: 14, y: 24 } + }), + makeAssetSized('Moon Jelly Aquarium', 'static', 'building', drawMoonJellyAquarium(), 24, 28, { + depthPixels: drawMoonJellyAquariumDepth(), + lightPixels: [{ x: 11, y: 0 }, { x: 12, y: 0 }, { x: 10, y: 10 }, { x: 13, y: 10 }, { x: 11, y: 20 }, { x: 12, y: 20 }], + lightColor: '#ffe7a6', + door: { x: 11, y: 24 } + }), + makeAssetSized('Aurora Observatory', 'static', 'building', drawAuroraObservatory(), 28, 28, { + depthPixels: filledDepthFromPixelsSized(drawAuroraObservatory(), 28, 28), + lightPixels: [{ x: 13, y: 2 }, { x: 14, y: 2 }, { x: 9, y: 13 }, { x: 18, y: 13 }, { x: 13, y: 23 }], + lightColor: '#d9eeff', + door: { x: 13, y: 24 } + }), + makeAssetSized('Hearthwind Mill', 'static', 'building', drawHearthwindMill(), 24, 28, { + depthPixels: filledDepthFromPixelsSized(drawHearthwindMill(), 24, 28), + lightPixels: [{ x: 8, y: 13 }, { x: 15, y: 13 }, { x: 11, y: 18 }], + lightColor: '#ffe6a5', + door: { x: 11, y: 22 } + }), + makeAssetSized('Tideglass Lighthouse', 'static', 'building', drawTideglassLighthouse(), 20, 36, { + depthPixels: filledDepthFromPixelsSized(drawTideglassLighthouse(), 20, 36), + lightPixels: [{ x: 8, y: 2 }, { x: 9, y: 2 }, { x: 8, y: 16 }, { x: 8, y: 24 }], + lightColor: '#f8f0bb', + door: { x: 8, y: 33 } + }), + makeAssetSized('Mossrail Depot', 'static', 'building', drawMossrailDepot(), 32, 20, { + depthPixels: filledDepthFromPixelsSized(drawMossrailDepot(), 32, 20), + lightPixels: [{ x: 6, y: 8 }, { x: 13, y: 8 }, { x: 20, y: 8 }, { x: 26, y: 8 }], + lightColor: '#ffe1a0', + door: { x: 15, y: 16 } + }), + makeAssetSized('Lantern Library', 'static', 'building', drawLanternLibrary(), 28, 24, { + depthPixels: filledDepthFromPixelsSized(drawLanternLibrary(), 28, 24), + lightPixels: [{ x: 8, y: 7 }, { x: 19, y: 7 }, { x: 13, y: 16 }, { x: 14, y: 16 }], + lightColor: '#ffe8b0', + door: { x: 13, y: 18 } + }), + makeAssetSized('Velvet Theater', 'static', 'building', drawVelvetTheater(), 28, 20, { + depthPixels: filledDepthFromPixelsSized(drawVelvetTheater(), 28, 20), + lightPixels: [{ x: 5, y: 1 }, { x: 9, y: 1 }, { x: 13, y: 1 }, { x: 17, y: 1 }, { x: 21, y: 1 }, { x: 13, y: 14 }], + lightColor: '#ffd19a', + door: { x: 13, y: 16 } + }), + makeAssetSized('Bloom Bridge Gate', 'static', 'nature', drawBloomBridgeGate(), 24, 24, { + depthPixels: filledDepthFromPixelsSized(drawBloomBridgeGate(), 24, 24), + particlePixels: [{ x: 7, y: 2, c: nearestPaletteCode('#ffd4ea'), dir: 'up' }, { x: 16, y: 2, c: nearestPaletteCode('#ffd4ea'), dir: 'up' }] + }), + makeAssetSized('Starreef Submarine', 'static', 'ship', drawStarreefSubmarine(), 32, 16, { + depthPixels: filledDepthFromPixelsSized(drawStarreefSubmarine(), 32, 16), + lightPixels: [{ x: 12, y: 3 }, { x: 15, y: 7 }, { x: 20, y: 7 }], + lightColor: '#c5f1ff' + }), + makeAssetSized('Astrolabe Courier', 'dynamic', 'human', drawAstrolabeCourierRight(), 12, 16, { + depthPixels: filledDepthFromPixelsSized(drawAstrolabeCourierRight(), 12, 16), + lightPixels: [{ x: 6, y: 5 }], + lightColor: '#d9eeff' + }), + makeAssetSized('Puddle Toad', 'dynamic', 'animal', drawPuddleToadRight(), 12, 10, { + depthPixels: filledDepthFromPixelsSized(drawPuddleToadRight(), 12, 10) + }), + makeAssetSized('Ribbon Swan', 'dynamic', 'bird', drawRibbonSwanRight(), 12, 12, { + depthPixels: filledDepthFromPixelsSized(drawRibbonSwanRight(), 12, 12) + }), + makeAssetSized('Lantern Beetle', 'dynamic', 'animal', drawLanternBeetleRight(), 12, 12, { + depthPixels: filledDepthFromPixelsSized(drawLanternBeetleRight(), 12, 12), + lightPixels: [{ x: 5, y: 3 }], + lightColor: '#fff1a8' + }), + makeAssetSized('Smile Portrait', 'static', 'building', drawSmilePortrait(), 24, 32, { + depthPixels: filledDepthFromPixelsSized(drawSmilePortrait(), 24, 32) + }), + makeAssetSized('Great Wave Panel', 'static', 'nature', drawGreatWavePanel(), 32, 24, { + depthPixels: filledDepthFromPixelsSized(drawGreatWavePanel(), 32, 24) + }), + makeAssetSized('Sunflower Still Life', 'static', 'nature', drawSunflowerStillLife(), 24, 32, { + depthPixels: filledDepthFromPixelsSized(drawSunflowerStillLife(), 24, 32) + }), + makeAssetSized('Rosetta Stela', 'static', 'building', drawRosettaStela(), 24, 32, { + depthPixels: filledDepthFromPixelsSized(drawRosettaStela(), 24, 32) + }), + makeAssetSized('Pharaoh Mask', 'static', 'building', drawPharaohMask(), 24, 32, { + depthPixels: filledDepthFromPixelsSized(drawPharaohMask(), 24, 32) + }), + makeAssetSized('Stone Circle', 'static', 'nature', drawStoneCircle(), 32, 24, { + depthPixels: filledDepthFromPixelsSized(drawStoneCircle(), 32, 24) + }), + makeAssetSized('Terracotta Sentinel', 'static', 'building', drawTerracottaSentinel(), 20, 32, { + depthPixels: filledDepthFromPixelsSized(drawTerracottaSentinel(), 20, 32) + }), + makeAssetSized('Rain Bell Tower', 'static', 'building', drawRainBellTower(), 20, 36, { + depthPixels: filledDepthFromPixelsSized(drawRainBellTower(), 20, 36), + lightPixels: [{ x: 9, y: 11 }, { x: 9, y: 19 }], + lightColor: '#fff0b8', + door: { x: 9, y: 33 } + }), + makeAssetSized('Crimson Pagoda', 'static', 'building', drawCrimsonPagoda(), 24, 32, { + depthPixels: filledDepthFromPixelsSized(drawCrimsonPagoda(), 24, 32), + lightPixels: [{ x: 8, y: 12 }, { x: 15, y: 12 }, { x: 11, y: 22 }], + lightColor: '#ffd38a', + door: { x: 11, y: 28 } + }), + makeAssetSized('Meteor Forge', 'static', 'building', drawMeteorForge(), 32, 24, { + depthPixels: filledDepthFromPixelsSized(drawMeteorForge(), 32, 24), + lightPixels: [{ x: 8, y: 10 }, { x: 23, y: 10 }, { x: 15, y: 16 }], + lightColor: '#ffb36b', + door: { x: 15, y: 19 } + }), + makeAssetSized('Ink Garden Screen', 'static', 'nature', drawInkGardenScreen(), 32, 24, { + depthPixels: filledDepthFromPixelsSized(drawInkGardenScreen(), 32, 24) + }), + makeAssetSized('Meadow Totem', 'static', 'nature', drawMeadowTotem(), 20, 28, { + depthPixels: filledDepthFromPixelsSized(drawMeadowTotem(), 20, 28) + }), + makeAssetSized('Twilight Caravan', 'static', 'ship', drawTwilightCaravan(), 32, 16, { + depthPixels: filledDepthFromPixelsSized(drawTwilightCaravan(), 32, 16), + lightPixels: [{ x: 9, y: 7 }, { x: 15, y: 7 }, { x: 22, y: 7 }], + lightColor: '#ffdba0' + }), + makeAssetSized('Pepper Fox', 'dynamic', 'animal', drawPepperFoxRight(), 16, 16, { + depthPixels: filledDepthFromPixelsSized(drawPepperFoxRight(), 16, 16) + }), + makeAssetSized('Glass Manta', 'dynamic', 'fish', drawGlassMantaRight(), 16, 12, { + depthPixels: filledDepthFromPixelsSized(drawGlassMantaRight(), 16, 12), + lightPixels: [{ x: 7, y: 5 }], + lightColor: '#9ef4ff' + }), + makeAssetSized('Festival Drummer', 'dynamic', 'human', drawFestivalDrummerRight(), 14, 16, { + depthPixels: filledDepthFromPixelsSized(drawFestivalDrummerRight(), 14, 16) + }), + makeAssetSized('Bloom Sprite', 'dynamic', 'animal', drawBloomSpriteRight(), 12, 12, { + depthPixels: filledDepthFromPixelsSized(drawBloomSpriteRight(), 12, 12), + lightPixels: [{ x: 5, y: 3 }], + lightColor: '#ffe7a8' }) ]; const idByName = Object.fromEntries(assets.map((a) => [a.name, a.id])); + const removedLowQualitySeedAssetIds = new Set([...REMOVED_LOW_QUALITY_SEED_ASSET_NAMES].map((name) => idByName[name]).filter(Boolean)); + const applySeedQualityFilter = (gallery) => ({ + ...gallery, + assets: gallery.assets.filter((asset) => !removedLowQualitySeedAssetIds.has(asset.id)), + placed: gallery.placed.filter((object) => !removedLowQualitySeedAssetIds.has(object.assetId)), + dynamicSummons: gallery.dynamicSummons.filter((object) => !removedLowQualitySeedAssetIds.has(object.assetId)) + }); const whalePos = findNearestTerrain('water', 62, 58); const koiPos = findNearestTerrain('water', 66, 60); const skiffPos = findNearestTerrain('water', 56, 58); @@ -6190,7 +6354,8 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { const sunsetKoiPos = findNearestTerrain('water', 60, 61); const troutPos = findNearestTerrain('water', 75, 56); const butterflyFishPos = findNearestTerrain('water', 68, 63); - return { + const starreefPos = findNearestTerrain('water', 118, 84); + return applySeedQualityFilter({ assets, placed: [ { id: uid(), assetId: idByName['Crescent Tea House'], ownerAccountId: 'island-team', x: 36, y: 36, placedAt: now, publishedAt: now, version: 1 }, @@ -6223,7 +6388,29 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { { id: uid(), assetId: idByName['Moonfall Cascade'], ownerAccountId: 'island-team', x: 72, y: 35, placedAt: now, publishedAt: now, version: 1 }, { id: uid(), assetId: idByName['Sunblossom Gate'], ownerAccountId: 'island-team', x: 34, y: 47, placedAt: now, publishedAt: now, version: 1 }, { id: uid(), assetId: idByName['Echo Cavern'], ownerAccountId: 'island-team', x: 98, y: 42, placedAt: now, publishedAt: now, version: 1 }, - { id: uid(), assetId: idByName['Worldroot Shrine'], ownerAccountId: 'island-team', x: 58, y: 31, placedAt: now, publishedAt: now, version: 1 } + { id: uid(), assetId: idByName['Worldroot Shrine'], ownerAccountId: 'island-team', x: 58, y: 31, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Moon Jelly Aquarium'], ownerAccountId: 'island-team', x: 112, y: 38, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Aurora Observatory'], ownerAccountId: 'island-team', x: 70, y: 26, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Hearthwind Mill'], ownerAccountId: 'island-team', x: 16, y: 56, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Tideglass Lighthouse'], ownerAccountId: 'island-team', x: 122, y: 28, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Mossrail Depot'], ownerAccountId: 'island-team', x: 104, y: 64, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Lantern Library'], ownerAccountId: 'island-team', x: 38, y: 29, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Velvet Theater'], ownerAccountId: 'island-team', x: 86, y: 31, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Bloom Bridge Gate'], ownerAccountId: 'island-team', x: 73, y: 81, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Starreef Submarine'], ownerAccountId: 'island-team', ...starreefPos, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Smile Portrait'], ownerAccountId: 'island-team', x: 13, y: 55, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Great Wave Panel'], ownerAccountId: 'island-team', x: 68, y: 51, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Sunflower Still Life'], ownerAccountId: 'island-team', x: 34, y: 80, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Rosetta Stela'], ownerAccountId: 'island-team', x: 122, y: 74, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Pharaoh Mask'], ownerAccountId: 'island-team', x: 93, y: 27, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Stone Circle'], ownerAccountId: 'island-team', x: 73, y: 87, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Terracotta Sentinel'], ownerAccountId: 'island-team', x: 111, y: 69, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Rain Bell Tower'], ownerAccountId: 'island-team', x: 126, y: 43, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Crimson Pagoda'], ownerAccountId: 'island-team', x: 26, y: 35, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Meteor Forge'], ownerAccountId: 'island-team', x: 47, y: 66, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Ink Garden Screen'], ownerAccountId: 'island-team', x: 86, y: 77, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Meadow Totem'], ownerAccountId: 'island-team', x: 22, y: 76, placedAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Twilight Caravan'], ownerAccountId: 'island-team', x: 18, y: 90, placedAt: now, publishedAt: now, version: 1 } ], dynamicSummons: [ { id: uid(), assetId: idByName['Lantern Cat'], ownerAccountId: 'island-team', homeX: 38, homeY: 39, createdAt: now, publishedAt: now, version: 1 }, @@ -6254,9 +6441,17 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { { id: uid(), assetId: idByName['Tea Robot'], ownerAccountId: 'island-team', homeX: 104, homeY: 59, createdAt: now, publishedAt: now, version: 1 }, { id: uid(), assetId: idByName['Balloon Vendor'], ownerAccountId: 'island-team', homeX: 98, homeY: 58, createdAt: now, publishedAt: now, version: 1 }, { id: uid(), assetId: idByName['Jelly Comet'], ownerAccountId: 'island-team', homeX: 112, homeY: 53, createdAt: now, publishedAt: now, version: 1 }, - { id: uid(), assetId: idByName['Courier Bike'], ownerAccountId: 'island-team', homeX: 88, homeY: 60, createdAt: now, publishedAt: now, version: 1 } + { id: uid(), assetId: idByName['Courier Bike'], ownerAccountId: 'island-team', homeX: 88, homeY: 60, createdAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Astrolabe Courier'], ownerAccountId: 'island-team', homeX: 72, homeY: 28, createdAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Puddle Toad'], ownerAccountId: 'island-team', homeX: 74, homeY: 79, createdAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Ribbon Swan'], ownerAccountId: 'island-team', homeX: 56, homeY: 37, createdAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Lantern Beetle'], ownerAccountId: 'island-team', homeX: 40, homeY: 30, createdAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Pepper Fox'], ownerAccountId: 'island-team', homeX: 28, homeY: 71, createdAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Glass Manta'], ownerAccountId: 'island-team', homeX: 122, homeY: 86, createdAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Festival Drummer'], ownerAccountId: 'island-team', homeX: 52, homeY: 67, createdAt: now, publishedAt: now, version: 1 }, + { id: uid(), assetId: idByName['Bloom Sprite'], ownerAccountId: 'island-team', homeX: 92, homeY: 79, createdAt: now, publishedAt: now, version: 1 } ] - }; + }); } function mergeDefaultGallery(baseState) { @@ -6265,6 +6460,18 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { baseState.assets = Array.isArray(baseState.assets) ? baseState.assets : []; baseState.placed = Array.isArray(baseState.placed) ? baseState.placed : []; baseState.dynamicSummons = Array.isArray(baseState.dynamicSummons) ? baseState.dynamicSummons : []; + const removedExistingSeedAssetIds = new Set(baseState.assets + .filter((asset) => REMOVED_LOW_QUALITY_SEED_ASSET_NAMES.has(asset.name) && (asset.ownerAccountId === 'island-team' || asset.author === 'Island Team')) + .map((asset) => asset.id)); + if (removedExistingSeedAssetIds.size) { + baseState.assets = baseState.assets.filter((asset) => !removedExistingSeedAssetIds.has(asset.id)); + baseState.placed = baseState.placed.filter((object) => !removedExistingSeedAssetIds.has(object.assetId)); + baseState.dynamicSummons = baseState.dynamicSummons.filter((object) => !removedExistingSeedAssetIds.has(object.assetId)); + for (const assetId of removedExistingSeedAssetIds) { + delete baseState.hiddenAssets?.[assetId]; + delete baseState.assetVotes?.[assetId]; + } + } const assetByName = new Map(baseState.assets.map((asset) => [asset.name, asset])); const assetIdByName = new Map(baseState.assets.map((asset) => [asset.name, asset.id])); for (const seededAsset of seeded.assets) { @@ -6942,6 +7149,17 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { return shadeAssetPixelColor(hex, visualSettings().enableLights === false ? 0 : depth, 0, 0, 1, renderPhase); } + function depthLocalLightResponse(distance, reach) { + const normalized = clamp(distance / Math.max(0.0001, reach), 0, 1.75); + // Keep a broad bright plateau so distance is not the main factor, while + // still giving the light source itself a strong flare and a soft tail. + const plateau = 1 - Math.pow(Math.min(normalized, 1), 1.12) * 0.2; + const shoulder = Math.pow(clamp(1 - normalized / 0.92, 0, 1), 1.08); + const hotspot = Math.pow(clamp(1 - normalized / 0.18, 0, 1), 4.1); + const tail = Math.pow(clamp(1 - normalized / 1.55, 0, 1), 2.0) * 0.42; + return clamp(plateau * 0.72 + shoulder * 0.36 + hotspot * 0.92 + tail, 0, 1.76); + } + function shadeAssetPixelColor(hex, depth, x, y, width, phase, pixels = null, depths = null, lights = [], height = width) { const rgb = parseHex(hex); if (!rgb) return hex; @@ -6968,40 +7186,63 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { for (const light of lights) { const lc = parseHex(light.c || '#ffd86a'); if (!lc) continue; + const isAssetLight = !!light.assetLight; const dist = Math.hypot((light.x + 0.5) - (x + 0.5), (light.y + 0.5) - (y + 0.5)); - const reach = Math.max(2.25, size * 0.46); + const reach = isAssetLight ? Math.max(1.85, size * 0.24) : Math.max(2.25, size * 0.46); const t = 1 - clamp(dist / reach, 0, 1); - if (t <= 0) continue; - const sourceIntensity = clamp(Number(light.intensity ?? 1) || 1, 0.25, 1.85); + const sourceHotspot = Math.pow(clamp(1 - dist / Math.max(0.001, reach * 0.24), 0, 1), 2.8); + const assetResponse = clamp(Math.pow(t, 1.45) * 0.52 + sourceHotspot * 1.18, 0, 1.58); + const depthResponse = depth ? (isAssetLight ? assetResponse : depthLocalLightResponse(dist, reach)) : (isAssetLight ? assetResponse : t); + const response = depth ? depthResponse : t; + if (response <= 0) continue; + const sourceIntensity = clamp(Number(light.intensity ?? 1) || 1, 0.18, 1.85); const edge = getDepthLightFacing(depth, x, y, width, pixels, depths, light.x, light.y, height); - const localDepthMultiplier = depth ? DEPTH_LOCAL_LIGHT_RESPONSE_MULTIPLIER : 1.15; - const depthFactor = depth > 0 ? 0.82 + edge * 0.46 : depth < 0 ? 0.56 + edge * 0.24 : 0.34 + edge * 0.08; - const strength = t * t * (6 + Math.abs(depth) * 4) * depthFactor * sourceIntensity * localDepthMultiplier; - const mix = Math.min(depth ? 0.78 : 0.32, (0.08 + t * (depth ? 0.18 : 0.12)) * sourceIntensity * (depth ? 1.85 : 1)); + const depthEdgePresence = isAssetLight + ? (0.18 + Math.pow(Math.max(0, edge), 1.4) * 0.74 + sourceHotspot * 0.7) + : (0.06 + edge * 1.24); + const edgePresence = depth ? depthEdgePresence : 1; + const localDepthMultiplier = depth ? DEPTH_LOCAL_LIGHT_RESPONSE_MULTIPLIER : 1.1; + const strengthBase = depth + ? (isAssetLight ? (sourceHotspot * 0.34 + depthResponse * 0.045) : (0.12 + depthResponse * 0.22)) + : t * t; + const strength = strengthBase * (isAssetLight ? (10.5 + sourceHotspot * 18 + Math.abs(depth) * 1.2) : (4.2 + Math.abs(depth) * 2.6)) * edgePresence * sourceIntensity * localDepthMultiplier; + const mix = Math.min(depth ? (isAssetLight ? 0.055 : 0.48) : (isAssetLight ? 0.06 : 0.24), (0.008 + response * (depth ? (isAssetLight ? 0.012 : 0.075) : (isAssetLight ? 0.028 : 0.10))) * sourceIntensity * (depth ? (isAssetLight ? 0.7 : 1.35) : 1)); r = lerp(r, lc.r + strength, mix); g = lerp(g, lc.g + strength * 0.82, mix * 0.94); - b = lerp(b, lc.b + strength * 0.74, mix * 0.88); + b = lerp(b, lc.b + strength * 0.74, mix * 0.9); - const tintPower = Math.pow(t, 1.35) * sourceIntensity * (depth ? 0.17 * DEPTH_LOCAL_LIGHT_RESPONSE_MULTIPLIER : 0.04) * (0.72 + edge * 0.72); + const colorWash = (depth ? (isAssetLight ? 0.004 : 0.045) : (isAssetLight ? 0.006 : 0.03)) * sourceIntensity * edgePresence * (depth ? (isAssetLight ? sourceHotspot : (0.26 + depthResponse * 0.22)) : t); + r += (lc.r - 152) * colorWash; + g += (lc.g - 152) * colorWash * 0.96; + b += (lc.b - 152) * colorWash * 0.92; + + const tintBase = depth ? (isAssetLight ? sourceHotspot * 0.11 : (0.12 + depthResponse * 0.18)) : Math.pow(t, 1.25); + const tintPower = tintBase * sourceIntensity * (depth ? (isAssetLight ? 0.016 : 0.12) * DEPTH_LOCAL_LIGHT_RESPONSE_MULTIPLIER : (isAssetLight ? 0.012 : 0.03)) * (depth ? edgePresence : 1); localTintR += lc.r * tintPower; localTintG += lc.g * tintPower; localTintB += lc.b * tintPower; localTintWeight += tintPower; - localLift += Math.pow(t, 2.0) * sourceIntensity * (depth ? 7.5 * DEPTH_LOCAL_LIGHT_RESPONSE_MULTIPLIER : 4.5) * (0.65 + edge * 0.75); + const liftBase = depth ? (isAssetLight ? (sourceHotspot * 0.42 + Math.pow(t, 2.2) * 0.035) : (0.12 + depthResponse * 0.16)) : Math.pow(t, 1.9); + localLift += liftBase * sourceIntensity * (depth ? (isAssetLight ? 0.85 : 2.4) * DEPTH_LOCAL_LIGHT_RESPONSE_MULTIPLIER : 3.6) * (depth ? edgePresence : 1); } } + const litBeforeQuantization = { r, g, b }; const quantized = quantizePixelShade(rgb, { r, g, b }, activePhase, depth); r = clamp(quantized.r, 0, 255); g = clamp(quantized.g, 0, 255); b = clamp(quantized.b, 0, 255); if (localTintWeight > 0) { const inv = 1 / localTintWeight; - const tintMix = clamp(localTintWeight / (depth ? 3.2 : 8.0), 0, depth ? 0.64 : 0.18); - const lift = clamp(localLift, 0, depth ? 72 : 14); - r = lerp(clamp(r + lift, 0, 255), localTintR * inv, tintMix); - g = lerp(clamp(g + lift * 0.9, 0, 255), localTintG * inv, tintMix * 0.94); - b = lerp(clamp(b + lift * 0.82, 0, 255), localTintB * inv, tintMix * 0.9); + const tintMix = clamp(localTintWeight / (depth ? 6.2 : 9.0), 0, depth ? 0.34 : 0.16); + const lift = clamp(localLift, 0, depth ? 11 : 12); + const chromaRestore = clamp(localTintWeight / (depth ? 1.15 : 8.8), 0, depth ? 0.9 : 0.16); + r = lerp(clamp(r + lift, 0, 255), litBeforeQuantization.r, chromaRestore); + g = lerp(clamp(g + lift * 0.88, 0, 255), litBeforeQuantization.g, chromaRestore); + b = lerp(clamp(b + lift * 0.8, 0, 255), litBeforeQuantization.b, chromaRestore); + r = lerp(r, localTintR * inv, tintMix); + g = lerp(g, localTintG * inv, tintMix * 0.95); + b = lerp(b, localTintB * inv, tintMix * 0.92); } return `#${Math.round(clamp(r, 0, 255)).toString(16).padStart(2,'0')}${Math.round(clamp(g, 0, 255)).toString(16).padStart(2,'0')}${Math.round(clamp(b, 0, 255)).toString(16).padStart(2,'0')}`; } @@ -7045,7 +7286,9 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { return lights.map((p) => ({ x: asset.category === 'dynamic' && side === 'left' ? w - 1 - p.x : p.x, y: p.y, - c: colorToHex(p.c || asset.meta?.lightColor || nearestPaletteCode('#ffd86a')) + c: colorToHex(p.c || asset.meta?.lightColor || nearestPaletteCode('#ffd86a')), + assetLight: true, + intensity: Number.isFinite(p.intensity) ? p.intensity : 0.92 })).filter((p) => Number.isFinite(p.x) && Number.isFinite(p.y) && p.x >= 0 && p.y >= 0 && p.x < w && p.y < h); } @@ -7074,6 +7317,21 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { return edgeDirs; } + function getDepthCornerStrength(edgeDirs) { + if (!edgeDirs?.length) return 0; + if (edgeDirs.length < 2) return 0; + let orthogonalPairs = 0; + for (let i = 0; i < edgeDirs.length; i++) { + for (let j = i + 1; j < edgeDirs.length; j++) { + const [ax, ay] = edgeDirs[i]; + const [bx, by] = edgeDirs[j]; + if ((ax && by) || (ay && bx)) orthogonalPairs++; + } + } + if (!orthogonalPairs) return edgeDirs.length >= 3 ? 0.6 : 0; + return clamp(0.42 + orthogonalPairs * 0.28 + (edgeDirs.length >= 3 ? 0.18 : 0), 0, 1.35); + } + function getDepthCellSelfShadow(depth, x, y, width, pixels, depths, phase, height = width) { if (!depth || !pixels || !depths) return 0; const edgeDirs = collectDepthEdgeDirs(x, y, width, pixels, depths, depth, height); @@ -7113,20 +7371,26 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { const nx = x + dx, ny = y + dy; return nx < 0 || ny < 0 || nx >= width || ny >= height || !pixels[ny * width + nx]; }); + const cornerStrength = getDepthCornerStrength(edgeDirs); const reach = Math.max(2.25, Math.max(width, height) * 0.46); let total = 0; for (const light of lights) { if (!light) continue; const d = Math.hypot(light.x - x, light.y - y); - const distanceFalloff = 1 - clamp(d / reach, 0, 1); - if (distanceFalloff <= 0) continue; + const distanceResponse = depthLocalLightResponse(d, reach); + if (distanceResponse <= 0) continue; const facing = getDepthLightFacing(depth, x, y, width, pixels, depths, light.x, light.y, height); if (!facing) continue; const sourceIntensity = clamp(Number(light.intensity ?? 1) || 1, 0.25, 1.85); - const edgeStrength = outerEdge ? 0.72 : 1; - total += facing * edgeStrength * distanceFalloff * distanceFalloff * sourceIntensity * (depth > 0 ? 20 : 14) * DEPTH_LOCAL_LIGHT_RESPONSE_MULTIPLIER; + const nearSource = Math.pow(clamp(1 - d / Math.max(1.2, reach * 0.18), 0, 1), 2.3); + const plateau = 0.74 + distanceResponse * 0.34; + const edgeFocus = 0.4 + facing * 0.95; + const edgeStrength = outerEdge ? 1.08 : 0.94; + const cornerBoost = 1 + cornerStrength * (0.9 + facing * 0.38); + const sourceBoost = 1 + nearSource * 1.12; + total += plateau * edgeFocus * edgeStrength * cornerBoost * sourceBoost * sourceIntensity * (depth > 0 ? 8.2 : 6.4) * DEPTH_LOCAL_LIGHT_RESPONSE_MULTIPLIER; } - return clamp(total, 0, depth > 0 ? 150 : 105); + return clamp(total, 0, depth > 0 ? 172 : 126); } function resizePixels(source, oldSize, newSize) { @@ -7386,6 +7650,83 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { }); } + function drawMoonJellyAquarium() { + return artRowsSized([ + '...........YY...........', + '..........YCCY..........', + '.........YNCCNY.........', + '........NQBBBBQN........', + '.......NQBAAAABQN.......', + '......NQBAACCAABQN......', + '......NBAAAAAAAABN......', + '.....NQBAAPPPPAABQN.....', + '.....NBAAPPYYPPAABN.....', + '....NQBAAPYYYYPPAABQN...', + '....NBAAPYYYYYYPPAABN...', + '....NBAAPYYYYYYPPAABN...', + '...NQBAAPYYYYYYPPAABQN..', + '...N.BAAPQQQQQQPPAAB.N..', + '...N.NYYQNNNNNNQYYN.N...', + '...N.TSYQY....YQYST.N...', + '....NTTSY......YSTTN....', + '....NSSSY......YSSSN....', + '....NSSSY..DD..YSSSN....', + '....NSSSY.DDDD.YSSSN....', + '....NSSSYYYYYYYYSSSN....', + '....NSSSTTTTTTTTSSSN....', + '....NTTTTSDDDDSTTTTN....', + '.....NTTTSD...DSTTTN....', + '.....NDDDSS...SSDDDN....', + '......NDDDDNNNDDDDN.....', + '.......NNNNNNNNNNN......', + '........................' + ], { + N: '#1e2030', + Y: '#ffe8a1', + C: '#f7ffff', + Q: '#9b7dff', + B: '#6dd8f0', + A: '#a6f5ff', + P: '#ff8cc8', + T: '#5f5968', + S: '#8a7f91', + D: '#3c3348' + }, 24, 28); + } + + function drawMoonJellyAquariumDepth() { + return depthRowsSized([ + '...........^^...........', + '..........^^^^..........', + '.........^^^^^^.........', + '........^^^^^^^^........', + '.......^^^^^^^^^^.......', + '......^^^^^^^^^^^^......', + '......^^^^^^^^^^^^......', + '.....^^^^^^..^^^^^^.....', + '.....^^^^^....^^^^^.....', + '....^^^^^^....^^^^^^....', + '....^^^^^^....^^^^^^....', + '....^^^^^^....^^^^^^....', + '...^^^^^^^....^^^^^^^...', + '...^^^^^^......^^^^^^...', + '...^^..^^......^^..^^...', + '...^^..^^......^^..^^...', + '....^^..^......^..^^....', + '....^^..^......^..^^....', + '....^^^^^..--..^^^^^....', + '....^^^^^.----.^^^^^....', + '....^^^^^^^^^^^^^^^^....', + '....^^^^^------^^^^^....', + '....^^^^^------^^^^^....', + '.....^^^^------^^^^.....', + '.....^^^^^....^^^^^.....', + '......^^^^^..^^^^^......', + '.......^^^^^^^^^^.......', + '........................' + ], 24, 28); + } + function drawCrescentTeaHouseDepth() { return depthRows([ '.......^^.......', @@ -9119,6 +9460,859 @@ function drawShipRipples(pos, time, seedValue = '', asset = null) { } + function drawAuroraObservatory() { + return artRowsSized([ + '............NNNN............', + '..........NNYYYYNN..........', + '.........NYYCCCCYYN.........', + '........NYYCCCCCCYYN........', + '.......NYYCCBBBBCCYYN.......', + '......NYYCBBBBBBBBCYYN......', + '......NYYBBBBBBBBBBYYN......', + '.....NYYBBBBBBBBBBBBYYN.....', + '.....NYYBBBBBBBBBBBBYYN.....', + '.....NYYYYYYYYYYYYYYYYN.....', + '....NNWWWWWWNNWWWWWWWWNN....', + '....NWWWWWWN..NWWWWWWWWN....', + '...NNWWWLLWNNNNWWLLWWWNN....', + '...NWWWLLLLWWWWLLLLWWWWN....', + '...NWWLLLLLLWWLLLLLLWWWN....', + '...NWWLLDDLLWWLLDDLLWWWN....', + '...NWWLLLLLLWWLLLLLLWWWN....', + '...NWWWWWWWWWWWWWWWWWWWN....', + '...NWWGGGGGGGGGGGGGGWWWN....', + '...NWWGTTTGGTTTTGGTTGWWN....', + '...NWWGTTTGGTTTTGGTTGWWN....', + '...NWWGGGGGGGGGGGGGGWWWN....', + '...NWWGGTTTGGGGGGTTGWWWN....', + '...NWWGGTTTGGDDGGTTGWWWN....', + '...NWWGGGGGGDDGGGGGGWWWN....', + '....NWWWWWWWWDDWWWWWWWN.....', + '....NNNNNNNNNNNNNNNNNN......', + '............................' + ], { + N: '#212532', Y: '#8b74dd', C: '#d9edff', B: '#8fb7f5', W: '#746453', L: '#fff0b4', G: '#c1ab84', T: '#70563f', D: '#3d2f28' + }, 28, 28); + } + + function drawHearthwindMill() { + return artRowsSized([ + '..........NNNN..........', + '.........NYYYYN.........', + '.........NYWWYN.........', + '........NYYWWYYN........', + '........NNNWWNNN........', + '.......N..NWWN..N.......', + '...NNNNN..NWWN..NNNNN...', + '..NPPPPNNNNWWNNNNPPPPN..', + '..NPPPPPPNNWWNNPPPPPPN..', + '..NPPPPPPPNNNNPPPPPPPN..', + '..NPPPPPPPPPPPPPPPPPPN..', + '..NQQQQQQQQQQQQQQQQQQN..', + '..NQQQQQQQQQQQQQQQQQQN..', + '..NQQLLQQQQQQQQQQLLQQN..', + '..NQLLLLQQQNNQQLLLLQQN..', + '..NQQLLQQQQNNQQQQLLQQN..', + '..NQQQQQGGGGGGQQQQQQQN..', + '..NQQGGGTTGGGGGGTTGQQN..', + '..NQQGTTTTGGDDGGTTTGQN..', + '..NQQGTTTTGGDDGGTTTGQN..', + '..NQQGGGGGGGDDGGGGGGQN..', + '..NQQQGGGGGGDDGGGGQQQN..', + '..NQQQQQQQQQDDQQQQQQQN..', + '..NQQQQQQQQQDDQQQQQQQN..', + '..NQQQQQQQQQDDQQQQQQQN..', + '..NQQQQQQQNNNNQQQQQQQN..', + '...NNNNNNNN..NNNNNNNN...', + '........................' + ], { + N: '#252934', Y: '#fff5d0', W: '#8bb8ff', P: '#8f5e47', Q: '#caa77f', L: '#ffe8a0', G: '#d6c29b', T: '#77543b', D: '#403027' + }, 24, 28); + } + + function drawTideglassLighthouse() { + return artRowsSized([ + '........NNNN........', + '.......NYYYYN.......', + '.......NYCCYN.......', + '......NYYCCYYN......', + '......NNNCCNNN......', + '.......N.CC.N.......', + '.......N.BB.N.......', + '......NN.BB.NN......', + '......NWWWWWWN......', + '......NWWLLWWN......', + '.....NNWWLLWWNN.....', + '.....NWWWWWWWWN.....', + '.....NWWGGGGWWN.....', + '.....NWWGTTGWWN.....', + '.....NWWGGGGWWN.....', + '....NNWWWWWWWWNN....', + '....NWWWWLLWWWWN....', + '....NWWWWLLWWWWN....', + '....NWWWWWWWWWWN....', + '....NWWWGGGGWWWN....', + '....NWWWGTTGWWWN....', + '....NWWWGGGGWWWN....', + '...NNWWWWWWWWWWNN...', + '...NWWWWWWWWWWWWN...', + '...NWWWGGWWGGWWWN...', + '...NWWWTTWWTTWWWN...', + '...NWWWGGWWGGWWWN...', + '..NNWWWWWWWWWWWWNN..', + '..NWWWWWWWWWWWWWWN..', + '..NWWWWWWDDWWWWWWN..', + '..NWWWWWWDDWWWWWWN..', + '..NWWWWGGDDGGWWWWN..', + '..NWWWWTTDDTTWWWWN..', + '..NWWWWGGDDGGWWWWN..', + '...NNNNNNDDNNNNNN...', + '........NNNN........' + ], { + N: '#212632', Y: '#fff0ad', C: '#eef7ff', B: '#8fc1ff', W: '#f2efe8', L: '#fff0b2', G: '#d7c5a8', T: '#8f6a4e', D: '#413128' + }, 20, 36); + } + + function drawMossrailDepot() { + return artRowsSized([ + '....NNNNNNNNNNNNNNNNNNNNNNNN....', + '...NYYYYYYYYYYYYYYYYYYYYYYYYN...', + '..NYYNNNNNNNNNNNNNNNNNNNNNNYYN..', + '..NYYNPPPPPPPPPPPPPPPPPPPPNYYN..', + '..NYYNPPPPPPPPPPPPPPPPPPPPNYYN..', + '..NYYNNNNNNNNNNNNNNNNNNNNNNYYN..', + '.NNWWWWWWWWWWWWWWWWWWWWWWWWWWNN.', + '.NWWWWWWWWWWWWWWWWWWWWWWWWWWWWN.', + '.NWWLLLLWWWWLLLLWWWWLLLLWWWWWN..', + '.NWWLLLLWWWWLLLLWWWWLLLLWWWWWN..', + '.NWWWWWWWWWWWWWWWWWWWWWWWWWWWN..', + '.NWWGGGGGGGGGGGGGGGGGGGGGGWWWN..', + '.NWWGTTTGGGGGGGGGGGGGGTTTGWWWN..', + '.NWWGGGGGGGGGNNNNGGGGGGGGGWWWN..', + '.NWWGTTTGGGGGNDDNGGGGGTTTGWWWN..', + '.NWWGGGGGGGGGNDDNGGGGGGGGGWWWN..', + '.NWWWWWWWWWWWWDDWWWWWWWWWWWWWN..', + '.NWWWWWWWWWWWWDDWWWWWWWWWWWWWN..', + '.NNNNNNNNNNNNNNNNNNNNNNNNNNNNNN.', + '................................' + ], { + N: '#232733', Y: '#f5d48f', P: '#7b5651', W: '#a9b8bf', L: '#ffeda7', G: '#d0b48d', T: '#7d5b45', D: '#3b2f2a' + }, 32, 20); + } + + function drawLanternLibrary() { + return artRowsSized([ + '.......NNNNNNNNNNNNNN.......', + '......NYYYYYYYYYYYYYYN......', + '.....NYYNNNNNNNNNNNNYYN.....', + '.....NYNPPPPPPPPPPPPNYN.....', + '....NNNNNNNNNNNNNNNNNNNN....', + '....NWWWWWWWWWWWWWWWWWWN....', + '...NNWWWLLLWWNNWWLLLWWWNN...', + '...NWWWLLLLWWWWWWLLLLWWWN...', + '...NWWWWLLWWWWWWWWLLWWWWN...', + '...NWWWWWWWWWWWWWWWWWWWWN...', + '...NWWGGGGGGGGGGGGGGGGWWN...', + '...NWWGTTTGGTTGGTTGGTTGWN...', + '...NWWGGGGGGGGGGGGGGGGWWN...', + '...NWWGTTTGGTTGGTTGGTTGWN...', + '...NWWGGGGGGGGGGGGGGGGWWN...', + '...NWWGGTTGGGGGGGGTTGGWWN...', + '...NWWGGTTGGGNNDGGTTGGWWN...', + '...NWWGGGGGGGNNDGGGGGGWWN...', + '...NWWWWWWWWWWDDWWWWWWWWN...', + '...NWWWWWWWWWWDDWWWWWWWWN...', + '....NWWWWWWWWNNNNWWWWWWN....', + '....NNNNNNNNN....NNNNNN.....', + '............................', + '............................' + ], { + N: '#222633', Y: '#e7c36c', P: '#704944', W: '#8a6a4a', L: '#ffeeb5', G: '#d7c0a0', T: '#6b5139', D: '#382c26' + }, 28, 24); + } + + function drawVelvetTheater() { + return artRowsSized([ + '....NNNNNNNNNNNNNNNNNNNN.....', + '...NYYYYYYYYYYYYYYYYYYYYN....', + '..NYYNNNNNNNNNNNNNNNNNNYYN...', + '..NYNPPPPPPPPPPPPPPPPPPNYN...', + '.NNNNNNNNNNNNNNNNNNNNNNNNNN..', + '.NWWWWWWWWWWWWWWWWWWWWWWWWN..', + '.NWWLLLLLLLLWWWWLLLLLLLLWWN..', + '.NWWLAAAAALLWWWWLLAAAAALWWN..', + '.NWWLLLLLLLLWWWWLLLLLLLLWWN..', + '.NWWWWWWWWWWWWWWWWWWWWWWWWN..', + '.NWWGGGGGGGGGGGGGGGGGGGGWWN..', + '.NWWGTTGGTTGGGGGGTTGGTTGWWN..', + '.NWWGGGGGGGGGNNGGGGGGGGGWWN..', + '.NWWGTTGGTTGGNDDNGGTTGGTGWWN.', + '.NWWGGGGGGGGGNDDNGGGGGGGGWWN.', + '.NWWWWWWWWWWWDDDWWWWWWWWWWN..', + '.NWWWWWWWWWWNDDDNWWWWWWWWWN..', + '.NNNNNNNNNNNNNNNNNNNNNNNNNN..', + '............................', + '............................' + ], { + N: '#231f2c', Y: '#f2bf68', P: '#7f2d47', W: '#5d4858', L: '#ffd692', A: '#f08ec0', G: '#b99a7d', T: '#654633', D: '#39262a' + }, 28, 20); + } + + function drawBloomBridgeGate() { + return artRowsSized([ + '..........NNNN..........', + '........NNYYYYNN........', + '.......NYYPPPPYYN.......', + '......NYYPYYYYPYYN......', + '.....NYYPYYNNYYPYYN.....', + '....NNYYYYN..NYYYYNN....', + '...NNWWWWWN..NWWWWWNN...', + '..NNWWWNNWWNNWWNNWWWNN..', + '..NWWWN..NWWWWN..NWWWN..', + '..NWWN....NWWN....NWWN..', + '..NWWN....NWWN....NWWN..', + '..NWWN....NWWN....NWWN..', + '..NWWNNNNNNWWNNNNNNWWN..', + '..NWWGGGGGGWWGGGGGGWWN..', + '..NWWGTTTGGWWGGTTTGWWN..', + '..NWWGGGGGGWWGGGGGGWWN..', + '..NWWPPPPPPWWPPPPPPWWN..', + '..NWWPPYYPPWWPPYYPPWWN..', + '..NWWPPPPPPWWPPPPPPWWN..', + '...NNWWWWWWWWWWWWWWNN...', + '....NNNNNNWWNNNNNNNN....', + '........NNWWNN..........', + '........NWWWWN..........', + '........NNNNNN..........' + ], { + N: '#242835', Y: '#f6d56c', P: '#f29fc3', W: '#7f6a5a', G: '#9aca7c', T: '#5b8e49' + }, 24, 24); + } + + function drawStarreefSubmarine() { + return artRowsSized([ + '................................', + '.............NNNNNN.............', + '..........NNNYYYYYYNNN..........', + '........NNYYCCCCCCCCYYNN........', + '......NNYYCCBBBBBBBBCCYYNN......', + '.....NYYCCBBBBBBBBBBBBCCYYN.....', + '....NYYCBBBBBNNNNBBBBBBCYYN.....', + '...NYYCBBBBBNGGGGNBBBBBCYYN.....', + '..NNYYBBBBBBNGTTGNBBBBBBYYNN....', + '.NNYYYYYYYYYNGGGGNYYYYYYYYYNN...', + '.NWWWWWWWWWWNNNNNNWWWWWWWWWWWN..', + '.NWWWWLLWWWWWWWWWWWWLLWWWWWWWN..', + '.NNWWWWWWWWWWWWWWWWWWWWWWWWWNN..', + '..NNNNNNNNNNNNNNNNNNNNNNNNNN....', + '................................', + '................................' + ], { + N: '#1f2431', Y: '#f4dc7a', C: '#d0f1ff', B: '#57b7d7', W: '#73544d', G: '#eaf5ff', T: '#89b2ff', L: '#fff2b6' + }, 32, 16); + } + + function drawAstrolabeCourierRight() { + return artRowsSized([ + '....NNNN....', + '...NYYYYN...', + '...NYYYYN...', + '...NNNNNN...', + '..NNWWWWNN..', + '..NWWCCWWN..', + '..NWWWCWWN..', + '...NWWWWN...', + '..NNWWWWNN..', + '.NNWWNNWWNN.', + '.NWWN..NWWN.', + '.NWWNNNNWWN.', + '.NWWWGGWWWN.', + '.NWWNGGNWWN.', + '..NNN..NNN..', + '...N....N...' + ], { + N: '#232833', Y: '#d6a17a', W: '#375476', C: '#d9eeff', G: '#9f6e46' + }, 12, 16); + } + + function drawPuddleToadRight() { + return artRowsSized([ + '............', + '...NN..NN...', + '..NYYNNYYN..', + '.NYYYYYYYYN.', + '.NYYNYYNYYN.', + '.NYYYYYYYYN.', + '.NWWYYYYWWN.', + '..NWWWWWWN..', + '...NNNNNN...', + '............' + ], { + N: '#202632', Y: '#7eb85c', W: '#d9eeff' + }, 12, 10); + } + + function drawRibbonSwanRight() { + return artRowsSized([ + '............', + '......NN....', + '.....NYYN...', + '....NYYYYN..', + '...NYYNNYYN.', + '.NNNYYNNYYN.', + 'NWWWWYYYYYN.', + 'NWWWWWWWWNN.', + '.NWWWWWWWN..', + '..NWWWWWN...', + '...NNNNN....', + '............' + ], { + N: '#222633', Y: '#ffd3dc', W: '#f7fbff' + }, 12, 12); + } + + function drawLanternBeetleRight() { + return artRowsSized([ + '............', + '....NNNN....', + '...NYYYYN...', + '..NYYCCYYN..', + '..NYYCCYYN..', + '.NNYYNNYYNN.', + '.NWWYYYYWWN.', + '..NWWWWWWN..', + '..NWN..NWN..', + '.NNN....NNN.', + '.N........N.', + '............' + ], { + N: '#202531', Y: '#f0d25f', C: '#fff1b5', W: '#7d4933' + }, 12, 12); + } + + function drawSmilePortrait() { + return artRowsSized([ + '......FFFFFFFFFFFF......', + '.....FNNNNNNNNNNNNF.....', + '....FNBBBBBBBBBBBBNF....', + '....FNBHHHHHHHHHHBNF....', + '....FNBHHHSSSSHHHBNF....', + '....FNBHHSSSSSSHHBNF....', + '....FNBHHSSSSSSHHBNF....', + '....FNBHHSEEESHHHBNF....', + '....FNBHHSSSSSSHHBNF....', + '....FNBHHHSDDSSHHBNF....', + '....FNBGGGSSSSGGGBNF....', + '....FNBGGGGGGGGGGBNF....', + '....FNBGGGGGGGGGGBNF....', + '....FNBGGGGGGGGGGBNF....', + '....FNBGGGGGGGGGGBNF....', + '....FNBGGTTGGGGTGBNF....', + '....FNBGTTTTGGTTTBNF....', + '....FNBGTTTTGGTTTBNF....', + '....FNBGGTTTGGTTGBNF....', + '....FNBGGGGGGGGGGBNF....', + '....FNBGGGGDDGGGGBNF....', + '....FNBGGGGDDGGGGBNF....', + '....FNBGGGGDDGGGGBNF....', + '....FNBGGGGDDGGGGBNF....', + '....FNBGGGGDDGGGGBNF....', + '....FNBGGGDDDDGGGBNF....', + '....FNBGGGDDDDGGGBNF....', + '....FNBBBBBBBBBBBBNF....', + '....FNNNNNNNNNNNNNNF....', + '.....FFFFFFFFFFFFFF.....', + '........................', + '........................' + ], { + F: '#a67c37', N: '#252836', B: '#67816b', H: '#4b3228', S: '#d5ad87', E: '#242834', D: '#5f4130', G: '#4e6b3f', T: '#395835' + }, 24, 32); + } + + function drawGreatWavePanel() { + return artRowsSized([ + '....FFFFFFFFFFFFFFFFFFFFFFFF....', + '...FNNNNNNNNNNNNNNNNNNNNNNNNF...', + '..FNCCCCCCCCCCCCCCCCCCCCCCCCNF..', + '..FNCWWWWWWWWWWWWWWWWWWCCCCCNF..', + '..FNCWWWWWWWWWWWWWWWWWCCCCCCNF..', + '..FNCWWWWWWWWWWWWWWCCCCCYYCCNF..', + '..FNCWWWWWWWWWWWWCCCCCCCCCMMNF..', + '..FNCWWWWWWWWWWCCCCCAAACCCCMNF..', + '..FNCWWWWWWWWCCCCCAAAAAACCCMNF..', + '..FNCWWWWWWCCCCCAAAWWWAAACCMNF..', + '..FNCWWWWCCCCCAAAWWWWWWAACCMNF..', + '..FNCWWWCCCAAACWWWWWWWWWACCMNF..', + '..FNCCWCCAAAACWWWWWWWWWWWCCMNF..', + '..FNCCCAAAAACWWWWWWWWWWWWWCMNF..', + '..FNCCAAAAACWWWWWWWWWWWWWWMNF..', + '..FNCCAAAACCWWWWWWWWWWWWWWMNF..', + '..FNCCCAACCCWWWWWWWWWWWWWWMNF..', + '..FNCCCCCCCCWWWWWWWWWWWWWWMNF..', + '..FNCCMMMMMCCCCCMMMMMMMCCCMNF..', + '..FNCCMMMMMMMCCMMMMMMMMCCCMNF..', + '..FNCCMMMMMMMMMMMMMMMMMCCCMNF..', + '..FNCCMMMMMMMMMMMMMMMMMCCCMNF..', + '..FNCCCCCCCCCCCCCCCCCCCCCCCNF..', + '..FNNNNNNNNNNNNNNNNNNNNNNNNNF..' + ], { + F: '#a67c37', N: '#252836', C: '#d3eaf9', W: '#4a97d6', A: '#ffffff', Y: '#f3d36a', M: '#745f56' + }, 32, 24); + } + + function drawSunflowerStillLife() { + return artRowsSized([ + '........NN..NN..........', + '.......NYYNNYYN.........', + '......NYYYYYYYYN........', + '.......NYYNNYYN.........', + '........NN..NN..........', + '..........GG............', + '.....NN..NN..NN..NN.....', + '....NYYNNYYNNYYNNYYN....', + '...NYYYYYYYYYYYYYYYYN...', + '....NYYNNYYNNYYNNYYN....', + '.....NN..NN..NN..NN.....', + '...........GG...........', + '......NN..NN..NN........', + '.....NYYNNYYNNYYN.......', + '....NYYYYYYYYYYYYN......', + '.....NYYNNYYNNYYN.......', + '......NN..NN..NN........', + '........GGGG............', + '........GGGG............', + '.......NBBBBBBN.........', + '......NBBBBBBBBN........', + '......NBBBBBBBBN........', + '......NBBBBBBBBN........', + '.......NBBBBBBN.........', + '........NBBBBN..........', + '........NBBBBN..........', + '.......NMMMMMMN.........', + '......NMMMMMMMMN........', + '......NNNNNNNNNN........', + '........................', + '........................', + '........................' + ], { + N: '#252836', Y: '#f0cc57', G: '#5e8b48', B: '#b48255', M: '#8c6a53' + }, 24, 32); + } + + function drawRosettaStela() { + return artRowsSized([ + '........NNNNNNNN........', + '.......NSSSSSSSSN.......', + '......NSSSSSSSSSSN......', + '......NSSSSSSSSSSN......', + '......NSSLLLSSLLSN......', + '......NSSSSSSSSSSN......', + '......NSSLLSSLLSSN......', + '......NSSSSSSSSSSN......', + '......NSSSLLLSSSSN......', + '......NSSSSSSSSSSN......', + '......NSSLLSSSSLSN......', + '......NSSSSSSSSSSN......', + '......NSSLLLSSLLSN......', + '......NSSSSSSSSSSN......', + '......NSSLLSSLLSSN......', + '......NSSSSSSSSSSN......', + '......NSSSLLLSSSSN......', + '......NSSSSSSSSSSN......', + '......NSSLLSSSSLSN......', + '......NSSSSSSSSSSN......', + '......NSSLLLSSLLSN......', + '......NSSSSSSSSSSN......', + '......NSSLLSSLLSSN......', + '......NSSSSSSSSSSN......', + '......NSSSLLLSSSSN......', + '......NSSSSSSSSSSN......', + '......NSSSSDDSSSSN......', + '......NSSSSDDSSSSN......', + '......NSSSSDDSSSSN......', + '.......NSSSDDSSSN.......', + '........NNNNNNNN........', + '........................' + ], { + N: '#252836', S: '#887b66', L: '#5d5446', D: '#6e5842' + }, 24, 32); + } + + function drawPharaohMask() { + return artRowsSized([ + '.........NNNNNN.........', + '........NYYYYYYN........', + '.......NYYBBBBYYN.......', + '......NYYBBBBBBYYN......', + '......NYYBSSSSBYYN......', + '......NYYBSSSSBYYN......', + '......NYYBSDDSBYYN......', + '......NYYBSEESBYYN......', + '......NYYBSSSSBYYN......', + '......NYYBSDDSBYYN......', + '......NYYBSSSSBYYN......', + '......NYYBSSSSBYYN......', + '......NYYBSDDSBYYN......', + '......NYYBSSSSBYYN......', + '......NYYBSSSSBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '......NYYBBSSBBYYN......', + '.......NYYBSSBYYN.......', + '........NYYSSYYN........', + '........NYYSSYYN........', + '.........NNNNNN.........', + '........................' + ], { + N: '#252836', Y: '#e0b94d', B: '#4a78bf', S: '#d7b585', E: '#232834', D: '#8c6035' + }, 24, 32); + } + + function drawStoneCircle() { + return artRowsSized([ + '................................', + '................................', + '............NN..NN............', + '..........NNSSNNSSNN..........', + '........NNSSSSSSSSSSNN........', + '.......NSSSSSSSSSSSSSSN.......', + '......NSSSSSSSSSSSSSSSSN......', + '.....NSSSNSSSN..NSSSNSSSN.....', + '....NSSSNSSSSN..NSSSSNSSSN....', + '....NSSSNSSSSN..NSSSSNSSSN....', + '....NSSSNSSSSN..NSSSSNSSSN....', + '....NSSSNSSSSN..NSSSSNSSSN....', + '....NSSSNSSSSNNNNSSSSNSSSN....', + '....NSSSNSSSSSSSSSSSSNSSSN....', + '....NSSSNSSSSSSSSSSSSNSSSN....', + '.....NSSSNSSSSSSSSSSNSSSN.....', + '......NSSSSSSSSSSSSSSSSN......', + '.......NSSSSSSSSSSSSSSN.......', + '........NNNNNNNNNNNNNN........', + '........GGGGGGGGGGGGGG........', + '.......GGTTGGGGGGGGTTGG.......', + '.......GGGGGGGGDDGGGGGG.......', + '.......GGGGGGGGDDGGGGGG.......', + '........NNNNNNNNNNNNNN........' + ], { + N: '#252836', S: '#8b8274', G: '#93b670', T: '#5d8d46', D: '#6c4a35' + }, 32, 24); + } + + function drawTerracottaSentinel() { + return artRowsSized([ + '.......NNNNNN.......', + '......NBBBBBBN......', + '.....NBBSSSSBBN.....', + '.....NBSSSSSSBN.....', + '.....NBSSDDSSBN.....', + '.....NBSSEESSBN.....', + '.....NBSSSSSSBN.....', + '.....NBBSSSSBBN.....', + '......NBBBBBBN......', + '......NBBBBBBN......', + '......NBBBBBBN......', + '......NBBBBBBN......', + '......NBBBBBBN......', + '.....NBBBBBBBBN.....', + '.....NBBBGGBBBN.....', + '.....NBBBGGBBBN.....', + '.....NBBBGGBBBN.....', + '.....NBBBGGBBBN.....', + '.....NBBBGGBBBN.....', + '.....NBBBBBBBBN.....', + '.....NBBNNNNBBN.....', + '.....NBN....NBN.....', + '....NBBN....NBBN....', + '....NBBN....NBBN....', + '....NBBN....NBBN....', + '....NBBN....NBBN....', + '....NBBN....NBBN....', + '....NBBN....NBBN....', + '....NMMN....NMMN....', + '....NMMN....NMMN....', + '.....NN......NN.....', + '....................' + ], { + N: '#252836', B: '#9a6a4f', S: '#be8964', E: '#1f2230', D: '#6f4838', G: '#7a5746', M: '#6b5143' + }, 20, 32); + } + + function drawRainBellTower() { + return artRowsSized([ + '........NNNN........', + '.......NYYYYN.......', + '......NYYYYYYN......', + '......NYYNNYYN......', + '......NNNWWNNN......', + '.......NWWWWN.......', + '.......NWWWWN.......', + '......NNWWWWNN......', + '......NWWGGWWN......', + '......NWWGGWWN......', + '......NWWGGWWN......', + '......NWWLLWWN......', + '......NWWGGWWN......', + '.....NNWWWWWWNN.....', + '.....NWWGGGGWWN.....', + '.....NWWGTTGWWN.....', + '.....NWWGGGGWWN.....', + '.....NWWWWWWWWN.....', + '.....NWWWLLWWWN.....', + '.....NWWWGGWWWN.....', + '.....NWWWGGWWWN.....', + '.....NWWWGGWWWN.....', + '....NNWWWGGWWWNN....', + '....NWWWWWWWWWWN....', + '....NWWWGGGGWWWN....', + '....NWWWGTTGWWWN....', + '....NWWWGGGGWWWN....', + '....NWWWWWWWWWWN....', + '....NWWWWDDWWWWN....', + '....NWWWWDDWWWWN....', + '....NWWGGDDGGWWN....', + '....NWWGGDDGGWWN....', + '....NWWWWDDWWWWN....', + '.....NNNNDDNNNN.....', + '........NNNN........', + '....................' + ], {N:'#242836',Y:'#f4d276',W:'#d9d8df',G:'#a49da3',L:'#fff0b6',T:'#6a5245',D:'#40322c'}, 20, 36); + } + + function drawCrimsonPagoda() { + return artRowsSized([ + '.........NNNNNN.........', + '.......NNYYYYYYNN.......', + '......NYYYYYYYYYYN......', + '......NNNNWWNNNNNN......', + '.....NNRRRRRRRRRRNN.....', + '.....NWRRRRRRRRRRWN.....', + '....NNWWWWWWWWWWWWNN....', + '....NWWWWWWWWWWWWWWN....', + '...NNRRRRRRRRRRRRRRNN...', + '...NWRRLLRRRRRRLLRRWN...', + '...NWWWWWWWWWWWWWWWWN...', + '..NNWWWWWWWWWWWWWWWWNN..', + '..NWRRRRRRRRRRRRRRRRWN..', + '..NWRRLLRRRNNRRRLLRRWN..', + '..NWWWWWWWWNNWWWWWWWWN..', + '.NNWWWWWWWWWWWWWWWWWWNN.', + '.NWRRRRRRRRRRRRRRRRRRWN.', + '.NWRRLLRRRRRRRRRRLLRRWN.', + '.NWWWWWWWWWWWWWWWWWWWWN.', + '.NWWGGGGGGGGGGGGGGGGWWN.', + '.NWWGTTTGGTTTTGGTTTGWWN.', + '.NWWGGGGGGGGGGGGGGGGWWN.', + '.NWWWWWWWWWWWWWWWWWWWWN.', + '.NWWWWWWWWWWWWWWWWWWWWN.', + '.NWWGGGGGGGGDDGGGGGGWWN.', + '.NWWGTTTGGGGDDGGGTTGWWN.', + '.NWWGGGGGGGGDDGGGGGGWWN.', + '.NWWWWWWWWWWDDWWWWWWWWN.', + '.NWWWWWWWWWWDDWWWWWWWWN.', + '..NNNNNNNNNNNNNNNNNNNN..', + '........................', + '........................' + ], {N:'#242833',Y:'#efc05e',W:'#4f403f',R:'#9c4354',L:'#ffd99f',G:'#cbb28d',T:'#6c513b',D:'#362a25'}, 24, 32); + } + + function drawMeteorForge() { + return artRowsSized([ + '................................', + '........NNNNNNNNNNNN............', + '......NNYYYYYYYYYYYYNN..........', + '.....NYYNNNNNNNNNNNNYYN.........', + '....NNNNNNNNNNNNNNNNNNNN........', + '...NWWWWWWWWWWWWWWWWWWWWN.......', + '..NNWWWLLLLWWWWWWLLLLWWWNN......', + '..NWWWLLLLLLWWWWLLLLLLWWWN......', + '..NWWWWLLLLLWWWWLLLLLWWWWN......', + '..NWWWWWWWWWWWWWWWWWWWWWWN......', + '.NNWWWWWWWWWWWWWWWWWWWWWWNN.....', + '.NWWGGGGGGGGGGGGGGGGGGGGWWN.....', + '.NWWGTTGGGTTGGGGGGTTGGGTGWN.....', + '.NWWGGGGGGGGGNNNNGGGGGGGGWN.....', + '.NWWGTTGGGGGGNDDNGGGGGTTGWN.....', + '.NWWGGGGGGGGGNDDNGGGGGGGGWN.....', + '.NWWWWWWWWWWWWDDWWWWWWWWWWN.....', + '.NWWWWLLWWWWWWDDWWWWWWLLWWN.....', + '.NWWWWWWWWWWWWDDWWWWWWWWWWN.....', + '.NWWGGGGGGGGGGDDGGGGGGGGWWN.....', + '.NWWGTTTGGGGGGDDGGGGGTTTGWN.....', + '.NWWGGGGGGGGGGDDGGGGGGGGWWN.....', + '.NNNNNNNNNNNNNNNNNNNNNNNNNN.....', + '................................' + ], {N:'#242833',Y:'#6f8fd8',W:'#5f544f',L:'#ffcf8a',G:'#b9916a',T:'#ff8f52',D:'#352924'}, 32, 24); + } + + function drawInkGardenScreen() { + return artRowsSized([ + 'NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN', + 'NCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCN', + 'NCMMMCCCCCCCCCCCCCCCCCCCCCCMMM CN'.replace(/ /g,''), + 'NCMMMMCCCCCCCCCCCCCCCCCCCCMMMMCN', + 'NCMMMMMCCCCCCCGGGGCCCCCCMMMMMCN', + 'NCMMMMMMCCCCCGGGGGGCCCCMMMMMMCN', + 'NCMMMMMMMCCCCGGGGGGCCCCMMMMMMCN', + 'NCMMMMMMCCCCCGGGGGGCCCCMMMMMMCN', + 'NCMMMMMCCCCCCCGGGGCCCCMMMMMMCN', + 'NCCCCCCCCCCCCCCCCCCCCCCCCCCCCCN', + 'NCCCCCCCCCCCCCNNNNCCCCCCCCCCCCN', + 'NCCCCCCCCCCCCNDDDDNCCCCCCCCCCCN', + 'NCCCCCCCCCCCCNDDDDNCCCCCCCCCCCN', + 'NCCCCCCCCCCCCNNNNNNCCCCCCCCCCCN', + 'NCCCCCCCCCCCCCCCCCCCCCCCCCCCCCN', + 'NCGGGCCCCCCCCCCCCCCCCCCCCGGGCCN', + 'NCGTGCCCCCCCCCCCCCCCCCCCCGTGCCN', + 'NCGGGCCCCCCCCCCCCCCCCCCCCGGGCCN', + 'NCCCCCCCCCCCCCCCCCCCCCCCCCCCCCN', + 'NCCCCCCCCCCCCCCCCCCCCCCCCCCCCCN', + 'NCCCCCCCCCCCCCCCCCCCCCCCCCCCCCN', + 'NCCCCCCCCCCCCCCCCCCCCCCCCCCCCCN', + 'NCCCCCCCCCCCCCCCCCCCCCCCCCCCCCN', + 'NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN' + ], {N:'#252836',C:'#ece6d8',M:'#2a554c',G:'#7ab08a',T:'#4f8a5e',D:'#716159'}, 32, 24); + } + + function drawMeadowTotem() { + return artRowsSized([ + '........NNNN........', + '.......NYYYYN.......', + '......NYYGGYYN......', + '......NYYGGYYN......', + '......NYYNNYYN......', + '......NYYSSYYN......', + '......NYYSSYYN......', + '......NYYNNYYN......', + '......NYYGGYYN......', + '......NYYGGYYN......', + '......NYYSSYYN......', + '......NYYSSYYN......', + '......NYYNNYYN......', + '......NYYYYYYN......', + '......NYYYYYYN......', + '......NYYYYYYN......', + '......NYYYYYYN......', + '......NYYYYYYN......', + '......NYYYYYYN......', + '......NYYYYYYN......', + '......NYYYYYYN......', + '......NYYDDYYN......', + '......NYYDDYYN......', + '......NYYDDYYN......', + '......NYYDDYYN......', + '.......NDDDDN.......', + '........NNNN........', + '....................' + ], {N:'#252836',Y:'#a57b5c',G:'#97cb6f',S:'#f1d691',D:'#5b4337'}, 20, 28); + } + + function drawTwilightCaravan() { + return artRowsSized([ + '................................', + '...........NNNNNNNN.............', + '........NNNYYYYYYYYNN...........', + '......NNYYPPPPPPPPYYNN..........', + '.....NYYPPPPPPPPPPPPYYN.........', + '....NYYPPPPPPPPPPPPPPYYN........', + '...NNWWWWWWWWWWWWWWWWWWNN.......', + '...NWWWWLLWWWWLLWWWWLLWWN.......', + '...NWWWWWWWWWWWWWWWWWWWWN.......', + '...NWWGGGGGGGGGGGGGGGGWWN.......', + '...NWWGTTTGGTTGGTTGGTTGWN.......', + '...NWWGGGGGGGGGGGGGGGGWWN.......', + '..NNWWWWWWWWWWWWWWWWWWWWNN......', + '..NWWWWNNWWWWNNWWWWNNWWWWN......', + '..NWWWN..NWWWN..NWWWN..NWWN......', + '..NNNN....NNNN....NNNN..NN......' + ], {N:'#252836',Y:'#c49b5b',P:'#7e5aa8',W:'#7b6654',L:'#ffe09c',G:'#8db873',T:'#5d8b45'}, 32, 16); + } + + function drawPepperFoxRight() { + return artRowsSized([ + '................', + '................', + '.......NN.......', + '......NYYN......', + '.....NYYYYNN....', + '....NYYYYYYN....', + '...NYYYYYYYYN...', + '...NYYYYNYYYN...', + '..NYYYYYYYNWN...', + '..NYYYYYYYWWN...', + '..NYYYYYYWWN....', + '...NYYYYWWN.....', + '....NYYWWWNN....', + '....NWWWWWWN....', + '.....NN..NN.....', + '................' + ], {N:'#252836',Y:'#d56f3f',W:'#fff1dd'}, 16, 16); + } + + function drawGlassMantaRight() { + return artRowsSized([ + '................', + '.......NN.......', + '.....NNCCNN.....', + '...NNCCCCCCNN...', + '..NCCCCCCCCCCN..', + '.NCCCCCCCCCCCCN.', + 'NNCCCCCCCCCCCCNN', + '.NCCCCCCCCCCCCN.', + '..NNCCCCCCCCNN..', + '....NNCCCCNN....', + '......NCCN......', + '.......NN.......' + ], {N:'#252836',C:'#7fdaf2'}, 16, 12); + } + + function drawFestivalDrummerRight() { + return artRowsSized([ + '.....NNNN.....', + '....NYYYYN....', + '....NYYYYN....', + '....NNNNNN....', + '...NNRRRRNN...', + '...NRRWWRRN...', + '...NRRWWRRN...', + '....NWWWWN....', + '..NNNWWWWNN...', + '.NNWWNNNNWWN..', + '.NWWN.TTNWWN..', + '.NWWNNNNNWWN..', + '.NWWN....NWN..', + '.NWWN....NWN..', + '..NN......NN..', + '..............' + ], {N:'#252836',Y:'#e0b18c',R:'#d4505f',W:'#425fb4',T:'#a26e4b'}, 14, 16); + } + + function drawBloomSpriteRight() { + return artRowsSized([ + '............', + '....NNNN....', + '...NYYYYN...', + '..NYYGGYYN..', + '..NYYGGYYN..', + '.NNYYYYYYNN.', + '.NWWYYYYWWN.', + '..NWWWWWWN..', + '..NWN..NWN..', + '.NN....NNN..', + '............', + '............' + ], {N:'#252836',Y:'#ffd3a8',G:'#ff8fc0',W:'#7bc56a'}, 12, 12); + } + window.PixelIslandDebug = { ...(window.PixelIslandDebug || {}), applySyncEvent }; bootstrap(); })(); diff --git a/assets.json b/assets.json new file mode 100644 index 0000000..ca1edbb --- /dev/null +++ b/assets.json @@ -0,0 +1,2815 @@ +[ + { + "id": "dkjphwcy69za", + "name": "Crescent Tea House", + "category": "static", + "subtype": "building", + "width": 16, + "height": 16, + "pixels": ".......NN.............N00N...........N00N.............NN............wwwwwww........wgggggggw......wggNggNggw......ggg0gg0ggg......gggggggggg......gggNAANggg......gggANNAggg......gggANNAggg.......ggAAAAgg.........wwwwww..........ggAAgg.........wwwwwwww.....", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 6, + "y": 5, + "c": "N" + }, + { + "x": 9, + "y": 5, + "c": "N" + }, + { + "x": 7, + "y": 10, + "c": "N" + } + ], + "lightColor": "N", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".......11.............1111...........1111.............11............-------........-1111111-......-11111111-......-11111111-......-11111111-......-111--111-......-111--111-......-111--111-.......--------.........------..........--11--.........--------.....", + "door": { + "x": 7, + "y": 14 + } + }, + "contentHash": "fnv1a:122df3c6" + }, + { + "id": "413sk5ay69zk", + "name": "Prism Sakura", + "category": "static", + "subtype": "nature", + "width": 16, + "height": 16, + "pixels": "......................................QQ.Q..........QQUUQQQ........QUUQQQUQ.......QQQUQQUQQQ.......QQUUUQQ...........QUQ..............k..............eke............ekkke..........eekkkee...........kkk.............ksk............sssss..........sssssss......", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": true, + "particlePixels": [ + { + "x": 5, + "y": 4, + "c": "Q", + "dir": "up" + }, + { + "x": 10, + "y": 5, + "c": "P", + "dir": "up" + } + ], + "particleConfig": { + "enabled": true, + "c": "Q", + "dir": "up" + }, + "depthPixels": "......................11.1..........1111111........11111111.......1111111111.......1111111...........111..............-..............---............-----..........-------...........---.............---............-----..........-------......................", + "door": null + }, + "contentHash": "fnv1a:729945aa" + }, + { + "id": "njlfq4gy69zo", + "name": "Clockwork Whale", + "category": "static", + "subtype": "ship", + "width": 16, + "height": 16, + "pixels": ".......................................................................................................N..............NN...........nnSSSSSn.......nSSSSSSSSn.....nSSS0SSS0Sn.....nSSSSSSSSSn.N....nSSSSSSSn.NN.....nnnnnnn.NN.......oooooo...........oooo.......", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".......................................1..............11...........11111111.......1111111111.....11111111111.....11111111111.1....111111111.11.....-------.11.......------...........----.......................................................................", + "door": null + }, + "contentHash": "fnv1a:64c5bc09" + }, + { + "id": "s4e450ky69zt", + "name": "Lantern Cat", + "category": "dynamic", + "subtype": "animal", + "width": 16, + "height": 16, + "pixels": ".....................................................................................................................E..E...........E9999E..........90909...........99w99..........ddddddd........dddNNdddN.......dddddddNN........d..ddd.........EE..E.E.......", + "faces": { + "right": ".....................................................................................................................E..E...........E9999E..........90909...........99w99..........ddddddd........dddNNdddN.......dddddddNN........d..ddd.........EE..E.E.......", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...................................1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111...................................................", + "door": null + }, + "contentHash": "fnv1a:ae4c582f" + }, + { + "id": "i1hkr1dy69zw", + "name": "Cloud Koi", + "category": "dynamic", + "subtype": "fish", + "width": 16, + "height": 16, + "pixels": ".....................................................................................................................................O..............OOO............OSSSOOO........OSSSSSSSO......OSS0SSS0SSO......OSSSSSSSO..Q.....OSSSOOO..QQ.......O......Q...", + "faces": { + "right": ".....................................................................................................................................O..............OOO............OSSSOOO........OSSSSSSSO......OSS0SSS0SSO......OSSSSSSSO..Q.....OSSSOOO..QQ.......O......Q...", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": true, + "particlePixels": [ + { + "x": 5, + "y": 8, + "c": "O", + "dir": "up" + } + ], + "particleConfig": { + "enabled": true, + "c": "O", + "dir": "up" + }, + "depthPixels": null, + "door": null + }, + "contentHash": "fnv1a:ee34e211" + }, + { + "id": "do3eje4y69zy", + "name": "Paper Crane", + "category": "dynamic", + "subtype": "bird", + "width": 16, + "height": 16, + "pixels": ".......................................................................................................................3..............333............33733..........3377333........3377E7733.........37E3.............EE.............E..E...........E....E......", + "faces": { + "right": ".......................................................................................................................3..............333............33733..........3377333........3377E7733.........37E3.............EE.............E..E...........E....E......", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": null, + "door": null + }, + "contentHash": "fnv1a:b14c3672" + }, + { + "id": "4ymi1wqy6a00", + "name": "Moon Lantern", + "category": "static", + "subtype": "building", + "width": 16, + "height": 16, + "pixels": ".......5..............555.............505............55555..........sssssss........skkkkkkks.......kbbkkbbk.......skk5555kks......kkkk55kkkk......kkkE55Ekkk......kkkEEEEkkk......kkkUEEUUkk.......kkUEEUk.........kkkkkkkk.........kkkkkk..........ssssss......", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 6, + "y": 7, + "c": "5" + }, + { + "x": 7, + "y": 7, + "c": "5" + }, + { + "x": 8, + "y": 7, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".......1..............111.............111............11111..........-------........-1111111-.......-111111-.......-11111111-......-11111111-......-111--111-......-111--111-......-111--111-.......-111111-........--------.........------..........------......", + "door": { + "x": 7, + "y": 14 + } + }, + "contentHash": "fnv1a:68b9107e" + }, + { + "id": "s74ryg2y6a08", + "name": "Glass Fern", + "category": "static", + "subtype": "nature", + "width": 16, + "height": 16, + "pixels": ".......................................i..............i6i............i666i........O..i6i6i..O......O.i6i6i.O........Oi666iO..........i6i6i..........i66666.........i666i6i........i6i6i6i6i.........ppppp...........pkkkp..........ppkkkpp.........kkkkkkk......", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".......................1..............111............11111........1..11111..1......1.11111.1........1111111..........11111..........111111.........1111111........111111111.........11111...........11111..........1111111.........1111111......................", + "door": null + }, + "contentHash": "fnv1a:b3bc2051" + }, + { + "id": "bpl16ouy6a0f", + "name": "Linen Cottage", + "category": "static", + "subtype": "building", + "width": 16, + "height": 16, + "pixels": "......................................................................................kkkk...........kkkkkk.........kkkkkkkk.......kkkkkkkkkk......kkkkkkkkkk.......hh9hhhhh........hddddd55........hddddd55........hdwwwddh........hdwwwddk........hhwwwhhh....", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 10, + "y": 9, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "......................................................1111...........111111.........11111111.......1111111111......1111111111.......11111111........11111111........11111111........11111111........11111111........11111111....................................", + "door": { + "x": 7, + "y": 13 + } + }, + "contentHash": "fnv1a:4fc8c8e4" + }, + { + "id": "kfci33qy6a0n", + "name": "Pine Cluster", + "category": "static", + "subtype": "nature", + "width": 16, + "height": 16, + "pixels": "......................................................................iii............iiiii...........aiiii..........iiiiiimmm.......iiiiiiaiii.....iiiiiimmmmm.....iiiiiiiiiiii...iiiiiimmmmmmm...iiiiiiiiiiiiii......kmmmmmmmmm......kk..kk..........kk..kk....", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "......................................111............11111...........11111..........111111111.......1111111111.....11111111111.....111111111111...1111111111111...11111111111111......1111111111......11..11..........11..11....................................", + "door": null + }, + "contentHash": "fnv1a:420bbd1e" + }, + { + "id": "6vyaizcy6a0w", + "name": "Coral Skiff", + "category": "static", + "subtype": "ship", + "width": 16, + "height": 16, + "pixels": "........................................................o...............o..............05o............005o...........0055o..........05555o.............ooo.........V...oo...V.....VVVllllllVV.....VlllllllllV......llllllll.........xxxxxx...........xxxx.......", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "........................1...............1..............11.............111............1111...........11111..............---.........1...--...1.....111-------1.....-----------......--------.........------...........----.......................................", + "door": null + }, + "contentHash": "fnv1a:7d1af0a3" + }, + { + "id": "h4vumx6y6a0z", + "name": "Sprout Fox", + "category": "dynamic", + "subtype": "animal", + "width": 16, + "height": 16, + "pixels": ".........................................................................................................................i..............i6i.........999..i.........90099..........99900999........9l9ll9099.......9999999..........9..9.9.........xx..xxx.......", + "faces": { + "right": ".........................................................................................................................i..............i6i.........999..i.........90099..........99900999........9l9ll9099.......9999999..........9..9.9.........xx..xxx.......", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...................................1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111...................................................", + "door": null + }, + "contentHash": "fnv1a:1ee0e8e9" + }, + { + "id": "n2rre9uy6a13", + "name": "Violet Moth", + "category": "dynamic", + "subtype": "animal", + "width": 16, + "height": 16, + "pixels": ".......................................................................................................................................T.............TTXTT..........TTXrXTT........TTXXrXXTT.........TXrXT............ErE............P.E.P..........P.....P.....", + "faces": { + "right": ".......................................................................................................................................T.............TTXTT..........TTXrXTT........TTXXrXXTT.........TXrXT............ErE............P.E.P..........P.....P.....", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": null, + "door": null + }, + "contentHash": "fnv1a:17684793" + }, + { + "id": "qpbwzi9y6a15", + "name": "Lantern Walker", + "category": "dynamic", + "subtype": "human", + "width": 16, + "height": 16, + "pixels": "......................................................................................EEE............E555E...........E5s5E............555............UUUUU..........UUUU5U5.........UUUU.55..........nnnU............n.nn............n..n...........EE..EE......", + "faces": { + "right": "......................................................................................EEE............E555E...........E5s5E............555............UUUUU..........UUUU5U5.........UUUU.55..........nnnU............n.nn............n..n...........EE..EE......", + "left": "mirror" + }, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 9, + "y": 7, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...................................1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111...................................................", + "door": null + }, + "contentHash": "fnv1a:32eb2b41" + }, + { + "id": "diitnqry6a19", + "name": "Wildflower Patch", + "category": "static", + "subtype": "nature", + "width": 8, + "height": 8, + "pixels": ".........eQeNe..e0eSeQe.eeeeeee.eNeQe0e.eeeeeee..ieiei....kk....", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".........11111..1111111.1111111.1111111.1111111..11111....11....", + "door": null + }, + "contentHash": "fnv1a:4a7f5581" + }, + { + "id": "f5wcp4iy6a1b", + "name": "River Stones", + "category": "static", + "subtype": "nature", + "width": 8, + "height": 8, + "pixels": "..................ff.....f88f...f8cc8f...f8888f...feif.....ff...", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "..........11.....1111...111111...111111...1111.....11...........", + "door": null + }, + "contentHash": "fnv1a:52d1f905" + }, + { + "id": "s7k786dy6a1d", + "name": "Maple Canopy", + "category": "static", + "subtype": "nature", + "width": 16, + "height": 16, + "pixels": "......................VV............VVhhVV.........VVhhNNVV.......VVhhNNNNVV......VhhNNeeNNV.....VhhNNeeeeNNV....VhNNeeeeeeNV....VNNee11eeeNV.....VNNeeeeeeNV.....VVNeeeeNNV.......VVNNNNNV..........pppp...........pppppp..........pppppp.........tttttttt.....", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "......11............111111.........11111111.......1111111111......1111111111.....111111111111....111111111111....111111111111.....1111111111......1111111111.......11111111..........----...........------..........------.........--------.....................", + "door": null + }, + "contentHash": "fnv1a:1ad36d0b" + }, + { + "id": "zxghctgy6a1i", + "name": "Misty Falls", + "category": "static", + "subtype": "nature", + "width": 16, + "height": 16, + "pixels": "....................eeeeee.........egggggge.......eggOOOOgge......egO3333Oge......egO3SS3Oge......egO3SS3Oge......egO3SS3Oge......egO3SS3Oge......egO3333Oge.......eO3333Oe.........OO33OO..........333333.........3bbbbbb3.......3bbbbbbbb3......3333333333....", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": true, + "particlePixels": [ + { + "x": 6, + "y": 8, + "c": "3", + "dir": "up" + }, + { + "x": 10, + "y": 8, + "c": "3", + "dir": "up" + } + ], + "particleConfig": { + "enabled": true, + "c": "3", + "dir": "up" + }, + "depthPixels": "....111111.........11111111.......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111......1111111111.......11111111.........111111..........------.........--------.......----------......----------....................", + "door": null + }, + "contentHash": "fnv1a:8ac4c6c5" + }, + { + "id": "1rfqz3ay6a1n", + "name": "Lotus Pond", + "category": "static", + "subtype": "nature", + "width": 16, + "height": 12, + "pixels": "....................................ei....ei......eiiie..eiie.....iiQQiiiiQMi....iiQQMQQiiQQii...iiSSSSSSSSSSi...iSSSSSSSSSSSi...iiSSSSSSSSSii....iiiSSSSiii.......iiiiiiii.........o....o......", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": true, + "particlePixels": [ + { + "x": 6, + "y": 6, + "c": "M", + "dir": "up" + }, + { + "x": 11, + "y": 5, + "c": "0", + "dir": "up" + } + ], + "particleConfig": { + "enabled": true, + "c": "M", + "dir": "up" + }, + "depthPixels": "....................11....11......11111..1111.....11111111111....1111111111111...1111----11111...111-------111...1111----11111....1111111111.......11111111.........-....-......................", + "door": null + }, + "contentHash": "fnv1a:0f18431e" + }, + { + "id": "koiuytsy6a1s", + "name": "Mossy Arch", + "category": "static", + "subtype": "nature", + "width": 16, + "height": 16, + "pixels": ".....................................eeee...........egggge.........egggggge.......eggeeeegge......ege....ege......ege....ege......ege....ege......ege....ege......ege....ege......eggeeeegge......eeecccceee........cccccc.........ccc..ccc.......oooo..oooo....", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".....................1111...........111111.........11111111.......1111..1111......111....111......111....111......111....111......111....111......111....111......1111..1111......1111111111........------.........---..---.......----..----....................", + "door": null + }, + "contentHash": "fnv1a:d89452f4" + }, + { + "id": "pj50yr5y6a20", + "name": "Sunflower Grove", + "category": "static", + "subtype": "nature", + "width": 12, + "height": 16, + "pixels": ".........................NN..NN..NN.NVVN.VVN.NVVNVpVNVpVNVpV.NVV..VV..VV..ee..ee..ee..eaeeeaeeae.aeeeeeeeeea.aeaeaeaeaea..e..e..e..e..k..k..k..k..k..k..k..k.kkkkkkkkkk..eaeaeaeaea...kkkkkkkk..", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".............11..11..11.1111.111.111111111111111.111..11..11..11..11..11..1111111111.11111111111.11111111111..1..1..1..1..1..1..1..1..1..1..1..1.1111111111..1111111111...11111111..............", + "door": null + }, + "contentHash": "fnv1a:66efaabf" + }, + { + "id": "5nzjl30y6a28", + "name": "Reed Bed", + "category": "static", + "subtype": "nature", + "width": 12, + "height": 12, + "pixels": "................ccc.......c.ccg.c.....gcccgcg.....gcccgcc.....gcccgcc....33333SS33..3SSSSSWWSS3.3SWWWWWWWS3..33SSSSSS3....eeeeee.......kkkk.....", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "................111.......1.111.1.....1111111.....1111111.....1111111....111111111..11111111111.11111111111..111111111....111111.......1111.....", + "door": null + }, + "contentHash": "fnv1a:d4c76094" + }, + { + "id": "jxztkudy6a2e", + "name": "Meadow Hare", + "category": "dynamic", + "subtype": "animal", + "width": 12, + "height": 12, + "pixels": "........................................cc.........cddc........cdddc......cddMMdc.....cddoodc.....cdddddc.....cddddd.......d.dd.......kk.k.k....", + "faces": { + "right": "........................................cc.........cddc........cdddc......cddMMdc.....cddoodc.....cdddddc.....cddddd.......d.dd.......kk.k.k....", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "................11.........1111........11111......1111111.....1111111.....1111111.....111111.......1.11.......11.1.1............................", + "door": null + }, + "contentHash": "fnv1a:2520de66" + }, + { + "id": "lb3ho6xy6a2h", + "name": "Brook Turtle", + "category": "dynamic", + "subtype": "animal", + "width": 12, + "height": 10, + "pixels": "........................................eee.......eaaaae.....eaa11aae....eaaeeaaee....eaaaaae......eeee..S......o..oSS..", + "faces": { + "right": "........................................eee.......eaaaae.....eaa11aae....eaaeeaaee....eaaaaae......eeee..S......o..oSS..", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "............................111.......111111.....11111111....111111111....1111111......1111..1......1..111..............", + "door": null + }, + "contentHash": "fnv1a:d8ac1b11" + }, + { + "id": "wyf8x9gy6a2n", + "name": "Red Panda", + "category": "dynamic", + "subtype": "animal", + "width": 12, + "height": 12, + "pixels": "...........................MM..MM.....MhMhMhhM....MhhMMhhM....MhhtthhM.....hZZZZh.....hZZZZZZh....hZZMMZZh....hZZZZZZh.....Z..Z.Z.....k...k.k...", + "faces": { + "right": "...........................MM..MM.....MhMhMhhM....MhhMMhhM....MhhtthhM.....hZZZZh.....hZZZZZZh....hZZMMZZh....hZZZZZZh.....Z..Z.Z.....k...k.k...", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...............11..11.....11111111....11111111....11111111.....111111.....11111111....11111111....11111111.....1..1.1.....1...1.1...............", + "door": null + }, + "contentHash": "fnv1a:d2fd3caf" + }, + { + "id": "eg4ckyiy6a2t", + "name": "River Otter", + "category": "dynamic", + "subtype": "animal", + "width": 14, + "height": 8, + "pixels": ".................kkk..........kggggkk......kgg44gggkk....kggxxgggggk...kgggggggggk....kgggg..gg......ooo...o....", + "faces": { + "right": ".................kkk..........kggggkk......kgg44gggkk....kggxxgggggk...kgggggggggk....kgggg..gg......ooo...o....", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".................111..........1111111......1111111111....11111111111...11111111111....11111..11......111...1....", + "door": null + }, + "contentHash": "fnv1a:bd0000ef" + }, + { + "id": "xwr5wr6y6a2x", + "name": "Amber Deer", + "category": "dynamic", + "subtype": "animal", + "width": 14, + "height": 14, + "pixels": ".................................V............V.V..........VV9VV.........V999VV.......VV9xx9VV......V999999V......V999999VV.....V9999999V......V99999V.......V.VV.V.......k..VV..k......k..VV..k....", + "faces": { + "right": ".................................V............V.V..........VV9VV.........V999VV.......VV9xx9VV......V999999V......V999999VV.....V9999999V......V99999V.......V.VV.V.......k..VV..k......k..VV..k....", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...................1............1.1..........11111.........111111.......11111111......11111111......111111111.....111111111......1111111.......1.11.1.......1..11..1......1..11..1..................", + "door": null + }, + "contentHash": "fnv1a:b497b00e" + }, + { + "id": "l2antp0y6a33", + "name": "Forest Owl", + "category": "dynamic", + "subtype": "bird", + "width": 10, + "height": 12, + "pixels": ".......................dd.d.....dkkkkd....k4444k...k44ww44k..k444444k..kk4444kk...kggggk....kggggk....k.kk.k.....k..k...", + "faces": { + "right": ".......................dd.d.....dkkkkd....k4444k...k44ww44k..k444444k..kk4444kk...kggggk....kggggk....k.kk.k.....k..k...", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".............11.1.....111111....111111...11111111..11111111..11111111...111111....111111....1.11.1.....1..1.............", + "door": null + }, + "contentHash": "fnv1a:6e50e7b9" + }, + { + "id": "byljnniy6a36", + "name": "Kingfisher", + "category": "dynamic", + "subtype": "bird", + "width": 10, + "height": 8, + "pixels": "........................W........WWWM.....WnMMMMd..WWnMMssd...Wnnnnd......o.o...", + "faces": { + "right": "........................W........WWWM.....WnMMMMd..WWnMMssd...Wnnnnd......o.o...", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "..............1........1111.....1111111..11111111...111111......1.1.............", + "door": null + }, + "contentHash": "fnv1a:5eaf945f" + }, + { + "id": "ybigmijy6a39", + "name": "Pond Duck", + "category": "dynamic", + "subtype": "bird", + "width": 12, + "height": 10, + "pixels": "........................................ii.........i4444......i444iiid....i4444444d...iii4444d......4..4.......k....k...", + "faces": { + "right": "........................................ii.........i4444......i444iiid....i4444444d...iii4444d......4..4.......k....k...", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "............................11.........11111......11111111....111111111...11111111......1..1.......1....1...............", + "door": null + }, + "contentHash": "fnv1a:aebe8348" + }, + { + "id": "uvnxnbmy6a3c", + "name": "Heron", + "category": "dynamic", + "subtype": "bird", + "width": 10, + "height": 16, + "pixels": "...................................3........333........33c......3333.....333ss.....33333......3333.......33........33........33........33.......k..k......k..k..", + "faces": { + "right": "...................................3........333........33c......3333.....333ss.....33333......3333.......33........33........33........33.......k..k......k..k..", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...............1........111........111......1111.....11111.....11111......1111.......11........11........11........11.......1..1......1..1......................", + "door": null + }, + "contentHash": "fnv1a:8a2d5c57" + }, + { + "id": "lg1jnrjy6a3f", + "name": "Sunset Koi", + "category": "dynamic", + "subtype": "fish", + "width": 12, + "height": 8, + "pixels": "........................................d.........ddhhhhdd...dhhMMMhhhR...dhhhhhhdd.....d.d.....", + "faces": { + "right": "........................................d.........ddhhhhdd...dhhMMMhhhR...dhhhhhhdd.....d.d.....", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": true, + "particlePixels": [ + { + "x": 2, + "y": 4, + "c": "7", + "dir": "up" + } + ], + "particleConfig": { + "enabled": true, + "c": "7", + "dir": "up" + }, + "depthPixels": "............................1.........11111111...1111111111...111111111.....1.1.................", + "door": null + }, + "contentHash": "fnv1a:ba7fa061" + }, + { + "id": "j3lfyriy6a3l", + "name": "Town Gardener", + "category": "dynamic", + "subtype": "human", + "width": 12, + "height": 16, + "pixels": "................................................................AA.........A55A........5MM5........55o55........oee........oeeee.......oeeee........ooo........oo.oo.......o...o......AA...AA...", + "faces": { + "right": "................................................................AA.........A55A........5MM5........55o55........oee........oeeee.......oeeee........ooo........oo.oo.......o...o......AA...AA...", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "................11.........1111........1111........11111........111........11111.......11111........111........11.11.......1...1......11...11...................................................", + "door": null + }, + "contentHash": "fnv1a:5b105e7b" + }, + { + "id": "4jtf6ioy6a3q", + "name": "Lantern Courier", + "category": "dynamic", + "subtype": "human", + "width": 12, + "height": 16, + "pixels": "................................................................AA.........A55A........5MM5........5555.........hhhh.......hhhhh5......hhhh.5.......nnnn.......nn.nn.......n...n......AA...AA...", + "faces": { + "right": "................................................................AA.........A55A........5MM5........5555.........hhhh.......hhhhh5......hhhh.5.......nnnn.......nn.nn.......n...n......AA...AA...", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "................11.........1111........1111........1111.........1111.......111111......1111.1.......1111.......11.11.......1...1......11...11...................................................", + "door": null + }, + "contentHash": "fnv1a:25a7719d" + }, + { + "id": "ix1a44vy6a3u", + "name": "Plaza Musician", + "category": "dynamic", + "subtype": "human", + "width": 14, + "height": 16, + "pixels": "...........................................................................AA...........A55A..........5MM5..........5555.........XXXXXX........Xttddd........Xttddd.........dkkd.........dk..kd........A....A.......AA....AA....", + "faces": { + "right": "...........................................................................AA...........A55A..........5MM5..........5555.........XXXXXX........Xttddd........Xttddd.........dkkd.........dk..kd........A....A.......AA....AA....", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...................11...........1111..........1111..........1111.........111111........111111........111111.........1111.........11..11........1....1.......11....11............................................................", + "door": null + }, + "contentHash": "fnv1a:0c84b262" + }, + { + "id": "2igldehy6a3z", + "name": "Bridge Mechanic", + "category": "dynamic", + "subtype": "human", + "width": 14, + "height": 16, + "pixels": "...........................................................................AA...........A55A..........5MM5..........5555.........jjjjjj........jjwjjj........jjwjjd.........oooo.........oo.oo.........o...o........AA...AA.....", + "faces": { + "right": "...........................................................................AA...........A55A..........5MM5..........5555.........jjjjjj........jjwjjj........jjwjjd.........oooo.........oo.oo.........o...o........AA...AA.....", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...................11...........1111..........1111..........1111.........111111........111111........111111.........1111.........11.11.........1...1........11...11.............................................................", + "door": null + }, + "contentHash": "fnv1a:48ca7020" + }, + { + "id": "ds7gpmty6a4a", + "name": "Harbor Clocktower", + "category": "static", + "subtype": "building", + "width": 32, + "height": 40, + "pixels": ".............................................................................................................................................................................................................................................................................oooooo.........................kkkkkkkk.......................kkkkkkkkkk........................kkkkkk..........................kkkkkk..........................kkkkkk.........................gggggggg........................gggggggg........................gggggggg........................gggggggg........................g444444g........................g400004g........................g400o04g........................g40oo04g........................g400004g........................g444444g........................gggggggg........................gggggggg........................gggggggg........................g55gg55g........................g55gg55g........................g55gg55g........................gggggggg........................gggggggg........................gggggggg........................gg55g55g........................gg55g55g........................gg55g55g........................gggggggg........................gggggggg.......................gggggggggg......................gggggggggg...........", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 15, + "y": 12, + "c": "5" + }, + { + "x": 16, + "y": 12, + "c": "5" + }, + { + "x": 13, + "y": 22, + "c": "5" + }, + { + "x": 18, + "y": 22, + "c": "5" + }, + { + "x": 14, + "y": 28, + "c": "5" + }, + { + "x": 17, + "y": 28, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".............111111.........................11111111.......................1111111111........................111111..........................111111..........................111111.........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111........................11111111.......................1111111111......................1111111111...........................................................................................................................................................................................................................................................................", + "door": { + "x": 15, + "y": 38 + } + }, + "contentHash": "fnv1a:84e7cd5a" + }, + { + "id": "fbd7df9y6a4u", + "name": "Glass Greenhouse", + "category": "static", + "subtype": "building", + "width": 28, + "height": 20, + "pixels": ".............................................................................................................................33.........................OOOO.......................333333.....................OOOOOOOO..............cccccccccccccccccccc........c333c333c333c333c333........c333c333c333c333c333........cccccccccccccccccccc........c333c333c333c3aac333........c333aa331111c3aac333........ccccaacc1111cccccccc........c33eee331111c3eee333........c33eee331111c3eee333........cccccccc1111cccccccc...............kkkkkk......................kkkkkk...........", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 10, + "y": 10, + "c": "1" + }, + { + "x": 13, + "y": 10, + "c": "1" + }, + { + "x": 16, + "y": 10, + "c": "1" + } + ], + "lightColor": "1", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".................................................................................................11.........................1111.......................111111.....................11111111..............11111111111111111111........11111111111111111111........11111111111111111111........11111111111111111111........11111111111111111111........11111111111111111111........11111111111111111111........11111111111111111111........11111111111111111111........11111111111111111111...............111111......................111111.......................................", + "door": { + "x": 13, + "y": 18 + } + }, + "contentHash": "fnv1a:2a1a7c75" + }, + { + "id": "170nhhsy6a5q", + "name": "Steam Workshop", + "category": "static", + "subtype": "building", + "width": 40, + "height": 24, + "pixels": "..................................................kbbk.............kbbbk..................kbbk.............kbbbk..................kbbk.............kbbbk..................kkkk.............kkkkk..................kkkk.............kkkkk..................kkkk....ssssssssskkkkksss...........ooookkkkoooossssssssskkkkksss...........ooookkkkoooossssssssskkkkksss.........kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk........kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk........kkggggggggggkkggggggggggggggggkk........kkggg999gg999kgggggg999gg999ggkk........kkggg999gg999kgggggg999gg999ggkk........kkggg999gg999kgggggg999gg999ggkk........kkggggggggggkkggggggggggggggggkk........kkggggggggggkkwwwwwwggggggggggkk........kkggggggggggkkwwwwwwggggggggggkk........kkggggggggggkkwwwwwwggggggggggkk........kkkkkkkkkkkkkkwwwwwwkkkkkkkkkkkk........kkkkkkkkkkkkkkwwwwwwkkkkkkkkkkkk......oooooooooooooooooooooooooooooooooooo....oooooooooooooooooooooooooooooooooooo....oooooooooooooooooooooooooooooooooooo..", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 13, + "y": 14, + "c": "9" + }, + { + "x": 18, + "y": 14, + "c": "9" + }, + { + "x": 27, + "y": 14, + "c": "9" + }, + { + "x": 32, + "y": 14, + "c": "9" + } + ], + "lightColor": "9", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "..........1111.............11111..................1111.............11111..................1111.............11111..................1111.............11111..................1111.............11111..................1111....11111111111111111...........11111111111111111111111111111...........11111111111111111111111111111.........11111111111111111111111111111111........11111111111111111111111111111111........11111111111111111111111111111111........11111111111111111111111111111111........11111111111111111111111111111111........11111111111111111111111111111111........11111111111111111111111111111111........11111111111111111111111111111111........11111111111111111111111111111111........11111111111111111111111111111111........11111111111111111111111111111111........11111111111111111111111111111111......111111111111111111111111111111111111....111111111111111111111111111111111111....111111111111111111111111111111111111..........................................", + "door": { + "x": 20, + "y": 22 + } + }, + "contentHash": "fnv1a:eb5424f2" + }, + { + "id": "k18uukoy6a6o", + "name": "Canal Bridge", + "category": "static", + "subtype": "building", + "width": 48, + "height": 16, + "pixels": "...........................................................................................................................................................................................................................................................................................................88..88..88..88..88..88..88..88.................8...8...8...8...8...8...8...8...................8...8...8...8...8...8...8...8...................8...8...8...8...8...8...8...8.................gg8ggg8ggg8ggg8ggg8ggg8ggg8ggg8g................gg8ggg8ggg8ggg8ggg8ggg8ggg8ggg8g..............ggggggggggggjjjjjjjjjjjjgggggggggggg............ggggggggggjjjjjjjjjjjjjjjjgggggggggg.........ooooooooooooooojjjjjjjjjjjjooooooooooooooo......ooooooooooooooooojjjjjjjjooooooooooooooooo...", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...........................................................................................................................................................................................................11..11..11..11..11..11..11..11.................1...1...1...1...1...1...1...1...................1...1...1...1...1...1...1...1...................1...1...1...1...1...1...1...1.................11111111111111111111111111111111................11111111111111111111111111111111..............111111111111111111111111111111111111............111111111111111111111111111111111111.........111111111111111111111111111111111111111111......111111111111111111111111111111111111111111...................................................................................................", + "door": null + }, + "contentHash": "fnv1a:508d58cb" + }, + { + "id": "sbl2ma4y6a78", + "name": "Grand Fountain", + "category": "static", + "subtype": "building", + "width": 24, + "height": 24, + "pixels": "...........................................................33.....................3333...................3SSSS3...................3SS3...................33SS33.................3SSSSSS3.................3SSSS3................ggg3333ggg.............gOOOggggOOOg...........gOOSSSSSSOOOg..........gOOSSSSSSSSOOOg.........gOSSSS33SSSSOOg.........gOOSSSSSSSSOOOg..........gOOSSSSSSOOOg............gOOOggggOOg..............ggggggggg...............kkkkkkkkk..............kkkggggkkkk............kkggggggggkk...........kkkkkkkkkkkkkk..........kkSSSSSSSSSSkk...........kkkkkkkkkkkk.......", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 11, + "y": 7, + "c": "3" + }, + { + "x": 12, + "y": 7, + "c": "3" + }, + { + "x": 9, + "y": 12, + "c": "3" + }, + { + "x": 14, + "y": 12, + "c": "3" + } + ], + "lightColor": "3", + "hasParticles": true, + "particlePixels": [ + { + "x": 11, + "y": 5, + "c": "3", + "dir": "up" + }, + { + "x": 12, + "y": 5, + "c": "3", + "dir": "up" + } + ], + "particleConfig": { + "enabled": true, + "c": "3", + "dir": "up" + }, + "depthPixels": "...................................11.....................1111...................111111...................1111...................111111.................11111111.................111111................1111111111.............111111111111...........1111111111111..........111111111111111.........111111111111111.........111111111111111..........1111111111111............11111111111..............111111111...............111111111..............11111111111............111111111111...........11111111111111..........11111111111111...........111111111111...............................", + "door": null + }, + "contentHash": "fnv1a:664416a8" + }, + { + "id": "965de5py6a7s", + "name": "Rocket Monument", + "category": "static", + "subtype": "building", + "width": 20, + "height": 32, + "pixels": ".............................hh.................h33h...............h3333h..............h3333h.............hh3bb3hh............h33bb33h............h333333h............h33kk33h............h33kk33h............h333333h...........hh333333hh..........h33333333h..........h33333333h..........h33hh3333h..........h33hh3333h..........h33333333h..........hh333333hh...........h333333h...........hh333333hh.........hhh333333hhh........h3333333333h........h3333333333h........hhhh3333hhhh.........kkk3333kkk..........kk999999kk..........kkdd99ddkk..........kk999999kk..........kkkkkkkkkk...........ooo..ooo...........ooo....ooo..........oo......oo.....", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 9, + "y": 8, + "c": "5" + }, + { + "x": 10, + "y": 8, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": true, + "particlePixels": [ + { + "x": 8, + "y": 27, + "c": "9", + "dir": "up" + }, + { + "x": 11, + "y": 27, + "c": "d", + "dir": "up" + } + ], + "particleConfig": { + "enabled": true, + "c": "9", + "dir": "up" + }, + "depthPixels": ".........11.................1111...............111111..............111111.............11111111............11111111............11111111............11111111............11111111............11111111...........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........1111111111...........11111111...........1111111111.........111111111111........111111111111........111111111111........111111111111.........1111111111..........1111111111..........1111111111..........1111111111..........1111111111...........111..111...........111....111..........11......11.........................", + "door": { + "x": 9, + "y": 30 + } + }, + "contentHash": "fnv1a:bed0e859" + }, + { + "id": "j2lv8uvy6a8c", + "name": "Arcade Booth", + "category": "static", + "subtype": "building", + "width": 24, + "height": 20, + "pixels": "....................................................................................................XXXXXXXXXXXXXXXX........XXXXXXNXXQXXOXXX.......sXXXXXXXXXXXXXXXXs......ssssssssssssssssss......ssszzzzzzzzzzzzsss......ssszWWWWWWWWWWzsss......ssszWWWWWWWWWWzsss......ssszWWWWWWWWWWzsss......ssszWWWWWWWWWWzsss......ssszzzzzzzzzzzzsss......ssssssssssssssssss......sssssswwwwwwssssss......sssssswwwwwwssssss...........oooooooo................oooooooo..........wwwwwwwwwwwwwwwwwwww..", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 7, + "y": 10, + "c": "b" + }, + { + "x": 16, + "y": 10, + "c": "b" + }, + { + "x": 11, + "y": 6, + "c": "b" + } + ], + "lightColor": "b", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "............................................................................1111111111111111........1111111111111111.......111111111111111111......111111111111111111......111111111111111111......111111111111111111......111111111111111111......111111111111111111......111111111111111111......111111111111111111......111111111111111111......111111111111111111......111111111111111111...........11111111................11111111..........11111111111111111111..........................", + "door": { + "x": 11, + "y": 18 + } + }, + "contentHash": "fnv1a:7553c015" + }, + { + "id": "qamstg6y6a8u", + "name": "Chess Knight Statue", + "category": "static", + "subtype": "building", + "width": 16, + "height": 24, + "pixels": "......................................88.............8008...........800008..........800f008.........8000088........80000008........80080008........80088008.........800008..........800008.........88000088.......8880000888......8000000008......8888008888........kk00kk.........kkk00kkk.......kkkkkkkkkk......kkkggggkkk......kkggggggkk.....kkkkkkkkkkkk....kffffffffffk.....kkkkkkkkkk....", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 7, + "y": 8, + "c": "3" + }, + { + "x": 8, + "y": 8, + "c": "3" + } + ], + "lightColor": "3", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "......................11.............1111...........111111..........1111111.........1111111........11111111........11111111........11111111.........111111..........111111.........11111111.......1111111111......1111111111......1111111111........111111.........11111111.......1111111111......1111111111......1111111111.....111111111111....111111111111.....1111111111....................", + "door": null + }, + "contentHash": "fnv1a:04de304a" + }, + { + "id": "cthsuy3y6a9h", + "name": "Desert Train", + "category": "static", + "subtype": "building", + "width": 44, + "height": 16, + "pixels": "................................................................................................33........................................77..........................................77.........................................kkkk...kkkkkkkkkk...kkkkkkkkkk..............kkkk...kkkkkkkkkk...kkkkkkkkkk..............kk55..hhhhhhhhhhhhhhhhhhhhhhhhhh...........kkk55kkhh999hh999hhhhhh999hh999hhkkkkk......kkkkkkkhh999hh999hhhhhh999hh999hhkkkkk......kkkkkkkhhhhhhhhhhhhhhhhhhhhhhhhhhkkkkk......kkAkkkkhhhhAhhhhhAhhhhhhhAhhhhhAhkkkAk.......AAA...oooAAAoooAAAoooooAAAoooAAA..AAA......AAgAA....AAgAA.AAgAA...AAgAA.AAgAAAAgAA...gggggggggggggggggggggggggggggggggggggggg..oooooooooooooooooooooooooooooooooooooooooooo", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 7, + "y": 7, + "c": "9" + }, + { + "x": 13, + "y": 8, + "c": "9" + }, + { + "x": 19, + "y": 8, + "c": "9" + }, + { + "x": 28, + "y": 8, + "c": "9" + }, + { + "x": 35, + "y": 8, + "c": "9" + } + ], + "lightColor": "9", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "................................................................................................11........................................11..........................................11.........................................1111...1111111111...1111111111..............1111...1111111111...1111111111..............1111..11111111111111111111111111...........11111111111111111111111111111111111111......11111111111111111111111111111111111111......11111111111111111111111111111111111111......11111111111111111111111111111111111111.......111...11111111111111111111111111..111......11111....11111.11111...11111.1111111111...1111111111111111111111111111111111111111..11111111111111111111111111111111111111111111", + "door": null + }, + "contentHash": "fnv1a:8604fff2" + }, + { + "id": "zl4ia2fy6a9y", + "name": "Tea Robot", + "category": "dynamic", + "subtype": "human", + "width": 12, + "height": 16, + "pixels": ".................................................................bb.........b33b........b3s3b.......b333b........ddd........dkkkd.......dkOkdO.......dkkd.......g.ggg......gg..gg......s....s...", + "faces": { + "right": ".................................................................bb.........b33b........b3s3b.......b333b........ddd........dkkkd.......dkOkdO.......dkkd.......g.ggg......gg..gg......s....s...", + "left": "mirror" + }, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 8, + "y": 8, + "c": "O" + } + ], + "lightColor": "O", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".................11.........1111........11111.......11111........111........11111.......111111.......1111.......1.111......11..11......1....1...................................................", + "door": null + }, + "contentHash": "fnv1a:e65ea2ff" + }, + { + "id": "bomdmjgy6aa2", + "name": "Balloon Vendor", + "category": "dynamic", + "subtype": "human", + "width": 14, + "height": 18, + "pixels": "..........................................................Q..N..b.......Q..N..b.......QQ.NN.bb.........k.............A............AkkA..........kMMk..........kkkk.........hhhhhh........hhhhhh.........bb.bb........bb...b........A....A.......AA....AA....", + "faces": { + "right": "..........................................................Q..N..b.......Q..N..b.......QQ.NN.bb.........k.............A............AkkA..........kMMk..........kkkk.........hhhhhh........hhhhhh.........bb.bb........bb...b........A....A.......AA....AA....", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "..1..1..1.......1..1..1.......11.11.11.........1.............1............1111..........1111..........1111.........111111........111111.........11.11........11...1........1....1.......11....11............................................................", + "door": null + }, + "contentHash": "fnv1a:d3a90d8d" + }, + { + "id": "tfwksj6y6aa6", + "name": "Jelly Comet", + "category": "dynamic", + "subtype": "animal", + "width": 12, + "height": 12, + "pixels": "..........................................b.........bbbbb.....bb33333bb...b33nnn33b...b3333333b....b33333b......bbbbb........7.7........7...7...", + "faces": { + "right": "..........................................b.........bbbbb.....bb33333bb...b33nnn33b...b3333333b....b33333b......bbbbb........7.7........7...7...", + "left": "mirror" + }, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 7, + "y": 4, + "c": "7" + } + ], + "lightColor": "7", + "hasParticles": true, + "particlePixels": [ + { + "x": 2, + "y": 6, + "c": "3", + "dir": "up" + } + ], + "particleConfig": { + "enabled": true, + "c": "3", + "dir": "up" + }, + "depthPixels": "..................1.........11111.....111111111...111111111...111111111....1111111......11111........1.1........1...1...........................", + "door": null + }, + "contentHash": "fnv1a:4b26e093" + }, + { + "id": "p3gxv6py6aaa", + "name": "Courier Bike", + "category": "dynamic", + "subtype": "human", + "width": 16, + "height": 12, + "pixels": "......................AA.............A55A............5MM5............5555...........WWWWWW..........Wooo.W..........W.oooW...........s.s...........44...44........44M4444M4........44...44......", + "faces": { + "right": "......................AA.............A55A............5MM5............5555...........WWWWWW..........Wooo.W..........W.oooW...........s.s...........44...44........44M4444M4........44...44......", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "......................11.............1111............1111............1111...........111111..........1111.1..........1.1111...........1.1...........11...11........111111111........11...11......", + "door": null + }, + "contentHash": "fnv1a:01dfc817" + }, + { + "id": "x451owfy6aad", + "name": "Great Cedar", + "category": "static", + "subtype": "nature", + "width": 24, + "height": 32, + "pixels": "..................................iiii..................iieeeeii..............iieee66eeii............ieee6666eeeii..........ieee66ii66eeei.........ieee66iiii66eeei........iee66iiiiii66eei.......iee66iimmmmii66eei......iee6iimmmmmmii6eei.....iee66immiiiimmi66eei....iee6iimiiiiiimii6eei....ie66iiiiiiiiiiii66ei....ie6iiiiiiiiiiiiii6ei...ie66iiiiiiiiiiiiii66ei..ie6iiiiiiiiiiiiiiii6ei..ie6iiiiiiiiiiiiiiii6ei...ie6iiiiiiiiiiiiii6ei....ie66iiiiiiiiiiii66ei....iee6iiiiiiiiiiii6eei....iee66iiiiiiiiii66eei.....iee6iiiiiiiiii6eei......iee66iiiiiiii66eei.......iee66iiiiii66eei.........ieee66ii66eeei...........ieee6666eeei.............ieeeppeeei...............ieeppeei................pppppppp...............pppppppppp..............ppppddpppp.............tttttttttttt.......", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "..........1111..................11111111..............11111111111............11111111111111.........111111111111111........11111111111111111.......11111111111111111......1111111111111111111.....1111111111111111111....111111111111111111111...111111111111111111111...111111111111111111111...111111111111111111111..11111111111111111111111.11111111111111111111111.11111111111111111111111..111111111111111111111...111111111111111111111...111111111111111111111...111111111111111111111....1111111111111111111.....1111111111111111111......11111111111111111........111111111111111..........1111111111111............1111----111..............111----11...............--------...............----------..............----------.............------------...............................", + "door": null + }, + "contentHash": "fnv1a:47b0b007" + }, + { + "id": "1rmrha4y6aaw", + "name": "Moonfall Cascade", + "category": "static", + "subtype": "nature", + "width": 24, + "height": 32, + "pixels": "..............................iiiiiiiiiiii..........iiggggggggggggii.......iggg77333377ggggi......igg773333333377gggi.....ig73333SSSS33337gi.....ig7333SSSSSSSS337gi.....ig333SSSffffSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSSf33fSSS33gi.....ig333SSS3333SSS33gi.....ig333333333333333gi......ig3333773377333gi.......ig3337733337733gi........ig33333333333gi..........ig3333333333gi..........ii3333333333ii...........33ffffffff33...........33ffffffffff33..........3ffffffffffff3..........33333333333333..........SSSSSSSSSSSSSS......", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": true, + "particlePixels": [ + { + "x": 9, + "y": 20, + "c": "3", + "dir": "up" + }, + { + "x": 14, + "y": 20, + "c": "3", + "dir": "up" + } + ], + "particleConfig": { + "enabled": true, + "c": "3", + "dir": "up" + }, + "depthPixels": "......111111111111..........1111111111111111.......11111111111111111......1111111111111111111.....1111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....1111111----1111111.......111111----111111........111111----111111.........11111----11111...........1111----1111............1111----1111.............------------...........--------------..........--------------..........--------------..........--------------..............................", + "door": null + }, + "contentHash": "fnv1a:836a9d7d" + }, + { + "id": "omsnif2y6abh", + "name": "Sunblossom Gate", + "category": "static", + "subtype": "nature", + "width": 24, + "height": 24, + "pixels": "................................NNNN..................NNVVVVNN...............NVVVeeVVVN.............NVVVeeeeVVVN...........NNVVee11eeVVNN.........NNVVee1111eeVVNN........NVVVe111111eVVVN.......NVVVe11....11eVVVN......NVVVe1......1eVVVN......NVVVe1......1eVVVN......NVVVe1......1eVVVN......NVVVe1......1eVVVN......NVVVe1......1eVVVN......NVVVe1......1eVVVN.......NVVVee....eeVVVN........NNVVVeeeeeeVVNN..........NNVVkkkkkkVNN............kkkkooookkk.............kkkkooookkk.............kkkkooookkk.............kkkkkkkkkkk..............eeeeeeee................eeeeeeee...........", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "........1111..................11111111...............1111111111.............111111111111...........11111111111111.........1111111111111111........1111111111111111.......1111111....1111111......111111......111111......111111......111111......111111......111111......111111......111111......111111......111111......111111......111111.......111111....111111........1111111111111111.........11111------111...........----1111----............----1111----............----1111----............-------------............--------................--------...................................", + "door": null + }, + "contentHash": "fnv1a:b728a136" + }, + { + "id": "kd1fy1my6abs", + "name": "Echo Cavern", + "category": "static", + "subtype": "nature", + "width": 32, + "height": 20, + "pixels": "..........................................gggggggggg...................ggggiiiiiiiigggg..............ggiiiiiAAAAiiiiiigg............giiiiAAAAAAAAAAiiiig...........giiiAAAAAAAAAAAAAAiiig.........giiAAAAAAAA..AAAAAAAAiig.......giiAAAAAA......AAAAAAAiig.......giAAAAA..........AAAAAAig.......giAAAA............AAAAAig.......giAAA..............AAAAig.......giAAA..............AAAAig.......giAAAA............AAAAAig.......giAAAAA..........AAAAAAig.......giiAAAAAA......AAAAAAAiig........giiAAAAAAAA..AAAAAAAAiig.........giiiAAAAAAAAAAAAAAiiig...........giiiiAAAAAAAAAAiiiig.............ggiiiiiAAAAiiiiigg...............oooooooooooooooo..........", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "..........................................1111111111...................1111111111111111..............11111111111111111111...........111111111111111111111..........11111111111111111111111........111111111111..1111111111.......1111111111......111111111.......11111111..........11111111......1111111............1111111......111111..............111111......111111..............111111......1111111............1111111......11111111..........11111111......1111111111......111111111........111111111111..1111111111.........11111111111111111111111..........111111111111111111111............1111111111111111111..............----------------..........", + "door": null + }, + "contentHash": "fnv1a:fb73fb21" + }, + { + "id": "shtpgwfy6ac5", + "name": "Worldroot Shrine", + "category": "static", + "subtype": "nature", + "width": 28, + "height": 28, + "pixels": "............iiii......................iieeeeii..................iieee66eeeii...............ieee666666eeei.............iee66iiiiii66eei...........iee6iiiiiiiiii6eei.........iee6iiiikkiiiiii6eei........iee6iiikkkkiiiii6eei.......iee6iikkkkkkkkiii6eei.......iee6iikkkoookkkii6eei......iee6iikkkoo66ookkii6eei.....iee6iikkoo6666ookii6eei.....iee6iikkoo6556ookii6eei.....iee6iikkoo5555ookii6eei.....iee6iikkoo6556ookii6eei.....iee6iikkoo6666ookii6eei.....iee6iikkkoo66ookkii6eei......iee6iikkkoookkkii6eei.......iee6iikkkkkkkkiii6eei........iee6iiikkkkiiiii6eei........iee6iiiikkiiiiii6eei.........iee6iiiiiiiiii6eei...........iee66iiiiii66eei.............ieee66kk66eeei...............ieeekkkkeeii.................kkkkkkkkkk.................kkkkcckkkkkk...............oooooooooooooo.......", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 13, + "y": 12, + "c": "5" + }, + { + "x": 14, + "y": 12, + "c": "5" + }, + { + "x": 12, + "y": 13, + "c": "5" + }, + { + "x": 15, + "y": 13, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "............1111......................11111111..................111111111111...............11111111111111.............1111111111111111...........111111111111111111.........11111111111111111111........11111111111111111111.......1111111111111111111111......1111111111111111111111.....111111111111111111111111....111111111111111111111111....111111111111111111111111....111111111111111111111111....111111111111111111111111....111111111111111111111111....111111111111111111111111.....1111111111111111111111......1111111111111111111111.......11111111111111111111........11111111111111111111.........111111111111111111...........1111111111111111.............11111111111111...............1111----1111.................----------.................------------...............----------------.....", + "door": null + }, + "contentHash": "fnv1a:4a077f44" + }, + { + "id": "kmjtd3ly6acp", + "name": "Moon Jelly Aquarium", + "category": "static", + "subtype": "building", + "width": 24, + "height": 28, + "pixels": "...................................55.....................5005...................5A00A5.................ATSSSSTA...............ATSOOOOSTA.............ATSOO00OOSTA............ASOOOOOOOOSA...........ATSOOQQQQOOSTA..........ASOOQQ55QQOOSA.........ATSOOQ5555QQOOSTA.......ASOOQ555555QQOOSA.......ASOOQ555555QQOOSA......ATSOOQ555555QQOOSTA.....A.SOOQTTTTTTQQOOS.A.....A.A55TAAAAAAT55A.A......A.kg5T5....5T5gk.A.......Akkg5......5gkkA........Aggg5......5gggA........Aggg5..ww..5gggA........Aggg5.wwww.5gggA........Aggg55555555gggA........AgggkkkkkkkkgggA........AkkkkgwwwwgkkkkA.........Akkkgw...wgkkkA.........Awwwgg...ggwwwA..........AwwwwAAAwwwwA............AAAAAAAAAAA......", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 10, + "y": 10, + "c": "5" + }, + { + "x": 13, + "y": 10, + "c": "5" + }, + { + "x": 11, + "y": 20, + "c": "5" + }, + { + "x": 12, + "y": 20, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...........11.....................1111...................111111.................11111111...............1111111111.............111111111111............111111111111...........111111..111111..........11111....11111.........111111....111111........111111....111111........111111....111111.......1111111....1111111......111111......111111......11..11......11..11......11..11......11..11.......11..1......1..11........11..1......1..11........11111..--..11111........11111.----.11111........1111111111111111........11111------11111........11111------11111.........1111------1111..........11111....11111...........11111..11111.............1111111111...............................", + "door": { + "x": 11, + "y": 24 + } + }, + "contentHash": "fnv1a:2ce3fef7" + }, + { + "id": "uzvrmc4y6adk", + "name": "Aurora Observatory", + "category": "static", + "subtype": "building", + "width": 28, + "height": 28, + "pixels": "........................................AAAA......................AAXXXXAA...................AXX7777XXA.................AXX777777XXA...............AXX77bbbb77XXA.............AXX7bbbbbbbb7XXA............AXXbbbbbbbbbbXXA...........AXXbbbbbbbbbbbbXXA..........AXXbbbbbbbbbbbbXXA..........AXXXXXXXXXXXXXXXXA.........AAkkkkkkAAkkkkkkkkAA........AkkkkkkA..AkkkkkkkkA.......AAkkk11kAAAAkk11kkkAA.......Akkk1111kkkk1111kkkkA.......Akk111111kk111111kkkA.......Akk11ww11kk11ww11kkkA.......Akk111111kk111111kkkA.......AkkkkkkkkkkkkkkkkkkkA.......AkkcccccccccccccckkkA.......AkkckkkcckkkkcckkckkA.......AkkckkkcckkkkcckkckkA.......AkkcccccccccccccckkkA.......AkkcckkkcccccckkckkkA.......AkkcckkkccwwcckkckkkA.......AkkccccccwwcccccckkkA........AkkkkkkkkwwkkkkkkkA.........AAAAAAAAAAAAAAAAAA......", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 13, + "y": 2, + "c": "3" + }, + { + "x": 14, + "y": 2, + "c": "3" + }, + { + "x": 9, + "y": 13, + "c": "3" + }, + { + "x": 18, + "y": 13, + "c": "3" + }, + { + "x": 13, + "y": 23, + "c": "3" + } + ], + "lightColor": "3", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "............1111......................11111111...................1111111111.................111111111111...............11111111111111.............1111111111111111............1111111111111111...........111111111111111111..........111111111111111111..........111111111111111111.........11111111111111111111........11111111..1111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111.......111111111111111111111........1111111111111111111.........111111111111111111..................................", + "door": { + "x": 13, + "y": 24 + } + }, + "contentHash": "fnv1a:6316cef7" + }, + { + "id": "h82at0uy6ael", + "name": "Hearthwind Mill", + "category": "static", + "subtype": "building", + "width": 24, + "height": 28, + "pixels": "..................................AAAA...................A1111A..................A1bb1A.................A11bb11A................AAAbbAAA...............A..AbbA..A..........AAAAA..AbbA..AAAAA.....AkkkkAAAAbbAAAAkkkkA....AkkkkkkAAbbAAkkkkkkA....AkkkkkkkAAAAkkkkkkkA....AkkkkkkkkkkkkkkkkkkA....AccccccccccccccccccA....AccccccccccccccccccA....Acc55cccccccccc55ccA....Ac5555cccAAcc5555ccA....Acc55ccccAAcccc55ccA....Accccc888888cccccccA....Acc888kk888888kk8ccA....Acc8kkkk88ww88kkk8cA....Acc8kkkk88ww88kkk8cA....Acc8888888ww888888cA....Accc888888ww8888cccA....AcccccccccwwcccccccA....AcccccccccwwcccccccA....AcccccccccwwcccccccA....AcccccccAAAAcccccccA.....AAAAAAAA..AAAAAAAA...", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 8, + "y": 13, + "c": "5" + }, + { + "x": 15, + "y": 13, + "c": "5" + }, + { + "x": 11, + "y": 18, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "..........1111...................111111..................111111.................11111111................11111111...............1..1111..1..........11111..1111..11111.....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111.....11111111..11111111...........................", + "door": { + "x": 11, + "y": 22 + } + }, + "contentHash": "fnv1a:3c976c7b" + }, + { + "id": "adu51aey6afj", + "name": "Tideglass Lighthouse", + "category": "static", + "subtype": "building", + "width": 20, + "height": 36, + "pixels": "........AAAA...............A5555A..............A5335A.............A553355A............AAA33AAA.............A.33.A..............A.bb.A.............AA.bb.AA............AMMMMMMA............AMM11MMA...........AAMM11MMAA..........AMMMMMMMMA..........AMM8888MMA..........AMM8kk8MMA..........AMM8888MMA.........AAMMMMMMMMAA........AMMMM11MMMMA........AMMMM11MMMMA........AMMMMMMMMMMA........AMMM8888MMMA........AMMM8kk8MMMA........AMMM8888MMMA.......AAMMMMMMMMMMAA......AMMMMMMMMMMMMA......AMMM88MM88MMMA......AMMMkkMMkkMMMA......AMMM88MM88MMMA.....AAMMMMMMMMMMMMAA....AMMMMMMMMMMMMMMA....AMMMMMMwwMMMMMMA....AMMMMMMwwMMMMMMA....AMMMM88ww88MMMMA....AMMMMkkwwkkMMMMA....AMMMM88ww88MMMMA.....AAAAAAwwAAAAAA...........AAAA........", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 8, + "y": 2, + "c": "1" + }, + { + "x": 9, + "y": 2, + "c": "1" + }, + { + "x": 8, + "y": 16, + "c": "1" + } + ], + "lightColor": "1", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "........1111...............111111..............111111.............11111111............11111111.............1.11.1..............1.11.1.............11.11.11............11111111............11111111...........1111111111..........1111111111..........1111111111..........1111111111..........1111111111.........111111111111........111111111111........111111111111........111111111111........111111111111........111111111111........111111111111.......11111111111111......11111111111111......11111111111111......11111111111111......11111111111111.....1111111111111111....1111111111111111....1111111111111111....1111111111111111....1111111111111111....1111111111111111....1111111111111111.....11111111111111...........1111........", + "door": { + "x": 8, + "y": 33 + } + }, + "contentHash": "fnv1a:a36dc353" + }, + { + "id": "yz6h7yry6agj", + "name": "Mossrail Depot", + "category": "static", + "subtype": "building", + "width": 32, + "height": 20, + "pixels": "....................................AAAAAAAAAAAAAAAAAAAAAAAA.......A555555555555555555555555A.....A55AAAAAAAAAAAAAAAAAAAAAA55A....A55AkkkkkkkkkkkkkkkkkkkkA55A....A55AkkkkkkkkkkkkkkkkkkkkA55A....A55AAAAAAAAAAAAAAAAAAAAAA55A...AA88888888888888888888888888AA..A8888888888888888888888888888A..A885555888855558888555588888A...A885555888855558888555588888A...A888888888888888888888888888A...A88cccccccccccccccccccccc888A...A88ckkkcccccccccccccckkkc888A...A88cccccccccAAAAccccccccc888A...A88ckkkcccccAwwAccccckkkc888A...A88cccccccccAwwAccccccccc888A...A888888888888ww8888888888888A...A888888888888ww8888888888888A...AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA.", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 6, + "y": 8, + "c": "5" + }, + { + "x": 13, + "y": 8, + "c": "5" + }, + { + "x": 20, + "y": 8, + "c": "5" + }, + { + "x": 26, + "y": 8, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "....111111111111111111111111.......11111111111111111111111111.....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111...111111111111111111111111111111..111111111111111111111111111111..11111111111111111111111111111...11111111111111111111111111111...11111111111111111111111111111...11111111111111111111111111111...11111111111111111111111111111...11111111111111111111111111111...11111111111111111111111111111...11111111111111111111111111111...11111111111111111111111111111...11111111111111111111111111111...111111111111111111111111111111.................................", + "door": { + "x": 15, + "y": 16 + } + }, + "contentHash": "fnv1a:b930d92b" + }, + { + "id": "rc1vh22y6ahk", + "name": "Lantern Library", + "category": "static", + "subtype": "building", + "width": 28, + "height": 24, + "pixels": "...............................................................AAAAAAAAAAAAAA.............A99999999999999A...........A99AAAAAAAAAAAA99A..........A9AooooooooooooA9A.........AAAAAAAAAAAAAAAAAAAA........AkkkkkkkkkkkkkkkkkkA.......AAkkk111kkAAkk111kkkAA......Akkk1111kkkkkk1111kkkA......Akkkk11kkkkkkkk11kkkkA......AkkkkkkkkkkkkkkkkkkkkA......Akk8888888888888888kkA......Akk8ooo88oo88oo88oo8kA......Akk8888888888888888kkA......Akk8ooo88oo88oo88oo8kA......Akk8888888888888888kkA......Akk88oo88888888oo88kkA......Akk88oo888AAw88oo88kkA......Akk8888888AAw888888kkA......AkkkkkkkkkkwwkkkkkkkkA......AkkkkkkkkkkwwkkkkkkkkA.......AkkkkkkkkAAAAkkkkkkA........AAAAAAAAA....AAAAAA.....", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 8, + "y": 7, + "c": "5" + }, + { + "x": 19, + "y": 7, + "c": "5" + }, + { + "x": 13, + "y": 16, + "c": "5" + }, + { + "x": 14, + "y": 16, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".......11111111111111.............1111111111111111...........111111111111111111..........111111111111111111.........11111111111111111111........11111111111111111111.......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111......1111111111111111111111.......11111111111111111111........111111111....111111.............................................................", + "door": { + "x": 13, + "y": 18 + } + }, + "contentHash": "fnv1a:ae675812" + }, + { + "id": "zzcxm83y6aij", + "name": "Velvet Theater", + "category": "static", + "subtype": "building", + "width": 28, + "height": 20, + "pixels": "............................................................AAAAAAAAAAAAAAAAAAAA.......A99999999999999999999A.....A99AAAAAAAAAAAAAAAAAA99A....A9AppppppppppppppppppA9A...AAAAAAAAAAAAAAAAAAAAAAAAAA..AooooooooooooooooooooooooA..Aoo55555555oooo55555555ooA..Aoo5QQQQQ55oooo55QQQQQ5ooA..Aoo55555555oooo55555555ooA..AooooooooooooooooooooooooA..AooccccccccccccccccccccooA..AoocooccooccccccooccoocooA..AoocccccccccAAcccccccccooA..AoocooccooccAAAAccooccocooA.AoocccccccccAAAAccccccccooA.AoooooooooooAAAooooooooooA..AooooooooooAAAAAoooooooooA..AAAAAAAAAAAAAAAAAAAAAAAAAA.", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 13, + "y": 14, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "....11111111111111111111.......1111111111111111111111.....111111111111111111111111....111111111111111111111111...11111111111111111111111111..11111111111111111111111111..11111111111111111111111111..11111111111111111111111111..11111111111111111111111111..11111111111111111111111111..11111111111111111111111111..11111111111111111111111111..11111111111111111111111111..111111111111111111111111111.111111111111111111111111111.11111111111111111111111111..11111111111111111111111111..11111111111111111111111111.........................................................", + "door": { + "x": 13, + "y": 16 + } + }, + "contentHash": "fnv1a:835a5a33" + }, + { + "id": "5n309pry6ajd", + "name": "Bloom Bridge Gate", + "category": "static", + "subtype": "nature", + "width": 24, + "height": 24, + "pixels": "..........AAAA..................AA9999AA...............A99QQQQ99A.............A99Q9999Q99A...........A99Q99AA99Q99A.........AA9999A..A9999AA.......AAkkkkkA..AkkkkkAA.....AAkkkAAkkAAkkAAkkkAA....AkkkA..AkkkkA..AkkkA....AkkA....AkkA....AkkA....AkkA....AkkA....AkkA....AkkA....AkkA....AkkA....AkkAAAAAAkkAAAAAAkkA....AkkaaaaaakkaaaaaakkA....AkkaiiiaakkaaiiiakkA....AkkaaaaaakkaaaaaakkA....AkkQQQQQQkkQQQQQQkkA....AkkQQ99QQkkQQ99QQkkA....AkkQQQQQQkkQQQQQQkkA.....AAkkkkkkkkkkkkkkAA.......AAAAAAkkAAAAAAAA............AAkkAA..................AkkkkA..................AAAAAA..........", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": true, + "particlePixels": [ + { + "x": 7, + "y": 2, + "c": "P", + "dir": "up" + }, + { + "x": 16, + "y": 2, + "c": "P", + "dir": "up" + } + ], + "particleConfig": { + "enabled": true, + "c": "P", + "dir": "up" + }, + "depthPixels": "..........1111..................11111111...............1111111111.............111111111111...........11111111111111.........1111111..1111111.......11111111..11111111.....11111111111111111111....11111..111111..11111....1111....1111....1111....1111....1111....1111....1111....1111....1111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111.....111111111111111111.......1111111111111111............111111..................111111..................111111..........", + "door": null + }, + "contentHash": "fnv1a:27609372" + }, + { + "id": "dlz3yc3y6ak1", + "name": "Starreef Submarine", + "category": "static", + "subtype": "ship", + "width": 32, + "height": 16, + "pixels": ".............................................................................................................AAAAAA.......................AAA999999AAA..................AA997777777799AA..............AA9977WWWWWWWW7799AA...........A9977WWWWWWWWWWWW7799A.........A997WWWWWAAAAWWWWWW799A........A997WWWWWA3333AWWWWW799A.......AA99WWWWWWA3bb3AWWWWWW99AA.....AA999999999A3333A999999999AA....AkkkkkkkkkkAAAAAAkkkkkkkkkkkA...Akkkk11kkkkkkkkkkkk11kkkkkkkA...AAkkkkkkkkkkkkkkkkkkkkkkkkkAA....AAAAAAAAAAAAAAAAAAAAAAAAAA....", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 15, + "y": 7, + "c": "7" + }, + { + "x": 20, + "y": 7, + "c": "7" + } + ], + "lightColor": "7", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".............................................111111.......................111111111111..................1111111111111111..............11111111111111111111...........1111111111111111111111.........11111111111111111111111........111111111111111111111111.......11111111111111111111111111.....1111111111111111111111111111....11111111111111111111111111111...11111111111111111111111111111...11111111111111111111111111111....11111111111111111111111111....................................................................", + "door": null + }, + "contentHash": "fnv1a:0d858047" + }, + { + "id": "3na95zgy6akh", + "name": "Astrolabe Courier", + "category": "dynamic", + "subtype": "human", + "width": 12, + "height": 16, + "pixels": "....AAAA.......AccccA......AccccA......AAAAAA.....AAnnnnAA....Ann33nnA....Annn3nnA.....AnnnnA.....AAnnnnAA...AAnnAAnnAA..AnnA..AnnA..AnnAAAAnnA..AnnnggnnnA..AnnAggAnnA...AAA..AAA.....A....A...", + "faces": { + "right": "....AAAA.......AccccA......AccccA......AAAAAA.....AAnnnnAA....Ann33nnA....Annn3nnA.....AnnnnA.....AAnnnnAA...AAnnAAnnAA..AnnA..AnnA..AnnAAAAnnA..AnnnggnnnA..AnnAggAnnA...AAA..AAA.....A....A...", + "left": "mirror" + }, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 6, + "y": 5, + "c": "3" + } + ], + "lightColor": "3", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "....1111.......111111......111111......111111.....11111111....11111111....11111111.....111111.....11111111...1111111111..1111..1111..1111111111..1111111111..1111111111...111..111.....1....1...", + "door": null + }, + "contentHash": "fnv1a:0e69132c" + }, + { + "id": "has1j9ty6ako", + "name": "Puddle Toad", + "category": "dynamic", + "subtype": "animal", + "width": 12, + "height": 10, + "pixels": "...........................AA..AA.....AeeAAeeA...AeeeeeeeeA..AeeAeeAeeA..AeeeeeeeeA..A33eeee33A...A333333A.....AAAAAA...", + "faces": { + "right": "...........................AA..AA.....AeeAAeeA...AeeeeeeeeA..AeeAeeAeeA..AeeeeeeeeA..A33eeee33A...A333333A.....AAAAAA...", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...............11..11.....11111111...1111111111..1111111111..1111111111..1111111111...11111111.....111111...............", + "door": null + }, + "contentHash": "fnv1a:b7d83351" + }, + { + "id": "cvcojfvy6aku", + "name": "Ribbon Swan", + "category": "dynamic", + "subtype": "bird", + "width": 12, + "height": 12, + "pixels": "..............................AA.........A44A.......A4444A.....A44AA44A..AAA44AA44A.A333344444A.A33333333AA..A3333333A....A33333A......AAAAA....", + "faces": { + "right": "..............................AA.........A44A.......A4444A.....A44AA44A..AAA44AA44A.A333344444A.A33333333AA..A3333333A....A33333A......AAAAA....", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "..................11.........1111.......111111.....11111111..1111111111.11111111111.11111111111..111111111....1111111......11111................", + "door": null + }, + "contentHash": "fnv1a:679a02b3" + }, + { + "id": "fjxfboey6al0", + "name": "Lantern Beetle", + "category": "dynamic", + "subtype": "animal", + "width": 12, + "height": 12, + "pixels": "............................AAAA.......ANNNNA.....ANN11NNA....ANN11NNA...AANNAANNAA..AppNNNNppA...AppppppA....ApA..ApA...AAA....AAA..A........A.", + "faces": { + "right": "............................AAAA.......ANNNNA.....ANN11NNA....ANN11NNA...AANNAANNAA..AppNNNNppA...AppppppA....ApA..ApA...AAA....AAA..A........A.", + "left": "mirror" + }, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 5, + "y": 3, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "................1111.......111111.....11111111....11111111...1111111111..1111111111...11111111....111..111...111....111..1........1.............", + "door": null + }, + "contentHash": "fnv1a:4dc817f4" + }, + { + "id": "dvrle37y6alj", + "name": "Smile Portrait", + "category": "static", + "subtype": "building", + "width": 24, + "height": 32, + "pixels": "......................................................llllllllllll...........lAAAAAAAAAAAAl.........lAkkkkkkkkkkkkAl........lAkttttttttttkAl........lAktttcccctttkAl........lAkttccccccttkAl........lAkttccccccttkAl........lAkttcAAActttkAl........lAkttccccccttkAl........lAktttcooccttkAl........lAkoooccccoookAl........lAkooooooooookAl........lAkooooooooookAl........lAkooooooooookAl........lAkooooooooookAl........lAkoossoooosokAl........lAkossssoossskAl........lAkossssoossskAl........lAkoosssoossokAl........lAkooooooooookAl........lAkooooooooookAl........lAkooooooooookAl........lAkooooooooookAl........lAkooooooooookAl........lAkooooooooookAl........lAkooooooooookAl........lAkooooooooookAl........lAkkkkkkkkkkkkAl........lAAAAAAAAAAAAAAl.........llllllllllllll.....", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "......111111111111...........11111111111111.........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111........1111111111111111.........11111111111111.....................................................", + "door": null + }, + "contentHash": "fnv1a:fb140a94" + }, + { + "id": "6yh56c9y6amq", + "name": "Great Wave Panel", + "category": "static", + "subtype": "nature", + "width": 32, + "height": 24, + "pixels": "....llllllllllllllllllllllll.......lAAAAAAAAAAAAAAAAAAAAAAAAl.....lA777777777777777777777777Al....lA7ffffffffffffffffff77777Al....lA7fffffffffffffffff777777Al....lA7ffffffffffffff777779977Al....lA7ffffffffffff777777777kkAl....lA7ffffffffff777770007777kAl....lA7ffffffff77777000000777kAl....lA7ffffff77777000fff00077kAl....lA7ffff77777000ffffff0077kAl....lA7fff7770007fffffffff077kAl....lA77f7700007fffffffffff77kAl....lA777000007fffffffffffff7kAl....lA77000007ffffffffffffffkAl.....lA77000077ffffffffffffffkAl.....lA77700777ffffffffffffffkAl.....lA77777777ffffffffffffffkAl.....lA77kkkkk77777kkkkkkk777kAl.....lA77kkkkkkk77kkkkkkkk777kAl.....lA77kkkkkkkkkkkkkkkkk777kAl.....lA77kkkkkkkkkkkkkkkkk777kAl.....lA77777777777777777777777Al.....lAAAAAAAAAAAAAAAAAAAAAAAAAl...", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "....111111111111111111111111.......11111111111111111111111111.....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....1111111111111111111111111111....111111111111111111111111111.....111111111111111111111111111.....111111111111111111111111111.....111111111111111111111111111.....111111111111111111111111111.....111111111111111111111111111.....111111111111111111111111111.....111111111111111111111111111.....111111111111111111111111111.....111111111111111111111111111...", + "door": null + }, + "contentHash": "fnv1a:70c41074" + }, + { + "id": "gpvjlwqy6ano", + "name": "Sunflower Still Life", + "category": "static", + "subtype": "nature", + "width": 24, + "height": 32, + "pixels": "................................................................................AA..AA.................ANNAANNA...............ANNNNNNNNA...............ANNAANNA.................AA..AA....................kk.................AA..AA..AA..AA.........ANNAANNAANNAANNA.......ANNNNNNNNNNNNNNNNA.......ANNAANNAANNAANNA.........AA..AA..AA..AA................kk.................AA..AA..AA.............ANNAANNAANNA...........ANNNNNNNNNNNNA...........ANNAANNAANNA.............AA..AA..AA................kkkk....................kkkk...................AggggggA...............AggggggggA..............AggggggggA..............AggggggggA...............AggggggA.................AggggA..................AggggA.................AkkkkkkA...............AkkkkkkkkA..............AAAAAAAAAA........", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "........11..11.................11111111...............1111111111...............11111111.................11..11....................11.................11..11..11..11.........1111111111111111.......111111111111111111.......1111111111111111.........11..11..11..11................11.................11..11..11.............111111111111...........11111111111111...........111111111111.............11..11..11................1111....................1111...................11111111...............1111111111..............1111111111..............1111111111...............11111111.................111111..................111111.................11111111...............1111111111..............1111111111................................................................................", + "door": null + }, + "contentHash": "fnv1a:212abf57" + }, + { + "id": "z0bmedey6aoc", + "name": "Rosetta Stela", + "category": "static", + "subtype": "building", + "width": 24, + "height": 32, + "pixels": "................................AAAAAAAA...............AggggggggA.............AggggggggggA............AggggggggggA............AggoooggoogA............AggggggggggA............AggooggooggA............AggggggggggA............AgggoooggggA............AggggggggggA............AggooggggogA............AggggggggggA............AggoooggoogA............AggggggggggA............AggooggooggA............AggggggggggA............AgggoooggggA............AggggggggggA............AggooggggogA............AggggggggggA............AggoooggoogA............AggggggggggA............AggooggooggA............AggggggggggA............AgggoooggggA............AggggggggggA............AggggkkggggA............AggggkkggggA............AggggkkggggA.............AgggkkgggA...............AAAAAAAA........", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "........11111111...............1111111111.............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111.............1111111111...............11111111................................", + "door": null + }, + "contentHash": "fnv1a:1e1362b6" + }, + { + "id": "7ykwughy6ap4", + "name": "Pharaoh Mask", + "category": "static", + "subtype": "building", + "width": 24, + "height": 32, + "pixels": ".................................AAAAAA.................ARRRRRRA...............ARRjjjjRRA.............ARRjjjjjjRRA............ARRjccccjRRA............ARRjccccjRRA............ARRjckkcjRRA............ARRjcAAcjRRA............ARRjccccjRRA............ARRjckkcjRRA............ARRjccccjRRA............ARRjccccjRRA............ARRjckkcjRRA............ARRjccccjRRA............ARRjccccjRRA............ARRjjccjjRRA............ARRjjccjjRRA............ARRjjccjjRRA............ARRjjccjjRRA............ARRjjccjjRRA............ARRjjccjjRRA............ARRjjccjjRRA............ARRjjccjjRRA............ARRjjccjjRRA............ARRjjccjjRRA............ARRjjccjjRRA............ARRjjccjjRRA.............ARRjccjRRA...............ARRccRRA................ARRccRRA.................AAAAAA.........", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".........111111.................11111111...............1111111111.............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111............111111111111.............1111111111...............11111111................11111111.................111111.................................", + "door": null + }, + "contentHash": "fnv1a:aa991de2" + }, + { + "id": "mtd2aazy6apv", + "name": "Stone Circle", + "category": "static", + "subtype": "nature", + "width": 32, + "height": 24, + "pixels": "............................................................................AA..AA........................AAggAAggAA....................AAggggggggggAA.................AggggggggggggggA...............AggggggggggggggggA.............AgggAgggA..AgggAgggA...........AgggAggggA..AggggAgggA..........AgggAggggA..AggggAgggA..........AgggAggggA..AggggAgggA..........AgggAggggA..AggggAgggA..........AgggAggggAAAAggggAgggA..........AgggAggggggggggggAgggA..........AgggAggggggggggggAgggA...........AgggAggggggggggAgggA.............AggggggggggggggggA...............AggggggggggggggA.................AAAAAAAAAAAAAA..................cccccccccccccc.................cckkcccccccckkcc................ccccccccoocccccc................ccccccccoocccccc.................AAAAAAAAAAAAAA..........", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "............................................................................11..11........................1111111111....................11111111111111.................1111111111111111...............111111111111111111.............111111111..111111111...........1111111111..1111111111..........1111111111..1111111111..........1111111111..1111111111..........1111111111..1111111111..........1111111111111111111111..........1111111111111111111111..........1111111111111111111111...........11111111111111111111.............111111111111111111...............1111111111111111.................11111111111111..................11111111111111.................1111111111111111................1111111111111111................1111111111111111.................11111111111111..........", + "door": null + }, + "contentHash": "fnv1a:4c5c232d" + }, + { + "id": "s9oeu1ay6aql", + "name": "Terracotta Sentinel", + "category": "static", + "subtype": "building", + "width": 20, + "height": 32, + "pixels": "...........................AAAAAA.............AggggggA...........AggggggggA..........AggggggggA..........AgggoogggA..........AgggAAgggA..........AggggggggA..........AggggggggA...........AggggggA............AggggggA............AggggggA............AggggggA............AggggggA...........AggggggggA..........AgggkkgggA..........AgggkkgggA..........AgggkkgggA..........AgggkkgggA..........AgggkkgggA..........AggggggggA..........AggAAAAggA..........AgA....AgA.........AggA....AggA........AggA....AggA........AggA....AggA........AggA....AggA........AggA....AggA........AggA....AggA........AooA....AooA........AooA....AooA.........AA......AA.....", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".......111111.............11111111...........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........1111111111...........11111111............11111111............11111111............11111111............11111111...........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........111....111.........1111....1111........1111....1111........1111....1111........1111....1111........1111....1111........1111....1111........1111....1111........1111....1111.........11......11.........................", + "door": null + }, + "contentHash": "fnv1a:d073e29a" + }, + { + "id": "sby5exdy6ar8", + "name": "Rain Bell Tower", + "category": "static", + "subtype": "building", + "width": 20, + "height": 36, + "pixels": "............................AAAA...............A9999A.............A999999A............A99AA99A............AAA44AAA.............A4444A..............A4444A.............AA4444AA............A44cc44A............A44cc44A............A44cc44A............A441144A............A44cc44A...........AA444444AA..........A44cccc44A..........A44cooc44A..........A44cccc44A..........A44444444A..........A44411444A..........A444cc444A..........A444cc444A..........A444cc444A.........AA444cc444AA........A4444444444A........A444cccc444A........A444cooc444A........A444cccc444A........A4444444444A........A4444ww4444A........A4444ww4444A........A44ccwwcc44A........A44ccwwcc44A........A4444ww4444A.........AAAAwwAAAA.............AAAA........", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 9, + "y": 11, + "c": "1" + }, + { + "x": 9, + "y": 19, + "c": "1" + } + ], + "lightColor": "1", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "........1111...............111111.............11111111............11111111............11111111.............111111..............111111.............11111111............11111111............11111111............11111111............11111111............11111111...........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........1111111111..........1111111111.........111111111111........111111111111........111111111111........111111111111........111111111111........111111111111........111111111111........111111111111........111111111111........111111111111........111111111111.........1111111111.............1111............................", + "door": { + "x": 9, + "y": 33 + } + }, + "contentHash": "fnv1a:3d2b4a8d" + }, + { + "id": "z3d6hrgy6as7", + "name": "Crimson Pagoda", + "category": "static", + "subtype": "building", + "width": 24, + "height": 32, + "pixels": ".........................................................AAAAAA................AA999999AA.............A9999999999A............AAAAssAAAAAA...........AAllllllllllAA..........AsllllllllllsA.........AAssssssssssssAA........AssssssssssssssA.......AAllllllllllllllAA......Asll55llllll55llsA......AssssssssssssssssA.....AAssssssssssssssssAA....AsllllllllllllllllsA....Asll55lllAAlll55llsA....AssssssssAAssssssssA...AAssssssssssssssssssAA..AsllllllllllllllllllsA..Asll55llllllllll55llsA..AssssssssssssssssssssA..AssccccccccccccccccssA..AsscoooccooooccooocssA..AssccccccccccccccccssA..AssssssssssssssssssssA..AssssssssssssssssssssA..AssccccccccAAccccccssA..AsscoooccccAAcccoocssA..AssccccccccAAccccccssA..AssssssssssAAssssssssA..AssssssssssAAssssssssA...AAAAAAAAAAAAAAAAAAAA..", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 8, + "y": 12, + "c": "5" + }, + { + "x": 15, + "y": 12, + "c": "5" + }, + { + "x": 11, + "y": 22, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".........111111................1111111111.............111111111111............111111111111...........11111111111111..........11111111111111.........1111111111111111........1111111111111111.......111111111111111111......111111111111111111......111111111111111111.....11111111111111111111....11111111111111111111....11111111111111111111....11111111111111111111...1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111..1111111111111111111111...11111111111111111111..................................................", + "door": { + "x": 11, + "y": 28 + } + }, + "contentHash": "fnv1a:30852f2b" + }, + { + "id": "65mnzeoy6atb", + "name": "Meteor Forge", + "category": "static", + "subtype": "building", + "width": 32, + "height": 24, + "pixels": "........................................................................AAAAAAAAAAAA..................AAffffffffffffAA...............AffAAAAAAAAAAAAffA.............AAAAAAAAAAAAAAAAAAAA...........AooooooooooooooooooooA.........AAooo5555oooooo5555oooAA........Aooo555555oooo555555oooA........Aoooo55555oooo55555ooooA........AooooooooooooooooooooooA.......AAooooooooooooooooooooooAA......AooggggggggggggggggggggooA......AoogddgggddggggggddgggdgoA......AoogggggggggAAAAggggggggoA......AoogddggggggAAAAgggggddgoA......AoogggggggggAAAAggggggggoA......AooooooooooooAAooooooooooA......Aoooo55ooooooAAoooooo55ooA......AooooooooooooAAooooooooooA......AooggggggggggAAggggggggooA......AoogdddggggggAAgggggdddgoA......AooggggggggggAAggggggggooA......AAAAAAAAAAAAAAAAAAAAAAAAAA.....", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 8, + "y": 10, + "c": "9" + }, + { + "x": 23, + "y": 10, + "c": "9" + }, + { + "x": 15, + "y": 16, + "c": "9" + } + ], + "lightColor": "9", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "........................................111111111111..................1111111111111111...............111111111111111111.............11111111111111111111...........1111111111111111111111.........111111111111111111111111........111111111111111111111111........111111111111111111111111........111111111111111111111111.......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111......11111111111111111111111111.....................................", + "door": { + "x": 15, + "y": 19 + } + }, + "contentHash": "fnv1a:9e1eeec0" + }, + { + "id": "1bvcy1sy6aum", + "name": "Ink Garden Screen", + "category": "static", + "subtype": "nature", + "width": 32, + "height": 24, + "pixels": "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA444444444444444444444444444444AA4qqq4444444444444444444444qqq4AA4qqqq44444444444444444444qqqq4AA4qqqqq4444444eeee444444qqqqq4A.A4qqqqqq44444eeeeee4444qqqqqq4A.A4qqqqqqq4444eeeeee4444qqqqqq4A.A4qqqqqq44444eeeeee4444qqqqqq4A.A4qqqqq4444444eeee4444qqqqqq4A..A44444444444444444444444444444A.A4444444444444AAAA444444444444A.A444444444444AkkkkA44444444444A.A444444444444AkkkkA44444444444A.A444444444444AAAAAA44444444444A.A44444444444444444444444444444A.A4eee44444444444444444444eee44A.A4eie44444444444444444444eie44A.A4eee44444444444444444444eee44A.A44444444444444444444444444444A.A44444444444444444444444444444A.A44444444444444444444444444444A.A44444444444444444444444444444A.A44444444444444444444444444444A.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.111111111111111111111111111111..1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.1111111111111111111111111111111.11111111111111111111111111111111", + "door": null + }, + "contentHash": "fnv1a:a406b639" + }, + { + "id": "6mumquiy6avl", + "name": "Meadow Totem", + "category": "static", + "subtype": "nature", + "width": 20, + "height": 28, + "pixels": "............................AAAA...............AggggA.............AggaaggA............AggaaggA............AggAAggA............Agg55ggA............Agg55ggA............AggAAggA............AggaaggA............AggaaggA............Agg55ggA............Agg55ggA............AggAAggA............AggggggA............AggggggA............AggggggA............AggggggA............AggggggA............AggggggA............AggggggA............AggggggA............AggooggA............AggooggA............AggooggA............AggooggA.............AooooA...............AAAA........", + "faces": null, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "........1111...............111111.............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111............11111111.............111111...............1111............................", + "door": null + }, + "contentHash": "fnv1a:c59114cf" + }, + { + "id": "ttfx2j0y6aw4", + "name": "Twilight Caravan", + "category": "static", + "subtype": "ship", + "width": 32, + "height": 16, + "pixels": "...........................................AAAAAAAA.....................AAAddddddddAA.................AAddXXXXXXXXddAA...............AddXXXXXXXXXXXXddA.............AddXXXXXXXXXXXXXXddA...........AAkkkkkkkkkkkkkkkkkkAA..........Akkkk55kkkk55kkkk55kkA..........AkkkkkkkkkkkkkkkkkkkkA..........AkkcccccccccccccccckkA..........AkkckkkcckkcckkcckkckA..........AkkcccccccccccccccckkA.........AAkkkkkkkkkkkkkkkkkkkkAA........AkkkkAAkkkkAAkkkkAAkkkkA........AkkkA..AkkkA..AkkkA..AkkA.......AAAA....AAAA....AAAA..AA......", + "faces": null, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 9, + "y": 7, + "c": "5" + }, + { + "x": 15, + "y": 7, + "c": "5" + }, + { + "x": 22, + "y": 7, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "...........................................11111111.....................1111111111111.................1111111111111111...............111111111111111111.............11111111111111111111...........1111111111111111111111..........1111111111111111111111..........1111111111111111111111..........1111111111111111111111..........1111111111111111111111..........1111111111111111111111.........111111111111111111111111........111111111111111111111111........11111..11111..11111..1111.......1111....1111....1111..11......", + "door": null + }, + "contentHash": "fnv1a:d8d15418" + }, + { + "id": "bln8teny6awj", + "name": "Pepper Fox", + "category": "dynamic", + "subtype": "animal", + "width": 16, + "height": 16, + "pixels": ".......................................................AA.............AhhA...........AhhhhAA........AhhhhhhA.......AhhhhhhhhA......AhhhhAhhhA.....AhhhhhhhA1A.....Ahhhhhhh11A.....Ahhhhhh11A.......Ahhhh11A.........Ahh111AA........A111111A.........AA..AA.....", + "faces": { + "right": ".......................................................AA.............AhhA...........AhhhhAA........AhhhhhhA.......AhhhhhhhhA......AhhhhAhhhA.....AhhhhhhhA1A.....Ahhhhhhh11A.....Ahhhhhh11A.......Ahhhh11A.........Ahh111AA........A111111A.........AA..AA.....", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".......................................11.............1111...........1111111........11111111.......1111111111......1111111111.....11111111111.....11111111111.....1111111111.......11111111.........11111111........11111111.........11..11.....................", + "door": null + }, + "contentHash": "fnv1a:221bfcd2" + }, + { + "id": "7f885l2y6awr", + "name": "Glass Manta", + "category": "dynamic", + "subtype": "fish", + "width": 16, + "height": 12, + "pixels": ".......................AA............AASSAA........AASSSSSSAA.....ASSSSSSSSSSA...ASSSSSSSSSSSSA.AASSSSSSSSSSSSAA.ASSSSSSSSSSSSA...AASSSSSSSSAA......AASSSSAA..........ASSA.............AA.......", + "faces": { + "right": ".......................AA............AASSAA........AASSSSSSAA.....ASSSSSSSSSSA...ASSSSSSSSSSSSA.AASSSSSSSSSSSSAA.ASSSSSSSSSSSSA...AASSSSSSSSAA......AASSSSAA..........ASSA.............AA.......", + "left": "mirror" + }, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 7, + "y": 5, + "c": "O" + } + ], + "lightColor": "O", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".......................11............111111........1111111111.....111111111111...11111111111111.1111111111111111.11111111111111...111111111111......11111111..........1111.............11.......", + "door": null + }, + "contentHash": "fnv1a:ed8b326c" + }, + { + "id": "vuo4tnuy6ax0", + "name": "Festival Drummer", + "category": "dynamic", + "subtype": "human", + "width": 14, + "height": 16, + "pixels": "...................AAAA.........AccccA........AccccA........AAAAAA.......AAhhhhAA......AhhjjhhA......AhhjjhhA.......AjjjjA......AAAjjjjAA....AAjjAAAAjjA...AjjA.ggAjjA...AjjAAAAAjjA...AjjA....AjA...AjjA....AjA....AA......AA..", + "faces": { + "right": "...................AAAA.........AccccA........AccccA........AAAAAA.......AAhhhhAA......AhhjjhhA......AhhjjhhA.......AjjjjA......AAAjjjjAA....AAjjAAAAjjA...AjjA.ggAjjA...AjjAAAAAjjA...AjjA....AjA...AjjA....AjA....AA......AA..", + "left": "mirror" + }, + "meta": { + "hasLight": false, + "lightPixels": [], + "lightColor": null, + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": ".....1111.........111111........111111........111111.......11111111......11111111......11111111.......111111......111111111....11111111111...1111.111111...11111111111...1111....111...1111....111....11......11................", + "door": null + }, + "contentHash": "fnv1a:5cc2b1fb" + }, + { + "id": "hnlnlzwy6ax7", + "name": "Bloom Sprite", + "category": "dynamic", + "subtype": "animal", + "width": 12, + "height": 12, + "pixels": "........................................AAAA.......A5555A.....A55QQ55A....A55QQ55A...AA555555AA..Aee5555eeA...AeeeeeeA....AeA..AeA...AA....AAA..", + "faces": { + "right": "........................................AAAA.......A5555A.....A55QQ55A....A55QQ55A...AA555555AA..Aee5555eeA...AeeeeeeA....AeA..AeA...AA....AAA..", + "left": "mirror" + }, + "meta": { + "hasLight": true, + "lightPixels": [ + { + "x": 5, + "y": 3, + "c": "5" + } + ], + "lightColor": "5", + "hasParticles": false, + "particlePixels": [], + "particleConfig": { + "enabled": false, + "c": "0", + "dir": "up" + }, + "depthPixels": "................1111.......111111.....11111111....11111111...1111111111..1111111111...11111111....111..111...11....111..........................", + "door": null + }, + "contentHash": "fnv1a:92282a25" + } +] \ No newline at end of file diff --git a/default_assets_sheet.png b/default_assets_sheet.png new file mode 100644 index 0000000..1edf6fd Binary files /dev/null and b/default_assets_sheet.png differ diff --git a/extract_assets.js b/extract_assets.js new file mode 100644 index 0000000..8b82082 --- /dev/null +++ b/extract_assets.js @@ -0,0 +1,24 @@ +const fs = require('fs'); +const vm = require('vm'); +const path = require('path'); +let code = fs.readFileSync(path.join(__dirname, 'app.js'), 'utf8'); +code = code.replace(/\n\s*bootstrap\(\);\s*\n\}\)\(\);\s*$/, `\n window.__PIXEL_DEBUG__ = { state, buildDefaultGalleryPack, PALETTE, PALETTE_BY_CODE, assetWidth, assetHeight };\n})();`); +function makeCtx(){ + const noop=()=>{}; + return new Proxy({imageSmoothingEnabled:false, canvas:{width:1,height:1}}, {get(t,p){ + if(p in t) return t[p]; + if(p==='measureText') return () => ({width:0}); + return noop; + }, set(t,p,v){ t[p]=v; return true; }}); +} +function makeEl(id){ return new Proxy({ id, width:640, height:480, style:{}, classList:{add(){},remove(){},toggle(){},contains(){return false;}}, dataset:{}, value:'', checked:false, textContent:'', innerHTML:'', append(){}, appendChild(){}, addEventListener(){}, removeEventListener(){}, setAttribute(){}, removeAttribute(){}, focus(){}, blur(){}, getBoundingClientRect(){return {left:0,top:0,width:640,height:480};}, getContext(){return makeCtx();}, querySelector(){return makeEl('q');}, querySelectorAll(){return [];}}, {get(t,p){ if(p in t) return t[p]; if(p==='children') return []; return undefined; }, set(t,p,v){ t[p]=v; return true; }}); } +const localStorage = { getItem(){return null;}, setItem(){}, removeItem(){} }; +const sandbox = { console, window: {}, document: { getElementById: makeEl, createElement: makeEl, querySelector(){return makeEl('q')}, querySelectorAll(){return []}, addEventListener(){}, body: makeEl('body')}, localStorage, performance: { now: () => 0 }, Math, Date, Map, Set, Array, Object, JSON, Number, String, Boolean, RegExp, Error, Uint8Array, Int8Array, Uint16Array, URL: {createObjectURL(){return ''}, revokeObjectURL(){}}, Blob: function(){}, Image: function(){}, FileReader: function(){}, requestAnimationFrame(){}, cancelAnimationFrame(){}, setTimeout, clearTimeout, structuredClone: global.structuredClone }; +sandbox.window = Object.assign(sandbox.window, { PixelIslandModules:{}, devicePixelRatio:1, addEventListener(){}, removeEventListener(){}, matchMedia(){return {matches:false, addEventListener(){}, removeEventListener(){}}}, requestAnimationFrame(){}, cancelAnimationFrame(){}, document: sandbox.document, localStorage: sandbox.localStorage }); +vm.createContext(sandbox); +vm.runInContext(code, sandbox, {filename:'app.js'}); +const debug = sandbox.window.__PIXEL_DEBUG__; +const assets = debug.state.assets.map(a => ({id:a.id,name:a.name,category:a.category,subtype:a.subtype,width:a.width,height:a.height,pixels:a.pixels,faces:a.faces,meta:a.meta,contentHash:a.contentHash})); +fs.writeFileSync(path.join(__dirname,'assets.json'), JSON.stringify(assets,null,2)); +console.log('assets', assets.length); +console.log(assets.map(a=>`${a.name} ${a.width}x${a.height} ${a.category}/${a.subtype}`).join('\n'));