Newer
Older
KeeperJerry_Launcher / Launcher / runtime / dialog / dialog.js
// Dialog nodes
var rootPane, news, authPane, dimPane;
var loginField, passwordField, savePasswordBox, profilesBox;
var movePoint = null; // Point2D

// State variables
var pingers = {};

function initDialog() {
	// Lookup news WebView
	news = rootPane.lookup("#news");
	var newsEngine = news.getEngine();
	newsEngine.setUserDataDirectory(dir.resolve("webview").toFile());
	newsEngine.load(config.newsURL);

	// Lookup auth pane and dim
	initAuthPane(rootPane.lookup("#authPane"));
	dimPane = rootPane.lookup("#dim");
	
	// Init overlays
	debug.initOverlay();
	processing.initOverlay();
	settings.initOverlay();
	update.initOverlay();

	// Verify launcher & make request
	verifyLauncher();
}

function initAuthPane(pane) {
	authPane = pane;
	
	// Lookup login field
	loginField = pane.lookup("#login");
	loginField.setOnAction(goAuth);
	if (settings.login !== null) {
		loginField.setText(settings.login);
	}

	// Lookup password field
	passwordField = pane.lookup("#password");
	passwordField.setOnAction(goAuth);
	if (settings.rsaPassword !== null) {
		passwordField.getStyleClass().add("hasSaved");
		passwordField.setPromptText("*** Сохранённый ***");
	}

	// Lookup profiles combobox
	profilesBox = pane.lookup("#profiles");
	profilesBox.setCellFactory(newProfileCell);
	profilesBox.setButtonCell(newProfileCell(null));

	// Lookup save password box
	savePasswordBox = pane.lookup("#savePassword");
	savePasswordBox.setSelected(settings.login === null || settings.rsaPassword !== null);
	
	// Lookup hyperlink text and actions
	var link = pane.lookup("#link");
	link.setText(config.linkText);
	link.setOnAction(function(event) app.getHostServices().showDocument(config.linkURL.toURI()));

	// Lookup action buttons
	pane.lookup("#goAuth").setOnAction(goAuth);
	pane.lookup("#goSettings").setOnAction(goSettings);
}

function initOffline() {
	// Update title
	stage.setTitle(config.title + " [Offline]");
	
	// Set login field as username field
	loginField.setPromptText("Имя пользователя");
	if (!VerifyHelper.isValidUsername(settings.login)) {
		loginField.setText(""); // Reset if not valid
	}
	
	// Disable password field
	passwordField.setDisable(true);
	passwordField.setPromptText("Недоступно");
	passwordField.setText("");
	
	// Switch news view to offline page
	var offlineURL = Launcher.getResourceURL("dialog/offline/offline.html");
	news.getEngine().load(offlineURL.toString());
}

/* ======== Handler functions ======== */
function goAuth(event) {
	// Verify there's no other overlays
	if (overlay.current !== null) {
		return;
	}

	// Get profile
	var profile = profilesBox.getSelectionModel().getSelectedItem();
	if (profile === null) {
		return; // No profile selected
	}

	// Get login
	var login = loginField.getText();
	if (login.isEmpty()) {
		return; // Maybe throw exception?)
	}

	// Get password if online-mode
	var rsaPassword = null;
	if (!passwordField.isDisable()) {
		var password = passwordField.getText();
		if (!password.isEmpty()) {
			rsaPassword = settings.setPassword(password);
		} else if (settings.rsaPassword !== null) {
			rsaPassword = settings.rsaPassword;
		} else {
			return; // No password - no auth, sorry :C
		}

		// Remember or reset password
		settings.rsaPassword = savePasswordBox.isSelected() ? rsaPassword : null;
	}

	// Show auth overlay
	settings.login = login;
	doAuth(profile, login, rsaPassword);
}

function goSettings(event) {
	// Verify there's no other overlays
	if (overlay.current !== null) {
		return;
	}

	// Show settings overlay
	overlay.show(settings.overlay, null);
}

