This commit is contained in:
Gilles Lazures 2025-04-30 05:01:03 +02:00
parent 4b8d7f1679
commit 7789bde384
10 changed files with 417 additions and 33 deletions

View File

@ -116,10 +116,11 @@ button.classic {
border: none; border: none;
cursor: pointer; cursor: pointer;
outline: none; outline: none;
margin-left: 2%;
margin-top: 5px;
transition: .3s; transition: .3s;
margin-top: 5px;
font-weight: 900;
border-radius: 5px; border-radius: 5px;
z-index: 9;
background-color: #39aa6d; background-color: #39aa6d;
} }
@ -247,6 +248,130 @@ main > section.twitch {
right: 60px; right: 60px;
} }
input[type="range"] {
width: 100%;
border: none;
accent-color: #2E8B57;
background-color: #2E8B57;
}
input[type="range"]#audioVolume {
width: 83%;
}
input[type="text"],
input[type="password"] {
width: 90%;
border: 0px;
color: #ffffff;
outline: 0px;
height: 30px;
padding-left: 10px;
margin-top: 4px;
margin-bottom: 4px;
border-radius: 5px;
background-color: #292929;
}
main > article.loginchoice {
position: absolute;
top: 50%;
left: 50%;
width: 25%;
height: 25%;
color: #ffffff;
text-align: center;
border-radius: 10px;
padding-top: 20px;
transform: translate(-50%, -50%);
background-color: #343434;
}
main > article.loginchoice > input:nth-of-type(1) {
margin-top: 10px;
}
button {
text-align: center;
}
button.login {
width: 90%;
height: 60px;
border: none;
outline: none;
color: #ffffff;
cursor: pointer;
font-size: larger;
font-weight: 900;
border-radius: 10px;
background-color: #292929;
border: 3px #292929 solid;
transition: .23s;
margin-top: 13px;
line-height: 40px;
}
button.login:hover {
border-color: #12865c;
}
button.login > img {
width: 40px;
margin-right: 10px;
vertical-align: middle;
}
div[frame="mojang"] > p {
width: 90%;
margin-left: 5%;
text-align: left;
font-size: small;
margin-top: 4px;
margin-bottom: 4px;
}
a {
text-decoration: underline;
color: #12865c;
}
article.game {
text-align: center;
}
article.game > label {
font-size: small;
margin-top: 7px;
}
article.game > div.ranges {
display: flex;
flex-wrap: wrap;
justify-content: space-evenly;
}
article.game > div.ranges > span {
font-size: small;
}
article.game > div.ranges > input {
width: 60%;
}
div.checkboxes {
width: 100%;
text-align: left;
}
input[type="checkbox"] {
accent-color: #12865c;
}
div.checkboxes > input[type="checkbox"] {
font-size: small;
}
[hidden] { [hidden] {
display: none; display: none;
visibility: hidden; visibility: hidden;

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 795 B

BIN
app/assets/img/mojang.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -1,15 +1,20 @@
const navBar = document.querySelector("nav") const navBar = document.querySelector("nav")
const uiButton = document.querySelector("footer>section.left") const uiButtons = document.querySelector("footer>section.left")
const footer = document.querySelector("footer")
const leftSection = document.querySelector("section.left")
const audioPourcentageLabel = document.querySelector("label[for='audioVolume']")
const audio = new Audio() const audio = new Audio()
function startAudio() { function startAudio() {
audio.src = "/app/assets/audio/Golden Hill (Radio Edit).mp3" audio.src = "./assets/audio/Golden Hill (Radio Edit).mp3"
audio.loop = true audio.loop = true
audio.play()
audio.onended = () => { audio.onended = () => {
if (!audio.paused) { if (!audio.paused) {
audio.play() audio.play()
} }
} }
updateVolume(audio.volume)
} }
function muteAudio() { function muteAudio() {
@ -21,23 +26,71 @@ function unmuteAudio() {
} }
function showNavBar() { function showNavBar() {
footer.style.zIndex = "-1"
leftSection.style.zIndex = "-1"
navBar.removeAttribute("hidden") navBar.removeAttribute("hidden")
for (const button of uiButton.children) { for (const button of uiButtons.children) {
button.setAttribute("hidden", "") button.setAttribute("hidden", "")
} }
} }
function hideNavBar() { function hideNavBar() {
footer.style.zIndex = "9"
leftSection.style.zIndex = "9"
navBar.setAttribute("hidden", "") navBar.setAttribute("hidden", "")
for (const button of uiButton.children) { for (const button of uiButtons.children) {
button.removeAttribute("hidden") button.removeAttribute("hidden")
} }
} }
function toggleAudio(element) {
if (element.getAttribute("state") == 0) {
system.call("audio::mute")
element.setAttribute("state", 1)
element.children[0].classList.replace("fa-music", "fa-music-slash")
} else {
system.call("audio::unmute")
element.setAttribute("state", 0)
element.children[0].classList.replace("fa-music-slash", "fa-music")
}
}
function toggleMusic(element) {
if (element.getAttribute("state") == 0) {
system.call("audio::mute")
element.setAttribute("state", 1)
element.children[0].classList.replace("fa-pause", "fa-play")
element.children[1].innerText = "Reprendre"
} else {
system.call("audio::unmute")
element.setAttribute("state", 0)
element.children[0].classList.replace("fa-play", "fa-pause")
element.children[1].innerText = "Pause"
}
}
function updateVolume(value) {
audio.volume = value / 100
audioPourcentageLabel.innerText = `${value}%`
}
function logout() {
localStorage.removeItem("user")
document.location.href = './login.html'
}
window.onload = () => { window.onload = () => {
system.call("server::ping") system.call("server::ping")
system.call("player::profile")
startAudio()
} }
system.result("server::ping", (data) => { system.result("server::ping", (data) => {
playersStatus.innerText = `${data.players.online}/${data.players.max}` playersStatus.innerText = `${data.players.online}/${data.players.max}`
})
system.result("player::profile", (data) => {
if (!localStorage.getItem("user")) {
localStorage.setItem("user", JSON.stringify(data))
}
}) })

30
app/assets/js/login.js Normal file
View File

@ -0,0 +1,30 @@
const loginchoice = document.querySelector("main > article.loginchoice")
function selectLoginType(type) {
for (const frame of loginchoice.children) {
frame.setAttribute("hidden", "")
if (frame.getAttribute("frame") == type) {
frame.removeAttribute("hidden")
}
}
if (type == "microsoft") {
system.call(`auth::${type}`)
}
}
system.result("auth::microsoft", () => {
selectLoginType("select")
})
system.result("auth::refresh", () => {
selectLoginType("select")
})
window.onload = () => {
if (localStorage.getItem("user")) {
system.call("auth::refresh", {
user: JSON.parse(localStorage.getItem("user"))
})
selectLoginType("token")
}
}

View File

@ -27,9 +27,9 @@
</button> </button>
</summary> </summary>
<article> <article>
<p> <button class="classic" style="background-color: #aa3939; width: 100%;" onclick="logout()">
a Déconnexion
</p> </button>
</article> </article>
</details> </details>
<details> <details>
@ -41,10 +41,72 @@
</span> </span>
</button> </button>
</summary> </summary>
<article> <article class="game">
<p> <label>
a Ram alloué
</p> </label>
<div class="ranges">
<span>
0.5GB
</span>
<input type="range" name="ram" min="0" max="2048" id="ram">
<span>
MAX
</span>
</div>
<br>
<label>
Distance de rendu
</label>
<div class="ranges">
<span>
4
</span>
<input type="range" name="ram" min="4" max="32" id="renderDistance">
<span>
32
</span>
</div>
<br>
<label>
Ram alloué
</label>
<div class="ranges">
<span>
1
</span>
<input type="range" name="ram" min="1" max="4" id="guiScale">
<span>
4
</span>
</div>
<br>
<div class="checkboxes">
<div>
<input type="checkbox" name="clouds" id="clouds">
<label for="clouds">
Nuages
</label>
</div>
<div>
<input type="checkbox" name="lowGraphism" id="lowGraphism">
<label for="lowGraphism">
Graphisme bas
</label>
</div>
<div>
<input type="checkbox" name="fullbright" id="fullbright">
<label for="fullbright">
Luminsoité max
</label>
</div>
<div>
<input type="checkbox" name="sildurs_shader" id="sildurs_shader">
<label for="sildurs_shader">
Sildur's Shader
</label>
</div>
</div>
</article> </article>
</details> </details>
<details> <details>
@ -57,12 +119,20 @@
</button> </button>
</summary> </summary>
<article> <article>
<p> <div>
a <input type="range" name="audioVolume" min="0" max="100" id="audioVolume" onchange="updateVolume(this.value)">
</p> <label for="audioVolume">
100%
</label>
</div>
<button class="classic" onclick="toggleMusic(this)" state="0">
<i class="fas fa-pause"></i>
<span>
Pause
</span>
</button>
</article> </article>
</details> </details>
<button class="nav" onclick="system.openInBrowser('https://discord.com/invite/catboatandrot')"> <button class="nav" onclick="system.openInBrowser('https://discord.com/invite/catboatandrot')">
<i class="fab fa-discord"></i> <i class="fab fa-discord"></i>
<span> <span>
@ -92,7 +162,7 @@
<label for="slim">Slim (Alex)</label> <label for="slim">Slim (Alex)</label>
</div> </div>
</fieldset> </fieldset>
<button class="classic" onclick="system.call('skin::set', { variant: temp1.querySelector('input:checked').value })"> <button class="classic" onclick="system.call('skin::set', { variant: document.querySelector('fieldset').querySelector('input:checked').value })">
Choisir le fichier Choisir le fichier
</button> </button>
</article> </article>
@ -109,12 +179,6 @@
Wiki Wiki
</span> </span>
</button> </button>
<button class="nav">
<i class="fas fa-terminal"></i>
<span>
Console
</span>
</button>
</nav> </nav>
<section class="twitch"> <section class="twitch">
<webview src="https://player.twitch.tv/?channel=catboat&parent=localhost&muted=true" bo></webview> <webview src="https://player.twitch.tv/?channel=catboat&parent=localhost&muted=true" bo></webview>
@ -134,7 +198,7 @@
<button class="default" onclick="showNavBar()"> <button class="default" onclick="showNavBar()">
<i class="fas fa-cog"></i> <i class="fas fa-cog"></i>
</button> </button>
<button class="default"> <button class="default" onclick="toggleAudio(this)" state="0">
<i class="far fa-music"></i> <i class="far fa-music"></i>
</button> </button>
</section> </section>

70
app/login.html Normal file
View File

@ -0,0 +1,70 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="./assets/css/index.css">
<title>Connexion</title>
</head>
<body style="background-image: url('./assets/img/login_wallpaper.gif');">
<main>
<button class="close" onclick="system.call('window::close')">
<i class="fas fa-times"></i>
</button>
<article class="loginchoice">
<div frame="select">
<h2>
Se connecter avec
</h2>
<button class="login" onclick="selectLoginType('microsoft')">
<img src="./assets/img/microsoft.png" alt="">
<span>
Connexion via Microsoft
</span>
</button>
<button class="login" onclick="selectLoginType('mojang')">
<img src="./assets/img/mojang.png" alt="">
<span>
Connexion via Mojang
</span>
</button>
</div>
<div frame="mojang" hidden>
<input type="text" name="username" id="username" placeholder="Adresse e-mail / pseudo">
<br>
<input type="password" name="password" id="password" placeholder="Mot de passe">
<p>
Il n'est plus possible de réinitialiser le mot de passe d'un compte mojang.
</p>
<button class="classic" style="width: 90%;" onclick="system.call('auth::mojang', { username: username.value, password: password.value })">
Connexion
</button>
<button class="classic" style="width: 90%; background-color: #aa3939;" onclick="selectLoginType('select')">
Retour
</button>
</div>
<div frame="microsoft" hidden>
<h2>
Processus en cours...
</h2>
<br>
<p>
La page d'authentification microsoft est ouverte
</p>
</div>
<div frame="token" hidden>
<h2>
Connexion au compte précédant...
</h2>
<br>
<p>
Connexion via le token sauvegarder du dernier compte utilisé
</p>
</div>
</article>
<script src="./assets/js/login.js"></script>
</main>
</body>
</html>

54
main.js
View File

@ -35,7 +35,7 @@ async function createLauncherWindow() {
} }
launcherWindow.setIcon(path.join(__dirname, "app", "assets", "img", "icon.png")) launcherWindow.setIcon(path.join(__dirname, "app", "assets", "img", "icon.png"))
if (isLauncherNotBanned.success) { if (isLauncherNotBanned.success) {
launcherWindow.loadFile(path.join(__dirname, "app", "logged.html")) launcherWindow.loadFile(path.join(__dirname, "app", "login.html"))
session.defaultSession.webRequest.onBeforeRequest({ session.defaultSession.webRequest.onBeforeRequest({
urls: [ urls: [
"https://embed.twitch.tv/*channel=*" "https://embed.twitch.tv/*channel=*"
@ -160,13 +160,52 @@ ipcMain.on("call", async (event, data) => {
} }
break break
case "auth::mojang": case "auth::mojang":
auth = Authenticator.getAuth(data.args.username, data.args.password) if (data.args.trim() != "") {
auth = Authenticator.getAuth(data.args.username, data.args.password)
await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html"))
} else {
dialog.showErrorBox("Erreur", "Le mot de passe n'est pas défini. Les comptes crackés ne sont pas supporté par le launcher.")
}
break break
case "auth::msmc": case "auth::microsoft":
const authManager = new msmc.Auth("select_account") const authManager = new msmc.Auth("select_account")
const xboxManager = await authManager.launch("raw") try {
const token = await xboxManager.getMinecraft() const xboxManager = await authManager.launch("raw")
auth = token.mclc() const token = await xboxManager.getMinecraft()
auth = token.mclc()
console.log(auth)
await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html"))
} catch (error) {
console.log(error)
if (error == "error.gui.closed") {
launcherWindow.webContents.send("Response<auth::microsoft>")
}
}
break
case "auth::refresh":
const user = data.args.user
if (user.meta?.type == "msa") {
try {
const authManager = new msmc.Auth("none")
const xboxManager = await authManager.refresh(user.meta.refresh)
const minecraft = await xboxManager.getMinecraft()
auth = minecraft.mclc()
await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html"))
} catch (error) {
dialog.showErrorBox("Erreur lors de la connexion via token", error)
console.log(error)
launcherWindow.webContents.send("Response<auth::refresh>")
}
} else {
try {
auth = Authenticator.refreshAuth(user.access_token, user.client_token)
await launcherWindow.loadFile(path.join(__dirname, "app", "logged.html"))
} catch (error) {
dialog.showErrorBox("Erreur lors de la connexion via token", error)
console.log(error)
launcherWindow.webContents.send("Response<auth::refresh>")
}
}
break break
case "shell::openExternal": case "shell::openExternal":
shell.openExternal(data.args.url) shell.openExternal(data.args.url)
@ -177,5 +216,8 @@ ipcMain.on("call", async (event, data) => {
case "audio::unmute": case "audio::unmute":
launcherWindow.webContents.setAudioMuted(false) launcherWindow.webContents.setAudioMuted(false)
break break
case "player::profile":
await launcherWindow.webContents.send("Response<player::profile>", auth)
break
} }
}) })

View File

@ -6,8 +6,8 @@ async function fetchServerStatus() {
return { return {
online: json.online, online: json.online,
players: { players: {
online: json.players.online || 0, online: json.players?.online || 0,
max: json.players.max || 0 max: json.players?.max || 0
} }
} }