diff --git a/Cargo.lock b/Cargo.lock
index 07e0b9d3b..467e34285 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -643,10 +643,10 @@ dependencies = [
[[package]]
name = "async-minecraft-ping"
version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "668b459c14dd8d9ef21e296af3f2a3651ff7dc3536e092fb0b09e528daaa6d89"
+source = "git+https://github.com/jsvana/async-minecraft-ping?rev=56a64a8a59de854fb81cc0f9f66c2285873d960c#56a64a8a59de854fb81cc0f9f66c2285873d960c"
dependencies = [
"async-trait",
+ "hickory-resolver 0.24.4",
"serde",
"serde_json",
"thiserror 1.0.69",
@@ -1896,7 +1896,7 @@ checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9"
dependencies = [
"cookie 0.18.1",
"document-features",
- "idna 1.1.0",
+ "idna",
"log",
"publicsuffix",
"serde",
@@ -2698,24 +2698,6 @@ dependencies = [
"zeroize",
]
-[[package]]
-name = "elytra-ping"
-version = "6.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "086ee116d28d0eb35ae108d1059d135e585dd1254e5df881c5b2505a6d67c445"
-dependencies = [
- "bytes",
- "chrono",
- "mc-varint",
- "rand 0.9.2",
- "serde",
- "serde_json",
- "snafu",
- "tokio",
- "tracing",
- "trust-dns-resolver",
-]
-
[[package]]
name = "email-encoding"
version = "0.4.1"
@@ -3806,6 +3788,30 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
+[[package]]
+name = "hickory-proto"
+version = "0.24.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248"
+dependencies = [
+ "async-trait",
+ "cfg-if",
+ "data-encoding",
+ "enum-as-inner",
+ "futures-channel",
+ "futures-io",
+ "futures-util",
+ "idna",
+ "ipnet",
+ "once_cell",
+ "rand 0.8.5",
+ "thiserror 1.0.69",
+ "tinyvec",
+ "tokio",
+ "tracing",
+ "url",
+]
+
[[package]]
name = "hickory-proto"
version = "0.25.2"
@@ -3819,7 +3825,7 @@ dependencies = [
"futures-channel",
"futures-io",
"futures-util",
- "idna 1.1.0",
+ "idna",
"ipnet",
"once_cell",
"rand 0.9.2",
@@ -3831,6 +3837,27 @@ dependencies = [
"url",
]
+[[package]]
+name = "hickory-resolver"
+version = "0.24.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e"
+dependencies = [
+ "cfg-if",
+ "futures-util",
+ "hickory-proto 0.24.4",
+ "ipconfig",
+ "lru-cache",
+ "once_cell",
+ "parking_lot",
+ "rand 0.8.5",
+ "resolv-conf",
+ "smallvec",
+ "thiserror 1.0.69",
+ "tokio",
+ "tracing",
+]
+
[[package]]
name = "hickory-resolver"
version = "0.25.2"
@@ -3839,7 +3866,7 @@ checksum = "dc62a9a99b0bfb44d2ab95a7208ac952d31060efc16241c87eaf36406fecf87a"
dependencies = [
"cfg-if",
"futures-util",
- "hickory-proto",
+ "hickory-proto 0.25.2",
"ipconfig",
"moka",
"once_cell",
@@ -4289,16 +4316,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
-[[package]]
-name = "idna"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
-dependencies = [
- "unicode-bidi",
- "unicode-normalization",
-]
-
[[package]]
name = "idna"
version = "1.1.0"
@@ -4824,7 +4841,6 @@ dependencies = [
"dotenv-build",
"dotenvy",
"either",
- "elytra-ping",
"eyre",
"futures",
"futures-util",
@@ -4935,7 +4951,7 @@ dependencies = [
"futures-util",
"hostname",
"httpdate",
- "idna 1.1.0",
+ "idna",
"mime",
"nom 8.0.0",
"percent-encoding",
@@ -5252,12 +5268,6 @@ dependencies = [
"rayon",
]
-[[package]]
-name = "mc-varint"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6407d50d4e371d5f450a4a5f1abd4531e48e9a1627409c051b5d4c7c84f6bb09"
-
[[package]]
name = "md-5"
version = "0.10.6"
@@ -7178,7 +7188,7 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf"
dependencies = [
- "idna 1.1.0",
+ "idna",
"psl-types",
]
@@ -8918,28 +8928,6 @@ dependencies = [
"serde",
]
-[[package]]
-name = "snafu"
-version = "0.8.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2"
-dependencies = [
- "backtrace",
- "snafu-derive",
-]
-
-[[package]]
-name = "snafu-derive"
-version = "0.8.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451"
-dependencies = [
- "heck 0.5.0",
- "proc-macro2",
- "quote",
- "syn 2.0.106",
-]
-
[[package]]
name = "socket2"
version = "0.5.10"
@@ -10086,7 +10074,7 @@ dependencies = [
"fs4",
"futures",
"heck 0.5.0",
- "hickory-resolver",
+ "hickory-resolver 0.25.2",
"indicatif",
"itertools 0.14.0",
"notify",
@@ -10792,52 +10780,6 @@ dependencies = [
"windows-sys 0.59.0",
]
-[[package]]
-name = "trust-dns-proto"
-version = "0.23.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374"
-dependencies = [
- "async-trait",
- "cfg-if",
- "data-encoding",
- "enum-as-inner",
- "futures-channel",
- "futures-io",
- "futures-util",
- "idna 0.4.0",
- "ipnet",
- "once_cell",
- "rand 0.8.5",
- "smallvec",
- "thiserror 1.0.69",
- "tinyvec",
- "tokio",
- "tracing",
- "url",
-]
-
-[[package]]
-name = "trust-dns-resolver"
-version = "0.23.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6"
-dependencies = [
- "cfg-if",
- "futures-util",
- "ipconfig",
- "lru-cache",
- "once_cell",
- "parking_lot",
- "rand 0.8.5",
- "resolv-conf",
- "smallvec",
- "thiserror 1.0.69",
- "tokio",
- "tracing",
- "trust-dns-proto",
-]
-
[[package]]
name = "try-lock"
version = "0.2.5"
@@ -11057,7 +10999,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
dependencies = [
"form_urlencoded",
- "idna 1.1.0",
+ "idna",
"percent-encoding",
"serde",
]
@@ -11205,7 +11147,7 @@ version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43fb22e1a008ece370ce08a3e9e4447a910e92621bb49b85d6e48a45397e7cfa"
dependencies = [
- "idna 1.1.0",
+ "idna",
"once_cell",
"regex",
"serde",
diff --git a/Cargo.toml b/Cargo.toml
index dd4dd8fd3..04639aa10 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,7 +33,7 @@ arc-swap = "1.7.1"
argon2 = { version = "0.5.3", features = ["std"] }
ariadne = { path = "packages/ariadne" }
async-compression = { version = "0.4.32", default-features = false }
-async-minecraft-ping = { version = "0.8.0" }
+async-minecraft-ping = { git = "https://github.com/jsvana/async-minecraft-ping", rev = "56a64a8a59de854fb81cc0f9f66c2285873d960c" }
async-recursion = "1.1.1"
async-stripe = { version = "0.41.0", default-features = false, features = [
"runtime-tokio-hyper-rustls",
@@ -72,7 +72,6 @@ dotenv-build = "0.1.1"
dotenvy = "0.15.7"
dunce = "1.0.5"
either = "1.15.0"
-elytra-ping = "6.0.1"
encoding_rs = "0.8.35"
enumset = "1.1.10"
eyre = "0.6.12"
diff --git a/apps/app-frontend/src/pages/Browse.vue b/apps/app-frontend/src/pages/Browse.vue
index 05c7afcd6..cd25e243f 100644
--- a/apps/app-frontend/src/pages/Browse.vue
+++ b/apps/app-frontend/src/pages/Browse.vue
@@ -666,6 +666,7 @@ previousFilterState.value = JSON.stringify({
'server_category_minecraft_server_meta',
'server_category_minecraft_server_community',
'server_game_version',
+ 'server_status',
].includes(filterType.id)
"
>
@@ -810,7 +811,7 @@ previousFilterState.value = JSON.stringify({
:tags="project.categories"
:link="`/project/${project.slug ?? project.project_id}`"
:server-online-players="project.minecraft_java_server?.ping?.data?.players_online ?? 0"
- :server-region-code="project.minecraft_server?.country"
+ :server-region="project.minecraft_server?.region"
:server-recent-plays="project.minecraft_java_server?.verified_plays_4w ?? 0"
:server-modpack-content="getServerModpackContent(project)"
:server-ping="serverPings[project.project_id]"
diff --git a/apps/app-frontend/src/pages/instance/Index.vue b/apps/app-frontend/src/pages/instance/Index.vue
index 3167f204f..3800d242b 100644
--- a/apps/app-frontend/src/pages/instance/Index.vue
+++ b/apps/app-frontend/src/pages/instance/Index.vue
@@ -58,16 +58,16 @@
-
+
diff --git a/apps/frontend/src/components/ui/create/ProjectCreateModal.vue b/apps/frontend/src/components/ui/create/ProjectCreateModal.vue
index 66db57596..17f8766ca 100644
--- a/apps/frontend/src/components/ui/create/ProjectCreateModal.vue
+++ b/apps/frontend/src/components/ui/create/ProjectCreateModal.vue
@@ -417,11 +417,9 @@ async function createProject() {
},
minecraft_java_server: {
address: '',
- port: 25565,
},
minecraft_bedrock_server: {
address: '',
- port: 19132,
},
})
createdProjectId = result.id
diff --git a/apps/frontend/src/composables/featureFlags.ts b/apps/frontend/src/composables/featureFlags.ts
index 1fbab75ba..96748eec5 100644
--- a/apps/frontend/src/composables/featureFlags.ts
+++ b/apps/frontend/src/composables/featureFlags.ts
@@ -38,7 +38,6 @@ export const DEFAULT_FEATURE_FLAGS = validateValues({
newProjectGeneralSettings: false,
newProjectEnvironmentSettings: true,
hideRussiaCensorshipBanner: false,
- serverDiscovery: true,
disablePrettyProjectUrlRedirects: false,
hidePreviewBanner: false,
i18nDebug: false,
diff --git a/apps/frontend/src/layouts/default.vue b/apps/frontend/src/layouts/default.vue
index 2121b197b..082f566e9 100644
--- a/apps/frontend/src/layouts/default.vue
+++ b/apps/frontend/src/layouts/default.vue
@@ -184,7 +184,6 @@
{
id: 'servers',
action: '/discover/servers',
- shown: flags.serverDiscovery,
},
]"
hoverable
@@ -1002,6 +1001,10 @@ const navRoutes = computed(() => [
label: formatMessage(getProjectTypeMessage('modpack', true)),
href: '/discover/modpacks',
},
+ {
+ label: formatMessage(getProjectTypeMessage('server', true)),
+ href: '/discover/servers',
+ },
])
const userMenuOptions = computed(() => {
diff --git a/apps/frontend/src/pages/[type]/[id].vue b/apps/frontend/src/pages/[type]/[id].vue
index d4836dc11..9c94f42b2 100644
--- a/apps/frontend/src/pages/[type]/[id].vue
+++ b/apps/frontend/src/pages/[type]/[id].vue
@@ -1188,7 +1188,7 @@ const serverProject = computed(() => ({
numPlayers: projectV3.value?.minecraft_java_server?.ping?.data?.players_online,
icon: project.value.icon_url,
statusOnline: !!projectV3.value?.minecraft_java_server?.ping?.data,
- region: projectV3.value?.minecraft_server?.country,
+ region: projectV3.value?.minecraft_server?.region,
}))
function handlePlayServerProject() {
@@ -2528,8 +2528,6 @@ const navLinks = computed(() => {
? project.value.gallery.filter((item) => item.name === '__mc_server_banner__').length
: project.value.gallery.length
- console.log('galleryCount', galleryCount, !!currentMember.value)
-
return [
{
label: formatMessage(messages.descriptionTab),
diff --git a/apps/frontend/src/pages/[type]/[id]/settings/index.vue b/apps/frontend/src/pages/[type]/[id]/settings/index.vue
index 264ce1fff..02b66082c 100644
--- a/apps/frontend/src/pages/[type]/[id]/settings/index.vue
+++ b/apps/frontend/src/pages/[type]/[id]/settings/index.vue
@@ -146,7 +146,9 @@
(e) => {
const input = e.target
if (input.files?.length) {
- if (fileIsValid(input.files[0], { maxSize: 524288, alertOnInvalid: true }))
+ if (
+ fileIsValid(input.files[0], { maxSize: 524288000, alertOnInvalid: true })
+ )
showBannerPreview(Array.from(input.files))
}
}
diff --git a/apps/frontend/src/pages/[type]/[id]/settings/server.vue b/apps/frontend/src/pages/[type]/[id]/settings/server.vue
index c3dddbc1d..af8881622 100644
--- a/apps/frontend/src/pages/[type]/[id]/settings/server.vue
+++ b/apps/frontend/src/pages/[type]/[id]/settings/server.vue
@@ -4,17 +4,17 @@
Server details
-
+
-
@@ -48,7 +48,7 @@
{
if (!lastPingAddressChanged && javaPingResult) return
@@ -64,16 +64,6 @@
wrapper-class="flex-grow"
autocomplete="off"
/>
-
.
+
+ If you have [SRV records]
+ , you do not need to add a port. Otherwise if you have a port which isn't 25565, you
+ can include it as :12345
+
@@ -140,16 +141,6 @@
wrapper-class="flex-grow"
autocomplete="off"
/>
-
@@ -168,7 +159,7 @@
diff --git a/apps/frontend/src/pages/discover/[type]/index.vue b/apps/frontend/src/pages/discover/[type]/index.vue
index 05b21c908..af485f6c1 100644
--- a/apps/frontend/src/pages/discover/[type]/index.vue
+++ b/apps/frontend/src/pages/discover/[type]/index.vue
@@ -642,6 +642,7 @@ const getServerModpackContent = (hit: Labrinth.Search.v3.ResultSearchProject) =>
'server_category_minecraft_server_meta',
'server_category_minecraft_server_community',
'server_game_version',
+ 'server_status',
].includes(filterType.id)
"
>
@@ -800,7 +801,7 @@ const getServerModpackContent = (hit: Labrinth.Search.v3.ResultSearchProject) =>
project.minecraft_java_server?.ping?.data?.players_online ?? 0
"
:server-recent-plays="project.minecraft_java_server?.verified_plays_2w ?? 0"
- :server-region-code="project.minecraft_server?.country"
+ :server-region="project.minecraft_server?.region"
:server-status-online="!!project.minecraft_java_server?.ping?.data"
:server-modpack-content="getServerModpackContent(project)"
:layout="
diff --git a/apps/labrinth/Cargo.toml b/apps/labrinth/Cargo.toml
index efe3723a3..a8598d158 100644
--- a/apps/labrinth/Cargo.toml
+++ b/apps/labrinth/Cargo.toml
@@ -21,7 +21,7 @@ actix-ws = { workspace = true }
arc-swap = { workspace = true }
argon2 = { workspace = true }
ariadne = { workspace = true }
-async-minecraft-ping = { workspace = true }
+async-minecraft-ping = { workspace = true, features = ["srv"] }
async-stripe = { workspace = true, features = [
"billing",
"checkout",
@@ -44,7 +44,6 @@ deadpool-redis.workspace = true
derive_more = { workspace = true, features = ["deref", "deref_mut"] }
dotenvy = { workspace = true }
either = { workspace = true }
-elytra-ping = { workspace = true }
eyre = { workspace = true }
futures = { workspace = true }
futures-util = { workspace = true }
diff --git a/apps/labrinth/src/clickhouse/mod.rs b/apps/labrinth/src/clickhouse/mod.rs
index 6830aed1a..3d922d0b9 100644
--- a/apps/labrinth/src/clickhouse/mod.rs
+++ b/apps/labrinth/src/clickhouse/mod.rs
@@ -172,7 +172,6 @@ pub async fn init_client_with_database(
recorded DateTime64(4),
project_id UInt64,
address String,
- port UInt16,
online Bool,
latency_ms Nullable(UInt32),
description Nullable(String),
@@ -219,5 +218,15 @@ pub async fn init_client_with_database(
.execute()
.await?;
+ client
+ .query(&format!(
+ "
+ ALTER TABLE {database}.{MINECRAFT_JAVA_SERVER_PINGS} {cluster_line}
+ DROP COLUMN IF EXISTS port
+ "
+ ))
+ .execute()
+ .await?;
+
Ok(client.with_database(database))
}
diff --git a/apps/labrinth/src/models/exp/compat.rs b/apps/labrinth/src/models/exp/compat.rs
index 562f71ddb..ba5f206b1 100644
--- a/apps/labrinth/src/models/exp/compat.rs
+++ b/apps/labrinth/src/models/exp/compat.rs
@@ -32,6 +32,7 @@ mod tests {
minecraft_server: Some(ServerProject {
max_players: None,
country: None,
+ region: None,
languages: vec![],
active_version: None,
}),
diff --git a/apps/labrinth/src/models/exp/minecraft.rs b/apps/labrinth/src/models/exp/minecraft.rs
index 1dcd9481b..a66333c76 100644
--- a/apps/labrinth/src/models/exp/minecraft.rs
+++ b/apps/labrinth/src/models/exp/minecraft.rs
@@ -101,6 +101,15 @@ component::define! {
#[validate(length(min = 2, max = 2))]
pub country: Option,
#[base(serde(default))]
+ #[edit(serde(
+ default,
+ skip_serializing_if = "Option::is_none",
+ with = "serde_with::rust::double_option"
+ ))]
+ #[create(optional)]
+ /// Geographical region which this server is hosted in.
+ pub region: Option,
+ #[base(serde(default))]
#[edit(serde(default))]
#[create(default)]
/// Languages which the owners of this server prefer.
@@ -129,11 +138,6 @@ component::define! {
/// Address (IP or domain name) of the Bedrock server, excluding port.
#[validate(length(max = 255))]
pub address: String,
- #[base()]
- #[edit(serde(default))]
- #[create(required)]
- /// Port which the server runs on.
- pub port: u16,
}
}
@@ -167,8 +171,6 @@ pub struct JavaServerProject {
/// Address (IP or domain name) of the Java server, excluding port.
#[validate(length(max = 255))]
pub address: String,
- /// Port which the server runs on.
- pub port: u16,
/// What game content this server is using.
#[serde(default)]
pub content: ServerContent,
@@ -180,15 +182,12 @@ pub struct JavaServerProjectEdit {
#[serde(default)]
pub address: Option,
#[serde(default)]
- pub port: Option,
- #[serde(default)]
pub content: Option,
}
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct JavaServerProjectQuery {
pub address: String,
- pub port: u16,
pub content: ServerContentQuery,
pub ping: Option,
pub verified_plays_2w: Option,
@@ -229,7 +228,6 @@ impl ComponentQuery for JavaServerProjectQuery {
let analytics = context.minecraft_server_analytics.get(&project_id);
Ok(Self {
address: serial.address,
- port: serial.port,
content: match serial.content {
ServerContent::Vanilla {
supported_game_versions,
@@ -276,7 +274,6 @@ impl ComponentEdit for JavaServerProjectEdit {
fn create(self) -> Result {
Ok(JavaServerProject {
address: self.address.wrap_err("missing `address`")?,
- port: self.port.wrap_err("missing `port`")?,
content: self.content.unwrap_or_default(),
})
}
@@ -285,9 +282,6 @@ impl ComponentEdit for JavaServerProjectEdit {
if let Some(address) = self.address {
component.address = address;
}
- if let Some(port) = self.port {
- component.port = port;
- }
if let Some(content) = self.content {
component.content = content;
}
@@ -347,6 +341,29 @@ impl Default for ServerContent {
}
}
+#[derive(
+ Debug,
+ Clone,
+ Copy,
+ PartialEq,
+ Eq,
+ Hash,
+ Serialize,
+ Deserialize,
+ utoipa::ToSchema,
+)]
+#[serde(rename_all = "snake_case")]
+pub enum ServerRegion {
+ UsEast,
+ UsWest,
+ Europe,
+ Asia,
+ Australia,
+ SouthAmerica,
+ MiddleEast,
+ Russia,
+}
+
/// Recorded ping attempt that Labrinth made to a Minecraft Java server project.
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct JavaServerPing {
@@ -354,8 +371,6 @@ pub struct JavaServerPing {
pub when: DateTime,
/// Address of the server at the time of the ping.
pub address: String,
- /// Port of the server at the time of the ping.
- pub port: u16,
/// If the ping was successful, info on the ping response.
pub data: Option,
}
diff --git a/apps/labrinth/src/queue/server_ping.rs b/apps/labrinth/src/queue/server_ping.rs
index f03a1aea0..b08f21b10 100644
--- a/apps/labrinth/src/queue/server_ping.rs
+++ b/apps/labrinth/src/queue/server_ping.rs
@@ -15,7 +15,7 @@ use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::Semaphore;
use tokio::task::JoinSet;
-use tracing::{Instrument, debug, info, info_span, trace, warn};
+use tracing::{Instrument, info, info_span, trace, warn};
pub struct ServerPingQueue {
pub db: PgPool,
@@ -44,17 +44,16 @@ impl ServerPingQueue {
let pings = server_projects
.into_iter()
.map(|(project_id, java_server)| {
- let address = java_server.address.to_string();
- let port = java_server.port;
- let span = info_span!("ping", %project_id, %address, %port);
+ let span = info_span!("ping", %project_id, address = %java_server.address);
let active_pings = active_pings.clone();
+ let address = java_server.address;
let task = async move {
let _permit = active_pings.acquire().await.expect("semaphore should not be closed now");
let mut retries = ENV.SERVER_PING_RETRIES;
let result = loop {
- match ping_server(&address, port, None).await {
+ match ping_server(&address, None).await {
Ok(ping) => {
info!(?ping, "Received successful ping");
break Ok(ping);
@@ -73,8 +72,7 @@ impl ServerPingQueue {
(project_id, exp::minecraft::JavaServerPing {
when: Utc::now(),
- address: address.to_string(),
- port,
+ address,
data: result.ok(),
})
};
@@ -108,7 +106,6 @@ impl ServerPingQueue {
/ 100_000,
project_id: project_id.0,
address: ping.address.clone(),
- port: ping.port,
latency_ms: data.map(|d| d.latency.as_millis() as u32),
description: data.map(|d| d.description.clone()),
version_name: data.map(|d| d.version_name.clone()),
@@ -251,7 +248,6 @@ impl ServerPingQueue {
pub async fn ping_server(
address: &str,
- port: u16,
timeout: Option,
) -> eyre::Result {
let start = Instant::now();
@@ -260,97 +256,45 @@ pub async fn ping_server(
.map(|duration| duration.min(default_duration))
.unwrap_or(default_duration);
- let task_ep = async move {
- fn map_component(c: elytra_ping::parse::TextComponent) -> String {
- match c {
- elytra_ping::parse::TextComponent::Plain(t) => t,
- elytra_ping::parse::TextComponent::Fancy(t) => {
- t.text.unwrap_or_default()
- }
- elytra_ping::parse::TextComponent::Extra(e) => e
- .into_iter()
- .map(map_component)
- .collect::>()
- .join(""),
- }
+ let (address, port) = match address.rsplit_once(':') {
+ Some((addr, port)) => {
+ let port = port.parse::().wrap_err("invalid port number")?;
+ (addr, port)
}
+ None => (address, 25565),
+ };
- let (result, latency) =
- elytra_ping::ping_or_timeout((address.to_string(), port), timeout)
- .await?;
+ let task = async move {
+ let conn = async_minecraft_ping::ConnectionConfig::build(address)
+ .with_port(port)
+ .with_srv_lookup()
+ .connect()
+ .await
+ .wrap_err("failed to connect to server")?;
+
+ let status = conn
+ .status()
+ .await
+ .wrap_err("failed to get server status")?
+ .status;
eyre::Ok(exp::minecraft::JavaServerPingData {
- latency,
- version_name: result
- .version
- .as_ref()
- .map(|v| v.name.to_string())
- .unwrap_or_default(),
- version_protocol: result
- .version
- .as_ref()
- .map(|v| v.protocol.cast_unsigned())
- .unwrap_or_default(),
- description: map_component(result.description),
- players_online: result
- .players
- .as_ref()
- .map(|p| p.online)
- .unwrap_or(0),
- players_max: result.players.as_ref().map(|p| p.max).unwrap_or(0),
+ latency: start.elapsed(),
+ version_name: status.version.name,
+ version_protocol: status.version.protocol,
+ description: match status.description {
+ ServerDescription::Plain(text)
+ | ServerDescription::Object { text } => text,
+ },
+ players_online: status.players.online,
+ players_max: status.players.max,
})
};
- let task_amp = async move {
- let task = async move {
- let conn = async_minecraft_ping::ConnectionConfig::build(address)
- .with_port(port)
- .connect()
- .await
- .wrap_err("failed to connect to server")?;
-
- let status = conn
- .status()
- .await
- .wrap_err("failed to get server status")?
- .status;
-
- eyre::Ok(exp::minecraft::JavaServerPingData {
- latency: start.elapsed(),
- version_name: status.version.name,
- version_protocol: status.version.protocol,
- description: match status.description {
- ServerDescription::Plain(text)
- | ServerDescription::Object { text } => text,
- },
- players_online: status.players.online,
- players_max: status.players.max,
- })
- };
-
- tokio::time::timeout(timeout, task)
- .await
- .map_err(eyre::Error::new)
- .flatten()
- };
-
- async move {
- let (result_ep, result_amp) = (task_ep.await, task_amp.await);
-
- let result_ep = result_ep
- .inspect(|_| debug!("Successful ping with `elytra_ping`"))
- .inspect_err(|err| {
- debug!("Failed to ping with `elytra_ping`: {err:#}")
- });
- let result_amp = result_amp
- .inspect(|_| debug!("Successful ping with `async_minecraft_ping`"))
- .inspect_err(|err| {
- debug!("Failed to ping with `async_minecraft_ping`: {err:#}")
- });
-
- result_ep.or(result_amp)
- }
- .await
+ tokio::time::timeout(timeout, task)
+ .await
+ .map_err(eyre::Error::new)
+ .flatten()
}
#[derive(Debug, Row, Serialize, Clone)]
@@ -358,7 +302,6 @@ struct ServerPingRecord {
recorded: i64,
project_id: u64,
address: String,
- port: u16,
latency_ms: Option,
description: Option,
version_name: Option,
@@ -373,19 +316,22 @@ mod tests {
#[actix_rt::test]
async fn test_ping_server_success() {
- let _status = ping_server("mc.hypixel.net", 25565, None).await.unwrap();
+ let _status = ping_server("mc.hypixel.net", None).await.unwrap();
+ }
+
+ #[actix_rt::test]
+ async fn test_follow_srv_record() {
+ _ = ping_server("hypixel.net", None).await.unwrap();
}
#[actix_rt::test]
async fn test_ping_server_invalid_address() {
- _ = ping_server("invalid.invalid", 25565, None)
- .await
- .unwrap_err();
+ _ = ping_server("invalid.invalid", None).await.unwrap_err();
}
#[actix_rt::test]
async fn test_ping_zero_timeout() {
- _ = ping_server("hypixel.net", 25565, Some(Duration::ZERO))
+ _ = ping_server("mc.hypixel.net", Some(Duration::ZERO))
.await
.unwrap_err();
}
diff --git a/apps/labrinth/src/routes/internal/server_ping.rs b/apps/labrinth/src/routes/internal/server_ping.rs
index 423cfc534..6f2d7e147 100644
--- a/apps/labrinth/src/routes/internal/server_ping.rs
+++ b/apps/labrinth/src/routes/internal/server_ping.rs
@@ -19,7 +19,6 @@ pub fn config(cfg: &mut utoipa_actix_web::service_config::ServiceConfig) {
#[derive(Debug, Clone, Serialize, Deserialize, utoipa::ToSchema)]
pub struct PingRequest {
pub address: String,
- pub port: u16,
pub timeout_ms: Option,
}
@@ -42,7 +41,7 @@ pub async fn ping_minecraft_java(
.await?;
let timeout = request.timeout_ms.map(Duration::from_millis);
- server_ping::ping_server(&request.address, request.port, timeout)
+ server_ping::ping_server(&request.address, timeout)
.await
.wrap_request_err("failed to ping server")?;
diff --git a/apps/labrinth/src/search/indexing/mod.rs b/apps/labrinth/src/search/indexing/mod.rs
index 614ef6b2f..85e506088 100644
--- a/apps/labrinth/src/search/indexing/mod.rs
+++ b/apps/labrinth/src/search/indexing/mod.rs
@@ -646,6 +646,7 @@ const DEFAULT_ATTRIBUTES_FOR_FACETING: &[&str] = &[
"minecraft_java_server.content.supported_game_versions",
"minecraft_java_server.content.recommended_game_version",
"minecraft_java_server.verified_plays_2w",
+ "minecraft_java_server.ping.data",
"minecraft_java_server.ping.data.players_online",
];
diff --git a/apps/labrinth/src/search/mod.rs b/apps/labrinth/src/search/mod.rs
index f45df7096..4763b3f91 100644
--- a/apps/labrinth/src/search/mod.rs
+++ b/apps/labrinth/src/search/mod.rs
@@ -274,9 +274,9 @@ pub fn get_sort_index(
"relevance" => (
projects_name,
&[
- "downloads:desc",
"minecraft_java_server.verified_plays_2w:desc",
"minecraft_java_server.ping.data.players_online:desc",
+ "downloads:desc",
],
),
"downloads" => (projects_filtered_name, &["downloads:desc"]),
diff --git a/packages/api-client/src/modules/labrinth/types.ts b/packages/api-client/src/modules/labrinth/types.ts
index 498b78d24..f3ecab2d6 100644
--- a/packages/api-client/src/modules/labrinth/types.ts
+++ b/packages/api-client/src/modules/labrinth/types.ts
@@ -408,9 +408,13 @@ export namespace Labrinth {
export interface MinecraftServer {
max_players?: number
- country?: string
+ region?: string
active_version?: string | null
languages?: string[]
+ /**
+ * deprecated, use region instead
+ */
+ country?: string
}
export interface ModpackContent {
@@ -428,7 +432,6 @@ export namespace Labrinth {
export interface MinecraftJavaServer {
address?: string
- port?: number
content?: ModpackContent | VanillaContent
verified_plays_4w?: number | null
verified_plays_2w?: number | null
@@ -437,7 +440,6 @@ export namespace Labrinth {
export interface MinecraftBedrockServer {
address?: string
- port?: number
}
export interface CreateServerProjectRequest {
@@ -817,7 +819,7 @@ export namespace Labrinth {
export namespace Internal {
export type MinecraftJavaPingRequest = {
address: string
- port: number
+ timeout_ms?: number
}
}
}
diff --git a/packages/moderation/src/data/nags/server-projects.ts b/packages/moderation/src/data/nags/server-projects.ts
index b95e4e5b9..caf092fca 100644
--- a/packages/moderation/src/data/nags/server-projects.ts
+++ b/packages/moderation/src/data/nags/server-projects.ts
@@ -14,7 +14,7 @@ export const serverProjectsNags: Nag[] = [
}),
status: 'required',
shouldShow: (context: NagContext) =>
- !!context.projectV3?.minecraft_server && !context.projectV3?.minecraft_server.country,
+ !!context.projectV3?.minecraft_server && !context.projectV3?.minecraft_server.region,
link: {
path: 'settings/server',
title: defineMessage({
diff --git a/packages/ui/src/components/project/ProjectSidebarServerInfo.vue b/packages/ui/src/components/project/ProjectSidebarServerInfo.vue
index 206b6279f..a9f841ad3 100644
--- a/packages/ui/src/components/project/ProjectSidebarServerInfo.vue
+++ b/packages/ui/src/components/project/ProjectSidebarServerInfo.vue
@@ -55,10 +55,10 @@
-
- Country
+
@@ -120,7 +120,7 @@ const props = withDefaults(defineProps(), {
const ipAddress = computed(() => props.projectV3?.minecraft_java_server?.address ?? '')
const languages = computed(() => props.projectV3?.minecraft_server?.languages ?? [])
-const country = computed(() => props.projectV3?.minecraft_server?.country)
+const region = computed(() => props.projectV3?.minecraft_server?.region)
const recommendedVersions = computed(() => {
if (props.recommendedVersion) return [props.recommendedVersion]
diff --git a/packages/ui/src/components/project/card/ProjectCard.vue b/packages/ui/src/components/project/card/ProjectCard.vue
index 2647fa72d..fa42dc40b 100644
--- a/packages/ui/src/components/project/card/ProjectCard.vue
+++ b/packages/ui/src/components/project/card/ProjectCard.vue
@@ -51,7 +51,7 @@
import { computed } from 'vue'
-import { defineMessage, useVIntl } from '../../../composables'
+import { TagItem } from '../../base'
const { region } = defineProps<{
region: string
}>()
-const { formatMessage } = useVIntl()
+const regionNames: Record = {
+ us_east: 'US East',
+ us_west: 'US West',
+ europe: 'Europe',
+ asia: 'Asia',
+ australia: 'Australia',
+ south_america: 'South America',
+ middle_east: 'Middle East',
+ russia: 'Russia',
+}
-const alt = defineMessage({
- id: 'project.server.region.alt',
- defaultMessage: 'Region: {regionCode}',
-})
-
-const regionLower = computed(() => region.toLowerCase())
+const regionName = computed(() => regionNames[region] ?? region)
-
+ {{ regionName }}
diff --git a/packages/ui/src/locales/en-US/index.json b/packages/ui/src/locales/en-US/index.json
index 236d956ce..515442075 100644
--- a/packages/ui/src/locales/en-US/index.json
+++ b/packages/ui/src/locales/en-US/index.json
@@ -992,9 +992,6 @@
"project.server.ping.ms": {
"defaultMessage": "{ping} ms"
},
- "project.server.region.alt": {
- "defaultMessage": "Region: {regionCode}"
- },
"project.settings.analytics.title": {
"defaultMessage": "Analytics"
},
diff --git a/packages/ui/src/utils/server-search.ts b/packages/ui/src/utils/server-search.ts
index 12c5306f9..88ac2d8cd 100644
--- a/packages/ui/src/utils/server-search.ts
+++ b/packages/ui/src/utils/server-search.ts
@@ -55,25 +55,15 @@ const SERVER_CATEGORY_ICON_MAP: Record = {
'world-resets': 'refresh-ccw',
}
-export const SERVER_COUNTRIES = [
- { code: 'US', name: 'United States' },
- { code: 'GB', name: 'United Kingdom' },
- { code: 'DE', name: 'Germany' },
- { code: 'FR', name: 'France' },
- { code: 'NL', name: 'Netherlands' },
- { code: 'PL', name: 'Poland' },
- { code: 'RU', name: 'Russia' },
- { code: 'BR', name: 'Brazil' },
- { code: 'CA', name: 'Canada' },
- { code: 'AU', name: 'Australia' },
- { code: 'SE', name: 'Sweden' },
- { code: 'FI', name: 'Finland' },
- { code: 'SG', name: 'Singapore' },
- { code: 'JP', name: 'Japan' },
- { code: 'KR', name: 'South Korea' },
- { code: 'TR', name: 'Turkey' },
- { code: 'IN', name: 'India' },
- { code: 'ZA', name: 'South Africa' },
+export const SERVER_REGIONS = [
+ { code: 'us_east', name: 'US East' },
+ { code: 'us_west', name: 'US West' },
+ { code: 'europe', name: 'Europe' },
+ { code: 'asia', name: 'Asia' },
+ { code: 'australia', name: 'Australia' },
+ { code: 'south_america', name: 'South America' },
+ { code: 'middle_east', name: 'Middle East' },
+ { code: 'russia', name: 'Russia' },
]
export const SERVER_LANGUAGES = [
@@ -106,7 +96,8 @@ export const SERVER_SORT_TYPES: SortType[] = [
const FILTER_FIELD_MAP: Record = {
server_content_type: 'minecraft_java_server.content.kind',
server_game_version: 'minecraft_java_server.content.supported_game_versions',
- server_country: 'minecraft_server.country',
+ server_status: 'minecraft_java_server.ping.data',
+ server_region: 'minecraft_server.region',
server_language: 'minecraft_server.languages',
}
@@ -128,7 +119,7 @@ export function useServerSearch(opts: {
const route = useRoute()
const serverCurrentSortType = ref(SERVER_SORT_TYPES[0])
- const serverCurrentFilters = ref([])
+ const serverCurrentFilters = ref([{ type: 'server_status', option: 'online' }])
const serverToggledGroups = ref([])
const serverFilterTypes = computed(() => {
@@ -206,18 +197,18 @@ export function useServerSearch(opts: {
})),
},
{
- id: 'server_country',
- formatted_name: 'Country',
+ id: 'server_region',
+ formatted_name: 'Region',
supported_project_types: ['server'],
- display: 'scrollable',
- query_param: 'sco',
+ display: 'all',
+ query_param: 'sr',
supports_negative_filter: true,
- searchable: true,
- options: SERVER_COUNTRIES.map((c) => ({
- id: c.code,
- formatted_name: c.name,
+ searchable: false,
+ options: SERVER_REGIONS.map((r) => ({
+ id: r.code,
+ formatted_name: r.name,
method: 'or' as const,
- value: c.code,
+ value: r.code,
})),
},
{
@@ -235,6 +226,19 @@ export function useServerSearch(opts: {
value: l.code,
})),
},
+ {
+ id: 'server_status',
+ formatted_name: 'Status',
+ supported_project_types: ['server'],
+ display: 'all',
+ query_param: 'sst',
+ supports_negative_filter: false,
+ searchable: false,
+ options: [
+ { id: 'online', formatted_name: 'Online', method: 'or', value: 'online' },
+ { id: 'offline', formatted_name: 'Offline', method: 'or', value: 'offline' },
+ ],
+ },
]
})
@@ -245,6 +249,18 @@ export function useServerSearch(opts: {
const field = getFilterField(filterType.id)
if (!field) continue
const matched = serverCurrentFilters.value.filter((f) => f.type === filterType.id)
+ if (matched.length === 0) continue
+
+ if (filterType.id === 'server_status') {
+ const selected = matched[0]?.option
+ if (selected === 'online') {
+ parts.push(`${field} EXISTS`)
+ } else if (selected === 'offline') {
+ parts.push(`${field} NOT EXISTS`)
+ }
+ continue
+ }
+
const included = matched.filter((f) => !f.negative)
const excluded = matched.filter((f) => f.negative)
if (included.length > 0) {