Skip to content

Commit

Permalink
[ChatCommandHandler] '/save' and '/load' commands added.
Browse files Browse the repository at this point in the history
  • Loading branch information
Unarelith committed Mar 17, 2020
1 parent bc3226e commit ef79c5b
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,11 +104,11 @@ This list is non exhaustive.
- Block metadata
- Player model display (currently without rotation nor animation)
- Dimensions (like the Nether or the Ender in Minecraft) ([#80](https://github.com/Unarelith/OpenMiner/pull/80))
- World loading/saving (using `/save <name>` and `/load <name>` commands, see [#26](https://github.com/Unarelith/OpenMiner/issues/26))

### Missing features

- Texture pack system ([#34](https://github.com/Unarelith/OpenMiner/issues/34))
- World loading/saving ([#26](https://github.com/Unarelith/OpenMiner/issues/26))
- Fluid propagation ([#62](https://github.com/Unarelith/OpenMiner/issues/62))
- Day/night cycle with sun/moon display ([#73](https://github.com/Unarelith/OpenMiner/issues/73))
- Real worldgen (seed-based, cave tunnels) ([#79](https://github.com/Unarelith/OpenMiner/issues/79))
Expand Down
31 changes: 30 additions & 1 deletion source/server/network/ChatCommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "ChatCommandHandler.hpp"
#include "ClientInfo.hpp"
#include "ServerCommandHandler.hpp"
#include "WorldController.hpp"

void ChatCommandHandler::parseCommand(const std::string &str, ClientInfo &client) const {
std::stringstream sstream;
Expand All @@ -42,7 +43,9 @@ void ChatCommandHandler::parseCommand(const std::string &str, ClientInfo &client
}

std::unordered_map<std::string, decltype(&ChatCommandHandler::teleportationCommand)> commands = {
{"tp", &ChatCommandHandler::teleportationCommand}
{"tp", &ChatCommandHandler::teleportationCommand},
{"save", &ChatCommandHandler::saveCommand},
{"load", &ChatCommandHandler::loadCommand},
};

if (!command.empty()) {
Expand Down Expand Up @@ -82,3 +85,29 @@ void ChatCommandHandler::teleportationCommand(const std::vector<std::string> &co
}
}

void ChatCommandHandler::saveCommand(const std::vector<std::string> &command, ClientInfo &client) const {
if (command.size() != 2) {
m_server.sendChatMessage(0, "Usage: /save <name>", &client);
}
else {
std::string name = command.at(1);

m_worldController.save(name);

m_server.sendChatMessage(0, "Saved '" + name + "'", &client);
}
}

void ChatCommandHandler::loadCommand(const std::vector<std::string> &command, ClientInfo &client) const {
if (command.size() != 2) {
m_server.sendChatMessage(0, "Usage: /load <name>", &client);
}
else {
std::string name = command.at(1);

m_worldController.load(name);

m_server.sendChatMessage(0, "Loaded '" + name + "'", &client);
}
}

7 changes: 6 additions & 1 deletion source/server/network/ChatCommandHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,22 @@

class ClientInfo;
class ServerCommandHandler;
class WorldController;

class ChatCommandHandler {
public:
ChatCommandHandler(ServerCommandHandler &server) : m_server(server) {}
ChatCommandHandler(ServerCommandHandler &server, WorldController &worldController)
: m_server(server), m_worldController(worldController) {}

void parseCommand(const std::string &str, ClientInfo &client) const;

private:
void teleportationCommand(const std::vector<std::string> &command, ClientInfo &client) const;
void saveCommand(const std::vector<std::string> &command, ClientInfo &client) const;
void loadCommand(const std::vector<std::string> &command, ClientInfo &client) const;

ServerCommandHandler &m_server;
WorldController &m_worldController;
};

#endif // CHATCOMMANDHANDLER_HPP_
2 changes: 1 addition & 1 deletion source/server/network/ServerCommandHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class ServerCommandHandler {

gk::Vector3d m_spawnPosition{14.5, 14.5, 18.};

ChatCommandHandler m_chatCommandHandler{*this};
ChatCommandHandler m_chatCommandHandler{*this, m_worldController};
};

#endif // SERVERCOMMANDHANDLER_HPP_
90 changes: 90 additions & 0 deletions source/server/world/WorldController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
*
* =====================================================================================
*/
#include <fstream>

#include "Registry.hpp"
#include "WorldController.hpp"

Expand All @@ -39,3 +41,91 @@ void WorldController::update() {
it.update();
}

void WorldController::load(const std::string &name) {
// std::cout << "Loading '" + name + "'..." << std::endl;

std::ifstream file(name + ".dat", std::ofstream::binary);

if (file.is_open()) {
file.seekg(0, file.end);
int length = file.tellg();
file.seekg(0, file.beg);

char *buffer = new char[length];
file.read(buffer, length);

sf::Packet save;
save.append(buffer, length);

delete[] buffer;

for (auto &world : m_worldList) {
unsigned int chunkCount;
save >> chunkCount;

// std::cout << "Dimension " << world.dimension().id() << " chunk count: " << chunkCount << std::endl;

for (unsigned int i = 0 ; i < chunkCount ; ++i) {
int cx, cy, cz;
save >> cx >> cy >> cz;

ServerChunk &chunk = world.createChunk(cx, cy, cz);
for (u8 z = 0 ; z < Chunk::height ; ++z) {
for (u8 y = 0 ; y < Chunk::depth ; ++y) {
for (u8 x = 0 ; x < Chunk::width ; ++x) {
u32 data;
u8 light;
save >> data >> light;

chunk.setBlockRaw(x, y, z, data & 0xffff);
chunk.setData(x, y, z, data >> 16);
chunk.lightmap().setLightData(x, y, z, light);
}
}
}

chunk.setInitialized(true);
chunk.setSent(false);
}
}
}

// std::cout << "Loading done." << std::endl;
}

void WorldController::save(const std::string &name) {
// std::cout << "Saving '" << name << "'..." << std::endl;

std::ofstream file(name + ".dat", std::ofstream::binary | std::ofstream::trunc);

sf::Packet save;
for (auto &world : m_worldList) {
sf::Packet chunks;
unsigned int chunkCount = 0;
for (auto &chunk : world.chunks()) {
if (!chunk.second->isInitialized()) continue;

const gk::Vector3i &chunkpos = chunk.first;
const Chunk::DataArray &data = chunk.second->data();
chunks << chunkpos.x << chunkpos.y << chunkpos.z;

for (u8 z = 0 ; z < Chunk::height ; ++z) {
for (u8 y = 0 ; y < Chunk::depth ; ++y) {
for (u8 x = 0 ; x < Chunk::width ; ++x) {
chunks << u32(data[z][y][x])
<< u8(chunk.second->lightmap().getLightData(x, y, z));
}
}
}

++chunkCount;
}

// std::cout << "Saving dimension " << world.dimension().id() << ". Chunk count: " << chunkCount << std::endl;

save << chunkCount;
save.append(chunks.getData(), chunks.getDataSize());
}

file.write((const char *)save.getData(), save.getDataSize());
}
3 changes: 3 additions & 0 deletions source/server/world/WorldController.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ class WorldController {

void update();

void load(const std::string &name);
void save(const std::string &name);

ServerWorld &getWorld(u16 dimension) { return m_worldList.at(dimension); }

void setServer(ServerCommandHandler &server) { m_server = &server; }
Expand Down

0 comments on commit ef79c5b

Please sign in to comment.