Compare commits
49 Commits
event-brac
...
7276552ed1
| Author | SHA1 | Date | |
|---|---|---|---|
| 7276552ed1 | |||
| a2ef92aaad | |||
| 8b85cd0729 | |||
|
|
2d024cf64b | ||
|
|
13d76d0a97 | ||
|
|
e65fadb65c | ||
|
|
6b4693b7f1 | ||
|
|
92282006fe | ||
| 5457632598 | |||
| bed134f8e0 | |||
| 353a415990 | |||
| 3c6d0f8528 | |||
| 887235dc86 | |||
| a99a066f0d | |||
| e5e3c15b07 | |||
|
|
fb74689c39 | ||
| 18b1f97a84 | |||
|
|
53b81db2c4 | ||
|
|
2314b4c5b5 | ||
|
|
6a81936f77 | ||
|
|
a128de3213 | ||
|
|
6df661f885 | ||
|
|
a32d84ed86 | ||
|
|
e60cebc9a3 | ||
| 3576d5e034 | |||
|
|
d5c7d8fc27 | ||
| ce895e9297 | |||
| 7c83ad0937 | |||
| 5e0a9d89b3 | |||
| 2a8b98ce5b | |||
| 427818d6bf | |||
| 8424c14ca9 | |||
| 602a7e1453 | |||
| 9f31c5ff0c | |||
| 8a41b98c58 | |||
| 9fc5c500f5 | |||
| bc879d7cad | |||
|
|
96f0019dc1 | ||
|
|
7418b608ab | ||
|
|
3802b9bc26 | ||
| 03effd2fd2 | |||
|
|
a4669a897b | ||
| eac0d5592d | |||
|
|
bd9aea8f35 | ||
|
|
6e715cee07 | ||
|
|
4147a1d243 | ||
|
|
46dba2a6f9 | ||
|
|
3d8ad3a129 | ||
|
|
7d50a4db12 |
@@ -1,4 +1,4 @@
|
|||||||
import {defineConfig, sharpImageService} from "astro/config";
|
import { defineConfig, sharpImageService } from "astro/config";
|
||||||
import svelte from "@astrojs/svelte";
|
import svelte from "@astrojs/svelte";
|
||||||
import tailwind from "@astrojs/tailwind";
|
import tailwind from "@astrojs/tailwind";
|
||||||
import configureI18n from "./astro-i18n.adapter";
|
import configureI18n from "./astro-i18n.adapter";
|
||||||
@@ -8,6 +8,8 @@ import robotsTxt from "astro-robots-txt";
|
|||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import mdx from "@astrojs/mdx";
|
import mdx from "@astrojs/mdx";
|
||||||
|
|
||||||
|
import starlight from "@astrojs/starlight";
|
||||||
|
|
||||||
// https://astro.build/config
|
// https://astro.build/config
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
output: "static",
|
output: "static",
|
||||||
@@ -18,14 +20,40 @@ export default defineConfig({
|
|||||||
site: "https://steamwar.de",
|
site: "https://steamwar.de",
|
||||||
integrations: [
|
integrations: [
|
||||||
svelte(),
|
svelte(),
|
||||||
|
starlight({
|
||||||
|
disable404Route: true,
|
||||||
|
title: "SteamWar Docs",
|
||||||
|
defaultLocale: "de",
|
||||||
|
logo: {
|
||||||
|
src: "./src/images/logo.png",
|
||||||
|
},
|
||||||
|
social: [
|
||||||
|
{ icon: "discord", label: "Discord", href: "https://steamwar.de/discord" },
|
||||||
|
{ icon: "document", label: "Gitea", href: "https://git.steamwar.de" },
|
||||||
|
],
|
||||||
|
sidebar: [
|
||||||
|
{ label: "Startseite", slug: "docs" },
|
||||||
|
{ label: "Bau", badge: "WIP", items: ["docs/bausystem", { label: "Script System", items: ["docs/bausystem/script"] }] },
|
||||||
|
{ label: "Kampfsystem", badge: "WIP", items: ["docs/fightsystem"] },
|
||||||
|
{ label: "Minigames", badge: "WIP", items: ["docs/minigames"] },
|
||||||
|
{ label: "Schematicsystem", badge: "WIP", items: ["docs/schematicsystem"] },
|
||||||
|
{ label: "API", badge: "WIP", items: ["docs/api"] },
|
||||||
|
],
|
||||||
|
editLink: {
|
||||||
|
baseUrl: "https://git.steamwar.de/SteamWar/Website/src/branch/main/",
|
||||||
|
},
|
||||||
|
}),
|
||||||
tailwind({
|
tailwind({
|
||||||
configFile: "./tailwind.config.js",
|
configFile: "./tailwind.config.js",
|
||||||
|
applyBaseStyles: false,
|
||||||
}),
|
}),
|
||||||
configureI18n(),
|
configureI18n(),
|
||||||
sitemap({
|
sitemap({
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultLocale: "en", locales: {
|
defaultLocale: "en",
|
||||||
en: "en-US", de: "de-DE",
|
locales: {
|
||||||
|
en: "en-US",
|
||||||
|
de: "de-DE",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
@@ -49,7 +77,7 @@ export default defineConfig({
|
|||||||
{ userAgent: "omgili", disallow: "/" },
|
{ userAgent: "omgili", disallow: "/" },
|
||||||
{ userAgent: "OmigliBot", disallow: "/" },
|
{ userAgent: "OmigliBot", disallow: "/" },
|
||||||
{ userAgent: "PerplexityBot", disallow: "/" },
|
{ userAgent: "PerplexityBot", disallow: "/" },
|
||||||
{ userAgent: "Timpibot", disallow: "/" }
|
{ userAgent: "Timpibot", disallow: "/" },
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
mdx(),
|
mdx(),
|
||||||
@@ -66,7 +94,7 @@ export default defineConfig({
|
|||||||
"@layouts": path.resolve("./src/layouts"),
|
"@layouts": path.resolve("./src/layouts"),
|
||||||
"@repo": path.resolve("./src/components/repo"),
|
"@repo": path.resolve("./src/components/repo"),
|
||||||
"@stores": path.resolve("./src/components/stores"),
|
"@stores": path.resolve("./src/components/stores"),
|
||||||
"$lib": path.resolve("./src"),
|
$lib: path.resolve("./src"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -58,6 +58,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/mdx": "^4.3.0",
|
"@astrojs/mdx": "^4.3.0",
|
||||||
"@astrojs/sitemap": "^3.4.0",
|
"@astrojs/sitemap": "^3.4.0",
|
||||||
|
"@astrojs/starlight": "^0.34.4",
|
||||||
|
"@astrojs/starlight-tailwind": "^4.0.1",
|
||||||
"@codemirror/commands": "^6.8.1",
|
"@codemirror/commands": "^6.8.1",
|
||||||
"@codemirror/lang-json": "^6.0.1",
|
"@codemirror/lang-json": "^6.0.1",
|
||||||
"@codemirror/view": "^6.36.8",
|
"@codemirror/view": "^6.36.8",
|
||||||
@@ -84,11 +86,9 @@
|
|||||||
"svelte-spa-router": "^4.0.1"
|
"svelte-spa-router": "^4.0.1"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
"ignoredBuiltDependencies": [
|
|
||||||
"esbuild"
|
|
||||||
],
|
|
||||||
"onlyBuiltDependencies": [
|
"onlyBuiltDependencies": [
|
||||||
"@parcel/watcher",
|
"@parcel/watcher",
|
||||||
|
"esbuild",
|
||||||
"sharp"
|
"sharp"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,35 +24,24 @@
|
|||||||
import type { ExtendedEvent } from "@type/event.ts";
|
import type { ExtendedEvent } from "@type/event.ts";
|
||||||
import "@styles/table.css";
|
import "@styles/table.css";
|
||||||
|
|
||||||
export let event: ExtendedEvent;
|
let {
|
||||||
export let group: number;
|
event,
|
||||||
export let rows: number = 1;
|
group,
|
||||||
|
rows = 1,
|
||||||
|
}: {
|
||||||
|
event: ExtendedEvent;
|
||||||
|
group: number;
|
||||||
|
rows?: number;
|
||||||
|
} = $props();
|
||||||
|
|
||||||
$: teamPoints = event.teams
|
let teamPoints = $derived(
|
||||||
.map((team) => {
|
Object.entries(event.groups.find((g) => g.id === group)?.points ?? {})
|
||||||
let fights = event.fights.filter((fight) => fight.blueTeam.id === team.id || fight.redTeam.id === team.id);
|
.map(([teamId, points]) => ({
|
||||||
|
team: event.teams.find((t) => t.id === Number(teamId))!!,
|
||||||
if (group !== undefined) {
|
points: points,
|
||||||
fights = fights.filter((fight) => fight.group?.id === group);
|
}))
|
||||||
}
|
.sort((a, b) => b.points - a.points)
|
||||||
|
);
|
||||||
const points = fights.reduce((acc, fight) => {
|
|
||||||
if (fight.ergebnis === 1 && fight.blueTeam.id === team.id) {
|
|
||||||
return acc + (fight.group?.pointsPerWin ?? 3);
|
|
||||||
} else if (fight.ergebnis === 2 && fight.redTeam.id === team.id) {
|
|
||||||
return acc + (fight.group?.pointsPerWin ?? 3);
|
|
||||||
} else if (fight.ergebnis === 3) {
|
|
||||||
return acc + (fight.group?.pointsPerDraw ?? 1);
|
|
||||||
} else {
|
|
||||||
return acc + (fight.group?.pointsPerLoss ?? 0);
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
return {
|
|
||||||
team,
|
|
||||||
points,
|
|
||||||
};
|
|
||||||
})
|
|
||||||
.sort((a, b) => b.points - a.points);
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="p-3 bg-gray-200 dark:bg-neutral-800 rounded-2xl w-3/4 mx-auto">
|
<div class="p-3 bg-gray-200 dark:bg-neutral-800 rounded-2xl w-3/4 mx-auto">
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import FightEditRow from "./FightEditRow.svelte";
|
import FightEditRow from "./FightEditRow.svelte";
|
||||||
|
|
||||||
import type { EventFight, EventFightEdit, ExtendedEvent } from "@type/event";
|
import type { EventFightEdit } from "@type/event";
|
||||||
import { createSvelteTable, FlexRender } from "@components/ui/data-table";
|
import { createSvelteTable, FlexRender } from "@components/ui/data-table";
|
||||||
import { type ColumnFiltersState, getCoreRowModel, getFilteredRowModel, getGroupedRowModel, getSortedRowModel, type RowSelectionState, type SortingState } from "@tanstack/table-core";
|
import { type ColumnFiltersState, getCoreRowModel, getFilteredRowModel, getGroupedRowModel, getSortedRowModel, type RowSelectionState, type SortingState } from "@tanstack/table-core";
|
||||||
import { columns } from "./columns";
|
import { columns } from "./columns";
|
||||||
@@ -38,7 +38,6 @@
|
|||||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@components/ui/dropdown-menu";
|
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@components/ui/dropdown-menu";
|
||||||
import GroupSelector from "@components/moderator/components/GroupSelector.svelte";
|
import GroupSelector from "@components/moderator/components/GroupSelector.svelte";
|
||||||
import { fightRepo } from "@components/repo/fight";
|
import { fightRepo } from "@components/repo/fight";
|
||||||
import type { Team } from "@components/types/team";
|
|
||||||
import type { EventModel } from "./eventmodel.svelte";
|
import type { EventModel } from "./eventmodel.svelte";
|
||||||
|
|
||||||
let { data = $bindable(), refresh }: { data: EventModel; refresh: () => void } = $props();
|
let { data = $bindable(), refresh }: { data: EventModel; refresh: () => void } = $props();
|
||||||
@@ -297,6 +296,7 @@
|
|||||||
bind:groups={data.groups}
|
bind:groups={data.groups}
|
||||||
event={data.event}
|
event={data.event}
|
||||||
onupdate={(update) => (data.fights = data.fights.map((v) => (v.id === update.id ? update : v)))}
|
onupdate={(update) => (data.fights = data.fights.map((v) => (v.id === update.id ? update : v)))}
|
||||||
|
{refresh}
|
||||||
></FightEditRow>
|
></FightEditRow>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
|
|||||||
@@ -1,15 +1,24 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { EventFight, EventFightEdit, ResponseGroups, SWEvent } from "@type/event";
|
import type { EventFight, EventFightEdit, ResponseGroups, SWEvent } from "@type/event";
|
||||||
import { Button } from "@components/ui/button";
|
import { Button } from "@components/ui/button";
|
||||||
import { EditIcon, MenuIcon, GroupIcon } from "lucide-svelte";
|
import { EditIcon, CopyIcon } from "lucide-svelte";
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@components/ui/dialog";
|
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger } from "@components/ui/dialog";
|
||||||
import FightEdit from "@components/moderator/components/FightEdit.svelte";
|
import FightEdit from "@components/moderator/components/FightEdit.svelte";
|
||||||
import type { Team } from "@components/types/team";
|
import type { Team } from "@components/types/team";
|
||||||
import { fightRepo } from "@components/repo/fight";
|
import { fightRepo } from "@components/repo/fight";
|
||||||
|
import { eventRepo } from "@components/repo/event";
|
||||||
|
|
||||||
let { fight, teams, groups = $bindable(), event, onupdate }: { fight: EventFight; teams: Team[]; groups: ResponseGroups[]; event: SWEvent; onupdate: (update: EventFight) => void } = $props();
|
let {
|
||||||
|
fight,
|
||||||
|
teams,
|
||||||
|
groups = $bindable(),
|
||||||
|
event,
|
||||||
|
onupdate,
|
||||||
|
refresh,
|
||||||
|
}: { fight: EventFight; teams: Team[]; groups: ResponseGroups[]; event: SWEvent; onupdate: (update: EventFight) => void; refresh: () => void } = $props();
|
||||||
|
|
||||||
let editOpen = $state(false);
|
let editOpen = $state(false);
|
||||||
|
let duplicateOpen = $state(false);
|
||||||
|
|
||||||
async function handleSave(fightData: EventFightEdit) {
|
async function handleSave(fightData: EventFightEdit) {
|
||||||
let f = await $fightRepo.updateFight(event.id, fight.id, {
|
let f = await $fightRepo.updateFight(event.id, fight.id, {
|
||||||
@@ -23,6 +32,18 @@
|
|||||||
|
|
||||||
editOpen = false;
|
editOpen = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handlyCopy(fightData: EventFightEdit) {
|
||||||
|
await $eventRepo.createFight(event.id.toString(), {
|
||||||
|
...fightData,
|
||||||
|
blueTeam: fightData.blueTeam.id,
|
||||||
|
redTeam: fightData.redTeam.id,
|
||||||
|
});
|
||||||
|
|
||||||
|
refresh();
|
||||||
|
|
||||||
|
duplicateOpen = false;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@@ -46,4 +67,24 @@
|
|||||||
</FightEdit>
|
</FightEdit>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
<Dialog bind:open={duplicateOpen}>
|
||||||
|
<DialogTrigger>
|
||||||
|
<Button variant="ghost" size="icon">
|
||||||
|
<CopyIcon />
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent>
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Fight duplizieren</DialogTitle>
|
||||||
|
<DialogDescription>Hier kannst du die Daten des duplizierten Fights ändern</DialogDescription>
|
||||||
|
</DialogHeader>
|
||||||
|
<FightEdit {fight} {teams} bind:groups {event} onSave={handlyCopy}>
|
||||||
|
{#snippet actions(dirty, submit)}
|
||||||
|
<DialogFooter>
|
||||||
|
<Button onclick={submit}>Speichern</Button>
|
||||||
|
</DialogFooter>
|
||||||
|
{/snippet}
|
||||||
|
</FightEdit>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -73,7 +73,7 @@
|
|||||||
<CommandEmpty>No Players found :(</CommandEmpty>
|
<CommandEmpty>No Players found :(</CommandEmpty>
|
||||||
<CommandGroup heading="Players">
|
<CommandGroup heading="Players">
|
||||||
{#each $players
|
{#each $players
|
||||||
.filter((v) => v.name.includes(playerSearch))
|
.filter((v) => v.name.toLowerCase().includes(playerSearch.toLowerCase()))
|
||||||
.filter((v, i) => i < 50)
|
.filter((v, i) => i < 50)
|
||||||
.filter((v) => !referees.some((k) => k.uuid === v.uuid)) as player (player.uuid)}
|
.filter((v) => !referees.some((k) => k.uuid === v.uuid)) as player (player.uuid)}
|
||||||
<CommandItem value={player.name} onSelect={() => addReferee(player.uuid)} keywords={[player.uuid]}>{player.name}</CommandItem>
|
<CommandItem value={player.name} onSelect={() => addReferee(player.uuid)} keywords={[player.uuid]}>{player.name}</CommandItem>
|
||||||
|
|||||||
@@ -20,12 +20,10 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Button } from "@components/ui/button";
|
import { Button } from "@components/ui/button";
|
||||||
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell, TableCaption } from "@components/ui/table";
|
import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell, TableCaption } from "@components/ui/table";
|
||||||
import type { ExtendedEvent } from "@type/event.ts";
|
|
||||||
import { eventRepo } from "@repo/event";
|
import { eventRepo } from "@repo/event";
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from "@components/ui/popover";
|
import { Popover, PopoverContent, PopoverTrigger } from "@components/ui/popover";
|
||||||
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@components/ui/command";
|
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@components/ui/command";
|
||||||
import { teams } from "@components/stores/stores";
|
import { teams } from "@components/stores/stores";
|
||||||
import type { Team } from "@components/types/team";
|
|
||||||
import type { EventModel } from "./eventmodel.svelte";
|
import type { EventModel } from "./eventmodel.svelte";
|
||||||
|
|
||||||
let { event = $bindable() }: { event: EventModel } = $props();
|
let { event = $bindable() }: { event: EventModel } = $props();
|
||||||
|
|||||||
@@ -37,10 +37,8 @@ export class OpenEditPage {
|
|||||||
contentToSave += "---\n\n";
|
contentToSave += "---\n\n";
|
||||||
}
|
}
|
||||||
contentToSave += this.content;
|
contentToSave += this.content;
|
||||||
const encodedContent = btoa(new TextEncoder().encode(contentToSave).reduce((data, byte) => data + String.fromCharCode(byte), ""));
|
|
||||||
|
|
||||||
console.log(encodedContent);
|
await get(pageRepo).updatePage(this.pageId, contentToSave, this.sha, prompt("Was hast du geändert?", `Updated ${this.pageTitle}`) ?? `Updated ${this.pageTitle}`, this.manager.branch);
|
||||||
//await get(pageRepo).updatePage(this.pageId, this.sha, encodedContent, this.manager.branch);
|
|
||||||
this.dirty = false;
|
this.dirty = false;
|
||||||
this.manager.reloadImages();
|
this.manager.reloadImages();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,20 +17,31 @@
|
|||||||
* 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 {readonly, writable} from "svelte/store";
|
import { readonly, writable } from "svelte/store";
|
||||||
|
|
||||||
import type {Readable, Subscriber, Unsubscriber} from "svelte/store";
|
import type { Readable, Subscriber, Unsubscriber } from "svelte/store";
|
||||||
|
|
||||||
export interface Cached<T> extends Readable<T> {
|
export interface Cached<T> extends Readable<T> {
|
||||||
reload: () => void;
|
reload: () => void;
|
||||||
|
future: Promise<T>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function cached<T>(normal: T, init: () => Promise<T>): Cached<T> {
|
export function cached<T>(normal: T, init: () => Promise<T>): Cached<T> {
|
||||||
const store = writable<T>(normal);
|
const store = writable<T>(normal);
|
||||||
|
const future = new Promise<T>((resolve) => {
|
||||||
|
let f = false;
|
||||||
|
store.subscribe((value) => {
|
||||||
|
if (f) {
|
||||||
|
resolve(value);
|
||||||
|
} else {
|
||||||
|
f = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
let first = true;
|
let first = true;
|
||||||
|
|
||||||
const reload = () => {
|
const reload = () => {
|
||||||
init().then(data => {
|
init().then((data) => {
|
||||||
store.set(data);
|
store.set(data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -45,6 +56,7 @@ export function cached<T>(normal: T, init: () => Promise<T>): Cached<T> {
|
|||||||
return store.subscribe(run, invalidate);
|
return store.subscribe(run, invalidate);
|
||||||
},
|
},
|
||||||
reload,
|
reload,
|
||||||
|
future,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +70,7 @@ export function cachedFamily<T, K>(normal: K, init: (arg0: T) => Promise<K>): (a
|
|||||||
let first = true;
|
let first = true;
|
||||||
|
|
||||||
const reload = () => {
|
const reload = () => {
|
||||||
init(arg).then(data => {
|
init(arg).then((data) => {
|
||||||
store.set(data);
|
store.set(data);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const gamemodes = cached<string[]>([], async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
|
export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
|
||||||
if (get(gamemodes).every((value) => value !== gamemode)) return [];
|
if ((await gamemodes.future).every((value) => value !== gamemode)) return [];
|
||||||
|
|
||||||
const res = await fetchWithToken(get(tokenStore), `/data/admin/gamemodes/${gamemode}/maps`);
|
const res = await fetchWithToken(get(tokenStore), `/data/admin/gamemodes/${gamemode}/maps`);
|
||||||
if (!res.ok) {
|
if (!res.ok) {
|
||||||
|
|||||||
@@ -24,14 +24,15 @@
|
|||||||
import { ScrollArea } from "$lib/components/ui/scroll-area";
|
import { ScrollArea } from "$lib/components/ui/scroll-area";
|
||||||
import { CalendarIcon } from "lucide-svelte";
|
import { CalendarIcon } from "lucide-svelte";
|
||||||
import { cn } from "@components/utils";
|
import { cn } from "@components/utils";
|
||||||
import type {ZonedDateTime} from "@internationalized/date";
|
import { fromDate, type ZonedDateTime } from "@internationalized/date";
|
||||||
|
import Input from "../input/input.svelte";
|
||||||
|
|
||||||
let {
|
let {
|
||||||
value = $bindable(),
|
value = $bindable(),
|
||||||
onChange
|
onChange,
|
||||||
}: {
|
}: {
|
||||||
value: ZonedDateTime
|
value: ZonedDateTime;
|
||||||
onChange?: ((date: ZonedDateTime | undefined) => void) | undefined
|
onChange?: ((date: ZonedDateTime | undefined) => void) | undefined;
|
||||||
} = $props();
|
} = $props();
|
||||||
|
|
||||||
let isOpen = $state(false);
|
let isOpen = $state(false);
|
||||||
@@ -63,13 +64,7 @@
|
|||||||
|
|
||||||
<Popover bind:open={isOpen}>
|
<Popover bind:open={isOpen}>
|
||||||
<PopoverTrigger>
|
<PopoverTrigger>
|
||||||
<Button
|
<Button variant="outline" class={cn("w-full justify-start text-left font-normal", !value && "text-muted-foreground")}>
|
||||||
variant="outline"
|
|
||||||
class={cn(
|
|
||||||
"w-full justify-start text-left font-normal",
|
|
||||||
!value && "text-muted-foreground"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<CalendarIcon class="mr-2 h-4 w-4" />
|
<CalendarIcon class="mr-2 h-4 w-4" />
|
||||||
{#if value}
|
{#if value}
|
||||||
{new Intl.DateTimeFormat("de-DE", {
|
{new Intl.DateTimeFormat("de-DE", {
|
||||||
@@ -86,23 +81,14 @@
|
|||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
|
|
||||||
<PopoverContent class="w-auto p-0">
|
<PopoverContent class="w-auto p-0">
|
||||||
|
<Input type="datetime-local" value={value.toDate().toISOString().slice(0, 16)} onchange={(e) => handleDateSelect(fromDate(e.target.valueAsDate, "Europe/Berlin"))} />
|
||||||
<div class="sm:flex">
|
<div class="sm:flex">
|
||||||
<Calendar
|
<Calendar mode="single" bind:value onValueChange={(date) => handleDateSelect(date)} initialFocus />
|
||||||
mode="single"
|
|
||||||
bind:value
|
|
||||||
onValueChange={(date) => handleDateSelect(date)}
|
|
||||||
initialFocus
|
|
||||||
/>
|
|
||||||
<div class="flex flex-col sm:flex-row sm:h-[300px] divide-y sm:divide-y-0 sm:divide-x">
|
<div class="flex flex-col sm:flex-row sm:h-[300px] divide-y sm:divide-y-0 sm:divide-x">
|
||||||
<ScrollArea class="w-64 sm:w-auto">
|
<ScrollArea class="w-64 sm:w-auto">
|
||||||
<div class="flex sm:flex-col p-2">
|
<div class="flex sm:flex-col p-2">
|
||||||
{#each [...hours].reverse() as hour}
|
{#each [...hours].reverse() as hour}
|
||||||
<Button
|
<Button size="icon" variant={value && value.hour === hour ? "default" : "ghost"} class="sm:w-full shrink-0 aspect-square" onclick={() => handleTimeChange("hour", hour)}>
|
||||||
size="icon"
|
|
||||||
variant={value && value.hour === hour ? "default" : "ghost"}
|
|
||||||
class="sm:w-full shrink-0 aspect-square"
|
|
||||||
onclick={() => handleTimeChange("hour", hour)}
|
|
||||||
>
|
|
||||||
{hour}
|
{hour}
|
||||||
</Button>
|
</Button>
|
||||||
{/each}
|
{/each}
|
||||||
@@ -113,12 +99,12 @@
|
|||||||
<div class="flex sm:flex-col p-2">
|
<div class="flex sm:flex-col p-2">
|
||||||
{#each Array.from({ length: 60 }, (_, i) => i) as minute}
|
{#each Array.from({ length: 60 }, (_, i) => i) as minute}
|
||||||
<Button
|
<Button
|
||||||
size="icon"
|
size="icon"
|
||||||
variant={value && value.minute === minute ? "default" : "ghost"}
|
variant={value && value.minute === minute ? "default" : "ghost"}
|
||||||
class="sm:w-full shrink-0 aspect-square"
|
class="sm:w-full shrink-0 aspect-square"
|
||||||
onclick={() => handleTimeChange("minute", minute)}
|
onclick={() => handleTimeChange("minute", minute)}
|
||||||
>
|
>
|
||||||
{minute.toString().padStart(2, '0')}
|
{minute.toString().padStart(2, "0")}
|
||||||
</Button>
|
</Button>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,29 +1,6 @@
|
|||||||
import Root from "./input.svelte";
|
import Root from "./input.svelte";
|
||||||
|
|
||||||
export type FormInputEvent<T extends Event = Event> = T & {
|
|
||||||
currentTarget: EventTarget & HTMLInputElement;
|
|
||||||
};
|
|
||||||
export type InputEvents = {
|
|
||||||
blur: FormInputEvent<FocusEvent>;
|
|
||||||
change: FormInputEvent<Event>;
|
|
||||||
click: FormInputEvent<MouseEvent>;
|
|
||||||
focus: FormInputEvent<FocusEvent>;
|
|
||||||
focusin: FormInputEvent<FocusEvent>;
|
|
||||||
focusout: FormInputEvent<FocusEvent>;
|
|
||||||
keydown: FormInputEvent<KeyboardEvent>;
|
|
||||||
keypress: FormInputEvent<KeyboardEvent>;
|
|
||||||
keyup: FormInputEvent<KeyboardEvent>;
|
|
||||||
mouseover: FormInputEvent<MouseEvent>;
|
|
||||||
mouseenter: FormInputEvent<MouseEvent>;
|
|
||||||
mouseleave: FormInputEvent<MouseEvent>;
|
|
||||||
mousemove: FormInputEvent<MouseEvent>;
|
|
||||||
paste: FormInputEvent<ClipboardEvent>;
|
|
||||||
input: FormInputEvent<InputEvent>;
|
|
||||||
wheel: FormInputEvent<WheelEvent>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export {
|
export {
|
||||||
Root,
|
Root,
|
||||||
//
|
//
|
||||||
Root as Input,
|
Root as Input,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,42 +1,39 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { HTMLInputAttributes } from "svelte/elements";
|
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from "svelte/elements";
|
||||||
import type { InputEvents } from "./index.js";
|
import { cn } from "@components/utils";
|
||||||
import { cn } from "$lib/components/utils.js";
|
import { type WithElementRef } from "bits-ui";
|
||||||
|
type InputType = Exclude<HTMLInputTypeAttribute, "file">;
|
||||||
type $$Props = HTMLInputAttributes;
|
type Props = WithElementRef<Omit<HTMLInputAttributes, "type"> & ({ type: "file"; files?: FileList } | { type?: InputType; files?: undefined })>;
|
||||||
type $$Events = InputEvents;
|
let { ref = $bindable(null), value = $bindable(), type, files = $bindable(), class: className, ...restProps }: Props = $props();
|
||||||
|
|
||||||
let className: $$Props["class"] = undefined;
|
|
||||||
export let value: $$Props["value"] = undefined;
|
|
||||||
export { className as class };
|
|
||||||
|
|
||||||
// Workaround for https://github.com/sveltejs/svelte/issues/9305
|
|
||||||
// Fixed in Svelte 5, but not backported to 4.x.
|
|
||||||
export let readonly: $$Props["readonly"] = undefined;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<input
|
{#if type === "file"}
|
||||||
class={cn(
|
<input
|
||||||
"border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex h-10 w-full rounded-md border px-3 py-2 text-sm file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
bind:this={ref}
|
||||||
className
|
data-slot="input"
|
||||||
)}
|
class={cn(
|
||||||
bind:value
|
"selection:bg-primary dark:bg-input/30 selection:text-primary-foreground border-input ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 pt-1.5 text-sm font-medium outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||||
{readonly}
|
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
||||||
on:blur
|
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||||
on:change
|
className
|
||||||
on:click
|
)}
|
||||||
on:focus
|
type="file"
|
||||||
on:focusin
|
bind:files
|
||||||
on:focusout
|
bind:value
|
||||||
on:keydown
|
{...restProps}
|
||||||
on:keypress
|
/>
|
||||||
on:keyup
|
{:else}
|
||||||
on:mouseover
|
<input
|
||||||
on:mouseenter
|
bind:this={ref}
|
||||||
on:mouseleave
|
data-slot="input"
|
||||||
on:mousemove
|
class={cn(
|
||||||
on:paste
|
"border-input bg-background selection:bg-primary dark:bg-input/30 selection:text-primary-foreground ring-offset-background placeholder:text-muted-foreground shadow-xs flex h-9 w-full min-w-0 rounded-md border px-3 py-1 text-base outline-none transition-[color,box-shadow] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||||
on:input
|
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
||||||
on:wheel|passive
|
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||||
{...$$restProps}
|
className
|
||||||
/>
|
)}
|
||||||
|
{type}
|
||||||
|
bind:value
|
||||||
|
{...restProps}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
|||||||
39
src/content/announcements/de/SC-Eventplan.md
Normal file
39
src/content/announcements/de/SC-Eventplan.md
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
---
|
||||||
|
title: SpaceCraft Eventplan
|
||||||
|
description: Der Kampfplan für das SpaceCraft Event am 29.6.
|
||||||
|
key: SC-Eventplan
|
||||||
|
created: 2025-06-28T00:00:00.000Z
|
||||||
|
tags:
|
||||||
|
- SpaceCraft
|
||||||
|
- Event
|
||||||
|
image: ../../../images/SpaceCraftWinners3.png
|
||||||
|
---
|
||||||
|
|
||||||
|
### Infos:
|
||||||
|
Eventleitung: TheBreadBeard
|
||||||
|
|
||||||
|
Sollten fights zu schnell vorbei sein, ist eine vorverschiebung der folgenden fights möglich. In diesem Fall wird eine Pause von 10 Minuten garantiert.
|
||||||
|
|
||||||
|
|
||||||
|
## Gruppen
|
||||||
|
|
||||||
|
<group-table data-event="72" data-group="2"> </group-table>
|
||||||
|
|
||||||
|
<group-table data-event="72" data-group="3"> </group-table>
|
||||||
|
|
||||||
|
## Tabelle
|
||||||
|
|
||||||
|

|
||||||
|
## Fights
|
||||||
|
|
||||||
|
### Gruppenphase
|
||||||
|
|
||||||
|
**Gruppe 1**
|
||||||
|
<fight-table data-event="72" data-group="2"> </group-table>
|
||||||
|
|
||||||
|
**Gruppe 2**
|
||||||
|
<fight-table data-event="72" data-group="3"> </group-table>
|
||||||
|
|
||||||
|
### KO-Phase
|
||||||
|
|
||||||
|
<fight-table data-event="72" data-group="4"> </group-table>
|
||||||
@@ -17,7 +17,7 @@ Die neue Physik nutzt ihr mit ***/nogravity*** auf dem Bau
|
|||||||
### Alle Infos zum Event:
|
### Alle Infos zum Event:
|
||||||
|
|
||||||
- Die Technik und das Design der Publics werden nochmal seperat Public gestellt. So könnt ihr, wenn ihr keine oder weniger eigene Technik bauen wollt, einfacher die Public technik verwenden.
|
- Die Technik und das Design der Publics werden nochmal seperat Public gestellt. So könnt ihr, wenn ihr keine oder weniger eigene Technik bauen wollt, einfacher die Public technik verwenden.
|
||||||
- Das Event findet am 19.06.2025 um 16 Uhr statt
|
- Das Event findet am 29.06.2025 um 16 Uhr statt
|
||||||
- Es gibt kein Entern
|
- Es gibt kein Entern
|
||||||
- Kits können wie bei WG und MWG selbst erstellt werden
|
- Kits können wie bei WG und MWG selbst erstellt werden
|
||||||
- es wird Redstone TKO verwendet
|
- es wird Redstone TKO verwendet
|
||||||
@@ -37,12 +37,13 @@ Die neue Physik nutzt ihr mit ***/nogravity*** auf dem Bau
|
|||||||
- Wasser darf in Kanonen verwendet werden
|
- Wasser darf in Kanonen verwendet werden
|
||||||
- Dadurch könnt ihr TNT einfacher komprimieren. Wasser muss nicht mehr den Zweck erfüllen, die Kanone vor eigenem Schaden zu bewahren
|
- Dadurch könnt ihr TNT einfacher komprimieren. Wasser muss nicht mehr den Zweck erfüllen, die Kanone vor eigenem Schaden zu bewahren
|
||||||
- 32 Projektile pro Seite
|
- 32 Projektile pro Seite
|
||||||
|
- Unterpunkt: Crossbows
|
||||||
|
- Es gibt keinen Techhider
|
||||||
# Regelwerk für das Event:
|
# Regelwerk für das Event:
|
||||||
|
|
||||||
## Definitionen
|
## Definitionen
|
||||||
|
|
||||||
Ein AirShip ist eine beidseitig bewaffnete Struktur in Minecraft 1.19 und sieht flugfähig aus.
|
Ein AirShip ist eine beidseitig bewaffnete Struktur in Minecraft 1.20 und sieht flugfähig aus.
|
||||||
|
|
||||||
## Maße
|
## Maße
|
||||||
|
|
||||||
@@ -57,16 +58,41 @@ Ein AirShip ist eine beidseitig bewaffnete Struktur in Minecraft 1.19 und sieht
|
|||||||
- 51 breit
|
- 51 breit
|
||||||
- 32 hoch
|
- 32 hoch
|
||||||
|
|
||||||
|
Technik, welche für die Funktion der Kanonen nicht relevant ist, darf sich in maßen auch im Design-Bereich befinden.
|
||||||
|
|
||||||
Entfernung von Mitte zu Mitte des Gegners: 100 Block
|
Entfernung von Mitte zu Mitte des Gegners: 100 Block
|
||||||
|
|
||||||
Es dürfen keine Blöcke über die Grenze des Designbereiches bewegt werden
|
Es dürfen keine Blöcke über die Grenze des Designbereiches bewegt werden
|
||||||
|
|
||||||
|
Panzerung darf nur im Technikbereich verbaut werden.
|
||||||
|
|
||||||
## Projektile
|
## Projektile
|
||||||
|
|
||||||
Ein Projektil ist ein gezündetes TNT, welches in die gegnerische Hälfte wechselt. Eine Kanone ist eine Vorrichtung zum Beschleunigen von Projektilen. Es ist verboten, mehrere Kanonen als eine Einzige auszugeben.
|
Ein Projektil ist ein gezündetes TNT, welches in die gegnerische Hälfte wechselt. Eine Kanone ist eine Vorrichtung zum Beschleunigen von Projektilen. Es ist verboten, mehrere Kanonen als eine Einzige auszugeben.
|
||||||
|
|
||||||
Jeder Seite stehen bis zu 32 Projektile zur Verfügung. Sie müssen auf der dem Gegner zugewandten Seite oder, wenn beidseitig, in der Mitte gezündet werden
|
Jeder Seite stehen bis zu 32 Projektile zur Verfügung. Sie müssen auf der dem Gegner zugewandten Seite oder, wenn beidseitig, in der Mitte gezündet werden
|
||||||
|
|
||||||
|
## Crossbows
|
||||||
|
|
||||||
|
Kanonen, welche, ohne nachgeladen werden zu müssen, mehrere Schüsse abgeben können, Müssen:
|
||||||
|
- Jeden Schuss das TNT an den selben Punkten zünden.
|
||||||
|
- Für jedes Projektil das die Kanone für einen Schuss maximal zünden könnte, mindestens 1,5 Redstone Tick zwischen den Schüssen warten.
|
||||||
|
|
||||||
|
##### Beispiele
|
||||||
|
|
||||||
|
| Projektile | Ticks |
|
||||||
|
|-------|------------|
|
||||||
|
| 1 | 1,5 |
|
||||||
|
| 2 | 3 |
|
||||||
|
| 3 | 4,5 |
|
||||||
|
| 4 | 6 |
|
||||||
|
| ... | ... |
|
||||||
|
| 8 | 12 |
|
||||||
|
| 12 | 18 |
|
||||||
|
| 16 | 24 |
|
||||||
|
| ... | ... |
|
||||||
|
| 32 | 48 |
|
||||||
|
|
||||||
## Siegesbedingung
|
## Siegesbedingung
|
||||||
|
|
||||||
- Ein AirShip wird zu 60% (nach prozentualer Redstonekomponenten) zerstört.
|
- Ein AirShip wird zu 60% (nach prozentualer Redstonekomponenten) zerstört.
|
||||||
@@ -76,10 +102,63 @@ Jeder Seite stehen bis zu 32 Projektile zur Verfügung. Sie müssen auf der dem
|
|||||||
|
|
||||||
## Blöcke
|
## Blöcke
|
||||||
|
|
||||||
Es dürfen maximal je 30 TNT und 32 Werfer verbaut werden. Verbaute Blöcke dürfen einen TNT-Widerstand von maximal 6 haben. Ausgenommen davon ist Wasser, welches ausschließlich in Kanonen verbaut werden darf.
|
Es dürfen maximal je 32 TNT und 32 Werfer verbaut werden. Verbaute Blöcke dürfen einen TNT-Widerstand von maximal 6 haben. Ausgenommen davon ist Wasser, welches ausschließlich in Kanonen verbaut werden darf.
|
||||||
|
|
||||||
Inventar-Blöcke dürfen nur mit Blumen, Honigflaschen und Pferderüstungen gefüllt sein. Zusätzlich dürfen sich in Kisten und Fässern TNT sowie in Werfern 2·64 Feuerbälle, 2·64 reguläre Pfeile oder 1 Eimer zum Aufheben von powdered Snow befinden.
|
Inventar-Blöcke dürfen nur mit Blumen, Honigflaschen und Pferderüstungen gefüllt sein. Zusätzlich dürfen sich in Kisten und Fässern TNT sowie in Werfern 2·64 Feuerbälle, 2·64 reguläre Pfeile oder 1 Eimer zum Aufheben von powdered Snow befinden.
|
||||||
|
|
||||||
Zusätzlich verboten: Monster Spawner, Eis, Nether Portal, Silberfischsteine, Leuchtfeuer, unsichtbare Blöcke (Ausnahme: structure_void) Das Duplizieren von Blöcken und Entities ist verboten.
|
Zusätzlich verboten: Monster Spawner, Eis, Nether Portal, Silberfischsteine, Leuchtfeuer, unsichtbare Blöcke (Ausnahme: structure_void) Das Duplizieren von Blöcken und Entities ist verboten.
|
||||||
Blöcke aus dem eigenen AS dürfen nicht in großer Menge entfernt werden.
|
Blöcke aus dem eigenen AS dürfen nicht in großer Menge entfernt werden.
|
||||||
Bug-Using ist nicht erwünscht.
|
Bug-Using ist nicht erwünscht.
|
||||||
|
|
||||||
|
# Versteckte Blöcke (Ersetzt durch Stein)
|
||||||
|
|
||||||
|
- WATER
|
||||||
|
- NOTE_BLOCK
|
||||||
|
- POWERED_RAIL
|
||||||
|
- DETECTOR_RAIL
|
||||||
|
- PISTON
|
||||||
|
- PISTON_HEAD
|
||||||
|
- STICKY_PISTON
|
||||||
|
- TNT
|
||||||
|
- CHEST
|
||||||
|
- TRAPPED_CHEST
|
||||||
|
- REDSTONE_WIRE
|
||||||
|
- STONE_PRESSURE_PLATE
|
||||||
|
- IRON_DOOR
|
||||||
|
- OAK_PRESSURE_PLATE
|
||||||
|
- SPRUCE_PRESSURE_PLATE
|
||||||
|
- BIRCH_PRESSURE_PLATE
|
||||||
|
- JUNGLE_PRESSURE_PLATE
|
||||||
|
- ACACIA_PRESSURE_PLATE
|
||||||
|
- DARK_OAK_PRESSURE_PLATE
|
||||||
|
- REDSTONE_TORCH
|
||||||
|
- REDSTONE_WALL_TORCH
|
||||||
|
- REPEATER
|
||||||
|
- BREWING_STAND
|
||||||
|
- TRIPWIRE_HOOK
|
||||||
|
- TRIPWIRE
|
||||||
|
- HEAVY_WEIGHTED_PRESSURE_PLATE
|
||||||
|
- LIGHT_WEIGHTED_PRESSURE_PLATE
|
||||||
|
- COMPARATOR
|
||||||
|
- REDSTONE_BLOCK
|
||||||
|
- HOPPER
|
||||||
|
- ACTIVATOR_RAIL
|
||||||
|
- DROPPER
|
||||||
|
- SLIME_BLOCK
|
||||||
|
- OBSERVER
|
||||||
|
- HONEY_BLOCK
|
||||||
|
- LEVER
|
||||||
|
|
||||||
|
# Zusatzinhalte folgender Blöcke (z.B. Text, Inhalt von Inventaren) werden mit versteckt:
|
||||||
|
|
||||||
|
- SIGN
|
||||||
|
- DISPENSER
|
||||||
|
- CHEST
|
||||||
|
- TRAPPED_CHEST
|
||||||
|
- FURNACE
|
||||||
|
- BREWING_STAND
|
||||||
|
- HOPPER
|
||||||
|
- DROPPER
|
||||||
|
- SHULKER_BOX
|
||||||
|
- JUKEBOX
|
||||||
|
- COMPARATOR
|
||||||
@@ -2,29 +2,31 @@
|
|||||||
title: SteamWar Arcade Eventplan
|
title: SteamWar Arcade Eventplan
|
||||||
key: sw-arcade-eventplan
|
key: sw-arcade-eventplan
|
||||||
description: Der Eventplan für SteamWar Arcade
|
description: Der Eventplan für SteamWar Arcade
|
||||||
created: 2025-05-14
|
created: 2025-05-14T00:00:00.000Z
|
||||||
tags:
|
tags:
|
||||||
- event
|
- event
|
||||||
- towerrun
|
- towerrun
|
||||||
- misslewars
|
- misslewars
|
||||||
- tntleague
|
- tntleague
|
||||||
- arcade
|
- arcade
|
||||||
image: ../../../images/sw-arcade-image.png
|
image: ../../../images/sw-arcade-image.png
|
||||||
---
|
---
|
||||||
|
|
||||||
### Infos:
|
### Infos:
|
||||||
|
|
||||||
Eventleitung: Chaoscaot
|
Eventleitung: Chaoscaot
|
||||||
|
|
||||||
Fights werden nach Möglichkeit mit einer Pause von 10 Minuten vorverschoben.
|
Fights werden nach Möglichkeit mit einer Pause von 10 Minuten vorverschoben.
|
||||||
|
|
||||||
# Kämpfe
|
# Kämpfe
|
||||||
|
|
||||||
## Punkte aus der Gruppenphase
|
## Punkte aus der Gruppenphase
|
||||||
|
|
||||||
<group-table data-event="70"> </group-table>
|
<group-table data-event="70"> </group-table>
|
||||||
|
|
||||||
### Fights
|
### Fights
|
||||||
|
|
||||||
<fight-table data-event="70" data-group="Gruppe 1"> </fight-table>
|
<fight-table data-event="70" data-group="1"> </fight-table>
|
||||||
|
|
||||||
## Auswahl des Spielmodis
|
## Auswahl des Spielmodis
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +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 {defineCollection, reference, z} from "astro:content";
|
import { defineCollection, reference, z } from "astro:content";
|
||||||
|
import { docsLoader } from "@astrojs/starlight/loaders";
|
||||||
|
import { docsSchema } from "@astrojs/starlight/schema";
|
||||||
|
|
||||||
export const pagesSchema = z.object({
|
export const pagesSchema = z.object({
|
||||||
title: z.string().min(1).max(80),
|
title: z.string().min(1).max(80),
|
||||||
@@ -55,8 +57,7 @@ export const downloads = defineCollection({
|
|||||||
schema: z.object({
|
schema: z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
description: z.string(),
|
description: z.string(),
|
||||||
url: z.string().url()
|
url: z.string().url().or(z.record(z.string(), z.string())),
|
||||||
.or(z.record(z.string(), z.string())),
|
|
||||||
sourceUrl: z.string().url().optional(),
|
sourceUrl: z.string().url().optional(),
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
@@ -71,45 +72,50 @@ export const rules = defineCollection({
|
|||||||
|
|
||||||
export const announcements = defineCollection({
|
export const announcements = defineCollection({
|
||||||
type: "content",
|
type: "content",
|
||||||
schema: ({image}) => z.object({
|
schema: ({ image }) =>
|
||||||
title: z.string(),
|
z.object({
|
||||||
description: z.string(),
|
title: z.string(),
|
||||||
author: z.string().optional(),
|
description: z.string(),
|
||||||
image: image().optional(),
|
author: z.string().optional(),
|
||||||
tags: z.array(z.string()),
|
image: image().optional(),
|
||||||
created: z.date(),
|
tags: z.array(z.string()),
|
||||||
key: z.string(),
|
created: z.date(),
|
||||||
}),
|
key: z.string(),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const publics = defineCollection({
|
export const publics = defineCollection({
|
||||||
type: "data",
|
type: "data",
|
||||||
schema: ({image}) => z.object({
|
schema: ({ image }) =>
|
||||||
"name": z.string(),
|
z.object({
|
||||||
"description": z.string(),
|
name: z.string(),
|
||||||
"id": z.number().positive(),
|
description: z.string(),
|
||||||
"creator": z.string().array().optional(),
|
id: z.number().positive(),
|
||||||
"showcase": z.string().url().optional(),
|
creator: z.string().array().optional(),
|
||||||
"camera": z.object({
|
showcase: z.string().url().optional(),
|
||||||
"fov": z.number().optional(),
|
camera: z
|
||||||
"near": z.number().optional(),
|
.object({
|
||||||
"far": z.number().optional(),
|
fov: z.number().optional(),
|
||||||
"distance": z.number().optional(),
|
near: z.number().optional(),
|
||||||
}).optional(),
|
far: z.number().optional(),
|
||||||
"image": image(),
|
distance: z.number().optional(),
|
||||||
"alt": image().optional(),
|
})
|
||||||
"xray": image().optional(),
|
.optional(),
|
||||||
"gamemode": reference("modes"),
|
image: image(),
|
||||||
"3d": z.boolean().optional().default(true),
|
alt: image().optional(),
|
||||||
}),
|
xray: image().optional(),
|
||||||
|
gamemode: reference("modes"),
|
||||||
|
"3d": z.boolean().optional().default(true),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const collections = {
|
export const collections = {
|
||||||
"pages": pages,
|
pages: pages,
|
||||||
"help": help,
|
help: help,
|
||||||
"modes": modes,
|
modes: modes,
|
||||||
"rules": rules,
|
rules: rules,
|
||||||
"downloads": downloads,
|
downloads: downloads,
|
||||||
"announcements": announcements,
|
announcements: announcements,
|
||||||
"publics": publics,
|
publics: publics,
|
||||||
|
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
|
||||||
};
|
};
|
||||||
|
|||||||
5
src/content/docs/docs/api/index.md
Normal file
5
src/content/docs/docs/api/index.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: Überblick
|
||||||
|
---
|
||||||
|
|
||||||
|
WIP
|
||||||
5
src/content/docs/docs/bausystem/index.md
Normal file
5
src/content/docs/docs/bausystem/index.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: Überblick
|
||||||
|
---
|
||||||
|
|
||||||
|
WIP
|
||||||
5
src/content/docs/docs/bausystem/script/index.md
Normal file
5
src/content/docs/docs/bausystem/script/index.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: Script Überblick
|
||||||
|
---
|
||||||
|
|
||||||
|
WIP
|
||||||
5
src/content/docs/docs/fightsystem/index.md
Normal file
5
src/content/docs/docs/fightsystem/index.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: Überblick
|
||||||
|
---
|
||||||
|
|
||||||
|
WIP
|
||||||
24
src/content/docs/docs/index.mdx
Normal file
24
src/content/docs/docs/index.mdx
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
---
|
||||||
|
title: Startseite
|
||||||
|
desciption: Startseite der SteamWar Dokumentation
|
||||||
|
---
|
||||||
|
|
||||||
|
import { Tabs, TabItem } from '@astrojs/starlight/components';
|
||||||
|
|
||||||
|
Herzlich Willkommen in der SteamWar Dokumentation!
|
||||||
|
|
||||||
|
## SteamWar beitreten
|
||||||
|
SteamWar ist ein Minecraft Java Server.
|
||||||
|
|
||||||
|
<Tabs>
|
||||||
|
<TabItem label="Java Edition">
|
||||||
|
- IP: `steamwar.de`
|
||||||
|
- Empholene Version: `1.21.5`
|
||||||
|
</TabItem>
|
||||||
|
<TabItem label="Bedrock Edition">
|
||||||
|
- IP: `steamwar.de`
|
||||||
|
- Port: `19132`
|
||||||
|
- Version: `Aktuellste`
|
||||||
|
</TabItem>
|
||||||
|
</Tabs>
|
||||||
|
|
||||||
5
src/content/docs/docs/minigames/index.md
Normal file
5
src/content/docs/docs/minigames/index.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: Überblick
|
||||||
|
---
|
||||||
|
|
||||||
|
WIP
|
||||||
5
src/content/docs/docs/schematicsystem/index.md
Normal file
5
src/content/docs/docs/schematicsystem/index.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
title: Überblick
|
||||||
|
---
|
||||||
|
|
||||||
|
WIP
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
"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.21.4": "https://git.steamwar.de/SteamWar/AdvancedScripts/releases/download/2.2.0/AdvancedScripts-2.2.0.jar",
|
"1.21.4": "https://git.steamwar.de/SteamWar/AdvancedScripts/releases/download/2.2.0/AdvancedScripts-2.2.0.jar",
|
||||||
|
"1.21.3": "https://git.steamwar.de/SteamWar/AdvancedScripts/releases/download/2.2.1/AdvancedScripts-2.2.1.jar",
|
||||||
"1.20.6": "https://git.steamwar.de/SteamWar/AdvancedScripts/releases/download/2.1.0/AdvancedScripts-2.1.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",
|
"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"
|
"Hotkey script": "https://git.steamwar.de/SteamWar/SteamWar/src/branch/main/BauSystem/hotkeys.lua"
|
||||||
|
|||||||
5
src/content/modes/spacecraft.json
Normal file
5
src/content/modes/spacecraft.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"translationKey": "sc",
|
||||||
|
"main": false,
|
||||||
|
"ranked": false
|
||||||
|
}
|
||||||
@@ -209,6 +209,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"login": {
|
"login": {
|
||||||
|
"page": "SteamWar - Login",
|
||||||
"title": "Login",
|
"title": "Login",
|
||||||
"placeholder": {
|
"placeholder": {
|
||||||
"username": "Nutzername...",
|
"username": "Nutzername...",
|
||||||
@@ -219,7 +220,7 @@
|
|||||||
"password": "Passwort",
|
"password": "Passwort",
|
||||||
"repeat": "Passwort Wiederholen"
|
"repeat": "Passwort Wiederholen"
|
||||||
},
|
},
|
||||||
"setPassword": "Wie setzte ich mein Passwort?",
|
"setPassword": "Wie setze ich mein Passwort?",
|
||||||
"submit": "Login",
|
"submit": "Login",
|
||||||
"error": "Falscher Nutzername oder falsches Passwort"
|
"error": "Falscher Nutzername oder falsches Passwort"
|
||||||
},
|
},
|
||||||
|
|||||||
BIN
src/images/SpaceCraftWinners3.png
Normal file
BIN
src/images/SpaceCraftWinners3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 212 KiB |
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* This file is a part of the SteamWar software.
|
* This file is a part of the SteamWar software.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2024 SteamWar.de-Serverteam
|
* Copyright (C) 2025 SteamWar.de-Serverteam
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
|||||||
@@ -22,10 +22,7 @@ import { fontFamily } from "tailwindcss/defaultTheme";
|
|||||||
/** @type {import('tailwindcss').Config} */
|
/** @type {import('tailwindcss').Config} */
|
||||||
const config = {
|
const config = {
|
||||||
darkMode: ["class"],
|
darkMode: ["class"],
|
||||||
content: [
|
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}", "./node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}"],
|
||||||
"./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}",
|
|
||||||
"./node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}",
|
|
||||||
],
|
|
||||||
safelist: ["dark"],
|
safelist: ["dark"],
|
||||||
theme: {
|
theme: {
|
||||||
container: {
|
container: {
|
||||||
|
|||||||
Reference in New Issue
Block a user