Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/renderer/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,32 @@ export default {
stepBuild: 'Build',
stepConfigure: 'Configure',
chooseType: 'Choose the server software',
recommended: 'Recommended',
cat: {
vanilla: 'Vanilla',
vanillaDesc: 'The official, unmodified server. No plugins or mods — simplest and most compatible.',
plugin: 'Plugin servers (Bukkit family)',
pluginDesc: 'Run server-side plugins (Bukkit/Spigot API) for admin tools, economy, minigames — players need no mods.',
modded: 'Modded',
moddedDesc: 'Run mods; players must join with the matching mod loader / modpack installed.',
hybrid: 'Hybrid (mods + plugins)',
hybridDesc: 'Run mods and Bukkit plugins together. Flexible, but less stable than a pure modded or plugin server.',
proxy: 'Proxy (network gateway)',
proxyDesc: 'Not a game server — links several servers under one address to form a network. Only pick this to build a network.',
other: 'Other',
otherDesc: 'Additional server software.'
},
typeBlurb: {
vanilla: 'Pure Minecraft, exactly as Mojang ships it.',
paper: 'Fast, well-supported Bukkit/Spigot fork. The usual choice.',
purpur: 'Paper fork with many extra gameplay/config options.',
folia: 'Multithreaded Paper for very large, spread-out servers.',
forge: 'The classic mod loader — huge modpack ecosystem.',
neoforge: 'Modern Forge fork; the default for newer modpacks.',
fabric: 'Lightweight, fast-updating mod loader.',
mohist: 'Forge mods + Bukkit plugins on one server.',
velocity: 'Modern, high-performance proxy to link servers.'
},
chooseVersion: 'Choose the Minecraft version',
chooseBuild: 'Choose the build / loader',
includeUnstable: 'Show snapshots / betas / release-candidates',
Expand Down
26 changes: 26 additions & 0 deletions src/renderer/src/locales/tr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,32 @@ const tr: typeof en = {
stepBuild: 'Yapı',
stepConfigure: 'Yapılandır',
chooseType: 'Sunucu yazılımını seçin',
recommended: 'Önerilen',
cat: {
vanilla: 'Vanilla',
vanillaDesc: 'Resmi, değiştirilmemiş sunucu. Eklenti veya mod yok — en basit ve en uyumlu.',
plugin: 'Eklentili sunucular (Bukkit ailesi)',
pluginDesc: 'Yönetim araçları, ekonomi, mini oyunlar için sunucu-tarafı eklentiler (Bukkit/Spigot API) çalıştırır — oyuncular mod kurmaz.',
modded: 'Modlu',
moddedDesc: 'Mod çalıştırır; oyuncular uygun mod yükleyici / modpack kurulu olarak katılmalıdır.',
hybrid: 'Hibrit (mod + eklenti)',
hybridDesc: 'Mod ve Bukkit eklentilerini birlikte çalıştırır. Esnek ama saf modlu/eklentili sunucudan daha az kararlı.',
proxy: 'Proxy (ağ geçidi)',
proxyDesc: 'Bir oyun sunucusu değil — birden çok sunucuyu tek adres altında birleştirip ağ oluşturur. Sadece ağ kurmak için seçin.',
other: 'Diğer',
otherDesc: 'Ek sunucu yazılımı.'
},
typeBlurb: {
vanilla: 'Saf Minecraft, tam Mojang’ın sunduğu gibi.',
paper: 'Hızlı, iyi desteklenen Bukkit/Spigot türevi. Alışılmış tercih.',
purpur: 'Ekstra oynanış/yapılandırma seçenekleri olan Paper türevi.',
folia: 'Çok büyük, dağınık sunucular için çok iş parçacıklı Paper.',
forge: 'Klasik mod yükleyici — devasa modpack ekosistemi.',
neoforge: 'Modern Forge türevi; yeni modpack’ler için varsayılan.',
fabric: 'Hafif, hızlı güncellenen mod yükleyici.',
mohist: 'Tek sunucuda Forge modları + Bukkit eklentileri.',
velocity: 'Sunucuları bağlamak için modern, yüksek performanslı proxy.'
},
chooseVersion: 'Minecraft sürümünü seçin',
chooseBuild: 'Yapıyı / yükleyiciyi seçin',
includeUnstable: 'Anlık görüntüleri / betaları / sürüm adaylarını göster',
Expand Down
54 changes: 49 additions & 5 deletions src/renderer/src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -788,20 +788,64 @@ textarea.input:focus {
}
.type-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(110px, 1fr));
grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
gap: 8px;
}
.type-cat {
margin-top: 16px;
}
.type-cat:first-of-type {
margin-top: 4px;
}
.type-cat > h4 {
margin: 0 0 2px;
font-size: 13.5px;
font-weight: 700;
}
.type-cat > .cat-desc {
margin: 0 0 8px;
font-size: 12px;
color: var(--text-dim);
line-height: 1.4;
}
.type-card {
padding: 12px 10px;
padding: 11px 12px;
border-radius: var(--radius-sm);
border: 1px solid var(--border);
background: var(--bg-input);
color: var(--text);
font-weight: 600;
font-size: 13px;
text-align: center;
text-align: left;
display: flex;
flex-direction: column;
gap: 4px;
cursor: pointer;
transition: border-color 0.12s, background 0.12s;
}
.type-card .tc-head {
display: flex;
align-items: center;
gap: 7px;
}
.type-card .tc-name {
font-weight: 650;
font-size: 13.5px;
}
.type-card .tc-rec {
font-size: 9.5px;
font-weight: 800;
text-transform: uppercase;
letter-spacing: 0.05em;
padding: 1px 6px;
border-radius: 999px;
background: color-mix(in srgb, var(--accent) 18%, transparent);
color: var(--accent);
}
.type-card .tc-blurb {
font-size: 11.5px;
color: var(--text-dim);
font-weight: 400;
line-height: 1.35;
}
.type-card:hover {
background: var(--bg-hover);
}
Expand Down
63 changes: 52 additions & 11 deletions src/renderer/src/views/CreateView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,21 @@ import type { JavaPreset, ServerType } from '@shared/types'
const PROXY_TYPES: ServerType[] = ['velocity', 'waterfall', 'bungeecord']
const PRESETS: JavaPreset[] = ['aikars', 'aikars-large', 'basic']

