forked from didirus/AstralRinth
Fix old Minecraft versions not having playtime resolved for servers (#3871)
* Fix old Minecraft versions not having playtime resolved for servers * Revert and clean up get_server_worlds_in_profile a bit * Add a semaphore to resolve_server_address in general to apply to all DNS queries * Remove unused tokio-stream dependency from theseus
This commit is contained in:
@@ -26,6 +26,8 @@ use std::net::{Ipv4Addr, Ipv6Addr};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::LazyLock;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::sync::Semaphore;
|
||||
use tokio::task::JoinSet;
|
||||
use tokio_util::compat::FuturesAsyncWriteCompatExt;
|
||||
use url::Url;
|
||||
|
||||
@@ -394,25 +396,27 @@ async fn get_server_worlds_in_profile(
|
||||
.await
|
||||
.ok();
|
||||
|
||||
let first_server_index = worlds.len();
|
||||
for (index, server) in servers.into_iter().enumerate() {
|
||||
if server.hidden {
|
||||
// TODO: Figure out whether we want to hide or show direct connect servers
|
||||
continue;
|
||||
}
|
||||
let icon = server.icon.and_then(|icon| {
|
||||
Url::parse(&format!("data:image/png;base64,{icon}")).ok()
|
||||
});
|
||||
let last_played = join_log
|
||||
.as_ref()
|
||||
.and_then(|log| {
|
||||
let address = parse_server_address(&server.ip).ok()?;
|
||||
log.get(&(address.0.to_owned(), address.1))
|
||||
})
|
||||
.copied();
|
||||
let world = World {
|
||||
name: server.name,
|
||||
last_played,
|
||||
icon: icon.map(Either::Right),
|
||||
last_played: join_log
|
||||
.as_ref()
|
||||
.and_then(|log| {
|
||||
let (host, port) = parse_server_address(&server.ip).ok()?;
|
||||
log.get(&(host.to_owned(), port))
|
||||
})
|
||||
.copied(),
|
||||
icon: server
|
||||
.icon
|
||||
.and_then(|icon| {
|
||||
Url::parse(&format!("data:image/png;base64,{icon}")).ok()
|
||||
})
|
||||
.map(Either::Right),
|
||||
display_status: DisplayStatus::Normal,
|
||||
details: WorldDetails::Server {
|
||||
index,
|
||||
@@ -423,6 +427,30 @@ async fn get_server_worlds_in_profile(
|
||||
worlds.push(world);
|
||||
}
|
||||
|
||||
if let Some(join_log) = join_log {
|
||||
let mut futures = JoinSet::new();
|
||||
for (index, world) in worlds.iter().enumerate().skip(first_server_index)
|
||||
{
|
||||
if world.last_played.is_some() {
|
||||
continue;
|
||||
}
|
||||
if let WorldDetails::Server { address, .. } = &world.details
|
||||
&& let Ok((host, port)) = parse_server_address(address)
|
||||
{
|
||||
let host = host.to_owned();
|
||||
futures.spawn(async move {
|
||||
resolve_server_address(&host, port)
|
||||
.await
|
||||
.ok()
|
||||
.map(|x| (index, x))
|
||||
});
|
||||
}
|
||||
}
|
||||
for (index, address) in futures.join_all().await.into_iter().flatten() {
|
||||
worlds[index].last_played = join_log.get(&address).copied();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -943,9 +971,13 @@ async fn resolve_server_address(
|
||||
host: &str,
|
||||
port: u16,
|
||||
) -> Result<(String, u16)> {
|
||||
static SIMULTANEOUS_DNS_QUERIES: Semaphore = Semaphore::const_new(24);
|
||||
|
||||
if host.parse::<Ipv4Addr>().is_ok() || host.parse::<Ipv6Addr>().is_ok() {
|
||||
return Ok((host.to_owned(), port));
|
||||
}
|
||||
|
||||
let _permit = SIMULTANEOUS_DNS_QUERIES.acquire().await?;
|
||||
let resolver = hickory_resolver::TokioResolver::builder_tokio()?.build();
|
||||
Ok(
|
||||
match resolver.srv_lookup(format!("_minecraft._tcp.{host}")).await {
|
||||
|
||||
Reference in New Issue
Block a user