diff --git a/.github/workflows/update-docs-download.yml b/.github/workflows/update-docs-download.yml deleted file mode 100644 index e56ab8c..0000000 --- a/.github/workflows/update-docs-download.yml +++ /dev/null @@ -1,166 +0,0 @@ -# --------------------------------------------------------------------------- -# update-docs-download.yml -# -# Additive, non-destructive workflow that fires whenever a GitHub Release is -# published. It queries the release assets, picks the **largest** .exe file -# (the real NSIS installer, not the tiny Tauri stub), and patches the -# download link inside docs/index.html so visitors always get a one-click -# download of the latest installer. -# -# Nothing is deleted — only the href of the download button is updated. -# --------------------------------------------------------------------------- - -name: Update Docs Download Link - -on: - release: - types: [published] - workflow_dispatch: # manual trigger for testing - -permissions: - contents: write - -jobs: - update-download-link: - name: Patch docs/index.html with latest EXE URL - runs-on: ubuntu-latest - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - ref: master # always update the branch that serves GitHub Pages - - - name: Resolve latest installer URL - id: resolve - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - echo "Fetching latest release assets..." - - # Get all .exe assets from the triggering release (or latest if manual) - if [ "${{ github.event_name }}" = "release" ]; then - TAG="${{ github.event.release.tag_name }}" - else - TAG="$(gh release list --limit 1 --exclude-drafts --exclude-pre-releases --json tagName -q '.[0].tagName')" - fi - - echo "Release tag: $TAG" - - # List all .exe assets with their sizes, pick the largest one - ASSET_INFO=$(gh release view "$TAG" --json assets \ - -q '[.assets[] | select(.name | endswith(".exe"))] | sort_by(.size) | last | {url: .url, name: .name, size: .size}') - - if [ -z "$ASSET_INFO" ] || [ "$ASSET_INFO" = "null" ]; then - echo "::error::No .exe assets found in release $TAG" - exit 1 - fi - - ASSET_NAME=$(echo "$ASSET_INFO" | jq -r '.name') - ASSET_SIZE=$(echo "$ASSET_INFO" | jq -r '.size') - ASSET_SIZE_MB=$(echo "scale=1; $ASSET_SIZE / 1048576" | bc) - - # Build the direct browser-download URL - DOWNLOAD_URL="https://github.com/${{ github.repository }}/releases/download/${TAG}/${ASSET_NAME}" - - echo "Selected asset: $ASSET_NAME ($ASSET_SIZE_MB MB)" - echo "Download URL: $DOWNLOAD_URL" - - echo "download_url=$DOWNLOAD_URL" >> "$GITHUB_OUTPUT" - echo "asset_name=$ASSET_NAME" >> "$GITHUB_OUTPUT" - echo "asset_size_mb=$ASSET_SIZE_MB" >> "$GITHUB_OUTPUT" - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - - - name: Update docs/index.html - env: - DOWNLOAD_URL: ${{ steps.resolve.outputs.download_url }} - ASSET_NAME: ${{ steps.resolve.outputs.asset_name }} - ASSET_SIZE: ${{ steps.resolve.outputs.asset_size_mb }} - TAG: ${{ steps.resolve.outputs.tag }} - run: | - FILE="docs/index.html" - - if [ ! -f "$FILE" ]; then - echo "::error::$FILE not found" - exit 1 - fi - - # 1. Update the data-download-url attribute (used by JS runtime fetcher) - # and the static fallback href on the main download button - python3 - "$FILE" "$DOWNLOAD_URL" "$ASSET_NAME" "$ASSET_SIZE" "$TAG" <<'PYEOF' - import sys, re - - file_path = sys.argv[1] - url = sys.argv[2] - asset_name = sys.argv[3] - size_mb = sys.argv[4] - tag = sys.argv[5] - - with open(file_path, "r", encoding="utf-8") as f: - html = f.read() - - # Update the nav Download link - html = re.sub( - r'({url}\2', - html, - ) - - # Update the data attributes on the download-installer link - html = re.sub( - r'(id="download-installer-btn"\s+href=")[^"]*(")', - rf'\g<1>{url}\2', - html, - ) - html = re.sub( - r'(data-download-url=")[^"]*(")', - rf'\g<1>{url}\2', - html, - ) - html = re.sub( - r'(data-asset-name=")[^"]*(")', - rf'\g<1>{asset_name}\2', - html, - ) - html = re.sub( - r'(data-asset-size=")[^"]*(")', - rf'\g<1>{size_mb}\2', - html, - ) - html = re.sub( - r'(data-release-tag=")[^"]*(")', - rf'\g<1>{tag}\2', - html, - ) - - # Update the visible version badge - html = re.sub( - r'(id="installer-version">)[^<]*()', - rf'\g<1>{tag} — {size_mb} MB\2', - html, - ) - - with open(file_path, "w", encoding="utf-8") as f: - f.write(html) - - print(f"Patched {file_path} → {url}") - PYEOF - - - name: Commit and push - run: | - git config user.name "github-actions[bot]" - git config user.email "github-actions[bot]@users.noreply.github.com" - - git add docs/index.html - - git diff --cached --quiet && { - echo "No changes to commit — docs already up to date." - exit 0 - } - - git commit -m "docs: update download link to ${{ steps.resolve.outputs.tag }} installer - - Asset: ${{ steps.resolve.outputs.asset_name }} (${{ steps.resolve.outputs.asset_size_mb }} MB) - URL: ${{ steps.resolve.outputs.download_url }}" - - git push origin master diff --git a/docs/index.html b/docs/index.html index d49a6b2..9106a65 100644 --- a/docs/index.html +++ b/docs/index.html @@ -501,7 +501,7 @@ Install Best Practices - Download + Download @@ -993,30 +993,6 @@

