#define BLANK_SERVER_SERVER_HPP
#include "../app/Config.hpp"
+#include "../world/World.hpp"
#include "../world/WorldManipulator.hpp"
#include <list>
namespace blank {
+class ChunkIndex;
class CompositeModel;
-class World;
+class Player;
class WorldSave;
namespace server {
: public WorldManipulator {
public:
- Server(const Config::Network &, World &, const WorldSave &);
+ Server(const Config::Network &, World &, const World::Config &, const WorldSave &);
~Server();
void Handle();
bool HasPlayerModel() const noexcept;
const CompositeModel &GetPlayerModel() const noexcept;
+ Player *JoinPlayer(const std::string &name);
+
void SetBlock(Chunk &, int, const Block &) override;
private:
std::list<ClientConnection> clients;
World &world;
+ ChunkIndex &spawn_index;
const WorldSave &save;
const CompositeModel *player_model;
#include "../app/Environment.hpp"
#include "../app/TextureIndex.hpp"
+#include "../io/WorldSave.hpp"
#include "../net/io.hpp"
#include <iostream>
: env(env)
, block_types()
, world(block_types, wc)
-, spawn_index(world.Chunks().MakeIndex(wc.spawn, 3))
, generator(gc)
, chunk_loader(world.Chunks(), generator, ws)
, skeletons()
, spawner(world, skeletons, env.rng)
-, server(config.net, world, ws)
+, server(config.net, world, wc, ws)
, loop_timer(16) {
TextureIndex tex_index;
env.loader.LoadBlockTypes("default", block_types, tex_index);
}
ServerState::~ServerState() {
- world.Chunks().UnregisterIndex(spawn_index);
+
}
void ServerState::Handle(const SDL_Event &event) {
if (event.type == SDL_QUIT) {
+ std::cout << "saving remaining chunks" << std::endl;
+ for (Chunk &chunk : world.Chunks()) {
+ if (chunk.ShouldUpdateSave()) {
+ chunk_loader.SaveFile().Write(chunk);
+ }
+ }
env.state.PopAll();
}
}
#include "../app/State.hpp"
#include "../model/Skeletons.hpp"
#include "../world/BlockTypeRegistry.hpp"
-#include "../world/ChunkIndex.hpp"
#include "../world/ChunkLoader.hpp"
#include "../world/Generator.hpp"
#include "../world/World.hpp"
HeadlessEnvironment &env;
BlockTypeRegistry block_types;
World world;
- ChunkIndex &spawn_index;
Generator generator;
ChunkLoader chunk_loader;
Skeletons skeletons;
DetachPlayer();
input.reset(new DirectInput(server.GetWorld(), player, server));
PlayerEntity().Ref();
- if (server.GetWorldSave().Exists(player)) {
- server.GetWorldSave().Read(player);
- } else {
- // TODO: spawn
- }
old_base = PlayerChunks().Base();
Chunk::Pos begin = PlayerChunks().CoordsBegin();
}
}
}
+ // TODO: should the server do this?
if (HasPlayerModel()) {
GetPlayerModel().Instantiate(PlayerEntity().GetModel());
}
string name;
pack.ReadPlayerName(name);
- Player *new_player = server.GetWorld().AddPlayer(name);
+ Player *new_player = server.JoinPlayer(name);
if (new_player) {
// success!
}
-Server::Server(const Config::Network &conf, World &world, const WorldSave &save)
+Server::Server(
+ const Config::Network &conf,
+ World &world,
+ const World::Config &wc,
+ const WorldSave &save)
: serv_sock(nullptr)
, serv_pack{ -1, nullptr, 0 }
, clients()
, world(world)
+, spawn_index(world.Chunks().MakeIndex(wc.spawn, 3))
, save(save)
, player_model(nullptr) {
serv_sock = SDLNet_UDP_Open(conf.port);
}
Server::~Server() {
+ world.Chunks().UnregisterIndex(spawn_index);
delete[] serv_pack.data;
SDLNet_UDP_Close(serv_sock);
}
return *player_model;
}
+Player *Server::JoinPlayer(const string &name) {
+ if (spawn_index.MissingChunks() > 0) {
+ return nullptr;
+ }
+ Player *player = world.AddPlayer(name);
+ if (!player) {
+ return nullptr;
+ }
+ if (save.Exists(*player)) {
+ save.Read(*player);
+ } else {
+ // TODO: spawn
+ }
+ return player;
+}
+
void Server::SetBlock(Chunk &chunk, int index, const Block &block) {
chunk.SetBlock(index, block);
// TODO: batch chunk changes