diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 00000000..a55e7a17
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml
index 1029fbc0..87c9bbae 100644
--- a/.idea/inspectionProfiles/Project_Default.xml
+++ b/.idea/inspectionProfiles/Project_Default.xml
@@ -7,8 +7,9 @@
+
-
+
diff --git a/assets/base/script/modules/fenv.lua b/assets/base/script/modules/fenv.lua
index bfab0dd1..02013e8a 100644
--- a/assets/base/script/modules/fenv.lua
+++ b/assets/base/script/modules/fenv.lua
@@ -1,3 +1,6 @@
+local debug = _G['debug']
+_G['debug'] = nil
+
if not setfenv then
_G['setfenv'] = function(fn, env)
local i = 1
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9cee9cb0..f9cd50b2 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,8 +1,6 @@
add_library(Zepha_Core
client/Client.cpp
client/Client.h
- client/ClientState.cpp
- client/ClientState.h
client/conn/ClientNetworkInterpreter.cpp
client/conn/ClientNetworkInterpreter.h
client/conn/ServerConnection.cpp
@@ -323,6 +321,6 @@ add_library(Zepha_Core
world/ServerWorld.h
world/World.cpp
world/World.h
-)
+ util/net/Address.cpp)
target_include_directories(Zepha_Core PUBLIC .)
\ No newline at end of file
diff --git a/src/Main.cpp b/src/Main.cpp
index 04b1914c..51bc0c5f 100644
--- a/src/Main.cpp
+++ b/src/Main.cpp
@@ -19,7 +19,14 @@
#include "StartGame.h"
+/**
+ * Main entrance point to the program. (Am I really describing what the main function is?)
+ * Intentionally kept minimal to allow for testing. Real startup logic is done in StartGame. *
+ * @param argc - Argument array length
+ * @param argv - Argument array
+ * @returns - A numerical value indicating exit status.
+ */
+
int main(int argc, char* argv[]) {
return StartGame(argc, argv);
}
-
diff --git a/src/StartGame.h b/src/StartGame.h
index 0858c76a..d52444f2 100644
--- a/src/StartGame.h
+++ b/src/StartGame.h
@@ -11,9 +11,18 @@
#include "client/Client.h"
#include "server/Server.h"
-enum class Mode { INVALID, CLIENT, SERVER };
+enum class Mode { CLIENT, SERVER };
-std::map parseArgs(int argc, char* argv[]) {
+
+/**
+ * Parses the arg list provided by the operating system into a map of key-value strings.
+ * @throws invalid_argument if it encounters a duplicate or improperly formatted argument.
+ * @param argc - Argument array length
+ * @param argv - Argument array
+ * @returns - A map of parsed arguments.
+ */
+
+std::map ParseArgs(int argc, char* argv[]) {
//Collect arguments into `args` map
std::map args;
for (int i = 1; i < argc; i++) {
@@ -32,76 +41,83 @@ std::map parseArgs(int argc, char* argv[]) {
return args;
}
+
+/**
+ * Instantiates a Client or Server instance, depending on the arguments provided.
+ * @param argc - Argument array length
+ * @param argv - Argument array
+ * @returns - A numerical value indicating exit status.
+ */
+
int StartGame(int argc, char* argv[]) {
- std::string path = argv[0];
-
- Address addr {"127.0.0.1", 32000};
Mode mode = Mode::CLIENT;
- std::string subgame = "";
- bool ascii = true;
- //Parse the arguments map
- for (auto arg : parseArgs(argc, argv)) {
- switch (Util::hash(arg.first.c_str())) {
- default: {
- std::cout << Log::err << "Invalid argument " << arg.first << "." << Log::endl;
- return -1;
- }
- case Util::hash("--mode"): {
+ try {
+ unsigned short port = Address::DEFAULT_PORT;
+ std::string subgame = "";
+ bool ascii = true;
+
+ /**
+ * Handle command line arguments.
+ * @arg mode ("client" | "server") - Whether to initialize a client instance, or a server. Defaults to "client".
+ * @arg port (unsigned short) - The port that the server should listen on. Defaults to Address::DEFAULT_PORT.
+ * @arg subgame (std::string) - The subgame that the server should load.
+ * @arg noascii - Switch to disable ASCII from the console output.
+ */
+
+ for (auto arg : ParseArgs(argc, argv)) {
+ switch (Util::hash(arg.first.c_str())) {
+ default:
+ throw std::runtime_error("Invalid argument '" + arg.first + "'.");
+
+ case Util::hash("--mode"):
if (arg.second == "client") mode = Mode::CLIENT;
else if (arg.second == "server") mode = Mode::SERVER;
- else std::cout << Log::err << "Invalid mode argument." << Log::endl;
+ else throw std::runtime_error("Invalid mode specified.");
break;
- }
- case Util::hash("--port"): {
- addr.port = static_cast(stoi(arg.second));
+
+// case Util::hash("--address"):
+// addr.host = arg.second;
+// break;
+
+ case Util::hash("--port"):
+ port = static_cast(stoi(arg.second));
break;
- }
- case Util::hash("--address"): {
- addr.host = arg.second;
- break;
- }
- case Util::hash("--subgame"): {
+
+ case Util::hash("--subgame"):
subgame = arg.second;
break;
- }
- case Util::hash("--noascii"): {
+
+ case Util::hash("--noascii"):
ascii = false;
break;
}
}
- }
- // Obligatory ASCII Art is obligatory.
- if (ascii) {
- Log::clear();
- std::cout << "\n"
- "\t\t▒███████▒▓█████ ██▓███ ██░ ██ ▄▄▄ \n"
- "\t\t▒ ▒ ▒ ▄▀░▓█ ▀ ▓██░ ██▒▓██░ ██▒▒████▄ \n"
- "\t\t░ ▒ ▄▀▒░ ▒███ ▓██░ ██▓▒▒██▀▀██░▒██ ▀█▄ \n"
- "\t\t ▄▀▒ ░▒▓█ ▄ ▒██▄█▓▒ ▒░▓█ ░██ ░██▄▄▄▄██ \n"
- "\t\t▒███████▒░▒████▒▒██▒ ░ ░░▓█▒░██▓ ▓█ ▓██▒\n"
- "\t\t░▒▒ ▓░▒░▒░░ ▒░ ░▒▓▒░ ░ ░ ▒ ░░▒░▒ ▒▒ ▓▒█░\n"
- "\t\t░ ▒ ▒ ░ ▒ ░ ░ ░░▒ ░ ▒ ░▒░ ░ ▒ ▒▒ ░\n"
- "\t\t ░ ░ ░ ░ ░░ ░ ░ ░ ▒ \n" << std::endl;
- }
-
- //Start the game
- switch (mode) {
- default: {
- std::cout << Log::err << "Mode not set." << Log::endl;
- return -1;
+ if (ascii) {
+ Log::clear();
+ std::cout <<
+ "\n"
+ "\t\t ____ ____ ____ _ _ __ \n"
+ "\t\t(__ )( __)( _ \\/ )( \\ / _\\ \n"
+ "\t\t / _/ ) _) ) __/) __ (/ \\\n"
+ "\t\t(____)(____)(__) \\_)(_/\\_/\\_/\n" << std::endl;
}
+
+ switch (mode) {
case Mode::CLIENT: {
- Client c(path, addr, {1366, 768});
- break;
- }
+ Client c({1366, 768});
+ break; }
+
case Mode::SERVER: {
- Server s(addr.port, subgame);
- break;
+ Server s(port, subgame);
+ break; }
}
+
+ return 0;
}
-
- return 0;
-};
-
+ catch (const std::exception& e) {
+ std::cout << Log::err << "Zepha failed to start.\n" << e.what() << Log::endl;
+ return 1;
+ }
+}
diff --git a/src/client/Client.cpp b/src/client/Client.cpp
index e6c01927..a603fb92 100644
--- a/src/client/Client.cpp
+++ b/src/client/Client.cpp
@@ -1,12 +1,8 @@
-//
-// Created by aurailus on 06/01/19.
-//
#include
#include "Client.h"
-#include "../util/Log.h"
#include "../util/Timer.h"
#include "LocalServerInstance.h"
@@ -14,55 +10,60 @@
#include "scene/ConnectScene.h"
#include "scene/MainMenuScene.h"
-Client::Client(const std::string& path, const Address &addr, glm::ivec2 dims) :
- state(path.substr(0, path.find_last_of('/') + 1), renderer),
- renderer(dims),
- addr(addr),
- executablePath(path) {
+
+/**
+ * Creates a client window and starts the main event loop.
+ * Initially opens to the main menu.
+ * @param window - The dimensions for the created window.
+ */
+
+Client::Client(glm::ivec2 window) :
+ renderer(window) {
std::cout << Log::info << "Starting Zepha Client." << Log::endl;
- std::unique_ptr scene = std::make_unique(state);
-// std::unique_ptr scene = std::make_unique(state, "whoopsie poopsie did a fucky wucky");
- sceneManager.setScene(std::move(scene));
-
+ scene.setScene(std::make_unique(*this));
while (!renderer.window.shouldClose()) loop();
}
+
+/**
+ * Get the last frame's delta time.
+ * @returns the delta time.
+ */
+
+double Client::getDelta() {
+ return delta;
+}
+
+
+/**
+ * Starts a local server and connects to it.
+ * @throws runtime_error if a local server is already running.
+ * @param subgame - The subgame for the local server to run.
+ */
+
+void Client::startLocalServer(const std::string& subgame) {
+ //TODO: Implement Local Server
+// localServer = std::make_shared(executablePath, addr.port, state.subgame);
+// localServer->start();
+
+ scene.setScene(std::make_unique(*this, Address { "127.0.0.1", Address::DEFAULT_PORT }));
+}
+
+
+/**
+ * The main event loop. Polls GLFW, and updates the scene and the renderer.
+ * Will be called by the Client constructor until render.window.shouldClose() returns true.
+ */
+
void Client::loop() {
- Timer t("Client Loop");
-
- if (state.desiredState == "local") {
- state.desiredState = "connect";
- localServer = std::make_shared(executablePath, addr.port, state.subgame);
- localServer->start();
- }
-
- if (state.desiredState == "connect") {
- state.desiredState = "this";
- std::unique_ptr scene = std::make_unique(state, addr);
- sceneManager.setScene(std::move(scene));
- }
-
- if (state.desiredState == "game") {
- state.desiredState = "this";
- std::unique_ptr scene = std::make_unique(state);
- sceneManager.setScene(std::move(scene));
- }
-
double now = glfwGetTime();
- state.delta = now - timeElapsed;
+ delta = now - timeElapsed;
timeElapsed = now;
glfwPollEvents();
- sceneManager.update();
- renderer.update(state.delta);
-
- state.fps = 1000.0 / (t.elapsedNs() / 1000000.0);
-}
-
-Client::~Client() {
- sceneManager.cleanupScene();
- if (localServer) localServer->stop();
+ scene.update();
+ renderer.update(delta);
}
\ No newline at end of file
diff --git a/src/client/Client.h b/src/client/Client.h
index d6d64d75..8d5d5d45 100644
--- a/src/client/Client.h
+++ b/src/client/Client.h
@@ -1,31 +1,41 @@
-//
-// Created by aurailus on 06/01/19.
-//
+/*
+ * Main Client object. Contains important properties, such as the renderer and scene manager.
+ * Also manages the local server, if there is one.
+ *
+ * - Auri, 03/11/20
+ */
#pragma once
#include "util/net/Address.h"
-#include "client/ClientState.h"
+#include "game/LocalSubgame.h"
#include "client/graph/Renderer.h"
#include "client/scene/SceneManager.h"
+#include "client/conn/ServerConnection.h"
class LocalServerInstance;
class Client {
public:
- Client(const std::string& path, const Address& addr, glm::ivec2 dims);
- ~Client();
+ Client(const Client& o) = delete;
+ explicit Client(glm::ivec2 window);
+
+ double getDelta();
+
+ void startLocalServer(const std::string& subgame);
+
+ Renderer renderer;
+ SceneManager scene;
+ ServerConnection connection {};
+
+ std::shared_ptr game = std::make_shared("../assets/textures");
+
private:
void loop();
- std::string executablePath;
- Address addr {};
- Renderer renderer;
- ClientState state;
- SceneManager sceneManager;
-
std::shared_ptr localServer = nullptr;
- double timeElapsed = 0.0f;
+ double delta = 0;
+ double timeElapsed = 0;
};
diff --git a/src/client/ClientState.cpp b/src/client/ClientState.cpp
deleted file mode 100644
index 862fe0bf..00000000
--- a/src/client/ClientState.cpp
+++ /dev/null
@@ -1,17 +0,0 @@
-//
-// Created by aurailus on 2019-12-11.
-//
-
-#include "ClientState.h"
-
-#ifdef _WIN32
-ClientState::ClientState(const std::string& path, Renderer& renderer) :
- path(path),
- renderer(renderer),
- defs(path + "assets\\textures") {}
-#else
-ClientState::ClientState(const std::string &path, Renderer &renderer) :
- path(path),
- renderer(renderer),
- game(path + "../assets/textures") {}
-#endif
diff --git a/src/client/ClientState.h b/src/client/ClientState.h
deleted file mode 100644
index ff3898a1..00000000
--- a/src/client/ClientState.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Created by aurailus on 06/01/19.
-//
-
-#pragma once
-
-#include "game/LocalSubgame.h"
-#include "client/conn/ServerConnection.h"
-
-class Renderer;
-
-class ClientState {
-public:
- ClientState(const std::string& path, Renderer& renderer);
-
- std::string path;
- std::string subgame;
-
- Renderer& renderer;
- ServerConnection connection {};
- LocalSubgame game;
-
- unsigned int seed = 0;
-
- std::string desiredState = "this";
-
- double fps = 0;
- double delta = 0;
-};
\ No newline at end of file
diff --git a/src/client/LocalServerInstance.cpp b/src/client/LocalServerInstance.cpp
index fc738373..7ddd2aa3 100644
--- a/src/client/LocalServerInstance.cpp
+++ b/src/client/LocalServerInstance.cpp
@@ -44,3 +44,7 @@ void LocalServerInstance::stop() {
std::cout << Log::err << "Local Server destructor not implemented on Windows!" << Log::endl;
#endif
}
+
+LocalServerInstance::~LocalServerInstance() {
+ stop();
+}
\ No newline at end of file
diff --git a/src/client/LocalServerInstance.h b/src/client/LocalServerInstance.h
index d8f0de6a..06c4c05b 100644
--- a/src/client/LocalServerInstance.h
+++ b/src/client/LocalServerInstance.h
@@ -18,6 +18,8 @@ public:
bool start();
void stop();
+
+ ~LocalServerInstance();
private:
std::string path;
std::string subgame;
diff --git a/src/client/gui/DebugGui.cpp b/src/client/gui/DebugGui.cpp
index b640c926..f964ce9e 100644
--- a/src/client/gui/DebugGui.cpp
+++ b/src/client/gui/DebugGui.cpp
@@ -43,7 +43,7 @@ DebugGui::DebugGui(glm::vec2 bufferSize, SubgamePtr game, WorldPtr world) :
add(genGraph);
auto packetGraph = std::make_shared("packetGraph");
- packetGraph->create({244, 64}, {}, "Packets", 120, 512, genericHistogramRef, f);
+ packetGraph->create({244, 64}, {}, "Packets", 120, 32, genericHistogramRef, f);
add(packetGraph);
auto fpsGraph = std::make_shared("fpsGraph");
diff --git a/src/client/menu/MenuSandbox.cpp b/src/client/menu/MenuSandbox.cpp
index 8151e5ce..025e6472 100644
--- a/src/client/menu/MenuSandbox.cpp
+++ b/src/client/menu/MenuSandbox.cpp
@@ -1,6 +1,4 @@
-//
-// Created by aurailus on 2019-12-12.
-//
+
#include
#include
#include
@@ -8,6 +6,7 @@
#include "MenuSandbox.h"
#include "lua/LuaMod.h"
+#include "client/Client.h"
#include "lua/ErrorFormatter.h"
#include "client/menu/SubgameDef.h"
#include "client/gui/basic/GuiText.h"
@@ -18,12 +17,13 @@
#include "lua/modules/mSetGui.h"
#include "lua/modules/mStartGame.h"
-MenuSandbox::MenuSandbox(glm::ivec2 &win, ClientState& state, std::shared_ptr container) : LuaParser(state.game),
+MenuSandbox::MenuSandbox(glm::ivec2 &win, Client& client, std::shared_ptr container) :
+ LuaParser(*client.game),
win(win),
- state(state),
+ client(client),
container(container),
luaContainer(std::dynamic_pointer_cast(container->add(std::make_shared("__lua")))),
- builder(state.game.textures, state.game.models, luaContainer) {}
+ builder(client.game->textures, client.game->models, luaContainer) {}
void MenuSandbox::reset() {
container->remove("error");
@@ -48,7 +48,7 @@ void MenuSandbox::loadApi() {
ClientApi::gui_element(lua);
MenuApi::set_gui (builder, win, lua, core);
- MenuApi::start_game (state, core);
+ MenuApi::start_game (client, core);
bindModules();
@@ -87,9 +87,10 @@ sol::protected_function_result MenuSandbox::runFileSandboxed(const std::string&
env["_FILE"] = f.path;
env["_MODNAME"] = mod.config.name;
- return lua.safe_script(f.file, env, std::bind(&MenuSandbox::errorCallback, this, std::placeholders::_2), "@" + f.path, sol::load_mode::text);
+ return lua.safe_script(f.file, env, std::bind(&MenuSandbox::errorCallback,
+ this, std::placeholders::_2), "@" + f.path, sol::load_mode::text);
}
- throw std::runtime_error("Error opening \"" + file + "\", file not found.");
+ throw std::runtime_error("Error opening '" + file + "', file not found.");
}
void MenuSandbox::loadAndRunMod(const std::string &modPath) {
@@ -149,7 +150,7 @@ void MenuSandbox::loadAndRunMod(const std::string &modPath) {
std::string texPath = modPath + "/textures";
if (cf_file_exists(texPath.data())) {
- this->modAssets = state.game.textures.loadDirectory(texPath, false, true);
+ this->modAssets = client.game->textures.loadDirectory(texPath, false, true);
}
this->mod = mod;
@@ -158,7 +159,7 @@ void MenuSandbox::loadAndRunMod(const std::string &modPath) {
void MenuSandbox::showError(const std::string& what, const std::string& subgame) {
const std::string errPrefixText = "Encountered an error while loading the menu for " + subgame + " ;-;";
- Font f(state.game.textures, state.game.textures["font"]);
+ Font f(client.game->textures, client.game->textures["font"]);
auto errWrap = std::make_shared("error");
container->add(errWrap);
diff --git a/src/client/menu/MenuSandbox.h b/src/client/menu/MenuSandbox.h
index dced2546..07bb153b 100644
--- a/src/client/menu/MenuSandbox.h
+++ b/src/client/menu/MenuSandbox.h
@@ -9,15 +9,15 @@
#include "lua/LuaMod.h"
#include "client/gui/GuiBuilder.h"
+class Client;
class Subgame;
class AtlasRef;
class SubgameDef;
-class ClientState;
class GuiContainer;
class MenuSandbox : LuaParser {
public:
- MenuSandbox(glm::ivec2& win, ClientState& state, std::shared_ptr container);
+ MenuSandbox(glm::ivec2& window, Client& client, std::shared_ptr container);
void load(const SubgameDef& subgame);
void update(double delta) override;
@@ -41,6 +41,6 @@ private:
std::shared_ptr luaContainer = nullptr;
GuiBuilder builder;
- ClientState& state;
+ Client& client;
glm::ivec2& win;
};
diff --git a/src/client/scene/ConnectScene.cpp b/src/client/scene/ConnectScene.cpp
index b9712741..69fee691 100644
--- a/src/client/scene/ConnectScene.cpp
+++ b/src/client/scene/ConnectScene.cpp
@@ -6,22 +6,31 @@
#include "ConnectScene.h"
+#include "client/Client.h"
#include "util/net/Packet.h"
#include "util/net/Address.h"
-#include "client/ClientState.h"
#include "util/net/PacketView.h"
#include "client/graph/Renderer.h"
#include "client/gui/basic/GuiRect.h"
#include "client/gui/basic/GuiText.h"
#include "game/atlas/asset/AssetType.h"
#include "game/atlas/LocalDefinitionAtlas.h"
+#include "GameScene.h"
-ConnectScene::ConnectScene(ClientState &state, Address addr) : Scene(state),
- connection(state.connection) {
- state.renderer.setClearColor(10, 10, 10);
+/**
+ * Initializes a connection to the remote address,
+ * sets up the GUI, and attempts to download subgame assets.
+ *
+ * @param addr - The server address to connect to.
+ */
- Font f(state.game.textures, state.game.textures["font"]);
+ConnectScene::ConnectScene(Client &client, Address addr) : Scene(client),
+ connection(client.connection) {
+
+ client.renderer.setClearColor(10, 10, 10);
+
+ Font f(client.game->textures, client.game->textures["font"]);
auto statusText = std::make_shared("statusText");
statusText->create({2, 2}, {}, {}, {1, 1, 1, 1}, f);
@@ -31,18 +40,18 @@ ConnectScene::ConnectScene(ClientState &state, Address addr) : Scene(state),
auto loadBar = std::make_shared("loadBar");
loadBar->create({1, 32}, {}, {0.17, 0.75, 0.93, 1});
- loadBar->setPos({0, state.renderer.window.getSize().y - 32});
+ loadBar->setPos({0, client.renderer.window.getSize().y - 32});
components.add(loadBar);
connection.attemptConnect(std::move(addr));
- state.renderer.window.addResizeCallback("scene", [&](glm::ivec2 win) {
+ client.renderer.window.addResizeCallback("scene", [&](glm::ivec2 win) {
components.get("loadBar")->setPos({0, win.y - 32});
});
}
void ConnectScene::update() {
- state.game.textures.update();
+ client.game->textures.update();
switch (connectState) {
default:
@@ -57,7 +66,7 @@ void ConnectScene::update() {
break;
case State::PROPERTIES: {
- components.get("loadBar")->setScale({state.renderer.window.getSize().x * 0.1, 32});
+ components.get("loadBar")->setScale({client.renderer.window.getSize().x * 0.1, 32});
ENetEvent e;
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
@@ -67,7 +76,8 @@ void ConnectScene::update() {
auto statusText = components.get("statusText");
statusText->setText(statusText->getText() + "Received server properties.\n");
- state.seed = p.d.read();
+ // TODO: Reimplement this somewhere or something.
+// state.seed = p.d.read();
connectState = State::IDENTIFIER_LIST;
Packet resp(Packet::Type::BLOCK_IDENTIFIER_LIST);
@@ -78,7 +88,7 @@ void ConnectScene::update() {
}
case State::IDENTIFIER_LIST: {
- components.get("loadBar")->setScale({state.renderer.window.getSize().x * 0.2, 32});
+ components.get("loadBar")->setScale({client.renderer.window.getSize().x * 0.2, 32});
ENetEvent e;
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
@@ -88,7 +98,7 @@ void ConnectScene::update() {
auto statusText = components.get("statusText");
statusText->setText(statusText->getText() + "Received block index-identifier table.\n");
- state.game.getDefs().setIdentifiers(p.d.read>());
+ client.game->getDefs().setIdentifiers(p.d.read>());
Packet resp(Packet::Type::BIOME_IDENTIFIER_LIST);
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
@@ -97,7 +107,7 @@ void ConnectScene::update() {
auto statusText = components.get("statusText");
statusText->setText(statusText->getText() + "Received biome index-identifier table.\nDownloading mods...\n");
- state.game.getBiomes().setIdentifiers(p.d.read>());
+ client.game->getBiomes().setIdentifiers(p.d.read>());
connectState = State::MODS;
Packet resp(Packet::Type::MODS);
@@ -108,7 +118,7 @@ void ConnectScene::update() {
}
case State::MODS: {
- components.get("loadBar")->setScale({state.renderer.window.getSize().x * 0.4, 32});
+ components.get("loadBar")->setScale({client.renderer.window.getSize().x * 0.4, 32});
ENetEvent e;
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
PacketView p(e.packet);
@@ -118,10 +128,10 @@ void ConnectScene::update() {
if (p.type == Packet::Type::MODS) {
auto luaMod = LuaMod::fromPacket(p);
statusText->setText(statusText->getText() + "Received mod " + luaMod.config.name + ".\n");
- state.game.getParser().getHandler().addLuaMod(std::move(luaMod));
+ client.game->getParser().getHandler().addLuaMod(std::move(luaMod));
}
else if (p.type == Packet::Type::MOD_ORDER) {
- state.game.getParser().getHandler().setModsOrder(p.d.read>());
+ client.game->getParser().getHandler().setModsOrder(p.d.read>());
statusText->setText(statusText->getText() + "Done downloading mods.\nReceived the mods order.\nDownloading media...\n");
@@ -134,7 +144,7 @@ void ConnectScene::update() {
}
case State::MEDIA: {
- components.get("loadBar")->setScale({state.renderer.window.getSize().x * 0.6, 32});
+ components.get("loadBar")->setScale({client.renderer.window.getSize().x * 0.6, 32});
ENetEvent e;
if (connection.pollEvents(&e) && e.type == ENET_EVENT_TYPE_RECEIVE) {
@@ -156,15 +166,15 @@ void ConnectScene::update() {
std::string data = p.d.read();
std::string uncompressed = gzip::decompress(data.data(), data.length());
- state.game.textures.addImage(
- reinterpret_cast(const_cast(uncompressed.data())),
- assetName, true, width, height);
+ client.game->textures.addImage(
+ reinterpret_cast(const_cast(uncompressed.data())),
+ assetName, true, width, height);
}
else if (t == AssetType::MODEL) {
std::string format = p.d.read();
std::string data = p.d.read();
- state.game.models.models.insert({assetName, SerializedModel{assetName, data, format}});
+ client.game->models.models.insert({assetName, SerializedModel{assetName, data, format}});
}
t = static_cast(p.d.read());
@@ -174,11 +184,11 @@ void ConnectScene::update() {
statusText->setText(statusText->getText() + "Received " + std::to_string(count) + "x media files.\n");
}
else if (p.type == Packet::Type::MEDIA_DONE) {
- components.get("loadBar")->setScale({state.renderer.window.getSize().x, 32});
+ components.get("loadBar")->setScale({client.renderer.window.getSize().x, 32});
statusText->setText(statusText->getText() + "Done downloading media.\nJoining world...\n");
connectState = State::DONE;
- state.desiredState = "game";
+ client.scene.setScene(std::make_unique(client));
}
}
break;
@@ -206,7 +216,7 @@ void ConnectScene::handleConnecting() {
case ServerConnection::State::ATTEMPTING_CONNECT:
connection.processConnecting();
- dotsTime += state.delta;
+ dotsTime += client.getDelta();
if (dotsTime > 1) {
dotsTime -= 1;
statusText->setText(statusText->getText() + ".");
@@ -225,12 +235,12 @@ void ConnectScene::handleConnecting() {
}
void ConnectScene::draw() {
- Renderer& renderer = state.renderer;
+ Renderer& renderer = client.renderer;
renderer.beginChunkDeferredCalls();
renderer.endDeferredCalls();
renderer.beginGUIDrawCalls();
- renderer.enableTexture(&state.game.textures.atlasTexture);
+ renderer.enableTexture(&client.game->textures.atlasTexture);
components.draw(renderer);
@@ -238,5 +248,5 @@ void ConnectScene::draw() {
}
void ConnectScene::cleanup() {
- state.renderer.window.removeResizeCallback("scene");
+ client.renderer.window.removeResizeCallback("scene");
}
\ No newline at end of file
diff --git a/src/client/scene/ConnectScene.h b/src/client/scene/ConnectScene.h
index 9e5fbff3..5b549b2c 100644
--- a/src/client/scene/ConnectScene.h
+++ b/src/client/scene/ConnectScene.h
@@ -23,15 +23,14 @@ public:
DONE
};
- ConnectScene(ClientState& state, Address addr);
+ ConnectScene(Client& state, Address addr);
void update() override;
+ void draw() override;
+ void cleanup() override;
void handleConnecting();
- void draw() override;
-
- void cleanup() override;
private:
State connectState = State::CONNECTING;
ServerConnection& connection;
diff --git a/src/client/scene/GameScene.cpp b/src/client/scene/GameScene.cpp
index aaf990eb..8f360602 100644
--- a/src/client/scene/GameScene.cpp
+++ b/src/client/scene/GameScene.cpp
@@ -4,36 +4,36 @@
#include "GameScene.h"
-#include "client/ClientState.h"
+#include "client/Client.h"
#include "util/net/PacketView.h"
#include "client/graph/Renderer.h"
-GameScene::GameScene(ClientState& state) : Scene(state),
- game(std::make_shared(state.game)),
- world(std::make_shared(game, state.connection, state.renderer)),
- debugGui(state.renderer.window.getSize(), game, world) {
+GameScene::GameScene(Client& client) : Scene(client),
+ world(std::make_shared(client.game, client.connection, client.renderer)),
+ debugGui(client.renderer.window.getSize(), client.game, world) {
Packet r(Packet::Type::CONNECT_DATA_RECVD);
- r.sendTo(state.connection.getPeer(), Packet::Channel::CONNECT);
+ r.sendTo(client.connection.getPeer(), Packet::Channel::CONNECT);
world.l()->connect();
- game .l()->init(world, world.l()->getPlayer(), state);
+ client.game->init(world, world.l()->getPlayer(), client);
world.l()->updatePlayerDimension();
- state.renderer.window.addResizeCallback("gamescene", Util::bind_this(&debugGui, &DebugGui::bufferResized));
- state.renderer.setClearColor(148, 194, 240);
- state.renderer.window.input.lockMouse(true);
+ client.renderer.window.addResizeCallback("gamescene", Util::bind_this(&debugGui, &DebugGui::bufferResized));
+ client.renderer.setClearColor(148, 194, 240);
+ client.renderer.window.input.lockMouse(true);
}
void GameScene::update() {
- Window& window = state.renderer.window;
+ Window& window = client.renderer.window;
- game.l()->update(state.delta);
- world->update(state.delta);
+ client.game->update(client.getDelta());
+ world->update(client.getDelta());
- for (auto entity : entities) entity->update(state.delta);
+ for (auto entity : entities) entity->update(client.getDelta());
- debugGui.update(world.l()->getPlayer().l(), state.fps, world.l()->getActiveDimension().l()->getMeshChunkCount(),
+ double lastFps = 1 / client.getDelta();
+ debugGui.update(world.l()->getPlayer().l(), lastFps, world.l()->getActiveDimension().l()->getMeshChunkCount(),
drawCalls, world.l()->getNet().serverSideChunkGens, world.l()->getNet().recvPackets);
world.l()->getNet().serverSideChunkGens = 0;
@@ -52,11 +52,11 @@ void GameScene::update() {
}
void GameScene::draw() {
- Renderer& renderer = state.renderer;
+ Renderer& renderer = client.renderer;
Camera& camera = renderer.camera;
renderer.beginChunkDeferredCalls();
- renderer.enableTexture(&game.l()->textures.atlasTexture);
+ renderer.enableTexture(&client.game->textures.atlasTexture);
drawCalls = world.l()->renderChunks(renderer);
@@ -67,7 +67,7 @@ void GameScene::draw() {
renderer.endDeferredCalls();
renderer.beginGUIDrawCalls();
- renderer.enableTexture(&game.l()->textures.atlasTexture);
+ renderer.enableTexture(&client.game->textures.atlasTexture);
world.l()->getPlayer().l()->drawHud(renderer);
debugGui.draw(renderer);
@@ -77,5 +77,5 @@ void GameScene::draw() {
}
void GameScene::cleanup() {
- state.renderer.window.removeResizeCallback("gamescene");
+ client.renderer.window.removeResizeCallback("gamescene");
}
diff --git a/src/client/scene/GameScene.h b/src/client/scene/GameScene.h
index f44b7eb8..6ccb8acf 100644
--- a/src/client/scene/GameScene.h
+++ b/src/client/scene/GameScene.h
@@ -17,14 +17,14 @@ class Drawable;
class GameScene : public Scene {
public:
- explicit GameScene(ClientState& state);
+ GameScene(Client& client);
void update() override;
void draw() override;
void cleanup() override;
+
public:
- SubgamePtr game;
WorldPtr world;
DebugGui debugGui;
diff --git a/src/client/scene/LuaErrorScene.cpp b/src/client/scene/LuaErrorScene.cpp
index 2596775c..8683faf1 100644
--- a/src/client/scene/LuaErrorScene.cpp
+++ b/src/client/scene/LuaErrorScene.cpp
@@ -4,18 +4,18 @@
#include "LuaErrorScene.h"
+#include "client/Client.h"
#include "client/graph/Font.h"
-#include "client/ClientState.h"
#include "client/graph/Renderer.h"
#include "client/gui/basic/GuiRect.h"
#include "client/gui/basic/GuiText.h"
-LuaErrorScene::LuaErrorScene(ClientState &state, const std::string &err) : Scene(state), err(err) {
- state.renderer.setClearColor(0, 0, 0);
- state.renderer.window.input.lockMouse(false);
+LuaErrorScene::LuaErrorScene(Client& client, const std::string &err) : Scene(client), err(err) {
+ client.renderer.setClearColor(0, 0, 0);
+ client.renderer.window.input.lockMouse(false);
- Font f(state.game.textures, state.game.textures["font"]);
- glm::ivec2 win = state.renderer.window.getSize();
+ Font f(client.game->textures, client.game->textures["font"]);
+ glm::ivec2 win = client.renderer.window.getSize();
auto container = std::make_shared("container");
container->create({800, 500}, {}, {0.05, 0.05, 0.05, 1});
@@ -34,22 +34,22 @@ LuaErrorScene::LuaErrorScene(ClientState &state, const std::string &err) : Scene
errorText->setPos({16, 48});
container->add(errorText);
- state.renderer.window.addResizeCallback("scene", [&](glm::ivec2 win) {
+ client.renderer.window.addResizeCallback("scene", [&](glm::ivec2 win) {
components.get("container")->setPos({win.x / 2 - 800 / 2, win.y / 2 - 500 / 2});
});
}
void LuaErrorScene::update() {
- state.game.textures.update();
+ client.game->textures.update();
}
void LuaErrorScene::draw() {
- Renderer& renderer = state.renderer;
+ Renderer& renderer = client.renderer;
renderer.beginChunkDeferredCalls();
renderer.endDeferredCalls();
renderer.beginGUIDrawCalls();
- renderer.enableTexture(&state.game.textures.atlasTexture);
+ renderer.enableTexture(&client.game->textures.atlasTexture);
components.draw(renderer);
@@ -57,5 +57,5 @@ void LuaErrorScene::draw() {
}
void LuaErrorScene::cleanup() {
- state.renderer.window.removeResizeCallback("scene");
+ client.renderer.window.removeResizeCallback("scene");
}
\ No newline at end of file
diff --git a/src/client/scene/LuaErrorScene.h b/src/client/scene/LuaErrorScene.h
index 21c3fa77..6ddb58e3 100644
--- a/src/client/scene/LuaErrorScene.h
+++ b/src/client/scene/LuaErrorScene.h
@@ -10,7 +10,7 @@
class LuaErrorScene : public Scene {
public:
- LuaErrorScene(ClientState& state, const std::string& err);
+ LuaErrorScene(Client& client, const std::string& err);
void update() override;
void draw() override;
diff --git a/src/client/scene/MainMenuScene.cpp b/src/client/scene/MainMenuScene.cpp
index 212f8dbe..4ca615a9 100644
--- a/src/client/scene/MainMenuScene.cpp
+++ b/src/client/scene/MainMenuScene.cpp
@@ -10,28 +10,32 @@
#include "MainMenuScene.h"
#include "util/Log.h"
-#include "client/ClientState.h"
+#include "client/Client.h"
#include "client/graph/Renderer.h"
#include "client/menu/SubgameDef.h"
#include "client/gui/basic/GuiText.h"
#include "game/atlas/asset/AtlasRef.h"
+#include "client/gui/basic/GuiContainer.h"
#include "client/gui/compound/GuiImageButton.h"
+#include "ConnectScene.h"
-MainMenuScene::MainMenuScene(ClientState& state) :
- Scene(state),
- sandbox(sandboxArea, state, menuContainer) {
+MainMenuScene::MainMenuScene(Client& client) :
+ Scene(client),
+ components(std::make_unique()),
+ menuContainer(std::make_shared("__menu")),
+ sandbox(sandboxArea, client, menuContainer) {
- state.renderer.setClearColor(0, 0, 0);
- state.renderer.window.input.lockMouse(false);
+ client.renderer.setClearColor(0, 0, 0);
+ client.renderer.window.input.lockMouse(false);
- Font f(state.game.textures, state.game.textures["font"]);
- win = state.renderer.window.getSize();
+ Font f(client.game->textures, client.game->textures["font"]);
+ win = client.renderer.window.getSize();
sandboxArea = win - glm::ivec2(0, 18 * GS);
- components.add(menuContainer);
+ components->add(menuContainer);
branding = std::make_shared("zephaBranding");
- components.add(branding);
+ components->add(branding);
{
auto zephaText = std::make_shared("zephaText");
zephaText->create({GS, GS}, {}, {}, {1, 1, 1, 1}, f);
@@ -51,34 +55,42 @@ MainMenuScene::MainMenuScene(ClientState& state) :
auto navigationBarIcons = navigationBar->get("navigationBarIcons");
- components.add(navigationBar);
+ components->add(navigationBar);
{
auto settingsButton = std::make_shared("settingsButton");
settingsButton->create({16 * GS, 16 * GS}, {},
- state.game.textures["crop(0, 0, 16, 16, menu_flag_settings)"],
- state.game.textures["crop(16, 0, 16, 16, menu_flag_settings)"]);
+ client.game->textures["crop(0, 0, 16, 16, menu_flag_settings)"],
+ client.game->textures["crop(16, 0, 16, 16, menu_flag_settings)"]);
+
navigationBar->get("navigationBarIcons")->add(settingsButton);
auto closeButton = std::make_shared("closeButton");
closeButton->create({16 * GS, 16 * GS}, {},
- state.game.textures["crop(0, 0, 16, 16, menu_flag_quit)"],
- state.game.textures["crop(16, 0, 16, 16, menu_flag_quit)"]);
+ client.game->textures["crop(0, 0, 16, 16, menu_flag_quit)"],
+ client.game->textures["crop(16, 0, 16, 16, menu_flag_quit)"]);
+
closeButton->setCallback(GuiComponent::CallbackType::PRIMARY, [](bool down, glm::ivec2) { if (down) exit(0); });
navigationBar->get("navigationBarIcons")->add(closeButton);
auto serversButton = std::make_shared("serversButton");
serversButton->create({16 * GS, 16 * GS}, {},
- state.game.textures["crop(0, 0, 16, 16, menu_flag_multiplayer)"],
- state.game.textures["crop(16, 0, 16, 16, menu_flag_multiplayer)"]);
+ client.game->textures["crop(0, 0, 16, 16, menu_flag_multiplayer)"],
+ client.game->textures["crop(16, 0, 16, 16, menu_flag_multiplayer)"]);
+
serversButton->setPos({GS, GS});
navigationBarIcons->add(serversButton);
auto contentButton = std::make_shared("contentButton");
contentButton->create({16 * GS, 16 * GS}, {},
- state.game.textures["crop(0, 0, 16, 16, menu_flag_content)"],
- state.game.textures["crop(16, 0, 16, 16, menu_flag_content)"]);
+ client.game->textures["crop(0, 0, 16, 16, menu_flag_content)"],
+ client.game->textures["crop(16, 0, 16, 16, menu_flag_content)"]);
+
contentButton->setPos({GS + GS * 18, GS});
- contentButton->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, glm::ivec2) { if (down) state.desiredState = "connect"; });
+ contentButton->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, glm::ivec2) {
+ if (!down) return;
+ client.scene.setScene(std::make_unique(client, Address { "127.0.0.1" }));
+ });
+
navigationBarIcons->add(contentButton);
auto divider = std::make_shared("divider");
@@ -91,16 +103,18 @@ MainMenuScene::MainMenuScene(ClientState& state) :
for (unsigned int i = 0; i < subgames.size(); i++) {
auto &subgame = subgames[i];
auto button = std::make_shared(subgame.config.name);
+
button->create({16 * GS, 16 * GS}, {},
- state.game.textures["crop(0, 0, 16, 16, " + subgame.iconRef->name + ")"],
- state.game.textures["crop(16, 0, 16, 16, " + subgame.iconRef->name + ")"]);
+ client.game->textures["crop(0, 0, 16, 16, " + subgame.iconRef->name + ")"],
+ client.game->textures["crop(16, 0, 16, 16, " + subgame.iconRef->name + ")"]);
+
button->setPos({GS * 7 + GS * 18 * (i + 2), GS});
- button->setCallback(GuiComponent::CallbackType::PRIMARY, [&, i](bool down, glm::ivec2) {
- if (down) {
- selectedSubgame = &subgame;
- sandbox.load(*selectedSubgame);
- }
+ button->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, glm::ivec2) {
+ if (!down) return;
+ selectedSubgame = &subgame;
+ sandbox.load(*selectedSubgame);
});
+
navigationBarIcons->add(button);
}
}
@@ -112,7 +126,7 @@ MainMenuScene::MainMenuScene(ClientState& state) :
positionElements();
- state.renderer.window.addResizeCallback("mainmenu", [&](glm::ivec2 win) {
+ client.renderer.window.addResizeCallback("mainmenu", [&](glm::ivec2 win) {
this->win = win;
sandboxArea = win - glm::ivec2(0, 18 * GS);
positionElements();
@@ -120,7 +134,7 @@ MainMenuScene::MainMenuScene(ClientState& state) :
}
void MainMenuScene::findSubgames() {
- std::string subgamesPath = state.path + "../subgames";
+ std::string subgamesPath = "../subgames";
cf_dir_t subgamesDir;
cf_dir_open(&subgamesDir, subgamesPath.data());
@@ -165,8 +179,8 @@ void MainMenuScene::findSubgames() {
std::string description = (j["description"].is_string() ? j["description"] : "");
std::string version = j["version"];
- std::shared_ptr icon = state.game.textures["menu_flag_missing"];
- if (hasIcon) icon = state.game.textures.loadImage(std::string(subgameFolder.path) + "/icon.png", name);
+ std::shared_ptr icon = client.game->textures["menu_flag_missing"];
+ if (hasIcon) icon = client.game->textures.loadImage(std::string(subgameFolder.path) + "/icon.png", name);
subgames.push_back({icon, {name, description, version}, subgameFolder.path});
}
@@ -191,7 +205,7 @@ void MainMenuScene::positionElements() {
auto navigationBarBg = navigationBar->get("navigationBarBg");
for (unsigned int i = 0; i < static_cast(win.x) / 64.f / GS; i++) {
auto segment = std::make_shared("segment_" + std::to_string(i));
- segment->create({64 * GS, 18 * GS}, {}, state.game.textures["menu_bar_bg"]);
+ segment->create({64 * GS, 18 * GS}, {}, client.game->textures["menu_bar_bg"]);
segment->setPos({i * 64 * GS, 0});
navigationBarBg->add(segment);
}
@@ -202,23 +216,23 @@ void MainMenuScene::positionElements() {
}
void MainMenuScene::update() {
- state.game.textures.update();
- sandbox.update(state.delta);
+ client.game->textures.update();
+ sandbox.update(client.getDelta());
- components.handleMouseInput(state.renderer.window);
+ components->handleMouseInput(client.renderer.window);
}
void MainMenuScene::draw() {
- state.renderer.beginChunkDeferredCalls();
- state.renderer.endDeferredCalls();
+ client.renderer.beginChunkDeferredCalls();
+ client.renderer.endDeferredCalls();
- state.renderer.beginGUIDrawCalls();
- state.renderer.enableTexture(&state.game.textures.atlasTexture);
- components.draw(state.renderer);
- state.renderer.swapBuffers();
+ client.renderer.beginGUIDrawCalls();
+ client.renderer.enableTexture(&client.game->textures.atlasTexture);
+ components->draw(client.renderer);
+ client.renderer.swapBuffers();
}
void MainMenuScene::cleanup() {
- state.renderer.window.setCursorHand(false);
- state.renderer.window.removeResizeCallback("mainmenu");
-}
+ client.renderer.window.setCursorHand(false);
+ client.renderer.window.removeResizeCallback("mainmenu");
+}
\ No newline at end of file
diff --git a/src/client/scene/MainMenuScene.h b/src/client/scene/MainMenuScene.h
index 22348188..d1ff20d9 100644
--- a/src/client/scene/MainMenuScene.h
+++ b/src/client/scene/MainMenuScene.h
@@ -8,13 +8,12 @@
#include "client/menu/SubgameDef.h"
#include "client/menu/MenuSandbox.h"
-#include "client/gui/basic/GuiContainer.h"
-class ClientState;
+class Client;
class MainMenuScene : public Scene {
public:
- explicit MainMenuScene(ClientState& state);
+ explicit MainMenuScene(Client& client);
void update() override;
void draw() override;
@@ -24,15 +23,15 @@ private:
void positionElements();
void findSubgames();
- const float GS = 3;
+ static constexpr float GS = 3;
glm::ivec2 win {};
glm::ivec2 sandboxArea {};
- GuiContainer components;
- std::shared_ptr branding = nullptr;
- std::shared_ptr navigationBar = nullptr;
- std::shared_ptr menuContainer = std::make_shared("__menu");
+ std::unique_ptr components;
+ std::shared_ptr branding;
+ std::shared_ptr navigationBar;
+ std::shared_ptr menuContainer;
MenuSandbox sandbox;
diff --git a/src/client/scene/Scene.h b/src/client/scene/Scene.h
index 6dbb0c9f..ad4a366c 100644
--- a/src/client/scene/Scene.h
+++ b/src/client/scene/Scene.h
@@ -1,14 +1,17 @@
-//
-// Created by aurailus on 06/01/19.
-//
+/*
+ * Scene abstract superclass, provides base scene methods for use by SceneManager.
+ * Stores a reference to the client, for children.
+ *
+ * - Auri, 03/11/20
+ */
#pragma once
-class ClientState;
+class Client;
class Scene {
public:
- explicit Scene(ClientState& state) : state(state) {}
+ explicit Scene(Client& client) : client(client) {}
virtual void update() = 0;
virtual void draw() = 0;
@@ -16,6 +19,6 @@ public:
virtual ~Scene() = default;
- ClientState& state;
+ Client& client;
};
diff --git a/src/client/scene/SceneManager.cpp b/src/client/scene/SceneManager.cpp
index 430868e2..07c61f7d 100644
--- a/src/client/scene/SceneManager.cpp
+++ b/src/client/scene/SceneManager.cpp
@@ -4,27 +4,55 @@
#include "SceneManager.h"
+
+/**
+ * Sets a new scene as the current scene.
+ * Cleans up the old scene.
+ * @param newScene - The new current scene.
+ */
+
+void SceneManager::setScene(std::unique_ptr newScene) {
+ cleanupScene();
+ scene = std::move(newScene);
+}
+
+
+/**
+ * Returns a reference to the current scene.
+ * @returns The current scene as a const reference.
+ */
+
+const Scene& SceneManager::getScene() {
+ return *scene;
+}
+
+
+/**
+ * Updates and renders the current scene, if there is one.
+ */
+
void SceneManager::update() {
+ if (!scene) return;
scene->update();
scene->draw();
}
-void SceneManager::setScene(std::unique_ptr scene) {
- if (this->scene != nullptr) cleanupScene();
- this->scene = std::move(scene);
-}
-Scene& SceneManager::getScene() {
- return *scene;
-}
+/**
+ * Cleans up the current scene and removes it.
+ * There will be no current scene after this method executes.
+ */
void SceneManager::cleanupScene() {
- if (scene != nullptr) {
- scene->cleanup();
- scene = nullptr;
- }
+ if (scene) scene->cleanup();
+ scene = nullptr;
}
+
+/*
+ * Clean up the scene on destruction.
+ */
+
SceneManager::~SceneManager() {
cleanupScene();
}
\ No newline at end of file
diff --git a/src/client/scene/SceneManager.h b/src/client/scene/SceneManager.h
index 565ac6ef..5583c321 100644
--- a/src/client/scene/SceneManager.h
+++ b/src/client/scene/SceneManager.h
@@ -10,15 +10,14 @@
class SceneManager {
public:
- SceneManager() = default;
-
void setScene(std::unique_ptr scene);
- Scene& getScene();
+ const Scene& getScene();
void update();
void cleanupScene();
~SceneManager();
+
private:
std::unique_ptr scene = nullptr;
};
diff --git a/src/game/LocalSubgame.cpp b/src/game/LocalSubgame.cpp
index 03421535..59ecb3b3 100644
--- a/src/game/LocalSubgame.cpp
+++ b/src/game/LocalSubgame.cpp
@@ -4,24 +4,42 @@
#include "LocalSubgame.h"
-LocalSubgame::LocalSubgame(const std::string& texPath) :
- texPath(texPath),
+
+/**
+ * Creates subgame instances, including the lua parser, and biome and block atlases.
+ * Also loads base assets into the texture atlas.
+ * @param baseAssets - The relative path to the base texture assets.
+ */
+
+LocalSubgame::LocalSubgame(const std::string& baseAssets) :
textures(2048),
lua(std::make_unique(*this)),
biomes(std::make_unique()),
defs(std::make_unique(textures)) {
- textures.loadDirectory(texPath);
+ textures.loadDirectory(baseAssets);
}
-void LocalSubgame::init(WorldPtr world, PlayerPtr player, ClientState& state) {
- lua->init(world, player, state);
+
+/**
+ * Initializes the Lua Parser.
+ * @param world - Passed in to the Lua Parser.
+ * @param player - Passed in to the Lua Parser.
+ * @param client - Passed in to the Lua Parser.
+ */
+
+void LocalSubgame::init(WorldPtr world, PlayerPtr player, Client& client) {
+ lua->init(world, player, client);
}
+
+/**
+ * Updates the lua parser and the texture atlas.
+ * @param delta - The last frame's delta time.
+ */
+
void LocalSubgame::update(double delta) {
lua->update(delta);
textures.update();
}
-
-LocalSubgame::~LocalSubgame() {}
diff --git a/src/game/LocalSubgame.h b/src/game/LocalSubgame.h
index b2fa90b9..f3031f2b 100644
--- a/src/game/LocalSubgame.h
+++ b/src/game/LocalSubgame.h
@@ -1,35 +1,32 @@
-//
-// The ClientGame class stores all of the subgame data for the client.
-// This data is used when in the GameScene. It is initialized when the client joins a game and cleared when they exit it.
-// The data within is in an undefined state until the init method is called.
-// Created by aurailus on 18/04/19.
-//
+/*
+ * The Local Subgame stores all local subgame data.
+ * Includes Block / Item definitions, biome definitions, the lua parser, models, and textures.
+ *
+ * - Auri, 03/11/20
+ */
#pragma once
#include "Subgame.h"
-#include "game/atlas/asset/ModelStore.h"
-#include "game/atlas/LocalBiomeAtlas.h"
-#include "game/atlas/LocalDefinitionAtlas.h"
-#include "game/atlas/TextureAtlas.h"
#include "util/CovariantPtr.h"
#include "lua/LocalLuaParser.h"
+#include "game/atlas/TextureAtlas.h"
+#include "game/atlas/LocalBiomeAtlas.h"
+#include "game/atlas/asset/ModelStore.h"
+#include "game/atlas/LocalDefinitionAtlas.h"
-class LocalPlayer;
+class Client;
class LocalWorld;
-class ClientState;
+class LocalPlayer;
class LocalSubgame : public Subgame {
public:
- explicit LocalSubgame(const std::string& texPath);
- ~LocalSubgame();
+ explicit LocalSubgame(const std::string& baseAssets);
- void init(WorldPtr world, PlayerPtr player, ClientState& state);
+ void init(WorldPtr world, PlayerPtr player, Client& client);
void update(double delta);
- std::string texPath;
-
LocalDefinitionAtlas& getDefs() override { return *defs; };
LocalBiomeAtlas& getBiomes() override { return *biomes; };
LocalLuaParser& getParser() override { return *lua; };
diff --git a/src/lua/LocalLuaParser.cpp b/src/lua/LocalLuaParser.cpp
index f32044c4..6afc35d3 100644
--- a/src/lua/LocalLuaParser.cpp
+++ b/src/lua/LocalLuaParser.cpp
@@ -4,8 +4,8 @@
#include "LocalLuaParser.h"
+#include "client/Client.h"
#include "ErrorFormatter.h"
-#include "client/ClientState.h"
#include "client/graph/Renderer.h"
#include "register/RegisterItems.h"
#include "register/RegisterBlocks.h"
@@ -33,12 +33,12 @@
LocalLuaParser::LocalLuaParser(LocalSubgame& game): LuaParser(game), keybinds(this) {}
-void LocalLuaParser::init(WorldPtr world, PlayerPtr player, ClientState& state) {
+void LocalLuaParser::init(WorldPtr world, PlayerPtr player, Client& client) {
lua.open_libraries(sol::lib::base, sol::lib::string, sol::lib::math, sol::lib::table, sol::lib::debug);
loadApi(world, player);
handler.executeMods(Util::bind_this(this, &LocalLuaParser::runFileSandboxed));
- state.renderer.window.input.setCallback(Util::bind_this(&keybinds, &LuaKeybindHandler::keybindHandler));
+ client.renderer.window.input.setCallback(Util::bind_this(&keybinds, &LuaKeybindHandler::keybindHandler));
registerDefs();
}
diff --git a/src/lua/LocalLuaParser.h b/src/lua/LocalLuaParser.h
index 3cfe81cd..d26d1968 100644
--- a/src/lua/LocalLuaParser.h
+++ b/src/lua/LocalLuaParser.h
@@ -4,21 +4,21 @@
#pragma once
-#include "LuaParser.h"
+#include "lua/LuaParser.h"
-#include "LocalModHandler.h"
-#include "LuaKeybindHandler.h"
-#include "../util/CovariantPtr.h"
+#include "util/CovariantPtr.h"
+#include "lua/LocalModHandler.h"
+#include "lua/LuaKeybindHandler.h"
-class LocalPlayer;
+class Client;
class LocalWorld;
-class ClientState;
+class LocalPlayer;
class LocalSubgame;
class LocalLuaParser : public LuaParser {
public:
explicit LocalLuaParser(LocalSubgame& game);
- void init(WorldPtr world, PlayerPtr player, ClientState& state);
+ void init(WorldPtr world, PlayerPtr player, Client& client);
void update(double delta) override;
diff --git a/src/lua/LuaParser.h b/src/lua/LuaParser.h
index f82ae475..8a1a3218 100644
--- a/src/lua/LuaParser.h
+++ b/src/lua/LuaParser.h
@@ -9,11 +9,10 @@
#include
#include
+#include "lua/Lua.h"
+#include "util/CovariantPtr.h"
#include "modules/SubgameModule.h"
-#include "Lua.h"
-#include "../util/CovariantPtr.h"
-
class Subgame;
class LuaParser {
diff --git a/src/lua/modules/mStartGame.h b/src/lua/modules/mStartGame.h
index 9da36f4e..f56ea043 100644
--- a/src/lua/modules/mStartGame.h
+++ b/src/lua/modules/mStartGame.h
@@ -4,21 +4,23 @@
#pragma once
-#include "../Lua.h"
-#include "client/ClientState.h"
+#include "lua/Lua.h"
+#include "client/Client.h"
+#include "util/net/Address.h"
+#include "client/scene/ConnectScene.h"
namespace MenuApi {
- void start_game(ClientState& state, sol::table& core) {
+ void start_game(Client& client, sol::table& core) {
//TODO: Don't hardcode the subgame
- core.set_function("start_game", [&]() {
- state.subgame = "zeus";
- state.desiredState = "connect";
+ core.set_function("game_connect", [&](std::string address) {
+ client.scene.setScene(std::make_unique(client, Address::fromString(address)));
});
- core.set_function("start_game_local", [&]() {
- state.subgame = "zeus";
- state.desiredState = "local";
+ core.set_function("game_host", [&](sol::this_state s) {
+ sol::state_view state(s);
+ const auto subgame = state.get("zepha.__builtin.subgame");
+ client.startLocalServer(subgame);
});
}
}
\ No newline at end of file
diff --git a/src/util/CovariantPtr.h b/src/util/CovariantPtr.h
index 34623540..30096113 100644
--- a/src/util/CovariantPtr.h
+++ b/src/util/CovariantPtr.h
@@ -41,6 +41,7 @@ class ServerInventoryRefs;
template
class CovariantPtr {
std::shared_ptr b = nullptr;
+
public:
CovariantPtr() = default;
CovariantPtr(std::nullptr_t) {};
diff --git a/src/util/net/Address.cpp b/src/util/net/Address.cpp
new file mode 100644
index 00000000..1b4e373d
--- /dev/null
+++ b/src/util/net/Address.cpp
@@ -0,0 +1,36 @@
+//
+// Created by auri on 2020-11-03.
+//
+
+#include
+
+#include "Address.h"
+
+
+/**
+ * Returns an Address object from the provided address string.
+ * Address string should be in standard dot + optional colon notation, e.g: 192.168.0.1:8000, 127.0.0.1.
+ * @throws std::invalid_argument - There is a value after a colon that cannot be converted into a valid numeric value.
+ * @throws std::out_of_range - There is a numeric port specified, but it is greater than the maximum unsigned short.
+ * @param addressString - The string to parse.
+ * @returns - An Address object with the specified address.
+ */
+
+Address Address::fromString(const std::string &addressString) {
+ std::string address;
+ unsigned short port;
+
+ size_t sep = addressString.find(':');
+ if (sep == std::string::npos) {
+ address = address;
+ port = Address::DEFAULT_PORT;
+ }
+ else {
+ address = addressString.substr(0, sep++); // Increment sep for next substr call.
+ unsigned int p = stoi(addressString.substr(sep, addressString.length() - sep));
+ if (p > 65535) throw std::out_of_range("Port value is greater than 65535.");
+ port = static_cast(p);
+ }
+
+ return Address { address, port };
+}
diff --git a/src/util/net/Address.h b/src/util/net/Address.h
index f4953179..6dcfb9ed 100644
--- a/src/util/net/Address.h
+++ b/src/util/net/Address.h
@@ -8,5 +8,9 @@
struct Address {
std::string host;
- unsigned short port;
+ unsigned short port = Address::DEFAULT_PORT;
+
+ static Address fromString(const std::string& addressString);
+
+ constexpr static unsigned short DEFAULT_PORT = 13110;
};