Compare commits
102 Commits
add-tutori
...
a2456c8b46
| Author | SHA1 | Date | |
|---|---|---|---|
| a2456c8b46 | |||
| 0952035091 | |||
|
|
9c8c02f679 | ||
|
|
3b5fdc57c0 | ||
|
|
733c63946f | ||
| fd846250ab | |||
|
|
17460772e9 | ||
|
|
9a20860072 | ||
| 8f51723a3b | |||
| 8ad2f283aa | |||
| 39f1af8b73 | |||
| 266c4cb4ea | |||
| f3df3c0000 | |||
|
|
cb78fc598b | ||
| ba7ecc1a8e | |||
| 6ea92f9383 | |||
|
|
998770bf59 | ||
| a231032555 | |||
| 3aa3731bcb | |||
| 5e80c95bfd | |||
|
|
09dc28b6da | ||
|
|
fd7cf716ca | ||
| 73bd6a5e96 | |||
| 9c02cc1f4d | |||
| de8457fe45 | |||
| bccd5eb5a0 | |||
| 53afe70b27 | |||
| 4bbdaa06a9 | |||
| f03867b9a7 | |||
| 23e10eef0f | |||
| 4c72f4f26b | |||
| 624ba7f296 | |||
|
|
d7d20e4347 | ||
|
|
43bd8f4a7c | ||
|
|
18e8627b54 | ||
|
|
0efc46c7e2 | ||
| 62fff0c0b2 | |||
|
|
86b479fb28 | ||
|
|
489402292d | ||
| b53ce04a75 | |||
| 069a9973a4 | |||
| c3410de1d7 | |||
| a23c514102 | |||
| bf8110af6c | |||
| 349f71af1c | |||
| dda37127ca | |||
| 6d210eb0ff | |||
|
|
cfede8f299 | ||
|
|
597153ed39 | ||
|
|
697e903a26 | ||
| 1433784369 | |||
| 2c63a33bda | |||
| 87265e5ccc | |||
| 75f1a6528b | |||
|
|
23f35a35c4 | ||
|
|
973f469c7b | ||
|
|
107caafc26 | ||
|
|
7f26845802 | ||
|
|
37b2e82e05 | ||
|
|
7e2ba9dbce | ||
|
|
69426da5be | ||
|
|
fd2ad65ad4 | ||
|
|
a728651cca | ||
|
|
b9e73ed7d0 | ||
| f1d55b3c99 | |||
|
|
9b49a0f81c | ||
|
|
11144043c1 | ||
|
|
e8f866ce8a | ||
|
|
e57a90feaf | ||
|
|
3aa8fea1fd | ||
|
|
95b327951c | ||
|
|
86b99b4e76 | ||
| 14b31be465 | |||
| 341e629aaf | |||
|
|
694ded4c61 | ||
| a75b5b7c09 | |||
| 9146f65455 | |||
| 254807efa6 | |||
| 36931aabb1 | |||
| 628599f019 | |||
| 0a6c61bd88 | |||
| 8bbad8b3cc | |||
| 5af6176889 | |||
| 9250dd5088 | |||
| 276e19409d | |||
| 11fa9fa126 | |||
| 17ec6023a9 | |||
| 3c7c899868 | |||
| 9cb161e470 | |||
| 7fc7c2a6eb | |||
| 2fce94d46b | |||
| 6356c9911a | |||
| 2402896fd5 | |||
| 2940304492 | |||
| 4c0a237b27 | |||
| 77b8b41afb | |||
| 163d049829 | |||
| a321b12680 | |||
| feba5a5b4a | |||
| faaf5f1852 | |||
| 18997e1384 | |||
| fdc7bb93dd |
3
.gitattributes
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
.png filter=lfs diff=lfs merge=lfs -text
|
||||
.glb filter=lfs diff=lfs merge=lfs -text
|
||||
@@ -5,10 +5,8 @@ import configureI18n from "./astro-i18n.adapter";
|
||||
import sitemap from "@astrojs/sitemap";
|
||||
|
||||
import robotsTxt from "astro-robots-txt";
|
||||
import {resolve} from "node:url";
|
||||
import path from "node:path";
|
||||
import mdx from "@astrojs/mdx";
|
||||
import pagefind from "astro-pagefind";
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
@@ -23,7 +21,6 @@ export default defineConfig({
|
||||
tailwind({
|
||||
configFile: "./tailwind.config.cjs",
|
||||
}),
|
||||
pagefind(),
|
||||
configureI18n(),
|
||||
sitemap({
|
||||
i18n: {
|
||||
|
||||
11
package.json
@@ -14,11 +14,11 @@
|
||||
"i18n:sync": "pnpm run i18n:generate:pages && pnpm run i18n:generate:types",
|
||||
"clean:dist": "rm -rf dist",
|
||||
"clean:node_modules": "rm -rf node_modules",
|
||||
"ci": "pnpm run clean:dist && pnpm install && pnpm run i18n:sync && pnpm run build"
|
||||
"ci": "pnpm install && pnpm run i18n:sync && pnpm run build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/svelte": "^6.0.2",
|
||||
"@astrojs/tailwind": "^5.1.2",
|
||||
"@astrojs/svelte": "^7.0.4",
|
||||
"@astrojs/tailwind": "^5.1.5",
|
||||
"@astropub/icons": "^0.2.0",
|
||||
"@types/color": "^4.2.0",
|
||||
"@types/node": "^22.9.3",
|
||||
@@ -41,11 +41,12 @@
|
||||
"typescript": "^5.7.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/mdx": "^3.1.9",
|
||||
"@astrojs/mdx": "^4.0.7",
|
||||
"@astrojs/sitemap": "^3.2.1",
|
||||
"@codemirror/commands": "^6.8.0",
|
||||
"@codemirror/lang-json": "^6.0.1",
|
||||
"@ddietr/codemirror-themes": "^1.4.4",
|
||||
"astro": "^4.16.14",
|
||||
"astro": "^5.1.8",
|
||||
"astro-i18n": "^2.2.4",
|
||||
"astro-pagefind": "^1.6.0",
|
||||
"astro-robots-txt": "^1.0.0",
|
||||
|
||||
9324
pnpm-lock.yaml
generated
@@ -20,6 +20,7 @@
|
||||
<script lang="ts">
|
||||
import {t} from "astro-i18n";
|
||||
import {statsRepo} from "@repo/stats.ts";
|
||||
import "@styles/table.css"
|
||||
|
||||
|
||||
interface Props {
|
||||
@@ -64,7 +65,3 @@
|
||||
<p>{error.message}</p>
|
||||
{/await}
|
||||
|
||||
<style>
|
||||
@import "../styles/table.css";
|
||||
</style>
|
||||
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{#each window(event.fights.filter(f => f.group === group), rows) as fights}
|
||||
{#each window(event.fights.filter(f => group === undefined ? true : f.group === group), rows) as fights}
|
||||
<tr>
|
||||
{#each fights as fight (fight.id)}
|
||||
<td>{Intl.DateTimeFormat(astroI18n.locale, {
|
||||
|
||||
@@ -31,8 +31,7 @@
|
||||
let error: string = $state("");
|
||||
|
||||
async function login() {
|
||||
let {tokenStore} = await import("./repo/repo.ts");
|
||||
let {authRepo} = await import("./repo/auth.ts");
|
||||
let {authV2Repo} = await import("./repo/authv2.ts");
|
||||
if (username === "" || pw === "") {
|
||||
pw = "";
|
||||
error = t("login.error");
|
||||
@@ -40,15 +39,14 @@
|
||||
}
|
||||
|
||||
try {
|
||||
let auth = await get(authRepo).login(username, pw);
|
||||
if (auth == undefined) {
|
||||
let auth = await get(authV2Repo).login(username, pw);
|
||||
if (!auth) {
|
||||
pw = "";
|
||||
error = t("login.error");
|
||||
return;
|
||||
}
|
||||
|
||||
tokenStore.set(auth);
|
||||
navigate(l("/dashboard"));
|
||||
await navigate(l("/dashboard"));
|
||||
} catch (e: any) {
|
||||
pw = "";
|
||||
error = t("login.error");
|
||||
@@ -75,9 +73,7 @@
|
||||
|
||||
<style lang="postcss">
|
||||
input {
|
||||
@apply border-2 rounded-md p-2 shadow-2xl w-80
|
||||
dark:bg-neutral-800
|
||||
focus:outline-none focus:ring-2 focus:ring-neutral-500 focus:border-transparent;
|
||||
@apply border-2 rounded-md p-2 shadow-2xl w-80 dark:bg-neutral-800 focus:outline-none focus:ring-2 focus:ring-neutral-500 focus:border-transparent text-black;
|
||||
}
|
||||
|
||||
label {
|
||||
|
||||
@@ -18,133 +18,94 @@
|
||||
-->
|
||||
|
||||
<script lang="ts">
|
||||
import "../styles/button.css";
|
||||
import { CaretDownOutline, SearchOutline } from "flowbite-svelte-icons";
|
||||
import { t } from "astro-i18n";
|
||||
import { l } from "../util/util";
|
||||
import { onMount } from "svelte";
|
||||
import { loggedIn } from "@repo/authv2.ts";
|
||||
import "../styles/button.css";
|
||||
import {CaretDownOutline, SearchOutline} from "flowbite-svelte-icons";
|
||||
import {t} from "astro-i18n";
|
||||
import {l} from "../util/util";
|
||||
import {onMount} from "svelte";
|
||||
import {loggedIn} from "@repo/authv2.ts";
|
||||
interface Props {
|
||||
logo?: import("svelte").Snippet;
|
||||
logo?: import('svelte').Snippet;
|
||||
}
|
||||
|
||||
let { logo }: Props = $props();
|
||||
|
||||
let navbar = $state<HTMLDivElement>();
|
||||
let searchOpen = $state(false);
|
||||
let navbar = $state<HTMLDivElement>();
|
||||
let searchOpen = $state(false);
|
||||
|
||||
let accountBtn = $state<HTMLAnchorElement>();
|
||||
let accountBtn = $state<HTMLAnchorElement>();
|
||||
|
||||
$effect(() => {
|
||||
if ($loggedIn) {
|
||||
accountBtn!.href = l("/dashboard");
|
||||
} else {
|
||||
accountBtn!.href = l("/login");
|
||||
$effect(() => {
|
||||
if ($loggedIn) {
|
||||
accountBtn!.href = l("/dashboard");
|
||||
} else {
|
||||
accountBtn!.href = l("/login");
|
||||
}
|
||||
})
|
||||
|
||||
onMount(() => {
|
||||
handleScroll();
|
||||
})
|
||||
|
||||
function handleScroll() {
|
||||
if (window.scrollY > 0) {
|
||||
navbar!.classList.add("before:scale-y-100");
|
||||
} else {
|
||||
navbar!.classList.remove("before:scale-y-100");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
handleScroll();
|
||||
});
|
||||
|
||||
function handleScroll() {
|
||||
if (window.scrollY > 0) {
|
||||
navbar!.classList.add("before:scale-y-100");
|
||||
} else {
|
||||
navbar!.classList.remove("before:scale-y-100");
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<svelte:window onscroll={handleScroll} />
|
||||
<svelte:window onscroll={handleScroll}/>
|
||||
|
||||
<nav
|
||||
data-pagefind-ignore
|
||||
class="fixed top-0 left-0 right-0 sm:px-4 py-1 transition-colors z-10 flex justify-center before:backdrop-blur before:shadow-2xl before:absolute before:top-0 before:left-0 before:bottom-0 before:right-0 before:-z-10 before:scale-y-0 before:transition-transform before:origin-top"
|
||||
bind:this={navbar}
|
||||
>
|
||||
<div
|
||||
class="flex flex-row items-center justify-evenly md:justify-between match"
|
||||
>
|
||||
<a class="flex items-center" href={l("/")}>
|
||||
{@render logo?.()}
|
||||
<span
|
||||
class="text-2xl uppercase font-bold dark:text-white hidden md:inline-block"
|
||||
>
|
||||
{t("navbar.title")}
|
||||
<span
|
||||
class="before:scale-y-100"
|
||||
style="display: none"
|
||||
aria-hidden="true"
|
||||
></span>
|
||||
</span>
|
||||
</a>
|
||||
<div class="flex justify-center flex-wrap">
|
||||
<div class="btn-dropdown">
|
||||
<button class="btn btn-gray">
|
||||
<a href={l("/")}>
|
||||
<span class="btn__text">{t("navbar.links.home.title")}</span>
|
||||
</a>
|
||||
<CaretDownOutline class="ml-2 mt-auto" />
|
||||
</button>
|
||||
<div>
|
||||
<a class="btn btn-gray" href={l("/announcements")}
|
||||
>{t("navbar.links.home.announcements")}</a
|
||||
>
|
||||
<a class="btn btn-gray" href={l("/downloads")}
|
||||
>{t("navbar.links.home.downloads")}</a
|
||||
>
|
||||
<a class="btn btn-gray" href={l("/tutorials")}
|
||||
>{t("navbar.links.home.tutorials")}</a
|
||||
>
|
||||
<a class="btn btn-gray" href={l("/faq")}
|
||||
>{t("navbar.links.home.faq")}</a
|
||||
>
|
||||
<a class="btn btn-gray" href={l("/code-of-conduct")}
|
||||
>{t("navbar.links.rules.coc")}</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-dropdown">
|
||||
<button class="btn btn-gray">
|
||||
<a rel="prefetch" href={l("/rules")}>
|
||||
<span class="btn__text">{t("navbar.links.rules.title")}</span>
|
||||
</a>
|
||||
<CaretDownOutline class="ml-2 mt-auto" />
|
||||
</button>
|
||||
<div>
|
||||
<a href={l("/rules/wargear")} class="btn btn-gray"
|
||||
>{t("navbar.links.rules.wg")}</a
|
||||
>
|
||||
<a href={l("/rules/miniwargear")} class="btn btn-gray"
|
||||
>{t("navbar.links.rules.mwg")}</a
|
||||
>
|
||||
<a href={l("/rules/warship")} class="btn btn-gray"
|
||||
>{t("navbar.links.rules.ws")}</a
|
||||
>
|
||||
<a href={l("/rules/airship")} class="btn btn-gray"
|
||||
>{t("navbar.links.rules.as")}</a
|
||||
>
|
||||
<a href={l("/rules/quickgear")} class="btn btn-gray"
|
||||
>{t("navbar.links.rules.qg")}</a
|
||||
>
|
||||
<h2 class="px-2 text-gray-300">{t("navbar.links.rules.rotating")}</h2>
|
||||
<a href={l("/rules/megawargear")} class="btn btn-gray"
|
||||
>{t("navbar.links.rules.megawg")}</a
|
||||
>
|
||||
<a href={l("/rules/microwargear")} class="btn btn-gray"
|
||||
>{t("navbar.links.rules.micro")}</a
|
||||
>
|
||||
<a href={l("/rules/streetfight")} class="btn btn-gray"
|
||||
>{t("navbar.links.rules.sf")}</a
|
||||
>
|
||||
<h2 class="px-2 text-gray-300">{t("navbar.links.rules.ranked")}</h2>
|
||||
<a href={l("/rangliste/missilewars")} class="btn btn-gray"
|
||||
>{t("navbar.links.ranked.mw")}</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<!-- TODO: Add help center
|
||||
<nav data-pagefind-ignore class="fixed top-0 left-0 right-0 sm:px-4 py-1 transition-colors z-10 flex justify-center before:backdrop-blur before:shadow-2xl before:absolute before:top-0 before:left-0 before:bottom-0 before:right-0 before:-z-10 before:scale-y-0 before:transition-transform before:origin-top" bind:this={navbar}>
|
||||
<div class="flex flex-row items-center justify-evenly md:justify-between match">
|
||||
<a class="flex items-center" href={l("/")}>
|
||||
{@render logo?.()}
|
||||
<span class="text-2xl uppercase font-bold dark:text-white hidden md:inline-block">
|
||||
{t("navbar.title")}
|
||||
<span class="before:scale-y-100" style="display: none" aria-hidden="true"></span>
|
||||
</span>
|
||||
</a>
|
||||
<div class="flex justify-center flex-wrap">
|
||||
<div class="btn-dropdown">
|
||||
<button class="btn btn-gray">
|
||||
<a href={l("/")}>
|
||||
<span class="btn__text">{t("navbar.links.home.title")}</span>
|
||||
</a>
|
||||
<CaretDownOutline class="ml-2 mt-auto"/>
|
||||
</button>
|
||||
<div>
|
||||
<a class="btn btn-gray" href={l("/announcements")}>{t("navbar.links.home.announcements")}</a>
|
||||
<a class="btn btn-gray" href={l("/downloads")}>{t("navbar.links.home.downloads")}</a>
|
||||
<a class="btn btn-gray" href={l("/faq")}>{t("navbar.links.home.faq")}</a>
|
||||
<a class="btn btn-gray" href={l("/code-of-conduct")}>{t("navbar.links.rules.coc")}</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-dropdown">
|
||||
<button class="btn btn-gray">
|
||||
<a rel="prefetch" href={l("/rules")}>
|
||||
<span class="btn__text">{t("navbar.links.rules.title")}</span>
|
||||
</a>
|
||||
<CaretDownOutline class="ml-2 mt-auto"/>
|
||||
</button>
|
||||
<div>
|
||||
<a href={l("/rules/wargear")} class="btn btn-gray">{t("navbar.links.rules.wg")}</a>
|
||||
<a href={l("/rules/miniwargear")} class="btn btn-gray">{t("navbar.links.rules.mwg")}</a>
|
||||
<a href={l("/rules/warship")} class="btn btn-gray">{t("navbar.links.rules.ws")}</a>
|
||||
<a href={l("/rules/airship")} class="btn btn-gray">{t("navbar.links.rules.as")}</a>
|
||||
<a href={l("/rules/quickgear")} class="btn btn-gray">{t("navbar.links.rules.qg")}</a>
|
||||
<h2 class="px-2 text-gray-300">{t("navbar.links.rules.rotating")}</h2>
|
||||
<a href={l("/rules/megawargear")}
|
||||
class="btn btn-gray">{t("navbar.links.rules.megawg")}</a>
|
||||
<a href={l("/rules/microwargear")}
|
||||
class="btn btn-gray">{t("navbar.links.rules.micro")}</a>
|
||||
<a href={l("/rules/streetfight")} class="btn btn-gray">{t("navbar.links.rules.sf")}</a>
|
||||
<h2 class="px-2 text-gray-300">{t("navbar.links.rules.ranked")}</h2>
|
||||
<a href={l("/rangliste/missilewars")} class="btn btn-gray">{t("navbar.links.ranked.mw")}</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- TODO: Add help center
|
||||
<div class="btn-dropdown my-1">
|
||||
<div class="btn btn-gray" tabindex="1">
|
||||
<a rel="prefetch">
|
||||
@@ -158,26 +119,26 @@
|
||||
</div>
|
||||
</div>
|
||||
-->
|
||||
<a class="btn" href={l("/login")} bind:this={accountBtn}>
|
||||
<span class="btn__text">{t("navbar.links.account")}</span>
|
||||
</a>
|
||||
<!--
|
||||
<a class="btn" href={l("/login")} bind:this={accountBtn}>
|
||||
<span class="btn__text">{t("navbar.links.account")}</span>
|
||||
</a>
|
||||
<!--
|
||||
<button class="btn my-1" onclick={() => searchOpen = true}>
|
||||
<SearchOutline ariaLabel="Site Search" class="inline-block h-6"/>
|
||||
</button>
|
||||
-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{#if searchOpen}
|
||||
{#await import("./SearchComponent.svelte") then c}
|
||||
<c.default bind:open={searchOpen} />
|
||||
{/await}
|
||||
{#await import("./SearchComponent.svelte") then c}
|
||||
<c.default bind:open={searchOpen} />
|
||||
{/await}
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
.match {
|
||||
width: min(100vw, 70em);
|
||||
}
|
||||
</style>
|
||||
.match {
|
||||
width: min(100vw, 70em);
|
||||
}
|
||||
</style>
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
import {CollectionEntry} from "astro:content";
|
||||
import type {CollectionEntry} from "astro:content";
|
||||
import {l} from "../util/util";
|
||||
import {astroI18n} from "astro-i18n";
|
||||
import {Image} from "astro:assets";
|
||||
|
||||
@@ -22,38 +22,40 @@
|
||||
import wrap from "svelte-spa-router/wrap";
|
||||
import Router, {replace} from "svelte-spa-router";
|
||||
import {get} from "svelte/store";
|
||||
import {tokenStore} from "@repo/repo";
|
||||
import {loggedIn} from "@repo/authv2.ts";
|
||||
|
||||
const routes: RouteDefinition = {
|
||||
"/": wrap({asyncComponent: () => import("./pages/Home.svelte"), conditions: detail => get(tokenStore) != ""}),
|
||||
"/": wrap({asyncComponent: () => import("./pages/Home.svelte"), conditions: detail => get(loggedIn)}),
|
||||
"/perms": wrap({
|
||||
asyncComponent: () => import("./pages/Perms.svelte"),
|
||||
conditions: detail => get(tokenStore) != ""
|
||||
conditions: detail => get(loggedIn)
|
||||
}),
|
||||
"/login": wrap({
|
||||
asyncComponent: () => import("./pages/Login.svelte"),
|
||||
conditions: detail => get(tokenStore) == ""
|
||||
conditions: detail => !get(loggedIn)
|
||||
}),
|
||||
"/event/:id": wrap({
|
||||
asyncComponent: () => import("./pages/Event.svelte"),
|
||||
conditions: detail => get(tokenStore) != ""
|
||||
conditions: detail => get(loggedIn)
|
||||
}),
|
||||
"/event/:id/generate": wrap({
|
||||
asyncComponent: () => import("./pages/Generate.svelte"),
|
||||
conditions: detail => get(tokenStore) != ""
|
||||
conditions: detail => get(loggedIn)
|
||||
}),
|
||||
"/edit": wrap({
|
||||
asyncComponent: () => import("./pages/Edit.svelte"),
|
||||
conditions: detail => get(tokenStore) != ""
|
||||
conditions: detail => get(loggedIn)
|
||||
}),
|
||||
"/display/:event": wrap({
|
||||
asyncComponent: () => import("./pages/Display.svelte"),
|
||||
conditions: detail => get(tokenStore) != ""
|
||||
conditions: detail => get(loggedIn)
|
||||
}),
|
||||
"*": wrap({asyncComponent: () => import("./pages/NotFound.svelte")})
|
||||
};
|
||||
|
||||
function conditionsFailed(event: ConditionsFailedEvent) {
|
||||
console.log(event)
|
||||
|
||||
if (event.detail.location === "/login") {
|
||||
replace("/");
|
||||
} else {
|
||||
|
||||
@@ -168,11 +168,11 @@
|
||||
</div>
|
||||
<div>
|
||||
{#if selectedBranch !== "master"}
|
||||
<Button onclick={createFile} color="alternative" disabled={!selectedPath}>Create File
|
||||
<Button onclick={() => createFile()} color="alternative" disabled={!selectedPath}>Create File
|
||||
</Button>
|
||||
<Button onclick={() => deleteBranch(false)} color="none">Delete Branch</Button>
|
||||
{:else}
|
||||
<Button onclick={createBranch}>Create Branch</Button>
|
||||
<Button onclick={() => createBranch()}>Create Branch</Button>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
let request = getRequest();
|
||||
|
||||
function getRequest() {
|
||||
return $statsRepo.getUserStats(user.id)
|
||||
return $statsRepo.getUserStats(user.uuid)
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -46,5 +46,4 @@
|
||||
{#if user.perms.includes("CHECK")}
|
||||
<p>{t("dashboard.stats.checked", {checked: data.acceptedSchematics})}</p>
|
||||
{/if}
|
||||
{:catch error}
|
||||
{/await}
|
||||
@@ -50,19 +50,20 @@
|
||||
// @ts-ignore
|
||||
let b64 = btoa(String.fromCharCode.apply(null, new Uint8Array(content)));
|
||||
|
||||
await $schemRepo.uploadSchematic(name, b64);
|
||||
let response = await $schemRepo.uploadSchematic(name, b64);
|
||||
|
||||
open = false;
|
||||
uploadFile = null;
|
||||
value = "";
|
||||
dispatch("reset")
|
||||
}
|
||||
|
||||
let uploadFile: FileList | null = $state(null);
|
||||
let value = $state("");
|
||||
</script>
|
||||
|
||||
<SWModal title={t("dashboard.schematic.title")} bind:open>
|
||||
<form>
|
||||
<input type="file" bind:files={uploadFile} />
|
||||
<input type="file" bind:files={uploadFile} bind:value />
|
||||
</form>
|
||||
{#snippet footer()}
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
import type {Player} from "@type/data.ts";
|
||||
import {l} from "@utils/util.ts";
|
||||
import Statistics from "./Statistics.svelte";
|
||||
import {authRepo} from "@repo/auth.ts";
|
||||
import {tokenStore} from "@repo/repo.ts";
|
||||
import {authV2Repo} from "@repo/authv2.ts";
|
||||
import Card from "@components/Card.svelte";
|
||||
import {navigate} from "astro:transitions/client";
|
||||
|
||||
interface Props {
|
||||
user: Player;
|
||||
@@ -33,9 +33,8 @@
|
||||
let { user }: Props = $props();
|
||||
|
||||
async function logout() {
|
||||
await $authRepo.logout()
|
||||
tokenStore.set("")
|
||||
window.location.href = l("/login")
|
||||
await $authV2Repo.logout();
|
||||
await navigate(l("/login"));
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -56,7 +55,7 @@
|
||||
</div>
|
||||
<div>
|
||||
<h1 class="text-4xl font-bold">{t("dashboard.title", {name: user.name})}</h1>
|
||||
<p>{t("dashboard.rank", {rank: t("home.prefix." + user.prefix)})}</p>
|
||||
<p>{t("dashboard.rank", {rank: t("home.prefix." + (user.prefix || "User"))})}</p>
|
||||
<Statistics {user} />
|
||||
</div>
|
||||
</div>
|
||||
@@ -22,7 +22,7 @@
|
||||
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
|
||||
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
|
||||
import {onDestroy, onMount} from "svelte";
|
||||
import { CollectionEntry } from "astro:content";
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
|
||||
interface Props {
|
||||
pub: CollectionEntry<"publics">;
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2023 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {fetchWithToken, tokenStore} from "./repo.ts";
|
||||
import {derived} from "svelte/store";
|
||||
|
||||
export class AuthRepo {
|
||||
constructor(private token: string) {
|
||||
}
|
||||
|
||||
public async login(username: string, password: string): Promise<string> {
|
||||
return await fetchWithToken(this.token, "/auth/login", {
|
||||
body: JSON.stringify({
|
||||
username,
|
||||
password,
|
||||
}),
|
||||
method: "POST",
|
||||
}).then(value => value.json()).then(value => value.token);
|
||||
}
|
||||
|
||||
public async logout(): Promise<void> {
|
||||
await fetchWithToken(this.token, "/auth/tokens/logout", {
|
||||
method: "POST",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const authRepo = derived(tokenStore, ($token) => new AuthRepo($token));
|
||||
184
src/components/repo/authv2.ts
Normal file
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {readable, writable} from "svelte/store";
|
||||
import dayjs, {type Dayjs} from "dayjs";
|
||||
import {type AuthToken, AuthTokenSchema} from "@type/auth.ts";
|
||||
|
||||
export class AuthV2Repo {
|
||||
private accessToken: string | undefined;
|
||||
private accessTokenExpires: Dayjs | undefined;
|
||||
private refreshToken: string | undefined;
|
||||
private refreshTokenExpires: Dayjs | undefined;
|
||||
|
||||
constructor() {
|
||||
if (typeof localStorage === "undefined") {
|
||||
return;
|
||||
}
|
||||
|
||||
this.accessToken = localStorage.getItem("sw-access-token") ?? undefined;
|
||||
if (this.accessToken) {
|
||||
this.accessTokenExpires = dayjs(localStorage.getItem("sw-access-token-expires") ?? "");
|
||||
}
|
||||
|
||||
this.refreshToken = localStorage.getItem("sw-refresh-token") ?? undefined;
|
||||
if (this.refreshToken) {
|
||||
loggedIn.set(true);
|
||||
this.refreshTokenExpires = dayjs(localStorage.getItem("sw-refresh-token-expires") ?? "");
|
||||
}
|
||||
}
|
||||
|
||||
async login(name: string, password: string) {
|
||||
if (this.accessToken !== undefined || this.refreshToken !== undefined) {
|
||||
throw new Error("Already logged in");
|
||||
}
|
||||
|
||||
try {
|
||||
const login = await this.request("/auth", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
name,
|
||||
password,
|
||||
keepLoggedIn: true,
|
||||
}),
|
||||
}).then(value => value.json()).then(value => AuthTokenSchema.parse(value));
|
||||
|
||||
this.setLoginState(login);
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
async logout() {
|
||||
if (this.accessToken === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
await this.request("/auth", {
|
||||
method: "DELETE",
|
||||
});
|
||||
|
||||
this.resetAccessToken();
|
||||
this.resetRefreshToken();
|
||||
}
|
||||
|
||||
private setLoginState(tokens: AuthToken) {
|
||||
this.setAccessToken(tokens.accessToken.token, dayjs(tokens.accessToken.expires));
|
||||
this.setRefreshToken(tokens.refreshToken.token, dayjs(tokens.refreshToken.expires));
|
||||
loggedIn.set(true);
|
||||
}
|
||||
|
||||
private setAccessToken(token: string, expires: Dayjs) {
|
||||
this.accessToken = token;
|
||||
this.accessTokenExpires = expires;
|
||||
localStorage.setItem("sw-access-token", token);
|
||||
localStorage.setItem("sw-access-token-expires", expires.toString());
|
||||
}
|
||||
|
||||
private resetAccessToken() {
|
||||
if (this.accessToken === undefined) {
|
||||
return;
|
||||
}
|
||||
this.accessToken = undefined;
|
||||
this.accessTokenExpires = undefined;
|
||||
localStorage.removeItem("sw-access-token");
|
||||
localStorage.removeItem("sw-access-token-expires");
|
||||
}
|
||||
|
||||
private setRefreshToken(token: string, expires: Dayjs) {
|
||||
this.refreshToken = token;
|
||||
this.refreshTokenExpires = expires;
|
||||
localStorage.setItem("sw-refresh-token", token);
|
||||
localStorage.setItem("sw-refresh-token-expires", expires.toString());
|
||||
}
|
||||
|
||||
private resetRefreshToken() {
|
||||
if (this.refreshToken === undefined) {
|
||||
return;
|
||||
}
|
||||
this.refreshToken = undefined;
|
||||
this.refreshTokenExpires = undefined;
|
||||
localStorage.removeItem("sw-refresh-token");
|
||||
localStorage.removeItem("sw-refresh-token-expires");
|
||||
|
||||
loggedIn.set(false);
|
||||
}
|
||||
|
||||
private async refresh() {
|
||||
if (this.refreshToken === undefined || this.refreshTokenExpires === undefined || this.refreshTokenExpires.isBefore(dayjs().add(10, "seconds"))) {
|
||||
this.resetRefreshToken();
|
||||
this.resetAccessToken();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const response = await this.requestWithToken(this.refreshToken!, "/auth", {
|
||||
method: "PUT",
|
||||
}).then(value => {
|
||||
if (value.status === 401) {
|
||||
this.resetRefreshToken();
|
||||
this.resetAccessToken();
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return value.json();
|
||||
}).then(value => AuthTokenSchema.parse(value));
|
||||
|
||||
this.setLoginState(response);
|
||||
}
|
||||
|
||||
async request(url: string, params: RequestInit = {}, retryCount: number = 0) {
|
||||
if (this.accessToken !== undefined && this.accessTokenExpires !== undefined && this.accessTokenExpires.isBefore(dayjs().add(10, "seconds"))) {
|
||||
await this.refresh();
|
||||
}
|
||||
|
||||
return this.requestWithToken(this.accessToken ?? "", url, params, retryCount);
|
||||
}
|
||||
|
||||
private async requestWithToken(token: string, url: string, params: RequestInit = {}, retryCount: number = 0): Promise<Response> {
|
||||
if (retryCount >= 3) {
|
||||
throw new Error("Too many retries");
|
||||
}
|
||||
|
||||
return fetch(`${import.meta.env.PUBLIC_API_SERVER}${url}`, {...params,
|
||||
headers: {
|
||||
...(token !== "" ? {"Authorization": "Bearer " + (token)} : {}),
|
||||
"Content-Type": "application/json", ...params.headers,
|
||||
},
|
||||
})
|
||||
.then(async value => {
|
||||
if (value.status === 401 && url !== "/auth") {
|
||||
try {
|
||||
await this.refresh();
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
} catch (_e) { /* empty */ }
|
||||
|
||||
return this.request(url, params, retryCount + 1);
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const loggedIn = writable(false);
|
||||
|
||||
export const authV2Repo = readable(new AuthV2Repo());
|
||||
@@ -17,31 +17,9 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {writable} from "svelte/store";
|
||||
import {get, writable} from "svelte/store";
|
||||
import {authV2Repo} from "@repo/authv2.ts";
|
||||
|
||||
export const fetchWithToken = (token: string, url: string, params: RequestInit = {}) =>
|
||||
fetch(`${import.meta.env.PUBLIC_API_SERVER}${url}`, {...params,
|
||||
headers: {
|
||||
...(token !== "" ? {"Authorization": "Bearer " + (token)} : {}),
|
||||
"Content-Type": "application/json", ...params.headers,
|
||||
},
|
||||
})
|
||||
.then(value => {
|
||||
if (value.status === 401) {
|
||||
tokenStore.set("");
|
||||
}
|
||||
return value;
|
||||
});
|
||||
export const fetchWithToken = (token: string, url: string, params: RequestInit = {}) => get(authV2Repo).request(url, params);
|
||||
|
||||
export function getLocalStorage() {
|
||||
if (typeof localStorage === "undefined") {
|
||||
return {
|
||||
getItem: () => "",
|
||||
setItem: () => {},
|
||||
};
|
||||
}
|
||||
return localStorage;
|
||||
}
|
||||
|
||||
export const tokenStore = writable((getLocalStorage().getItem("sw-session") ?? ""));
|
||||
tokenStore.subscribe((value) => getLocalStorage().setItem("sw-session", value));
|
||||
export const tokenStore = writable("");
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
import {fetchWithToken, tokenStore} from "./repo.ts";
|
||||
import {type Schematic, SchematicSchema} from "@type/schem.ts";
|
||||
import {derived} from "svelte/store";
|
||||
import {ResponseErrorSchema} from "@type/data.ts";
|
||||
|
||||
export class SchematicRepo {
|
||||
constructor(private token: string) {
|
||||
@@ -40,7 +41,7 @@ export class SchematicRepo {
|
||||
name,
|
||||
content,
|
||||
}),
|
||||
});
|
||||
}).then(value => value.json()).then(SchematicSchema.or(ResponseErrorSchema).parse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ export class StatsRepo {
|
||||
}
|
||||
|
||||
public async getUserStats(id: string): Promise<UserStats> {
|
||||
return await fetchWithToken(this.token, `/stats/user/${id}`).then(value => value.json()).then(UserStatsSchema.parse);
|
||||
return await fetchWithToken(this.token, `/stats/user`).then(value => value.json()).then(UserStatsSchema.parse);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
34
src/components/types/auth.ts
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {z} from "zod";
|
||||
|
||||
export const TokenSchema = z.object({
|
||||
token: z.string(),
|
||||
expires: z.string(),
|
||||
});
|
||||
|
||||
export type Token = z.infer<typeof TokenSchema>;
|
||||
|
||||
export const AuthTokenSchema = z.object({
|
||||
accessToken: TokenSchema,
|
||||
refreshToken: TokenSchema,
|
||||
});
|
||||
|
||||
export type AuthToken = z.infer<typeof AuthTokenSchema>;
|
||||
@@ -50,3 +50,10 @@ export const ServerSchema = z.object({
|
||||
});
|
||||
|
||||
export type Server = z.infer<typeof ServerSchema>;
|
||||
|
||||
export const ResponseErrorSchema = z.object({
|
||||
error: z.string(),
|
||||
code: z.string(),
|
||||
});
|
||||
|
||||
export type ResponseError = z.infer<typeof ResponseErrorSchema>;
|
||||
|
||||
22
src/content/announcements/de/eventplan-2025.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: Eventplan 2025
|
||||
key: eventplan-2025
|
||||
description: Der Eventplan für das Jahr 2025.
|
||||
created: 2025-01-20
|
||||
tags:
|
||||
- event
|
||||
image: ../../../images/jAHRESPLAN-gro-5.png
|
||||
---
|
||||
|
||||
2025 wird ein Jahr voller spannender Events. Hier findet ihr eine Übersicht über die geplanten Events.
|
||||
|
||||
Highlights sind:
|
||||
- **WargearSeason 2025**
|
||||
- **SteamWar Arcade**
|
||||
- **WarGear mit SFA**
|
||||
- **MiniWarGear Liga**
|
||||
- **SpaceShip**
|
||||
|
||||
aber auch viele mehr.
|
||||
|
||||
Es wird auch kleinere Events geben, die nicht angekündigt sind.
|
||||
27
src/content/announcements/de/missilewars-iii-ankündigung.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
title: MissileWars III
|
||||
key: missilewarsiii
|
||||
description: Das dritte MissileWars Event steht an. Wir freuen uns auf eure Teilnahme!
|
||||
created: 2025-01-29
|
||||
tags:
|
||||
- event
|
||||
---
|
||||
|
||||
# MissileWars III
|
||||
|
||||
Ahoi SteamWar.
|
||||
Wie in unserem [***Jahresplan***](https://steamwar.de/ankuendigungen/eventplan-2025) angekündigt, findet am 23.02.2025 ein MissileWars Event statt. Wir laden auch vor allem neue und kleine Teams ein, an diesem Event teilzunehmen.
|
||||
|
||||
Hier die Details:
|
||||
- Max 3 Spieler pro Fight pro Team
|
||||
- Fights finden eventuell auf einer neuen Arena statt. Sollte diese nicht fertig werden, wird die Arena genommen, für die im [***Forenpost***](https://discord.com/channels/690530484920385586/1334228469164544030) abgestimmt wird.
|
||||
- Beginn: voraussichtlich wie gewohnt um 16 Uhr.
|
||||
|
||||
Ihr könnt euch ab jetzt mit
|
||||
- `/team event MissileWarsIII`
|
||||
- oder über unseren [***Discord-Server***](https://discord.gg/J6fENfz6Zf) in #「📣」events , sofern ihr euren Minecraft und Discord Account verknüpft habt ( #「👮」regel-infos )
|
||||
|
||||
Anmelden
|
||||
|
||||
Liebe Grüße,
|
||||
Das SteamWar Serverteam
|
||||
46
src/content/announcements/de/missilewars-iii-eventplan.md
Normal file
@@ -0,0 +1,46 @@
|
||||
---
|
||||
title: MissileWars III Eventplan
|
||||
key: missilewars3-eventplan
|
||||
description: Der Eventplan für MissileWars 3
|
||||
created: 2025-02-23
|
||||
tags:
|
||||
- event
|
||||
- missilewars
|
||||
---
|
||||
|
||||
### Infos:
|
||||
Eventleitung: TheBreadBeard
|
||||
|
||||
Fights werden nach Möglichkeit mit einer Pause von 10 Minuten vorverschoben.
|
||||
# Gruppenphase
|
||||
## Punkte aus der Gruppenphase
|
||||
|
||||
<group-table data-event="67"> </group-table>
|
||||
|
||||
### Fights
|
||||
|
||||
| Start | Teams |
|
||||
|-------|------------|
|
||||
| 16:00:00 | KT vs Borg |
|
||||
| 16:00:30 | VI vs FK |
|
||||
| 16:30:00 | FK vs KT |
|
||||
| 16:30:30 | Hlcy vs VI |
|
||||
| 17:00:00 | VI vs KT |
|
||||
| 17:00:30 | Borg vs Hlcy |
|
||||
| 17:30:00 | KT vs Hlcy|
|
||||
| 17:30:30 | FK vs Borg |
|
||||
| 18:00:00 | VI vs Borg |
|
||||
| 18:00:30 | FK vs Hlcy |
|
||||
|
||||
## KO-Phase
|
||||
|
||||
| Start | Teams |
|
||||
|-------|------------|
|
||||
| 17:50:00 | VI vs Borg |
|
||||
| 18:20:00 | Hlcy vs FK |
|
||||
| 18:22:00 | VI vs FK |
|
||||
| 18:44:00 | Hlcy vs Borg |
|
||||
|
||||
## Ergebnisse
|
||||
|
||||
<fight-table data-event="67" data-group="Gruppe 1"> </fight-table>
|
||||
105
src/content/announcements/de/wgs25-kampfplan.md
Normal file
@@ -0,0 +1,105 @@
|
||||
---
|
||||
title: WGS 2025 Kampfplan
|
||||
description: WGS 2025 Kampfplan
|
||||
key: wgs-2025-kampfplan
|
||||
created: 2025-03-01
|
||||
tags:
|
||||
- event
|
||||
- wargear
|
||||
---
|
||||
|
||||
# WGS 2025 Kampfplan
|
||||
|
||||
### Platzierung
|
||||
|
||||
| Platzierung | Team | Punkte |
|
||||
|-------------|-------------|--------|
|
||||
| 1. | Halcyon | 7 |
|
||||
| 2. | Happy-End | 6 |
|
||||
| 3. | ABYSS | 4 |
|
||||
| 4. | Borg | 3 |
|
||||
| 5. | TheNoobTeam | 1 |
|
||||
| 6. | BlackFire | 0 |
|
||||
|
||||
### Aktueller Spieltag
|
||||
|
||||
<fight-table data-event="68"></fight-table>
|
||||
|
||||
### Qualifikation
|
||||
|
||||
| 01.03.2025 | Begegnung | Ergebnis |
|
||||
|------------|--------------|----------|
|
||||
| 19:00 | HPY vs ABYS | HPY qualifiziert |
|
||||
| 19:30 | Borg vs Hlcy | Hlcy qualifiziert |
|
||||
| 20:00 | TNT vs BF | TNT qualifiziert |
|
||||
| 20:30 | ABYS vs Borg | Sieg ABYS |
|
||||
| 21:00 | Borg vs BF | Sieg Borg |
|
||||
| 21:30 | BF vs ABYS | ABYS, Borg qualifiziert |
|
||||
|
||||
PL hat sich nach der Qualifikation zurückgezogen, womit BF nachgerückt ist.
|
||||
|
||||
### 1. Spieltag
|
||||
|
||||
| 08.03.2025 | Begegnung | Ergebnis |
|
||||
|------------|--------------|----------|
|
||||
| 19:00 | ABYS vs Borg | Sieg ABYS |
|
||||
| 19:30 | Hlcy vs HPY | Sieg Hlcy |
|
||||
| 20:00 | BF vs TNT | Sieg TNT |
|
||||
| 20:30 | HPY vs ABYS | Sieg HPY |
|
||||
| 21:00 | Borg vs BF | Sieg Borg |
|
||||
| 21:30 | TNT vs Hlcy | Sieg Hlcy |
|
||||
|
||||
### 2. Spieltag
|
||||
|
||||
| 15.03.2025 | Begegnung | Ergebnis |
|
||||
|------------|--------------|----------|
|
||||
| 19:00 | HPY vs TNT | Sieg HPY |
|
||||
| 19:30 | ABYS vs BF | Sieg ABYS |
|
||||
| 20:00 | Borg vs Hlcy | Sieg Hlcy |
|
||||
| 20:30 | BF vs HPY | Sieg HPY |
|
||||
| 21:00 | TNT vs Borg | Sieg Borg |
|
||||
| 21:30 | Hlcy vs ABYS | Sieg Hlcy |
|
||||
|
||||
### 3. Spieltag
|
||||
|
||||
| 22.03.2025 | Begegnung | Ergebnis |
|
||||
|------------|-------------|----------|
|
||||
| 19:00 | ABYS vs TNT | Sieg ABYS |
|
||||
| 19:30 | Borg vs HPY | Sieg HPY |
|
||||
| 20:00 | Hlcy vs BF | Sieg Hlcy |
|
||||
| 20:30 | - | / |
|
||||
| 21:00 | - | / |
|
||||
| 21:30 | - | / |
|
||||
|
||||
### 4. Spieltag
|
||||
|
||||
| 29.03.2025 | Begegnung | Ergebnis |
|
||||
|------------|--------------|----------|
|
||||
| 19:00 | TNT vs ABYS | Sieg ABYS |
|
||||
| 19:30 | HPY vs Borg | Sieg HPY |
|
||||
| 20:00 | BF vs Hlcy | Sieg Hlcy |
|
||||
| 20:30 | Borg vs TNT | Sieg Borg |
|
||||
| 21:00 | HPY vs BF | Sieg HPY |
|
||||
| 21:30 | ABYS vs Hlcy | Sieg Hlcy |
|
||||
|
||||
### 5. Spieltag
|
||||
|
||||
| 05.04.2025 | Begegnung | Ergebnis |
|
||||
|------------|--------------|----------|
|
||||
| 19:00 | TNT vs HPY | / |
|
||||
| 19:30 | BF vs ABYS | / |
|
||||
| 20:00 | Hlcy vs Borg | / |
|
||||
| 20:30 | ABYS vs HPY | / |
|
||||
| 21:00 | BF vs Borg | / |
|
||||
| 21:30 | Hlcy vs TNT | / |
|
||||
|
||||
### 6. Spieltag
|
||||
|
||||
| 12.04.2025 | Begegnung | Ergebnis |
|
||||
|------------|--------------|----------|
|
||||
| 19:00 | Borg vs ABYS | / |
|
||||
| 19:30 | HPY vs Hlcy | / |
|
||||
| 20:00 | TNT vs BF | / |
|
||||
| 20:30 | - | / |
|
||||
| 21:00 | - | / |
|
||||
| 21:30 | - | / |
|
||||
@@ -104,14 +104,6 @@ export const publics = defineCollection({
|
||||
}),
|
||||
});
|
||||
|
||||
export const tutorials = defineCollection({
|
||||
type: "content",
|
||||
schema: z.object({
|
||||
title: z.string(),
|
||||
translationKey: z.string(),
|
||||
}),
|
||||
});
|
||||
|
||||
export const collections = {
|
||||
"pages": pages,
|
||||
"help": help,
|
||||
@@ -120,5 +112,4 @@ export const collections = {
|
||||
"downloads": downloads,
|
||||
"announcements": announcements,
|
||||
"publics": publics,
|
||||
"tutorials": tutorials
|
||||
};
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
"name": "AdvancedScripts",
|
||||
"description": "Ein Fabric-Mod, der für den BauServer von SteamWar Hotkeys für das ScriptSystem hinzufügt. Hierzu werden die einzelnen Zeichen an den Server gesendet und vom Server verarbeitet.",
|
||||
"url": {
|
||||
"1.20.1": "https://steamwar.de/AdvancedScriptsV3",
|
||||
"1.19": "https://steamwar.de/AdvancedScripts"
|
||||
"1.21.4": "https://git.steamwar.de/SteamWar/AdvancedScripts/releases/download/2.2.0/AdvancedScripts-2.2.0.jar",
|
||||
"1.20.6": "https://git.steamwar.de/SteamWar/AdvancedScripts/releases/download/2.1.0/AdvancedScripts-2.1.0.jar",
|
||||
"1.19.3": "https://git.steamwar.de/SteamWar/AdvancedScripts/releases/download/2.0.0/AdvancedScripts-2.0.0.jar",
|
||||
"Hotkey script": "https://git.steamwar.de/SteamWar/SteamWar/src/branch/main/BauSystem/hotkeys.lua"
|
||||
},
|
||||
"sourceUrl": "https://steamwar.de/devlabs/SteamWar/AdvancedScripts"
|
||||
"sourceUrl": "https://git.steamwar.de/SteamWar/AdvancedScripts"
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"name": "FabricModSender",
|
||||
"description": "Ein Fabric-Mod, der SteamWar beim Serverjoin die von dir installierten Mods sendet und es uns damit ermöglicht, sie auf schädliche Mods zu überprüfen. Eine Installation dieses Mods ermöglicht dir das Joinen von Arenen mit Fabric auf SteamWar.",
|
||||
"url": "https://steamwar.de/FabricModSender",
|
||||
"sourceUrl": "https://steamwar.de/devlabs/SteamWar/FabricModSender"
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"description": "Dieses Plugin ermöglicht die einfache Einbindung deines Servers in SteamWar. Wie du deinen (Team-)Server über SteamWar erreichbar machen kannst findest du hier.",
|
||||
"url": {
|
||||
"Info": "/teamserverintegration",
|
||||
"Download": "https://steamwar.de/SteamWarTeamserver"
|
||||
"Download": "https://git.steamwar.de/SteamWar/SteamWarTeamserverIntegration/releases/download/latest/SteamWarTeamserverIntegration.jar"
|
||||
},
|
||||
"sourceUrl": "https://steamwar.de/devlabs/SteamWar/SteamWarBungeeTeamserver"
|
||||
"sourceUrl": "https://git.steamwar.de/SteamWar/SteamWarTeamserverIntegration"
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"translationKey": "microwg",
|
||||
"main": false
|
||||
"main": false,
|
||||
"ranked": true
|
||||
}
|
||||
5
src/content/modes/missilewars.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"translationKey": "mw",
|
||||
"main": false,
|
||||
"ranked": true
|
||||
}
|
||||
BIN
src/content/pages/de/Lieutenant2.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
src/content/pages/de/STEAMIE.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/content/pages/de/STEAMIE2.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
src/content/pages/de/captain2.png
Normal file
|
After Width: | Height: | Size: 2.5 KiB |
BIN
src/content/pages/de/commander2.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
src/content/pages/de/key1.png
Normal file
|
After Width: | Height: | Size: 922 B |
BIN
src/content/pages/de/key2-2.png
Normal file
|
After Width: | Height: | Size: 1000 B |
BIN
src/content/pages/de/key3-2.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
178
src/content/pages/de/shop.md
Normal file
@@ -0,0 +1,178 @@
|
||||
---
|
||||
title: Shop
|
||||
description: Shop
|
||||
slug: shop
|
||||
slugs:
|
||||
en: shop
|
||||
---
|
||||
|
||||
# Ranks
|
||||
|
||||

|
||||
|
||||
| | |
|
||||
|:------------------------------------|:--------:|
|
||||
| 1x Monthly crate Key | GIFT |
|
||||
| Toggle night vision | PERK |
|
||||
| `/enderchest` access | PERK |
|
||||
| 4 additional homes | PERK |
|
||||
| 4 additional auction house listings | PERK |
|
||||
| extra particle slot | COSMETIC |
|
||||
|
||||
<button>Buy now for 5€</button>\
|
||||
\
|
||||
\
|
||||

|
||||
|
||||
| | |
|
||||
|:------------------------------------|:--------:|
|
||||
| 3x Monthly crate Key | GIFT |
|
||||
| Toggle night vision | PERK |
|
||||
| `/enderchest` access | PERK |
|
||||
| 6 additional homes | PERK |
|
||||
| 6 additional auction house listings | PERK |
|
||||
| 2 extra particle slot | COSMETIC |
|
||||
| 5 Minion Slots | PERK |
|
||||
| reduced Premium shop access | PERK |
|
||||
| Fireball cannon | PERK |
|
||||
| 1x monthly airstrike | PERk |
|
||||
| use chat color codes | COSMETIC |
|
||||
| `/back` access | PERK |
|
||||
| 1 invincible chunk | PERK |
|
||||
|
||||
<button>Buy now for 14,25€</button>\
|
||||
\
|
||||
\
|
||||

|
||||
|
||||
| | |
|
||||
|:-------------------------------------|:--------:|
|
||||
| 6x Monthly crate Key | GIFT |
|
||||
| Toggle night vision | PERK |
|
||||
| `/enderchest` access | PERK |
|
||||
| 10 additional homes | PERK |
|
||||
| 10 additional auction house listings | PERK |
|
||||
| 5 extra particle slot | COSMETIC |
|
||||
| 10 Minion Slots | PERK |
|
||||
| Premium shop access | PERK |
|
||||
| Fireball cannon | PERK |
|
||||
| 3x monthly airstrike | PERk |
|
||||
| use chat color codes | COSMETIC |
|
||||
| `/back` access | PERK |
|
||||
| spectate other players | PERK |
|
||||
| +27 secure clan vault slots | PERK |
|
||||
| 1x monthly 3 days raid protection | PERK |
|
||||
| 1 cannon moving create | GIFT |
|
||||
| 10% more Steamies per € | PERK |
|
||||
| 2 invincible chunk | PERK |
|
||||
| 1x Monthly invincible chunk buster | GIFT |
|
||||
| `/nick` access | PERK |
|
||||
|
||||
<button>Buy now for 27€</button>
|
||||
|
||||
# Keys
|
||||
|
||||

|
||||
|
||||
| 70% | 20% | 10% |
|
||||
|--------------------|---------------------------|----------------------|
|
||||
| Scraps Kit | Creeper Bomb | Charged Creeper Bomb |
|
||||
| Animal Crate | 3x Wither Skull | Airstrike |
|
||||
| Trench Axe | Totem of Dying | Crate 2 Key |
|
||||
| Trench Pickaxe | Legendary Trench Axe | Wither EMP |
|
||||
| Trench Shovel | Legendary Trench Pikaxe | Random Max Enchant |
|
||||
| Sell Wand | Legendary Trench Shovel | Legendary Multitool |
|
||||
| 2x Portal | Minion | colorcode Nametag |
|
||||
| Starter Weapon Kit | Legendary Helmet | Guardian Spawner |
|
||||
| 1x God Apple | Legendary Chestplate | Legendary Raid Key |
|
||||
| Shulker Box | Legendary Leggings | |
|
||||
| Random Enchant | Legendary Boots | |
|
||||
| Common Raid Key | 6x God Apples | |
|
||||
| Starter Tool Kit | 3x Throwable Creeper | |
|
||||
| 10 Steamies | Zombie Spawner | |
|
||||
| Endstone Crate | Witch Spawner | |
|
||||
| | Supercharged Auto Crafter | |
|
||||
| | Scroll of Durability | |
|
||||
| | 16x Reinforced Obsidian | |
|
||||
| | Zombie Villager Spawner | |
|
||||
| | Scroll of Binding | |
|
||||
| | Rare Raid Key | |
|
||||
|
||||
<button>Buy now for 230s</button>\
|
||||
\
|
||||
\
|
||||

|
||||
|
||||
| 20% | 40% | 30% | 10% |
|
||||
|--------------------|---------------------------|----------------------|-------------------------|
|
||||
| Scraps Kit | Creeper Bomb | Charged Creeper Bomb | Cannon Moving Crate |
|
||||
| Animal Crate | 3x Wither Skull | Airstrike | Invincible Chunk Buster |
|
||||
| Trench Axe | Totem of Dying | Crate 2 Key | Mythic Kit |
|
||||
| Trench Pickaxe | Legendary Trench Axe | Wither EMP | Mythic Raid Key |
|
||||
| Trench Shovel | Legendary Trench Pikaxe | Random Max Enchant | Wither Skeleton Spawner |
|
||||
| Sell Wand | Legendary Trench Shovel | Legendary Multitool | Blaze Spawner |
|
||||
| 2x Portal | Minion | colorcode Nametag | Captain Rank |
|
||||
| Starter Weapon Kit | Legendary Helmet | Guardian Spawner | |
|
||||
| 1x God Apple | Legendary Chestplate | Legendary Raid Key | |
|
||||
| Shulker Box | Legendary Leggings | | |
|
||||
| Random Enchant | Legendary Boots | | |
|
||||
| Common Raid Key | 6x God Apples | | |
|
||||
| Starter Tool Kit | 3x Throwable Creeper | | |
|
||||
| 10 Steamies | Zombie Spawner | | |
|
||||
| Endstone Crate | Witch Spawner | | |
|
||||
| | Supercharged Auto Crafter | | |
|
||||
| | Scroll of Durability | | |
|
||||
| | 16x Reinforced Obsidian | | |
|
||||
| | Zombie Villager Spawner | | |
|
||||
| | Scroll of Binding | | |
|
||||
| | Rare Raid Key | | |
|
||||
|
||||
<button>Buy now for 230s</button>| Common Raid Key | 6x God Apples | |
|
||||
| Starter Tool Kit | 3x Throwable Creeper | |
|
||||
| 10 Steamies | Zombie Spawner | |
|
||||
| Endstone Crate | Witch Spawner | |
|
||||
| | Supercharged Auto Crafter | |
|
||||
| | Scroll of Durability | |
|
||||
| | 16x Reinforced Obsidian | |
|
||||
| | Zombie Villager Spawner | |
|
||||
| | Scroll of Binding | |
|
||||
| | Rare Raid Key | |
|
||||
|
||||
<button>Buy now for 1173s</button>\
|
||||
\
|
||||
\
|
||||

|
||||
|
||||
| 10% | 70% | 20% |
|
||||
|---------------------------|----------------------|-------------------------|
|
||||
| Creeper Bomb | Charged Creeper Bomb | Cannon Moving Crate |
|
||||
| 3x Wither Skull | Airstrike | Invincible Chunk Buster |
|
||||
| Totem of Dying | Crate 2 Key | Mythic Kit |
|
||||
| Legendary Trench Axe | Wither EMP | Mythic Raid Key |
|
||||
| Legendary Trench Pikaxe | Random Max Enchant | Wither Skeleton Spawner |
|
||||
| Legendary Trench Shovel | Legendary Multitool | Blaze Spawner |
|
||||
| Minion | colorcode Nametag | Captain Rank |
|
||||
| Legendary Helmet | Guardian Spawner | |
|
||||
| Legendary Chestplate | Legendary Raid Key | |
|
||||
| Legendary Leggings | | |
|
||||
| Legendary Boots | | |
|
||||
| 6x God Apples | | |
|
||||
| 3x Throwable Creeper | | |
|
||||
| Zombie Spawner | | |
|
||||
| Witch Spawner | | |
|
||||
| Supercharged Auto Crafter | | |
|
||||
| Scroll of Durability | | |
|
||||
| 16x Reinforced Obsidian | | |
|
||||
| Zombie Villager Spawner | | |
|
||||
| Scroll of Binding | | |
|
||||
| Rare Raid Key | | |
|
||||
|
||||
<button>Buy now for 5869s</button>
|
||||
|
||||
# Steamies
|
||||
|
||||
 420 Steamies für 4,50€\
|
||||
\
|
||||
 4269 Steamies für 45,00€\
|
||||
\
|
||||
 42690 Steamies für 450,00€
|
||||
BIN
src/content/pages/de/steamiebag.png
Normal file
|
After Width: | Height: | Size: 943 B |
@@ -4,7 +4,7 @@ description: Verhaltensrichtlinien von SteamWar.de
|
||||
slug: verhaltensrichtlinien
|
||||
---
|
||||
|
||||
# Allgemeines Verhalten
|
||||
# 1 Allgemeines Verhalten
|
||||
|
||||
Es ist uns wichtig, dass sich unsere Spieler in einer freundlichen Umgebung befinden und sich wohlfühlen. Um dies zu gewährleisten, ist folgendes auf unserem Server nicht gestattet
|
||||
|
||||
@@ -13,39 +13,44 @@ Es ist uns wichtig, dass sich unsere Spieler in einer freundlichen Umgebung befi
|
||||
3. Unsportliches Verhalten gegenüber Neulingen, vor allem die Ausnutzung ihrer Unwissenheit
|
||||
4. Die Veröffentlichung oder Verbreitung privater Informationen anderer Spieler
|
||||
|
||||
# Chatverhalten
|
||||
# 2 Chatverhalten
|
||||
|
||||
Das Benutzen von unsichtbaren Unicode-Zeichen sowie das Verwenden von Zeichen, die über die normale Chat-Größe hinausgehen, ist verboten!
|
||||
Chatinhalte müssen auf Deutsch oder Englisch verfasst werden
|
||||
1. Das Benutzen von unsichtbaren Unicode-Zeichen sowie das Verwenden von Zeichen, die über die normale Chat-Größe hinausgehen, ist verboten!
|
||||
2. Chatinhalte müssen auf Deutsch oder Englisch verfasst werden
|
||||
|
||||
# Fairness
|
||||
# 3 Fairness
|
||||
|
||||
Um ein Faires miteinander zu ermöglichen, muss folgendes beachtet werden
|
||||
|
||||
1. Es ist verboten, unfaire Vorteile zu schaffen, die über Performance und Zooms hinausgehen. Darunter zählen Modifikationen des Spiels, Autoclicker und tools welche die Clickmenge künstlich erhöhen, Makros, Skripte oder anderweitige Applikationen, die das Spielgeschehen beeinflussen.
|
||||
2. Das Umgehen, oder der Versuch des Umgehens, von Systemen, die die Sicherheit oder Fairness gewährleisten sollen, ist strengstens untersagt.
|
||||
1. Das Verbreiten von Informationen oder Tools, die das Umgehen solcher Systeme ermöglichen, ist ebenfalls untersagt
|
||||
3. Es ist verboten, Modifikationen zu benutzen, mit denen es möglich ist, die Anordnung von Blöcken zu speichern oder diese anzeigen zu lassen. Darunter fallen u.a. Modifikationen wie World Downloader, Litematica und die Replay Mod. Letztere darf nur von Usern mit YouTube-Rang oder Mitgliedern des Serverteams, beginnend ab dem Supporter Rang, benutzt werden.
|
||||
1. Das Privileg, durch besondere Berechtigungen bestimmte Modifikationen nutzen zu können, darf nicht missbraucht werden.
|
||||
4. Es ist verboten, über Wege, die nicht durch die Unachtsamkeit eines Spielers ermöglicht wurden, den Aufbau von Redstone-Schaltungen, Winkeln und Prinzipien sowie ganzen Kanonen und Schildtechniken zu kopieren oder durch das unerlaubte Erlangen von Informationen selbst umzusetzen. Dies gilt als Techklau und wird hart bestraft.
|
||||
1. Es ist verboten, geklaute Tech oder Informationen über diese selbst zu benutzen, egal ob sie selbst geklaut wurden, durch Weitergabe oder ähnliche Methoden erlangt wurden. Dazu zählt auch der Download oder das Kopieren von Tech.
|
||||
5. Es ist strengstens verboten, Informationen zu verbreiten, die durch Regelverstöße erlangt wurden, unabhängig davon, wann diese stattgefunden haben. Fälle vor der Einführung dieser Regel werden entsprechend vermerkt. (Einführung der Regel erfolgte am 26. April 2023)
|
||||
6. Mitglieder des eigenen Teams dürfen nicht willentlich behindert werden, solange es nicht anderweitig vom Spielmodus oder Event gefordert wird.
|
||||
7. Der Missbrauch von Features, die Entities, welche du normalerweise nicht sehen könntest, sichtbar machen, ist verboten. Dazu zählen unter anderem Features, die Chunks neu laden, wie F3+A oder Shader reloads.
|
||||
3. Das Verbreiten von Informationen oder Tools, die das Umgehen solcher Systeme ermöglichen, ist ebenfalls untersagt
|
||||
4. Es ist verboten, Modifikationen zu benutzen, mit denen es möglich ist, die Anordnung von Blöcken zu speichern oder diese anzeigen zu lassen. Darunter fallen u.a. Modifikationen wie World Downloader, Litematica und die Replay Mod. Letztere darf nur von Usern mit YouTube-Rang oder Mitgliedern des Serverteams, beginnend ab dem Supporter Rang, benutzt werden.
|
||||
5. Das Privileg, durch besondere Berechtigungen bestimmte Modifikationen nutzen zu können, darf nicht missbraucht werden.
|
||||
6. Es ist verboten, über Wege, die nicht durch die Unachtsamkeit eines Spielers ermöglicht wurden, den Aufbau von Redstone-Schaltungen, Winkeln und Prinzipien sowie ganzen Kanonen und Schildtechniken zu kopieren oder durch das unerlaubte Erlangen von Informationen selbst umzusetzen. Dies gilt als Techklau und wird hart bestraft.
|
||||
7. Es ist verboten, geklaute Tech oder Informationen über diese selbst zu benutzen, egal ob sie selbst geklaut wurden, durch Weitergabe oder ähnliche Methoden erlangt wurden. Dazu zählt auch der Download oder das Kopieren von Tech.
|
||||
8. Es ist strengstens verboten, Informationen zu verbreiten, die durch Regelverstöße erlangt wurden, unabhängig davon, wann diese stattgefunden haben. Fälle vor der Einführung dieser Regel werden entsprechend vermerkt. (Einführung der Regel erfolgte am 26. April 2023)
|
||||
9. Mitglieder des eigenen Teams dürfen nicht willentlich behindert werden, solange es nicht anderweitig vom Spielmodus oder Event gefordert wird.
|
||||
10. Der Missbrauch von Features, die Entities, welche du normalerweise nicht sehen könntest, sichtbar machen, ist verboten. Dazu zählen unter anderem Features, die Chunks neu laden, wie F3+A oder Shader reloads.
|
||||
|
||||
# Serverintegrität
|
||||
|
||||
# 4 Serverintegrität
|
||||
|
||||
Um die Serversicherheit und die Zukunft unserer Community gewährleisten zu können, müssen folgende Richtlinien beachtet werden
|
||||
|
||||
1. Angriffe gegen den Server, das Benutzen von Proxyservern, Virtual Private Networks und IP-Changern, um dem Server zu schaden, sind in jeglicher Form untersagt.
|
||||
2. Das Umgehen jeglicher vom Serverteam erteilten Bestrafungen ist verboten.
|
||||
3. Es ist verboten, Spiel- und/oder Pluginfehler auszunutzen.
|
||||
1. Es ist verboten, Informationen über Pluginfehler zu verbreiten, wenn diese zu unfairen Vorteilen führen. Diese müssen zwangsläufig dem Serverteam gemeldet werden.
|
||||
4. Verhalten, welches die Integrität der Community in einem unverhältnismäßigen Maß beeinträchtigt, kann sanktioniert werden
|
||||
5. Teams, welche einen unverhältnismäßig negativen Effekt auf den Server, die Community und dessen Zukunft haben, können nach Verwarnung aufgelöst werden.
|
||||
1. Sollten von denselben Mitgliedern weiter Teams erstellt werden, welche unter diesen Paragraph fallen, können weitere Strafen folgen.
|
||||
4. Es ist verboten, Informationen über Pluginfehler zu verbreiten, wenn diese zu unfairen Vorteilen führen. Diese müssen zwangsläufig dem Serverteam gemeldet werden.
|
||||
5. Verhalten, welches die Integrität der Community in einem unverhältnismäßigen Maß beeinträchtigt, kann sanktioniert werden
|
||||
6. Teams, welche einen unverhältnismäßig negativen Effekt auf den Server, die Community und dessen Zukunft haben, können nach Verwarnung aufgelöst werden.
|
||||
7. Sollten von denselben Mitgliedern weiter Teams erstellt werden, welche unter diesen Paragraph fallen, können weitere Strafen folgen.
|
||||
8. Informationen zu potenziellem Fehlverhalten dürfen nicht als Thread oder Forumsbeitrag veröffentlicht werden. Die folgenden Unterpunkte sind die korrekten Formen, Anschuldigungen anzusprechen:
|
||||
- Weitergabe der Information/en in Form eines Tickets
|
||||
- Private Kontaktaufnahme mit der Moderation, Admiralseekrank oder einer den Vorwürfen entsprechend leitenden Instanz des Serverteams (Builderleitung/Head Devs). Diese Variante ist vor allem dafür geeignet, wenn das Fehlverhalten von einem Serverteammitglied ausgeht.
|
||||
|
||||
# Verhalten gegenüber dem Serverteam
|
||||
|
||||
# 5 Verhalten gegenüber dem Serverteam
|
||||
|
||||
1. Entscheidungen des Serverteams stehen nicht zur Diskussion.
|
||||
2. Anweisungen von Teammitgliedern sind zu befolgen, und bei Verweigerung wird bestraft!
|
||||
@@ -57,12 +62,12 @@ Um die Serversicherheit und die Zukunft unserer Community gewährleisten zu kön
|
||||
8. Griefing auf der Buildercloud ist verboten.
|
||||
9. Es ist verboten, das Serverteam zu täuschen oder dies zu versuchen. Dies betrifft insbesondere den Prüfvorgang.
|
||||
|
||||
# Werbung
|
||||
# 6 Werbung
|
||||
|
||||
1. Werbung in jeglicher Form muss vor Veröffentlichung durch die Serverleitung genehmigt werden. Ausgenommen sind hier Spieler mit dem YouTube-Rang, welche jederzeit für ihre eigenen Inhalte werben dürfen, solange diese den Server einbeziehen und das Werben in Maßen geschieht.
|
||||
2. Inhalte, die als Werbung gewertet werden könnten, dürfen außerhalb von Paragraph 6.1 nur auf ausdrücklichen Wunsch eines Spielers für diesen veröffentlicht werden. Diese Ausnahme darf nicht missbraucht werden.
|
||||
|
||||
# Richtlinien im Bezug auf Regelbrüche
|
||||
# 7 Richtlinien im Bezug auf Regelbrüche
|
||||
|
||||
Folgende Richtlinien befassen sich mit dem Verhalten um jegliche Regelbrüche
|
||||
|
||||
@@ -71,18 +76,17 @@ Folgende Richtlinien befassen sich mit dem Verhalten um jegliche Regelbrüche
|
||||
|
||||
# Handel
|
||||
|
||||
1. Jeglicher Handel, egal ob mit echter oder virtueller Ware, ist verboten und wird dementsprechend bestraft.
|
||||
2. Bauten, die auf oder mithilfe von SteamWar.de entstanden sind, dürfen nicht verkauft werden. Das bezieht sich auch auf Handel außerhalb von SteamWar.
|
||||
1. Jeglicher Handel, welcher mit einer reellen Vermögensveränderung verbunden ist, wird im Zusammenhang mit SteamWar nicht gestattet.
|
||||
1. Bauten, die auf oder mithilfe von SteamWar.de entstanden sind, dürfen nicht verkauft werden. Das bezieht sich auch auf Handel außerhalb von SteamWar.
|
||||
|
||||
# Teamserver Integration
|
||||
|
||||
1. Die Verhaltensrichtlinien gelten auch für Team-Server, die über die Team-Server-Integration mit dem SteamWar-Netzwerk verbunden sind, sofern mehr Spieler als die des verbundenen Teams und wenige weitere ausgewählte Personen auf dem Team-Server zugelassen sind. Ausgenommen hiervon sind Paragraph 4.3.1, da Vorfälle dieser Art dem Serverbetreiber gemeldet werden müssen. Es sei denn es geht um SteamWar, sowie Paragraph 3.1.
|
||||
2. Das Hinzufügen von Regeln, welche unsere Verhaltensrichtlinien erweitern ist erlaubt, solange diese nicht unsere Verhaltensrichtlinien verletzen.
|
||||
3. Diese Regel greift nur, solange entsprechende Spieler auch über SteamWar.de auf den Team-Server gelangt sind
|
||||
|
||||
# Events
|
||||
|
||||
1. Kampfmaschinen, die von SteamWar in limitierter Form verteilt wurden, dürfen nicht erneut eingesendet werden. Sollte dies dennoch geschehen, wird die Schematic abgelehnt. Bei wiederholtem Einsenden greift Paragraph 5.5.
|
||||
1. Kampfmaschinen, die von SteamWar in limitierter Form verteilt wurden, dürfen nicht weiterverbreitet werden.
|
||||
|
||||
Die Ausnutzung von Lücken in diesen Richtlinien und anderweitige Versuche diese zu umgehen, werden ebenso als Regelverstoß geahndet.
|
||||
Mögliche strafen sind:
|
||||
@@ -103,4 +107,4 @@ Alle genannten Strafen können entweder temporär oder permanent sein.
|
||||
Das Serverteam behält sich das Recht vor, diese Richtlinien jederzeit zu ändern oder zu ergänzen
|
||||
Unwissenheit schützt nicht vor Strafe!
|
||||
|
||||
Letztes update: `08.10.2023`
|
||||
Letztes update: `04.05.2024`
|
||||
@@ -44,6 +44,9 @@ To be able to guarantee server security and our communities future, the followin
|
||||
4. Behavior which disproportionately impairs the communities integrity may be subject to sanctions.
|
||||
5. Teams which disproportionately affect the server, the community and it’s future, can be disbanded after being warned.
|
||||
1. If members of such a team continue to create similar teams, further penalties may follow
|
||||
6. Information about potential misconduct may not be posted as a thread or forum post. The following subpoints are the correct ways to address accusations:
|
||||
- Submitting the information in the form of a ticket.
|
||||
- Initiation of private contact with the moderation, Admiralseekrank, or an authority within the server team corresponding to the allegations (Builder leadership/Head Devs). This option is particularly suitable if the misconduct is attributed to a member of the server team.
|
||||
|
||||
# Behavior toward the server team
|
||||
|
||||
@@ -82,14 +85,14 @@ The following guidelines deal with the behavior around any rule breaks
|
||||
|
||||
# Events
|
||||
|
||||
1. Schematics that have been distributed by SteamWar in limited form may not be resubmitted. If this happens nevertheless, the schematic will be rejected. In case of repeated submissions, paragraph 5.5 applies.
|
||||
1. Schematics that have been distributed by SteamWar in limited form may not be redistributed.
|
||||
|
||||
**The exploitation of loopholes in these guidelines and otherwise attempting to circumvent them will also be penalized as a rule violation.**
|
||||
|
||||
## Possible penalties are:
|
||||
* No Dev: It is no longer possible for you to join the dev server.
|
||||
* No Fight: It is no longer possible for you to participate in fights.
|
||||
* No Schem Receiving: It is impossible for others to add you to their schematics or use them on your build server. Also, you cannot copy schematics from other players or upload schematics.
|
||||
* No Schem Receiving: Others can’t add you to their schematics or use them on your build server. Also, you cannot copy schematics from other players or upload schematics.
|
||||
* No Schem Sharing: You can no longer allow anyone to use your schematics. Also, no one can create a schematic on your build server. You also can’t download schematics.
|
||||
* No Schem Submitting: You can no longer submit schematics.
|
||||
* No Team Server: You can no longer link your team server to SteamWar.
|
||||
@@ -102,4 +105,4 @@ All the penalties above can be either temporary or permanent.
|
||||
|
||||
The server team reserves the right to change or amend these guidelines at any time. Unawareness does not protect from punishment!
|
||||
|
||||
Last update: `2023.10.08`
|
||||
Last update: `2024.05.04`
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"name": "Graf Spree",
|
||||
"name": "Graf Spee",
|
||||
"description": "A simple, lightweight description of a frostbite.",
|
||||
"id": 123,
|
||||
"creator": ["Test", "Test2"],
|
||||
"gamemode": "warship",
|
||||
"image": "../../../images/publics/grafspree/area_render.png",
|
||||
"image": "../../../images/publics/grafspee/area_render.png",
|
||||
"3d": false
|
||||
}
|
||||
@@ -26,6 +26,7 @@ Schuss zu verhindern.
|
||||
|
||||
## Kanonen
|
||||
|
||||
Jedes MicroWargear muss über mindestens eine funktionstüchtige Kanone verfügen.
|
||||
Eine Kanone ist eine durchgehende Redstonekonstruktion, welche in der Lage ist,
|
||||
den Gegner durch gezündetes TNT zu beschädigen. Eine TNT-Kanone ist der einzige Ort in einem Micro an dem Wasser verbaut werden darf, wenn es die Kanone nicht verlässt und /oder im intakten Zustand Wasserschilde bildet. Außerdem darf sich die Kanone nicht gezielt selbst beschädigen. Eine TNT-Kanone darf maximal 8 Projektile pro Schuss abfeuern.
|
||||
Zusätzlich ist eine Hauptkanone mit 12 Projektilen erlaubt.
|
||||
|
||||
@@ -5,7 +5,7 @@ mode: miniwargear
|
||||
|
||||
# MiniWarGear-Regelwerk
|
||||
|
||||
MiniWargears werden in der 1.19 gebaut.
|
||||
MiniWargears werden in der 1.20 gebaut.
|
||||
|
||||
## Maße
|
||||
|
||||
|
||||
3
src/content/rules/de/missilewars.md
Normal file
@@ -0,0 +1,3 @@
|
||||
---
|
||||
translationKey: mw
|
||||
---
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
title: Tracer
|
||||
translationKey: tracer
|
||||
slug: tracer
|
||||
---
|
||||
|
||||
# Der Tracer
|
||||

|
||||
|
||||
Der Tracer ist eines der Kern-Tools unseres BauSystems. Durch ihn kannst du
|
||||
dir komfortabel angucken wie sich die TNT deiner Kanonen Tick für Tick
|
||||
verhalten. Dies tut der Tracer, indem er alle Daten der auf einem Plot
|
||||
gezündeten TNTs aufnimmt und speichert. Du kannst dir dann verschiedene
|
||||
Darstellungsformen der aufgezeichneten TNTs angucken.
|
||||
|
||||
## Den Tracer starten
|
||||
Um die Schüsse deiner Kanone auf einem Plot aufzunehmen, musst du den Tracer
|
||||
für diese Plot einschalten. Nutze hierfür `/trace auto`.
|
||||
Nun da der Tracer an ist, wird für jeden Kanonenschuss ein Trace erstellt.
|
||||
|
||||
## Traces anzeigen und analysieren
|
||||
Jetzt da der Tracer an ist und du einen Schuss abgegeben hast, kannst du dir
|
||||
den Trace mit
|
||||
`/trace show` anzeigen (Falls du mehrere Schüsse abgegeben hast kannst du
|
||||
dir mit
|
||||
`/trace isolate [Schuss-Nummer]` den Trace eines einzelnen Schusses anzeigen).
|
||||
|
||||
|
||||
Zur Analyse eines Schusses stellen wir dir verschiedene **View-Flags** zur
|
||||
Verfügung. Diese aktivierst du, indem du sie an den Trace-show Command
|
||||
anhängst.
|
||||
|
||||
| Flag | Beschreibung |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `count` | Zeige dir die Zahl der TNTs an die an einem Trace-Punkt aufgenommen wurden |
|
||||
| `explosion` | Zeige dir nur die Trace-Punkte an, an denen TNT explodiert ist |
|
||||
| `fuse` | Zeige dir an wie weit die TNTs an einem Trace Punkt von der Explosion weg waren |
|
||||
| `ignite` | Ohne diese Flag zeigt der Tracer nur Trace-Punkte an, die nach der ersten Explosion entstanden sind. Mit dieser Flag werden alle Trace-Punkte angezeigt |
|
||||
| `micromotion` | Zeige nur TNT an, die sich zu einem beliebigen Zeitpunkt mir einer Geschwindigkeit von kleiner 0.001 bewegt haben |
|
||||
| `source` | Zeige dir nur Trace-Punkte an, bei denen TNT gezündet wurde |
|
||||
| `build-destroy-only` | Zeige dir nur TNT an, die im Bau-Bereich explodiert sind |
|
||||
| `testblock-destroy-only` | Zeige dir nur TNT an, die im Testblock-Bereich explodiert sind |
|
||||
| `advanced` | Zeige dir die TNT-Zwischenberechnungspunkte auf den einzelnen Achsen an |
|
||||
|
||||
\
|
||||
Du kannst dir auch nur einen Abschnitt des Traces mit
|
||||
`\trace show from [Start-Zeit] to [End-Zeit] with [View-Flags]` anzeigen. Du kann auch `from` oder `to` weglassen, um dir den Trace von bzw. bis zu einem gewissen Zeitpunkt angucken.
|
||||
|
||||
## Traces löschen
|
||||
Allgemein empfiehlt es sich Traces nicht ewig rumliegen zu lassen, da ein
|
||||
`/trace show` schnell den PC zum erliegen bringen kann. Nutze `/trace
|
||||
delete [Schuss-Nummer]` um einzelne Traces zu löschen und `/trace clear`
|
||||
um alle Traces auf einem Plot zu löschen.
|
||||
|
||||
## Traces gemeinsam betrachten
|
||||
Wenn man zusammen an einer Kanonen arbeitet kann es praktisch sein, die selben Traces, mit den selben View-Flags zu betrachten. Dies kannst du machen mit `/trace follow [Spieler]`. Den Follow kannst du mit `/trace unfollow` wieder aufheben. Zusätzlich kannst du alle Spieler auf einem Bau-Server mit `/trace broadcast` einladen deiner Trace-View zu folgen.
|
||||
@@ -1,50 +0,0 @@
|
||||
# Der Tracer
|
||||

|
||||
|
||||
Der Tracer ist eines der Kern-Tools unseres BauSystems. Durch ihn kannst du
|
||||
dir komfortabel angucken wie sich die TNT deiner Kanonen Tick für Tick
|
||||
verhalten. Dies tut der Tracer, indem er alle Daten der auf einem Plot
|
||||
gezündeten TNTs aufnimmt und speichert. Du kannst dir dann verschiedene
|
||||
Darstellungsformen der aufgezeichneten TNTs angucken.
|
||||
|
||||
## Den Tracer starten
|
||||
Um die Schüsse deiner Kanone auf einem Plot aufzunehmen, musst du den Tracer
|
||||
für diese Plot einschalten. Nutze hierfür `/trace auto`.
|
||||
Nun da der Tracer an ist, wird für jeden Kanonenschuss ein Trace erstellt.
|
||||
|
||||
## Traces anzeigen und analysieren
|
||||
Jetzt da der Tracer an ist und du einen Schuss abgegeben hast, kannst du dir
|
||||
den Trace mit
|
||||
`/trace show` anzeigen (Falls du mehrere Schüsse abgegeben hast kannst du
|
||||
dir mit
|
||||
`/trace isolate [Schuss-Nummer]` den Trace eines einzelnen Schusses anzeigen).
|
||||
|
||||
|
||||
Zur Analyse eines Schusses stellen wir dir verschiedene **View-Flags** zur
|
||||
Verfügung. Diese aktivierst du, indem du sie an den Trace-show Command
|
||||
anhängst.
|
||||
|
||||
| Flag | Beschreibung |
|
||||
| - | - |
|
||||
| `count` | Zeige dir die Zahl der TNTs an die an einem Trace-Punkt aufgenommen wurden |
|
||||
| `explosion` | Zeige dir nur die Trace-Punkte an, an denen TNT explodiert ist |
|
||||
| `fuse` | Zeige dir an wie weit die TNTs an einem Trace Punkt von der Explosion weg waren |
|
||||
| `ignite` | Ohne diese Flag zeigt der Tracer nur Trace-Punkte an, die nach der ersten Explosion entstanden sind. Mit dieser Flag werden alle Trace-Punkte angezeigt |
|
||||
| `micromotion` | Zeige nur TNT an, die sich zu einem beliebigen Zeitpunkt mir einer Geschwindigkeit von kleiner 0.001 bewegt haben |
|
||||
| `source` | Zeige dir nur Trace-Punkte an, bei denen TNT gezündet wurde |
|
||||
| `build-destroy-only` | Zeige dir nur TNT an, die im Bau-Bereich explodiert sind |
|
||||
| `testblock-destroy-only` | Zeige dir nur TNT an, die im Testblock-Bereich explodiert sind |
|
||||
| `advanced` | Zeige dir die TNT-Zwischenberechnungspunkte auf den einzelnen Achsen an |
|
||||
|
||||
\
|
||||
Du kannst dir auch nur einen Abschnitt des Traces mit
|
||||
`\trace show from [Start-Zeit] to [End-Zeit] with [View-Flags]` anzeigen. Du kann auch `from` oder `to` weglassen, um dir den Trace von bzw. bis zu einem gewissen Zeitpunkt angucken.
|
||||
|
||||
## Traces löschen
|
||||
Allgemein empfiehlt es sich Traces nicht ewig rumliegen zu lassen, da ein
|
||||
`/trace show` schnell den PC zum erliegen bringen kann. Nutze `/trace
|
||||
delete [Schuss-Nummer]` um einzelne Traces zu löschen und `/trace clear`
|
||||
um alle Traces auf einem Plot zu löschen.
|
||||
|
||||
## Traces gemeinsam betrachten
|
||||
Wenn man zusammen an einer Kanonen arbeitet kann es praktisch sein, die selben Traces, mit den selben View-Flags zu betrachten. Dies kannst du machen mit `/trace follow [Spieler]`. Den Follow kannst du mit `/trace unfollow` wieder aufheben. Zusätzlich kannst du alle Spieler auf einem Bau-Server mit `/trace broadcast` einladen deiner Trace-View zu folgen.
|
||||
@@ -41,7 +41,9 @@
|
||||
"Dev": "Developer",
|
||||
"Mod": "Moderator",
|
||||
"Sup": "Supporter",
|
||||
"Arch": "Architekt"
|
||||
"Arch": "Architekt",
|
||||
"User": "Spieler",
|
||||
"YT": "YouTuber"
|
||||
}
|
||||
},
|
||||
"status": {
|
||||
@@ -63,7 +65,6 @@
|
||||
"announcements": "Ankündigungen",
|
||||
"about": "Über Uns",
|
||||
"downloads": "Downloads",
|
||||
"tutorials": "Tutorials",
|
||||
"faq": "FAQ"
|
||||
},
|
||||
"rules": {
|
||||
@@ -86,7 +87,10 @@
|
||||
"title": "Hilfe",
|
||||
"docs": "Dokumentation"
|
||||
},
|
||||
"account": "Konto"
|
||||
"account": "Konto",
|
||||
"ranked": {
|
||||
"mw": "MissileWars"
|
||||
}
|
||||
}
|
||||
},
|
||||
"wg": {
|
||||
@@ -119,9 +123,12 @@
|
||||
"megawg": {
|
||||
"title": "MegaWarGear"
|
||||
},
|
||||
"micro": {
|
||||
"microwg": {
|
||||
"title": "MicroWarGear"
|
||||
},
|
||||
"mw": {
|
||||
"title": "MissileWars"
|
||||
},
|
||||
"footer": {
|
||||
"imprint": "Impressum",
|
||||
"privacy": "Datenschutzerklärung",
|
||||
@@ -204,7 +211,8 @@
|
||||
},
|
||||
"label": {
|
||||
"username": "Nutzername",
|
||||
"password": "Passwort"
|
||||
"password": "Passwort",
|
||||
"repeat": "Passwort Wiederholen"
|
||||
},
|
||||
"setPassword": "Wie setzte ich mein Passwort?",
|
||||
"submit": "Login",
|
||||
@@ -241,5 +249,9 @@
|
||||
},
|
||||
"ranking": {
|
||||
"heading": "{# mode #} Rangliste"
|
||||
},
|
||||
"404": {
|
||||
"title": "404 - Seite nicht gefunden",
|
||||
"description": "Seite nicht gefunden"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
"announcements": "Announcements",
|
||||
"about": "About",
|
||||
"downloads": "Downloads",
|
||||
"tutorials": "Tutorials",
|
||||
"faq": "FAQ"
|
||||
},
|
||||
"rules": {
|
||||
@@ -63,7 +62,9 @@
|
||||
"Dev": "Developer",
|
||||
"Mod": "Moderator",
|
||||
"Sup": "Supporter",
|
||||
"Arch": "Builder"
|
||||
"Arch": "Builder",
|
||||
"User": "User",
|
||||
"YT": "YouTuber"
|
||||
}
|
||||
},
|
||||
"footer": {
|
||||
@@ -148,7 +149,8 @@
|
||||
},
|
||||
"label": {
|
||||
"username": "Username",
|
||||
"password": "Password"
|
||||
"password": "Password",
|
||||
"repeat": "Repeat Password"
|
||||
},
|
||||
"setPassword": "How to set a Password",
|
||||
"submit": "Login",
|
||||
@@ -181,5 +183,9 @@
|
||||
},
|
||||
"stats": {
|
||||
"title": "Fight Statistics"
|
||||
},
|
||||
"404": {
|
||||
"title": "404 - Page not found",
|
||||
"description": "Page not found"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/images/jAHRESPLAN-gro-4.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
src/images/jAHRESPLAN-gro-5.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.3 MiB |
|
Before Width: | Height: | Size: 7.0 MiB |
|
Before Width: | Height: | Size: 7.0 MiB |
@@ -3,9 +3,8 @@ import icon from "../images/logo.png";
|
||||
import {getImage} from "astro:assets";
|
||||
import {astroI18n} from "astro-i18n";
|
||||
import {SEO} from "astro-seo";
|
||||
import {ViewTransitions} from "astro:transitions";
|
||||
import {ClientRouter} from "astro:transitions";
|
||||
const {title, description, clientSideRouter = true} = Astro.props.frontmatter || Astro.props;
|
||||
|
||||
import "../../public/fonts/roboto/roboto.css";
|
||||
|
||||
const iconImage = await getImage({src: icon, height: 32, width: 32, format: "png", quality: 100});
|
||||
@@ -40,7 +39,7 @@ if (localStorage["theme-mode"] === "light" || (!("theme-mode" in localStorage) &
|
||||
|
||||
<slot name="head"/>
|
||||
|
||||
{clientSideRouter && <ViewTransitions/>}
|
||||
{clientSideRouter && <ClientRouter/>}
|
||||
</head>
|
||||
<body class="dark:bg-zinc-800">
|
||||
<slot/>
|
||||
|
||||
@@ -3,7 +3,7 @@ import {Image} from "astro:assets";
|
||||
import Basic from "./Basic.astro";
|
||||
import "../styles/button.css";
|
||||
import localLogo from "../images/logo.png";
|
||||
import {YoutubeSolid, DiscordSolid} from "flowbite-svelte-icons";
|
||||
import {YoutubeSolid, DiscordSolid, FileCodeSolid} from "flowbite-svelte-icons";
|
||||
import {t} from "astro-i18n";
|
||||
import {l} from "../util/util";
|
||||
|
||||
@@ -50,6 +50,9 @@ const {title, description} = Astro.props;
|
||||
<a class="flex" href="/discord">
|
||||
<DiscordSolid class="mr-2"/>
|
||||
Discord</a>
|
||||
<a class="flex" href="https://git.steamwar.de">
|
||||
<FileCodeSolid class="mr-2"/>
|
||||
Gitea</a>
|
||||
</div>
|
||||
</div>
|
||||
<span class="text-sm text-white text-center mt-1">© SteamWar.de - Made with ❤️ by Chaoscaot</span>
|
||||
|
||||
@@ -10,7 +10,7 @@ const {title, description} = Astro.props;
|
||||
<div class="h-screen w-screen fixed -z-10">
|
||||
<BackgroundImage />
|
||||
</div>
|
||||
<div class="mx-auto bg-gray-100 p-8 rounded-b-md shadow-md pt-40 sm:pt-28 md:pt-14 relative
|
||||
<div class="mx-auto bg-gray-100 p-8 rounded-b-md shadow-md pt-14 relative
|
||||
dark:text-white dark:bg-neutral-900" style="width: min(100%, 75em);">
|
||||
<slot/>
|
||||
</div>
|
||||
|
||||
@@ -77,7 +77,7 @@ const ogImage = await getImage({
|
||||
)}
|
||||
<div class={post.data.image ? "absolute bottom-8 left-2" : "mb-4"}>
|
||||
<h1 class="text-4xl mb-0" transition:name={post.data.title + "-title"}>{post.data.title}</h1>
|
||||
<div class="flex items-center mt-2 text-neutral-300">
|
||||
<div class="flex items-center mt-2 text-neutral-800 dark:text-neutral-300">
|
||||
<TagSolid class="w-4 h-4 mr-2"/>
|
||||
<div transition:name={post.data.title + "-tags"}>
|
||||
{post.data.tags.map(tag => (
|
||||
@@ -111,15 +111,13 @@ const ogImage = await getImage({
|
||||
import type {ExtendedEvent} from "@type/event";
|
||||
import {mount} from "svelte";
|
||||
|
||||
const eventMounts: Map<string, ((ev: ExtendedEvent) => void)[]> = new Map();
|
||||
const eventMounts: Map<string, Promise<ExtendedEvent>> = new Map();
|
||||
|
||||
class FightTableElement extends HTMLElement {
|
||||
connectedCallback(): void {
|
||||
if (!eventMounts.has(this.dataset["event"]!)) {
|
||||
eventMounts.set(this.dataset["event"]!, []);
|
||||
}
|
||||
loadEvent(this.dataset["event"]!);
|
||||
const rows = Number.parseInt(this.dataset["rows"]!);
|
||||
eventMounts.get(this.dataset["event"]!)!.push(ev => {
|
||||
eventMounts.get(this.dataset["event"]!)!.then(ev => {
|
||||
mount(FightTable, {
|
||||
target: this,
|
||||
props: {
|
||||
@@ -134,11 +132,9 @@ const ogImage = await getImage({
|
||||
|
||||
class GroupTableElement extends HTMLElement {
|
||||
connectedCallback(): void {
|
||||
if (!eventMounts.has(this.dataset["event"]!)) {
|
||||
eventMounts.set(this.dataset["event"]!, []);
|
||||
}
|
||||
loadEvent(this.dataset["event"]!);
|
||||
const rows = Number.parseInt(this.dataset["rows"]!);
|
||||
eventMounts.get(this.dataset["event"]!)!.push(ev => {
|
||||
eventMounts.get(this.dataset["event"]!)!.then(ev => {
|
||||
mount(GroupTable, {
|
||||
target: this,
|
||||
props: {
|
||||
@@ -154,17 +150,13 @@ const ogImage = await getImage({
|
||||
customElements.define("fight-table", FightTableElement);
|
||||
customElements.define("group-table", GroupTableElement);
|
||||
|
||||
function mountEvent() {
|
||||
for (const key of eventMounts.keys()) {
|
||||
get(eventRepo).getEvent(key).then(ev => {
|
||||
for (const mount of eventMounts.get(key)!) {
|
||||
mount(ev);
|
||||
}
|
||||
});
|
||||
function loadEvent(id: string) {
|
||||
if (!eventMounts.has(id)) {
|
||||
eventMounts.set(id, get(eventRepo).getEvent(id));
|
||||
}
|
||||
}
|
||||
|
||||
mountEvent();
|
||||
document.addEventListener("astro:before-swap", eventMounts.clear);
|
||||
</script>
|
||||
</article>
|
||||
</PageLayout>
|
||||
|
||||
@@ -8,9 +8,11 @@ import {t} from "astro-i18n";
|
||||
<script>
|
||||
import {l} from "../util/util";
|
||||
import {navigate} from "astro:transitions/client";
|
||||
import {get} from "svelte/store";
|
||||
import {loggedIn} from "../components/repo/authv2";
|
||||
document.addEventListener("astro:page-load", () => {
|
||||
if (window.location.href.endsWith("/dashboard") || window.location.href.endsWith("/dashboard/")) {
|
||||
if ((localStorage.getItem("sw-session") ?? "") === "") {
|
||||
if (!get(loggedIn)) {
|
||||
navigate(l("/login"), {});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import {type Player} from "../components/types/data";
|
||||
import PostComponent from "../components/PostComponent.astro";
|
||||
import BackgroundImage from "../components/BackgroundImage.astro";
|
||||
|
||||
const teamMember: { [key: string]: Player[]} = await fetch("https://api.steamwar.de/data/team")
|
||||
const teamMember: { [key: string]: Player[]} = await fetch("http://127.0.0.1:1337/data/team")
|
||||
.then(value => value.json());
|
||||
|
||||
const posts = await getCollection("announcements", entry => entry.id.split("/")[0] === astroI18n.locale);
|
||||
|
||||
@@ -9,10 +9,12 @@ import BackgroundImage from "../components/BackgroundImage.astro";
|
||||
<script>
|
||||
import {l} from "../util/util";
|
||||
import {navigate} from "astro:transitions/client";
|
||||
import {loggedIn} from "../components/repo/authv2";
|
||||
import {get} from "svelte/store";
|
||||
|
||||
document.addEventListener("astro:page-load", () => {
|
||||
if (window.location.href.endsWith("/login") || window.location.href.endsWith("/login/")) {
|
||||
if ((localStorage.getItem("sw-session") ?? "") !== "") {
|
||||
if (get(loggedIn)) {
|
||||
navigate(l("/dashboard"), {history: "replace"});
|
||||
}
|
||||
}
|
||||
|
||||
39
src/pages/not-found.astro
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
import PageLayout from "../layouts/PageLayout.astro";
|
||||
import {t} from "astro-i18n";
|
||||
---
|
||||
|
||||
<PageLayout title={t("404.title")}>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 800 400">
|
||||
<!-- 404 Text - heller für besseren Kontrast -->
|
||||
<text x="400" y="150" font-family="Arial Black" font-size="120" fill="#ffffff" text-anchor="middle">404</text>
|
||||
|
||||
<!-- Trauriger Roboter - hellere Farben für besseren Kontrast -->
|
||||
<!-- Körper -->
|
||||
<rect x="350" y="200" width="100" height="120" rx="10" fill="#888888"/>
|
||||
|
||||
<!-- Kopf -->
|
||||
<rect x="365" y="160" width="70" height="60" rx="5" fill="#888888"/>
|
||||
|
||||
<!-- Augen -->
|
||||
<circle cx="385" cy="185" r="8" fill="#ff6b6b"/>
|
||||
<circle cx="415" cy="185" r="8" fill="#ff6b6b"/>
|
||||
|
||||
<!-- Antenne -->
|
||||
<line x1="400" y1="160" x2="400" y2="140" stroke="#888888" stroke-width="4"/>
|
||||
<circle cx="400" cy="135" r="5" fill="#888888"/>
|
||||
|
||||
<!-- Arme -->
|
||||
<rect x="320" y="220" width="30" height="10" rx="5" fill="#888888"/>
|
||||
<rect x="450" y="220" width="30" height="10" rx="5" fill="#888888"/>
|
||||
|
||||
<!-- Text unter dem Roboter - heller für besseren Kontrast -->
|
||||
<text x="400" y="360" font-family="Arial" font-size="24" fill="#ffffff" text-anchor="middle">{t("404.description")}</text>
|
||||
|
||||
<!-- Dekorative Elemente - heller für besseren Kontrast -->
|
||||
<circle cx="250" cy="100" r="5" fill="#bbbbbb"/>
|
||||
<circle cx="550" cy="150" r="5" fill="#bbbbbb"/>
|
||||
<circle cx="200" cy="300" r="5" fill="#bbbbbb"/>
|
||||
<circle cx="600" cy="250" r="5" fill="#bbbbbb"/>
|
||||
</svg>
|
||||
</PageLayout>
|
||||
@@ -44,4 +44,5 @@ const modes = await getCollection("modes", entry => entry.data.main);
|
||||
</div>
|
||||
</div>
|
||||
</div>))}
|
||||
<a href={l("/rangliste/MissileWars")}>MissileWars Rangliste</a>
|
||||
</PageLayout>
|
||||
@@ -1,19 +0,0 @@
|
||||
---
|
||||
import { createGetStaticPaths } from "astro-i18n";
|
||||
import { getCollection } from "astro:content";
|
||||
|
||||
const { tutorial } = Astro.props;
|
||||
|
||||
export const getStaticPaths = createGetStaticPaths(async () => {
|
||||
const tutorials = await getCollection("tutorials");
|
||||
|
||||
return tutorials.map((entry) => ({
|
||||
props: {
|
||||
title: entry.data.title
|
||||
},
|
||||
params: {
|
||||
title: entry.slug,
|
||||
},
|
||||
}));
|
||||
});
|
||||
---
|
||||
@@ -31,7 +31,7 @@ table {
|
||||
text-align: center;
|
||||
|
||||
tr:nth-child(odd) {
|
||||
@apply bg-neutral-800;
|
||||
@apply bg-neutral-200 dark:bg-neutral-800;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
build:
|
||||
- "echo 'PUBLIC_API_SERVER=https://dev.steamwar.de/api' > .env"
|
||||
- "pnpm run ci"
|
||||
- "printenv"
|
||||
- "echo 'PUBLIC_API_SERVER=https://api.steamwar.de' > .env"
|
||||
- "pnpm install"
|
||||
- "./node_modules/.bin/astro-i18n generate:pages --purge"
|
||||
- "./node_modules/.bin/astro-i18n generate:types"
|
||||
- "./node_modules/.bin/astro build"
|
||||
|
||||
release:
|
||||
- "rm -r /var/www/dev/*"
|
||||
- "mv dist/* /var/www/dev"
|
||||
- "rm -r /var/www/html/*"
|
||||
- "mv dist/* /var/www/html"
|
||||
@@ -9,7 +9,6 @@ module.exports = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
// flowbite-svelte
|
||||
primary: { 50: '#FFF5F2', 100: '#FFF1EE', 200: '#FFE4DE', 300: '#FFD5CC', 400: '#FFBCAD', 500: '#FE795D', 600: '#EF562F', 700: '#EB4F27', 800: '#CC4522', 900: '#A5371B'},
|
||||
}
|
||||
},
|
||||
|
||||