Разработка системы виртуальных земельных участков (virtual land)

Встречали проекты, где виртуальная земля продаётся как NFT, а потом никто не знает, что с ней делать? Без продуманной архитектуры координатной системы, гибкой системы прав и экономики с дефицитом карта остаётся пустой. Мы разработали десятки таких систем — от простых 2D гридов до полноценных 3D миро

Направления блокчейн-разработки

Часто задаваемые вопросы

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1441
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    998
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1267
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    713
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    1003

Встречали проекты, где виртуальная земля продаётся как NFT, а потом никто не знает, что с ней делать? Без продуманной архитектуры координатной системы, гибкой системы прав и экономики с дефицитом карта остаётся пустой. Мы разработали десятки таких систем — от простых 2D гридов до полноценных 3D миров. Закажите разработку virtual land под ключ — от смарт-контрактов до клиентского рендеринга.

Основные проблемы: как хранить координаты в смарт-контрактах без безумных газ-трат? Как объединять участки в Estate с проверкой смежности? Как дать владельцам права настройки своей земли? Ниже разберём каждую из проблем с кодом и цифрами.

Координатная система и хранение

Земля обычно представлена как 2D Grid — целочисленные координаты (x, y). Каждый участок — уникальный NFT с координатами как ключевым атрибутом. Упаковка координат в tokenId (x: int16, y: int16 → uint32) ограничивает мир, но снижает газ.

contract VirtualLand is ERC721 { struct LandInfo { int16 x; int16 y; address owner; bool developed; uint32 districtId; } mapping(uint256 => LandInfo) public lands; mapping(bytes32 => uint256) public coordsToTokenId; function _coordsToId(int16 x, int16 y) internal pure returns (uint256) { return uint256(uint32(uint16(int16(x))) | (uint32(uint16(int16(y))) << 16)); } function _hashCoords(int16 x, int16 y) internal pure returns (bytes32) { return keccak256(abi.encodePacked(x, y)); } function mint(int16 x, int16 y, address to) external onlyMinter { bytes32 coordHash = _hashCoords(x, y); require(coordsToTokenId[coordHash] == 0, "Land already exists"); uint256 tokenId = _coordsToId(x, y); _safeMint(to, tokenId); lands[tokenId] = LandInfo({x: x, y: y, owner: to, developed: false, districtId: _getDistrictId(x, y)}); coordsToTokenId[coordHash] = tokenId; } } 

Estate: объединение участков

Estate — несколько соседних участков, объединённых в один NFT. Упрощает управление большим пространством. Проверка смежности on-chain — дорогая для крупных объединений, поэтому для estates до 20–30 участков используется O(n²) алгоритм, а для больших — off-chain с Merkle proof или ZK proof.

Детали проверки смежностиДля on-chain проверки можно использовать алгоритм поиска в глубину (DFS), ограниченный по газу. Примерный лимит — 2000 единиц на участок. Off-chain с Merkle proof дешевле в 10 раз.

Как проверить смежность участков on‑chain?

Проверка того, что набор участков образует связный граф, — дорогая on-chain операция. Оптимизация: проверять, что каждый участок имеет хотя бы одного соседа в множестве. Это не полная связность, но достаточно для Estate. On-chain проверка в 10 раз дороже, чем off-chain с ZK proof, поэтому для крупных объединений используйте off-chain.

Система прав и операторов

Владелец участка должен контролировать, кто может строить на его земле. Реализуем через bitmap прав: BUILD, SCRIPT, ADMIN.

uint8 public constant RIGHT_BUILD = 1 << 0; uint8 public constant RIGHT_SCRIPT = 1 << 1; uint8 public constant RIGHT_ADMIN = 1 << 3; mapping(uint256 => mapping(address => uint8)) public landOperators; function grantRights(uint256 landId, address operator, uint8 rights) external { require(ownerOf(landId) == msg.sender, "Not owner"); landOperators[landId][operator] |= rights; } function hasRight(uint256 landId, address operator, uint8 right) public view returns (bool) { return ownerOf(landId) == operator || (landOperators[landId][operator] & right) != 0; } 