/* ======== Processing functions ======== */
function verifyLauncher(e) {
	processing.resetOverlay();
	overlay.show(processing.overlay, function(event) makeLauncherRequest(function(result) {
		settings.lastSign = result.sign;
		settings.lastProfiles = result.profiles;
		
		// Init offline if set
		if (settings.offline) {
			initOffline();
		}

		// Update profiles list and hide overlay
		updateProfilesList(result.profiles);
		overlay.hide(0, function() {
			if (cliParams.autoLogin) {
				goAuth(null);
			}
		});
	}));
}

function doAuth(profile, login, rsaPassword) {
	processing.resetOverlay();
	overlay.show(processing.overlay, function(event) makeAuthRequest(login, rsaPassword, function(result)
		doUpdate(profile, result.pp, result.accessToken)
	));
}

function doUpdate(profile, pp, accessToken) {
	update.resetOverlay("Обновление файлов JVM");
	overlay.swap(0, update.overlay, function(event) {
		var jvmDir = settings.updatesDir.resolve(jvmDirName);
		makeUpdateRequest(jvmDirName, jvmDir, null, function(jvmHDir) {
			settings.lastHDirs.put(jvmDirName, jvmHDir);
			
			// Update asset dir
			update.resetOverlay("Обновление файлов ресурсов");
			var assetDirName = profile.object.block.getEntryValue("assetDir", StringConfigEntryClass);
			var assetDir = settings.updatesDir.resolve(assetDirName);
			var assetMatcher = profile.object.getAssetUpdateMatcher();
			makeUpdateRequest(assetDirName, assetDir, assetMatcher, function(assetHDir) {
				settings.lastHDirs.put(assetDirName, assetHDir);
				
				// Update client dir
				update.resetOverlay("Обновление файлов клиента");
				var clientDirName = profile.object.block.getEntryValue("dir", StringConfigEntryClass);
				var clientDir = settings.updatesDir.resolve(clientDirName);
				var clientMatcher = profile.object.getClientUpdateMatcher();
				makeUpdateRequest(clientDirName, clientDir, clientMatcher, function(clientHDir) {
					settings.lastHDirs.put(clientDirName, clientHDir);
					doLaunchClient(jvmDir, jvmHDir, assetDir, assetHDir, clientDir, clientHDir, profile, pp, accessToken);
				});
			});
		});
	});
}

function doLaunchClient(jvmDir, jvmHDir, assetDir, assetHDir, clientDir, clientHDir, profile, pp, accessToken) {
	processing.resetOverlay();
	overlay.swap(0, processing.overlay, function(event)
		launchClient(jvmDir, jvmHDir, assetHDir, clientHDir, profile, new ClientLauncherParams(settings.lastSign,
			assetDir, clientDir, pp, accessToken, settings.autoEnter, settings.fullScreen, settings.ram, 0, 0), doDebugClient)
	);
}

function doDebugClient(process) {
	if (!LogHelper.isDebugEnabled()) {
		javafx.application.Platform.exit();
		return;
	}
	
	// Switch to debug overlay
	debug.resetOverlay();
	overlay.swap(0, debug.overlay, function(event) debugProcess(process));
}

/* ======== Server handler functions ======== */
function updateProfilesList(profiles) {
	// Set profiles items
	profilesBox.setItems(javafx.collections.FXCollections.observableList(profiles));
	for each (var profile in profiles) {
		pingers[profile.object] = new ServerPinger(profile.object.getServerSocketAddress(), profile.object.getVersion());
	}

	// Set profiles selection model
	var sm = profilesBox.getSelectionModel();
	sm.selectedIndexProperty()["addListener(javafx.beans.value.ChangeListener)"](
		function(o, ov, nv) settings.profile = nv); // Store selected profile index

	// Restore selected item
	var i = settings.profile;
	sm.select(i < profiles.size() ? i : 0);
}

function newProfileCell(listView) {
	var statusBox = loadFXML("dialog/profileCell.fxml");

	// Lookup labels
	var title = statusBox.lookup("#profileTitle");
	var status = statusBox.lookup("#serverStatus");
	var statusCircle = title.getGraphic();

	// Create and return new cell
	var cell = new (Java.extend(javafx.scene.control.ListCell))() {
		updateItem: function(item, empty) {
			Java.super(cell).updateItem(item, empty);
			cell.setGraphic(empty ? null : statusBox);
			if (empty) { // No need to update state
				return;
			}

			// Update title and server status
			title.setText(item.object.getTitle());
			pingServer(status, statusCircle, item);
		}
	};
	cell.setText(null);
	return cell;
}

