Skip to content
DnsLister Forum

Where domain hunters compare notes

The Server Implementation Repo is now public on Github!

Here's the guide and repo to set everything up! I apologize in advance but I used AI to write up this guide to make sure it covers every single detail, so that even the less knowledgeable can set it up.

Repo: https://github.com/i-Ac1D-i/heroic-chant

This guide assumes zero experience with any of this. If you already know your way around adb, skip to section 5 and just read the README.

What actually works right now

  • Login, lobby, the full 138-hero roster
  • Story stages: turn-based combat, rewards, star flags, unlocking the next stage
  • Progress that survives closing the game
  • Hero rarity (A / S / SS / SSS)
  • Level up, star-up with shards and memory stones, the awakening skill tree
  • Equipment: equip, auto-equip, upgrade, sell, runes
  • City Search (the idle farm) with a working claim button
  • Summoning at the real drop rates, pulled from the game's own tables
  • Guilds: founding, donations, buffs, the exchange shop

What doesn't: PvP, arena, raids, guild wars — basically anything that needs other players. The Store screen only renders its Costume tab. The gacha grants your hero correctly but the result screen doesn't close itself, so you back out and reopen and the hero's sitting there.

58 of the 401 packets the client can send have handlers written. The rest get decoded and logged but don't do anything yet. That's the todo list if anyone wants to pitch in.

1. What you need before you start

A Windows PC. The server is plain Python so it runs anywhere, but every command below is written for Windows because that's what I have. Linux and Mac people, you'll be fine, just swap the path separators.

An Android emulator that can do ARM. This is important and it's where most people are going to get stuck.

The APK ships arm64-v8a and armeabi-v7a only. There is no x86 build. That means a normal Android Studio emulator will not run this. You need one that does ARM translation:

A real Android phone works too, but it also needs root.

Root. Non-negotiable, sorry. The game's 2 GB of assets have to sit inside /data/data/com.ngelgames.herocantare/, which is a protected folder. A fresh install can't download them because the CDN is dead, so we're copying them in by hand, and that needs root. Both emulators above have a root toggle in their settings.

Around 8 GB of free disk once everything's unzipped.

Emulator settings: Android 9 or 11, root ON, 4 GB RAM.

2. Downloads

The game files

The tools

3. Setting up adb

adb is the tool your PC uses to talk to the emulator. You want it on your PATH so you can type adb from any folder instead of the full path every single time.

Unzip it somewhere permanent. I use C:\platform-tools. Not Downloads, not Desktop — somewhere you won't clean out later. When you unzip you should end up with C:\platform-tools\adb.exe sitting right there. If you've got C:\platform-tools\platform-tools\adb.exe you nested it one folder too deep, move everything up a level.

Add it to PATH:

  1. Hit Start, type environment, click "Edit the system environment variables"
  2. Click the Environment Variables… button at the bottom
  3. In the top box (the one labelled "User variables"), find the row called Path and click it
  4. Click Edit…
  5. Click New
  6. Type C:\platform-tools
  7. OK on all three windows to close them

Now close every terminal window you have open. PATH changes only apply to new ones. This catches everybody.

Open a fresh PowerShell (Start, type powershell, Enter) and check:

adb version 

If you get "Android Debug Bridge version 1.0.41" or similar, you're set. If you get "not recognized", the PATH didn't take — check the folder path is right and that you actually opened a new window.

While you're there, check Python too:

python --version 

Should say 3.10 or higher.

4. Turn on ADB in your emulator

MuMu Player 12: Settings (the gear icon) → Other → turn on ADB debugging. Note the port it shows you, it's usually 16384.

LDPlayer 9: Settings → Other settings → ADB debugging: Open local connection.

Turn on root while you're in there. In MuMu it's under Other as "Root permission". Restart the emulator after changing it.

Now check your PC can see it:

adb devices 

You want a line like 127.0.0.1:16384 device. If the list comes back empty, connect by hand:

adb connect 127.0.0.1:16384 

Use 7555 for older MuMu, 5555 for LDPlayer.

If it says unauthorized, look at the emulator screen — there's a popup asking you to allow USB debugging. Tick "always allow" and hit OK.

5. Building the folder tree

Pay attention to this bit. The tools find things by relative path, so if the folders aren't laid out exactly like this, nothing works.

Make a folder somewhere. I'll call it HeroCantare but the name genuinely doesn't matter. Inside it you're aiming for exactly this:

HeroCantare\ ├── com.ngelgames.herocantare_1.2.389.apk ├── files\ │ └── ngelgames\ │ ├── AssetBundle\ │ ├── dnsinfo.json │ ├── real_serverinfo.json │ └── ... (lots more) ├── table\ │ └── herocantare.db ├── server-research\ │ ├── dump.cs │ └── protocol.json └── server\ <- the repo, we clone this in a second 

