Skip to main content
Explore is the launcher’s repack store and Downloads is the queue of its built-in torrent client (with the Install button when a download finishes). A theme can paint both its own way. Declare this in theme.json:
and the quick menu, Ctrl+E, Ctrl+J and the host’s notices will ask it to open its view instead of opening the launcher’s generic windows:
Without features.explore, the theme does not have to do anything. The host opens its own windows (and the theme can open them with ejg.downloads.open("explore" | "downloads")).

Wishlist

The games the user wants. It is stored on the PC (in ejGames’ database), one per local profile, and it is the same in every theme and in the host’s Explore window. Each game carries its status, kept up to date (downloading, installed, in the library…), like the other lists.
The kit has the usual pieces for painting it (/_sdk/kit/store.js): WISH_SORTS and sortWishlist(items, order) (added, name, release, size) and toggleWish(ejg, page), which adds or removes it with a notice. Each theme names it in its own words. The source strings are “Lista de deseados” on Steam and Moneda, “Lista de deseos” on PS5, Xbox and Switch, “Deseados” on Cinema and “DESEADOS” on Retro. In English those become Wishlist, or WISHLIST on Retro. toggleWish(ejg, page, "tu lista de deseos") uses that name in the notice.

Hypervisor cracks (HV)

Some repacks carry a hypervisor crack. They do not remove the game’s protection. They fool it with an unsigned driver that runs underneath Windows. To play them you have to turn off Windows’ virtualization-based security for a while (memory integrity, Credential Guard, the Windows hypervisor, mandatory driver signing…) and turn it back on when you are done. Those pages carry hypervisor: true (and the prepared download, p.hypervisor). Mark it next to the name wherever the game appears, and explain it on the page before the download button. The kit has the text and the pieces, so each theme only has to give them its skin:
repackName puts the name in a <span> so it can be cut with ”…” without taking the tag with it:
hypervisorInfo(ejg, r, { cls, open, labels }) starts collapsed (open: true opens it). cls prefixes all of its classes (hv, hv-head, hv-badge, hv-title, hv-sum, hv-body, hv-sec, hv-sec-<id>, hv-sec-title, hv-note, hv-list, hv-foot, hv-more, hv-guide; is-open when expanded) and labels changes the HYPERVISOR texts (for example, into capitals). Its buttons carry data-focus.

The catalog with filters

browse(filters, page) walks the whole catalog:
With maxGb or hideOwned the filtering happens in the launcher, so one response can read several pages of the website. Ask for the next one with page + 1 from the response (not yours) and, if filtered is true, total is an estimate. genres() returns the genres in Spanish, with their group: genre (genres), view (perspective: first person, isometric…) and setting (setting: fantasy, cyberpunk…). Each Repack carries its ids in tags, so on a page you can open the catalog filtered by its genres. Each item (Repack) carries title, version, cover (vertical cover, a thumbnail), coverFull, hero (a large screenshot; it can be missing), genres, companies, languages, originalSize, repackSize, selective, hypervisor and status ({ state, downloadId, gameId, progress }, with state = none, library, queued, downloading, paused, seeding, completed, installing, installed or error). The images already arrive as ejg-media URLs. If the game is on the Steam store, it also carries its art: capsule (the horizontal 460×215 capsule), capsuleBig (the large carousel one, 616×353) and library (the vertical 600×900). The first time, ejGames looks it up in the background and, once it has it, fires the explore-art event. The kit’s createExplore already asks for the front page and the search again. If you do not use it:
Until it arrives (or if the game is not on Steam), use cover and hero.
A download’s states: queued (waiting; pauseReason says why: queue, playing or install), downloading (checking while it checks files), paused (the user paused it), seeding and completed (ready to install), installing, installed (gameId) and error (error). Also: progress (0..1), doneBytes, totalBytes, downBps, upBps, peers and eta (seconds). Each file’s kind: setup and core are required. selective are languages and optional are extras you can leave out (selected is the proposed selection: English, the user’s language, and nothing optional). The kit has the shared logic in /_sdk/kit/store.js: createExplore (front page, search that waits while you type, pages and cached game pages), createDownloads (the queue, grouped), fileSelection (what is required cannot be removed; bytes, error, fits(free), indices()), askQuery (with a controller it opens the on-screen keyboard), repackAction (which button is due: Download, Install, Play…), downloadLabel, canInstall, isActive, genreLabel (genres arrive in English: “Open world” → “Mundo abierto”) and the formatters bytes, speed, eta, percent and sizeText (“from 18 GB” → “desde 18 GB”). The Steam theme uses all of it (themes/steam/store.js). For the catalog, createExplore has loadGenres(), browse(changes, wait) (it merges the changes with the current filters and goes back to the first page), browseMore(), toggleGenre(id) (false if there are already four), clearFilters() and similar(repack) (similar games: the ones that share its first two genres), with the state in state.catalog (filters, items, page, pages, total, filtered, loading, error) and state.genres. It also exports SORTS, SIZES, GENRE_GROUPS, MAX_GENRES, emptyFilters, filterCount and describeFilters (“Rol · Mundo abierto · Hasta 25 GB”). Inside the iframe, confirm(), alert() and window.open() do not work. Paint your own dialogs.