Porting a PHP Based Web Game to Mobile Part 1

Advance Wars by Web (AWBW) is a web port of the Advance Wars Nintendo game. I was first introduced to the game by my best friend. I thought it was a fun game, however it was lacking in the mobile department. There is currently no mobile version of the game, at least not one that connects up to the same backend. I've decided to start building a mobile port for the game, my goal is to have an easy to navigate interface for mobile users, as well as notifications for when its the player's turn. The player should be able to play the game as they would on the web, only via their phone. Currently the web version does work on mobile, but it is clunky and difficult to navigate. I will build the app in Unity and make it compatible with all major current resolutions as at 2025. I started by running the web app with firefox's network logging enabled, in order to see what kind of game data I could get and from which endpoints. I uncovered a response from https://awbw.amarriner.com/game.php?games_id={{game_id}} seems to hold the vast majority of game data, from terrain to building to unit data. All that I needed to do now was to parse it, so I started building a parser that would take in the response from game.php and extract the relevant data I would need and transform it into a usable form. I also found that you can login via the https://awbw.amarriner.com/logincheck.php endpoint. This returns a 200 regardless of success, instead opting to return a 0 or 1 to indicate a failed or successful login respectfully. This will be helpful later when we actually start trying to send move data to the server. I continued working on the parser for the terrain info from game.php. I spent far too long trying to remember how to handle de-serializing JSONs with dynamic keys, eventually I settled on the following: public class GameInfoParser {     public TerrainInfo ParseTerrain(string gameInfoHtml)     {         TerrainInfo terrainInfo = new TerrainInfo();         terrainInfo.Tiles = new List();         List serverTerrainInfos = ExtractTerrainInfoJson(gameInfoHtml);         terrainInfo.Tiles = serverTerrainInfos.ConvertAll(t => new() { X = t.tiles_x, Y = t.tiles_y});         return terrainInfo;     }     private List ExtractTerrainInfoJson(string gameInfoHtml)     {         string terrainInfoJson = gameInfoHtml.Split("const terrainInfo = ")[1].Split(";")[0];         var json = JsonConvert.DeserializeObject(terrainInfoJson);         List serverTerrainInfoList = new List();         foreach(var xCoord in json.Keys)         {             foreach(var yCoord in json[xCoord].Keys)             {                 serverTerrainInfoList.Add(json[xCoord][yCoord]);             }         }         return serverTerrainInfoList;     }     private struct ServerTerrainInfo     {         public int tiles_x;         public int tiles_y;     } } After trying to run the code above against the actual game.php response HTML, I was - to be honest not awfully - surprised to find the code failing. After some debugging and a lot of confusion, I found the culprit. The game.php response returned an HTML file, in that HTML, you will find large JSON objects comprising of all the game state data. The terrain data as it turned out, had a rogue JSON array in amongst its JSON objects, likely caused by the JSON serializer mistaking the keys 0, 1, 2, 3... for indexes in an array as opposed to actual keys. You see, the JSON keys were y coordinates, while the value was a dictionary of x coordinates to objects, where the objects were the data I needed). If a y coordinate's corresponding collection of x coordinates happened to be a consecutive set of numbers starting from 0, the y coordinate's value would show as an array as opposed to just a JSON object. A bit strange, but we can easily make use of a library to instead parse the JSON into JSONNode objects, where we can deal with the data regardless of whether it is an array or an object. Eventually, we end on: private List ExtractTerrainInfoJson(string gameInfoHtml) { string terrainInfoJson = gameInfoHtml.Split("const terrainInfo = ")[1].Split(";")[0]; List serverTerrainInfoList = new List(); JSONNode jsonNode = SimpleJSON.JSON.Parse(terrainInfoJson); foreach(JSONNode yNode in jsonNode.Values) { foreach(JSONNode xNode in yNode.Values) { string jsonValue = xNode.ToString(); ServerTerrainInfo serverTerrainInfo = JsonConvert.DeserializeObject(jsonValue); serverTerrainInfoList.Add(serverTerrainInfo); } } return serverTerrainInfoList; } Finally, all green on my tests. It would be nice to at least start being able to view the map we have worked so hard to parse data for. So I got to work on building out a little map renderer. Nothing fancy, just taking the collections of data we extracted previously and instantiating some ti

Apr 10, 2025 - 08:07
 0
Porting a PHP Based Web Game to Mobile Part 1

