Compare commits
7 Commits
acaae13379
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 7deb2a7d95 | |||
| 8cee39ad1c | |||
| f622c09fd4 | |||
| 9227f2de30 | |||
| ecb0d8ebc2 | |||
| c38d538f93 | |||
| e32e0fb972 |
@@ -1 +0,0 @@
|
||||
^C
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
> server-wiki@0.0.1 dev
|
||||
> astro dev --host 0.0.0.0 --port 4321
|
||||
|
||||
[vite] connected.
|
||||
@@ -1,6 +1,54 @@
|
||||
# Dependencies and build output
|
||||
node_modules
|
||||
dist
|
||||
.astro
|
||||
dist
|
||||
|
||||
# VCS metadata
|
||||
.git
|
||||
.gitignore
|
||||
|
||||
# Local Codex/dev artifacts
|
||||
.codex*
|
||||
.codex/
|
||||
.codex-dev.*
|
||||
.codex-cache/
|
||||
.tmp*
|
||||
*.tmp
|
||||
|
||||
# Logs and runtime junk
|
||||
*.log
|
||||
*.log.*
|
||||
*.out
|
||||
*.err
|
||||
*.pid
|
||||
*.pid.lock
|
||||
logs
|
||||
preview*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Env and local-only config
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
*.local
|
||||
|
||||
# OS/editor files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
.vscode
|
||||
.idea
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Local caches
|
||||
tmp
|
||||
.cache
|
||||
temp
|
||||
coverage
|
||||
.nyc_output
|
||||
.pnpm-store
|
||||
.npm
|
||||
*.tsbuildinfo
|
||||
|
||||
47
.gitignore
vendored
@@ -1,4 +1,51 @@
|
||||
node_modules/
|
||||
.astro/
|
||||
dist/
|
||||
|
||||
# Local Codex/dev artifacts
|
||||
.codex*
|
||||
.codex/
|
||||
.codex-dev.*
|
||||
.codex-cache/
|
||||
.tmp*
|
||||
*.tmp
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
*.log.*
|
||||
*.out
|
||||
*.err
|
||||
*.pid
|
||||
*.pid.lock
|
||||
logs/
|
||||
preview*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
# Env and local-only config
|
||||
.env
|
||||
.env.*
|
||||
!.env.example
|
||||
*.local
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Editor / local workspace junk
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Caches / tooling
|
||||
.cache/
|
||||
tmp/
|
||||
temp/
|
||||
coverage/
|
||||
.nyc_output/
|
||||
.pnpm-store/
|
||||
.npm/
|
||||
*.tsbuildinfo
|
||||
|
||||
2417
.tmp_live_index.html
93
Makefile
Normal file
@@ -0,0 +1,93 @@
|
||||
# ================================
|
||||
# Настройки
|
||||
# ================================
|
||||
COMPOSE=docker compose
|
||||
SERVICE=primoguard
|
||||
|
||||
# Список команд
|
||||
.PHONY: help install dev build preview up down restart logs pull update ps shell clean prune tunnel
|
||||
|
||||
# ================================
|
||||
# Помощь
|
||||
# ================================
|
||||
help:
|
||||
@echo "Доступные команды:"
|
||||
@echo " make install - установить npm зависимости"
|
||||
@echo " make dev - локальный запуск Astro для разработки"
|
||||
@echo " make build - продакшн сборка Astro"
|
||||
@echo " make preview - предпросмотр продакшн сборки"
|
||||
@echo " make up - поднять Docker контейнер"
|
||||
@echo " make down - остановить Docker контейнер"
|
||||
@echo " make restart - перезапустить Docker контейнер"
|
||||
@echo " make logs - смотреть логи Docker"
|
||||
@echo " make pull - обновить проект через git pull"
|
||||
@echo " make update - обновить проект и перезапустить Docker"
|
||||
@echo " make ps - список контейнеров"
|
||||
@echo " make shell - зайти внутрь контейнера"
|
||||
@echo " make clean - остановить контейнер"
|
||||
@echo " make prune - очистить Docker мусор"
|
||||
@echo " make tunnel - запустить Cloudflare Tunnel"
|
||||
|
||||
# ================================
|
||||
# Локальная разработка
|
||||
# ================================
|
||||
install:
|
||||
npm install
|
||||
|
||||
dev:
|
||||
npm run dev
|
||||
|
||||
build:
|
||||
npm run build
|
||||
|
||||
preview:
|
||||
npm run preview
|
||||
|
||||
# ================================
|
||||
# Docker
|
||||
# ================================
|
||||
up:
|
||||
$(COMPOSE) up -d --build
|
||||
|
||||
down:
|
||||
$(COMPOSE) down
|
||||
|
||||
restart:
|
||||
$(COMPOSE) down
|
||||
$(COMPOSE) up -d --build
|
||||
|
||||
logs:
|
||||
$(COMPOSE) logs -f
|
||||
|
||||
ps:
|
||||
$(COMPOSE) ps
|
||||
|
||||
shell:
|
||||
docker exec -it $(SERVICE) sh
|
||||
|
||||
# ================================
|
||||
# Git + Docker
|
||||
# ================================
|
||||
pull:
|
||||
git pull
|
||||
|
||||
update:
|
||||
$(COMPOSE) down
|
||||
git pull
|
||||
$(COMPOSE) up -d --build
|
||||
$(COMPOSE) logs -f
|
||||
|
||||
# ================================
|
||||
# Очистка
|
||||
# ================================
|
||||
clean:
|
||||
$(COMPOSE) down
|
||||
|
||||
prune:
|
||||
docker system prune -f
|
||||
|
||||
# ================================
|
||||
# Публичный доступ
|
||||
# ================================
|
||||
tunnel:
|
||||
cloudflared tunnel --url http://127.0.0.1:4321 --protocol http2 --edge-ip-version 4
|
||||
@@ -1,6 +1,7 @@
|
||||
import { defineConfig } from 'astro/config';
|
||||
import starlight from '@astrojs/starlight';
|
||||
|
||||
|
||||
export default defineConfig({
|
||||
site: 'https://wiki.example.com',
|
||||
vite: {
|
||||
@@ -25,6 +26,7 @@ export default defineConfig({
|
||||
}
|
||||
},
|
||||
tagline: 'Нереалистичный архив игрового мира',
|
||||
favicon: '/photo_2026-03-14_11-18-15.jpg',
|
||||
customCss: ['/src/styles/wiki-egames.css'],
|
||||
lastUpdated: true,
|
||||
disable404Route: true,
|
||||
@@ -45,48 +47,40 @@ export default defineConfig({
|
||||
label: 'О сервере',
|
||||
items: [
|
||||
{ label: 'Главная', link: '/' },
|
||||
{ label: 'Сюжет', link: '/story/' },
|
||||
{ label: 'Начало игры', link: '/getting-started/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Введение',
|
||||
items: [
|
||||
{ label: 'Часто задаваемые вопросы', link: '/faq/' },
|
||||
{ label: 'Правила', link: '/rules/' }
|
||||
{ label: 'О проекте', link: '/about-server/' },
|
||||
{ label: 'Правила', link: '/rules/' },
|
||||
{ label: 'Часто задаваемые вопросы', link: '/faq/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Игровые системы',
|
||||
items: [
|
||||
{ label: 'Гайды', link: '/guides/' },
|
||||
{ label: 'Механики', link: '/mechanics/' },
|
||||
{ label: 'Профессии / классы / расы', link: '/professions/' },
|
||||
{ label: 'Экономика', link: '/economy/' },
|
||||
{ label: 'Предметы и ресурсы', link: '/items-resources/' },
|
||||
{ label: 'Общее', link: '/general/' },
|
||||
{ label: 'Команды', link: '/commands/' },
|
||||
{ label: 'Города', link: '/cities/' },
|
||||
{ label: 'Крафты', link: '/crafting/' },
|
||||
{
|
||||
label: 'Алкоголь',
|
||||
items: [
|
||||
{ label: 'Варка алкоголя', link: '/alcohol-brewing/' },
|
||||
{ label: 'Как варить', link: '/alcohol-brewing/' },
|
||||
{ label: 'Рецепты напитков', link: '/alcohol-recipes/' }
|
||||
]
|
||||
}
|
||||
},
|
||||
{ label: 'EasyArmorStands', link: '/easyarmorstands/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Техническое',
|
||||
label: 'Тех. Информация',
|
||||
items: [
|
||||
{ label: 'Все IP', link: '/all-ip/' },
|
||||
{ label: 'Контакты и ссылки', link: '/contacts/' }
|
||||
]
|
||||
},
|
||||
{
|
||||
label: 'Для редакторов',
|
||||
items: [
|
||||
{ label: 'Как редактировать wiki', link: '/editing/' },
|
||||
{ label: 'Шаблон новой страницы', link: '/templates/new-page-template/' }
|
||||
]
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
name: parabox-wiki
|
||||
|
||||
services:
|
||||
wiki:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: parabox-wiki
|
||||
ports:
|
||||
- "4321:80"
|
||||
#ports:
|
||||
#- "4321:80"
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- proxy
|
||||
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
|
||||
BIN
public/ChatGPT Image 22 апр. 2026 г., 05_34_46.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
public/brand-logo.png
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
public/crafts/anvil-variant-base.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/crafts/anvil-variant-l.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
public/crafts/bell.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/crafts/bundle.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
public/crafts/cartography-table.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/crafts/clock-to-gold-ingot-smelting.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/crafts/compass-to-iron-ingot-smelting.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/crafts/diamond-ore-variant-k.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/crafts/diamond-ore-variant-s.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/crafts/dispenser.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/crafts/dragons-breath.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
public/crafts/enchanted-book.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
public/crafts/fletching-table.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/crafts/glow-ink-sac.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/crafts/invisible-glow-item-frame.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/crafts/invisible-item-frame.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/crafts/invisible-light.png
Normal file
|
After Width: | Height: | Size: 8.8 KiB |
BIN
public/crafts/jukebox.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/crafts/knowledge-book.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/crafts/loom.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
public/crafts/name-tag.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/crafts/note-block.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/crafts/phantom-membrane.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
public/crafts/recovery-compass-to-compass-smelting.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
public/crafts/red-glass-smelting.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
BIN
public/crafts/stripped-log-stonecutter.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/crafts/sturdy-slab.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
public/icons/minimal-solid/community.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
BIN
public/icons/minimal-solid/exclamation.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/icons/minimal-solid/game-controller.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
public/icons/minimal-solid/gear.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
BIN
public/icons/minimal-solid/keyboard.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
BIN
public/icons/minimal-solid/message.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
public/icons/minimal-solid/safe.png
Normal file
|
After Width: | Height: | Size: 2.2 KiB |
BIN
public/icons/minimal-solid/user-profile.png
Normal file
|
After Width: | Height: | Size: 3.9 KiB |
@@ -2,10 +2,11 @@
|
||||
import { Icon } from '@astrojs/starlight/components';
|
||||
|
||||
const { editUrl } = Astro.locals.starlightRoute;
|
||||
const showEditorDocs = import.meta.env.PUBLIC_SHOW_EDITOR_DOCS === 'true';
|
||||
---
|
||||
|
||||
{
|
||||
editUrl && (
|
||||
showEditorDocs && editUrl && (
|
||||
<a href={editUrl} class="wiki-edit-link sl-flex print:hidden" target="_blank" rel="noopener noreferrer">
|
||||
<Icon name="pencil" size="1.05em" />
|
||||
Редактировать страницу
|
||||
|
||||
@@ -3,7 +3,6 @@ import config from 'virtual:starlight/user-config';
|
||||
|
||||
import LanguageSelect from 'virtual:starlight/components/LanguageSelect';
|
||||
import Search from 'virtual:starlight/components/Search';
|
||||
import SiteTitle from 'virtual:starlight/components/SiteTitle';
|
||||
import SocialIcons from 'virtual:starlight/components/SocialIcons';
|
||||
|
||||
const shouldRenderSearch =
|
||||
@@ -11,8 +10,8 @@ const shouldRenderSearch =
|
||||
|
||||
const topLinks = [
|
||||
{ label: 'Старт', href: '/getting-started/' },
|
||||
{ label: 'Гайды', href: '/guides/' },
|
||||
{ label: 'Механики', href: '/mechanics/' },
|
||||
{ label: 'Команды', href: '/commands/' },
|
||||
{ label: 'Города', href: '/cities/' },
|
||||
{ label: 'FAQ', href: '/faq/' },
|
||||
{ label: 'Правила', href: '/rules/' }
|
||||
];
|
||||
@@ -21,7 +20,15 @@ const topLinks = [
|
||||
<div class="wiki-header-shell">
|
||||
<div class="header wiki-header">
|
||||
<div class="title-wrapper sl-flex">
|
||||
<SiteTitle />
|
||||
<a class="wiki-brand" href="/" aria-label="PARABOX PROJECT">
|
||||
<span class="wiki-brand__icon" aria-hidden="true">
|
||||
<img src="/brand-logo.png" alt="" loading="eager" decoding="async" />
|
||||
</span>
|
||||
<span class="wiki-brand__copy">
|
||||
<span class="wiki-brand__title">PARABOX</span>
|
||||
<span class="wiki-brand__subtitle">PROJECT</span>
|
||||
</span>
|
||||
</a>
|
||||
<nav class="wiki-top-nav" aria-label="Быстрая навигация">
|
||||
{
|
||||
topLinks.map((link) => (
|
||||
@@ -89,10 +96,365 @@ const topLinks = [
|
||||
</div>
|
||||
|
||||
<button class="wiki-back-to-top" type="button" aria-label="Прокрутить в начало" data-back-to-top>
|
||||
<span aria-hidden="true">↑</span>
|
||||
<svg aria-hidden="true" class="wiki-back-to-top__icon" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M12 18V6" />
|
||||
<path d="m6.8 11.2 5.2-5.2 5.2 5.2" />
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<script>
|
||||
const emojiPattern = (() => {
|
||||
try {
|
||||
return new RegExp('[\\p{Extended_Pictographic}\\u2600-\\u27BF]', 'gu');
|
||||
} catch {
|
||||
return /[\u2600-\u27BF]/g;
|
||||
}
|
||||
})();
|
||||
|
||||
const stripDecorativeSymbols = (value) =>
|
||||
value
|
||||
.replace(emojiPattern, '')
|
||||
.replace(/\s{2,}/g, ' ')
|
||||
.trim();
|
||||
|
||||
const normalizeLabelKey = (value) => stripDecorativeSymbols(value).toLowerCase();
|
||||
|
||||
const minimalIconByHeading = new Map([
|
||||
['настройки', '/icons/minimal-solid/gear.png'],
|
||||
['личные сообщения', '/icons/minimal-solid/message.png'],
|
||||
['игнор', '/icons/minimal-solid/safe.png'],
|
||||
['развлечения', '/icons/minimal-solid/game-controller.png'],
|
||||
['rp и взаимодействие', '/icons/minimal-solid/community.png'],
|
||||
['статус игрока', '/icons/minimal-solid/user-profile.png'],
|
||||
['информация', '/icons/minimal-solid/exclamation.png'],
|
||||
['символы', '/icons/minimal-solid/keyboard.png']
|
||||
]);
|
||||
|
||||
const sanitizeNavLabels = () => {
|
||||
const navLinks = document.querySelectorAll('.sidebar-content a, starlight-toc a, mobile-starlight-toc a');
|
||||
|
||||
navLinks.forEach((linkNode) => {
|
||||
if (!(linkNode instanceof HTMLElement)) return;
|
||||
|
||||
const sourceText = linkNode.textContent;
|
||||
if (!sourceText) return;
|
||||
|
||||
const normalizedText = stripDecorativeSymbols(sourceText);
|
||||
|
||||
if (!normalizedText || normalizedText === sourceText.trim()) return;
|
||||
linkNode.textContent = normalizedText;
|
||||
});
|
||||
};
|
||||
|
||||
const sanitizeDocHeadings = () => {
|
||||
const headings = document.querySelectorAll('.sl-markdown-content :is(h1, h2, h3, h4, h5, h6)');
|
||||
|
||||
headings.forEach((headingNode) => {
|
||||
if (!(headingNode instanceof HTMLElement)) return;
|
||||
|
||||
const sourceText = headingNode.textContent;
|
||||
if (!sourceText) return;
|
||||
|
||||
const normalizedText = stripDecorativeSymbols(sourceText);
|
||||
|
||||
if (!normalizedText || normalizedText === sourceText.trim()) return;
|
||||
headingNode.textContent = normalizedText;
|
||||
});
|
||||
};
|
||||
|
||||
const decorateSectionIcons = () => {
|
||||
const headings = document.querySelectorAll('.sl-markdown-content h3');
|
||||
|
||||
headings.forEach((headingNode) => {
|
||||
if (!(headingNode instanceof HTMLElement)) return;
|
||||
|
||||
const sourceText = headingNode.textContent;
|
||||
if (!sourceText) return;
|
||||
|
||||
const normalizedText = normalizeLabelKey(sourceText);
|
||||
const iconPath = minimalIconByHeading.get(normalizedText);
|
||||
if (!iconPath) return;
|
||||
|
||||
if (headingNode.querySelector('.minimal-heading-icon')) return;
|
||||
|
||||
const iconNode = document.createElement('span');
|
||||
iconNode.className = 'minimal-heading-icon';
|
||||
iconNode.setAttribute('aria-hidden', 'true');
|
||||
iconNode.style.setProperty('--icon-url', `url('${iconPath}')`);
|
||||
headingNode.prepend(iconNode);
|
||||
});
|
||||
};
|
||||
|
||||
const trimDestination = (value, maxLength = 42) => {
|
||||
if (value.length <= maxLength) return value;
|
||||
return `${value.slice(0, Math.max(0, maxLength - 1))}…`;
|
||||
};
|
||||
|
||||
const decodePath = (value) => {
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
} catch {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
const annotateLinkDestinations = () => {
|
||||
const links = document.querySelectorAll('a[href]');
|
||||
|
||||
links.forEach((linkNode) => {
|
||||
if (!(linkNode instanceof HTMLAnchorElement)) return;
|
||||
if (linkNode.dataset.linkAnnotated === 'true') return;
|
||||
|
||||
const rawHref = linkNode.getAttribute('href')?.trim();
|
||||
if (!rawHref || rawHref.toLowerCase().startsWith('javascript:')) return;
|
||||
|
||||
let parsedUrl;
|
||||
try {
|
||||
parsedUrl = new URL(rawHref, window.location.href);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const isHashOnly = rawHref.startsWith('#');
|
||||
const isHttp = parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:';
|
||||
const isMail = parsedUrl.protocol === 'mailto:';
|
||||
const isTel = parsedUrl.protocol === 'tel:';
|
||||
const isExternal = isHttp && parsedUrl.origin !== window.location.origin;
|
||||
const isSamePageAnchor =
|
||||
!isExternal && !!parsedUrl.hash && parsedUrl.pathname === window.location.pathname;
|
||||
|
||||
const isContentLink = linkNode.closest('.sl-markdown-content') instanceof HTMLElement;
|
||||
const shouldDecorate =
|
||||
isContentLink &&
|
||||
!isHashOnly &&
|
||||
!linkNode.classList.contains('sl-anchor-link') &&
|
||||
!linkNode.classList.contains('map-cta-button') &&
|
||||
!linkNode.classList.contains('map-ghost-button') &&
|
||||
!linkNode.classList.contains('sl-link-button');
|
||||
|
||||
if (shouldDecorate) {
|
||||
let kind = 'internal';
|
||||
if (isExternal) kind = 'external';
|
||||
else if (isMail) kind = 'mail';
|
||||
else if (isTel) kind = 'tel';
|
||||
else if (isSamePageAnchor) kind = 'anchor';
|
||||
linkNode.dataset.linkKind = kind;
|
||||
|
||||
let destination = '';
|
||||
if (isExternal) destination = parsedUrl.hostname.replace(/^www\./, '');
|
||||
else if (isMail) destination = rawHref.replace(/^mailto:/i, '');
|
||||
else if (isTel) destination = rawHref.replace(/^tel:/i, '');
|
||||
else destination = `${decodePath(parsedUrl.pathname)}${parsedUrl.hash || ''}`;
|
||||
if (destination) {
|
||||
linkNode.dataset.linkDestination = trimDestination(destination);
|
||||
}
|
||||
}
|
||||
|
||||
if (isExternal) {
|
||||
const relValues = new Set((linkNode.rel || '').split(/\s+/).filter(Boolean));
|
||||
relValues.add('noopener');
|
||||
relValues.add('noreferrer');
|
||||
linkNode.rel = Array.from(relValues).join(' ');
|
||||
if (!linkNode.target) {
|
||||
linkNode.target = '_blank';
|
||||
}
|
||||
}
|
||||
|
||||
if (!linkNode.title) {
|
||||
if (isHashOnly || isSamePageAnchor) {
|
||||
linkNode.title = `Переход к разделу: ${parsedUrl.hash || rawHref}`;
|
||||
} else if (isExternal) {
|
||||
linkNode.title = `Внешняя ссылка: ${parsedUrl.hostname.replace(/^www\./, '')}`;
|
||||
} else if (isMail) {
|
||||
linkNode.title = `Написать: ${rawHref.replace(/^mailto:/i, '')}`;
|
||||
} else if (isTel) {
|
||||
linkNode.title = `Позвонить: ${rawHref.replace(/^tel:/i, '')}`;
|
||||
} else {
|
||||
linkNode.title = `Перейти: ${decodePath(parsedUrl.pathname)}${parsedUrl.hash || ''}`;
|
||||
}
|
||||
}
|
||||
|
||||
linkNode.dataset.linkAnnotated = 'true';
|
||||
});
|
||||
};
|
||||
|
||||
const copyTextToClipboard = async (value) => {
|
||||
if (navigator.clipboard?.writeText) {
|
||||
await navigator.clipboard.writeText(value);
|
||||
return;
|
||||
}
|
||||
|
||||
const helperInput = document.createElement('textarea');
|
||||
helperInput.value = value;
|
||||
helperInput.setAttribute('readonly', '');
|
||||
helperInput.style.position = 'fixed';
|
||||
helperInput.style.opacity = '0';
|
||||
document.body.appendChild(helperInput);
|
||||
helperInput.select();
|
||||
document.execCommand('copy');
|
||||
helperInput.remove();
|
||||
};
|
||||
|
||||
const bindCopyIpChips = () => {
|
||||
const copyButtons = document.querySelectorAll('[data-copy-ip]');
|
||||
|
||||
copyButtons.forEach((buttonNode) => {
|
||||
if (!(buttonNode instanceof HTMLButtonElement)) return;
|
||||
if (buttonNode.dataset.copyBound === 'true') return;
|
||||
|
||||
buttonNode.dataset.copyBound = 'true';
|
||||
buttonNode.classList.add('is-copy-ready');
|
||||
if (!buttonNode.title) {
|
||||
buttonNode.title = 'Нажмите, чтобы скопировать';
|
||||
}
|
||||
buttonNode.addEventListener('click', async () => {
|
||||
const value = buttonNode.dataset.copyIp?.trim();
|
||||
if (!value) return;
|
||||
|
||||
try {
|
||||
await copyTextToClipboard(value);
|
||||
buttonNode.classList.add('is-copied');
|
||||
buttonNode.setAttribute('aria-label', `Скопировано: ${value}`);
|
||||
window.setTimeout(() => {
|
||||
buttonNode.classList.remove('is-copied');
|
||||
buttonNode.setAttribute('aria-label', `Скопировать: ${value}`);
|
||||
}, 1200);
|
||||
} catch {
|
||||
buttonNode.classList.add('is-copy-error');
|
||||
buttonNode.setAttribute('aria-label', `Не удалось скопировать: ${value}`);
|
||||
window.setTimeout(() => {
|
||||
buttonNode.classList.remove('is-copy-error');
|
||||
buttonNode.setAttribute('aria-label', `Скопировать: ${value}`);
|
||||
}, 1400);
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const normalizeCraftSearch = (value) =>
|
||||
stripDecorativeSymbols(value)
|
||||
.toLowerCase()
|
||||
.replace(/ё/g, 'е')
|
||||
.replace(/\s+/g, ' ')
|
||||
.trim();
|
||||
|
||||
const bindCraftCatalogFilters = () => {
|
||||
const catalogNodes = document.querySelectorAll('[data-craft-catalog]');
|
||||
|
||||
catalogNodes.forEach((catalogNode) => {
|
||||
if (!(catalogNode instanceof HTMLElement)) return;
|
||||
if (catalogNode.dataset.craftBound === 'true') return;
|
||||
catalogNode.dataset.craftBound = 'true';
|
||||
|
||||
const searchInput = catalogNode.querySelector('[data-craft-search]');
|
||||
const filterButtons = Array.from(catalogNode.querySelectorAll('[data-craft-filter]')).filter(
|
||||
(node) => node instanceof HTMLButtonElement
|
||||
);
|
||||
const groupNodes = Array.from(catalogNode.querySelectorAll('[data-craft-group]')).filter(
|
||||
(node) => node instanceof HTMLElement
|
||||
);
|
||||
const emptyState = catalogNode.querySelector('[data-craft-empty]');
|
||||
|
||||
let activeFilter = 'all';
|
||||
const activeButton = filterButtons.find(
|
||||
(buttonNode) =>
|
||||
buttonNode.classList.contains('is-active') ||
|
||||
buttonNode.getAttribute('aria-pressed') === 'true'
|
||||
);
|
||||
|
||||
if (activeButton?.dataset.craftFilter) {
|
||||
activeFilter = activeButton.dataset.craftFilter;
|
||||
}
|
||||
|
||||
const applyFilters = () => {
|
||||
const searchQuery =
|
||||
searchInput instanceof HTMLInputElement ? normalizeCraftSearch(searchInput.value) : '';
|
||||
|
||||
filterButtons.forEach((buttonNode) => {
|
||||
const isActive = (buttonNode.dataset.craftFilter || 'all') === activeFilter;
|
||||
buttonNode.classList.toggle('is-active', isActive);
|
||||
buttonNode.setAttribute('aria-pressed', String(isActive));
|
||||
});
|
||||
|
||||
let visibleCount = 0;
|
||||
|
||||
groupNodes.forEach((groupNode) => {
|
||||
const defaultCategory = groupNode.dataset.craftCategory || '';
|
||||
const itemNodes = Array.from(groupNode.querySelectorAll('[data-craft-item]')).filter(
|
||||
(node) => node instanceof HTMLElement
|
||||
);
|
||||
|
||||
let groupVisibleCount = 0;
|
||||
|
||||
itemNodes.forEach((itemNode) => {
|
||||
const itemCategory = itemNode.dataset.craftCategory || defaultCategory;
|
||||
const itemName =
|
||||
itemNode.dataset.craftName || itemNode.querySelector('h3')?.textContent || '';
|
||||
const normalizedName = normalizeCraftSearch(itemName);
|
||||
const matchesCategory = activeFilter === 'all' || itemCategory === activeFilter;
|
||||
const matchesSearch = !searchQuery || normalizedName.includes(searchQuery);
|
||||
const isVisible = matchesCategory && matchesSearch;
|
||||
|
||||
itemNode.hidden = !isVisible;
|
||||
if (isVisible) groupVisibleCount += 1;
|
||||
});
|
||||
|
||||
groupNode.hidden = groupVisibleCount === 0;
|
||||
visibleCount += groupVisibleCount;
|
||||
});
|
||||
|
||||
if (emptyState instanceof HTMLElement) {
|
||||
emptyState.hidden = visibleCount > 0;
|
||||
}
|
||||
};
|
||||
|
||||
filterButtons.forEach((buttonNode) => {
|
||||
buttonNode.addEventListener('click', () => {
|
||||
const nextFilter = buttonNode.dataset.craftFilter || 'all';
|
||||
if (nextFilter === activeFilter) return;
|
||||
activeFilter = nextFilter;
|
||||
applyFilters();
|
||||
});
|
||||
});
|
||||
|
||||
if (searchInput instanceof HTMLInputElement) {
|
||||
searchInput.addEventListener('input', applyFilters);
|
||||
searchInput.addEventListener('search', applyFilters);
|
||||
}
|
||||
|
||||
applyFilters();
|
||||
});
|
||||
};
|
||||
|
||||
const enhanceSidebarGroupLinks = () => {
|
||||
const targets = [];
|
||||
if (targets.length === 0) return;
|
||||
const labelNodes = document.querySelectorAll('.sidebar-content details > summary .group-label .large');
|
||||
|
||||
labelNodes.forEach((labelNode) => {
|
||||
if (!(labelNode instanceof HTMLElement)) return;
|
||||
|
||||
const text = labelNode.textContent?.trim();
|
||||
const target = targets.find((item) => item.label === text);
|
||||
if (!target) return;
|
||||
|
||||
if (labelNode.querySelector('a[data-sidebar-group-link]')) return;
|
||||
|
||||
const link = document.createElement('a');
|
||||
link.href = target.href;
|
||||
link.className = 'sidebar-group-link';
|
||||
link.dataset.sidebarGroupLink = 'true';
|
||||
link.textContent = target.label;
|
||||
link.addEventListener('click', (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
window.location.href = target.href;
|
||||
});
|
||||
|
||||
labelNode.replaceChildren(link);
|
||||
});
|
||||
};
|
||||
|
||||
const setReadProgress = () => {
|
||||
const progressEl = document.querySelector('[data-read-progress]');
|
||||
const backToTopBtn = document.querySelector('[data-back-to-top]');
|
||||
@@ -135,6 +497,13 @@ const topLinks = [
|
||||
});
|
||||
});
|
||||
|
||||
enhanceSidebarGroupLinks();
|
||||
sanitizeNavLabels();
|
||||
sanitizeDocHeadings();
|
||||
decorateSectionIcons();
|
||||
annotateLinkDestinations();
|
||||
bindCopyIpChips();
|
||||
bindCraftCatalogFilters();
|
||||
setReadProgress();
|
||||
window.addEventListener('scroll', setReadProgress, { passive: true });
|
||||
window.addEventListener('resize', setReadProgress);
|
||||
@@ -146,7 +515,16 @@ const topLinks = [
|
||||
bindReadProgress();
|
||||
}
|
||||
|
||||
document.addEventListener('astro:page-load', setReadProgress);
|
||||
document.addEventListener('astro:page-load', () => {
|
||||
enhanceSidebarGroupLinks();
|
||||
sanitizeNavLabels();
|
||||
sanitizeDocHeadings();
|
||||
decorateSectionIcons();
|
||||
annotateLinkDestinations();
|
||||
bindCopyIpChips();
|
||||
bindCraftCatalogFilters();
|
||||
setReadProgress();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -171,10 +549,70 @@ const topLinks = [
|
||||
padding: 0.25rem;
|
||||
margin: -0.25rem;
|
||||
min-width: 0;
|
||||
gap: 1rem;
|
||||
gap: 1.1rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.wiki-brand {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.55rem;
|
||||
text-decoration: none;
|
||||
flex-shrink: 0;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 0.3rem;
|
||||
padding: 0.2rem 0.28rem 0.2rem 0.22rem;
|
||||
transition: border-color 150ms ease, background 150ms ease;
|
||||
}
|
||||
|
||||
.wiki-brand:hover {
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 32%, transparent);
|
||||
background: color-mix(in srgb, var(--sl-color-accent-low) 64%, transparent);
|
||||
}
|
||||
|
||||
.wiki-brand__icon {
|
||||
width: 1.85rem;
|
||||
height: 1.85rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.wiki-brand__icon img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
border-radius: 0;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.wiki-brand__copy {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.wiki-brand__title {
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-size: 1.43rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.02em;
|
||||
color: var(--sl-color-white);
|
||||
}
|
||||
|
||||
.wiki-brand__subtitle {
|
||||
margin-top: 0.14rem;
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-size: 0.56rem;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0.28em;
|
||||
color: var(--sl-color-gray-3);
|
||||
}
|
||||
|
||||
.wiki-top-nav {
|
||||
display: none;
|
||||
gap: 0.45rem;
|
||||
@@ -295,51 +733,56 @@ const topLinks = [
|
||||
.wiki-back-to-top {
|
||||
position: fixed;
|
||||
top: auto;
|
||||
right: max(0.75rem, env(safe-area-inset-right));
|
||||
bottom: max(1.1rem, env(safe-area-inset-bottom));
|
||||
right: max(1.35rem, calc(env(safe-area-inset-right) + 0.8rem));
|
||||
bottom: max(1.45rem, calc(env(safe-area-inset-bottom) + 0.7rem));
|
||||
z-index: 30;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 70%, transparent);
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 74%, transparent);
|
||||
border-radius: 999px;
|
||||
background: linear-gradient(
|
||||
140deg,
|
||||
color-mix(in srgb, var(--wiki-purple-2) 78%, #101522),
|
||||
color-mix(in srgb, var(--wiki-blue-2) 82%, #101522)
|
||||
color-mix(in srgb, var(--wiki-purple-2) 74%, #101522),
|
||||
color-mix(in srgb, var(--wiki-blue-2) 84%, #101522)
|
||||
);
|
||||
color: #f6f9ff;
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.01em;
|
||||
width: 2.6rem;
|
||||
height: 2.6rem;
|
||||
width: 3.1rem;
|
||||
height: 3.1rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
line-height: 1;
|
||||
box-shadow:
|
||||
0 10px 24px hsl(220 95% 62% / 0.24),
|
||||
0 0 0 1px hsl(214 88% 70% / 0.22);
|
||||
0 0 0 1px hsl(214 88% 70% / 0.24),
|
||||
0 0 24px hsl(217 100% 68% / 0.38),
|
||||
0 0 42px hsl(221 100% 65% / 0.22);
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
transform: translateY(6px);
|
||||
transform: translateY(8px) scale(0.96);
|
||||
pointer-events: none;
|
||||
transition: opacity 160ms ease, transform 160ms ease, border-color 160ms ease;
|
||||
transition: opacity 180ms ease, transform 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
|
||||
}
|
||||
|
||||
.wiki-back-to-top__icon {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
stroke: currentColor;
|
||||
stroke-width: 2.15;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
}
|
||||
|
||||
.wiki-back-to-top.is-visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
transform: translateY(0);
|
||||
transform: translateY(0) scale(1);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.wiki-back-to-top:hover {
|
||||
border-color: color-mix(in srgb, #9ec4ff 80%, transparent);
|
||||
box-shadow:
|
||||
0 14px 28px hsl(220 95% 62% / 0.32),
|
||||
0 0 0 1px hsl(214 88% 70% / 0.35),
|
||||
0 0 18px hsl(220 96% 68% / 0.34);
|
||||
0 0 28px hsl(219 97% 70% / 0.44),
|
||||
0 0 50px hsl(221 98% 68% / 0.27);
|
||||
}
|
||||
|
||||
.social-icons::after {
|
||||
@@ -383,12 +826,36 @@ const topLinks = [
|
||||
}
|
||||
|
||||
@media (max-width: 50rem) {
|
||||
.wiki-brand {
|
||||
padding: 0.14rem 0.2rem;
|
||||
gap: 0.42rem;
|
||||
}
|
||||
|
||||
.wiki-brand__icon {
|
||||
width: 1.55rem;
|
||||
height: 1.55rem;
|
||||
}
|
||||
|
||||
.wiki-brand__title {
|
||||
font-size: 1.08rem;
|
||||
}
|
||||
|
||||
.wiki-brand__subtitle {
|
||||
font-size: 0.46rem;
|
||||
letter-spacing: 0.24em;
|
||||
}
|
||||
|
||||
.wiki-back-to-top {
|
||||
top: auto;
|
||||
right: max(0.62rem, env(safe-area-inset-right));
|
||||
bottom: max(1rem, env(safe-area-inset-bottom));
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
right: max(1rem, calc(env(safe-area-inset-right) + 0.52rem));
|
||||
bottom: max(1.18rem, calc(env(safe-area-inset-bottom) + 0.58rem));
|
||||
width: 2.85rem;
|
||||
height: 2.85rem;
|
||||
}
|
||||
|
||||
.wiki-back-to-top__icon {
|
||||
width: 1.34rem;
|
||||
height: 1.34rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ description: "Концепция мира, формат сервера и осн
|
||||
|
||||
## Концепция
|
||||
|
||||
Сервер построен вокруг идеи «архива реальностей»: каждая локация выглядит как отдельный фрагмент мира со своей физикой и историей.
|
||||
Сервер построен как единый живой мир: у разных локаций свой стиль, история и атмосфера.
|
||||
|
||||
### Формат
|
||||
|
||||
@@ -13,14 +13,6 @@ description: "Концепция мира, формат сервера и осн
|
||||
- Выживание с RPG-элементами
|
||||
- Упор на исследование и кооператив
|
||||
|
||||
## Лор в двух словах
|
||||
|
||||
После Раскола Неба мир разделился на слои. Игроки находят обломки карт, восстанавливают порталы и открывают утраченные ремёсла.
|
||||
|
||||
:::caution
|
||||
Некоторые сюжетные зоны открываются только после выполнения цепочки квестов.
|
||||
:::
|
||||
|
||||
## Техническая база
|
||||
|
||||
| Параметр | Значение |
|
||||
@@ -31,7 +23,7 @@ description: "Концепция мира, формат сервера и осн
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/mechanics/">Механики</a> · <a href="/team/">Команда проекта</a>
|
||||
<a href="/general/">Общее</a> · <a href="/faq/">FAQ</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -50,11 +50,11 @@ description: "Полное руководство по ферментации,
|
||||
|
||||
Всего существует 10 уровней качества:
|
||||
|
||||
- `☆` — уровень 1
|
||||
- `★` — уровень 2
|
||||
- `★☆` — уровень 3
|
||||
- `I` — уровень 1
|
||||
- `II` — уровень 2
|
||||
- `III` — уровень 3
|
||||
- `...`
|
||||
- `★★★★★ (10)` — максимальное качество
|
||||
- `X` — максимальное качество (уровень 10)
|
||||
|
||||
:::note
|
||||
Чем точнее соблюдён рецепт, тем выше качество.
|
||||
|
||||
@@ -1,14 +1,54 @@
|
||||
---
|
||||
---
|
||||
title: "Все IP"
|
||||
description: "Черновик страницы с адресами сервера."
|
||||
description: "Адреса и порты сервера PARABOX для Java и Bedrock."
|
||||
---
|
||||
|
||||
## Все IP
|
||||
## Основные адреса
|
||||
|
||||
Это временная страница-заглушка.
|
||||
<div class="ip-main-grid">
|
||||
<article class="ip-main-card">
|
||||
<h3>Java 1.21.11</h3>
|
||||
<ul>
|
||||
<li>
|
||||
Основной:
|
||||
<button class="copy-ip-chip" type="button" data-copy-ip="mc.parabox.su" aria-label="Скопировать: mc.parabox.su">
|
||||
<code>mc.parabox.su</code>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
AnyCast-прокси:
|
||||
<button class="copy-ip-chip" type="button" data-copy-ip="mine.rpcm.su" aria-label="Скопировать: mine.rpcm.su">
|
||||
<code>mine.rpcm.su</code>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</article>
|
||||
|
||||
- Основной IP: `example-1`
|
||||
- Резервный IP: `example-2`
|
||||
- Тестовый IP: `example-3`
|
||||
<article class="ip-main-card">
|
||||
<h3>Bedrock 26.2</h3>
|
||||
<ul>
|
||||
<li>
|
||||
Основной:
|
||||
<button class="copy-ip-chip" type="button" data-copy-ip="mc.parabox.su" aria-label="Скопировать: mc.parabox.su">
|
||||
<code>mc.parabox.su</code>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
Запасной IP:
|
||||
<button class="copy-ip-chip" type="button" data-copy-ip="213.152.43.52" aria-label="Скопировать: 213.152.43.52">
|
||||
<code>213.152.43.52</code>
|
||||
</button>
|
||||
</li>
|
||||
<li>
|
||||
Порт:
|
||||
<button class="copy-ip-chip" type="button" data-copy-ip="25875" aria-label="Скопировать: 25875">
|
||||
<code>25875</code>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
Замените эти значения на реальные адреса сервера.
|
||||
<div class="ip-main-note">
|
||||
Используйте запасной адрес, если основной IP временно недоступен.
|
||||
</div>
|
||||
|
||||
40
src/content/docs/cities.md
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
title: "Города"
|
||||
description: "Раздел для представления городов и проектов игроков."
|
||||
---
|
||||
|
||||
## Города и проекты игроков
|
||||
|
||||
На PARABOX можно создать свой город, собрать жителей и развивать территорию вместе с другими игроками.
|
||||
|
||||
<div class="lore-grid">
|
||||
<article class="lore-card city-feature-card">
|
||||
<p><strong class="city-highlight">Представить свой город.</strong> Расскажите о проекте и его отличительных чертах.</p>
|
||||
</article>
|
||||
<article class="lore-card city-feature-card">
|
||||
<p><strong class="city-highlight">Найти жителей.</strong> Публикуйте набор и указывайте роли, которые сейчас нужны городу.</p>
|
||||
</article>
|
||||
<article class="lore-card city-feature-card">
|
||||
<p><strong class="city-highlight">Показывать развитие.</strong> Делитесь скриншотами, координатами и текущими задачами.</p>
|
||||
</article>
|
||||
<article class="lore-card city-feature-card">
|
||||
<p><strong class="city-highlight">Организовывать союзы.</strong> Договаривайтесь о торговле, ивентах и совместных проектах.</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
## Шаблон публикации города
|
||||
|
||||
```text
|
||||
Название города:
|
||||
Координаты:
|
||||
Мэр / управляющий орган:
|
||||
Описание:
|
||||
Набор жителей: да / нет
|
||||
Правила города:
|
||||
```
|
||||
|
||||
Подробный процесс входа на сервер описан в статье <a href="/getting-started/">«Начало игры»</a>.
|
||||
|
||||
:::tip
|
||||
Чем понятнее и полнее описание города, тем быстрее к вам присоединятся игроки.
|
||||
:::
|
||||
@@ -1,14 +1,82 @@
|
||||
---
|
||||
---
|
||||
title: "Команды"
|
||||
description: "Черновик страницы с командами сервера."
|
||||
description: "Справочник игровых команд: чат, личные сообщения, RP и полезные функции."
|
||||
---
|
||||
|
||||
## Команды
|
||||
|
||||
Это временная страница-заглушка.
|
||||
Ниже собраны основные команды сервера, сгруппированные по категориям.
|
||||
|
||||
- `/spawn` — пример команды 1
|
||||
- `/home` — пример команды 2
|
||||
- `/rtp` — пример команды 3
|
||||
### Настройки
|
||||
|
||||
Позже замените этот список на реальные команды вашего сервера.
|
||||
- `/chatsetting` - открыть меню настроек чата (уведомления, отображение, звук и т.д.).
|
||||
|
||||
### Личные сообщения
|
||||
|
||||
- `/tell <ник> <сообщение>` - отправить личное сообщение игроку.
|
||||
- `/msg`, `/w`, `/m`, `/message`, `/send` - альтернативы команды `/tell`.
|
||||
- `/r` - ответить последнему игроку.
|
||||
|
||||
### Игнор
|
||||
|
||||
- `/ignore <ник>` - игнорировать сообщения игрока.
|
||||
|
||||
### Развлечения
|
||||
|
||||
- `/ball <вопрос>` - задать вопрос и получить случайный ответ.
|
||||
- `/tictactoe <ник>` - сыграть в крестики-нолики.
|
||||
- `/rockpaperscissors <ник>` - камень-ножницы-бумага.
|
||||
- `/try` - проверить удачу (случайный шанс).
|
||||
- `/coin` - подбросить монетку.
|
||||
- `/dice` - бросить кубик.
|
||||
|
||||
### Кастомные пластинки
|
||||
|
||||
- `/disc burn <url> [name]` - создать кастомную пластинку из аудио по URL.
|
||||
- `/disc erase` - вернуть кастомную пластинку к обычному виду.
|
||||
- `/disc search <query>` - найти треки на YouTube.
|
||||
|
||||
:::note
|
||||
Для `/disc burn` нужно держать музыкальную пластинку в руке.
|
||||
:::
|
||||
|
||||
### RP и взаимодействие
|
||||
|
||||
- `/do <действие>` - RP-описание действия от третьего лица.
|
||||
- `/anon <сообщение>` - отправить анонимное сообщение.
|
||||
- `/helper` - попросить помощь.
|
||||
|
||||
### Статус игрока
|
||||
|
||||
- `/afk` - включить или выключить режим AFK.
|
||||
- `/crawl` - позволяет игроку ползти.
|
||||
- `/sit` - позволяет игроку сидеть.
|
||||
- `/lay` - позволяет игроку лечь.
|
||||
|
||||
### ImageFrame (изображения на картах)
|
||||
|
||||
- `/imageframe select` - выбрать рамки, в которые будет поставлено изображение.
|
||||
- `/imageframe create <name> <url> <width> <height>` - создать новое изображение на картах.
|
||||
- `/imageframe create <name> <url> selection` - создать изображение и сразу разместить его в выбранных рамках.
|
||||
- `/imageframe get <name>` - получить ранее созданное вами изображение.
|
||||
- `/imageframe get <name> selection` - поставить ранее созданное изображение сразу в выбранные рамки.
|
||||
- `/imageframe list` - показать список ваших созданных изображений.
|
||||
- `/imageframe info` - показать информацию об изображении, которое вы держите в руке.
|
||||
- `/imageframe refresh [image_name] [new_url]` - обновить изображение из источника (при необходимости с новой ссылкой).
|
||||
- `/imageframe rename <name> <new_name>` - переименовать ваше изображение.
|
||||
- `/imageframe delete <name>` - удалить ваше изображение.
|
||||
|
||||
:::note
|
||||
Для `/imageframe create` используйте прямую ссылку на изображение.
|
||||
`<width>` и `<height>` - это размер в картах (например `2 2` для сетки 2x2).
|
||||
:::
|
||||
|
||||
### Информация
|
||||
|
||||
- `/ping` - узнать задержку (пинг).
|
||||
- `/toponline` - посмотреть топ игроков по наигранному времени.
|
||||
- `/breweryx info` - показать уровень опьянения.
|
||||
|
||||
### Символы
|
||||
|
||||
- `/symbol` - открыть меню символов.
|
||||
|
||||
@@ -1,19 +1,24 @@
|
||||
---
|
||||
title: "Контакты / ссылки"
|
||||
description: "Каналы связи, соцсети, поддержка и полезные внешние ресурсы."
|
||||
title: "Контакты и ссылки"
|
||||
description: "Официальные контакты сервера и связь с администрацией."
|
||||
---
|
||||
|
||||
## Официальные ссылки
|
||||
|
||||
- Discord: `https://discord.gg/example`
|
||||
- GitHub wiki: `https://github.com/your-org/parabox`
|
||||
- Почта поддержки: `support@example.com`
|
||||
|
||||
## Когда писать в поддержку
|
||||
|
||||
1. Потеря предметов из-за серверного сбоя.
|
||||
2. Баги квестов и непроходимые этапы.
|
||||
3. Вопросы по платежам и привилегиям.
|
||||
<div class="lore-grid">
|
||||
<a class="lore-card contact-link-card" href="https://discord.gg/V5gD2a3HpQ" target="_blank" rel="noopener noreferrer">
|
||||
<h3>Discord сервера</h3>
|
||||
<p>Официальный Discord проекта.</p>
|
||||
</a>
|
||||
<a class="lore-card contact-link-card" href="https://t.me/verdise" target="_blank" rel="noopener noreferrer">
|
||||
<h3>Владелец проекта</h3>
|
||||
<p>Связь в Telegram.</p>
|
||||
</a>
|
||||
<a class="lore-card contact-link-card" href="https://t.me/s1s2s3sf" target="_blank" rel="noopener noreferrer">
|
||||
<h3>Администратор проекта</h3>
|
||||
<p>Связь в Telegram.</p>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
## Шаблон тикета
|
||||
|
||||
@@ -26,8 +31,5 @@ description: "Каналы связи, соцсети, поддержка и п
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/faq/">FAQ</a> · <a href="/team/">Команда проекта</a>
|
||||
<a href="/faq/">FAQ</a> · <a href="/getting-started/">Начало игры</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
155
src/content/docs/crafting.md
Normal file
@@ -0,0 +1,155 @@
|
||||
---
|
||||
title: "Крафты"
|
||||
description: "Раздел по кастомным крафтам сервера PARABOX."
|
||||
---
|
||||
|
||||
## Каталог крафтов
|
||||
|
||||
<div class="craft-catalog" data-craft-catalog>
|
||||
<div class="craft-controls">
|
||||
<label class="craft-search-field" for="craft-search-input">
|
||||
<span>Поиск по названию</span>
|
||||
<input
|
||||
id="craft-search-input"
|
||||
class="craft-search-input"
|
||||
type="search"
|
||||
placeholder="Например, наковальня или книга"
|
||||
data-craft-search
|
||||
/>
|
||||
</label>
|
||||
<div class="craft-filter-group" role="group" aria-label="Фильтр крафтов по категориям">
|
||||
<button type="button" class="craft-filter-chip is-active" data-craft-filter="all" aria-pressed="true">Все</button>
|
||||
<button type="button" class="craft-filter-chip" data-craft-filter="special" aria-pressed="false">Спец-предметы</button>
|
||||
<button type="button" class="craft-filter-chip" data-craft-filter="blocks" aria-pressed="false">Блоки и станции</button>
|
||||
<button type="button" class="craft-filter-chip" data-craft-filter="smelting" aria-pressed="false">Переработка</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="craft-empty" data-craft-empty hidden>По вашему запросу крафты не найдены.</p>
|
||||
|
||||
<section class="craft-group" data-craft-group data-craft-category="special">
|
||||
<h3>Спец-предметы</h3>
|
||||
<div class="craft-grid">
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="special" data-craft-name="невидимая рамка">
|
||||
<h3>Невидимая рамка</h3>
|
||||
<img class="craft-card-image" src="/crafts/invisible-item-frame.png" alt="Рецепт невидимой рамки" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="special" data-craft-name="невидимая светящаяся рамка">
|
||||
<h3>Невидимая светящаяся рамка</h3>
|
||||
<img class="craft-card-image" src="/crafts/invisible-glow-item-frame.png" alt="Рецепт невидимой светящейся рамки" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="special" data-craft-name="невидимый свет">
|
||||
<h3>Невидимый свет</h3>
|
||||
<img class="craft-card-image" src="/crafts/invisible-light.png" alt="Рецепт невидимого света" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="special" data-craft-name="чародейская книга">
|
||||
<h3>Чародейская книга</h3>
|
||||
<img class="craft-card-image" src="/crafts/enchanted-book.png" alt="Рецепт чародейской книги" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="special" data-craft-name="книга знаний">
|
||||
<h3>Книга знаний</h3>
|
||||
<img class="craft-card-image" src="/crafts/knowledge-book.png" alt="Рецепт книги знаний" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="special" data-craft-name="дыхание дракона">
|
||||
<h3>Дыхание дракона</h3>
|
||||
<img class="craft-card-image" src="/crafts/dragons-breath.png" alt="Рецепт дыхания дракона" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="special" data-craft-name="светящиеся чернила">
|
||||
<h3>Светящиеся чернила</h3>
|
||||
<img class="craft-card-image" src="/crafts/glow-ink-sac.png" alt="Рецепт светящихся чернил" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="special" data-craft-name="мембрана фантома">
|
||||
<h3>Мембрана фантома</h3>
|
||||
<img class="craft-card-image" src="/crafts/phantom-membrane.png" alt="Рецепт мембраны фантома" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="special" data-craft-name="бирка">
|
||||
<h3>Бирка</h3>
|
||||
<img class="craft-card-image" src="/crafts/name-tag.png" alt="Рецепт бирки" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="special" data-craft-name="мешок">
|
||||
<h3>Мешок</h3>
|
||||
<img class="craft-card-image" src="/crafts/bundle.png" alt="Рецепт мешка" loading="lazy" />
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="craft-group" data-craft-group data-craft-category="blocks">
|
||||
<h3>Блоки и рабочие станции</h3>
|
||||
<div class="craft-grid">
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="стол лучника">
|
||||
<h3>Стол лучника</h3>
|
||||
<img class="craft-card-image" src="/crafts/fletching-table.png" alt="Рецепт стола лучника" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="стол картографа">
|
||||
<h3>Стол картографа</h3>
|
||||
<img class="craft-card-image" src="/crafts/cartography-table.png" alt="Рецепт стола картографа" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="ткацкий станок">
|
||||
<h3>Ткацкий станок</h3>
|
||||
<img class="craft-card-image" src="/crafts/loom.png" alt="Рецепт ткацкого станка" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="нотный блок">
|
||||
<h3>Нотный блок</h3>
|
||||
<img class="craft-card-image" src="/crafts/note-block.png" alt="Рецепт нотного блока" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="проигрыватель">
|
||||
<h3>Проигрыватель</h3>
|
||||
<img class="craft-card-image" src="/crafts/jukebox.png" alt="Рецепт проигрывателя" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="раздатчик">
|
||||
<h3>Раздатчик</h3>
|
||||
<img class="craft-card-image" src="/crafts/dispenser.png" alt="Рецепт раздатчика" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="колокол">
|
||||
<h3>Колокол</h3>
|
||||
<img class="craft-card-image" src="/crafts/bell.png" alt="Рецепт колокола" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="обтесанное бревно">
|
||||
<h3>Обтесанное бревно</h3>
|
||||
<img class="craft-card-image" src="/crafts/stripped-log-stonecutter.png" alt="Рецепт обтесанного бревна в камнерезе" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="прочный полублок">
|
||||
<h3>Прочный полублок</h3>
|
||||
<img class="craft-card-image" src="/crafts/sturdy-slab.png" alt="Рецепт прочного полублока" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="наковальня вариант 1">
|
||||
<h3>Наковальня (вариант 1)</h3>
|
||||
<img class="craft-card-image" src="/crafts/anvil-variant-base.png" alt="Первый вариант рецепта наковальни" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="blocks" data-craft-name="наковальня вариант 2">
|
||||
<h3>Наковальня (вариант 2)</h3>
|
||||
<img class="craft-card-image" src="/crafts/anvil-variant-l.png" alt="Второй вариант рецепта наковальни" loading="lazy" />
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="craft-group" data-craft-group data-craft-category="smelting">
|
||||
<h3>Переработка и конверсия</h3>
|
||||
<div class="craft-grid">
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="smelting" data-craft-name="компас из компаса восстановления">
|
||||
<h3>Компас из компаса восстановления</h3>
|
||||
<img class="craft-card-image" src="/crafts/recovery-compass-to-compass-smelting.png" alt="Переплавка компаса восстановления в обычный компас" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="smelting" data-craft-name="железный слиток из компаса">
|
||||
<h3>Железный слиток из компаса</h3>
|
||||
<img class="craft-card-image" src="/crafts/compass-to-iron-ingot-smelting.png" alt="Переплавка компаса в железный слиток" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="smelting" data-craft-name="золотой слиток из часов">
|
||||
<h3>Золотой слиток из часов</h3>
|
||||
<img class="craft-card-image" src="/crafts/clock-to-gold-ingot-smelting.png" alt="Переплавка часов в золотой слиток" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="smelting" data-craft-name="красное стекло">
|
||||
<h3>Красное стекло</h3>
|
||||
<img class="craft-card-image" src="/crafts/red-glass-smelting.png" alt="Переплавка в красное стекло" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="smelting" data-craft-name="алмазная руда вариант 1">
|
||||
<h3>Алмазная руда (вариант 1)</h3>
|
||||
<img class="craft-card-image" src="/crafts/diamond-ore-variant-k.png" alt="Первый вариант рецепта алмазной руды" loading="lazy" />
|
||||
</article>
|
||||
<article class="lore-card craft-card" data-craft-item data-craft-category="smelting" data-craft-name="алмазная руда вариант 2">
|
||||
<h3>Алмазная руда (вариант 2)</h3>
|
||||
<img class="craft-card-image" src="/crafts/diamond-ore-variant-s.png" alt="Второй вариант рецепта алмазной руды" loading="lazy" />
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
@@ -1,33 +0,0 @@
|
||||
---
|
||||
title: "Донат / привилегии"
|
||||
description: "Добровольная поддержка сервера, наборы и прозрачные правила привилегий."
|
||||
---
|
||||
|
||||
## Принципы
|
||||
|
||||
- Донат не должен ломать баланс мира.
|
||||
- Боевые преимущества ограничены и прозрачны.
|
||||
- Все пакеты имеют чёткое описание.
|
||||
|
||||
## Уровни поддержки
|
||||
|
||||
| Уровень | Что входит |
|
||||
| --- | --- |
|
||||
| Traveler | Косметика + расширенный /home |
|
||||
| Patron | Больше слотов хранилища + титул |
|
||||
| Curator | Эксклюзивные визуальные эффекты |
|
||||
|
||||
## Политика возвратов
|
||||
|
||||
Возвраты рассматриваются через тикет-систему в течение 7 дней после покупки.
|
||||
|
||||
:::note
|
||||
Покупка привилегий - способ поддержать развитие сервера, а не обязательное условие комфортной игры.
|
||||
:::
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/rules/">Правила</a> · <a href="/contacts/">Контакты / ссылки</a>
|
||||
</div>
|
||||
|
||||
|
||||
156
src/content/docs/easyarmorstands.md
Normal file
@@ -0,0 +1,156 @@
|
||||
---
|
||||
title: "EasyArmorStands — как пользоваться"
|
||||
description: "Пошаговая инструкция по редактированию стоек, display-объектов и текста через EasyArmorStands."
|
||||
---
|
||||
|
||||
## 1. Получить инструмент
|
||||
|
||||
Выполните команду:
|
||||
|
||||
`/eas give`
|
||||
|
||||
Возьмите выданный предмет в руку — это инструмент редактирования.
|
||||
|
||||
## 2. Выбрать объект
|
||||
|
||||
Наведитесь на нужный объект:
|
||||
|
||||
- стойка для брони
|
||||
- текст
|
||||
- block/item display
|
||||
|
||||
Нажмите ПКМ.
|
||||
|
||||
После этого появятся линии и точки — это режим редактирования.
|
||||
|
||||
## 3. Выбрать часть (для стойки)
|
||||
|
||||
Вы увидите:
|
||||
|
||||
- белые линии — части тела
|
||||
- жёлтую точку — центр
|
||||
|
||||
Кликните по нужной части:
|
||||
|
||||
- хотите двигать руку — кликните по руке
|
||||
- хотите двигать всё — кликните по центру
|
||||
|
||||
## 4. Двигать объект
|
||||
|
||||
После выбора части:
|
||||
|
||||
- двигайте мышкой / смотрите в сторону
|
||||
- объект будет двигаться
|
||||
|
||||
Управление:
|
||||
|
||||
- `ПКМ` — подтвердить
|
||||
- `ЛКМ` — отменить
|
||||
|
||||
## 5. Поворот
|
||||
|
||||
Выберите инструмент `Rotate` (через меню или переключение).
|
||||
|
||||
- двигайте камерой
|
||||
- объект будет вращаться
|
||||
|
||||
Управление:
|
||||
|
||||
- `ПКМ` — сохранить
|
||||
- `ЛКМ` — отменить
|
||||
|
||||
## 6. Масштаб (увеличение/уменьшение)
|
||||
|
||||
Для display-объектов (блок, предмет, текст):
|
||||
|
||||
- откройте меню (`F`)
|
||||
- найдите `scale`
|
||||
- увеличьте или уменьшите размер
|
||||
|
||||
## 7. Открыть меню
|
||||
|
||||
Нажмите `F`.
|
||||
|
||||
В меню можно:
|
||||
|
||||
- выбрать инструмент (`Move` / `Rotate`)
|
||||
- менять размер
|
||||
- включать настройки
|
||||
- надевать броню
|
||||
|
||||
## 8. Как поставить блок (Block Display)
|
||||
|
||||
Используйте один из способов:
|
||||
|
||||
- `Shift + ЛКМ` по блоку
|
||||
- `/eas block`
|
||||
|
||||
После этого можно:
|
||||
|
||||
- двигать блок
|
||||
- вращать
|
||||
- масштабировать
|
||||
|
||||
## 9. Как поставить предмет (Item Display)
|
||||
|
||||
- откройте меню (`F`)
|
||||
- вставьте предмет в слот
|
||||
|
||||
Предмет появится как display-объект.
|
||||
|
||||
Дальше можно:
|
||||
|
||||
- двигать
|
||||
- вращать
|
||||
- увеличивать
|
||||
|
||||
## 10. Как сделать текст
|
||||
|
||||
Выполните:
|
||||
|
||||
`/eas text`
|
||||
|
||||
Появится текстовый объект. Далее можно:
|
||||
|
||||
- двигать его
|
||||
- менять размер
|
||||
- редактировать текст
|
||||
|
||||
Чтобы текст всегда смотрел на игрока:
|
||||
|
||||
- в меню установите `billboard = center`
|
||||
- используйте `/eas reset`
|
||||
|
||||
## 11. Работа с группой
|
||||
|
||||
- зажмите `Shift + ПКМ` по объектам
|
||||
- выберите несколько объектов
|
||||
|
||||
После этого `ПКМ` редактирует всё сразу.
|
||||
|
||||
## 12. Отмена действий
|
||||
|
||||
- `/eas undo`
|
||||
- `/eas redo`
|
||||
|
||||
## 13. Быстрые действия
|
||||
|
||||
- `/eas clone` — копировать
|
||||
- `/eas align` — выровнять по центру блока
|
||||
|
||||
## Простой алгоритм
|
||||
|
||||
1. `/eas give`
|
||||
2. ПКМ по объекту
|
||||
3. Выберите часть
|
||||
4. Подвигайте мышкой
|
||||
5. ПКМ для подтверждения
|
||||
|
||||
Это базовый рабочий цикл.
|
||||
|
||||
## Самое главное
|
||||
|
||||
- всё делается мышкой
|
||||
- `ПКМ` = подтвердить
|
||||
- `ЛКМ` = отменить
|
||||
- `F` = меню
|
||||
@@ -1,38 +0,0 @@
|
||||
---
|
||||
title: "Экономика"
|
||||
description: "Валюты, рынки, аукцион, контракты и рекомендации по торговле."
|
||||
---
|
||||
|
||||
## Валюты
|
||||
|
||||
- `Aurum` - базовая торговая валюта.
|
||||
- `Echo` - редкая валютная единица для реликвий.
|
||||
|
||||
## Как работает рынок
|
||||
|
||||
### Аукцион
|
||||
|
||||
Игроки выставляют предметы на открытый рынок.
|
||||
|
||||
### Контракты
|
||||
|
||||
Сделки между игроками с фиксированными условиями.
|
||||
|
||||
## Мини-стратегия для старта
|
||||
|
||||
| Шаг | Действие | Ожидаемый эффект |
|
||||
| --- | --- | --- |
|
||||
| 1 | Продавать излишки еды | Быстрый стартовый капитал |
|
||||
| 2 | Копить железо и редстоун | Стабильный спрос |
|
||||
| 3 | Вкладываться в алхимию | Высокая маржа |
|
||||
|
||||
:::caution
|
||||
Не держи все активы в одном виде ресурса: цены цикличны.
|
||||
:::
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/items-resources/">Предметы и ресурсы</a> · <a href="/donate/">Донат / привилегии</a>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
---
|
||||
title: "Как редактировать wiki"
|
||||
description: "Простая инструкция по добавлению и изменению страниц в Markdown."
|
||||
---
|
||||
|
||||
## Быстрый принцип
|
||||
|
||||
Каждая статья - отдельный `.md`-файл в `src/content/docs/`.
|
||||
|
||||
## Минимальный frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
title: "Название страницы"
|
||||
description: "Короткое описание страницы"
|
||||
---
|
||||
```
|
||||
|
||||
## Как добавить новую страницу
|
||||
|
||||
1. Создай файл в `src/content/docs/`, например `new-biome.md`.
|
||||
2. Добавь frontmatter (`title`, `description`).
|
||||
3. Напиши контент в Markdown (заголовки, списки, таблицы, код).
|
||||
4. Добавь ссылку в `sidebar` в `astro.config.mjs`.
|
||||
|
||||
## Полезные блоки Starlight
|
||||
|
||||
```md
|
||||
:::note
|
||||
Заметка
|
||||
:::
|
||||
|
||||
:::tip
|
||||
Подсказка
|
||||
:::
|
||||
|
||||
:::caution
|
||||
Предупреждение
|
||||
:::
|
||||
|
||||
:::danger
|
||||
Опасность
|
||||
:::
|
||||
```
|
||||
|
||||
## Пример spoiler/details
|
||||
|
||||
```md
|
||||
<details>
|
||||
<summary>Показать секрет</summary>
|
||||
Здесь скрытый текст.
|
||||
</details>
|
||||
```
|
||||
|
||||
## Где редактируется меню
|
||||
|
||||
Меню и порядок разделов настраиваются в `astro.config.mjs` -> `starlight({ sidebar: [...] })`.
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/templates/new-page-template/">Шаблон новой страницы</a>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,40 +1,16 @@
|
||||
---
|
||||
title: "FAQ"
|
||||
description: "Ответы на частые вопросы игроков о запуске, прогрессе и аккаунте."
|
||||
description: "Частый вопрос по регистрации на сервере."
|
||||
---
|
||||
|
||||
## Основные вопросы
|
||||
## Основной вопрос
|
||||
|
||||
<details>
|
||||
<summary>Как попасть на сервер?</summary>
|
||||
Добавь адрес сервера в клиент Minecraft Java Edition и пройди короткое интро на спавне.
|
||||
<summary>Как зарегистрироваться на сервере?</summary>
|
||||
При первом запуске зарегистрируйтесь командой <code>/reg вашпароль повторпароля</code>. При следующем входе используйте <code>/l вашпароль</code>.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Можно ли играть одному?</summary>
|
||||
Да. Большая часть контента доступна соло, но рейды и разломы удобнее проходить группой.
|
||||
</details>
|
||||
|
||||
<details>
|
||||
<summary>Что делать, если потерял вещи?</summary>
|
||||
Проверь лог смертей и открой тикет в Discord с точным временем события.
|
||||
</details>
|
||||
|
||||
## Технические вопросы
|
||||
|
||||
### Минимальные рекомендации
|
||||
|
||||
- 8 ГБ RAM на ПК
|
||||
- Java 21+
|
||||
- Стабильный интернет
|
||||
|
||||
:::tip
|
||||
Перед обращением в поддержку приложи скриншот ошибки и список модов.
|
||||
:::
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/getting-started/">Начало игры</a> · <a href="/contacts/">Контакты / ссылки</a>
|
||||
<a href="/getting-started/">Начало игры</a>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
61
src/content/docs/general.md
Normal file
@@ -0,0 +1,61 @@
|
||||
---
|
||||
title: "Общее"
|
||||
description: "Общая информация и веб-карта сервера PARABOX."
|
||||
---
|
||||
|
||||
## Веб-карта сервера
|
||||
|
||||
Интерактивная веб-карта отображает мир в реальном времени и помогает быстро ориентироваться на сервере.
|
||||
|
||||
На карте вы увидите:
|
||||
|
||||
- расположение городов и построек игроков;
|
||||
- дороги, биомы и основные локации;
|
||||
- масштаб карты.
|
||||
|
||||
<div class="map-actions">
|
||||
<a class="map-cta-button" href="https://map.rpcm.su/#world:0:0:0:1500:0:0:0:0:perspective" target="_blank" rel="noopener noreferrer">
|
||||
Открыть веб-карту
|
||||
</a>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
## Как сменить скин
|
||||
|
||||
На сервере доступна система скинов, которая позволяет установить любой внешний вид. Скин будет отображаться в чате, на карте и в других местах.
|
||||
|
||||
### Способ 1. Через команду
|
||||
|
||||
- для установки: `/skin set <ссылка на скин / ник лицензионного аккаунта>`
|
||||
- для сброса: `/skin clear`
|
||||
|
||||
### Способ 2. Через сайт SkinRestorer
|
||||
|
||||
1. Загрузите скин файлом на сайт: [SkinRestorer](https://skinsrestorer.net/upload)
|
||||
2. Нажмите кнопку `GENERATE` и скопируйте полученную команду.
|
||||
3. Введите команду в чате Minecraft.
|
||||
|
||||
---
|
||||
|
||||
## ImageForm (бета): гайд
|
||||
|
||||
`ImageForm` позволяет делать map-art автоматически по ссылке на изображение, без ручной постройки пиксель-арт схем.
|
||||
|
||||
### Как использовать
|
||||
|
||||
1. Подготовьте прямую ссылку на картинку (форматы `png`/`jpg`/`webp`).
|
||||
2. Зайдите на сервер и вызовите инструмент ImageForm (команда/интерфейс, доступный на вашей роли).
|
||||
3. Вставьте ссылку на изображение и подтвердите создание.
|
||||
4. Выберите размер и формат карты (если сервер предложит параметры).
|
||||
5. Дождитесь генерации и заберите готовый результат.
|
||||
|
||||
### Советы по качеству
|
||||
|
||||
- используйте изображения с хорошим контрастом и без мелкого текста;
|
||||
- лучше всего подходят квадратные или близкие к квадрату картинки;
|
||||
- при необходимости уменьшите изображение заранее, чтобы карта читалась лучше.
|
||||
|
||||
:::note
|
||||
ImageForm работает в бета-режиме: отдельные параметры или ограничения могут меняться в следующих патчах.
|
||||
:::
|
||||
@@ -1,12 +1,22 @@
|
||||
---
|
||||
title: "Начало игры"
|
||||
description: "Черновик раздела. Здесь будет ваш текст о старте."
|
||||
description: "Как подать заявку на сервер PARABOX и что указать в анкете."
|
||||
---
|
||||
|
||||
## Начало игры
|
||||
## Как вступить
|
||||
|
||||
Это временный текст-заглушка для раздела про старт игрока.
|
||||
Чтобы попасть на сервер, отправьте заявку через бота.
|
||||
После одобрения вы получите доступ к миру PARABOX.
|
||||
|
||||
В первые минуты герой просыпается у древнего маяка, получает рюкзак с картой и слышит голос хранителя, который шепчет о пути через туманные равнины.
|
||||
<div class="see-also">
|
||||
<p>Подача заявки через бота</p>
|
||||
<a href="https://t.me/RPCM_MINE_BOT" target="_blank" rel="noopener noreferrer"><strong>@RPCM_MINE_BOT</strong></a>
|
||||
</div>
|
||||
|
||||
Когда будете готовы, замените этот текст на свой подробный гайд.
|
||||
## Форма анкеты
|
||||
|
||||
Чтобы вступить, заполните короткую анкету в боте:
|
||||
|
||||
1. Как к вам обращаться (имя или псевдоним).
|
||||
2. Ваш никнейм для привязки к серверу.
|
||||
3. От какого проекта вы пришли, или откуда узнали о сервере.
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
---
|
||||
title: "Гайды"
|
||||
description: "Практические сценарии: выживание, прогресс, босс-раны и командная игра."
|
||||
---
|
||||
|
||||
## Навигатор по гайдам
|
||||
|
||||
<div class="lore-grid">
|
||||
<article class="lore-card">
|
||||
<h3>Соло-старт</h3>
|
||||
<p>Как стабильно развиться одному игроку за первые два вечера.</p>
|
||||
</article>
|
||||
<article class="lore-card">
|
||||
<h3>Гильдейский старт</h3>
|
||||
<p>Роли в группе, распределение ресурсов и ротация задач.</p>
|
||||
</article>
|
||||
<article class="lore-card">
|
||||
<h3>Босс-раны</h3>
|
||||
<p>Минимальный набор, тактики и контроль рисков на арене.</p>
|
||||
</article>
|
||||
</div>
|
||||
|
||||
## Пример структурированного гайда
|
||||
|
||||
### Подготовка
|
||||
|
||||
- 32+ еды
|
||||
- Броня не ниже железной
|
||||
- 2 тотема или 3 зелья лечения
|
||||
|
||||
### Выполнение
|
||||
|
||||
1. Активируй обелиск.
|
||||
2. Удерживай центральную платформу 3 волны.
|
||||
3. Сфокусируй урон по призывателю на 4-й фазе.
|
||||
|
||||
### Завершение
|
||||
|
||||
Разбери добычу по ролям: танк, саппорт, дамагер.
|
||||
|
||||
:::danger
|
||||
Не заходи в событие с поломанной бронёй: штраф на урон и критический риск потери лута.
|
||||
:::
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/mechanics/">Механики</a> · <a href="/professions/">Профессии / классы / расы</a>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,27 +1,41 @@
|
||||
---
|
||||
title: "ParaBox"
|
||||
description: "Черновик главной страницы. Текст будет заполнен позже."
|
||||
title: "Project PARABOX"
|
||||
description: "Единый сервер РПКМ: города проектов, экономика, выживание и взаимодействие между игроками."
|
||||
hero:
|
||||
tagline: Временный текст для главной страницы
|
||||
tagline: Единый мир для проектов и игроков
|
||||
actions:
|
||||
- text: Начать игру
|
||||
link: /getting-started/
|
||||
icon: right-arrow
|
||||
variant: primary
|
||||
- text: Читать сюжет
|
||||
link: /story/
|
||||
- text: Смотреть все IP
|
||||
link: /all-ip/
|
||||
variant: minimal
|
||||
---
|
||||
|
||||
## Главная
|
||||
## Project PARABOX
|
||||
|
||||
Это временный блок с тестовым содержимым. Здесь позже появится вступление о сервере, его атмосфере и ключевых особенностях.
|
||||
Project PARABOX объединяет проекты РПКМ и игроков в едином живом мире: выживание, развитие городов, торговля и совместные события происходят на одной карте.
|
||||
|
||||
:::note
|
||||
Текст-заглушка. После финального наполнения этот раздел можно полностью переписать.
|
||||
## Города, регистрация и первые шаги
|
||||
|
||||
1. Подайте заявку через бота и дождитесь подтверждения.
|
||||
2. Зайдите на сервер по одному из IP выше.
|
||||
3. Зарегистрируйтесь или войдите в игровую систему.
|
||||
4. Выберите город для вступления или создайте свой проектный город.
|
||||
5. Ознакомьтесь с правилами и базовыми механиками.
|
||||
|
||||
Подробный разбор процесса вступления находится в статье <a href="/getting-started/">«Начало игры»</a>, а информация по городам — в разделе <a href="/cities/">«Города»</a>.
|
||||
|
||||
## Основные особенности
|
||||
|
||||
- Система городов с возможностью набора жителей.
|
||||
- Экономика и торговля между игроками.
|
||||
- Ивенты и активности.
|
||||
- Классическое выживание с социальным взаимодействием.
|
||||
|
||||
:::tip
|
||||
Чем быстрее вы подключитесь по IP и выберете точку старта, тем проще будет влиться в текущие города и события.
|
||||
:::
|
||||
|
||||
## Черновой абзац
|
||||
|
||||
Пыль поднимается над каменными дорогами, на горизонте мерцают порталы, а старые башни хранят забытые руны. Здесь начинается история, которую вы позже заполните своими правилами, лором и целями.
|
||||
|
||||
## Добро пожаловать и приятной игры
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
title: "Предметы и ресурсы"
|
||||
description: "Каталог ключевых материалов, редких артефактов и их применение."
|
||||
---
|
||||
|
||||
## Базовые ресурсы
|
||||
|
||||
- Древесина
|
||||
- Камень
|
||||
- Железо
|
||||
- Кварц
|
||||
|
||||
## Редкие материалы
|
||||
|
||||
### Пыль кометы
|
||||
|
||||
Используется для усиления портальных якорей.
|
||||
|
||||
### Лунный обсидиан
|
||||
|
||||
Нужен для защитных печатей и высокоуровневых рецептов.
|
||||
|
||||
## Пример блока внимания
|
||||
|
||||
:::danger
|
||||
Артефакты с меткой «Связанный» нельзя передавать или продавать.
|
||||
:::
|
||||
|
||||
## Таблица предметов
|
||||
|
||||
| Предмет | Где найти | Для чего нужен |
|
||||
| --- | --- | --- |
|
||||
| Пыль кометы | Небесный дождь | Ритуалы усиления |
|
||||
| Лунный обсидиан | Глубинные разломы | Структуры защиты |
|
||||
| Эхо-кристалл | Рейдовые боссы | Улучшение реликвий |
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/mechanics/">Механики</a> · <a href="/guides/">Гайды</a>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
---
|
||||
title: "Механики"
|
||||
description: "Основные игровые системы: энергия, климат, аномалии и мировые события."
|
||||
---
|
||||
|
||||
## Энергия эфира
|
||||
|
||||
Эфир усиливает способности и влияет на доступ к скрытым зонам.
|
||||
|
||||
| Уровень эфира | Эффект |
|
||||
| --- | --- |
|
||||
| 0-20 | Базовые действия |
|
||||
| 21-60 | Бонус к добыче и скорости |
|
||||
| 61+ | Открываются артефактные узлы |
|
||||
|
||||
### Как повышать эфир
|
||||
|
||||
- Выполнять ежедневные контракты.
|
||||
- Закрывать аномалии в группе.
|
||||
- Исследовать архивные башни.
|
||||
|
||||
## Мировые события
|
||||
|
||||
### Разломы
|
||||
|
||||
Появляются раз в несколько часов и требуют командной обороны.
|
||||
|
||||
### Небесный дождь
|
||||
|
||||
Даёт редкие ингредиенты, но привлекает элитных мобов.
|
||||
|
||||
:::note
|
||||
`h2` и `h3` автоматически попадают в оглавление страницы справа.
|
||||
:::
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/items-resources/">Предметы и ресурсы</a> · <a href="/rules/">Правила</a>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
title: "Профессии / классы / расы"
|
||||
description: "Гибкая RPG-система: роли, бонусы, ограничения и синергия в группе."
|
||||
---
|
||||
|
||||
## Расы
|
||||
|
||||
- Астралы: бонус к мане и исследованию.
|
||||
- Форджеры: ускоренный крафт и переработка руд.
|
||||
- Вейлборны: скрытность и мобильность.
|
||||
|
||||
## Классы
|
||||
|
||||
### Страж
|
||||
|
||||
Высокая выживаемость и контроль зоны.
|
||||
|
||||
### Проводник
|
||||
|
||||
Баффы команды и лечение в бою.
|
||||
|
||||
### Пилигрим
|
||||
|
||||
Урон по одиночным целям и ускорение перемещения.
|
||||
|
||||
## Профессии
|
||||
|
||||
1. Алхимик
|
||||
2. Инженер
|
||||
3. Хранитель ферм
|
||||
4. Архивариус-торговец
|
||||
|
||||
:::tip
|
||||
Лучше выбрать профессию, которая дополняет класс, а не дублирует его сильные стороны.
|
||||
:::
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/economy/">Экономика</a> · <a href="/guides/">Гайды</a>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
---
|
||||
title: "Сюжет"
|
||||
description: "Черновик сюжета. Заполните своим лором."
|
||||
---
|
||||
|
||||
## Сюжет
|
||||
|
||||
Это временный блок, чтобы раздел уже был в меню.
|
||||
|
||||
Над архипелагом горят три луны, по ночам реки светятся серебром, а у подножия черной цитадели начинают исчезать целые караваны.
|
||||
|
||||
Позже вы сможете полностью заменить этот текст на основной сюжет сервера.
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
title: "Команда проекта"
|
||||
description: "Кто развивает сервер: роли, ответственность и зоны поддержки."
|
||||
---
|
||||
|
||||
## Состав команды
|
||||
|
||||
| Роль | Зона ответственности |
|
||||
| --- | --- |
|
||||
| Lead Admin | Архитектура мира и баланс |
|
||||
| Content Designer | Квесты, лор, события |
|
||||
| Tech Admin | Стабильность, плагины, бэкапы |
|
||||
| Community Manager | Коммуникация с игроками |
|
||||
|
||||
## Как мы работаем
|
||||
|
||||
### Принцип 1
|
||||
|
||||
Решения по балансу принимаются на основе статистики, а не эмоций.
|
||||
|
||||
### Принцип 2
|
||||
|
||||
Критические правки публикуются с changelog.
|
||||
|
||||
## Как присоединиться
|
||||
|
||||
Следи за открытыми ролями в Discord и оставляй заявку с примерами работ.
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/contacts/">Контакты / ссылки</a> · <a href="/about-server/">О сервере</a>
|
||||
</div>
|
||||
|
||||
|
||||
48
src/content/docs/templates/new-page-template.md
vendored
@@ -1,48 +0,0 @@
|
||||
---
|
||||
title: "Шаблон новой страницы"
|
||||
description: "Готовый шаблон Markdown-страницы для быстрого добавления новых материалов."
|
||||
---
|
||||
|
||||
## Копируй и используй
|
||||
|
||||
```md
|
||||
---
|
||||
title: "Название раздела"
|
||||
description: "Краткое описание страницы"
|
||||
---
|
||||
|
||||
## Введение
|
||||
|
||||
Коротко опиши, что на странице.
|
||||
|
||||
## Основной раздел
|
||||
|
||||
### Подраздел
|
||||
|
||||
- Пункт 1
|
||||
- Пункт 2
|
||||
|
||||
:::tip
|
||||
Добавляй подсказки через стандартные блоки Starlight.
|
||||
:::
|
||||
|
||||
## Таблица
|
||||
|
||||
| Колонка | Значение |
|
||||
| --- | --- |
|
||||
| Пример | Текст |
|
||||
|
||||
<div class="see-also">
|
||||
<p>Смотри также</p>
|
||||
<a href="/getting-started/">Начало игры</a>
|
||||
</div>
|
||||
```
|
||||
|
||||
## Рекомендации по структуре
|
||||
|
||||
- Один файл = одна тема.
|
||||
- Пиши короткие абзацы.
|
||||
- Используй `h2` и `h3`, чтобы оглавление было полезным.
|
||||
- Добавляй блок «Смотри также» в конце страницы.
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ starlight-menu-button button::before {
|
||||
}
|
||||
|
||||
starlight-menu-button[aria-expanded='true'] button::before {
|
||||
content: '✕';
|
||||
content: '×';
|
||||
font-size: 1.02rem;
|
||||
letter-spacing: 0;
|
||||
transform: none;
|
||||
@@ -226,6 +226,21 @@ starlight-menu-button button:hover {
|
||||
background: color-mix(in srgb, var(--sl-color-accent-low) 32%, transparent);
|
||||
}
|
||||
|
||||
.sidebar-content .sidebar-group-link {
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sidebar-content .sidebar-group-link:hover {
|
||||
text-decoration: none;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.sidebar-content :is(a[aria-current='page'], a[aria-current='page']:hover) {
|
||||
background: color-mix(in srgb, var(--sl-color-gray-6) 62%, transparent);
|
||||
color: var(--sl-color-white);
|
||||
@@ -305,9 +320,26 @@ starlight-menu-button button:hover {
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
/* Единый эффект свечения в момент нажатия для всех кнопок/кнопкоподобных элементов. */
|
||||
:is(
|
||||
button:not(:disabled),
|
||||
.sl-link-button,
|
||||
.map-cta-button,
|
||||
.map-ghost-button,
|
||||
.copy-ip-chip
|
||||
):active {
|
||||
transform: translateY(0) scale(0.98) !important;
|
||||
box-shadow:
|
||||
0 0 0 1px color-mix(in srgb, var(--sl-color-accent) 34%, transparent),
|
||||
0 0 18px color-mix(in srgb, var(--sl-color-accent) 34%, transparent),
|
||||
0 0 34px color-mix(in srgb, var(--wiki-blue-2) 26%, transparent) !important;
|
||||
filter: saturate(1.08);
|
||||
}
|
||||
|
||||
.sl-markdown-content h1,
|
||||
.sl-markdown-content h2,
|
||||
.sl-markdown-content h3 {
|
||||
.sl-markdown-content h3,
|
||||
.sl-markdown-content h4 {
|
||||
font-family: 'Sora', sans-serif;
|
||||
letter-spacing: 0.005em;
|
||||
line-height: 1.24;
|
||||
@@ -331,6 +363,40 @@ starlight-menu-button button:hover {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.sl-markdown-content h4 {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 0.36rem;
|
||||
font-size: clamp(0.96rem, 0.93rem + 0.18vw, 1.07rem);
|
||||
color: color-mix(in srgb, var(--sl-color-white) 86%, var(--wiki-blue-2));
|
||||
}
|
||||
|
||||
.sl-markdown-content .sl-heading-wrapper.level-h3 > h3 {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 0.52rem;
|
||||
}
|
||||
|
||||
.sl-markdown-content .minimal-heading-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
flex-shrink: 0;
|
||||
opacity: 0.98;
|
||||
background: linear-gradient(
|
||||
150deg,
|
||||
color-mix(in srgb, var(--wiki-purple-2) 76%, #ffffff),
|
||||
color-mix(in srgb, var(--wiki-blue-2) 82%, #ffffff)
|
||||
);
|
||||
-webkit-mask-image: var(--icon-url);
|
||||
mask-image: var(--icon-url);
|
||||
-webkit-mask-size: contain;
|
||||
mask-size: contain;
|
||||
-webkit-mask-repeat: no-repeat;
|
||||
mask-repeat: no-repeat;
|
||||
-webkit-mask-position: center;
|
||||
mask-position: center;
|
||||
}
|
||||
|
||||
.sl-markdown-content p,
|
||||
.sl-markdown-content li {
|
||||
color: var(--wiki-text);
|
||||
@@ -355,6 +421,61 @@ starlight-menu-button button:hover {
|
||||
text-decoration-thickness: 0.07em;
|
||||
}
|
||||
|
||||
.sl-markdown-content :is(p, li, td, blockquote) a[href]:not(.sl-anchor-link):not(.map-cta-button):not(
|
||||
.map-ghost-button
|
||||
):not(.sl-link-button):not([href^='#']) {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 2.44rem;
|
||||
max-width: min(100%, 100ch);
|
||||
margin: 0.1rem 0.2rem 0.1rem 0;
|
||||
padding: 0.55rem 1rem;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 48%, transparent);
|
||||
border-radius: 0.2rem;
|
||||
background: linear-gradient(
|
||||
110deg,
|
||||
color-mix(in srgb, var(--wiki-blue-2) 76%, #233145),
|
||||
color-mix(in srgb, var(--wiki-purple-2) 66%, #273850)
|
||||
);
|
||||
color: #f8fbff;
|
||||
text-decoration: none;
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
letter-spacing: 0.008em;
|
||||
line-height: 1;
|
||||
overflow-wrap: anywhere;
|
||||
box-shadow: 0 6px 14px color-mix(in srgb, var(--sl-color-accent) 18%, transparent);
|
||||
transition: transform 170ms ease, border-color 170ms ease, box-shadow 170ms ease;
|
||||
}
|
||||
|
||||
.sl-markdown-content :is(p, li, td, blockquote) a[href]:not(.sl-anchor-link):not(.map-cta-button):not(
|
||||
.map-ghost-button
|
||||
):not(.sl-link-button):not([href^='#']):hover {
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
transform: translateY(-1px);
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 64%, transparent);
|
||||
box-shadow: 0 10px 18px color-mix(in srgb, var(--sl-color-accent) 24%, transparent);
|
||||
}
|
||||
|
||||
.sl-markdown-content :is(p, li, td, blockquote) a[href]:not(.sl-anchor-link):not(.map-cta-button):not(
|
||||
.map-ghost-button
|
||||
):not(.sl-link-button):not([href^='#']):focus-visible {
|
||||
outline: none;
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 72%, transparent);
|
||||
box-shadow:
|
||||
0 0 0 1px color-mix(in srgb, var(--sl-color-accent) 30%, transparent),
|
||||
0 0 0 4px color-mix(in srgb, var(--sl-color-accent) 20%, transparent);
|
||||
}
|
||||
|
||||
.sl-markdown-content :is(p, li, td, blockquote) a[href]:not(.sl-anchor-link):not(.map-cta-button):not(
|
||||
.map-ghost-button
|
||||
):not(.sl-link-button):not([href^='#']):active {
|
||||
transform: translateY(0) scale(0.98);
|
||||
}
|
||||
|
||||
.sl-markdown-content code {
|
||||
border-radius: 0.16rem;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-hairline) 78%, transparent);
|
||||
@@ -415,6 +536,28 @@ starlight-toc a {
|
||||
transition: background 180ms ease, color 180ms ease, transform 180ms ease;
|
||||
}
|
||||
|
||||
/* Разделы, внутри которых есть подпункты, выделяем сильнее. */
|
||||
starlight-toc li:has(> ul) > a,
|
||||
mobile-starlight-toc li:has(> ul) > a {
|
||||
font-weight: 700;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 22%, transparent);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
color-mix(in srgb, var(--wiki-purple-2) 20%, transparent),
|
||||
color-mix(in srgb, var(--wiki-blue-2) 12%, transparent)
|
||||
);
|
||||
}
|
||||
|
||||
starlight-toc li:has(> ul) > a:hover,
|
||||
mobile-starlight-toc li:has(> ul) > a:hover {
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 44%, transparent);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
color-mix(in srgb, var(--wiki-purple-2) 30%, transparent),
|
||||
color-mix(in srgb, var(--wiki-blue-2) 18%, transparent)
|
||||
);
|
||||
}
|
||||
|
||||
starlight-toc a::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@@ -585,6 +728,197 @@ starlight-theme-select .caret {
|
||||
margin-bottom: 0.45rem;
|
||||
}
|
||||
|
||||
.craft-grid {
|
||||
display: grid;
|
||||
gap: 1rem;
|
||||
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||
grid-auto-rows: 1fr;
|
||||
margin: 1rem 0 1.3rem;
|
||||
}
|
||||
|
||||
.craft-grid > .craft-card {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.craft-catalog {
|
||||
margin-top: 0.95rem;
|
||||
}
|
||||
|
||||
.craft-controls {
|
||||
display: grid;
|
||||
gap: 0.72rem;
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
.craft-search-field {
|
||||
display: grid;
|
||||
gap: 0.36rem;
|
||||
font-weight: 700;
|
||||
font-size: 0.95rem;
|
||||
color: color-mix(in srgb, var(--wiki-text) 92%, var(--sl-color-white));
|
||||
}
|
||||
|
||||
.craft-search-input {
|
||||
width: 100%;
|
||||
min-height: 2.42rem;
|
||||
border-radius: 0.18rem;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-hairline) 82%, transparent);
|
||||
background: color-mix(in srgb, var(--wiki-card) 92%, transparent);
|
||||
color: var(--wiki-text);
|
||||
padding: 0.5rem 0.68rem;
|
||||
font: inherit;
|
||||
transition: border-color 150ms ease, box-shadow 150ms ease;
|
||||
}
|
||||
|
||||
.craft-search-input::placeholder {
|
||||
color: color-mix(in srgb, var(--wiki-muted) 78%, var(--sl-color-white));
|
||||
}
|
||||
|
||||
.craft-search-input:focus-visible {
|
||||
outline: none;
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 68%, transparent);
|
||||
box-shadow:
|
||||
0 0 0 1px color-mix(in srgb, var(--sl-color-accent) 30%, transparent),
|
||||
0 0 0 4px color-mix(in srgb, var(--sl-color-accent) 18%, transparent);
|
||||
}
|
||||
|
||||
.craft-filter-group {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.48rem;
|
||||
}
|
||||
|
||||
.craft-filter-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 2.1rem;
|
||||
border-radius: 999px;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-hairline) 85%, transparent);
|
||||
background: color-mix(in srgb, var(--wiki-card) 92%, transparent);
|
||||
color: color-mix(in srgb, var(--wiki-text) 92%, var(--sl-color-white));
|
||||
padding: 0.4rem 0.82rem;
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 0.84rem;
|
||||
letter-spacing: 0.008em;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
transform 150ms ease,
|
||||
border-color 150ms ease,
|
||||
background 150ms ease,
|
||||
color 150ms ease;
|
||||
}
|
||||
|
||||
.craft-filter-chip:hover {
|
||||
transform: translateY(-1px);
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 42%, transparent);
|
||||
}
|
||||
|
||||
.craft-filter-chip.is-active {
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 56%, transparent);
|
||||
background: linear-gradient(
|
||||
120deg,
|
||||
color-mix(in srgb, var(--wiki-blue-2) 74%, #233145),
|
||||
color-mix(in srgb, var(--wiki-purple-2) 64%, #273850)
|
||||
);
|
||||
color: #f7fbff;
|
||||
}
|
||||
|
||||
.craft-empty {
|
||||
margin: 0.18rem 0 1.02rem;
|
||||
border: 1px dashed color-mix(in srgb, var(--sl-color-accent) 34%, transparent);
|
||||
border-radius: 0.16rem;
|
||||
background: color-mix(in srgb, var(--sl-color-accent-low) 66%, transparent);
|
||||
padding: 0.62rem 0.74rem;
|
||||
font-size: 0.93rem;
|
||||
}
|
||||
|
||||
.craft-group {
|
||||
margin-bottom: 1.15rem;
|
||||
}
|
||||
|
||||
.craft-group > h3 {
|
||||
margin-bottom: 0.58rem;
|
||||
}
|
||||
|
||||
.craft-card {
|
||||
padding: 0.82rem 0.86rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.craft-card:hover {
|
||||
transform: none;
|
||||
}
|
||||
|
||||
.craft-card h3 {
|
||||
margin: 0 0 0.6rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.35;
|
||||
min-height: calc(1.35em * 2);
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.craft-card-image {
|
||||
display: block;
|
||||
width: 100%;
|
||||
aspect-ratio: 346 / 167;
|
||||
object-fit: cover;
|
||||
border-radius: 0.18rem;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-hairline) 88%, transparent);
|
||||
background: color-mix(in srgb, #ffffff 18%, transparent);
|
||||
box-shadow: var(--sl-shadow-sm);
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.craft-card[hidden],
|
||||
.craft-group[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.alcohol-nav-card {
|
||||
display: block;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.alcohol-nav-card:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.alcohol-nav-card p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.contact-link-card {
|
||||
display: block;
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.contact-link-card:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.contact-link-card p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.city-feature-card p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.city-highlight {
|
||||
font-size: inherit;
|
||||
font-weight: 700;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
.command-block {
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-hairline) 88%, transparent);
|
||||
border-radius: 0.16rem;
|
||||
@@ -615,6 +949,221 @@ starlight-theme-select .caret {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.ip-main-grid {
|
||||
display: grid;
|
||||
gap: 0.96rem;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
grid-auto-rows: minmax(0, 1fr);
|
||||
align-items: stretch;
|
||||
margin: 0.95rem 0 0.8rem;
|
||||
}
|
||||
|
||||
.ip-main-card {
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 28%, var(--sl-color-hairline));
|
||||
border-radius: 0.2rem;
|
||||
padding: 1rem 1.02rem;
|
||||
height: 100%;
|
||||
min-height: 11.2rem;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background:
|
||||
linear-gradient(
|
||||
160deg,
|
||||
color-mix(in srgb, var(--wiki-purple-2) 12%, transparent),
|
||||
color-mix(in srgb, var(--wiki-blue-2) 8%, transparent)
|
||||
),
|
||||
color-mix(in srgb, var(--wiki-card) 96%, transparent);
|
||||
}
|
||||
|
||||
.ip-main-grid > .ip-main-card {
|
||||
margin: 0 !important;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
.ip-main-grid > .ip-main-card + .ip-main-card {
|
||||
margin-top: 0 !important;
|
||||
}
|
||||
|
||||
.ip-main-card h3 {
|
||||
margin: 0 0 0.52rem;
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-size: 1.02rem;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.ip-main-card ul {
|
||||
margin: 0;
|
||||
padding-inline-start: 1.06rem;
|
||||
display: grid;
|
||||
gap: 0.52rem;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.ip-main-card li {
|
||||
margin: 0;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.copy-ip-chip {
|
||||
appearance: none;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 48%, transparent);
|
||||
border-radius: 0.2rem;
|
||||
background: linear-gradient(
|
||||
110deg,
|
||||
color-mix(in srgb, var(--wiki-blue-2) 76%, #233145),
|
||||
color-mix(in srgb, var(--wiki-purple-2) 66%, #273850)
|
||||
);
|
||||
color: #f8fbff;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 2rem;
|
||||
padding: 0.36rem 0.72rem;
|
||||
margin: 0 0 0 0.24rem;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 0.86rem;
|
||||
letter-spacing: 0.008em;
|
||||
line-height: 1;
|
||||
box-shadow: 0 6px 14px color-mix(in srgb, var(--sl-color-accent) 18%, transparent);
|
||||
transition: transform 170ms ease, border-color 170ms ease, box-shadow 170ms ease;
|
||||
}
|
||||
|
||||
.copy-ip-chip code {
|
||||
margin: 0;
|
||||
border: 0;
|
||||
background: transparent;
|
||||
display: inline-block;
|
||||
padding: 0;
|
||||
font-size: inherit;
|
||||
font-family: inherit;
|
||||
font-weight: inherit;
|
||||
line-height: 1.2;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.copy-ip-chip:hover {
|
||||
color: #ffffff;
|
||||
transform: translateY(-1px);
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 66%, transparent);
|
||||
box-shadow: 0 10px 18px color-mix(in srgb, var(--sl-color-accent) 24%, transparent);
|
||||
}
|
||||
|
||||
.copy-ip-chip:focus-visible {
|
||||
outline: none;
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 72%, transparent);
|
||||
box-shadow:
|
||||
0 0 0 1px color-mix(in srgb, var(--sl-color-accent) 30%, transparent),
|
||||
0 0 0 4px color-mix(in srgb, var(--sl-color-accent) 20%, transparent);
|
||||
}
|
||||
|
||||
.copy-ip-chip.is-copied {
|
||||
border-color: color-mix(in srgb, #7ed49b 66%, transparent);
|
||||
background: linear-gradient(
|
||||
110deg,
|
||||
color-mix(in srgb, #63b888 76%, #223b2f),
|
||||
color-mix(in srgb, #5ccd9f 66%, #26463b)
|
||||
);
|
||||
}
|
||||
|
||||
.copy-ip-chip.is-copied::after {
|
||||
content: '';
|
||||
}
|
||||
|
||||
.copy-ip-chip.is-copy-error {
|
||||
border-color: color-mix(in srgb, #ef6f85 74%, transparent);
|
||||
background: linear-gradient(
|
||||
110deg,
|
||||
color-mix(in srgb, #d56b7f 78%, #3b242a),
|
||||
color-mix(in srgb, #cf6f90 68%, #3f2532)
|
||||
);
|
||||
}
|
||||
|
||||
.copy-ip-chip.is-copy-error::after {
|
||||
content: '';
|
||||
}
|
||||
|
||||
.ip-main-note {
|
||||
margin-top: 0.52rem;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 30%, transparent);
|
||||
border-radius: 0.18rem;
|
||||
padding: 0.58rem 0.72rem;
|
||||
background: color-mix(in srgb, var(--sl-color-accent-low) 66%, transparent);
|
||||
color: var(--wiki-text);
|
||||
font-size: 0.94rem;
|
||||
}
|
||||
|
||||
.map-actions {
|
||||
margin-top: 1rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.62rem;
|
||||
}
|
||||
|
||||
.map-cta-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 2.44rem;
|
||||
padding: 0.55rem 1rem;
|
||||
border-radius: 0.2rem;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 48%, transparent);
|
||||
background: linear-gradient(
|
||||
110deg,
|
||||
color-mix(in srgb, var(--wiki-blue-2) 76%, #233145),
|
||||
color-mix(in srgb, var(--wiki-purple-2) 66%, #273850)
|
||||
);
|
||||
color: #f8fbff;
|
||||
text-decoration: none;
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
letter-spacing: 0.008em;
|
||||
box-shadow: 0 6px 14px color-mix(in srgb, var(--sl-color-accent) 18%, transparent);
|
||||
transition: transform 170ms ease, border-color 170ms ease, box-shadow 170ms ease;
|
||||
}
|
||||
|
||||
.map-cta-button:hover {
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
transform: translateY(-1px);
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 66%, transparent);
|
||||
box-shadow: 0 10px 18px color-mix(in srgb, var(--sl-color-accent) 24%, transparent);
|
||||
}
|
||||
|
||||
.map-ghost-button {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 2.44rem;
|
||||
padding: 0.55rem 1rem;
|
||||
border-radius: 0.2rem;
|
||||
border: 1px solid color-mix(in srgb, var(--sl-color-accent) 48%, transparent);
|
||||
background: linear-gradient(
|
||||
110deg,
|
||||
color-mix(in srgb, var(--wiki-blue-2) 76%, #233145),
|
||||
color-mix(in srgb, var(--wiki-purple-2) 66%, #273850)
|
||||
);
|
||||
color: #f8fbff;
|
||||
text-decoration: none;
|
||||
font-family: 'Sora', sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
letter-spacing: 0.008em;
|
||||
box-shadow: 0 6px 14px color-mix(in srgb, var(--sl-color-accent) 18%, transparent);
|
||||
transition: transform 170ms ease, border-color 170ms ease, box-shadow 170ms ease;
|
||||
}
|
||||
|
||||
.map-ghost-button:hover {
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
transform: translateY(-1px);
|
||||
border-color: color-mix(in srgb, var(--sl-color-accent) 66%, transparent);
|
||||
box-shadow: 0 10px 18px color-mix(in srgb, var(--sl-color-accent) 24%, transparent);
|
||||
}
|
||||
|
||||
@media (min-width: 50rem) {
|
||||
.hero {
|
||||
grid-template-columns: 1fr;
|
||||
@@ -631,6 +1180,10 @@ starlight-theme-select .caret {
|
||||
}
|
||||
|
||||
@media (max-width: 50rem) {
|
||||
.ip-main-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.wiki-header {
|
||||
gap: 0.5rem;
|
||||
}
|
||||
@@ -710,4 +1263,19 @@ starlight-theme-select .caret {
|
||||
border-radius: 0.16rem;
|
||||
padding: 0.92rem 0.84rem;
|
||||
}
|
||||
|
||||
.map-actions {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.map-cta-button,
|
||||
.map-ghost-button {
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.copy-ip-chip {
|
||||
margin-inline-start: 0.2rem;
|
||||
}
|
||||
}
|
||||
|
||||