function pingServer(status, statusCircle, profile) {
	setServerStatus(status, statusCircle, javafx.scene.paint.Color.GREY, "...");
	var task = newTask(function() pingers[profile.object].ping());
	task.setOnSucceeded(function(event) {
		var result = task.getValue();
		var color = result.isOverfilled() ? javafx.scene.paint.Color.YELLOW : javafx.scene.paint.Color.GREEN;
		setServerStatus(status, statusCircle, color, java.lang.String.format("%d из %d", result.onlinePlayers, result.maxPlayers));
	});
	task.setOnFailed(function(event) setServerStatus(status, statusCircle, javafx.scene.paint.Color.RED, "Недоступен"));
	startTask(task);
}

function setServerStatus(status, statusCircle, color, description) {
	status.setText(description);
	statusCircle.setFill(color);
}

/* ======== Overlay helper functions ======== */
function fade(region, delay, from, to, onFinished) {
	var transition = new javafx.animation.FadeTransition(javafx.util.Duration.millis(100), region);
	if (onFinished !== null) {
		transition.setOnFinished(onFinished);
	}

	// Launch transition
	transition.setDelay(javafx.util.Duration.millis(delay));
	transition.setFromValue(from);
	transition.setToValue(to);
	transition.play();
}

var overlay = {
	current: null,

	show: function(newOverlay, onFinished) {
		// Freeze root pane
		news.setDisable(true);
		authPane.setDisable(true);
		overlay.current = newOverlay;
		
		// Show dim pane
		dimPane.setVisible(true);
		dimPane.toFront();
		
		// Fade dim pane
		fade(dimPane, 0.0, 0.0, 1.0, function(event) {
			dimPane.requestFocus();
			dimPane.getChildren().add(newOverlay);
			
			// Fix overlay position
			newOverlay.setLayoutX((dimPane.getPrefWidth() - newOverlay.getPrefWidth()) / 2.0);
			newOverlay.setLayoutY((dimPane.getPrefHeight() - newOverlay.getPrefHeight()) / 2.0);
			
			// Fade in
			fade(newOverlay, 0.0, 0.0, 1.0, onFinished);
		});
	},

	hide: function(delay, onFinished) {
		fade(overlay.current, delay, 1.0, 0.0, function(event) {
			dimPane.getChildren().remove(overlay.current);
			fade(dimPane, 0.0, 1.0, 0.0, function(event) {
				dimPane.setVisible(false);
				
				// Unfreeze root pane
				news.setDisable(false);
				authPane.setDisable(false);
				rootPane.requestFocus();
				
				// Reset overlay state
				overlay.current = null;
				if (onFinished !== null) {
					onFinished();
				}
			});
		});
	},

	swap: function(delay, newOverlay, onFinished) {
		dimPane.toFront();
		fade(overlay.current, delay, 1.0, 0.0, function(event) {
			dimPane.requestFocus();

			// Hide old overlay
			if (overlay.current !== newOverlay) {
				var child = dimPane.getChildren();
				child.set(child.indexOf(overlay.current), newOverlay);
			}
			
			// Fix overlay position
			newOverlay.setLayoutX((dimPane.getPrefWidth() - newOverlay.getPrefWidth()) / 2.0);
			newOverlay.setLayoutY((dimPane.getPrefHeight() - newOverlay.getPrefHeight()) / 2.0);

			// Show new overlay
			overlay.current = newOverlay;
			fade(newOverlay, 0.0, 0.0, 1.0, onFinished);
		});
	}
};

/* ======== Overlay scripts ======== */
launcher.loadScript(Launcher.getResourceURL("dialog/overlay/debug/debug.js"));
launcher.loadScript(Launcher.getResourceURL("dialog/overlay/processing/processing.js"));
launcher.loadScript(Launcher.getResourceURL("dialog/overlay/settings/settings.js"));
launcher.loadScript(Launcher.getResourceURL("dialog/overlay/update/update.js"));