Статьи

PHP, Arduino и … Minecraft? Объединяя Майнкрафт с PHP!

IoTWeek_Gray

Это неделя Интернета вещей в SitePoint! Всю неделю мы публикуем статьи, ориентированные на пересечение интернета и физического мира, поэтому следите за последними обновлениями в теге IoT .

Некоторые из самых интересных программ, которые я делал, были в Minecraft . Это игра-песочница с открытым миром, разработанная Mojang (недавно приобретенная Microsoft). Minecraft начинался как холст для творческого самовыражения, и хотя я делаю в нем совсем другие вещи в наши дни, это все еще для меня.

Я отправлю вас в путешествие, когда мы построим особняк Minecraft, а затем обеспечим его реальной системой сигнализации. Здесь есть немало оснований, и хотя я планирую сделать это серией из двух частей, мне придется оставить некоторые тангенциальные детали, чтобы вы могли их обнаружить!

Вы можете найти код для этого учебника по адресу https://github.com/sitepoint-editors/tutorial-php-arduino-and-minecraft

Ускоренный курс по программированию Minecraft

Minecraft начался как комбинация двух простых идей. Во-первых, игроки могут собирать ресурсы с карты, на которой они находятся. Некоторые из этих ресурсов, такие как еда и древесина, распространены над землей. Другие, такие как золото и камень, требуют немного виртуальной смазки для локтей.

Отсюда и «шахта» (в Minecraft). Один из этих ресурсов называется Redstone. Он найден глубоко под землей, и это своего рода проводник. Собранный и размещенный на земле, он напоминает серебристые линии на оборотной стороне монтажных плат. Существуют также источники энергии, похожие на батареи или сетевое питание, которые принимают различные формы в игре.

Скриншот Redstone в игре

Используя эти собранные ресурсы, игроки могут строить жилища, готовить еду и даже подключать виртуальные схемы. Отсюда и происходит «ремесло».

Я рассказываю обо всем этом, а также об основных схемах и программировании, в своей конференции «Зомби и двоичные файлы». Я представил его совсем недавно на php [tek] 2016, но запись была потеряна. Вот версия на тему JavaScript от FluentConf 2016: https://youtu.be/APJRBZUxADQ .

Представьте, что мы создали особняк Майнкрафт …

Скриншот особняка в игре

А теперь представьте, что мы хотим защитить входную дверь указанного особняка … Нам нужен способ проверить, открыта ли входная дверь. Для этого нам нужно использовать Redstone, который называется Comparator, и еще один объект, называемый блоком Command:

Внутриигровой скриншот тестирования для блока

Вы можете заметить переключатель, который я подключил к командному блоку. Переключатели являются одним из видов источника питания, и этот будет обеспечивать некоторое питание для командного блока, чтобы он мог выполнять проверку открытых дверей. Мы немного автоматизируем этот источник питания …

Блоки команд — это заполнители, которые могут содержать одну серверную команду. Команды сервера — это все, что вы, как игрок, можете делать (при условии, что вы являетесь администратором сервера или в режиме одиночной игры). Они похожи на кнопки Amazon Dash в том смысле , что им можно дать одну команду для запуска одним нажатием кнопки.

Мы собираемся сделать тестовый блок для открытой двери. Карты Minecraft основаны на координатах, что означает, что тест должен включать координаты места, где будет расположена дверь. Ради аргумента, скажем, дверь в 191 67 -194 . Команда для теста (открытой деревянной двери) будет тогда:

 /testforblock 191 67 -194 wooden_door 3 

Вы можете найти свои текущие координаты карты с помощью клавиш fn + alt + F3 (для Mac) и F3 (для Windows). Идите к блоку, где вы разместите дверь, и введите эти координаты в команде.

