Add online player skin rendering to the webui

This commit is contained in:
sqozz 2021-03-25 01:27:33 +01:00
parent 1fb05934f7
commit f1dbbcbbb1
4 changed files with 83 additions and 0 deletions

View file

@ -41,6 +41,9 @@
</div>
</div>
</div>
<div id="skin_container">
</div>
<script src="/js/index.js"></script>
<script src="/js/skinview3d.bundle.js"></script>
</body>
</html>

View file

@ -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")

View file

@ -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');

View file

@ -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();
}