So:

  1. Put the APK in the root folder. Rename it to exactly com.ngelgames.herocantare_1.2.389.apk — Google Drive likes adding junk to filenames.
  2. Make a folder called table and drop herocantare.db in it.
  3. Unzip additional-files.zip into the root. It gives you files\ and server-research\. Double-check afterwards that you've got HeroCantare\files\ngelgames\AssetBundle and not HeroCantare\additional-files\files\ngelgames\AssetBundle — if you got the extra layer, move the folders up one.

Now open PowerShell in that folder. Easiest way: open the folder in File Explorer, click the address bar at the top, type powershell, hit Enter.

Clone the server:

git clone https://github.com/i-Ac1D-i/heroic-chant.git server 

The server on the end matters — it names the folder server, which is what the tools are expecting.

Then go into it:

cd server 

Every command from here on runs from inside that server folder.

6. Building the game data

The repo deliberately ships with no game data in it at all. Not one asset, not one table, no packet definitions. That's on purpose, I'm not redistributing someone else's game. So we build all of it locally from the files you just downloaded.

Install the libraries the build tools need:

pip install -r requirements-dev.txt 

That pulls in UnityPy (reads Unity asset bundles), capstone (an ARM disassembler), and cryptography. Takes a minute or two.

Now build the packet definitions:

python tools/gen_protocol.py --apk ../com.ngelgames.herocantare_1.2.389.apk 

This yanks libil2cpp.so out of the APK and disassembles every marshalling function in it to work out the exact byte layout of all 859 packets. Takes a couple of minutes and prints a wall of text. You want it to finish saying 859/859 verified.

Then extract the data tables:

python tools/extract_assets.py 

That reads the Unity bundles and dumps 252 JSON tables into server\data\. Another minute or so.

Now test it before you go anywhere near the emulator:

python tools/selftest.py 

This runs the actual server against a fake client — handshake, login, clearing a stage, checking the rewards landed, levelling a hero. You want to see:

ALL CHECKS PASSED 

If that passes, the server side is completely done and anything that goes wrong from here is a device problem, which narrows things down a lot. If it fails, fix it now, don't carry on.

7. Installing the game

Install the APK:

adb install ../com.ngelgames.herocantare_1.2.389.apk 

Launch it once from the emulator's app drawer, let it sit a few seconds, then close it. It'll fail to load, that's expected — we just need Android to create its data folder.

Now push the game assets in. This is the slow part, it's 2 GB:

adb push ../files/ngelgames /sdcard/ngelgames 

Go make a coffee.

Then copy it into the app's private folder and fix the permissions. Three commands:

adb shell su -c "cp -a /sdcard/ngelgames /data/data/com.ngelgames.herocantare/files/" adb shell su -c 'chown -R $(stat -c %U:%G /data/data/com.ngelgames.herocantare) /data/data/com.ngelgames.herocantare/files' adb shell su -c "restorecon -R /data/data/com.ngelgames.herocantare/files" 

Note the single quotes on that middle one — that's deliberate. PowerShell would try to run the $(stat ...) bit on your PC if you used double quotes, and stat isn't a Windows command. Single quotes send it through untouched so it runs on the device, which is where it needs to run.

Do not skip that last one. restorecon fixes the SELinux labels. Get it wrong and the app silently can't read its own files, shows you no error at all, and you'll burn an hour wondering why it crashes.

If su gives you "permission denied", root isn't actually on. Back to your emulator settings, turn it on, restart the emulator.

You can delete the staging copy afterwards to claw back 2 GB:

adb shell rm -rf /sdcard/ngelgames 

8. Pointing the client at your PC

The client has a config baked into it full of dead server addresses. We rewrite them to point at you.

We're going to use the loopback route via adb reverse, which tunnels ports over the ADB connection. Much easier than going over your LAN — no admin rights, no firewall rules, no touching your router. As far as the emulator is concerned your PC is just 127.0.0.1.

Patch the config files:

python tools/patch_client_config.py ../files/ngelgames --host 127.0.0.1 

That rewrites dnsinfo.json (39 hostnames), real_serverinfo.json, and all 37 real_patchinfo*.json files, keeping a .bak of each one. Add --restore later if you ever want the originals back.

Push the patched files back:

adb push ../files/ngelgames /sdcard/ngelgames adb shell su -c "cp -a /sdcard/ngelgames /data/data/com.ngelgames.herocantare/files/" adb shell su -c "restorecon -R /data/data/com.ngelgames.herocantare/files" 

Now redirect the one hostname that isn't in that config. Before the client opens a socket it fetches two JSON files over plain HTTP from dlhc.ngelgames.net. That hostname is baked into the binary and it's not in dnsinfo.json, so it goes through the normal system resolver and we have to catch it in the hosts file:

