const buttons = document.querySelectorAll("button[frame]") const dynmapFrame = document.querySelector("article.frame.dynmap > iframe") const capesSelector = document.querySelector("article.capes > div.capes") const logsContainer = document.querySelector("div.container.logs") const playButton = document.querySelector("button.play") const logoutButton = document.querySelector("button.logout") let viewerInstance = new skinview3d.SkinViewer({ canvas: document.getElementById("skin"), width: 390, height: 490, skin: "https://yggdrasil.azures.fr/textures/texture/steve.png" }) viewerInstance.animation = new skinview3d.IdleAnimation() viewerInstance.animation.speed = 1 function wait(ms) { return new Promise(resolve => setTimeout(resolve, ms)) } function setActiveButton(frameIdentifier) { for (const button of buttons) { button.classList.remove("active") if (button.getAttribute("frame") == frameIdentifier) { button.classList.add("active") } } } function fixedTo(number, n) { const k = Math.pow(10, n) const result = (Math.round(number * k) / k) return Number.isInteger(result) ? result.toFixed(2) : result } window.getPlayer = async function getPlayer() { const result = await system.call("network::getPlayer") console.log(result) if (result.error) { console.error("Impossible de récupéré le profil") return null } return result } window.displayMinecraftHead = function displayMinecraftHead(skinUrl, targetImg) { const canvas = document.createElement("canvas") const ctx = canvas.getContext("2d") const skinImg = new Image() skinImg.crossOrigin = "anonymous" skinImg.onload = function() { canvas.width = 8 canvas.height = 8 ctx.imageSmoothingEnabled = false ctx.drawImage(skinImg, 8, 8, 8, 8, 0, 0, 8, 8) ctx.drawImage(skinImg, 40, 8, 8, 8, 0, 0, 8, 8) document.querySelector(targetImg).src = canvas.toDataURL() } skinImg.src = skinUrl } window.profile = await getPlayer() displayMinecraftHead(`https://yggdrasil.azures.fr/textures/${profile.skins.find(skin => skin.state == "ACTIVE").url.replace(/^\//, "")}`, "img.avatar") window.refreshProfile = async function refreshProfile() { window.profile = await getPlayer() } window.setting = {} window.setting.set = async function settingSet(key, value) { await system.call("settings::set", { key, value }) } window.showPage = function showPage(frameIdentifier) { showFrame(frameIdentifier) setActiveButton(frameIdentifier) } window.initDynmap = async function initDynmap() { const dynampUrl = await system.call("lentia::dynamp") || "http://azures.fr:8123/" if (dynmapFrame.src != dynampUrl) { dynmapFrame.src = dynampUrl } } window.getRamInformation = async function getRamInformation() { const $ram = await system.call("hardware::ram") ram.setAttribute("max", Math.floor($ram.freeGb * 1024)) freeRam.innerText = `${$ram.totalGb} Gb` totalRam.innerText = `${$ram.freeGb} Gb` } window.handleSettingsChanges = async function handleSettingsChanges(key, value) { const span = document.querySelector(`span#${key.includes("ram") ? "currentRam" : key}`) setting.set(key, value) if (span) { span.innerText = key.includes("ram") ? fixedTo(value / 1024, 2) + " G" : value } } window.initSettings = async function initSettings() { const settings = await system.call("settings::read") ram.value = settings.ram.max javaPath.value = settings.javaPath currentRam.innerText = fixedTo(settings.ram.max / 1024, 2) + " G" getRamInformation() } window.initSkin = async function initSkin() { const container = document.querySelector(".skinview3d") if (container.clientWidth === 0 || container.clientHeight === 0) { requestAnimationFrame(initSkin) return } const skinUrl = `https://yggdrasil.azures.fr/textures/${profile.skins.find(skin => skin.state == "ACTIVE").url.replace(/^\//, "")}` viewerInstance = new skinview3d.SkinViewer({ canvas: document.getElementById("skin"), width: container.clientWidth, height: container.clientHeight, skin: skinUrl }) displayMinecraftHead(skinUrl, "img.avatar") const activeCape = window.profile.capes.find(s => s.state === "ACTIVE") || null const capeUrl = activeCape == null ? null : `https://yggdrasil.azures.fr/textures/${activeCape.url.replace(/^\//, "")}?t=${Date.now()}` viewerInstance.animation = new skinview3d.IdleAnimation() viewerInstance.nameTag = profile.name viewerInstance.zoom = 0.7 viewerInstance.loadCape(capeUrl) const ro = new ResizeObserver(() => { viewerInstance.width = container.clientWidth viewerInstance.height = container.clientHeight }) ro.observe(container) } window.selectSkin = async function selectSkin() { const skin = await system.call("dialog::selectSkin") if (!skin.success) { return iziToast.error({ title: "Erreur", message: "Impossible d'envoyer le skin" }) } return validateSkinSelection(skin.path) } window.validateSkinSelection = async function validateSkinSelection(localPath) { const isSlim = confirm("Modèle Slim ?") const variant = isSlim ? "slim" : "classic" const result = await system.call("network::uploadSkin", { path: localPath, variant: variant }) if (result.success && viewerInstance) { await wait(500) await refreshProfile() const activeSkin = window.profile.skins.find(s => s.state === "ACTIVE") const activeCape = window.profile.capes.find(s => s.state === "ACTIVE") || null if (activeSkin) { const skinUrl = `https://yggdrasil.azures.fr/textures/${activeSkin.url.replace(/^\//, "")}?t=${Date.now()}` const capeUrl = activeCape == null ? null : `https://yggdrasil.azures.fr/textures/${activeCape.url.replace(/^\//, "")}?t=${Date.now()}` displayMinecraftHead(skinUrl, "img.avatar") await viewerInstance.loadSkin(skinUrl, { model: variant.toLowerCase() === "slim" ? "slim" : "default" }) await viewerInstance.loadCape(capeUrl) } } } window.initCapesSelector = async function initCapesSelector() { capesSelector.innerHTML = "" const blankCape = document.createElement("div") blankCape.classList.add("cape") blankCape.setAttribute("onclick", `hideCape()`) blankCape.title = "Cacher ma cape" capesSelector.appendChild(blankCape) await viewerInstance.loadCape(null) for (const cape of profile.capes) { const $cape = document.createElement("div") $cape.classList.add("cape") $cape.setAttribute("title", cape.alias) $cape.setAttribute("style", `background-image: url("https://yggdrasil.azures.fr/textures/${cape.url.replace(/^\//, "")}?t=${Date.now()}") !important;`) $cape.setAttribute("onclick", `showCape("${cape.id}")`) if (cape.state == "ACTIVE") { $cape.classList.add("active") await viewerInstance.loadCape(`https://yggdrasil.azures.fr/textures/${cape.url.replace(/^\//, "")}?t=${Date.now()}`) } capesSelector.appendChild($cape) } } window.showCape = async function showCape(id) { const result = await system.call("network::showCape", { capeId: id }) if (result.success) { await refreshProfile() await initCapesSelector() if (typeof viewerInstance !== "undefined" && window.profile) { const activeCape = window.profile.capes.find(c => c.state === "ACTIVE") if (activeCape) { const fullUrl = `https://yggdrasil.azures.fr/textures/${activeCape.url.replace(/^\//, "")}?t=${Date.now()}` await viewerInstance.loadCape(fullUrl) } } return result.data } else { alert("Erreur d'équipement : " + result.error) } } window.hideCape = async function hideCape() { const result = await system.call("network::hideCape") if (result.success) { await refreshProfile() await initCapesSelector() if (typeof viewerInstance !== "undefined") { viewerInstance.loadCape(null) } return result.data } else { alert("Erreur lors du retrait : " + result.error) } } window.changeUsername = async function changeUsername(newName) { if (!newName || newName.length < 3) return alert("Pseudo trop court !"); const result = await system.call("network::changeUsername", { username: newName }) if (result.success) { viewerInstance.nameTag = result.profile.name window.profile = result.profile } else { alert("Erreur : " + result.error) } } window.gamelog = {} window.gamelog.put = function put(log) { const logElement = document.createElement("p") logElement.innerText = log logsContainer.appendChild(logElement) } window.gamelog.clear = function clear() { logsContainer.innerHTML = "" } window.play = async function play() { gamelog.clear() showLoadingBar() playButton.setAttribute("disabled", "") logoutButton.setAttribute("disabled", "") const gameLaunch = await system.call("launcher::game") if (gameLaunch.success) { hideLoadingBar() } else { hideLoadingBar() playButton.removeAttribute("disabled") logoutButton.removeAttribute("disabled") } } window.external.receiveMessage(message => { try { const data = JSON.parse(message) switch (data.requestId) { case "game::log": const logMessage = data.payload.message if (logMessage != "GAME_CLOSED") { console.log("MC:", logMessage) gamelog.put(logMessage) logsContainer.scrollTop = logsContainer.scrollHeight } else { playButton.removeAttribute("disabled") } break; default: break; } } catch (e) { console.error("Erreur réception message Photino:", e) } }) await initSkin() await initSettings() await initCapesSelector() hideLoadingBar() showFrame("game")