summaryrefslogtreecommitdiffstats
path: root/game
diff options
context:
space:
mode:
Diffstat (limited to 'game')
-rw-r--r--game/client/receive.cc12
-rw-r--r--game/client/session.cc4
-rw-r--r--game/server/game.cc3
-rw-r--r--game/server/overworld.cc67
-rw-r--r--game/server/sessions.cc10
-rw-r--r--game/server/worldgen.cc19
-rw-r--r--game/server/worldgen.hh5
-rw-r--r--game/shared/feature.cc16
-rw-r--r--game/shared/feature.hh6
-rw-r--r--game/shared/item_registry.cc14
-rw-r--r--game/shared/item_registry.hh5
-rw-r--r--game/shared/protocol.cc8
-rw-r--r--game/shared/protocol.hh4
-rw-r--r--game/shared/voxel_registry.cc2
-rw-r--r--game/shared/voxel_registry.hh2
15 files changed, 125 insertions, 52 deletions
diff --git a/game/client/receive.cc b/game/client/receive.cc
index 5b053d0..ab1cd62 100644
--- a/game/client/receive.cc
+++ b/game/client/receive.cc
@@ -12,6 +12,7 @@
#include "client/factory.hh"
#include "client/globals.hh"
#include "client/gui_screen.hh"
+#include "client/message_box.hh"
#include "client/session.hh"
#include "client/sound.hh"
#include "client/window_title.hh"
@@ -33,6 +34,17 @@ static bool synchronize_entity_id(Dimension *dimension, entt::entity entity)
session::disconnect("protocol.entity_id_desync");
spdlog::critical("receive: entity desync: network {} resolved as client {}",
static_cast<std::uint64_t>(entity), static_cast<std::uint64_t>(created));
+
+ message_box::reset();
+ message_box::set_title("disconnected.disconnected");
+ message_box::set_subtitle("protocol.entity_id_desync");
+ message_box::add_button("disconnected.back", [](void) {
+ globals::gui_screen = GUI_PLAY_MENU;
+ window_title::update();
+ });
+
+ globals::gui_screen = GUI_MESSAGE_BOX;
+
return false;
}
diff --git a/game/client/session.cc b/game/client/session.cc
index 4c4d06b..b5ed12a 100644
--- a/game/client/session.cc
+++ b/game/client/session.cc
@@ -7,6 +7,7 @@
#include "shared/coord.hh"
#include "shared/dimension.hh"
#include "shared/head.hh"
+#include "shared/item_registry.hh"
#include "shared/player.hh"
#include "shared/protocol.hh"
#include "shared/transform.hh"
@@ -275,7 +276,8 @@ void session::send_login_request(void)
{
protocol::LoginRequest packet;
packet.version = protocol::VERSION;
- packet.voxel_def_checksum = voxel_registry::checksum();
+ packet.voxel_registry_checksum = voxel_registry::calcualte_checksum();
+ packet.item_registry_checksum = item_registry::calcualte_checksum();
packet.password_hash = server_password_hash;
packet.username = client_game::username.get();
diff --git a/game/server/game.cc b/game/server/game.cc
index cc5baf8..c6fc67f 100644
--- a/game/server/game.cc
+++ b/game/server/game.cc
@@ -28,6 +28,7 @@
#include "server/universe.hh"
#include "server/unloader.hh"
#include "server/whitelist.hh"
+#include "server/worldgen.hh"
ConfigUnsigned server_game::view_distance(4U, 4U, 32U);
@@ -55,6 +56,8 @@ void server_game::init(void)
server_chat::init();
server_recieve::init();
+ worldgen::init();
+
unloader::init();
universe::init();
}
diff --git a/game/server/overworld.cc b/game/server/overworld.cc
index 78747fc..608fd01 100644
--- a/game/server/overworld.cc
+++ b/game/server/overworld.cc
@@ -1,6 +1,8 @@
#include "server/pch.hh"
#include "server/overworld.hh"
+#include "core/vectors.hh"
+
#include "shared/coord.hh"
#include "shared/game_voxels.hh"
#include "shared/voxel_storage.hh"
@@ -11,9 +13,12 @@ static void compute_tree_feature(unsigned int height, Feature &feature, voxel_id
// Ensure the tree height is too small
height = cxpr::max<unsigned int>(height, 4U);
+ // Put down a single piece of dirt
+ feature.push_back({ voxel_pos(0, -1, 0), game_voxels::dirt, true });
+
// Generate tree stem
for(unsigned int i = 0; i < height; ++i) {
- feature.push_back({ voxel_pos(0, i, 0), log_voxel });
+ feature.push_back({ voxel_pos(0, i, 0), log_voxel, true });
}
auto leaves_start = height - 3U;
@@ -23,43 +28,43 @@ static void compute_tree_feature(unsigned int height, Feature &feature, voxel_id
// Generate the thin 3x3 layer of leaves that
// starts from leaves_start and ends at leaves_thin_end
for(unsigned int i = leaves_start; i <= leaves_thin_end; ++i) {
- feature.push_back({ local_pos(-1, i, -1), leaves_voxel });
- feature.push_back({ local_pos(-1, i, +0), leaves_voxel });
- feature.push_back({ local_pos(-1, i, +1), leaves_voxel });
- feature.push_back({ local_pos(+0, i, -1), leaves_voxel });
- feature.push_back({ local_pos(+0, i, +1), leaves_voxel });
- feature.push_back({ local_pos(+1, i, -1), leaves_voxel });
- feature.push_back({ local_pos(+1, i, +0), leaves_voxel });
- feature.push_back({ local_pos(+1, i, +1), leaves_voxel });
+ feature.push_back({ local_pos(-1, i, -1), leaves_voxel, false });
+ feature.push_back({ local_pos(-1, i, +0), leaves_voxel, false });
+ feature.push_back({ local_pos(-1, i, +1), leaves_voxel, false });
+ feature.push_back({ local_pos(+0, i, -1), leaves_voxel, false });
+ feature.push_back({ local_pos(+0, i, +1), leaves_voxel, false });
+ feature.push_back({ local_pos(+1, i, -1), leaves_voxel, false });
+ feature.push_back({ local_pos(+1, i, +0), leaves_voxel, false });
+ feature.push_back({ local_pos(+1, i, +1), leaves_voxel, false });
}
// Generate the tree cap; a 3x3 patch of leaves
// that is slapped right on top of the thin 3x3 layer
- feature.push_back({ local_pos(-1, height, +0), leaves_voxel });
- feature.push_back({ local_pos(+0, height, -1), leaves_voxel });
- feature.push_back({ local_pos(+0, height, +0), leaves_voxel });
- feature.push_back({ local_pos(+0, height, +1), leaves_voxel });
- feature.push_back({ local_pos(+1, height, +0), leaves_voxel });
+ feature.push_back({ local_pos(-1, height, +0), leaves_voxel, false });
+ feature.push_back({ local_pos(+0, height, -1), leaves_voxel, false });
+ feature.push_back({ local_pos(+0, height, +0), leaves_voxel, false });
+ feature.push_back({ local_pos(+0, height, +1), leaves_voxel, false });
+ feature.push_back({ local_pos(+1, height, +0), leaves_voxel, false });
// Generate the thin 5x5 layer of leaves that
// starts from leaves_start and ends at leaves_thin_end
for(unsigned int i = leaves_start; i <= leaves_thick_end; ++i) {
- feature.push_back({ local_pos(-1, i, -2), leaves_voxel });
- feature.push_back({ local_pos(-1, i, +2), leaves_voxel });
- feature.push_back({ local_pos(-2, i, -1), leaves_voxel });
- feature.push_back({ local_pos(-2, i, -2), leaves_voxel });
- feature.push_back({ local_pos(-2, i, +0), leaves_voxel });
- feature.push_back({ local_pos(-2, i, +1), leaves_voxel });
- feature.push_back({ local_pos(-2, i, +2), leaves_voxel });
- feature.push_back({ local_pos(+0, i, -2), leaves_voxel });
- feature.push_back({ local_pos(+0, i, +2), leaves_voxel });
- feature.push_back({ local_pos(+1, i, -2), leaves_voxel });
- feature.push_back({ local_pos(+1, i, +2), leaves_voxel });
- feature.push_back({ local_pos(+2, i, -1), leaves_voxel });
- feature.push_back({ local_pos(+2, i, -2), leaves_voxel });
- feature.push_back({ local_pos(+2, i, +0), leaves_voxel });
- feature.push_back({ local_pos(+2, i, +1), leaves_voxel });
- feature.push_back({ local_pos(+2, i, +2), leaves_voxel });
+ feature.push_back({ local_pos(-1, i, -2), leaves_voxel, false });
+ feature.push_back({ local_pos(-1, i, +2), leaves_voxel, false });
+ feature.push_back({ local_pos(-2, i, -1), leaves_voxel, false });
+ feature.push_back({ local_pos(-2, i, -2), leaves_voxel, false });
+ feature.push_back({ local_pos(-2, i, +0), leaves_voxel, false });
+ feature.push_back({ local_pos(-2, i, +1), leaves_voxel, false });
+ feature.push_back({ local_pos(-2, i, +2), leaves_voxel, false });
+ feature.push_back({ local_pos(+0, i, -2), leaves_voxel, false });
+ feature.push_back({ local_pos(+0, i, +2), leaves_voxel, false });
+ feature.push_back({ local_pos(+1, i, -2), leaves_voxel, false });
+ feature.push_back({ local_pos(+1, i, +2), leaves_voxel, false });
+ feature.push_back({ local_pos(+2, i, -1), leaves_voxel, false });
+ feature.push_back({ local_pos(+2, i, -2), leaves_voxel, false });
+ feature.push_back({ local_pos(+2, i, +0), leaves_voxel, false });
+ feature.push_back({ local_pos(+2, i, +1), leaves_voxel, false });
+ feature.push_back({ local_pos(+2, i, +2), leaves_voxel, false });
}
}
@@ -216,7 +221,7 @@ const Overworld_Metadata &Overworld::get_or_create_metadata(const chunk_pos_xz &
auto is_unique = true;
for(const auto &check_lpos : metadata.trees) {
- if(check_lpos == lpos) {
+ if(cxvectors::distance2(check_lpos, lpos) <= 9) {
is_unique = false;
break;
}
diff --git a/game/server/sessions.cc b/game/server/sessions.cc
index f2e643d..58f12d4 100644
--- a/game/server/sessions.cc
+++ b/game/server/sessions.cc
@@ -11,6 +11,7 @@
#include "shared/dimension.hh"
#include "shared/factory.hh"
#include "shared/head.hh"
+#include "shared/item_registry.hh"
#include "shared/player.hh"
#include "shared/protocol.hh"
#include "shared/transform.hh"
@@ -56,13 +57,20 @@ static void on_login_request_packet(const protocol::LoginRequest &packet)
// FIXME: calculate voxel registry checksum ahead of time
// instead of figuring it out every time a new player connects
- if(packet.voxel_def_checksum != voxel_registry::checksum()) {
+ if(packet.voxel_registry_checksum != voxel_registry::calcualte_checksum()) {
protocol::Disconnect response;
response.reason = "protocol.voxel_registry_checksum";
protocol::send(packet.peer, protocol::encode(response));
return;
}
+ if(packet.item_registry_checksum != item_registry::calcualte_checksum()) {
+ protocol::Disconnect response;
+ response.reason = "protocol.item_registry_checksum";
+ protocol::send(packet.peer, protocol::encode(response));
+ return;
+ }
+
// Don't assign new usernames and just kick the player if
// an another client using the same username is already connected
// and playing; since we have a whitelist, adding "(1)" isn't feasible anymore
diff --git a/game/server/worldgen.cc b/game/server/worldgen.cc
index 83fddbb..4fc37c7 100644
--- a/game/server/worldgen.cc
+++ b/game/server/worldgen.cc
@@ -1,13 +1,19 @@
#include "server/pch.hh"
#include "server/worldgen.hh"
+#include "core/config.hh"
+
#include "shared/chunk.hh"
#include "shared/dimension.hh"
#include "shared/protocol.hh"
#include "shared/threading.hh"
+#include "server/globals.hh"
+#include "server/inhabited.hh"
#include "server/sessions.hh"
+static ConfigBoolean aggressive_caching(false);
+
static emhash8::HashMap<Dimension *, emhash8::HashMap<chunk_pos, std::unordered_set<Session *>>> active_tasks;
class WorldgenTask final : public Task {
@@ -60,6 +66,14 @@ void WorldgenTask::finalize(void)
auto chunk = m_dimension->create_chunk(m_cpos);
chunk->set_voxels(m_voxels);
+ if(aggressive_caching.get_value()) {
+ // Marking the chunk with InhabitedComponent makes
+ // it so that it is saved regardles of whether it was
+ // modified by players or not. This isn't particularly
+ // good for server-side disk usage but it might improve performance
+ m_dimension->chunks.emplace<InhabitedComponent>(chunk->get_entity());
+ }
+
protocol::ChunkVoxels response;
response.voxels = m_voxels;
response.chunk = m_cpos;
@@ -84,6 +98,11 @@ void WorldgenTask::finalize(void)
}
}
+void worldgen::init(void)
+{
+ globals::server_config.add_value("worldgen.aggressive_caching", aggressive_caching);
+}
+
bool worldgen::is_generating(Dimension *dimension, const chunk_pos &cpos)
{
auto dim_tasks = active_tasks.find(dimension);
diff --git a/game/server/worldgen.hh b/game/server/worldgen.hh
index 3153071..7fb08b9 100644
--- a/game/server/worldgen.hh
+++ b/game/server/worldgen.hh
@@ -9,6 +9,11 @@ class Session;
namespace worldgen
{
+void init(void);
+} // namespace worldgen
+
+namespace worldgen
+{
bool is_generating(Dimension *dimension, const chunk_pos &cpos);
void request_chunk(Session *session, const chunk_pos &cpos);
} // namespace worldgen
diff --git a/game/shared/feature.cc b/game/shared/feature.cc
index 6f884b2..845bb40 100644
--- a/game/shared/feature.cc
+++ b/game/shared/feature.cc
@@ -6,10 +6,10 @@
#include "shared/dimension.hh"
#include "shared/voxel_storage.hh"
-void Feature::place(const voxel_pos &vpos, Dimension *dimension, bool overwrite) const
+void Feature::place(const voxel_pos &vpos, Dimension *dimension) const
{
- for(const auto &it : (*this)) {
- auto it_vpos = vpos + it.first;
+ for(const auto [rpos, voxel, overwrite] : (*this)) {
+ auto it_vpos = vpos + rpos;
auto it_cpos = coord::to_chunk(it_vpos);
if(auto chunk = dimension->create_chunk(it_cpos)) {
@@ -23,15 +23,15 @@ void Feature::place(const voxel_pos &vpos, Dimension *dimension, bool overwrite)
continue;
}
- chunk->set_voxel(it.second, it_index);
+ chunk->set_voxel(voxel, it_index);
}
}
}
-void Feature::place(const voxel_pos &vpos, const chunk_pos &cpos, VoxelStorage &voxels, bool overwrite) const
+void Feature::place(const voxel_pos &vpos, const chunk_pos &cpos, VoxelStorage &voxels) const
{
- for(const auto &it : (*this)) {
- auto it_vpos = vpos + it.first;
+ for(const auto [rpos, voxel, overwrite] : (*this)) {
+ auto it_vpos = vpos + rpos;
auto it_cpos = coord::to_chunk(it_vpos);
if(it_cpos == cpos) {
@@ -45,7 +45,7 @@ void Feature::place(const voxel_pos &vpos, const chunk_pos &cpos, VoxelStorage &
continue;
}
- voxels[it_index] = it.second;
+ voxels[it_index] = voxel;
}
}
}
diff --git a/game/shared/feature.hh b/game/shared/feature.hh
index f5fe73b..b5cb262 100644
--- a/game/shared/feature.hh
+++ b/game/shared/feature.hh
@@ -7,14 +7,14 @@
class Dimension;
class VoxelStorage;
-class Feature final : public std::vector<std::pair<voxel_pos, voxel_id>> {
+class Feature final : public std::vector<std::tuple<voxel_pos, voxel_id, bool>> {
public:
explicit Feature(void) = default;
virtual ~Feature(void) = default;
public:
- void place(const voxel_pos &vpos, Dimension *dimension, bool overwrite = false) const;
- void place(const voxel_pos &vpos, const chunk_pos &cpos, VoxelStorage &voxels, bool overwrite = false) const;
+ void place(const voxel_pos &vpos, Dimension *dimension) const;
+ void place(const voxel_pos &vpos, const chunk_pos &cpos, VoxelStorage &voxels) const;
};
#endif /* SHARED_FEATURE_HH */
diff --git a/game/shared/item_registry.cc b/game/shared/item_registry.cc
index 02164bd..23dffdc 100644
--- a/game/shared/item_registry.cc
+++ b/game/shared/item_registry.cc
@@ -1,6 +1,8 @@
#include "shared/pch.hh"
#include "shared/item_registry.hh"
+#include "core/crc64.hh"
+
#include "shared/voxel_registry.hh"
std::unordered_map<std::string, ItemInfoBuilder> item_registry::builders = {};
@@ -78,3 +80,15 @@ void item_registry::purge(void)
item_registry::names.clear();
item_registry::items.clear();
}
+
+std::uint64_t item_registry::calcualte_checksum(void)
+{
+ std::uint64_t result = 0;
+
+ for(const auto &info : item_registry::items) {
+ result = crc64::get(info->name, result);
+ result += static_cast<std::uint64_t>(info->place_voxel);
+ }
+
+ return result;
+}
diff --git a/game/shared/item_registry.hh b/game/shared/item_registry.hh
index 7160b0b..83b6053 100644
--- a/game/shared/item_registry.hh
+++ b/game/shared/item_registry.hh
@@ -54,4 +54,9 @@ namespace item_registry
void purge(void);
} // namespace item_registry
+namespace item_registry
+{
+std::uint64_t calcualte_checksum(void);
+} // namespace item_registry
+
#endif /* SHARED_ITEM_REGISTRY_HH */
diff --git a/game/shared/protocol.cc b/game/shared/protocol.cc
index e2c79b5..3b32701 100644
--- a/game/shared/protocol.cc
+++ b/game/shared/protocol.cc
@@ -39,8 +39,8 @@ ENetPacket *protocol::encode(const protocol::LoginRequest &packet, enet_uint32 f
write_buffer.reset();
write_buffer.write_UI16(protocol::LoginRequest::ID);
write_buffer.write_UI32(packet.version);
- write_buffer.write_UI64(packet.voxel_def_checksum);
- write_buffer.write_UI64(packet.item_def_checksum);
+ write_buffer.write_UI64(packet.voxel_registry_checksum);
+ write_buffer.write_UI64(packet.item_registry_checksum);
write_buffer.write_UI64(packet.password_hash);
write_buffer.write_string(packet.username.substr(0, protocol::MAX_USERNAME));
return write_buffer.to_packet(flags);
@@ -280,8 +280,8 @@ void protocol::decode(entt::dispatcher &dispatcher, const ENetPacket *packet, EN
case protocol::LoginRequest::ID:
login_request.peer = peer;
login_request.version = read_buffer.read_UI32();
- login_request.voxel_def_checksum = read_buffer.read_UI64();
- login_request.item_def_checksum = read_buffer.read_UI64();
+ login_request.voxel_registry_checksum = read_buffer.read_UI64();
+ login_request.item_registry_checksum = read_buffer.read_UI64();
login_request.password_hash = read_buffer.read_UI64();
login_request.username = read_buffer.read_string();
dispatcher.trigger(login_request);
diff --git a/game/shared/protocol.hh b/game/shared/protocol.hh
index 0b8b0f1..727ab1f 100644
--- a/game/shared/protocol.hh
+++ b/game/shared/protocol.hh
@@ -118,8 +118,8 @@ struct protocol::StatusResponse final : public protocol::Base<0x0001> {
struct protocol::LoginRequest final : public protocol::Base<0x0002> {
std::uint32_t version;
- std::uint64_t voxel_def_checksum;
- std::uint64_t item_def_checksum;
+ std::uint64_t voxel_registry_checksum;
+ std::uint64_t item_registry_checksum;
std::uint64_t password_hash;
std::string username;
};
diff --git a/game/shared/voxel_registry.cc b/game/shared/voxel_registry.cc
index dea7179..ce6ee7f 100644
--- a/game/shared/voxel_registry.cc
+++ b/game/shared/voxel_registry.cc
@@ -169,7 +169,7 @@ void voxel_registry::purge(void)
voxel_registry::voxels.clear();
}
-std::uint64_t voxel_registry::checksum(void)
+std::uint64_t voxel_registry::calcualte_checksum(void)
{
std::uint64_t result = 0;
diff --git a/game/shared/voxel_registry.hh b/game/shared/voxel_registry.hh
index 722cec1..b12bc68 100644
--- a/game/shared/voxel_registry.hh
+++ b/game/shared/voxel_registry.hh
@@ -138,7 +138,7 @@ void purge(void);
namespace voxel_registry
{
-std::uint64_t checksum(void);
+std::uint64_t calcualte_checksum(void);
} // namespace voxel_registry
#endif /* SHARED_VOXEL_REGISTRY_HH */