adb shell su -c "mount -o rw,remount /system" adb shell su -c "echo '127.0.0.1 dlhc.ngelgames.net' >> /system/etc/hosts" 

Check it stuck:

adb shell su -c "cat /system/etc/hosts" 

Your new line should be at the bottom. If the mount command failed, try /etc/hosts instead of /system/etc/hosts — some emulator builds symlink it differently.

9. Run it

One command does everything:

python tools/resume.py 

It connects to the emulator, sets up the port forwards, starts both servers, and launches the game for you.

What it's doing under the hood:

  • adb reverse tcp:80 tcp:8080 — the device's port 80 now lands on your PC's 8080
  • adb reverse tcp:21010 tcp:21010 — same deal for the game server port
  • starts the boot shim, which answers those two HTTP requests the client makes
  • starts the game server
  • force-stops and relaunches the game

You should see:

device: 127.0.0.1:16384 reverse: reverse tcp:80 tcp:8080 | reverse tcp:21010 tcp:21010 bootserver : http://127.0.0.1:8080 (log: logs/boot.log) game server: 127.0.0.1:21010 (log: logs/game.log) launched com.ngelgames.herocantare 

Logs land in server\logs\. Ctrl+C stops both servers.

A healthy boot looks like this in logs\game.log:

hc.net connected ('127.0.0.1', 41xxx) hc.net handshake complete with (...) (hostID 1) hc.net C2S CenterServerC2S.GetServerGroupInfoReq hc.center new account 1001 for device <id> hc.net C2S CenterServerC2S.GetConnectGameServerInfoReq hc.net connected (...) hc.net C2S GameServerC2S.LogInReq hc.login login: account 1001 (Player1001) client 1.2.389, 138 units 

That last line means you're in. Go play.

One thing to know: the adb reverse forwards die whenever the emulator restarts or your PC reboots. That is the number one reason this "randomly stops working". Just run python tools/resume.py again, it puts them back.

10. When it doesn't work

What you're seeing What's wrong
Stuck on the loading / patch screen forever It never reached the boot shim. Check logsboot.log — if it's empty, either the hosts redirect or the adb reverse isn't there
Crashes at the splash screen Either your emulator isn't doing ARM translation, or the files copy didn't land properly. Redo the chown and restorecon
logsgame.log says connected then immediately disconnected Client didn't like the handshake. Run with --log-level DEBUG and look for a decode error
Both logs completely empty DNS isn't redirected. Run adb shell ping dlhc.ngelgames.net — it has to come back as 127.0.0.1
Black screen after login Client's waiting on a packet nobody handles yet. logsgame.log will have a no handler line naming it
adb: no devices/emulators found Emulator isn't running, ADB isn't enabled in its settings, or you need adb connect 127.0.0.1:16384
adb not found -- add platform-tools to PATH Section 3, and make sure you opened a fresh terminal after
su: permission denied Root isn't enabled in the emulator. Turn it on, restart the emulator
herocantare.db not found It's in the wrong place. It goes in HeroCantaretableherocantare.db, not inside server

If you're stuck, run the server on its own with debug logging so you can watch every packet going both directions:

python -m hc.main --public-host 127.0.0.1 --log-level DEBUG 

11. Messing with your save

Accounts are plain JSON sitting at server\accounts\1001.json. Open it in any text editor, change your gold or your gems or whatever you feel like, restart the client. Nothing is validated, because it's your own server on your own machine.

To wipe and start fresh: delete that file and remove your device's entry from accounts\index.json.

12. If you want to help out

There's a CONTRIBUTING.md in the repo that walks through adding a packet handler start to finish with a real worked example. It's honestly not hard — the difficult part (working out the wire format) is already done, so most handlers come out around ten lines.

The way to find something to do: run the server, play, and watch for lines like

C2S GameServerC2S.SomeThingReq -- no handler (24 body bytes) 

That's a packet the game sent that nobody's implemented. There are 343 of them, and the ones the game hits first are the ones worth doing first.

Bigger stuff that needs actual design work: arena and PvP (the game shipped with AI bot teams sitting in its data, so it's doable without other players), guild raids and wars, and working out why the Store screen only draws its Costume tab.

Legal, quickly

The server code is mine and you can do whatever you want with it. The game isn't mine.

No game assets, data tables, packet definitions or APK are in the repo and they shouldn't be added — everything gets rebuilt from your own copy. The Drive links up top are there so people who already played this game can play it again. It's been dead for two years, there's no way to buy it and no way to play it.

Don't repackage this into an APK and hand it around as "the game". Share the server and let people point their own client at it.

That's the lot. If you get stuck, post what logs\game.log and logs\boot.log say — that's usually enough to spot the problem straight away.

Source: r/Herocantare · by /u/haikottero

Leave a Reply

Your email address will not be published. Required fields are marked *