Пользователь
- Регистрация
- 11 Май 2025
- Сообщения
- 10
- Автор темы
- #1
Структура проекта ( Maven )
src/├── main/
│ ├── java/com/crmp/launcher/
│ │ ├── core/
│ │ │ ├── AuthManager.java # Аутентификация
│ │ │ ├── UpdateEngine.java # Система обновлений
│ │ │ ├── SecurityModule.java # Античит и шифрование
│ │ │ └── ServerBrowser.java # Список серверов
│ │ ├── gui/
│ │ │ ├── MainWindow.java # Основное окно
│ │ │ ├── LoginController.java # Форма входа
│ │ │ └── Animations.java # Анимации JavaFX
│ │ └── LauncherMain.java # Точка входа
│ └── resources/ # Шрифы, стили, иконки
└── test/ # Юнит-тест
Код основных модулей, шифрование трафика
import javax.crypto.Cipher;import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Base64;
public class SecurityModule {
private static final String ALGORITHM = "AES";
private static final byte[] KEY = "MySuperSecretKey".getBytes();
public static String encrypt(String data) throws Exception {
Key key = new SecretKeySpec(KEY, ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] encrypted = cipher.doFinal(data.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
}
public static String decrypt(String encryptedData) throws Exception {
Key key = new SecretKeySpec(KEY, ALGORITHM);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, key);
byte[] decoded = Base64.getDecoder().decode(encryptedData);
byte[] decrypted = cipher.doFinal(decoded);
return new String(decrypted);
}
}
Система обновлений
import org.apache.http.client.methods.HttpGet;import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.security.MessageDigest;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class UpdateEngine {
private static final String MANIFEST_URL = "https://api.crmp.mobi/launcher/manifest";
public CompletableFuture<Boolean> checkUpdates() {
return CompletableFuture.supplyAsync(() -> {
try (CloseableHttpClient client = HttpClients.createDefault()) {
HttpGet request = new HttpGet(MANIFEST_URL);
String manifestJson = client.execute(request, response ->
new BufferedReader(new InputStreamReader(response.getEntity().getContent()))
.lines().collect(Collectors.joining("\n")));
List<FileMetadata> remoteFiles = parseManifest(manifestJson);
return remoteFiles.stream().anyMatch(remote ->
!Files.exists(Paths.get(remote.path)) ||
!checksumMatch(remote.path, remote.hash));
} catch (Exception e) {
throw new RuntimeException("Update check failed", e);
}
});
}
private boolean checksumMatch(String path, String expectedHash) {
try (InputStream is = Files.newInputStream(Paths.get(path))) {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] buffer = new byte[8192];
int read;
while ((read = is.read(buffer)) != -1) {
md.update(buffer, 0, read);
}
byte[] hash = md.digest();
return bytesToHex(hash).equals(expectedHash);
} catch (Exception e) {
return false;
}
}
}
Античит-Модуль
import java.nio.file.Files;import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
public class AntiCheat {
private static final List<String> BANNED_SIGNATURES = Arrays.asList(
"4D5A900003000000", // Сигнатура .exe
"CEFAEDFE0C000000" // Сигнатура Mach-O
);
public static boolean scanGameFiles() {
try {
Files.walk(Paths.get("game_files"))
.filter(Files::isRegularFile)
.forEach(path -> {
byte[] data = Files.readAllBytes(path);
String hex = bytesToHex(data);
if (BANNED_SIGNATURES.stream().anyMatch(hex::contains)) {
throw new RuntimeException("Обнаружен запрещенный файл: " + path);
}
});
return true;
} catch (Exception e) {
return false;
}
}
}
GUI на JAVAFX
import javafx.application.Application;import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;
public class MainWindow extends Application {
@Override
public void start(Stage primaryStage) {
StackPane root = new StackPane();
ProgressBar progressBar = new ProgressBar();
root.getChildren().add(progressBar);
Scene scene = new Scene(root, 800, 600);
scene.getStylesheets().add("styles.css");
primaryStage.setTitle("CRMP Mobile Launcher");
primaryStage.setScene(scene);
primaryStage.show();
// Запуск проверки обновлений
UpdateEngine updateEngine = new UpdateEngine();
updateEngine.checkUpdates().thenAccept(hasUpdates -> {
if (hasUpdates) {
showUpdateScreen();
} else {
showLoginScreen();
}
});
}
private void showUpdateScreen() { /* ... */ }
private void showLoginScreen() { /* ... */ }
}
Запуск лаунчера
mvn clean javafx:runТРЕБОВАНИЕ
Java 17+ ( с модулями JPMS )2. Зависимость от Maven
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>17</version>
</dependency>
</dependencies>