AMFPHP Scripting
When curating, there's a chance you'll come across a game that requests a URL that returns a unique binary response with an application/x-amf header. This means the game is communicating with an AMFPHP server.
What is AMFPHP
AMFPHP is a PHP library that serializes ActionScript objects in a binary format, and it uses PHP classes to configure and serve the data. More in depth specifications can be found on its website https://amfphp.org/
Identifying AMFPHP Games
You should be able to check all of these in the Network tab, if these are true, it could use AMFPHP
- The game makes a request with "gateway" in its url
- The request payload of the PHP script contains a TargetURI
- The script's Content-Type is application/x-amf
Here's an example of a game that uses AMFPHP, it's requesting gateway.php to return team data:
https://www.neopets.com/games/play_flash.phtml?va=&game_id=1288&width=670&height=600&quality=low
Notes Before Proceeding
Curating games that use AMFPHP requires the scripts PHP code to be recreated, which requires some PHP programing knowledge. Continue the tutorial if you're familiar with the PHP programing language. If at any point you need help or are confused on something, feel free to ask in the #hackers chat of the Flashpoint Discord. Below are also a few resources if you're interested in learning PHP:
https://www.w3schools.com/php/
It's also expected that you've followed the Curation Tutorial to understand the curation process. Please follow that before moving on.
All games that use AMFPHP scripts must also have the mount parameter -extract --server=apache
Scripting Steps
You'll first want to create the gateway script where the game is requesting it. If your game is requesting the url without the .php extension, you should also make an htaccess file to redirect the request to your script.
Next you'll add the gateway code into the PHP script. The example code here can be used for most cases:
require dirname($_SERVER['DOCUMENT_ROOT']) . '/vendor/autoload.php'; $config = new Amfphp_Core_Config(); $voFolders = array(dirname(__FILE__) . '/vo/'); $config->pluginsConfig['AmfphpVoConverter'] = array('voFolders' => $voFolders); $config->serviceFolders = array(dirname(__FILE__) . '/services/'); $gateway = Amfphp_Core_HttpRequestGatewayFactory::createGateway($config); $gateway->service(); $gateway->output();
Explanation: This loads AMFPHP through Vendor and creates an AMFPHP config that sets the services folder so it can find the custom class scripts you make. The service function then runs the class function based on the requests, then the output function outputs the serialized response.
Next you'll make a services folder in the same folder as your gateway script. This is where you'll put custom class scripts the game requires, by reverse engineering the responses from the live site. There are several ways to go about this, which will be listed next.
AMFPHP Use Cases
In order to create the classes, it's first important to understand a few use cases and techniques for dealing with scripts.
TargetURIs
TargetURIs are the format containing the service and function name, separated by either a "." or "/". An example would be AltadorCupService.getTeamInfo, with AltadorCupService being the name of the Service, and getTeamInfo being the function in the service.
TargetURIs with more than 1 separator include additional directories to nest your service in. For example the TargetURI slxdev.cfc.BioChem.getAllModuleInfo would have BioChem.php at slxdev\cfc\BioChem.php, with getAllModuleInfo being the function it's calling.
Explicit Types
Some function may need to return objects with explicit types. This can be done by creating a class of the same name, or by using the FIELD_EXPLICIT_TYPE constant in the following example code:
$response = new stdClass(); $responseTypeField = Amfphp_Core_Amf_Constants::FIELD_EXPLICIT_TYPE; $response->$responseTypeField = "flex.messaging.messages.AcknowledgeMessage";
The responseTypeField string would be changed to the type you are wanting to create.
Using the Explicit Type constant is also useful for types that have special characters, like ".".
Headers
Sometimes games will send an AMF request with headers. If so, you can access this data with the variable Amfphp_Core_Amf_Handler::$requestPacket->headers[0]->data;
Curated Examples
Listed bellow are some games in the Flashpoint database that use AMFPHP, and are a good reference for understanding the script format.
Game | UUID |
---|---|
Bloons Super Monkey 2 | 0ea6fb47-3af9-4cbe-981d-ab47f37d5f79 |
mini racers | 225eea1f-020a-4cc8-a1ac-0665e9bccad5 |
Sensory World | be359a9b-4738-4932-ab70-6dd07f7f2eae |
Fizzy's Lunch Lab: Fizzy's Balance Bots | b0e4d5c8-8ed5-4177-a6af-5ba110305735 |