Различные блоки Minecraft (как созданные, так и встречающиеся в природе) имеют уникальные названия блоков. wooden_door — это уникальное имя блока для дубовой двери. 3 является ссылкой на ориентацию двери, поэтому она может отличаться на ваших картах, если вы расположите дверь в другой ориентации. Если это так, попробуйте от 0 до 3 пока не получите желаемый результат.

Мы заставим второй блок Command шептать нам сообщение, чтобы указать, когда тест обнаружил соответствующий блок. Когда мы щелкаем выключателем, а дверь все еще закрыта, мы ничего не видим. Но когда мы открываем дверь (и тест соответствует ориентации открытой двери), мы должны увидеть подтверждение этому!

Внутриигровое движущееся изображение тестирования для блока

Теперь у нас есть способ проверить наличие открытой двери. Мы не хотим стоять, чтобы вручную запустить эту проверку, хотя. Давайте настроим программный эквивалент бесконечного цикла или электронный эквивалент кристаллических часов.

Для этого нам понадобятся два командных блока, расположенных следующим образом:

Скриншот часов в игре

Обратите внимание, что я прикрепил кнопку к каждому блоку команд, чтобы я мог запускать их команды. Эти кнопки также служат источником питания, давая краткий импульс мощности для блоков, к которым они подключены.

Координаты карты также могут быть относительно определены. То есть, если вам нужно ссылаться на координаты рядом с командным блоком, вы можете использовать ~-1 ~ ~+1 для обозначения координаты x командного блока минус 1, той же координаты y и его координаты z плюс 1.

В этом расположении мы хотим, чтобы верхний блок Command размещал блок Redstone чуть ниже него:

 /setblock ~ ~-1 ~ redstone_block 

… И мы хотим, чтобы нижний командный блок поместил над ним воздушный блок:

 /setblock ~ ~+1 ~ air 

Редстоун блоки также выступают в качестве источника энергии. У этой договоренности есть интересный побочный эффект. Когда верхний блок помещает блок Редстоуна под собой, блок Редстоуна сначала подает питание нижнему блоку команд. Затем он подает питание на верхний командный блок.

Тем временем нижний блок Command удалил блок Redstone. Поскольку верхний командный блок получил новый сигнал питания (из размещенного им блока Редстоуна), а затем блок был удален нижним командным блоком, цикл начинается снова.

Это приводит к бесконечному циклу, о котором я говорил. Цикл будет сохраняться до перезапуска сервера, и если вы находитесь в творческом режиме, вы сможете разорвать блок Redstone и увидеть новые, созданные мгновенно.

В игре анимированное изображение рабочих часов

По умолчанию эти действия блока команд будут регистрироваться и вызывать сообщения на сервере. Вы можете отключить их с помощью пары команд (которые вы должны вводить только один раз для каждой карты): /gamerule logAdminCommands false и /gamerule commandBlockOutput false .

Если мы возьмем питание от часов и направим его в блок команд тестирования, тест будет выполняться много раз в секунду, давая немедленную обратную связь при открытии двери!

Новые версии Minecraft позволяют командным блокам приводить себя в действие и даже повторяться. При этом проверка двери может повториться без часов. Если вы используете более старую версию Minecraft, особенно при использовании мод-пакетов, вам все равно может понадобиться сделать часы самостоятельно …

Внутриигровая анимация работы двери, открытия и закрытия