Экономика виртуальной земли

District — административная единица, объединяющая участки. Может иметь свой governance и общий доход. Adjacency bonus — участки рядом с landmarks (центр города) дороже. Реализуется через хранение landmark-координат и расчёт расстояния. Например, для каждого соседнего участка проверяется наличие landmark и присваивается бонус. Такая механика создаёт ажиотаж на primary sale, но без контента земля бесполезна. Наш опыт показывает: сначала first-party контент, потом сценарии использования.

Marketplace и торговля

Встроенный marketplace с EIP-2981 роялти позволяет торговать участками. Газ-эффективная реализация с проверкой авторских прав.

struct Listing { uint256 tokenId; uint256 price; address seller; uint256 expiresAt; } mapping(uint256 => Listing) public listings; function buy(uint256 tokenId) external payable { Listing memory listing = listings[tokenId]; require(block.timestamp <= listing.expiresAt, "Listing expired"); require(msg.value >= listing.price, "Insufficient payment"); delete listings[tokenId]; (address royaltyReceiver, uint256 royaltyAmount) = royaltyInfo(tokenId, listing.price); uint256 sellerProceeds = listing.price - royaltyAmount - (listing.price * PLATFORM_FEE / 10000); payable(royaltyReceiver).transfer(royaltyAmount); payable(PLATFORM_TREASURY).transfer(listing.price * PLATFORM_FEE / 10000); payable(listing.seller).transfer(sellerProceeds); _safeTransfer(listing.seller, msg.sender, tokenId, ""); } 

Что входит в работу над проектом?

  • Аудит и оптимизация смарт-контрактов (экономия на gas до 30%).
  • Полная документация и тесты (Foundry/Hardhat).
  • Интеграция с The Graph или кастомным индексером.
  • Передача доступа к контрактам, IPFS и CDN.
  • Обучение команды заказчика работе с системой.
  • Техническая поддержка на этапе запуска.

Рендеринг карты: 2D vs 3D

Подход Технология Производительность Сложность
2D top-down React + Pixi.js/Konva.js Высокая (viewport culling) Средняя
3D world Three.js/Babylon.js Средняя (LOD, streaming) Высокая

Для первой версии достаточно 2D карты. 3D рендеринг — отдельная итерация, требующая CDN для сцен и системы LOD.

Индексирование данных

On-chain данные неэффективно читать напрямую. Используйте индексер: The Graph или кастомный с PostGIS.

type Land @entity { id: ID! x: Int! y: Int! owner: Bytes! districtId: Int content: LandContent listings: [Listing!]! @derivedFrom(field: "land") transactions: [Transfer!]! @derivedFrom(field: "land") } 

Стек технологий

Компонент Технология
Land NFT контракт ERC-721 + Solidity
Estate контракт ERC-721 + adjacency logic
Marketplace Solidity (кастомный или Seaport)
Индексер The Graph / кастомный + PostGIS
2D карта React + Pixi.js / Konva.js
3D рендеринг Three.js / Babylon.js
Content storage IPFS + Pinata / Arweave
Сеть Polygon / Immutable zkEVM

Сроки и бюджет

MVP (Land NFT, базовый marketplace, 2D карта, загрузка контента) — 2–3 месяца. Полная система с Estate, Districts, 3D рендерингом, системой прав, индексером — 5–7 месяцев. 3D world engine — отдельный проект, 6–12 месяцев. Каждый проект оценивается индивидуально — получите консультацию. Гарантируем безопасность контрактов (аудит обязателен) и опыт в подобных проектах. Команда имеет 7+ лет опыта и 30+ законченных NFT-проектов — оценим ваш проект за 1 день. Свяжитесь с нами, чтобы обсудить детали.