9 Neural Nets. Pick Your Weapon.

From Zero to Auto-Farm in 5 Minutes

No PhD required. Just follow these steps and your AI will be farming while you sleep. Windows 10/11 for gameplay; training works on any OS.

- -
- - - Download Windows Installer - -
- v0.2.0 — 181 MB - | - All releases -
-
- -

- Or install from source using the steps below: -

-
1
@@ -1326,62 +1302,6 @@

Enjoying the Bot? Drop a Star!

}); }); -// ============================================= -// AUTO-RESOLVE LATEST INSTALLER FROM GITHUB RELEASES -// Fetches the latest release, finds the largest .exe -// asset (the real NSIS installer), and updates all -// download links on the page. -// ============================================= -(function(){ - var REPO = 'ruslanmv/BOT-MMORPG-AI'; - var API = 'https://api.github.com/repos/' + REPO + '/releases/latest'; - - fetch(API) - .then(function(r){ return r.json(); }) - .then(function(release){ - if (!release || !release.assets) return; - - // Find the largest .exe asset (the real installer, not stubs) - var best = null; - release.assets.forEach(function(a){ - if (a.name.endsWith('.exe') && (!best || a.size > best.size)) { - best = a; - } - }); - if (!best) return; - - var url = best.browser_download_url; - var name = best.name; - var sizeMB = (best.size / 1048576).toFixed(0); - var tag = release.tag_name; - - // Update the main installer download button - var dlBtn = document.getElementById('download-installer-btn'); - if (dlBtn) { - dlBtn.href = url; - dlBtn.setAttribute('data-download-url', url); - dlBtn.setAttribute('data-asset-name', name); - dlBtn.setAttribute('data-asset-size', sizeMB); - dlBtn.setAttribute('data-release-tag', tag); - } - - // Update version badge - var verSpan = document.getElementById('installer-version'); - if (verSpan) { - verSpan.textContent = tag + ' \u2014 ' + sizeMB + ' MB'; - } - - // Update nav download link - var navCta = document.querySelector('.nav-cta'); - if (navCta) { - navCta.href = url; - } - }) - .catch(function(){ - // Silently fall back to the static URL already in the HTML - }); -})(); - // ============================================= // ANIMATED STAT COUNTERS // ============================================= diff --git a/src/bot_mmorpg/inference/engine.py b/src/bot_mmorpg/inference/engine.py index 56be61e..3328a76 100644 --- a/src/bot_mmorpg/inference/engine.py +++ b/src/bot_mmorpg/inference/engine.py @@ -175,7 +175,7 @@ def from_checkpoint( # Load checkpoint device = cls._detect_device_static() - checkpoint = torch.load(checkpoint_path, map_location=device, weights_only=False) + checkpoint = torch.load(checkpoint_path, map_location=device) # Extract metadata metadata = cls._extract_metadata(checkpoint) @@ -270,11 +270,12 @@ def _build_model(metadata: ModelMetadata) -> nn.Module: if str(src_path) not in sys.path: sys.path.insert(0, str(src_path)) - from bot_mmorpg.scripts.models_pytorch import get_model + from bot_mmorpg.scripts.models_pytorch import create_model - model = get_model( - model_name=metadata.architecture, - num_actions=metadata.num_classes, + model = create_model( + architecture=metadata.architecture, + num_classes=metadata.num_classes, + input_size=metadata.input_size, temporal_frames=metadata.temporal_frames, pretrained=False, # We'll load weights separately ) diff --git a/src/bot_mmorpg/scripts/collect_data.py b/src/bot_mmorpg/scripts/collect_data.py index f6563f3..147fef2 100644 --- a/src/bot_mmorpg/scripts/collect_data.py +++ b/src/bot_mmorpg/scripts/collect_data.py @@ -412,7 +412,9 @@ def main(argv: Optional[List[str]] = None) -> int: ) except FileNotFoundError: logger.error(f"Game profile '{args.game}' not found.") - logger.error("Available profiles are listed in game_profiles/index.yaml") + logger.error( + "Available profiles are listed in game_profiles/index.yaml" + ) return 1 # --- Auto-detect game window region --- diff --git a/src/bot_mmorpg/scripts/grabscreen.py b/src/bot_mmorpg/scripts/grabscreen.py index 3faf66a..98a55ea 100644 --- a/src/bot_mmorpg/scripts/grabscreen.py +++ b/src/bot_mmorpg/scripts/grabscreen.py @@ -258,7 +258,12 @@ def _enum_callback(hwnd, _): parts = line.split() # wmctrl -lG format: id desktop x y w h hostname title... if len(parts) >= 7: - x, y, w, h = int(parts[2]), int(parts[3]), int(parts[4]), int(parts[5]) + x, y, w, h = ( + int(parts[2]), + int(parts[3]), + int(parts[4]), + int(parts[5]), + ) return (x, y, x + w, y + h) except (FileNotFoundError, subprocess.CalledProcessError): pass