71 Commits

Author SHA1 Message Date
624ba7f296 Merge pull request 'Merge branch wgs25-kampfplan' (#7) from wgs25-kampfplan into master
All checks were successful
SteamWarCI Build successful
Reviewed-on: #7
2025-03-01 10:51:19 +01:00
Lixfel
d7d20e4347 Update wgs25-kampfplan.md
All checks were successful
SteamWarCI Build successful
2025-03-01 10:50:17 +01:00
Lixfel
43bd8f4a7c Update wgs25-kampfplan.md
Some checks failed
SteamWarCI Build failed
2025-03-01 10:49:03 +01:00
Lixfel
18e8627b54 Update wgs25-kampfplan.md
Some checks failed
SteamWarCI Build failed
2025-03-01 10:42:19 +01:00
Lixfel
0efc46c7e2 Create page announcements/de/wgs25-kampfplan.md
Some checks failed
SteamWarCI Build failed
2025-03-01 09:53:50 +01:00
62fff0c0b2 Merge pull request 'Refactor authentication and implement password reset.' (#3) from develop/authv2 into master
All checks were successful
SteamWarCI Build successful
Reviewed-on: #3
Reviewed-by: Lixfel <lixfel@noreply.localhost>
2025-02-25 22:39:40 +01:00
TheBreadBeard
86b479fb28 Update missilewars-iii-eventplan.md
All checks were successful
SteamWarCI Build successful
2025-02-23 18:34:53 +01:00
Chaoscaot
489402292d Update adventskalender-schems.md
All checks were successful
SteamWarCI Build successful
2025-02-23 18:31:10 +01:00
b53ce04a75 Remove reset password functionality
All checks were successful
SteamWarCI Build successful
2025-02-23 17:23:45 +01:00
069a9973a4 Add Gitea link and icon to navbar layout
All checks were successful
SteamWarCI Build successful
2025-02-23 15:20:50 +01:00
c3410de1d7 Refactor event handling to use Promises for better efficiency.
All checks were successful
SteamWarCI Build successful
2025-02-23 12:25:56 +01:00
a23c514102 Revert "Refactor event mounts and update script management."
This reverts commit bf8110af6c.
2025-02-23 12:20:34 +01:00
bf8110af6c Refactor event mounts and update script management.
All checks were successful
SteamWarCI Build successful
2025-02-23 12:18:58 +01:00
349f71af1c Add event listener for "astro:before-swap" in slug page
All checks were successful
SteamWarCI Build successful
2025-02-23 12:14:11 +01:00
dda37127ca Use type import and update page load event handling.
All checks were successful
SteamWarCI Build successful
2025-02-23 09:59:37 +01:00
6d210eb0ff Merge pull request 'Merge branch missilewars-iii-eventplan' (#4) from missilewars-iii-eventplan into master
All checks were successful
SteamWarCI Build successful
Reviewed-on: #4
2025-02-23 09:49:04 +01:00
Chaoscaot
cfede8f299 Update missilewars-iii-eventplan.md
All checks were successful
SteamWarCI Build successful
2025-02-23 09:47:30 +01:00
TheBreadBeard
597153ed39 Update missilewars-iii-eventplan.md
All checks were successful
SteamWarCI Build successful
2025-02-23 07:43:22 +01:00
TheBreadBeard
697e903a26 Create page announcements/de/missilewars-iii-eventplan.md
Some checks failed
SteamWarCI Build failed
2025-02-23 07:21:02 +01:00
1433784369 Update auth API endpoints to remove "/v2" prefix
All checks were successful
SteamWarCI Build successful
2025-02-20 22:15:02 +01:00
2c63a33bda Refine token validation and update user stats endpoint.
All checks were successful
SteamWarCI Build successful
Extend access token validation to include a 10-second buffer to prevent potential expiry issues. Modify the user stats API call to use the base `/stats/user` endpoint for improved consistency.
2025-02-18 00:09:06 +01:00
87265e5ccc Add "Repeat Password" label to i18n and form components
All checks were successful
SteamWarCI Build successful
2025-02-17 18:32:54 +01:00
75f1a6528b Refactor authentication and implement password reset.
All checks were successful
SteamWarCI Build successful
2025-02-17 18:29:17 +01:00
TheBreadBeard
23f35a35c4 Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 21:58:50 +01:00
TheBreadBeard
973f469c7b Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 21:58:04 +01:00
TheBreadBeard
107caafc26 Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 21:57:15 +01:00
TheBreadBeard
7f26845802 Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 21:54:28 +01:00
TheBreadBeard
37b2e82e05 Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 21:53:28 +01:00
TheBreadBeard
7e2ba9dbce Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 21:50:59 +01:00
TheBreadBeard
69426da5be Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 21:50:11 +01:00
TheBreadBeard
fd2ad65ad4 Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 21:46:58 +01:00
TheBreadBeard
a728651cca Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 21:46:04 +01:00
TheBreadBeard
b9e73ed7d0 Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 21:38:36 +01:00
f1d55b3c99 Merge pull request 'Merge branch missilewars-iii-ankündigung' (#2) from missilewars-iii-ankündigung into master
All checks were successful
SteamWarCI Build successful
Reviewed-on: #2
Reviewed-by: YoyoNow <yoyonow@noreply.localhost>
2025-01-29 20:27:43 +01:00
TheBreadBeard
9b49a0f81c Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 19:46:02 +01:00
TheBreadBeard
11144043c1 Update missilewars-iii-ankündigung.md
All checks were successful
SteamWarCI Build successful
2025-01-29 19:39:12 +01:00
TheBreadBeard
e8f866ce8a Update missilewars-iii-ankündigung.md
Some checks failed
SteamWarCI Build failed
2025-01-29 19:28:01 +01:00
TheBreadBeard
e57a90feaf Create page announcements/de/missilewars-iii-ankündigung.md
Some checks failed
SteamWarCI Build failed
2025-01-29 19:19:43 +01:00
TheBreadBeard
3aa8fea1fd Update verhaltensrichtlinien.md
All checks were successful
SteamWarCI Build successful
2025-01-29 18:59:19 +01:00
TheBreadBeard
95b327951c Update verhaltensrichtlienien.md
All checks were successful
SteamWarCI Build successful
2025-01-29 18:51:55 +01:00
TheBreadBeard
86b99b4e76 Update miniwargear.md
All checks were successful
SteamWarCI Build successful
2025-01-29 18:36:59 +01:00
14b31be465 Fix i18n MircoWG
All checks were successful
SteamWarCI Build successful
2025-01-26 10:35:23 +01:00
341e629aaf Merge pull request 'Merge branch MicroRW' (#1) from MicroRW into master
All checks were successful
SteamWarCI Build successful
Reviewed-on: #1
2025-01-26 10:33:54 +01:00
Friderik
694ded4c61 Update microwargear.md
All checks were successful
SteamWarCI Build successful
2025-01-26 10:32:11 +01:00
a75b5b7c09 Fix Branch Creation
All checks were successful
SteamWarCI Build successful
2025-01-26 10:24:20 +01:00
9146f65455 Fix Padding
All checks were successful
SteamWarCI Build successful
2025-01-21 14:57:05 +01:00
254807efa6 Rebuild
All checks were successful
SteamWarCI Build successful
2025-01-20 23:06:52 +01:00
36931aabb1 Fixes and Upgrade to Astro 5
Some checks failed
SteamWarCI Build failed
2025-01-20 23:04:34 +01:00
628599f019 Fix Login Page and add Jahresplan
All checks were successful
SteamWarCI Build successful
2025-01-20 19:21:21 +01:00
0a6c61bd88 Fix Upload
All checks were successful
SteamWarCI Build successful
2025-01-20 17:42:08 +01:00
8bbad8b3cc Fix CI
All checks were successful
SteamWarCI Build successful
2025-01-20 15:50:17 +01:00
5af6176889 Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:49:59 +01:00
9250dd5088 Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:49:36 +01:00
276e19409d Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:48:49 +01:00
11fa9fa126 Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:46:46 +01:00
17ec6023a9 Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:45:43 +01:00
3c7c899868 Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:41:59 +01:00
9cb161e470 Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:38:58 +01:00
7fc7c2a6eb Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:37:28 +01:00
2fce94d46b Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:35:21 +01:00
6356c9911a Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:34:38 +01:00
2402896fd5 Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:33:12 +01:00
2940304492 Fix CI
Some checks failed
SteamWarCI Build failed
2025-01-20 15:32:20 +01:00
4c0a237b27 Merge remote-tracking branch 'origin/master'
Some checks failed
SteamWarCI Build failed
2025-01-20 15:26:55 +01:00
77b8b41afb Fix CodeMirror 2025-01-20 15:19:18 +01:00
163d049829 astro.config.mjs aktualisiert
Some checks failed
SteamWarCI Build failed
2025-01-20 15:06:44 +01:00
a321b12680 Merge remote-tracking branch 'origin/master'
Some checks failed
SteamWarCI Build failed
2025-01-20 15:05:42 +01:00
feba5a5b4a Fix CodeMirror 2025-01-20 15:05:33 +01:00
faaf5f1852 steamwarci.yml aktualisiert
Some checks failed
SteamWarCI Build failed
2025-01-20 15:03:34 +01:00
18997e1384 tailwind.config.cjs aktualisiert
Some checks failed
SteamWarCI Build failed
2025-01-20 15:02:11 +01:00
fdc7bb93dd Add some stuff 2025-01-19 17:58:26 +01:00
43 changed files with 1205 additions and 779 deletions

View File

@@ -5,7 +5,6 @@ import configureI18n from "./astro-i18n.adapter";
import sitemap from "@astrojs/sitemap"; import sitemap from "@astrojs/sitemap";
import robotsTxt from "astro-robots-txt"; import robotsTxt from "astro-robots-txt";
import {resolve} from "node:url";
import path from "node:path"; import path from "node:path";
import mdx from "@astrojs/mdx"; import mdx from "@astrojs/mdx";
import pagefind from "astro-pagefind"; import pagefind from "astro-pagefind";

View File

@@ -14,11 +14,11 @@
"i18n:sync": "pnpm run i18n:generate:pages && pnpm run i18n:generate:types", "i18n:sync": "pnpm run i18n:generate:pages && pnpm run i18n:generate:types",
"clean:dist": "rm -rf dist", "clean:dist": "rm -rf dist",
"clean:node_modules": "rm -rf node_modules", "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": { "devDependencies": {
"@astrojs/svelte": "^6.0.2", "@astrojs/svelte": "^7.0.4",
"@astrojs/tailwind": "^5.1.2", "@astrojs/tailwind": "^5.1.5",
"@astropub/icons": "^0.2.0", "@astropub/icons": "^0.2.0",
"@types/color": "^4.2.0", "@types/color": "^4.2.0",
"@types/node": "^22.9.3", "@types/node": "^22.9.3",
@@ -41,11 +41,12 @@
"typescript": "^5.7.2" "typescript": "^5.7.2"
}, },
"dependencies": { "dependencies": {
"@astrojs/mdx": "^3.1.9", "@astrojs/mdx": "^4.0.7",
"@astrojs/sitemap": "^3.2.1", "@astrojs/sitemap": "^3.2.1",
"@codemirror/commands": "^6.8.0",
"@codemirror/lang-json": "^6.0.1", "@codemirror/lang-json": "^6.0.1",
"@ddietr/codemirror-themes": "^1.4.4", "@ddietr/codemirror-themes": "^1.4.4",
"astro": "^4.16.14", "astro": "^5.1.8",
"astro-i18n": "^2.2.4", "astro-i18n": "^2.2.4",
"astro-pagefind": "^1.6.0", "astro-pagefind": "^1.6.0",
"astro-robots-txt": "^1.0.0", "astro-robots-txt": "^1.0.0",

1192
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -31,8 +31,7 @@
let error: string = $state(""); let error: string = $state("");
async function login() { async function login() {
let {tokenStore} = await import("./repo/repo.ts"); let {authV2Repo} = await import("./repo/authv2.ts");
let {authRepo} = await import("./repo/auth.ts");
if (username === "" || pw === "") { if (username === "" || pw === "") {
pw = ""; pw = "";
error = t("login.error"); error = t("login.error");
@@ -40,15 +39,14 @@
} }
try { try {
let auth = await get(authRepo).login(username, pw); let auth = await get(authV2Repo).login(username, pw);
if (auth == undefined) { if (!auth) {
pw = ""; pw = "";
error = t("login.error"); error = t("login.error");
return; return;
} }
tokenStore.set(auth); await navigate(l("/dashboard"));
navigate(l("/dashboard"));
} catch (e: any) { } catch (e: any) {
pw = ""; pw = "";
error = t("login.error"); error = t("login.error");
@@ -75,9 +73,7 @@
<style lang="postcss"> <style lang="postcss">
input { input {
@apply border-2 rounded-md p-2 shadow-2xl w-80 @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;
dark:bg-neutral-800
focus:outline-none focus:ring-2 focus:ring-neutral-500 focus:border-transparent;
} }
label { label {

View File

@@ -23,24 +23,35 @@
import {t} from "astro-i18n"; import {t} from "astro-i18n";
import {l} from "../util/util"; import {l} from "../util/util";
import {onMount} from "svelte"; import {onMount} from "svelte";
import {loggedIn} from "@repo/authv2.ts";
interface Props { interface Props {
logo?: import('svelte').Snippet; logo?: import('svelte').Snippet;
} }
let { logo }: Props = $props(); let { logo }: Props = $props();
let navbar: HTMLDivElement = $state(); let navbar = $state<HTMLDivElement>();
let searchOpen = $state(false); let searchOpen = $state(false);
let accountBtn = $state<HTMLAnchorElement>();
$effect(() => {
if ($loggedIn) {
accountBtn!.href = l("/dashboard");
} else {
accountBtn!.href = l("/login");
}
})
onMount(() => { onMount(() => {
handleScroll(); handleScroll();
}) })
function handleScroll() { function handleScroll() {
if (window.scrollY > 0) { if (window.scrollY > 0) {
navbar.classList.add("before:scale-y-100"); navbar!.classList.add("before:scale-y-100");
} else { } else {
navbar.classList.remove("before:scale-y-100"); navbar!.classList.remove("before:scale-y-100");
} }
} }
</script> </script>
@@ -106,7 +117,7 @@
</div> </div>
</div> </div>
--> -->
<a class="btn" href={l("/login")}> <a class="btn" href={l("/login")} bind:this={accountBtn}>
<span class="btn__text">{t("navbar.links.account")}</span> <span class="btn__text">{t("navbar.links.account")}</span>
</a> </a>
<!-- <!--

View File

@@ -1,5 +1,5 @@
--- ---
import {CollectionEntry} from "astro:content"; import type {CollectionEntry} from "astro:content";
import {l} from "../util/util"; import {l} from "../util/util";
import {astroI18n} from "astro-i18n"; import {astroI18n} from "astro-i18n";
import {Image} from "astro:assets"; import {Image} from "astro:assets";

View File

@@ -22,38 +22,40 @@
import wrap from "svelte-spa-router/wrap"; import wrap from "svelte-spa-router/wrap";
import Router, {replace} from "svelte-spa-router"; import Router, {replace} from "svelte-spa-router";
import {get} from "svelte/store"; import {get} from "svelte/store";
import {tokenStore} from "@repo/repo"; import {loggedIn} from "@repo/authv2.ts";
const routes: RouteDefinition = { 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({ "/perms": wrap({
asyncComponent: () => import("./pages/Perms.svelte"), asyncComponent: () => import("./pages/Perms.svelte"),
conditions: detail => get(tokenStore) != "" conditions: detail => get(loggedIn)
}), }),
"/login": wrap({ "/login": wrap({
asyncComponent: () => import("./pages/Login.svelte"), asyncComponent: () => import("./pages/Login.svelte"),
conditions: detail => get(tokenStore) == "" conditions: detail => !get(loggedIn)
}), }),
"/event/:id": wrap({ "/event/:id": wrap({
asyncComponent: () => import("./pages/Event.svelte"), asyncComponent: () => import("./pages/Event.svelte"),
conditions: detail => get(tokenStore) != "" conditions: detail => get(loggedIn)
}), }),
"/event/:id/generate": wrap({ "/event/:id/generate": wrap({
asyncComponent: () => import("./pages/Generate.svelte"), asyncComponent: () => import("./pages/Generate.svelte"),
conditions: detail => get(tokenStore) != "" conditions: detail => get(loggedIn)
}), }),
"/edit": wrap({ "/edit": wrap({
asyncComponent: () => import("./pages/Edit.svelte"), asyncComponent: () => import("./pages/Edit.svelte"),
conditions: detail => get(tokenStore) != "" conditions: detail => get(loggedIn)
}), }),
"/display/:event": wrap({ "/display/:event": wrap({
asyncComponent: () => import("./pages/Display.svelte"), asyncComponent: () => import("./pages/Display.svelte"),
conditions: detail => get(tokenStore) != "" conditions: detail => get(loggedIn)
}), }),
"*": wrap({asyncComponent: () => import("./pages/NotFound.svelte")}) "*": wrap({asyncComponent: () => import("./pages/NotFound.svelte")})
}; };
function conditionsFailed(event: ConditionsFailedEvent) { function conditionsFailed(event: ConditionsFailedEvent) {
console.log(event)
if (event.detail.location === "/login") { if (event.detail.location === "/login") {
replace("/"); replace("/");
} else { } else {

View File

@@ -168,11 +168,11 @@
</div> </div>
<div> <div>
{#if selectedBranch !== "master"} {#if selectedBranch !== "master"}
<Button onclick={createFile} color="alternative" disabled={!selectedPath}>Create File <Button onclick={() => createFile()} color="alternative" disabled={!selectedPath}>Create File
</Button> </Button>
<Button onclick={() => deleteBranch(false)} color="none">Delete Branch</Button> <Button onclick={() => deleteBranch(false)} color="none">Delete Branch</Button>
{:else} {:else}
<Button onclick={createBranch}>Create Branch</Button> <Button onclick={() => createBranch()}>Create Branch</Button>
{/if} {/if}
</div> </div>
</div> </div>

View File

@@ -31,7 +31,7 @@
let request = getRequest(); let request = getRequest();
function getRequest() { function getRequest() {
return $statsRepo.getUserStats(user.id) return $statsRepo.getUserStats(user.uuid)
} }
</script> </script>
@@ -46,5 +46,4 @@
{#if user.perms.includes("CHECK")} {#if user.perms.includes("CHECK")}
<p>{t("dashboard.stats.checked", {checked: data.acceptedSchematics})}</p> <p>{t("dashboard.stats.checked", {checked: data.acceptedSchematics})}</p>
{/if} {/if}
{:catch error}
{/await} {/await}

View File

@@ -50,19 +50,20 @@
// @ts-ignore // @ts-ignore
let b64 = btoa(String.fromCharCode.apply(null, new Uint8Array(content))); let b64 = btoa(String.fromCharCode.apply(null, new Uint8Array(content)));
await $schemRepo.uploadSchematic(name, b64); let response = await $schemRepo.uploadSchematic(name, b64);
open = false; open = false;
uploadFile = null; value = "";
dispatch("reset") dispatch("reset")
} }
let uploadFile: FileList | null = $state(null); let uploadFile: FileList | null = $state(null);
let value = $state("");
</script> </script>
<SWModal title={t("dashboard.schematic.title")} bind:open> <SWModal title={t("dashboard.schematic.title")} bind:open>
<form> <form>
<input type="file" bind:files={uploadFile} /> <input type="file" bind:files={uploadFile} bind:value />
</form> </form>
{#snippet footer()} {#snippet footer()}

View File

@@ -22,9 +22,9 @@
import type {Player} from "@type/data.ts"; import type {Player} from "@type/data.ts";
import {l} from "@utils/util.ts"; import {l} from "@utils/util.ts";
import Statistics from "./Statistics.svelte"; import Statistics from "./Statistics.svelte";
import {authRepo} from "@repo/auth.ts"; import {authV2Repo} from "@repo/authv2.ts";
import {tokenStore} from "@repo/repo.ts";
import Card from "@components/Card.svelte"; import Card from "@components/Card.svelte";
import {navigate} from "astro:transitions/client";
interface Props { interface Props {
user: Player; user: Player;
@@ -33,9 +33,8 @@
let { user }: Props = $props(); let { user }: Props = $props();
async function logout() { async function logout() {
await $authRepo.logout() await $authV2Repo.logout();
tokenStore.set("") await navigate(l("/login"));
window.location.href = l("/login")
} }
</script> </script>
@@ -56,7 +55,7 @@
</div> </div>
<div> <div>
<h1 class="text-4xl font-bold">{t("dashboard.title", {name: user.name})}</h1> <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} /> <Statistics {user} />
</div> </div>
</div> </div>

View File

@@ -22,7 +22,7 @@
import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js"; import { GLTFLoader } from "three/addons/loaders/GLTFLoader.js";
import { OrbitControls } from "three/addons/controls/OrbitControls.js"; import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import {onDestroy, onMount} from "svelte"; import {onDestroy, onMount} from "svelte";
import { CollectionEntry } from "astro:content"; import type { CollectionEntry } from "astro:content";
interface Props { interface Props {
pub: CollectionEntry<"publics">; pub: CollectionEntry<"publics">;

View File

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

View File

@@ -0,0 +1,173 @@
/*
* 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 {tokenStore} from "@repo/repo.ts";
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;
}
try {
const response = await this.requestWithToken(this.refreshToken!, "/auth", {
method: "PUT",
}).then(value => value.json()).then(value => AuthTokenSchema.parse(value));
this.setLoginState(response);
} catch (e) {
this.resetRefreshToken();
this.resetAccessToken();
return;
}
}
async request(url: string, params: RequestInit = {}) {
if (this.accessToken !== undefined && this.accessTokenExpires !== undefined && this.accessTokenExpires.isBefore(dayjs().add(10, "seconds"))) {
await this.refresh();
}
return this.requestWithToken(this.accessToken ?? "", url, params);
}
private async requestWithToken(token: string, url: string, params: RequestInit = {}) {
return 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 loggedIn = writable(false);
export const authV2Repo = readable(new AuthV2Repo());

View File

@@ -17,31 +17,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * 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 = {}) => export const fetchWithToken = (token: string, url: string, params: RequestInit = {}) => get(authV2Repo).request(url, params);
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 function getLocalStorage() { export const tokenStore = writable("");
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));

View File

@@ -20,6 +20,7 @@
import {fetchWithToken, tokenStore} from "./repo.ts"; import {fetchWithToken, tokenStore} from "./repo.ts";
import {type Schematic, SchematicSchema} from "@type/schem.ts"; import {type Schematic, SchematicSchema} from "@type/schem.ts";
import {derived} from "svelte/store"; import {derived} from "svelte/store";
import {ResponseErrorSchema} from "@type/data.ts";
export class SchematicRepo { export class SchematicRepo {
constructor(private token: string) { constructor(private token: string) {
@@ -40,7 +41,7 @@ export class SchematicRepo {
name, name,
content, content,
}), }),
}); }).then(value => value.json()).then(SchematicSchema.or(ResponseErrorSchema).parse);
} }
} }

View File

@@ -36,7 +36,7 @@ export class StatsRepo {
} }
public async getUserStats(id: string): Promise<UserStats> { 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);
} }
} }

View 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>;

View File

@@ -50,3 +50,10 @@ export const ServerSchema = z.object({
}); });
export type Server = z.infer<typeof ServerSchema>; 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>;

View 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.

View 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

View File

@@ -0,0 +1,46 @@
---
title: MissileWars III Eventplan
key: missilewars3-eventplan
description: Der Eventplan für MissileWars 3
created: 2025-03-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>

View File

@@ -0,0 +1,104 @@
---
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. | ABYSS | 0 |
| | BlackFire | 0 |
| | Borg | 0 |
| | Halcyon | 0 |
| | Happy-End | 0 |
| | Pulse | 0 |
| | TheNoobTeam | 0 |
### Aktueller Spieltag
<fight-table data-event="68"></fight-table>
### Qualifikation
| 01.03.2025 | Begegnung | Ergebnis |
|------------|--------------|----------|
| 19:00 | HPY vs ABYS | / |
| 19:30 | Borg vs Hlcy | / |
| 20:00 | TNT vs BF | / |
| 20:30 | ? vs ? | / |
| 21:00 | ? vs ? | / |
| 21:30 | ? vs ? | / |
### 1. Spieltag
| 08.03.2025 | Begegnung | Ergebnis |
|------------|-----------|----------|
| 19:00 | ? vs ? | / |
| 19:30 | ? vs ? | / |
| 20:00 | ? vs ? | / |
| 20:30 | ? vs ? | / |
| 21:00 | ? vs ? | / |
| 21:30 | ? vs ? | / |
### 2. Spieltag
| 15.03.2025 | Begegnung | Ergebnis |
|------------|-----------|----------|
| 19:00 | ? vs ? | / |
| 19:30 | ? vs ? | / |
| 20:00 | ? vs ? | / |
| 20:30 | ? vs ? | / |
| 21:00 | ? vs ? | / |
| 21:30 | ? vs ? | / |
### 3. Spieltag
| 22.03.2025 | Begegnung | Ergebnis |
|------------|-----------|----------|
| 19:00 | ? vs ? | / |
| 19:30 | ? vs ? | / |
| 20:00 | ? vs ? | / |
| 20:30 | - | / |
| 21:00 | - | / |
| 21:30 | - | / |
### 4. Spieltag
| 29.03.2025 | Begegnung | Ergebnis |
|------------|-----------|----------|
| 19:00 | ? vs ? | / |
| 19:30 | ? vs ? | / |
| 20:00 | ? vs ? | / |
| 20:30 | ? vs ? | / |
| 21:00 | ? vs ? | / |
| 21:30 | ? vs ? | / |
### 5. Spieltag
| 05.04.2025 | Begegnung | Ergebnis |
|------------|-----------|----------|
| 19:00 | ? vs ? | / |
| 19:30 | ? vs ? | / |
| 20:00 | ? vs ? | / |
| 20:30 | ? vs ? | / |
| 21:00 | ? vs ? | / |
| 21:30 | ? vs ? | / |
### 6. Spieltag
| 12.04.2025 | Begegnung | Ergebnis |
|------------|-----------|----------|
| 19:00 | ? vs ? | / |
| 19:30 | ? vs ? | / |
| 20:00 | ? vs ? | / |
| 20:30 | - | / |
| 21:00 | - | / |
| 21:30 | - | / |

View File

@@ -2,8 +2,9 @@
"name": "AdvancedScripts", "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.", "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": { "url": {
"1.20.1": "https://steamwar.de/AdvancedScriptsV3", "1.21.4": "https://git.steamwar.de/SteamWar/AdvancedScripts/releases/download/2.2.0/AdvancedScripts-2.2.0.jar",
"1.19": "https://steamwar.de/AdvancedScripts" "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"
}, },
"sourceUrl": "https://steamwar.de/devlabs/SteamWar/AdvancedScripts" "sourceUrl": "https://git.steamwar.de/SteamWar/AdvancedScripts"
} }

View File

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

View File

@@ -2,8 +2,7 @@
"name": "SteamWarTeamserver", "name": "SteamWarTeamserver",
"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.", "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": { "url": {
"Info": "/teamserverintegration", "Info": "/teamserverintegration"
"Download": "https://steamwar.de/SteamWarTeamserver"
}, },
"sourceUrl": "https://steamwar.de/devlabs/SteamWar/SteamWarBungeeTeamserver" "sourceUrl": "https://git.steamwar.de/SteamWar/SteamWarBungeeTeamserver"
} }

View File

@@ -4,7 +4,7 @@ description: Verhaltensrichtlinien von SteamWar.de
slug: verhaltensrichtlinien 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 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 3. Unsportliches Verhalten gegenüber Neulingen, vor allem die Ausnutzung ihrer Unwissenheit
4. Die Veröffentlichung oder Verbreitung privater Informationen anderer Spieler 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! 1. 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 2. Chatinhalte müssen auf Deutsch oder Englisch verfasst werden
# Fairness # 3 Fairness
Um ein Faires miteinander zu ermöglichen, muss folgendes beachtet werden 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. 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. 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. 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. 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.
1. Das Privileg, durch besondere Berechtigungen bestimmte Modifikationen nutzen zu können, darf nicht missbraucht werden. 5. 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. 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.
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. 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.
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) 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)
6. Mitglieder des eigenen Teams dürfen nicht willentlich behindert werden, solange es nicht anderweitig vom Spielmodus oder Event gefordert wird. 9. 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. 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 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. 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. 2. Das Umgehen jeglicher vom Serverteam erteilten Bestrafungen ist verboten.
3. Es ist verboten, Spiel- und/oder Pluginfehler auszunutzen. 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. 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. 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. 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.
1. Sollten von denselben Mitgliedern weiter Teams erstellt werden, welche unter diesen Paragraph fallen, können weitere Strafen folgen. 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. 1. Entscheidungen des Serverteams stehen nicht zur Diskussion.
2. Anweisungen von Teammitgliedern sind zu befolgen, und bei Verweigerung wird bestraft! 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. 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. 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. 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. 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 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 # Handel
1. Jeglicher Handel, egal ob mit echter oder virtueller Ware, ist verboten und wird dementsprechend bestraft. 1. Jeglicher Handel, welcher mit einer reellen Vermögensveränderung verbunden ist, wird im Zusammenhang mit SteamWar nicht gestattet.
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. 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 # 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. 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. 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 3. Diese Regel greift nur, solange entsprechende Spieler auch über SteamWar.de auf den Team-Server gelangt sind
# Events # 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. Die Ausnutzung von Lücken in diesen Richtlinien und anderweitige Versuche diese zu umgehen, werden ebenso als Regelverstoß geahndet.
Mögliche strafen sind: 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 Das Serverteam behält sich das Recht vor, diese Richtlinien jederzeit zu ändern oder zu ergänzen
Unwissenheit schützt nicht vor Strafe! Unwissenheit schützt nicht vor Strafe!
Letztes update: `08.10.2023` Letztes update: `04.05.2024`

View File

@@ -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. 4. Behavior which disproportionately impairs the communities integrity may be subject to sanctions.
5. Teams which disproportionately affect the server, the community and its future, can be disbanded after being warned. 5. Teams which disproportionately affect the server, the community and its future, can be disbanded after being warned.
1. If members of such a team continue to create similar teams, further penalties may follow 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 # Behavior toward the server team
@@ -82,14 +85,14 @@ The following guidelines deal with the behavior around any rule breaks
# Events # 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.** **The exploitation of loopholes in these guidelines and otherwise attempting to circumvent them will also be penalized as a rule violation.**
## Possible penalties are: ## Possible penalties are:
* No Dev: It is no longer possible for you to join the dev server. * 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 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 cant 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 cant download 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 cant download schematics.
* No Schem Submitting: You can no longer submit schematics. * No Schem Submitting: You can no longer submit schematics.
* No Team Server: You can no longer link your team server to SteamWar. * 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! 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`

View File

@@ -26,6 +26,7 @@ Schuss zu verhindern.
## Kanonen ## Kanonen
Jedes MicroWargear muss über mindestens eine funktionstüchtige Kanone verfügen.
Eine Kanone ist eine durchgehende Redstonekonstruktion, welche in der Lage ist, 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. 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. Zusätzlich ist eine Hauptkanone mit 12 Projektilen erlaubt.

View File

@@ -5,7 +5,7 @@ mode: miniwargear
# MiniWarGear-Regelwerk # MiniWarGear-Regelwerk
MiniWargears werden in der 1.19 gebaut. MiniWargears werden in der 1.20 gebaut.
## Maße ## Maße

View File

@@ -41,7 +41,9 @@
"Dev": "Developer", "Dev": "Developer",
"Mod": "Moderator", "Mod": "Moderator",
"Sup": "Supporter", "Sup": "Supporter",
"Arch": "Architekt" "Arch": "Architekt",
"User": "Spieler",
"YT": "YouTuber"
} }
}, },
"status": { "status": {
@@ -118,7 +120,7 @@
"megawg": { "megawg": {
"title": "MegaWarGear" "title": "MegaWarGear"
}, },
"micro": { "microwg": {
"title": "MicroWarGear" "title": "MicroWarGear"
}, },
"footer": { "footer": {
@@ -203,7 +205,8 @@
}, },
"label": { "label": {
"username": "Nutzername", "username": "Nutzername",
"password": "Passwort" "password": "Passwort",
"repeat": "Passwort Wiederholen"
}, },
"setPassword": "Wie setzte ich mein Passwort?", "setPassword": "Wie setzte ich mein Passwort?",
"submit": "Login", "submit": "Login",
@@ -240,5 +243,9 @@
}, },
"ranking": { "ranking": {
"heading": "{# mode #} Rangliste" "heading": "{# mode #} Rangliste"
},
"404": {
"title": "404 - Seite nicht gefunden",
"description": "Seite nicht gefunden"
} }
} }

View File

@@ -62,7 +62,9 @@
"Dev": "Developer", "Dev": "Developer",
"Mod": "Moderator", "Mod": "Moderator",
"Sup": "Supporter", "Sup": "Supporter",
"Arch": "Builder" "Arch": "Builder",
"User": "User",
"YT": "YouTuber"
} }
}, },
"footer": { "footer": {
@@ -147,7 +149,8 @@
}, },
"label": { "label": {
"username": "Username", "username": "Username",
"password": "Password" "password": "Password",
"repeat": "Repeat Password"
}, },
"setPassword": "How to set a Password", "setPassword": "How to set a Password",
"submit": "Login", "submit": "Login",
@@ -180,5 +183,9 @@
}, },
"stats": { "stats": {
"title": "Fight Statistics" "title": "Fight Statistics"
},
"404": {
"title": "404 - Page not found",
"description": "Page not found"
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

View File

@@ -3,9 +3,8 @@ import icon from "../images/logo.png";
import {getImage} from "astro:assets"; import {getImage} from "astro:assets";
import {astroI18n} from "astro-i18n"; import {astroI18n} from "astro-i18n";
import {SEO} from "astro-seo"; 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; const {title, description, clientSideRouter = true} = Astro.props.frontmatter || Astro.props;
import "../../public/fonts/roboto/roboto.css"; import "../../public/fonts/roboto/roboto.css";
const iconImage = await getImage({src: icon, height: 32, width: 32, format: "png", quality: 100}); 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"/> <slot name="head"/>
{clientSideRouter && <ViewTransitions/>} {clientSideRouter && <ClientRouter/>}
</head> </head>
<body class="dark:bg-zinc-800"> <body class="dark:bg-zinc-800">
<slot/> <slot/>

View File

@@ -3,7 +3,7 @@ import {Image} from "astro:assets";
import Basic from "./Basic.astro"; import Basic from "./Basic.astro";
import "../styles/button.css"; import "../styles/button.css";
import localLogo from "../images/logo.png"; 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 {t} from "astro-i18n";
import {l} from "../util/util"; import {l} from "../util/util";
@@ -50,6 +50,9 @@ const {title, description} = Astro.props;
<a class="flex" href="/discord"> <a class="flex" href="/discord">
<DiscordSolid class="mr-2"/> <DiscordSolid class="mr-2"/>
Discord</a> Discord</a>
<a class="flex" href="https://git.steamwar.de">
<FileCodeSolid class="mr-2"/>
Gitea</a>
</div> </div>
</div> </div>
<span class="text-sm text-white text-center mt-1">© SteamWar.de - Made with ❤️ by Chaoscaot</span> <span class="text-sm text-white text-center mt-1">© SteamWar.de - Made with ❤️ by Chaoscaot</span>

View File

@@ -10,7 +10,7 @@ const {title, description} = Astro.props;
<div class="h-screen w-screen fixed -z-10"> <div class="h-screen w-screen fixed -z-10">
<BackgroundImage /> <BackgroundImage />
</div> </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);"> dark:text-white dark:bg-neutral-900" style="width: min(100%, 75em);">
<slot/> <slot/>
</div> </div>

View File

@@ -111,15 +111,13 @@ const ogImage = await getImage({
import type {ExtendedEvent} from "@type/event"; import type {ExtendedEvent} from "@type/event";
import {mount} from "svelte"; 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 { class FightTableElement extends HTMLElement {
connectedCallback(): void { connectedCallback(): void {
if (!eventMounts.has(this.dataset["event"]!)) { loadEvent(this.dataset["event"]!);
eventMounts.set(this.dataset["event"]!, []);
}
const rows = Number.parseInt(this.dataset["rows"]!); const rows = Number.parseInt(this.dataset["rows"]!);
eventMounts.get(this.dataset["event"]!)!.push(ev => { eventMounts.get(this.dataset["event"]!)!.then(ev => {
mount(FightTable, { mount(FightTable, {
target: this, target: this,
props: { props: {
@@ -134,11 +132,9 @@ const ogImage = await getImage({
class GroupTableElement extends HTMLElement { class GroupTableElement extends HTMLElement {
connectedCallback(): void { connectedCallback(): void {
if (!eventMounts.has(this.dataset["event"]!)) { loadEvent(this.dataset["event"]!);
eventMounts.set(this.dataset["event"]!, []);
}
const rows = Number.parseInt(this.dataset["rows"]!); const rows = Number.parseInt(this.dataset["rows"]!);
eventMounts.get(this.dataset["event"]!)!.push(ev => { eventMounts.get(this.dataset["event"]!)!.then(ev => {
mount(GroupTable, { mount(GroupTable, {
target: this, target: this,
props: { props: {
@@ -154,17 +150,13 @@ const ogImage = await getImage({
customElements.define("fight-table", FightTableElement); customElements.define("fight-table", FightTableElement);
customElements.define("group-table", GroupTableElement); customElements.define("group-table", GroupTableElement);
function mountEvent() { function loadEvent(id: string) {
for (const key of eventMounts.keys()) { if (!eventMounts.has(id)) {
get(eventRepo).getEvent(key).then(ev => { eventMounts.set(id, get(eventRepo).getEvent(id));
for (const mount of eventMounts.get(key)!) {
mount(ev);
}
});
} }
} }
mountEvent(); document.addEventListener("astro:before-swap", eventMounts.clear);
</script> </script>
</article> </article>
</PageLayout> </PageLayout>

View File

@@ -8,9 +8,11 @@ import {t} from "astro-i18n";
<script> <script>
import {l} from "../util/util"; import {l} from "../util/util";
import {navigate} from "astro:transitions/client"; import {navigate} from "astro:transitions/client";
import {get} from "svelte/store";
import {loggedIn} from "../components/repo/authv2";
document.addEventListener("astro:page-load", () => { document.addEventListener("astro:page-load", () => {
if (window.location.href.endsWith("/dashboard") || window.location.href.endsWith("/dashboard/")) { if (window.location.href.endsWith("/dashboard") || window.location.href.endsWith("/dashboard/")) {
if ((localStorage.getItem("sw-session") ?? "") === "") { if (!get(loggedIn)) {
navigate(l("/login"), {}); navigate(l("/login"), {});
} }
} }

View File

@@ -9,10 +9,12 @@ import BackgroundImage from "../components/BackgroundImage.astro";
<script> <script>
import {l} from "../util/util"; import {l} from "../util/util";
import {navigate} from "astro:transitions/client"; import {navigate} from "astro:transitions/client";
import {loggedIn} from "../components/repo/authv2";
import {get} from "svelte/store";
document.addEventListener("astro:page-load", () => { document.addEventListener("astro:page-load", () => {
if (window.location.href.endsWith("/login") || window.location.href.endsWith("/login/")) { if (window.location.href.endsWith("/login") || window.location.href.endsWith("/login/")) {
if ((localStorage.getItem("sw-session") ?? "") !== "") { if (get(loggedIn)) {
navigate(l("/dashboard"), {history: "replace"}); navigate(l("/dashboard"), {history: "replace"});
} }
} }

39
src/pages/not-found.astro Normal file
View 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>

View File

@@ -1,7 +1,11 @@
build: build:
- "echo 'PUBLIC_API_SERVER=https://dev.steamwar.de/api' > .env" - "printenv"
- "pnpm run ci" - "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: release:
- "rm -r /var/www/dev/*" - "rm -r /var/www/html/*"
- "mv dist/* /var/www/dev" - "mv dist/* /var/www/html"

View File

@@ -9,7 +9,6 @@ module.exports = {
theme: { theme: {
extend: { extend: {
colors: { colors: {
// flowbite-svelte
primary: { 50: '#FFF5F2', 100: '#FFF1EE', 200: '#FFE4DE', 300: '#FFD5CC', 400: '#FFBCAD', 500: '#FE795D', 600: '#EF562F', 700: '#EB4F27', 800: '#CC4522', 900: '#A5371B'}, primary: { 50: '#FFF5F2', 100: '#FFF1EE', 200: '#FFE4DE', 300: '#FFD5CC', 400: '#FFBCAD', 500: '#FE795D', 600: '#EF562F', 700: '#EB4F27', 800: '#CC4522', 900: '#A5371B'},
} }
}, },