Исправлена корректная загрузка локализации при обновлении игры.
Исправлено уведомление ошибки, о несуществующей ошибке.
Переехали на новый сервер, скорость скачивания через "Прокси" должна работать у всех и в несколько раз быстрее.
Стабильная версия лаунчера 1.4.7 вышла из стадии бета-тестирования.
• Добавлена 4-я цифра для критических патчей.
• Переработана вся система работы с путями.
• Обнаружена критическая ошибка в игре, при работе с путями. Интегрировали свою уникальную систему виртуализации в лаунчер, при её активации - игра будет гарантированно работать, игнорируя проблемные пути и символы. (Удачи другим лаунчерам сделать подобное 😆)
• Добавлена виртуализация для запуска локального сервера.
• Исправлено...
понял спасибо@TixTodi, извини, я не в той теме ответил. Да, жди пожалуйста онлайнфикса. Скоро всё будет работать. Поддержка лаунчера тут: HytaleNet Launcher Support
• Переписана вся логика лаунчера, исправлены все старые проблемы с установкой, скачиванием и запуском.
• Ускорена работа скачивания, функция докачивания файлов при проблемах.
• Ускорена работа патчей (снова).
• Ускорена проверка ресурсов игры при запуске.Исправлены все проблемы с русификацией.
• Добавили кнопку "Исправить клиент" в настройки, если игра сломалась.
• Наш новый надёжный патч, теперь не обязательно обновлять лаунчер при выходе новой версии игры.
• Изменили дизайн, сделали его...
#[cfg(windows)]
use std::ffi::OsStr;
#[cfg(windows)]
use std::os::windows::ffi::OsStrExt;
#[cfg(windows)]
use std::ptr;
#[cfg(windows)]
use winapi::um::fileapi::GetLogicalDrives;
#[cfg(windows)]
use winapi::shared::minwindef::DWORD;
#[cfg(windows)]
use winapi::um::winnt::LPCWSTR;
#[cfg(windows)]
extern "system" {
fn DefineDosDeviceW(
dwFlags: DWORD,
lpDeviceName: LPCWSTR,
lpTargetPath: LPCWSTR,
) -> i32;
}
#[cfg(windows)]
const DDD_REMOVE_DEFINITION: u32 = 0x00000002;
#[cfg(windows)]
pub fn find_available_drive_letter() -> Result<char, String> {
let drives = unsafe { GetLogicalDrives() };
let mut occupied = Vec::new();
for i in 0..26 {
let bit = 1 << i;
if (drives & bit) != 0 {
let letter = (b'A' + i as u8) as char;
occupied.push(letter);
}
}
eprintln!("[VIRTUALIZATION] Occupied drive letters: {:?}", occupied);
let preferred = ['Z', 'Y', 'X', 'W', 'V', 'U', 'T', 'S', 'R', 'Q', 'P', 'O', 'N', 'M', 'L', 'K', 'J', 'I', 'H', 'G', 'F', 'E', 'D'];
for &letter in preferred.iter() {
let bit = 1 << (letter as u8 - b'A');
if (drives & bit) == 0 {
eprintln!("[VIRTUALIZATION] Found available drive letter: {}", letter);
return Ok(letter);
}
}
Err("Нет свободных букв дисков. Отключите ненужные диски (сетевые, USB, виртуальные) в Проводнике и попробуйте снова.".to_string())
}
#[cfg(not(windows))]
pub fn find_available_drive_letter() -> Result<char, String> {
Err("Path virtualization is only available on Windows".to_string())
}
#[cfg(windows)]
fn to_wide_string(s: &str) -> Vec<u16> {
OsStr::new(s)
.encode_wide()
.chain(Some(0))
.collect()
}
#[cfg(windows)]
pub fn create_virtual_drive(drive_letter: char, target_path: &str) -> Result<(), String> {
use std::path::Path;
let drive_str = format!("{}:", drive_letter);
let drive_wide = to_wide_string(&drive_str);
let target_wide = to_wide_string(target_path);
eprintln!("[VIRTUALIZATION] Creating virtual drive {} -> {}", drive_str, target_path);
let target_path_obj = Path::new(target_path);
if !target_path_obj.exists() {
eprintln!("[VIRTUALIZATION] ERROR: Target path does not exist: {}", target_path);
return Err(format!("Target path does not exist: {}", target_path));
}
if !target_path_obj.is_dir() {
eprintln!("[VIRTUALIZATION] ERROR: Target path is not a directory: {}", target_path);
return Err(format!("Target path is not a directory: {}", target_path));
}
eprintln!("[VIRTUALIZATION] Target path validated, calling DefineDosDeviceW...");
let result = unsafe {
DefineDosDeviceW(
0,
drive_wide.as_ptr(),
target_wide.as_ptr(),
)
};
if result == 0 {
let error = unsafe { winapi::um::errhandlingapi::GetLastError() };
eprintln!("[VIRTUALIZATION] DefineDosDeviceW failed with error code: {}", error);
eprintln!("[VIRTUALIZATION] Drive: {}, Target: {}", drive_str, target_path);
eprintln!("[VIRTUALIZATION] Target path exists: {}, is_dir: {}", target_path_obj.exists(), target_path_obj.is_dir());
return Err(format!("Failed to create virtual drive: Windows error {} (check if path is valid and drive letter free)", error));
}
eprintln!("[VIRTUALIZATION] Virtual drive {} created successfully", drive_str);
Ok(())
}
#[cfg(not(windows))]
pub fn create_virtual_drive(_drive_letter: char, _target_path: &str) -> Result<(), String> {
Err("Path virtualization is only available on Windows".to_string())
}
#[cfg(windows)]
pub fn remove_virtual_drive(drive_letter: char) -> Result<(), String> {
let drive_str = format!("{}:", drive_letter);
let drive_wide = to_wide_string(&drive_str);
eprintln!("[VIRTUALIZATION] Removing virtual drive {}", drive_str);
let result = unsafe {
DefineDosDeviceW(
DDD_REMOVE_DEFINITION,
drive_wide.as_ptr(),
ptr::null(),
)
};
if result == 0 {
let error = unsafe { winapi::um::errhandlingapi::GetLastError() };
return Err(format!("Failed to remove virtual drive: Windows error {}", error));
}
eprintln!("[VIRTUALIZATION] Virtual drive {} removed successfully", drive_str);
Ok(())
}
#[cfg(not(windows))]
pub fn remove_virtual_drive(_drive_letter: char) -> Result<(), String> {
Err("Path virtualization is only available on Windows".to_string())
}
pub fn get_virtual_path(drive_letter: char, relative_path: &str) -> String {
if relative_path.is_empty() {
format!("{}:\\", drive_letter)
} else {
let normalized = relative_path.trim_start_matches('\\').trim_start_matches('/');
format!("{}:\\{}", drive_letter, normalized.replace('/', "\\"))
}
}#[tauri::command]
#[cfg(windows)]
async fn setup_path_virtualization(target_path: String) -> Result<String, String> {
use crate::virtualization;
use crate::config::Config;
eprintln!("[VIRTUALIZATION] setup_path_virtualization called with target_path: {}", target_path);
let drive_letter = virtualization::find_available_drive_letter().map_err(|e| {
eprintln!("[VIRTUALIZATION] ERROR: {}", e);
e
})?;
eprintln!("[VIRTUALIZATION] Found available drive letter: {}", drive_letter);
virtualization::create_virtual_drive(drive_letter, &target_path).map_err(|e| {
eprintln!("[VIRTUALIZATION] ERROR in create_virtual_drive: {}", e);
e
})?;
eprintln!("[VIRTUALIZATION] Loading config to save virtualization settings...");
let mut config = Config::load().await.map_err(|e| {
eprintln!("[VIRTUALIZATION] ERROR loading config: {}", e);
format!("Failed to load config: {}", e)
})?;
config.path_virtualization_enabled = true;
config.virtual_drive_letter = Some(format!("{}", drive_letter));
config.virtual_drive_target = Some(target_path.clone());
eprintln!("[VIRTUALIZATION] Saving config with virtualization enabled...");
config.save().await.map_err(|e| {
eprintln!("[VIRTUALIZATION] ERROR saving config: {}", e);
format!("Failed to save config: {}", e)
})?;
eprintln!("[VIRTUALIZATION] setup_path_virtualization completed successfully, drive: {}:", drive_letter);
Ok(format!("{}:", drive_letter))
}По вашим просьбам, вернули вам выбор старых релизов игры.
Исправили редкую ошибку создания портативной версии, напоминаем что её создать можно вручную, прописав в названии лаунчера слово "portable".
• Исправлено множество редких ошибок во время обновления игры.
• Исправлена неправильная логика IO патчинга игры, процесс ускорен.
• Исправлена ошибка сохранения версии при обновлениях, заменены индексы на их названия.
• Исправлена ошибка, когда лончер мог скачать битый файл со смещением.
• Исправлено множество внутренних исключений в работе с файлами.
• Исправлено зависание интерфейса при работе с большими файлами.
• Ускорены все проверки клиента игры, сильно ускорен её запуск.
• Переписана...
• Добавлены флаги запуска локального сервера, автоматический пресет настроек.
• Перенесена папка всех данных сервера в%appdata%\HLauncher\ServerDataдля безопасного хранения миров и данных локального сервера.
• Исправлена установка игры, если путь файлов сверх пределов длинный.
• Исправлено отображение выбранной версии в углу.
• Исправлено отображение иконки и цвета текста на отключенных кнопках.
1.5.4:
• Система аккаунтов
• Исправление ошибки 403
• Изменен сервер скачивания
• Добавлена новая система обработки скинов в Hytale
• Множество маленьких улучшений1.5.7:
• Исправлено растягивание картинки в Splash Screen
• Уменьшен вес лаунчера на ~0.6 мб
• Другие улучшения.... о которых мы забыли
Новый дизайн и кастомизация.
Новый патч под новые версии игры.
Новый производительный локальный сервер.
Учли пожелания наших пользователей, добавили красивые темы на выбор, сильно освежили весь дизайн лаунчера.
Нормальная локализация.
Проект почищен, удалены мусорные библиотеки и файлы.
Множество маленьких исправлений для Windows 10.
Исправлены проблемы с масштабированием в Windows 11.
Тысячи мелких правок и исправлений незначительных внутренних ошибок в угоду оптимизации.
Исправлена...
Мелкие улучшения
Исправлена редкая ошибка отрисовки компонентов GDI+
Исправлено наслоение уведомлений и их высота.
Исправлена смена языка в Changelog.
Исправлены некоторые кривые скругления.
Исправлены мелкие утечки памяти и ресурсов.
Исправлена редкая ошибка, когда лаунчер открывался свёрнутым.
Добавлено начальное обучение для новых пользователей.
Добавлена локализация, где она отсутствовала.
Добавлена параллельная загрузка файлов.
Добавлена генерация ников по стандарту.
Добавлена возможность...