/**
* Display grouping for the type picker (in order). Only types that are also in
* CREATABLE_TYPES render; any creatable type not listed here falls into an
* "other" bucket at render time, so nothing silently disappears if the set grows.
*/
const TYPE_CATEGORIES: { key: string; types: ServerType[] }[] = [
{ key: 'vanilla', types: ['vanilla'] },
{ key: 'plugin', types: ['paper', 'purpur', 'folia'] },
{ key: 'modded', types: ['forge', 'neoforge', 'fabric'] },
{ key: 'hybrid', types: ['mohist'] },
{ key: 'proxy', types: ['velocity'] }
]
/** Sensible defaults for newcomers, badged in the picker. */
const RECOMMENDED: ServerType[] = ['vanilla', 'paper', 'fabric']

/**
* Turn a raw createServer error code into a human message. The backend surfaces
* short codes (e.g. `no-mohist-build` when the upstream API lists a version but
Expand Down Expand Up @@ -131,6 +146,20 @@ export function CreateView(): JSX.Element {
}
}

// Type picker grouped into explained categories; any creatable type not
// placed in TYPE_CATEGORIES lands in a trailing "other" group.
const categorized = useMemo(() => {
const seen = new Set<ServerType>()
const cats = TYPE_CATEGORIES.map((c) => {
const types = c.types.filter((tp) => CREATABLE_TYPES.includes(tp))
types.forEach((tp) => seen.add(tp))
return { key: c.key, types }
}).filter((c) => c.types.length > 0)
const other = CREATABLE_TYPES.filter((tp) => !seen.has(tp))
if (other.length) cats.push({ key: 'other', types: other })
return cats
}, [])

const progressLabel = useMemo(() => {
if (!progress) return ''
switch (progress.stage) {
Expand Down Expand Up @@ -159,17 +188,29 @@ export function CreateView(): JSX.Element {
{/* Step 1: type */}
<div className="panel" style={{ maxWidth: 900 }}>
<div className="field-label">{t('wizard.chooseType')}</div>
<div className="type-grid">
{CREATABLE_TYPES.map((tp) => (
<button
key={tp}
className={`type-card ${type === tp ? 'active' : ''}`}
onClick={() => setType(tp)}
>
{t(`types.${tp}`)}
</button>
))}
</div>
{categorized.map((cat) => (
<div key={cat.key} className="type-cat">
<h4>{t(`wizard.cat.${cat.key}`)}</h4>
<p className="cat-desc">{t(`wizard.cat.${cat.key}Desc`)}</p>
<div className="type-grid">
{cat.types.map((tp) => (
<button
key={tp}
className={`type-card ${type === tp ? 'active' : ''}`}
onClick={() => setType(tp)}
>
<span className="tc-head">
<span className="tc-name">{t(`types.${tp}`)}</span>
{RECOMMENDED.includes(tp) && (
<span className="tc-rec">{t('wizard.recommended')}</span>
)}
</span>
<span className="tc-blurb">{t(`wizard.typeBlurb.${tp}`)}</span>
</button>
))}
</div>
</div>
))}

{type && (
<>
Expand Down
Loading