Advance Wars by Web (AWBW) is a web port of the Advance Wars Nintendo game. I was first introduced to the game by my best friend. I thought it was a fun game, however it was lacking in the mobile department. There is currently no mobile version of the game, at least not one that connects up to the same backend.

I've decided to start building a mobile port for the game, my goal is to have an easy to navigate interface for mobile users, as well as notifications for when its the player's turn. The player should be able to play the game as they would on the web, only via their phone. Currently the web version does work on mobile, but it is clunky and difficult to navigate. I will build the app in Unity and make it compatible with all major current resolutions as at 2025.

I started by running the web app with firefox's network logging enabled, in order to see what kind of game data I could get and from which endpoints. I uncovered a response from https://awbw.amarriner.com/game.php?games_id={{game_id}} seems to hold the vast majority of game data, from terrain to building to unit data. All that I needed to do now was to parse it, so I started building a parser that would take in the response from game.php and extract the relevant data I would need and transform it into a usable form.

I also found that you can login via the https://awbw.amarriner.com/logincheck.php endpoint. This returns a 200 regardless of success, instead opting to return a 0 or 1 to indicate a failed or successful login respectfully. This will be helpful later when we actually start trying to send move data to the server.

I continued working on the parser for the terrain info from game.php. I spent far too long trying to remember how to handle de-serializing JSONs with dynamic keys, eventually I settled on the following:

public class GameInfoParser

{

    public TerrainInfo ParseTerrain(string gameInfoHtml)

    {

        TerrainInfo terrainInfo = new TerrainInfo();

        terrainInfo.Tiles = new List();



        List serverTerrainInfos = ExtractTerrainInfoJson(gameInfoHtml);

        terrainInfo.Tiles = serverTerrainInfos.ConvertAll(t => new() { X = t.tiles_x, Y = t.tiles_y});



        return terrainInfo;

    }

    private List ExtractTerrainInfoJson(string gameInfoHtml)

    {

        string terrainInfoJson = gameInfoHtml.Split("const terrainInfo = ")[1].Split(";")[0];

        var json = JsonConvert.DeserializeObject>>(terrainInfoJson);

        List serverTerrainInfoList = new List();

        foreach(var xCoord in json.Keys)

        {

            foreach(var yCoord in json[xCoord].Keys)

            {

                serverTerrainInfoList.Add(json[xCoord][yCoord]);

            }

        }



        return serverTerrainInfoList;

    }



    private struct ServerTerrainInfo

    {

        public int tiles_x;

        public int tiles_y;

    }

}

After trying to run the code above against the actual game.php response HTML, I was - to be honest not awfully - surprised to find the code failing. After some debugging and a lot of confusion, I found the culprit.

The game.php response returned an HTML file, in that HTML, you will find large JSON objects comprising of all the game state data. The terrain data as it turned out, had a rogue JSON array in amongst its JSON objects, likely caused by the JSON serializer mistaking the keys 0, 1, 2, 3... for indexes in an array as opposed to actual keys. You see, the JSON keys were y coordinates, while the value was a dictionary of x coordinates to objects, where the objects were the data I needed). If a y coordinate's corresponding collection of x coordinates happened to be a consecutive set of numbers starting from 0, the y coordinate's value would show as an array as opposed to just a JSON object. A bit strange, but we can easily make use of a library to instead parse the JSON into JSONNode objects, where we can deal with the data regardless of whether it is an array or an object.

Eventually, we end on:

private List ExtractTerrainInfoJson(string gameInfoHtml)
    {
        string terrainInfoJson = gameInfoHtml.Split("const terrainInfo = ")[1].Split(";")[0];
        List serverTerrainInfoList = new List();
        JSONNode jsonNode = SimpleJSON.JSON.Parse(terrainInfoJson);

        foreach(JSONNode yNode in jsonNode.Values)
        {
            foreach(JSONNode xNode in yNode.Values)
            {
                string jsonValue = xNode.ToString();
                ServerTerrainInfo serverTerrainInfo = JsonConvert.DeserializeObject(jsonValue);
                serverTerrainInfoList.Add(serverTerrainInfo);
            }
        }

        return serverTerrainInfoList;
    }

Finally, all green on my tests.

It would be nice to at least start being able to view the map we have worked so hard to parse data for. So I got to work on building out a little map renderer. Nothing fancy, just taking the collections of data we extracted previously and instantiating some tiles in the scene according to their positions and tile type. That gives us this rather hideous looking image, but we know what it took to make, so it's beautiful to us.
Image description

Next time, we'll need to start parsing the units types and look into getting actions to the server. Until then!