55 Commits

Author SHA1 Message Date
5d7eb3b8fb Merge pull request 'Merge branch mwgl' (#16) from mwgl into master
All checks were successful
SteamWarCI Build successful
Reviewed-on: #16
2025-07-28 13:02:14 +02:00
6933af1554 Updated mwgl.md
All checks were successful
SteamWarCI Build successful
2025-07-28 13:01:56 +02:00
e607ea1343 Updated mwgl.md
All checks were successful
SteamWarCI Build successful
2025-07-28 13:00:51 +02:00
b0ae4e978e Create page announcements/de/mwgl.md
All checks were successful
SteamWarCI Build successful
2025-07-28 12:57:57 +02:00
8fe273f3e0 Add Open-Source section to documentation
All checks were successful
SteamWarCI Build successful
2025-07-10 17:57:42 +02:00
1b48cbe1f4 Update edit link base URL to point to the master branch
All checks were successful
SteamWarCI Build successful
2025-07-10 13:51:09 +02:00
7276552ed1 Merge branch 'master' of https://git.steamwar.de/SteamWar/Website
All checks were successful
SteamWarCI Build successful
2025-07-10 13:49:15 +02:00
a2ef92aaad Add Docs 2025-07-10 13:49:00 +02:00
8b85cd0729 src/content/modes/spacecraft.json aktualisiert
All checks were successful
SteamWarCI Build successful
2025-06-29 22:51:13 +02:00
2d024cf64b Create page modes/spacecraft.json
Some checks failed
SteamWarCI Build failed
2025-06-29 22:49:58 +02:00
13d76d0a97 Updated SC-Eventplan.md
All checks were successful
SteamWarCI Build successful
2025-06-29 20:34:55 +02:00
e65fadb65c Updated SC-Eventplan.md
All checks were successful
SteamWarCI Build successful
2025-06-29 20:32:23 +02:00
6b4693b7f1 Updated SC-Eventplan.md
All checks were successful
SteamWarCI Build successful
2025-06-29 20:29:54 +02:00
92282006fe Add Image SpaceCraftWinners3.png
All checks were successful
SteamWarCI Build successful
2025-06-29 20:29:16 +02:00
5457632598 Fix formatting of teamPoints calculation in GroupTable component for improved readability
All checks were successful
SteamWarCI Build successful
2025-06-29 19:47:35 +02:00
bed134f8e0 Fix group points retrieval in GroupTable component to ensure correct mapping of event groups
All checks were successful
SteamWarCI Build successful
2025-06-29 19:45:18 +02:00
353a415990 Refactor GroupTable component to use $props for event, group, and rows; simplify teamPoints calculation with derived state
All checks were successful
SteamWarCI Build successful
2025-06-29 19:41:43 +02:00
3c6d0f8528 Fix
All checks were successful
SteamWarCI Build successful
2025-06-29 14:00:09 +02:00
887235dc86 Enhance caching mechanism by adding future promise to cached function and updating maps retrieval logic to use it
All checks were successful
SteamWarCI Build successful
2025-06-29 13:54:03 +02:00
a99a066f0d Merge branch 'master' of https://git.steamwar.de/SteamWar/Website
All checks were successful
SteamWarCI Build successful
2025-06-29 11:24:07 +02:00
e5e3c15b07 Add refresh functionality and duplicate fight feature in FightEditRow component 2025-06-29 11:23:51 +02:00
fb74689c39 Updated SC-Eventplan.md
All checks were successful
SteamWarCI Build successful
2025-06-29 09:15:11 +02:00
18b1f97a84 src/content/announcements/de/SC-Eventplan.md aktualisiert
All checks were successful
SteamWarCI Build successful
2025-06-29 03:07:37 +02:00
53b81db2c4 Updated SC-Eventplan.md
Some checks failed
SteamWarCI Build failed
2025-06-29 02:44:17 +02:00
2314b4c5b5 Updated SC-Eventplan.md
Some checks failed
SteamWarCI Build failed
2025-06-28 17:53:43 +02:00
6a81936f77 Updated SC-Eventplan.md
Some checks failed
SteamWarCI Build failed
2025-06-28 17:32:32 +02:00
a128de3213 Updated SC-Eventplan.md
Some checks failed
SteamWarCI Build failed
2025-06-28 17:31:58 +02:00
6df661f885 Create page announcements/de/SC-Eventplan.md
Some checks failed
SteamWarCI Build failed
2025-06-28 17:21:11 +02:00
a32d84ed86 Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-27 16:12:51 +02:00
e60cebc9a3 Updated sw-arcade-fightplan.md
All checks were successful
SteamWarCI Build successful
2025-06-27 00:31:58 +02:00
3576d5e034 Refactor save method to remove base64 encoding for page content
All checks were successful
SteamWarCI Build successful
2025-06-27 00:31:08 +02:00
d5c7d8fc27 Updated sw-arcade-fightplan.md
Some checks failed
SteamWarCI Build failed
2025-06-27 00:29:26 +02:00
ce895e9297 Add default value to prompt for change description in page update
All checks were successful
SteamWarCI Build successful
2025-06-27 00:28:37 +02:00
7c83ad0937 Add prompt for change description in page update
All checks were successful
SteamWarCI Build successful
2025-06-27 00:28:16 +02:00
5e0a9d89b3 Fixing
All checks were successful
SteamWarCI Build successful
2025-06-27 00:24:13 +02:00
2a8b98ce5b Update copyright year to 2025 in table.css
All checks were successful
SteamWarCI Build successful
2025-06-26 23:57:55 +02:00
427818d6bf Fixing
Some checks failed
SteamWarCI Build failed
2025-06-26 23:56:45 +02:00
8424c14ca9 Remove unused import of ExtendedEvent from TeamTable.svelte
Some checks failed
SteamWarCI Build failed
2025-06-26 23:54:21 +02:00
602a7e1453 Remove unused import of Team from TeamTable.svelte
Some checks failed
SteamWarCI Build failed
2025-06-26 23:53:03 +02:00
9f31c5ff0c Remove unused import of Team from EventFightList.svelte
Some checks failed
SteamWarCI Build failed
2025-06-26 23:50:28 +02:00
8a41b98c58 Remove unused import of ExtendedEvent from EventFightList.svelte
Some checks failed
SteamWarCI Build failed
2025-06-26 23:49:09 +02:00
9fc5c500f5 Merge pull request 'Event Brackets' (#11) from event-brackets into master
All checks were successful
SteamWarCI Build successful
Reviewed-on: #11
2025-06-26 23:40:59 +02:00
bc879d7cad Add login.page to de.json
All checks were successful
SteamWarCI Build successful
2025-06-26 15:02:08 +02:00
96f0019dc1 Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-22 16:55:31 +02:00
7418b608ab Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-21 23:33:31 +02:00
3802b9bc26 Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-13 14:21:16 +02:00
03effd2fd2 src/content/downloads/advancedscripts.json aktualisiert
All checks were successful
SteamWarCI Build successful
2025-06-12 20:35:23 +02:00
a4669a897b Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-06 19:20:33 +02:00
eac0d5592d src/i18n/common/de.json aktualisiert
All checks were successful
SteamWarCI Build successful
2025-06-03 14:11:22 +02:00
bd9aea8f35 Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-03 09:53:14 +02:00
6e715cee07 Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-03 07:11:00 +02:00
4147a1d243 Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-02 23:46:46 +02:00
46dba2a6f9 Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-02 23:44:12 +02:00
3d8ad3a129 Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-02 23:40:31 +02:00
7d50a4db12 Update spacheship-event-ankündigung-und-regelwerk.md
All checks were successful
SteamWarCI Build successful
2025-06-02 23:30:42 +02:00
31 changed files with 440 additions and 201 deletions

View File

@ -1,4 +1,4 @@
import {defineConfig, sharpImageService} from "astro/config";
import { defineConfig, sharpImageService } from "astro/config";
import svelte from "@astrojs/svelte";
import tailwind from "@astrojs/tailwind";
import configureI18n from "./astro-i18n.adapter";
@ -8,6 +8,8 @@ import robotsTxt from "astro-robots-txt";
import path from "node:path";
import mdx from "@astrojs/mdx";
import starlight from "@astrojs/starlight";
// https://astro.build/config
export default defineConfig({
output: "static",
@ -18,14 +20,40 @@ export default defineConfig({
site: "https://steamwar.de",
integrations: [
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/master/",
},
}),
tailwind({
configFile: "./tailwind.config.js",
applyBaseStyles: false,
}),
configureI18n(),
sitemap({
i18n: {
defaultLocale: "en", locales: {
en: "en-US", de: "de-DE",
defaultLocale: "en",
locales: {
en: "en-US",
de: "de-DE",
},
},
}),
@ -49,7 +77,7 @@ export default defineConfig({
{ userAgent: "omgili", disallow: "/" },
{ userAgent: "OmigliBot", disallow: "/" },
{ userAgent: "PerplexityBot", disallow: "/" },
{ userAgent: "Timpibot", disallow: "/" }
{ userAgent: "Timpibot", disallow: "/" },
],
}),
mdx(),
@ -66,7 +94,7 @@ export default defineConfig({
"@layouts": path.resolve("./src/layouts"),
"@repo": path.resolve("./src/components/repo"),
"@stores": path.resolve("./src/components/stores"),
"$lib": path.resolve("./src"),
$lib: path.resolve("./src"),
},
},
},

View File

@ -58,6 +58,8 @@
"dependencies": {
"@astrojs/mdx": "^4.3.0",
"@astrojs/sitemap": "^3.4.0",
"@astrojs/starlight": "^0.34.4",
"@astrojs/starlight-tailwind": "^4.0.1",
"@codemirror/commands": "^6.8.1",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/view": "^6.36.8",
@ -84,11 +86,9 @@
"svelte-spa-router": "^4.0.1"
},
"pnpm": {
"ignoredBuiltDependencies": [
"esbuild"
],
"onlyBuiltDependencies": [
"@parcel/watcher",
"esbuild",
"sharp"
]
}

View File

@ -24,35 +24,24 @@
import type { ExtendedEvent } from "@type/event.ts";
import "@styles/table.css";
export let event: ExtendedEvent;
export let group: number;
export let rows: number = 1;
let {
event,
group,
rows = 1,
}: {
event: ExtendedEvent;
group: number;
rows?: number;
} = $props();
$: teamPoints = event.teams
.map((team) => {
let fights = event.fights.filter((fight) => fight.blueTeam.id === team.id || fight.redTeam.id === team.id);
if (group !== undefined) {
fights = fights.filter((fight) => fight.group?.id === group);
}
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);
let teamPoints = $derived(
Object.entries(event.groups.find((g) => g.id === group)?.points ?? {})
.map(([teamId, points]) => ({
team: event.teams.find((t) => t.id === Number(teamId))!!,
points: points,
}))
.sort((a, b) => b.points - a.points)
);
</script>
<div class="p-3 bg-gray-200 dark:bg-neutral-800 rounded-2xl w-3/4 mx-auto">

View File

@ -20,7 +20,7 @@
<script lang="ts">
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 { type ColumnFiltersState, getCoreRowModel, getFilteredRowModel, getGroupedRowModel, getSortedRowModel, type RowSelectionState, type SortingState } from "@tanstack/table-core";
import { columns } from "./columns";
@ -38,7 +38,6 @@
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@components/ui/dropdown-menu";
import GroupSelector from "@components/moderator/components/GroupSelector.svelte";
import { fightRepo } from "@components/repo/fight";
import type { Team } from "@components/types/team";
import type { EventModel } from "./eventmodel.svelte";
let { data = $bindable(), refresh }: { data: EventModel; refresh: () => void } = $props();
@ -297,6 +296,7 @@
bind:groups={data.groups}
event={data.event}
onupdate={(update) => (data.fights = data.fights.map((v) => (v.id === update.id ? update : v)))}
{refresh}
></FightEditRow>
</TableCell>
</TableRow>

View File

@ -1,15 +1,24 @@
<script lang="ts">
import type { EventFight, EventFightEdit, ResponseGroups, SWEvent } from "@type/event";
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 FightEdit from "@components/moderator/components/FightEdit.svelte";
import type { Team } from "@components/types/team";
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 duplicateOpen = $state(false);
async function handleSave(fightData: EventFightEdit) {
let f = await $fightRepo.updateFight(event.id, fight.id, {
@ -23,6 +32,18 @@
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>
<div>
@ -46,4 +67,24 @@
</FightEdit>
</DialogContent>
</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>

View File

@ -73,7 +73,7 @@
<CommandEmpty>No Players found :(</CommandEmpty>
<CommandGroup heading="Players">
{#each $players
.filter((v) => v.name.includes(playerSearch))
.filter((v) => v.name.toLowerCase().includes(playerSearch.toLowerCase()))
.filter((v, i) => i < 50)
.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>

View File

@ -20,12 +20,10 @@
<script lang="ts">
import { Button } from "@components/ui/button";
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 { Popover, PopoverContent, PopoverTrigger } from "@components/ui/popover";
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@components/ui/command";
import { teams } from "@components/stores/stores";
import type { Team } from "@components/types/team";
import type { EventModel } from "./eventmodel.svelte";
let { event = $bindable() }: { event: EventModel } = $props();

View File

@ -37,10 +37,8 @@ export class OpenEditPage {
contentToSave += "---\n\n";
}
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, this.sha, encodedContent, this.manager.branch);
await get(pageRepo).updatePage(this.pageId, contentToSave, this.sha, prompt("Was hast du geändert?", `Updated ${this.pageTitle}`) ?? `Updated ${this.pageTitle}`, this.manager.branch);
this.dirty = false;
this.manager.reloadImages();
}

View File

@ -17,20 +17,31 @@
* 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> {
reload: () => void;
future: Promise<T>;
}
export function cached<T>(normal: T, init: () => Promise<T>): Cached<T> {
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;
const reload = () => {
init().then(data => {
init().then((data) => {
store.set(data);
});
};
@ -45,6 +56,7 @@ export function cached<T>(normal: T, init: () => Promise<T>): Cached<T> {
return store.subscribe(run, invalidate);
},
reload,
future,
};
}
@ -58,7 +70,7 @@ export function cachedFamily<T, K>(normal: K, init: (arg0: T) => Promise<K>): (a
let first = true;
const reload = () => {
init(arg).then(data => {
init(arg).then((data) => {
store.set(data);
});
};

View File

@ -55,7 +55,7 @@ export const gamemodes = cached<string[]>([], async () => {
});
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`);
if (!res.ok) {

View File

@ -24,14 +24,15 @@
import { ScrollArea } from "$lib/components/ui/scroll-area";
import { CalendarIcon } from "lucide-svelte";
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 {
value = $bindable(),
onChange
onChange,
}: {
value: ZonedDateTime
onChange?: ((date: ZonedDateTime | undefined) => void) | undefined
value: ZonedDateTime;
onChange?: ((date: ZonedDateTime | undefined) => void) | undefined;
} = $props();
let isOpen = $state(false);
@ -63,13 +64,7 @@
<Popover bind:open={isOpen}>
<PopoverTrigger>
<Button
variant="outline"
class={cn(
"w-full justify-start text-left font-normal",
!value && "text-muted-foreground"
)}
>
<Button variant="outline" class={cn("w-full justify-start text-left font-normal", !value && "text-muted-foreground")}>
<CalendarIcon class="mr-2 h-4 w-4" />
{#if value}
{new Intl.DateTimeFormat("de-DE", {
@ -86,23 +81,14 @@
</PopoverTrigger>
<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">
<Calendar
mode="single"
bind:value
onValueChange={(date) => handleDateSelect(date)}
initialFocus
/>
<Calendar 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">
<ScrollArea class="w-64 sm:w-auto">
<div class="flex sm:flex-col p-2">
{#each [...hours].reverse() as hour}
<Button
size="icon"
variant={value && value.hour === hour ? "default" : "ghost"}
class="sm:w-full shrink-0 aspect-square"
onclick={() => handleTimeChange("hour", hour)}
>
<Button size="icon" variant={value && value.hour === hour ? "default" : "ghost"} class="sm:w-full shrink-0 aspect-square" onclick={() => handleTimeChange("hour", hour)}>
{hour}
</Button>
{/each}
@ -113,12 +99,12 @@
<div class="flex sm:flex-col p-2">
{#each Array.from({ length: 60 }, (_, i) => i) as minute}
<Button
size="icon"
variant={value && value.minute === minute ? "default" : "ghost"}
class="sm:w-full shrink-0 aspect-square"
onclick={() => handleTimeChange("minute", minute)}
size="icon"
variant={value && value.minute === minute ? "default" : "ghost"}
class="sm:w-full shrink-0 aspect-square"
onclick={() => handleTimeChange("minute", minute)}
>
{minute.toString().padStart(2, '0')}
{minute.toString().padStart(2, "0")}
</Button>
{/each}
</div>

View File

@ -1,29 +1,6 @@
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 {
Root,
//
Root as Input,
Root,
//
Root as Input,
};

View File

@ -1,42 +1,39 @@
<script lang="ts">
import type { HTMLInputAttributes } from "svelte/elements";
import type { InputEvents } from "./index.js";
import { cn } from "$lib/components/utils.js";
type $$Props = HTMLInputAttributes;
type $$Events = InputEvents;
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;
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from "svelte/elements";
import { cn } from "@components/utils";
import { type WithElementRef } from "bits-ui";
type InputType = Exclude<HTMLInputTypeAttribute, "file">;
type Props = WithElementRef<Omit<HTMLInputAttributes, "type"> & ({ type: "file"; files?: FileList } | { type?: InputType; files?: undefined })>;
let { ref = $bindable(null), value = $bindable(), type, files = $bindable(), class: className, ...restProps }: Props = $props();
</script>
<input
class={cn(
"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",
className
)}
bind:value
{readonly}
on:blur
on:change
on:click
on:focus
on:focusin
on:focusout
on:keydown
on:keypress
on:keyup
on:mouseover
on:mouseenter
on:mouseleave
on:mousemove
on:paste
on:input
on:wheel|passive
{...$$restProps}
/>
{#if type === "file"}
<input
bind:this={ref}
data-slot="input"
class={cn(
"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",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className
)}
type="file"
bind:files
bind:value
{...restProps}
/>
{:else}
<input
bind:this={ref}
data-slot="input"
class={cn(
"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",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className
)}
{type}
bind:value
{...restProps}
/>
{/if}

View 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
![](https://cdn.discordapp.com/attachments/690535200865910794/1388779302782501014/SPaceship_Eventplan.png?ex=68623904&is=6860e784&hm=5f32d5f34449aee7e2b58b9c16d657f0d3b08e2cd5b341a7b31559a1b1b30f27&)
## 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>

View File

@ -0,0 +1,24 @@
---
title: MiniWarGearLiga Ankündigung
description: Die MiniWargear-Liga 2025 findet am 27./28. September statt.
key: mwgl
created: 2025-07-28T00:00:00.000Z
tags:
- event
- miniwargear
---
**Ahoi Liebe Community,**
Es ist wieder so weit die MiniWargear-Liga findet auch dieses Jahr wieder statt.
Infos zum Event:
* Die MWGL findet am Wochenende des **27./28.09.2025** um **16 Uhr** statt.
* Einsendeschluss ist der **22.09.2025** um 23:59 Uhr bis dahin muss ein MWG gemäß Regelwerk vorhanden sein.
* Hotfixes (geringe Änderungen wie z.B. das Fixen von Läufen usw.) dürfen bis zum **25.09.2025** um 23:59 Uhr nachgereicht werden.
* Max. **4 Kämpfer** pro Team
* Normales SW-MWG-Regelwerk mit automatischen Kanonen
* Es wird einen eigenen Schem-Typ geben.
* Der Schem-Name muss mit dem Teamkürzel enden.
* Gefightet wird mit getrenntem Spectate- und Fightserver (wie bei der WGS)

View File

@ -17,7 +17,7 @@ Die neue Physik nutzt ihr mit ***/nogravity*** auf dem Bau
### 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.
- 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
- Kits können wie bei WG und MWG selbst erstellt werden
- 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
- 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
- Unterpunkt: Crossbows
- Es gibt keinen Techhider
# Regelwerk für das Event:
## 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
@ -57,16 +58,41 @@ Ein AirShip ist eine beidseitig bewaffnete Struktur in Minecraft 1.19 und sieht
- 51 breit
- 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
Es dürfen keine Blöcke über die Grenze des Designbereiches bewegt werden
Panzerung darf nur im Technikbereich verbaut werden.
## 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.
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
- 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
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.
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.
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

View File

@ -2,29 +2,31 @@
title: SteamWar Arcade Eventplan
key: sw-arcade-eventplan
description: Der Eventplan für SteamWar Arcade
created: 2025-05-14
created: 2025-05-14T00:00:00.000Z
tags:
- event
- towerrun
- misslewars
- tntleague
- arcade
- event
- towerrun
- misslewars
- tntleague
- arcade
image: ../../../images/sw-arcade-image.png
---
### Infos:
Eventleitung: Chaoscaot
Fights werden nach Möglichkeit mit einer Pause von 10 Minuten vorverschoben.
# Kämpfe
## Punkte aus der Gruppenphase
<group-table data-event="70"> </group-table>
### 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

View File

@ -17,7 +17,9 @@
* 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({
title: z.string().min(1).max(80),
@ -55,8 +57,7 @@ export const downloads = defineCollection({
schema: z.object({
name: z.string(),
description: z.string(),
url: z.string().url()
.or(z.record(z.string(), z.string())),
url: z.string().url().or(z.record(z.string(), z.string())),
sourceUrl: z.string().url().optional(),
}),
});
@ -71,45 +72,50 @@ export const rules = defineCollection({
export const announcements = defineCollection({
type: "content",
schema: ({image}) => z.object({
title: z.string(),
description: z.string(),
author: z.string().optional(),
image: image().optional(),
tags: z.array(z.string()),
created: z.date(),
key: z.string(),
}),
schema: ({ image }) =>
z.object({
title: z.string(),
description: z.string(),
author: z.string().optional(),
image: image().optional(),
tags: z.array(z.string()),
created: z.date(),
key: z.string(),
}),
});
export const publics = defineCollection({
type: "data",
schema: ({image}) => z.object({
"name": z.string(),
"description": z.string(),
"id": z.number().positive(),
"creator": z.string().array().optional(),
"showcase": z.string().url().optional(),
"camera": z.object({
"fov": z.number().optional(),
"near": z.number().optional(),
"far": z.number().optional(),
"distance": z.number().optional(),
}).optional(),
"image": image(),
"alt": image().optional(),
"xray": image().optional(),
"gamemode": reference("modes"),
"3d": z.boolean().optional().default(true),
}),
schema: ({ image }) =>
z.object({
name: z.string(),
description: z.string(),
id: z.number().positive(),
creator: z.string().array().optional(),
showcase: z.string().url().optional(),
camera: z
.object({
fov: z.number().optional(),
near: z.number().optional(),
far: z.number().optional(),
distance: z.number().optional(),
})
.optional(),
image: image(),
alt: image().optional(),
xray: image().optional(),
gamemode: reference("modes"),
"3d": z.boolean().optional().default(true),
}),
});
export const collections = {
"pages": pages,
"help": help,
"modes": modes,
"rules": rules,
"downloads": downloads,
"announcements": announcements,
"publics": publics,
pages: pages,
help: help,
modes: modes,
rules: rules,
downloads: downloads,
announcements: announcements,
publics: publics,
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
};

View File

@ -0,0 +1,5 @@
---
title: Überblick
---
WIP

View File

@ -0,0 +1,5 @@
---
title: Überblick
---
WIP

View File

@ -0,0 +1,5 @@
---
title: Script Überblick
---
WIP

View File

@ -0,0 +1,5 @@
---
title: Überblick
---
WIP

View File

@ -0,0 +1,29 @@
---
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>
## Open-Source
Die SteamWar Software ist Open-Source und auf der internen [Gitea](https://git.steamwar.de) verfügbar. Jeglicher Code ist unter der [GNU Affero General Public License v3.0](https://www.gnu.org/licenses/agpl-3.0.en.html) lizenziert. Das bedeutet, dass du den Code frei nutzen, modifizieren und verteilen kannst, solange du den Code ebenfalls unter der AGPL lizenziert verfügbar machst.
Bugs und Feature Requests können im [Gitea Issue Tracker](https://git.steamwar.de/SteamWar/SteamWar/issues) erstellt werden. Contributions sind immer willkommen! Bitte erstelle einen Pull Request im [SteamWar Repository](https://git.steamwar.de/SteamWar/SteamWar).

View File

@ -0,0 +1,5 @@
---
title: Überblick
---
WIP

View File

@ -0,0 +1,5 @@
---
title: Überblick
---
WIP

View File

@ -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.",
"url": {
"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.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"

View File

@ -0,0 +1,5 @@
{
"translationKey": "sc",
"main": false,
"ranked": false
}

View File

@ -209,6 +209,7 @@
}
},
"login": {
"page": "SteamWar - Login",
"title": "Login",
"placeholder": {
"username": "Nutzername...",
@ -219,7 +220,7 @@
"password": "Passwort",
"repeat": "Passwort Wiederholen"
},
"setPassword": "Wie setzte ich mein Passwort?",
"setPassword": "Wie setze ich mein Passwort?",
"submit": "Login",
"error": "Falscher Nutzername oder falsches Passwort"
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

View File

@ -1,7 +1,7 @@
/*
* 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
* it under the terms of the GNU Affero General Public License as published by

View File

@ -22,10 +22,7 @@ import { fontFamily } from "tailwindcss/defaultTheme";
/** @type {import('tailwindcss').Config} */
const config = {
darkMode: ["class"],
content: [
"./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}",
"./node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}",
],
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}", "./node_modules/flowbite-svelte/**/*.{html,js,svelte,ts}"],
safelist: ["dark"],
theme: {
container: {