Skip to content

Instantly share code, notes, and snippets.

@FelixWolf
Last active February 25, 2023 07:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FelixWolf/4ecf188c18fee7c3dbe7ba82926ba95b to your computer and use it in GitHub Desktop.
Save FelixWolf/4ecf188c18fee7c3dbe7ba82926ba95b to your computer and use it in GitHub Desktop.
This script will take a while to run because it has to download stuff
#!/usr/bin/env python3
#Mainland(Minus Zindra): 897 982 1130 1190
#Corsica: 1082 1101 1100 1158
#Gaeta 1: 1112 1140 1130 1155
#Gaeta 5: 1081 1160 1100 1190
#Nautilus: 1050 1108 1080 1137
#Satori: 1005 1099 1047 1134
#Heterocera: 1013 991 1036 1014
#Sansara: 974 982 1012 1038
#Bellisseria: 954 1024 977 1045
#Jeogeot: 897 1004 939 1036
#Sharp: 988 1159 1002 1179
#Blake Sea: 1036 1136 1061 1157
#Mainland(Zindra + Horizons): 1179 1797 1210 1821
#Zindra: 1179 1797 1200 1821
#Horizons: 1201 1804 1210 1813
#Premium: 500 1000 926 1215
#Premium East: 907 1192 926 1215
#Premium South 1: 811 1013 828 1028
#Premium South 2: 750 1000 768 1022
#Premium South 3: 500 1000 518 1022
import argparse
from PIL import Image
import tempfile
import os
import threading
import urllib.request
import urllib.error
import struct
import time
import math
cachedir = os.path.join(tempfile.gettempdir(), "slmapcache")
mappath = "https://s3.amazonaws.com/map.secondlife.com/map-1-{x}-{y}-objects.jpg"
starttime = round(time.time())
yesterday = starttime - (60 * 60 * 24)
BOTTOM = 0
LEFT = 1
TOP = 2
RIGHT = 3
def threadedDownload(path, saveFunction, *args, **kwargs):
def thread():
try:
with urllib.request.urlopen(path) as req:
saveFunction(req, *args, **kwargs)
except urllib.error.HTTPError as req:
saveFunction(req, *args, **kwargs)
x = threading.Thread(target=thread)
x.start()
return x
def printProgressBar(value, length=40, title = " ", vmin=0.0, vmax=1.0):
"""
Text progress bar
Parameters
----------
value : float
Current value to be displayed as progress
vmin : float
Minimum value
vmax : float
Maximum value
length: int
Bar length (in character)
title: string
Text to be prepend to the bar
"""
# Block progression is 1/8
blocks = ["", "▏","▎","▍","▌","▋","▊","▉","█"]
vmin = vmin or 0.0
vmax = vmax or 1.0
lsep, rsep = "▏", "▕"
# Normalize value
value = min(max(value, vmin), vmax)
value = (value-vmin)/float(vmax-vmin)
v = value*length
x = math.floor(v) # integer part
y = v - x # fractional part
base = 0.125 # 0.125 = 1/8
prec = 3
i = int(round(base*math.floor(float(y)/base),prec)/base)
bar = "█"*x + blocks[i]
n = length-len(bar)
bar = lsep + bar + " "*n + rsep
print("\r" + title + bar + " %.1f%%" % (value*100), end = "\r")
# Print New Line on Complete
if value == 100:
print()
def processProgress(i, t, title=""):
if i == t or i > t:
printProgressBar(i/t, title=title)
elif i % round(t/1000) == 0:
printProgressBar(i/t, title=title)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('-b', '--bounds', nargs=4, type=int, default=(897, 982, 1130, 1190),
metavar=("bottom", "left", "top", "right"),
help='Bounds to render/download')
parser.add_argument('-r', '--resolution', type=int, default = 8,
help='Resolution of each tile')
parser.add_argument('-n', '--nocache', action='store_true',
help='Ignore cache')
parser.add_argument('-t', '--threads', type=int, default = 32,
help='Download threads')
parser.add_argument('file', help='Output file')
args = parser.parse_args()
bounds = args.bounds
if not os.path.exists(cachedir):
os.makedirs(cachedir)
totalTiles = (bounds[TOP] - bounds[BOTTOM] + 1) * (bounds[RIGHT] - bounds[LEFT] + 1)
imageSize = (
(bounds[RIGHT] - bounds[LEFT] + 1) * args.resolution,
(bounds[TOP] - bounds[BOTTOM] + 1) * args.resolution
)
print("Need {} tiles".format(totalTiles))
print("Destionation Resolution {}x{}".format(*imageSize))
maxThreads = args.threads
threadList = [None]*maxThreads
downloaded = 0
for y in range(bounds[BOTTOM], bounds[TOP]+2):
for x in range(bounds[LEFT], bounds[RIGHT]+2):
file = os.path.join(cachedir, "map-{x}-{y}.jpg".format(x=x, y=y))
if not args.nocache:
if os.path.isfile(file):
stat = os.stat(file)
if stat.st_mtime > yesterday:
continue
def saveFunction(req, file):
with open(file, "wb") as f:
if req.code == 200:
f.write(req.read())
else:
f.write(b"")
thread = None
while not thread:
for i in range(0, maxThreads):
if threadList[i] == None or not threadList[i].is_alive():
thread = threadedDownload(mappath.format(x=x, y=y), saveFunction, file)
threadList[i] = thread
break
downloaded += 1
processProgress(downloaded, totalTiles)
print("Download complete")
im = Image.new("RGB", imageSize, color=0x5f471d)
top = bounds[TOP] - bounds[BOTTOM]
for y in range(bounds[BOTTOM], bounds[TOP]+1):
for x in range(bounds[LEFT], bounds[RIGHT]+1):
file = os.path.join(cachedir, "map-{x}-{y}.jpg".format(x=x, y=y))
with open(file, "rb") as f:
f.seek(0, 2)
if f.tell() == 0:
continue
f.seek(0, 0)
tile = Image.open(f)\
.resize((args.resolution, args.resolution))
im.paste(tile, (
args.resolution * (x - bounds[LEFT]),
args.resolution * (top - (y - bounds[BOTTOM]))
))
im.save(args.file)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment