diff --git a/scripts/gui/main_menu.mjs b/scripts/gui/main_menu.mjs
index 1481c53541f..ee56233059a 100644
--- a/scripts/gui/main_menu.mjs
+++ b/scripts/gui/main_menu.mjs
@@ -25,6 +25,45 @@ export function runMenuSetup(){
common.playButtonPressSound();
newGame();
}, true);
+ document.getElementById("extrasButton").addEventListener("click", (event) => {
+ event.stopPropagation();
+ $("#mainMenu").slideUp("fast", () => {
+ $("#extrasMenu").slideDown("fast");
+ });
+ }, true);
+ document.getElementById("backFromExtras").addEventListener("click", (event) => {
+ event.stopPropagation();
+ $("#extrasMenu").slideUp("fast", () => {
+ $("#mainMenu").slideDown("fast");
+ });
+ }, true);
+ document.getElementById("toMultiplayerProtoButton").addEventListener("click", (event) => {
+ event.stopPropagation();
+ $("#extrasMenu").slideUp("fast", () => {
+ $("#serverConnectingMenu").slideDown("fast");
+ });
+ }, true);
+ document.getElementById("backFromConnecting").addEventListener("click", (event) => {
+ event.stopPropagation();
+ $("#serverConnectingMenu").slideUp("fast", () => {
+ $("#extrasMenu").slideDown("fast");
+ });
+ }, true);
+ document.getElementById("backFromConnecting").addEventListener("click", (event) => {
+ event.stopPropagation();
+ $("#serverConnectingMenu").slideUp("fast", () => {
+ $("#extrasMenu").slideDown("fast");
+ });
+ }, true);
+ document.getElementById("connectToServerButton").addEventListener("click", (event) => {
+ event.stopPropagation();
+ connectToSelectedServerURL();
+ }, true);
+ document.getElementById("disconnectFromServer").addEventListener("click", (event) => {
+ event.stopPropagation();
+ disconnectFromCurrentServer();
+ }, true);
+
document.addEventListener("keydown", (event) => {
if(event.key === "Escape"){
@@ -50,6 +89,11 @@ export function runMenuSetup(){
doExitToMenu();
});
+ // Server status message display
+ Leviathan.OnGeneric("ConnectStatusMessage", (event, vars) => {
+ handleConnectionStatusEvent(vars);
+ });
+
// Start intro video
Leviathan.PlayCutscene("Data/Videos/intro.mkv", onIntroEnded, onIntroEnded);
@@ -150,6 +194,49 @@ function newGame(){
}
}
+function connectToSelectedServerURL(){
+ // The url is from this textbox
+ const url = document.getElementById("connectServerURLInput").value;
+
+ if(!url)
+ return;
+
+ if(common.isInEngine()){
+
+ Thrive.connectToServer(url);
+
+ } else {
+
+ handleConnectionStatusEvent({
+ show: true, server: url,
+ message: "This is the GUI in a browser and can't actually connect"
+ });
+ }
+}
+
+function disconnectFromCurrentServer(){
+ if(common.isInEngine()){
+
+ Thrive.disconnectFromServer();
+
+ } else {
+
+ handleConnectionStatusEvent({show: false});
+ }
+}
+
+function handleConnectionStatusEvent(event){
+ if(event.show){
+ document.getElementById("serverConnectPopup").style.display = "flex";
+ } else {
+ document.getElementById("serverConnectPopup").style.display = "none";
+ }
+
+ if(event.server)
+ document.getElementById("currentServerAddress").innerText = event.server;
+ document.getElementById("currentConnectionStatusMessage").innerText = event.message;
+}
+
function onMicrobeIntroEnded(error){
if(error)
diff --git a/scripts/gui/thrive_gui.html b/scripts/gui/thrive_gui.html
index dd9e604237d..d870efa87d0 100644
--- a/scripts/gui/thrive_gui.html
+++ b/scripts/gui/thrive_gui.html
@@ -49,11 +49,39 @@
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
JavaScript not loaded...
diff --git a/scripts/gui/thrive_style.css b/scripts/gui/thrive_style.css
index 9e00d51be6f..77d0e0e4cd1 100644
--- a/scripts/gui/thrive_style.css
+++ b/scripts/gui/thrive_style.css
@@ -205,6 +205,28 @@ video {
vertical-align: middle;
line-height: 40px;
font-size: 15pt;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.MenuTextBox {
+ background: rgb(0, 125, 125, 0.8);
+ border: 1px solid rgb(112, 159, 159, 0.6);
+ color: white;
+ height: 32px;
+ font-size: 18pt;
+ margin-bottom: 3px;
+}
+
+.MenuDialogBox {
+ width: 500px;
+ height: 160px;
+ border-radius: 3px;
+ background: rgb(0, 125, 125, 0.9);
+ border: 2px solid rgb(112, 159, 159, 0.6);
+ display: flex;
+ align-items: center;
+ flex-direction: column;
}
.DisabledButton {
@@ -556,6 +578,7 @@ video {
background-color: rgb(0, 0, 0, 0.7);
z-index: 1;
display: flex;
+ align-items: center;
justify-content: center;
}
diff --git a/src/ThriveGame.cpp b/src/ThriveGame.cpp
index ec93defb5ed..f805e6ca072 100644
--- a/src/ThriveGame.cpp
+++ b/src/ThriveGame.cpp
@@ -623,6 +623,100 @@ void
m_impl->m_cellStage->GetMicrobeCameraSystem().changeCameraOffset(
amount);
}
+// ------------------------------------ //
+void
+ ThriveGame::connectToServer(const std::string& url)
+{
+ LOG_INFO("Connecting to server at: " + url);
+
+ if(m_network->IsConnected()) {
+ disconnectFromServer(
+ false, "Disconnect by user, joining another server");
+ }
+
+ auto connection = m_network->GetOwner()->OpenConnectionTo(url);
+
+ if(!connection) {
+
+ Leviathan::GenericEvent::pointer event =
+ new Leviathan::GenericEvent("ConnectStatusMessage");
+
+ auto vars = event->GetVariables();
+
+ vars->Add(std::make_shared(
+ "show", new Leviathan::BoolBlock(true)));
+ vars->Add(std::make_shared("message",
+ new Leviathan::StringBlock("Invalid address specified")));
+
+ Engine::Get()->GetEventHandler()->CallEvent(event.detach());
+
+ } else {
+
+ if(!m_network->JoinServer(connection)) {
+
+ Leviathan::GenericEvent::pointer event =
+ new Leviathan::GenericEvent("ConnectStatusMessage");
+
+ auto vars = event->GetVariables();
+
+ vars->Add(std::make_shared(
+ "show", new Leviathan::BoolBlock(true)));
+ vars->Add(std::make_shared("message",
+ new Leviathan::StringBlock(
+ "Unknown error from JoinServer (try disconnecting?)")));
+
+ Engine::Get()->GetEventHandler()->CallEvent(event.detach());
+ return;
+ }
+
+ Leviathan::GenericEvent::pointer event =
+ new Leviathan::GenericEvent("ConnectStatusMessage");
+
+ auto vars = event->GetVariables();
+
+ vars->Add(std::make_shared(
+ "show", new Leviathan::BoolBlock(true)));
+ vars->Add(std::make_shared(
+ "server", new Leviathan::StringBlock(url)));
+ vars->Add(std::make_shared(
+ "message", new Leviathan::StringBlock("Opening connection")));
+
+ Engine::Get()->GetEventHandler()->CallEvent(event.detach());
+ }
+}
+
+void
+ ThriveGame::disconnectFromServer(bool userInitiated,
+ const std::string& reason)
+{
+ LOG_INFO("Initiating disconnect from server");
+ m_network->DisconnectFromServer(reason);
+
+ if(!userInitiated) {
+ Leviathan::GenericEvent::pointer event =
+ new Leviathan::GenericEvent("ConnectStatusMessage");
+
+ auto vars = event->GetVariables();
+
+ vars->Add(std::make_shared(
+ "show", new Leviathan::BoolBlock(true)));
+ vars->Add(std::make_shared(
+ "message", new Leviathan::StringBlock("Disconnected: " + reason)));
+
+ Engine::Get()->GetEventHandler()->CallEvent(event.detach());
+ } else {
+ Leviathan::GenericEvent::pointer event =
+ new Leviathan::GenericEvent("ConnectStatusMessage");
+
+ auto vars = event->GetVariables();
+
+ // This hides it
+ vars->Add(std::make_shared(
+ "show", new Leviathan::BoolBlock(false)));
+
+ Engine::Get()->GetEventHandler()->CallEvent(event.detach());
+ }
+}
// ------------------------------------ //
void
diff --git a/src/ThriveGame.h b/src/ThriveGame.h
index 3b1f9162839..05c88e7293d 100644
--- a/src/ThriveGame.h
+++ b/src/ThriveGame.h
@@ -71,6 +71,17 @@ class ThriveGame : public Leviathan::ClientApplication, public ThriveCommon {
void
onZoomChange(float amount);
+
+ // ------------------------------------ //
+ //! \brief Begins connecting to server at url
+ void
+ connectToServer(const std::string& url);
+
+ //! \brief Disconnects from current server
+ void
+ disconnectFromServer(bool userInitiated,
+ const std::string& reason = "Disconnect by user");
+
// ------------------------------------ //
// Hooking into the engine, and overridden methods from base application
// etc.
diff --git a/src/thrive_js_interface.cpp b/src/thrive_js_interface.cpp
index e6850e8ec43..75ead1d33d1 100644
--- a/src/thrive_js_interface.cpp
+++ b/src/thrive_js_interface.cpp
@@ -109,6 +109,28 @@ bool
auto args = message->GetArgumentList();
args->SetString(0, "exitToMenuClicked");
+ Owner->SendCustomExtensionMessage(message);
+ return true;
+ } else if(name == "connectToServer") {
+
+ if(arguments.size() < 1 || !arguments[0]->IsString()) {
+ // Invalid arguments //
+ exception = "Invalid arguments passed, expected: string";
+ return true;
+ }
+
+ auto message = CefProcessMessage::Create("Custom");
+ auto args = message->GetArgumentList();
+ args->SetString(0, "connectToServer");
+ args->SetString(1, arguments[0]->GetStringValue());
+
+ Owner->SendCustomExtensionMessage(message);
+ return true;
+ } else if(name == "disconnectFromServer") {
+ auto message = CefProcessMessage::Create("Custom");
+ auto args = message->GetArgumentList();
+ args->SetString(0, "disconnectFromServer");
+
Owner->SendCustomExtensionMessage(message);
return true;
}
@@ -159,7 +181,16 @@ bool
ThriveGame::Get()->exitToMenuClicked();
return true;
+ } else if(customType == "connectToServer") {
+
+ ThriveGame::Get()->connectToServer(args->GetString(1));
+ return true;
+ } else if(customType == "disconnectFromServer") {
+
+ ThriveGame::Get()->disconnectFromServer(true);
+ return true;
}
+
// Not ours
return false;
}
diff --git a/src/thrive_v8_extension.js b/src/thrive_v8_extension.js
index ca3cc99abb7..2fb037fcc14 100644
--- a/src/thrive_v8_extension.js
+++ b/src/thrive_v8_extension.js
@@ -26,4 +26,10 @@ var Thrive = {};
native function exitToMenuClicked();
Thrive.exitToMenuClicked = exitToMenuClicked;
+ native function connectToServer(url);
+ Thrive.connectToServer = connectToServer;
+
+ native function disconnectFromServer();
+ Thrive.disconnectFromServer = disconnectFromServer;
+
}());