I've made a spike for cartriges to send http requests and receive their response.
The way it works is the cartrige communicates with the browser through gpio. In here I'm using 2 assumptions (I guess dangerous ones) that make it quite simple to send messages:
- We get synchronous interrupts from p8 -> JS when p8 writes to a GPIO.
- We read an analog value 0-255 in perfect accuracy.
So... yep, this code atm only works in a browser. And it might be posible that it breaks later on (specially for assumption 1, as it depends on the runtime implementation)
It's separated in two layers: The first one just abstracts over sending and receiving any message
html_messaging.lua html_messaging={ send_message=function(self, message) -- sends a `message` string to the host HTML end, add_listener=function(self, listener) -- adds the `listener` function to be called with receiving messages end, remove_listener=function(self, listener) -- stops sending message updates to the listener end, update=function(self) -- this function must be called on every update, so that html_messaging can check for new messages end } |
gpio_messaging.js // This file also sets window.pico8_gpio - Make sure not to override it, or it won't get the interrupts! window.pico8_gpioMessaging={ sendMessage(message) { // sends the string `message` to p8 // returns a promise that resolves when the message was completely sent // (we don't have synchronous interrupts from js -> p8) } } // pico8_gpioMessaging is an EventEmitter of 'message' events // which have a 'message' prop with the received message |
The other layer needs to have that one imported first - This is the one to send and receive HTTP requests
http_request.lua http_request={ get=function(self,url,cb) -- sends a GET request to url, sending the message as a string to callback once it's received end } |
http_request.js // Exports nothing: This file listens for p8 http requests and proxies them to the real BE |
I can't embed an example cartrige here because it also needs some setup on the HTML/JS side, but a simple script that requests the datetime from worldclockapi:
#include html_messaging.lua #include http_request.lua function _update() if btnp(🅾️) then http_request:get("http://worldclockapi.com/api/json/utc/now", function (response) printh(response) end ) end html_messaging:update() end |
The only thing the host HTML needs is importing both gpio_messaging.js and http_request.js.
Now I only need to write a JSON parser :'D (/s - I know this would be a bad idea).
I think this might be useful for simple ad-hoc services, like global highscores. Also maybe to run around the size limit in cartridge for things like level data, or maybe even to some extend turn-based multiplayer games? :exploding_head:
nice package, though I suspect that’s only working if destination url=pico web page url (browser will not allow x-site calls).
as for multiplayer & leaderboard, sure, and have already been done (still quite rare as the dev workflow is quite tedious)
> (browser will not allow x-site calls).
Yes it will, but request success depends on CORS configuration in the target server.
@freds72 x-site calls are enforced by the browser as you said, but it's the server who defines what policies apply.
For instance, the call to the worldclockapi (http://worldclockapi.com/api/json/utc/now) replies with a header "Access-Control-Allow-Origin: *", which means it can be requested from any domain, so the browser will allow that one through. Most public APIs have open CORS requests, and if you build a server for your own game you can also set it up so it's available for all domains or a whitelist.
[Please log in to post a comment]