All checks were successful
Deploy production / deploy (push) Successful in 1m15s
- server.js wraps Bun.serve to add /ws/<channel> upgrades (same server and port) and serve the map tiles from the host mount; Dockerfile now runs bun ./server.js - ws hub (channel registry, origin check) + pubg-map channel: rooms by unguessable code, validated + rate-limited messages, per-room write queue, presence - games.pubg_rooms / pubg_matches / pubg_markers; per-match sessions with history - /trackers/games/pubg/map hub (owner: rooms, landings over time, history) and /trackers/games/pubg/map/<code> fullscreen Leaflet map (all 11 maps) - deploy-remote.sh bind-mounts ~/pubg-maps; scripts/build-pubg-tiles.py rebuilds it
42 lines
2.0 KiB
Python
42 lines
2.0 KiB
Python
#!/usr/bin/env python3
|
|
"""Build the PUBG drop map tiles from PUBG's official api-assets (github.com/pubg/api-assets,
|
|
used under the PUBG Developer API terms; © KRAFTON). Not in the repo or image (~115 MB):
|
|
the output goes to the host directory that scripts/deploy-remote.sh bind-mounts at /pubg-maps.
|
|
|
|
python3 scripts/build-pubg-tiles.py [out_dir] (default ~/pubg-maps; needs Pillow)
|
|
|
|
Each 8192 px map becomes 512 px WebP tiles, zoom 0 (whole map) to 4 (full resolution),
|
|
<out>/<map>/<z>/<x>/<y>.webp, plus a 384 px <out>/<map>/thumb.webp."""
|
|
import os, sys, tempfile, urllib.request
|
|
from multiprocessing import Pool
|
|
from PIL import Image
|
|
|
|
Image.MAX_IMAGE_PIXELS = None
|
|
T = 512
|
|
BASE = 'https://media.githubusercontent.com/media/pubg/api-assets/master/Assets/Maps'
|
|
# Keep in sync with MAPS in src/lib/pubg-map/shared.ts.
|
|
MAPS = {'erangel': 'Erangel', 'miramar': 'Miramar', 'sanhok': 'Sanhok', 'vikendi': 'Vikendi',
|
|
'taego': 'Taego', 'deston': 'Deston', 'rondo': 'Rondo', 'karakin': 'Karakin',
|
|
'paramo': 'Paramo', 'haven': 'Haven', 'camp-jackal': 'Camp_Jackal'}
|
|
OUT = os.path.expanduser(sys.argv[1] if len(sys.argv) > 1 else '~/pubg-maps')
|
|
|
|
def run(slug):
|
|
with tempfile.NamedTemporaryFile(suffix='.png') as f:
|
|
urllib.request.urlretrieve(f'{BASE}/{MAPS[slug]}_Main_High_Res.png', f.name)
|
|
src = Image.open(f.name).convert('RGB')
|
|
for z in range(4, -1, -1):
|
|
size = T * 2**z
|
|
im = src if size == src.width else src.resize((size, size), Image.LANCZOS)
|
|
for x in range(2**z):
|
|
d = f'{OUT}/{slug}/{z}/{x}'
|
|
os.makedirs(d, exist_ok=True)
|
|
for y in range(2**z):
|
|
im.crop((x*T, y*T, (x+1)*T, (y+1)*T)).save(f'{d}/{y}.webp', 'WEBP', quality=78, method=5)
|
|
src.resize((384, 384), Image.LANCZOS).save(f'{OUT}/{slug}/thumb.webp', 'WEBP', quality=75)
|
|
return slug
|
|
|
|
if __name__ == '__main__':
|
|
with Pool(4) as p:
|
|
for s in p.imap_unordered(run, list(MAPS)):
|
|
print(s, flush=True)
|