# Evony Scout — Documentación

Herramienta de scouting de monstruos / bosses / players en **Evony: The King's Return**
(server **2163**) mediante **Frida + frida-il2cpp-bridge** sobre emuladores Android
rooteados. Lee la memoria del juego en vivo, mueve la cámara para barrer el mapa y
sirve una UI web con filtros (radio, familias boss/event, players, "Discovered", etc.).

Hay **dos versiones** (independientes, NO se pueden correr a la vez — ambas
enganchan Frida al Evony de emulator-5554):

| | Carpeta | Puerto | Escáneres | Vuelta al mapa | Uso |
|---|---|---|---|---|---|
| **v1** | `iscout/` | 8770 | 1 (emulator-5554 / cuenta #1) | ~110 s | Setup simple, 1 emulador |
| **v2 DUAL** | `evony-scout-dual/` | 8771 | 2 (½ mapa c/u) | ~30 s/½ en paralelo | Más frescura/throughput |

v2 reparte el mapa por un corte vertical en **X=650**: emulator-5554 (cuenta #1)
barre el **Oeste** (X≤650), emulator-5556 (cuenta #2) el **Este** (X≥650), y el
backend **fusiona** ambos flujos en un único pool.

---

## Arranque rápido

```bash
./start_v1.sh      # v1 single  -> http://127.0.0.1:8770
./start_v2.sh      # v2 dual    -> http://127.0.0.1:8771
```

Cada script: levanta el/los emulador(es) si no están, arranca `frida-server` como
root, lanza Evony y el backend. **Detiene automáticamente la otra versión**
(no pueden coexistir). Lo único **manual** (siempre lo haces tú): iniciar sesión
en Evony y dejar la(s) cuenta(s) en el **mapa del mundo del server 2163**, con
**la(s) ventana(s) de emulador visibles** (Unity pausa el render sin foco).

Parar:
```bash
lsof -ti :8770 | xargs kill -9     # v1
lsof -ti :8771 | xargs kill -9     # v2
```

---

## Arranque manual (equivalente)

**Prerrequisitos** (una vez): AVDs `evony_root` (5554) y `evony_root_2` (5556),
SDK en `/opt/homebrew/share/android-commandlinetools`, `adb` en PATH, `python3`
con `frida` 17.9.10, `frida-server-17.9.10-android-arm64` en cada carpeta.

```bash
# 1) Emulador(es)
/opt/homebrew/share/android-commandlinetools/emulator/emulator -avd evony_root \
  -port 5554 -no-snapshot -writable-system -no-boot-anim -gpu auto \
  -memory 4096 -partition-size 8192 -no-audio &
#   (v2: lanzar también evony_root_2 en -port 5556)

# 2) frida-server (por cada emulador, tras cada reinicio del emulador)
adb -s emulator-5554 root
adb -s emulator-5554 push iscout/frida-server-17.9.10-android-arm64 /data/local/tmp/frida-server
adb -s emulator-5554 shell "chmod 755 /data/local/tmp/frida-server"
adb -s emulator-5554 shell "nohup /data/local/tmp/frida-server >/dev/null 2>&1 &"

# 3) Login (MANUAL): cuenta(s) en el mapa del mundo, server 2163

# 4) Backend
python3 iscout/iscout_web.py              # v1  -> 8770
python3 evony-scout-dual/iscout_web.py    # v2  -> 8771
```

---

## La UI

- Pestañas **Monstruos** y **Players**, filtros de familia (pills Boss/Event),
  radio (centro 603,603), tipo, orden, límite.
- Columna **Discovered**: hace cuánto se descubrió esa instancia.
- Filas resaltadas en **amarillo** = descubierto hace < **2 min** (`FRESH_WINDOW`).
- Header: en v2 muestra el estado de los dos escáneres: `sweep W núm.X (t) · E núm.Y (t)`.
- "solo activos": por defecto solo lo visto en los últimos ~90 s (`STALE_SECONDS`).

### Detección de "nuevo" (instancia, no coordenada)
Los bosses reaparecen en tiles recurrentes. Un objeto cuenta como **spawn nuevo**
(resetea "Discovered" y se resalta) si: el tile nunca se vio, **o** cambió
`id`/`level`, **o** el tile estuvo sin verse ≥ `RESPAWN_GAP_S`.
`RESPAWN_GAP_S` = **80 s** en v2 (½ vuelta ~30 s) y **250 s** en v1 (vuelta ~110 s);
está calado a la cadencia de cada versión — no copiar el valor entre versiones.

---

## Rebuild de los agentes (solo si tocas `agent_sweep.ts`)

`frida-compile` produce un *bundle* (empieza por 📦) que **NO** se puede editar en
runtime. v2 usa **dos agentes precompilados** (`agent_W.js`, `agent_E.js`):

```bash
cd /tmp/il2cpp_work
NODE=/Users/danicosta/.nvm/versions/node/v22.11.0/bin
# v1:
cp /Users/danicosta/Desktop/Evony/iscout/agent_sweep.ts agent_sweep.ts
PATH="$NODE:$PATH" node_modules/.bin/frida-compile agent_sweep.ts -o agent_sweep.js
cp agent_sweep.js /Users/danicosta/Desktop/Evony/iscout/agent.js
# v2 (por mitad):
SRC=/Users/danicosta/Desktop/Evony/evony-scout-dual/agent_sweep.ts
for H in W E; do
  sed "s/\"SCANHALF_PLACEHOLDER\"/\"$H\"/" "$SRC" > agent_sweep_$H.ts
  PATH="$NODE:$PATH" node_modules/.bin/frida-compile agent_sweep_$H.ts -o agent_$H.js
  cp agent_$H.js /Users/danicosta/Desktop/Evony/evony-scout-dual/agent_$H.js
done
```

---

## Troubleshooting (gotchas reales)

- **Una ventana de emulador sin foco** → Unity pausa el render → ese escáner deja
  de capturar. Mantén las ventanas visibles (en v2, las dos, lado a lado).
- **Tras reiniciar un emulador** hay que re-armar `frida-server` (los scripts lo hacen).
- **`malformed package`** al cargar el agente → NO edites el bundle de
  frida-compile en runtime; usa los precompilados (ver §Rebuild).
- **Cuenta #2 / Google Play "Linking account failed"**: el emulador rooteado usa
  imagen `google_apis` (sin Play Store) y **no autentica Google Play Games**. La
  #2 debe entrar por un vínculo NO-Google (Facebook/email) hecho desde un sitio
  donde la #2 funcione. Las imágenes con Play Store no son rooteables (sin root
  no hay Frida).
- **"someone login with your account"**: Evony permite 1 sesión por cuenta. Si
  clonas un AVD, borra datos de Evony del clon (`pm clear`) y dale identidad de
  dispositivo distinta; la #2 debe ir por OTRA cuenta (Google/FB) distinta de la #1.
- **v1 y v2 a la vez** = imposible (ambas enganchan Frida a emulator-5554). Los
  scripts paran la otra automáticamente.
- **Ritmo de "nuevos"** esperado: v1 ~4-5/min a ráfagas (1 lote/vuelta),
  v2 ~3-24/min continuo. Ambos por encima del ~1/min de referencia de iScout.
