diff --git a/homepage/html/index.html b/homepage/html/index.html index 43d19e6..97cf4bf 100644 --- a/homepage/html/index.html +++ b/homepage/html/index.html @@ -41,6 +41,9 @@ +
+
+ diff --git a/homepage/main.py b/homepage/main.py index 41cd8c1..bf404c1 100644 --- a/homepage/main.py +++ b/homepage/main.py @@ -5,6 +5,10 @@ from os.path import join as pathjoin from random import random, choice from mcrcon import MCRcon import configparser +import requests +import hashlib +import base64 +import json import re # echo -n "["; ls | xargs -I{} echo -n \"{}\",; echo "]" @@ -24,6 +28,15 @@ def index(): players = currentPlayerData() return template("html/index.html", **{"player_count": players["count"]["current"] , "max_players": players["count"]["max"], "news": news}) +@route("/getPlayerSkins") +def getPlayerSkins(): + players = currentPlayerData() + skins = [] + for p in players["players"]: + hash = fetchSkin(p["uuid"]) + skins.append(hash) + return {"skins": skins} + @route("/img/bg.png") def random_bg_image(): bg_file = choice(BG_IMAGES) @@ -63,6 +76,18 @@ def currentPlayerData(): player["players"].append({"name": name, "uuid": uuid}) return player +def fetchSkin(uuid): + profile = requests.get("https://sessionserver.mojang.com/session/minecraft/profile/{}".format(uuid)).json() + properties = profile.get("properties") + skin = list(filter(lambda x: x.get("name", "") == "textures", properties))[0] + skin_json = json.loads(base64.b64decode(skin.get("value"))) + skin_url = skin_json.get("textures").get("SKIN").get("url") + skin_req = requests.get(skin_url) + player_hash = hashlib.sha256(uuid.encode()).hexdigest() + with open('./static/img/skins/{}'.format(player_hash), 'wb') as f: + f.write(skin_req.content) + return player_hash + def parseConfig(): config = configparser.ConfigParser() config.read("config.ini") diff --git a/homepage/static/css/styles.css b/homepage/static/css/styles.css index 52cf522..bff5240 100644 --- a/homepage/static/css/styles.css +++ b/homepage/static/css/styles.css @@ -126,6 +126,17 @@ body { background-size: 80px; } +#skin_container { + position: absolute; + left: 0; + top: 0; + margin: 10px; + display: flex; + flex-flow: column wrap; + background-color: #fdfdfd45; + border: 3px solid #686767; +} + @font-face { font-family: 'minecraft'; src: URL('/fonts/Minecraft.ttf') format('truetype'); diff --git a/homepage/static/js/index.js b/homepage/static/js/index.js index cbf2ac2..38ec9fb 100644 --- a/homepage/static/js/index.js +++ b/homepage/static/js/index.js @@ -9,3 +9,47 @@ function toggleDetails(e) { } return false; } + +// Fetch a list of all online player hashes +function getSkins() { + let xhr = new XMLHttpRequest(); + xhr.open ( "GET", "getPlayerSkins", true ); + xhr.onreadystatechange = function () { + if (xhr.readyState == 4 && xhr.status == 200) { + skins = JSON.parse(xhr.responseText)["skins"]; + skins.forEach(skin_hash => addSkin(skin_hash)); + } + } + xhr.send (); +} + +// Add a new canvas to the container and render the given skin +function addSkin(hash) { + var container = document.querySelector("#skin_container"); + var canvas = document.createElement("canvas"); + container.appendChild(canvas); + canvas.id = hash; + renderSkin(hash, canvas); +} + +// Create a new instance of the renderer in the given canvas with the given hash as player skin +function renderSkin(hash, canvas) { + let skinViewer = new skinview3d.SkinViewer({ + canvas: canvas, + width: 60, + height: 80, + skin: "/img/skins/" + hash + }); + + let control = skinview3d.createOrbitControls(skinViewer); + control.enableRotate = false; + control.enableZoom = false; + control.enablePan = false; + + let walk = skinViewer.animations.add(skinview3d.WalkingAnimation); + let rotate = skinViewer.animations.add(skinview3d.RotatingAnimation); +} + +window.onload = function () { + getSkins(); +}