By using a combination of HTML, Javascript, Lua, and a simple templating engine (built into the HTTP library), you'll be able to create small apps that serve dynamic content, allowing you to do damn-near anything you want, such as:
- View information about the current status of your system, the bot, activity/status logs, screenshots, see a live-updated map of where your character, enemies, and other players are, or any other piece of data you can pull in for display
- Make configuration changes on-the-fly; no need to restart the scripts to add new skills
- Assign the bot to a new task, such as repairing equipment, selling garbage, move to a new area, etc.
- Send commands to be processed by the bot without pausing, such as sending a chat message, take a screenshot, or anything else you can imagine
- Upload new configuration files, addons, or other data to be immediately inserted into the bot during run-time
Setting up your script to create an HTTPD server:
Step one, you'll need the latest version of MicroMacro, 1.94. A huge amount of debugging was required to weed out all the problems with sockets and so this update is required (otherwise you're going to have a bad time).
Once you've got that installed, create your script folder (I threw my demo into a folder named 'web', which you can download below). Create a 'main.lua' file with this in it:
Code: Select all
require('httpd/httpd');
function macro.init()
httpd = Httpd();
end
function macro.main()
return true;
end
function macro.event(e, ...)
httpd:handleEvent(e, ...);
end
Configuring IP port binds:
In order to make the HTTPD more accessible from outside of this machine, you need to bind to an IP that will accept connections from those. The simplest way to do that is to bind to port 0.0.0.0, which essentially just means "Accept any incoming connection regardless of its origin." We will also bind to port 80, the default web-page port.
To do that, we simply pass a table with our configuration details to the constructor during instantiation of our server.
Code: Select all
function macro.init()
local config = {
ip = "0.0.0.0",
port = 80,
};
httpd = Httpd(config);
end
Setting routes and controllers
Create a filer named 'routes.lua' in your script's main folder. That is, it should be right along-side your 'main.lua' file. Open it up and pop this line in it:
Code: Select all
Route:controller('/', 'HomeController');
The first string can be any URI-acceptable string that you want to listen to, and the second string is the name of the controller to pass the load off to for handling, and must correspond to both the filename and object name of the controller. You may place as many routes as you would like in your route file; each call to Route:controller() will bind a URI to a controller.
Now, create 3 more folders: 'Controllers', 'Static', and 'Views'.
Controllers is where you're going to put your controllers; objects that have the job of returning the data that the client (viewer) is requesting to access off the server.
Static is where you put static content, such as CSS, Javascript, images, and so on.
Views is the place to put view files, which are template chunks used when you want to display a webpage to the user.
The name/locations of these folders can be changed in the config table to passed to the Httpd, just the same as the IP/port can. Use variables 'controllerDir', 'viewDir', and 'staticDir' for that purpose.
A note about routes.lua and controllers: These are loaded dynamically, meaning you do not need to restart the script every time you change the routes.lua file or any controller file. The same goes for views; any changes you make go live the instant you save the file.
Serving content:
In our Controllers folder, create a new file named HomeController.lua and in it place this:
Code: Select all
HomeController = class.new();
function HomeController:getIndex(request)
return View:make('home');
end
Remember earlier how we bound '/' to HomeController? That means that any access of the web-GUI homepage ('/' or '/index') will be sent to HomeController for processing. Since no other function was specified in the URI, it defaults to calling the appropriate index function. Attempting to view a webpage is typically done with a GET method (as opposed to POST, which is designed for forms and uploading data). As such, the final destination of accessing http://127.0.0.1 is going to be HomeController's getIndex() function. If we accessed http://127.0.0.1/index/somethingelse we would instead route to HomeController's getSomethingelse() function. A hyphenated 2nd URI segment will be translated to camel-case, such as http://127.0.0.1/index/something-else mapping to HomeController's getSomethingElse().
Essentially it boils down to this: http://<your ip>/controller/function/extra-uri-segment1/extra-uri-segment2/.../extra-uri-segmentn
Anyways, enough of the specifics. Lets get back on-topic here. The only thing that getIndex() does is build and return a view as text/HTML to be delivers to the client since we told the View object to make the home view. So, create home.view.lua in your Views folder. Yes, it must have the format of <name>.view.lua!
We can just pop the text "Hello World!" into it and save it for now. If we try to load up http://127.0.0.1 we should see a fairly lame blank, white page with that written on it. At least that means everything is working so far.
Templating and views:
It's time to make our view look bad-ass! The cleanest/easiest way to accomplish this is by using a template. This boils down to dumping a bunch of HTML into a view file (such as template.view.lua, though you can name it anything as long as it has the .view.lua extension), and telling our view to extend on that template. If the first line of your view contains the @extends directive, it'll load the template and pop our 'sections' of our view into it.
Our template should look something like (excluding tons of HTML):
Code: Select all
<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
@section('content')
</body>
</html>
Code: Select all
@extends('template')
@beginsection('content')
Hello World!
@endsection
There's a number of other templating directives, too, which we will use to display our content:
@include('otherview') Allows us to load another view and insert it here; handle to just separate out chunks of code that you might like to include in various places
@foreach(variable as index,value){ content here } Will act much like Lua's for i,v in pairs(); this lets us loop over a Lua variable and display some content for each row in the table
@for(variable = startCount,endCount){ content here } Simple forloop that sets the given variable to a number that will increment starting at 'startCount' and ending at 'endCount'. So, index = 1,10 will repeat 10 times with variable being set to 1, 2, 3, ..., up to 10.
@if(...){ ... } else { ... } Is exactly like any other if/else statement; displays contents based on which condition is true
@if(...){ ... } Pretty self explanatory, only display the content if some condition is true
{{# statement #}} This will NOT display anything, but runs the statement as code; useful for setting variables you might want to see later. See regular {{ ... }} for more
{{! statement !}} This will display the un-escaped output of the statement; useful only if the string you want to display includes HTML content. See regular {{ ... }} for more
{{ statement }} Displays the escaped content of the statement. For example:
Code: Select all
{{ 'Hello<b>World</b>' }}
{{! 'Hello<b>World</b>' !}}
You can also output the contents of variables or other statements:
Code: Select all
{{ someVariableHere }}
{{ if(true) then return 'This statement is true!'; else return 'This statement is false!' end }}
@foreach({1, 2, 3, 4, 5} as index,value)
{
{{ index }} = {{ value }}<br />
}
Well, that should cover the basics! There's tons that I'm glossing over, but just take a look at the example code I've supplied and that should give you much more to go by. If you've got questions or comments, please reply!
Example:
To use the example, extract the attachment into your scripts folder. Start micromacro and run this command: web
Now open your web browser and go to: http://127.0.0.1:8080