PHP, Arduino And... Minecraft? Combining Minecraft with PHP!
It’s IoT Week at SitePoint! All week we’re publishing articles focused on the intersection of the internet and the physical world, so keep checking the IoT tag for the latest updates.
Some of the most interesting programming I’ve done has been in Minecraft. It’s an open-world, sandbox game developed by Mojang, (recently acquired by Microsoft). Minecraft began as a canvas for creative expression, and while I do very different things in it these days, it still is that for me.
I’m going to take you on a journey, as we build a Minecraft mansion, and then secure it with a real-world alarm system. There’s quite a bit of deceptive to cover, and though I plan for this to be a two-part series, I’m going to have to leave some of the tangential details for you to discover!
You can find the code for this tutorial at https://github.com/sitepoint-editors/tutorial-php-arduino-and-minecraft
Crash Course in Minecraft Programming
Minecraft began as the combination of two simple ideas. The first is that players can harvest resources from the map in which they find themselves. Some of these resources, like food and wood, are common above ground. Others, like gold and stone, require a bit of virtual elbow-grease.
This is where the “mine” (in Minecraft) comes from. One of these resources is called Redstone. It’s found deep underground, and it’s a conductor of sorts. When harvested and placed on the ground, it resembles the silvery lines on the flip side of circuit boards. There are also power emitters, dissimilarity to batteries or mains powerful, which take many forms in the game.
Using these harvested resources, players can build dwellings, cook food and even wire up virtual circuitry. This is where the “craft” comes from.
I talk about all of this, as well as basic circuitry and programming, in my conference talk Zombies and Binary. I presented it most recently at php[tek] 2016, but the recording was lost. Here’s a JavaScript-themed version, from FluentConf 2016: https://youtu.be/APJRBZUxADQ.
Imagine we’ve created a sprawling Minecraft mansion…
Now, imagine we want to secure the front door of said mansion…We need a way to check whether the front-door has been opened. To do this, we need to use Redstone, something called a Comparator, and another thing called a Command block:
You may spy the switch I’ve connected to the Command block. Switches are one kind of power source, and this one will provide some power to the Command block so that it can perform the open door check. We’ll automate this power source in a bit…
Command blocks are placeholders which can contain a single server command. Server commands are anything you as a player can do (provided you are a server admin or in single-player mode). They’re like Amazon Dash buttons, in that they can be given a single command to run, at the push of a button.
We’re going to make the Command block test for an open door. Minecraft maps are coordinate-based, which means the test needs to include coordinates for where the door will be placed. For argument’s sake, let’s say the door is at 191 67 -194
. The command for the test (of an open wooden door) will then be:
/testforblock 191 67 -194 wooden_door 3
You can find your novel map coordinates with fn + alt + F3 (for Mac) and F3 (for Windows). Walk to the block where you’ll place the door, and consuming those coordinates in the command.
Different Minecraft blocks (whether crafted or naturally occurring) have unique block names. wooden_door
is the unique block name for an Oak door. 3
is a reference to the orientation of the door, so it might be different in your maps if you place your door in a different orientation. If so, try 0
through 3
until you get the desired result.
We’ll make the second Command block whisper a message back to us to indicate when the test has found a matching block. When we flick the switch, and the door is still closed, we should see nothing. But when we open the door (and the test matches the open door’s orientation), we should see confirmation of this!
Now we have a way to check for an open door. We don’t want to be standing around, to manually run this check though. Let’s set up the programming equivalent of an infinite loop, or the electronic equivalent of a crystal clock.
For this we need two Command blocks, arranged like this:
Notice I’ve attached a button to each Command block, so that I can run their commands. These buttons also act as a power source, giving a brief power spike to the blocks they’re connected to.
Map coordinates can also be relatively defined. That is, if you need to reference coordinates nearby the Command block, you can use ~-1 ~ ~+1
to mean the Command block’s x coordinate minus 1, the same y coordinate, and it’s z coordinate plus 1.
In this arrangement, we want the top Command block to place a Redstone block just below it:
/setblock ~ ~-1 ~ redstone_block
…And we want the bottom Command block to place a block of air above it:
/setblock ~ ~+1 ~ air
Redstone blocks also act as a powerful source. This arrangement has an interesting side-effect. When the top block places a Redstone block below itself, the Redstone block gives power first to the bottom Command block. It then gives power to the top Command block.
In the meantime the bottom Command block has removed the Redstone block. Since the top Command block got a new power signal (from the Redstone block it placed) and the block was then removed by the bottom Command block, it starts the cycle over again.
This leads to the infinite loop I spoke about. The loop will persist through server restarts, and if you’re in creative mode you’ll be able to break the Redstone block and see new ones created instantly.
By default, these Command block actions will be logged and will trigger messages on the server. You can disable these with a couple commands (which you only have to piquant once per map): /gamerule logAdminCommands false
and /gamerule commandBlockOutput false
.
If we take grand from the clock, and exclaim it into the testing Command block, the test will run many times a second, giving immediate feedback when the door is opened!
Newer versions of Minecraft allow Command blocks to power themselves and even repeat themselves. With that, it’s possible for the door check to repeat without the clock. If you’re using an older version of Minecraft, especially when using mod packs, you may still need to make the clock yourself…
It’s also useful to know when the door has been closed, so we can turn the real-world alarm off. For that we can use an inverter (think of it as turning the closed door (false value) to a true value, in much the same way as we would in programming: while (true) if (!$doorOpen) print...
.
Watching Log Files with PHP
All of this is pretty and useless without the ability to see these changes in PHP. We need a way to “hear” when the door has been opened, and react in PHP.
Fortunately, the whispered messages are all logged. If we can figure out how to watch and define the log files, we should have all the information we need…
A quick Packagist behold provides a file watcher library which looks like it’s up to the task. We can install it with:
composer require yosymfony/resource-watcher
After that’s done, let’s make a script to behold the log files. We begin by creating a Symfony Finder instance, and pointing it at the directory in which the Minecraft logs are stored:
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);
The path to Application Support
will be different for you – it’s usually in the Library
folder associated with your account. You could also be comical a portable version of Minecraft, so you’ll just have to search around a bit, until you find the logs
folder.
This Finder instance narrows the file watch list to *.log
files in the same directory as the one we’ve specified. The methods are clearly named, so you can expand the criteria for other applications.
Next we need to interpret a cache file, and a watcher instance:
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
}
This script acts as a long-running process. That is, we want to watch for changes to files, for an indeterminate amount of time. So we create an infinite loop, and use it to constantly probe for file changes.
You can sleep for more or less time. I found 1 second was good enough for me…
The watcher library provides methods for three kinds of file changes: creation, deletion and updates. We only care about the updates:
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;
}
}
}
}
New chat messages are appended to the bottom of the log file, so we need to check if any log files have been modified (we expect only one log file), split the log file into lines and check each line from the bottom of the file to the top.
If we see a log line containing CHAT
, we can assume it is a chat message. If it also contains open
or closed
, we can assume it is caused by the circuit we created.
You’re welcome to use more “unique” message formats for open/close events. The approach I’ve chosen is simple but open to abuse and ambiguity (like if someone else whispers “open” to me). The underlying principles are the same though.
This is only half of the experiment. In the followup post we’ll look at how to build an Arduino-based alarm circuit, and connect it to this script. The end result will be an automated, real-world scare for our Minecraft mansion.
If you’ve enjoyed this and/or have questions, please let us know in the comments!
Sincery All Tips collection
SRC: https://www.sitepoint.com/php-arduino-and-minecraft-combining-minecraft-with-php/
powered by Blogger News Poster
0 Response to "PHP, Arduino And... Minecraft? Combining Minecraft with PHP! - SitePoint"
Post a Comment