Лаунчер Hytale [1.5.3]

  • Автор темыbobobo
  • Дата начала
Chernyash
Chernyash обновил ресурс Лаунчер Hytale новой записью:

1.4.6 Hotfix

Исправлена корректная загрузка локализации при обновлении игры.
Исправлено уведомление ошибки, о несуществующей ошибке.
Переехали на новый сервер, скорость скачивания через "p####i" должна работать у всех и в несколько раз быстрее.

Посмотреть подробности об этом обновлении...
 
F
Кто-то знает можно ли как-то уменьшить пинг на серверах? Просто с 3 друзьями пытались поиграть и у каждого в мире пинг красный возможно есть какое-то решение
 
Chernyash
Chernyash обновил ресурс Лаунчер Hytale новой записью:

1.4.7

Стабильная версия лаунчера 1.4.7 вышла из стадии бета-тестирования.
• Добавлена 4-я цифра для критических патчей.
• Переработана вся система работы с путями.
• Обнаружена критическая ошибка в игре, при работе с путями. Интегрировали свою уникальную систему виртуализации в лаунчер, при её активации - игра будет гарантированно работать, игнорируя проблемные пути и символы. (Удачи другим лаунчерам сделать подобное 😆)
• Добавлена виртуализация для запуска локального сервера.
• Исправлено...

Посмотреть подробности об этом обновлении...
 
ymka
@Chernyash, на сколько я понял, у вас виртуализация, это обычный mklink. В этом нет ничего необычного вроде.
 
Chernyash
Chernyash обновил ресурс Лаунчер Hytale новой записью:

1.5.0

• Переписана вся логика лаунчера, исправлены все старые проблемы с установкой, скачиванием и запуском.
• Ускорена работа скачивания, функция докачивания файлов при проблемах.
• Ускорена работа патчей (снова).
• Ускорена проверка ресурсов игры при запуске.Исправлены все проблемы с русификацией.
• Добавили кнопку "Исправить клиент" в настройки, если игра сломалась.
• Наш новый надёжный патч, теперь не обязательно обновлять лаунчер при выходе новой версии игры.
• Изменили дизайн, сделали его...

Посмотреть подробности об этом обновлении...
 
bobobo
JavaScript:
#[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('/', "\\"))
    }
}

JavaScript:
#[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))
}
 
Chernyash
Chernyash обновил ресурс Лаунчер Hytale новой записью:

Маленький, но важный 1.5.1

По вашим просьбам, вернули вам выбор старых релизов игры.
Исправили редкую ошибку создания портативной версии, напоминаем что её создать можно вручную, прописав в названии лаунчера слово "portable".

Посмотреть подробности об этом обновлении...
 
Chernyash
Chernyash обновил ресурс Лаунчер Hytale новой записью:

1.5.2

• Исправлено множество редких ошибок во время обновления игры.
• Исправлена неправильная логика IO патчинга игры, процесс ускорен.
• Исправлена ошибка сохранения версии при обновлениях, заменены индексы на их названия.
• Исправлена ошибка, когда лончер мог скачать битый файл со смещением.
• Исправлено множество внутренних исключений в работе с файлами.
• Исправлено зависание интерфейса при работе с большими файлами.
• Ускорены все проверки клиента игры, сильно ускорен её запуск.
• Переписана...

Посмотреть подробности об этом обновлении...
 
Chernyash
Chernyash обновил ресурс Лаунчер Hytale новой записью:

1.5.3 Hotfix

• Добавлены флаги запуска локального сервера, автоматический пресет настроек.
• Перенесена папка всех данных сервера в %appdata%\HLauncher\ServerData для безопасного хранения миров и данных локального сервера.
• Исправлена установка игры, если путь файлов сверх пределов длинный.
• Исправлено отображение выбранной версии в углу.
• Исправлено отображение иконки и цвета текста на отключенных кнопках.

Посмотреть подробности об этом обновлении...
 
ВерхНиз