Initial commit
This commit is contained in:
parent
1c81513230
commit
d754678ada
5 changed files with 355 additions and 0 deletions
1
.env
Normal file
1
.env
Normal file
|
@ -0,0 +1 @@
|
|||
API_KEY=bc8ce846-6647-4f5c-bf9d-e299a5e429ee
|
12
Cargo.toml
Normal file
12
Cargo.toml
Normal file
|
@ -0,0 +1,12 @@
|
|||
[package]
|
||||
name = "embray-vanguard"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
axum = "0.7.9"
|
||||
dotenv = "0.15.0"
|
||||
reqwest = { version = "0.12.9", features = ["json"] }
|
||||
serde_json = "1.0.133"
|
||||
tokio = { version = "1", features = ["full"] }
|
||||
tower-http = { version = "0.6.2", features = ["fs"] }
|
46
src/main.rs
Normal file
46
src/main.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use serde_json::{Value, from_str};
|
||||
use reqwest::header::{HeaderMap, HeaderValue};
|
||||
use std::error::Error;
|
||||
use dotenv::dotenv;
|
||||
use axum::{
|
||||
routing::{get, post},
|
||||
Router,
|
||||
};
|
||||
use tower_http::services::ServeDir;
|
||||
|
||||
async fn get_data() -> Result<Value, Box<dyn Error>> {
|
||||
dotenv().ok();
|
||||
let url = "https://api.hypixel.net/v2/skyblock/profile?profile=7c52c237-12ed-448c-9c35-e63daf4d9db7";
|
||||
|
||||
let mut headers = HeaderMap::new();
|
||||
headers.insert("api-key", HeaderValue::from_str(&std::env::var("API_KEY").expect("API KEY not found"))?);
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let response = client.get(url)
|
||||
.headers(headers) // Attach the headers
|
||||
.send()
|
||||
.await?;
|
||||
let response_text = response.text().await?;
|
||||
let v: Value = from_str(&response_text).unwrap();
|
||||
|
||||
Ok(v)
|
||||
|
||||
}
|
||||
|
||||
async fn return_data() -> String {
|
||||
let v: Value = get_data().await.unwrap();
|
||||
v["profile"]["members"]["933ea6ed49d346398ad6fb0c26fe077d"]["glacite_player_data"]["corpses_looted"]["vanguard"].to_string()
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let app = Router::new()
|
||||
.route("/vanguards", post(return_data().await))
|
||||
.nest_service("/", ServeDir::new("static"));
|
||||
|
||||
let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||
axum::serve(listener, app).await.unwrap();
|
||||
|
||||
//let v: Value = get_data().await.unwrap();
|
||||
//println!("{}", v["profile"]["members"]["933ea6ed49d346398ad6fb0c26fe077d"]["glacite_player_data"]["corpses_looted"]["vanguard"]);
|
||||
}
|
57
static/index.html
Normal file
57
static/index.html
Normal file
|
@ -0,0 +1,57 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Vanguards</title>
|
||||
</head>
|
||||
<style>
|
||||
@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:ital,wght@0,700;1,700&display=swap');
|
||||
:root {
|
||||
background-color: black;
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
text-align: center;
|
||||
font-family: 'JetBrains Mono', monospace;
|
||||
color: white;
|
||||
}
|
||||
.container h1 {
|
||||
font-size: 8rem;
|
||||
margin: 0;
|
||||
}
|
||||
.container h2 {
|
||||
font-size: 5rem;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
async function updateVanguardCount() {
|
||||
try {
|
||||
const response = await fetch('http://localhost:3000/vanguards', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-type": "application/json; charset=UTF-8"
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
document.getElementById('vanguard-count').textContent = `${data} Vanguards`;
|
||||
} catch (error) {
|
||||
console.error('Error:', error);
|
||||
}
|
||||
}
|
||||
|
||||
updateVanguardCount();
|
||||
</script>
|
||||
<body>
|
||||
<script src="./neko.js"></script>
|
||||
<div class="container">
|
||||
<h1>Embray Has</h1>
|
||||
<h2 id="vanguard-count">1 Vanguards</h2>
|
||||
<h1>And no locket!</h3>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
239
static/neko.js
Normal file
239
static/neko.js
Normal file
|
@ -0,0 +1,239 @@
|
|||
// oneko.js: https://github.com/adryd325/oneko.js
|
||||
|
||||
(function oneko() {
|
||||
const isReducedMotion =
|
||||
window.matchMedia(`(prefers-reduced-motion: reduce)`) === true ||
|
||||
window.matchMedia(`(prefers-reduced-motion: reduce)`).matches === true;
|
||||
|
||||
if (isReducedMotion) return;
|
||||
|
||||
const nekoEl = document.createElement("div");
|
||||
|
||||
let nekoPosX = 32;
|
||||
let nekoPosY = 32;
|
||||
|
||||
let mousePosX = 0;
|
||||
let mousePosY = 0;
|
||||
|
||||
let frameCount = 0;
|
||||
let idleTime = 0;
|
||||
let idleAnimation = null;
|
||||
let idleAnimationFrame = 0;
|
||||
|
||||
const nekoSpeed = 10;
|
||||
const spriteSets = {
|
||||
idle: [[-3, -3]],
|
||||
alert: [[-7, -3]],
|
||||
scratchSelf: [
|
||||
[-5, 0],
|
||||
[-6, 0],
|
||||
[-7, 0],
|
||||
],
|
||||
scratchWallN: [
|
||||
[0, 0],
|
||||
[0, -1],
|
||||
],
|
||||
scratchWallS: [
|
||||
[-7, -1],
|
||||
[-6, -2],
|
||||
],
|
||||
scratchWallE: [
|
||||
[-2, -2],
|
||||
[-2, -3],
|
||||
],
|
||||
scratchWallW: [
|
||||
[-4, 0],
|
||||
[-4, -1],
|
||||
],
|
||||
tired: [[-3, -2]],
|
||||
sleeping: [
|
||||
[-2, 0],
|
||||
[-2, -1],
|
||||
],
|
||||
N: [
|
||||
[-1, -2],
|
||||
[-1, -3],
|
||||
],
|
||||
NE: [
|
||||
[0, -2],
|
||||
[0, -3],
|
||||
],
|
||||
E: [
|
||||
[-3, 0],
|
||||
[-3, -1],
|
||||
],
|
||||
SE: [
|
||||
[-5, -1],
|
||||
[-5, -2],
|
||||
],
|
||||
S: [
|
||||
[-6, -3],
|
||||
[-7, -2],
|
||||
],
|
||||
SW: [
|
||||
[-5, -3],
|
||||
[-6, -1],
|
||||
],
|
||||
W: [
|
||||
[-4, -2],
|
||||
[-4, -3],
|
||||
],
|
||||
NW: [
|
||||
[-1, 0],
|
||||
[-1, -1],
|
||||
],
|
||||
};
|
||||
|
||||
function init() {
|
||||
nekoEl.id = "oneko";
|
||||
nekoEl.ariaHidden = true;
|
||||
nekoEl.style.width = "32px";
|
||||
nekoEl.style.height = "32px";
|
||||
nekoEl.style.position = "fixed";
|
||||
nekoEl.style.pointerEvents = "none";
|
||||
nekoEl.style.imageRendering = "pixelated";
|
||||
nekoEl.style.left = `${nekoPosX - 16}px`;
|
||||
nekoEl.style.top = `${nekoPosY - 16}px`;
|
||||
nekoEl.style.zIndex = 2147483647;
|
||||
|
||||
let nekoFile = "https://raw.githubusercontent.com/adryd325/oneko.js/main/oneko.gif";
|
||||
const curScript = document.currentScript
|
||||
if (curScript && curScript.dataset.cat) {
|
||||
nekoFile = curScript.dataset.cat
|
||||
}
|
||||
nekoEl.style.backgroundImage = `url(${nekoFile})`;
|
||||
|
||||
document.body.appendChild(nekoEl);
|
||||
|
||||
document.addEventListener("mousemove", function (event) {
|
||||
mousePosX = event.clientX;
|
||||
mousePosY = event.clientY;
|
||||
});
|
||||
|
||||
window.requestAnimationFrame(onAnimationFrame);
|
||||
}
|
||||
|
||||
let lastFrameTimestamp;
|
||||
|
||||
function onAnimationFrame(timestamp) {
|
||||
// Stops execution if the neko element is removed from DOM
|
||||
if (!nekoEl.isConnected) {
|
||||
return;
|
||||
}
|
||||
if (!lastFrameTimestamp) {
|
||||
lastFrameTimestamp = timestamp;
|
||||
}
|
||||
if (timestamp - lastFrameTimestamp > 100) {
|
||||
lastFrameTimestamp = timestamp
|
||||
frame()
|
||||
}
|
||||
window.requestAnimationFrame(onAnimationFrame);
|
||||
}
|
||||
|
||||
function setSprite(name, frame) {
|
||||
const sprite = spriteSets[name][frame % spriteSets[name].length];
|
||||
nekoEl.style.backgroundPosition = `${sprite[0] * 32}px ${sprite[1] * 32}px`;
|
||||
}
|
||||
|
||||
function resetIdleAnimation() {
|
||||
idleAnimation = null;
|
||||
idleAnimationFrame = 0;
|
||||
}
|
||||
|
||||
function idle() {
|
||||
idleTime += 1;
|
||||
|
||||
// every ~ 20 seconds
|
||||
if (
|
||||
idleTime > 10 &&
|
||||
Math.floor(Math.random() * 200) == 0 &&
|
||||
idleAnimation == null
|
||||
) {
|
||||
let avalibleIdleAnimations = ["sleeping", "scratchSelf"];
|
||||
if (nekoPosX < 32) {
|
||||
avalibleIdleAnimations.push("scratchWallW");
|
||||
}
|
||||
if (nekoPosY < 32) {
|
||||
avalibleIdleAnimations.push("scratchWallN");
|
||||
}
|
||||
if (nekoPosX > window.innerWidth - 32) {
|
||||
avalibleIdleAnimations.push("scratchWallE");
|
||||
}
|
||||
if (nekoPosY > window.innerHeight - 32) {
|
||||
avalibleIdleAnimations.push("scratchWallS");
|
||||
}
|
||||
idleAnimation =
|
||||
avalibleIdleAnimations[
|
||||
Math.floor(Math.random() * avalibleIdleAnimations.length)
|
||||
];
|
||||
}
|
||||
|
||||
switch (idleAnimation) {
|
||||
case "sleeping":
|
||||
if (idleAnimationFrame < 8) {
|
||||
setSprite("tired", 0);
|
||||
break;
|
||||
}
|
||||
setSprite("sleeping", Math.floor(idleAnimationFrame / 4));
|
||||
if (idleAnimationFrame > 192) {
|
||||
resetIdleAnimation();
|
||||
}
|
||||
break;
|
||||
case "scratchWallN":
|
||||
case "scratchWallS":
|
||||
case "scratchWallE":
|
||||
case "scratchWallW":
|
||||
case "scratchSelf":
|
||||
setSprite(idleAnimation, idleAnimationFrame);
|
||||
if (idleAnimationFrame > 9) {
|
||||
resetIdleAnimation();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setSprite("idle", 0);
|
||||
return;
|
||||
}
|
||||
idleAnimationFrame += 1;
|
||||
}
|
||||
|
||||
function frame() {
|
||||
frameCount += 1;
|
||||
const diffX = nekoPosX - mousePosX;
|
||||
const diffY = nekoPosY - mousePosY;
|
||||
const distance = Math.sqrt(diffX ** 2 + diffY ** 2);
|
||||
|
||||
if (distance < nekoSpeed || distance < 48) {
|
||||
idle();
|
||||
return;
|
||||
}
|
||||
|
||||
idleAnimation = null;
|
||||
idleAnimationFrame = 0;
|
||||
|
||||
if (idleTime > 1) {
|
||||
setSprite("alert", 0);
|
||||
// count down after being alerted before moving
|
||||
idleTime = Math.min(idleTime, 7);
|
||||
idleTime -= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
let direction;
|
||||
direction = diffY / distance > 0.5 ? "N" : "";
|
||||
direction += diffY / distance < -0.5 ? "S" : "";
|
||||
direction += diffX / distance > 0.5 ? "W" : "";
|
||||
direction += diffX / distance < -0.5 ? "E" : "";
|
||||
setSprite(direction, frameCount);
|
||||
|
||||
nekoPosX -= (diffX / distance) * nekoSpeed;
|
||||
nekoPosY -= (diffY / distance) * nekoSpeed;
|
||||
|
||||
nekoPosX = Math.min(Math.max(16, nekoPosX), window.innerWidth - 16);
|
||||
nekoPosY = Math.min(Math.max(16, nekoPosY), window.innerHeight - 16);
|
||||
|
||||
nekoEl.style.left = `${nekoPosX - 16}px`;
|
||||
nekoEl.style.top = `${nekoPosY - 16}px`;
|
||||
}
|
||||
|
||||
init();
|
||||
})();
|
Loading…
Reference in a new issue