Также полезно знать, когда дверь была закрыта, чтобы мы могли выключить реальную тревогу. Для этого мы можем использовать инвертор (представьте, что он превращает закрытую дверь (ложное значение) в истинное значение, почти так же, как мы это делаем в программировании: while (true) if (!$doorOpen) print... ,

Скриншот инвертора в игре

Просмотр лог файлов с PHP

Все это красиво и бесполезно без возможности увидеть эти изменения в PHP. Нам нужен способ «услышать», когда дверь открыта, и реагировать на PHP.

К счастью, все шепотные сообщения регистрируются. Если мы сможем понять, как просматривать и интерпретировать файлы журнала, у нас должна быть вся необходимая информация…

Быстрый поиск Packagist предоставляет библиотеку наблюдателя файлов, которая выглядит так, как будто она соответствует задаче. Мы можем установить его с:

 composer require yosymfony/resource-watcher 

После того, как это будет сделано, давайте создадим скрипт для просмотра файлов журнала. Мы начнем с создания экземпляра Symfony Finder и наведения его на каталог, в котором хранятся журналы Minecraft:

 require __DIR__ . "/vendor/autoload.php"; use Symfony\Component\Finder\Finder; $path = "/path/to/Application Support/minecraft/logs"; $finder = new Finder(); $finder->files() ->name("*.log") ->depth(0) ->in($path); . require __DIR__ . "/vendor/autoload.php"; use Symfony\Component\Finder\Finder; $path = "/path/to/Application Support/minecraft/logs"; $finder = new Finder(); $finder->files() ->name("*.log") ->depth(0) ->in($path); 

Путь к Application Support для вас будет другим — обычно он находится в папке « Library », связанной с вашей учетной записью. Вы также можете использовать переносную версию Minecraft, так что вам просто нужно немного поискать, пока не найдете папку logs .

Этот экземпляр Finder сужает список отслеживания файлов до файлов *.log в том же каталоге, что и указанный нами. Методы имеют четкое название, поэтому вы можете расширить критерии для других приложений.

Далее нам нужно определить файл кеша и экземпляр наблюдателя:

 use Yosymfony\ResourceWatcher\ResourceCacheFile; use Yosymfony\ResourceWatcher\ResourceWatcher; $cache = new ResourceCacheFile(__DIR__ . "/cache.php"); $watcher = new ResourceWatcher($cache); $watcher->setFinder($finder); while(true) { sleep(1); $watcher->findChanges(); // ...respond to changes } 

Этот сценарий действует как длительный процесс. То есть мы хотим следить за изменениями в файлах в течение неопределенного периода времени. Поэтому мы создаем бесконечный цикл и используем его для постоянного поиска изменений файла.

Вы можете спать больше или меньше времени. Я нашел, что 1 секунда была достаточно хороша для меня …

Библиотека наблюдателя предоставляет методы для трех видов изменений файла: создание, удаление и обновление. Мы заботимся только об обновлениях:

 while(true) { sleep(1); $watcher->findChanges(); // ...respond to changes $changes = $watcher->getUpdatedResources(); if (count($changes) > 0) { $first = $changes[0]; $lines = file($first); for ($i = count($lines) - 1; $i > -1; $i--) { if (stristr($lines[$i], "CHAT")) { if (stristr($lines[$i], "closed")) { print "closed!"; } if (stristr($lines[$i], "open")) { print "open!"; } break; } } } } 

Новые сообщения чата добавляются в конец файла журнала, поэтому нам нужно проверить, были ли изменены какие-либо файлы журнала (мы ожидаем, что только один файл журнала), разбить файл журнала на строки и проверить каждую строку в нижней части файла. наверх

Если мы видим строку журнала, содержащую CHAT , мы можем предположить, что это сообщение чата. Если он также содержит open или closed , мы можем предположить, что это вызвано созданной нами цепью.

Анимированное изображение PHP и Minecraft, работающих вместе

Вы можете использовать более «уникальные» форматы сообщений для открытия / закрытия событий. Подход, который я выбрал, прост, но открыт для злоупотреблений и двусмысленности (например, если кто-то шепчет мне «открыто»). Основополагающие принципы одинаковы, хотя.

Это только половина эксперимента. В последующем посте мы рассмотрим, как построить схему сигнализации на основе Arduino, и подключим ее к этому сценарию. Конечным результатом будет автоматическая, реальная сигнализация для нашего особняка Minecraft.

Если вам понравилось и / или у вас есть вопросы, пожалуйста, сообщите нам об этом в комментариях!