Fixed connection & many network packets.

master
Auri 2021-06-22 18:13:39 -07:00
parent 4487997b92
commit 38bec3ab25
59 changed files with 830 additions and 839 deletions

View File

@ -199,7 +199,6 @@ add_library(Zepha_Core
lua/usertype/Target.h
server/Server.cpp
server/Server.h
server/ServerClient.cpp
server/ServerClient.h
server/ServerClients.cpp
server/ServerClients.h
@ -324,6 +323,7 @@ add_library(Zepha_Core
lua/modules/Message.cpp
lua/modules/Message.h
lua/NoiseFromLua.cpp
lua/NoiseFromLua.h util/Types.h)
lua/NoiseFromLua.h
util/Types.h)
target_include_directories(Zepha_Core PUBLIC .)

View File

@ -63,27 +63,32 @@ void ClientNetworkInterpreter::update() {
void ClientNetworkInterpreter::receivedPacket(uptr<PacketView> p) {
switch (p->type) {
default:
default: {
std::cout << Log::err << "Received unknown packet of type " << static_cast<int>(p->type)
<< ". Is the server on a different protocol version?" << Log::endl;
<< ". Is the server on a different protocol version?" << Log::endl;
break;
}
case Packet::Type::SERVER_INFO:
case Packet::Type::SERVER_INFO: {
serverSideChunkGens = p->d.read<u32>();
break;
}
case Packet::Type::THIS_PLAYER_INFO:
case Packet::Type::THIS_PLAYER_INFO: {
world.getPlayer()->handleAssertion(p->d);
break;
}
case Packet::Type::PLAYER_ENT_INFO:
case Packet::Type::PLAYER_ENT_INFO: {
world.handlePlayerEntPacket(std::move(p));
break;
}
case Packet::Type::CHUNK:
case Packet::Type::MAPBLOCK:
case Packet::Type::MAPBLOCK: {
world.handleWorldPacket(std::move(p));
break;
}
// case Packet::Type::BLOCK_SET: {
// auto pos = p->d.read<ivec3>();
@ -92,27 +97,29 @@ void ClientNetworkInterpreter::receivedPacket(uptr<PacketView> p) {
// break;
// }
case Packet::Type::ENTITY_INFO:
case Packet::Type::ENTITY_INFO: {
world.getActiveDimension().l()->serverEntitiesInfo(p->d);
break;
}
case Packet::Type::ENTITY_REMOVED:
case Packet::Type::ENTITY_REMOVED: {
world.getActiveDimension().l()->serverEntitiesRemoved(p->d);
break;
}
case Packet::Type::INV_DATA:
onInvPacket(std::move(p));
break;
case Packet::Type::INV_INVALID: {
std::string source = p->d.read<std::string>();
std::string list = p->d.read<std::string>();
string source = p->d.read<string>();
string list = p->d.read<string>();
throw std::runtime_error("Invalid inventory " + source + ":" + list + " was request by client.");
}
case Packet::Type::MOD_MESSAGE: {
std::string channel = p->d.read<std::string>();
std::string message = p->d.read<std::string>();
string channel = p->d.read<string>();
string message = p->d.read<string>();
world.handleModMessage(channel, message);
break;
}

View File

@ -89,10 +89,10 @@ glm::vec2 Camera::getBufferDimensions() {
}
bool Camera::inFrustum(glm::vec3& p) {
return frustum.pointInFrustum(p) == Frustum::INSIDE;
return frustum.pointInFrustum(p) == Frustum::Intersection::INSIDE;
}
int Camera::inFrustum(FrustumAABB& b) {
Frustum::Intersection Camera::inFrustum(FrustumAABB& b) {
return frustum.boxInFrustum(b);
}

View File

@ -40,7 +40,7 @@ class Camera {
bool inFrustum(glm::vec3& p);
int inFrustum(FrustumAABB& b);
Frustum::Intersection inFrustum(FrustumAABB& b);
~Camera();

View File

@ -52,7 +52,7 @@ Renderer::Renderer(glm::ivec2 win) :
void Renderer::update(double delta) {
//VSync 1 = On, 0 = Off
glfwSwapInterval(1);
glfwSwapInterval(0);
elapsedTime += delta;
window.update();

View File

@ -43,7 +43,7 @@ class MenuSandbox : LuaParser {
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override;
LuaMod mod{};
LuaMod mod {};
std::vector<std::shared_ptr<AtlasRef>> modAssets{};
std::shared_ptr<GuiContainer> container = nullptr;

View File

@ -2,10 +2,12 @@
// Created by aurailus on 11/07/19.
//
#include <thread>
#include <gzip/decompress.hpp>
#include "ConnectScene.h"
#include "GameScene.h"
#include "client/Client.h"
#include "util/net/Packet.h"
#include "util/net/Address.h"
@ -14,8 +16,6 @@
#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"
/**
@ -54,12 +54,15 @@ void ConnectScene::update() {
client.game->textures.update();
switch (connectState) {
default:throw std::runtime_error("Invalid connection state.");
default:
throw std::runtime_error("Invalid connection state.");
case State::DONE:
case State::FAILED_CONNECT:break;
case State::FAILED_CONNECT:
break;
case State::CONNECTING:handleConnecting();
case State::CONNECTING:
handleConnecting();
break;
case State::PROPERTIES: {
@ -73,8 +76,8 @@ void ConnectScene::update() {
auto statusText = components.get<GuiText>("statusText");
statusText->setText(statusText->getText() + "Received server properties.\n");
// TODO: Reimplement this somewhere or something.
// state.seed = p.d.read<unsigned int>();
const u32 seed = p.d.read<u32>();
// std::cout << seed << std::endl;
connectState = State::IDENTIFIER_LIST;
Packet resp(Packet::Type::BLOCK_IDENTIFIER_LIST);
@ -124,15 +127,15 @@ void ConnectScene::update() {
auto statusText = components.get<GuiText>("statusText");
if (p.type == Packet::Type::MODS) {
auto luaMod = LuaMod::fromPacket(p);
auto luaMod = LuaMod(p);
statusText->setText(statusText->getText() + "Received mod " + luaMod.config.name + ".\n");
client.game->getParser().getHandler().addLuaMod(std::move(luaMod));
}
else if (p.type == Packet::Type::MOD_ORDER) {
client.game->getParser().getHandler().setModsOrder(p.d.read<vec<string>>());
statusText->setText(
statusText->getText() + "Done downloading mods.\nReceived the mods order.\nDownloading media...\n");
statusText->setText(statusText->getText() +
"Done downloading mods.\nReceived the mods order.\nReceiving media");
connectState = State::MEDIA;
Packet resp(Packet::Type::MEDIA);
@ -152,42 +155,42 @@ void ConnectScene::update() {
auto statusText = components.get<GuiText>("statusText");
if (p.type == Packet::Type::MEDIA) {
AssetType t = static_cast<AssetType>(p.d.read<int>());
unsigned int count = 0;
AssetType t = p.d.read<AssetType>();
usize count = 0;
while (t != AssetType::END) {
std::string assetName = p.d.read<string>();
string assetName = p.d.read<string>();
statusText->setText(statusText->getText() + ".");
if (t == AssetType::TEXTURE) {
int width = p.d.read<unsigned int>();
int height = p.d.read<unsigned int>();
u16 width = p.d.read<u16>();
u16 height = p.d.read<u16>();
std::string data = p.d.read<std::string>();
std::string uncompressed = gzip::decompress(data.data(), data.length());
string data = p.d.read<string>();
string uncompressed = gzip::decompress(data.data(), data.length());
client.game->textures.addImage(
reinterpret_cast<unsigned char*>(const_cast<char*>(uncompressed.data())),
assetName, true, width, height);
}
else if (t == AssetType::MODEL) {
std::string format = p.d.read<std::string>();
std::string data = p.d.read<std::string>();
string format = p.d.read<string>();
string data = p.d.read<string>();
client.game->models.models.insert({ assetName, SerializedModel{ assetName, data, format }});
}
t = static_cast<AssetType>(p.d.read<int>());
t = p.d.read<AssetType>();
count++;
}
statusText->setText(statusText->getText() + "Received " + std::to_string(count) + "x media files.\n");
}
else if (p.type == Packet::Type::MEDIA_DONE) {
statusText->setText(statusText->getText() + " Done.\nDone receiving media.\nJoining world...\n");
components.get<GuiRect>("loadBar")->setScale({ client.renderer.window.getSize().x, 32 });
statusText->setText(statusText->getText() + "Done downloading media.\nJoining world...\n");
connectState = State::DONE;
client.scene.setScene(std::make_unique<GameScene>(client));
client.scene.setScene(make_unique<GameScene>(client));
}
}
break;
@ -196,15 +199,14 @@ void ConnectScene::update() {
}
void ConnectScene::handleConnecting() {
Packet resp(Packet::Type::SERVER_INFO);
auto statusText = components.get<GuiText>("statusText");
switch (connection.getConnectionStatus()) {
default:throw std::runtime_error("Uncaught connection error.");
default:
throw std::runtime_error("Uncaught connection error.");
case ServerConnection::State::ENET_ERROR:
throw std::runtime_error("Enet Initialization error.");
break;
case ServerConnection::State::FAILED_CONNECT:
connectState = State::FAILED_CONNECT;
@ -222,13 +224,15 @@ void ConnectScene::handleConnecting() {
break;
case ServerConnection::State::CONNECTED:connectState = State::PROPERTIES;
case ServerConnection::State::CONNECTED: {
connectState = State::PROPERTIES;
statusText->setText(statusText->getText() + " Connected!~\n");
Packet resp(Packet::Type::SERVER_INFO);
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
break;
}
}
}
void ConnectScene::draw() {

View File

@ -13,7 +13,7 @@ class ServerConnection;
class Address;
class ConnectScene : public Scene {
public:
public:
enum class State {
CONNECTING,
FAILED_CONNECT,
@ -34,7 +34,7 @@ class ConnectScene : public Scene {
void handleConnecting();
private:
private:
State connectState = State::CONNECTING;
ServerConnection& connection;

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 17/12/18.
//
#include "GameScene.h"
#include "client/Client.h"
@ -9,7 +5,7 @@
#include "client/graph/Renderer.h"
GameScene::GameScene(Client& client) : Scene(client),
world(std::make_shared<LocalWorld>(client.game, client.connection, client.renderer)) {
world(make_shared<LocalWorld>(client.game, client.connection, client.renderer)) {
Packet r(Packet::Type::CONNECT_DATA_RECVD);
r.sendTo(client.connection.getPeer(), Packet::Channel::CONNECT);

View File

@ -1,18 +1,15 @@
//
// Created by aurailus on 17/12/18.
//
#pragma once
#include "Scene.h"
#include "world/LocalWorld.h"
class LocalSubgame;
class Drawable;
class LocalSubgame;
class GameScene : public Scene {
public:
GameScene(Client& client);
void update() override;
@ -22,6 +19,7 @@ public:
void cleanup() override;
public:
WorldPtr world;
};

View File

@ -1,28 +1,25 @@
//
// Created by aurailus on 2019-11-13.
//
#include "BiomeAtlas.h"
#include "game/def/BiomeDef.h"
unsigned int BiomeAtlas::size() {
u16 BiomeAtlas::size() {
return defs.size();
}
BiomeDef& BiomeAtlas::biomeFromId(unsigned int index) {
if (index >= defs.size()) throw std::runtime_error("Undefined biome ID " + std::to_string(index) + " requested.");
return *defs.at(static_cast<unsigned long>(index));
BiomeDef& BiomeAtlas::biomeFromId(u16 index) {
if (index >= defs.size()) throw std::runtime_error(
"Undefined biome ID " + std::to_string(index) + " requested.");
return *defs.at(index);
}
BiomeDef& BiomeAtlas::biomeFromStr(const std::string& identifier) {
if (defTable.count(identifier) <= 0)
throw std::runtime_error("Undefined biome identifier " + identifier + " requested.");
return *defs.at(static_cast<unsigned long>(defTable.at(identifier)));
BiomeDef& BiomeAtlas::biomeFromStr(const string& identifier) {
if (defTable.count(identifier) <= 0) throw std::runtime_error(
"Undefined biome identifier " + identifier + " requested.");
return *defs.at(defTable.at(identifier));
}
std::vector<BiomeDef*> BiomeAtlas::biomesFromTag(const std::string& tag) {
std::vector<BiomeDef*> matched{};
vec<BiomeDef*> BiomeAtlas::biomesFromTag(const string& tag) {
vec<BiomeDef*> matched {};
for (auto biome : defs)
if (biome->tags.count(tag) && biome->tags.at(tag) != 0) matched.push_back(biome);
return std::move(matched);

View File

@ -1,31 +1,31 @@
//
// Manages biome definitions and Voronoi map.
// Created by aurailus on 2019-11-13.
//
#pragma once
#include <vector>
#include <unordered_map>
#include "util/Types.h"
class BiomeDef;
/**
* Stores biome definitions, allowing access by ID or identifier.
*/
class BiomeAtlas {
public:
public:
BiomeAtlas() = default;
virtual void registerBiome(BiomeDef* def) = 0;
BiomeDef& biomeFromId(unsigned int index);
BiomeDef& biomeFromId(u16 index);
BiomeDef& biomeFromStr(const std::string& identifier);
BiomeDef& biomeFromStr(const string& identifier);
std::vector<BiomeDef*> biomesFromTag(const std::string& tag);
vec<BiomeDef*> biomesFromTag(const string& tag);
unsigned int size();
u16 size();
const static unsigned int INVALID = 0;
protected:
std::vector<BiomeDef*> defs;
std::unordered_map<std::string, unsigned int> defTable;
const static u16 INVALID = 0;
protected:
vec<BiomeDef*> defs;
std::unordered_map<string, u32> defTable;
};

View File

@ -1,12 +1,8 @@
//
// Created by aurailus on 2019-11-18.
//
#include "ServerBiomeAtlas.h"
#include "game/def/BiomeDef.h"
ServerBiomeAtlas::ServerBiomeAtlas(unsigned int seed) :
ServerBiomeAtlas::ServerBiomeAtlas(u32 seed) :
seed(seed) {
BiomeDef* invalid = new BiomeDef();
@ -20,5 +16,9 @@ ServerBiomeAtlas::ServerBiomeAtlas(unsigned int seed) :
void ServerBiomeAtlas::registerBiome(BiomeDef* def) {
defs.push_back(def);
defTable.insert({ def->identifier, def->index });
defTable.emplace(def->identifier, def->index);
}
u32 ServerBiomeAtlas::getSeed() {
return seed;
}

View File

@ -1,16 +1,15 @@
//
// Created by aurailus on 2019-11-18.
//
#pragma once
#include "BiomeAtlas.h"
class ServerBiomeAtlas : public BiomeAtlas {
public:
ServerBiomeAtlas(unsigned int seed);
public:
ServerBiomeAtlas(u32 seed);
void registerBiome(BiomeDef* def) override;
unsigned int seed;
u32 getSeed();
private:
u32 seed;
};

View File

@ -4,10 +4,10 @@
#pragma once
#include <string>
#include "util/Types.h"
struct SerializedModel {
std::string name{};
std::string data{};
std::string format{};
string name;
string data;
string format;
};

View File

@ -4,12 +4,15 @@
#pragma once
#include <string>
#include "util/Types.h"
struct ServerTexture {
std::string name{};
std::string data{};
unsigned int width = 0;
unsigned int height = 0;
ServerTexture(string name, string data, u16 width, u16 height) :
name(name), data(data), width(width), height(height) {};
string name;
string data;
u16 width;
u16 height;
};

View File

@ -11,20 +11,20 @@
#include "../util/Log.h"
std::string
ErrorFormatter::formatError(const std::string& fileName, int line, const std::string& stack, std::string file,
ErrorFormatter::formatError(const string& fileName, usize line, const string& stack, string file,
bool ansiColors) noexcept {
const std::string red = (ansiColors ? Log::red : "");
const std::string unbl = (ansiColors ? Log::unbl : "");
const std::string endl = (ansiColors ? Log::endl : "\n");
const string red = (ansiColors ? Log::red : "");
const string unbl = (ansiColors ? Log::unbl : "");
const string endl = (ansiColors ? Log::endl : "\n");
std::stringstream out{};
// Split the file into lines, and add them to a vector
std::vector<std::string> fileLines{};
size_t pos = 0;
std::string token;
vec<string> fileLines{};
usize pos = 0;
string token;
while ((pos = file.find("\n")) != std::string::npos) {
while ((pos = file.find("\n")) != string::npos) {
token = file.substr(0, pos);
fileLines.push_back(token);
file.erase(0, pos + 1);
@ -34,8 +34,8 @@ ErrorFormatter::formatError(const std::string& fileName, int line, const std::st
while (fileLines.back() == "") fileLines.pop_back();
// Format and add lines to the stringstream
for (unsigned int i = (std::max)(0, line - 6); i < (std::min)(static_cast<int>(fileLines.size()), line + 5); i++) {
for (unsigned int j = 0; j < 3 - std::to_string(i + 1).length(); j++) out << " ";
for (usize i = (std::max)(static_cast<usize>(0), line - 6); i < (std::min)(fileLines.size(), line + 5); i++) {
for (usize j = 0; j < 3 - std::to_string(i + 1).length(); j++) out << " ";
out << red << (i + 1 == line ? unbl : "") << (i + 1) << (i + 1 == line ? " # " : " | ") << fileLines[i] << endl;
}

View File

@ -4,10 +4,10 @@
#pragma once
#include <string>
#include "util/Types.h"
class ErrorFormatter {
public:
static std::string formatError(const std::string& fileName, int line,
const std::string& stack, std::string file, bool ansiColors = true) noexcept;
public:
static string formatError(const string& fileName, usize line,
const string& stack, string file, bool ansiColors = true) noexcept;
};

View File

@ -1,37 +1,23 @@
//
// Created by aurailus on 05/08/19.
//
#include <gzip/decompress.hpp>
#include "LuaMod.h"
#include "util/net/PacketView.h"
LuaMod LuaMod::fromPacket(PacketView& p) {
LuaMod luaMod{};
LuaMod::LuaMod(PacketView& p) {
auto serialized = p.d.read<string>();
std::string mod = gzip::decompress(serialized.c_str(), serialized.length());
luaMod.serialized = serialized;
string mod = gzip::decompress(serialized.c_str(), serialized.length());
vec<string> depends;
string name, description, version;
std::string name, description, version, dependsStr;
Deserializer d(mod);
d.read(name).read(description).read(version).read(dependsStr);
d.read(name).read(description).read(version).read(depends);
config = { name, description, version, depends };
std::vector<std::string> depends;
size_t pos = 0;
std::string token;
while ((pos = dependsStr.find(',')) != std::string::npos) {
token = dependsStr.substr(0, pos);
depends.push_back(token);
dependsStr.erase(0, pos + 1);
while (!d.atEnd()) {
string path, contents;
d.read(path).read(contents);
files.emplace_back(path, contents);
}
depends.push_back(dependsStr);
luaMod.config = { name, description, version, depends };
while (!d.atEnd()) luaMod.files.push_back({ d.read<std::string>(), d.read<std::string>() });
return std::move(luaMod);
}

View File

@ -1,32 +1,44 @@
//
// Created by aurailus on 03/08/19.
//
#pragma once
#include <vector>
#include <string>
#include "util/Types.h"
class PacketView;
/**
* Holds the name, description, version and dependencies
* of a lua mod, as well as its scripts.
*/
class LuaMod {
public:
public:
struct File {
std::string path;
std::string file;
File(string path, string file): path(path), file(file) {};
string path;
string file;
};
struct Config {
std::string name;
std::string description;
std::string version;
std::vector<std::string> depends;
string name;
string description;
string version;
vec<string> depends;
};
std::vector<File> files{};
Config config{};
std::string modPath;
std::string serialized;
LuaMod() = default;
static LuaMod fromPacket(PacketView& p);
/** Creates a new lua mod from a packet containing mod data. */
LuaMod(PacketView& p);
/** The mod's source files. */
vec<File> files {};
/** The mod's configuration data. */
Config config {};
/** The mod's filesystem path. */
string modPath;
/** The serialized mod, populated on the server. */
string serialized;
};

View File

@ -60,7 +60,7 @@ void ServerLuaParser::sendModsPacket(ENetPeer* peer) const {
for (const LuaMod& mod : handler.cGetMods())
Serializer().append(mod.serialized).packet(Packet::Type::MODS).sendTo(peer, Packet::Channel::CONNECT);
std::vector<std::string> order{};
vec<string> order {};
for (const LuaMod& mod : handler.cGetMods()) order.push_back(mod.config.name);
Serializer().append(order).packet(Packet::Type::MOD_ORDER).sendTo(peer, Packet::Channel::CONNECT);
}

View File

@ -196,8 +196,8 @@ void ServerModHandler::loadTextures(ServerSubgame& defs, const std::vector<LuaMo
std::string comp = gzip::compress(str.data(), str.length());
free(data);
defs.assets.textures.push_back({ std::move(name), comp, static_cast<unsigned int>(width),
static_cast<unsigned int>(height) });
defs.assets.textures.emplace_back(
std::move(name), comp, static_cast<u16>(width), static_cast<u16>(height));
}
}
}
@ -282,26 +282,17 @@ void ServerModHandler::organizeDependencies(std::vector<LuaMod>& mods) {
void ServerModHandler::serializeMods(std::vector<LuaMod>& mods) {
for (LuaMod& mod : mods) {
Serializer s = {};
Serializer s;
s.append(mod.config.name)
.append(mod.config.description)
.append(mod.config.version);
std::string depends;
bool delimiter = false;
for (const std::string& dep : mod.config.depends) {
if (delimiter) depends.append(",");
else delimiter = true;
depends.append(dep);
}
s.append(depends);
.append(mod.config.description)
.append(mod.config.version)
.append(mod.config.depends);
for (LuaMod::File& file : mod.files) {
s.append(file.path).append(file.file);
}
std::string comp = gzip::compress(s.data.c_str(), s.data.length());
string comp = gzip::compress(s.data.c_str(), s.data.length());
mod.serialized = comp;
}
}

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 09/01/19.
//
#include <thread>
#include <iostream>
@ -34,14 +30,17 @@ Server::Server(u16 port, const std::string& subgame) :
}
void Server::update() {
const static i64 interval_ns = static_cast<long>((1000 / 60.f) * 1000000L);
const static i64 interval_ns = static_cast<i64>((1000 / 60.f) * 1000000L);
Timer loop("");
world->update(delta);
game.s()->update(delta);
// Read incoming events.
ENetEvent event;
while (handler.update(&event) && loop.elapsedNs() < interval_ns) {
u64 runs = 0;
while (handler.update(&event) && (loop.elapsedNs() < interval_ns || runs++ < 8)) {
switch (event.type) {
default:
case ENET_EVENT_TYPE_NONE:
@ -55,14 +54,28 @@ void Server::update() {
clients.handleDisconnect(event);
break;
case ENET_EVENT_TYPE_RECEIVE:
packetReceived(event);
case ENET_EVENT_TYPE_RECEIVE: {
PacketView p(event.packet);
auto client = static_cast<ServerClient*>(event.peer->data);
if (client->player) return playerPacketReceived(p, clients.getClient(client->id)->player);
if (config.handlePacket(*client, p)) {
auto clientShr = clients.getClient(client->id);
clients.createPlayer(clientShr, world->getDefaultDimension());
}
break;
}
}
}
// Update players with the status of other players.
for (u32 id : playersUpdated) {
auto player = clients.getPlayer(id);
auto client = clients.getClient(id);
if (!client) continue;
auto player = client->player;
if (!player) continue;
Packet p = Serializer()
@ -72,101 +85,101 @@ void Server::update() {
.append(NetField::LOOK_PITCH).append(player->getPitch())
.packet(Packet::Type::PLAYER_ENT_INFO, false);
for (auto& iter : clients.players)
if (iter->getId() != id && glm::distance(player->getPos(), iter->getPos()) < 200)
p.sendTo(iter->getPeer(), Packet::Channel::ENTITY);
for (auto& iter : clients.getClients())
if (iter.first != id && iter.second->player &&
glm::distance(player->getPos(), iter.second->player->getPos()) < 200)
p.sendTo(iter.second->peer, Packet::Channel::ENTITY);
}
playersUpdated.clear();
u64 sleep_for = interval_ns - loop.elapsedNs();
u64 sleep_for = (std::max)(interval_ns - static_cast<i64>(loop.elapsedNs()), 0L);
if (sleep_for > 0) std::this_thread::sleep_for(std::chrono::nanoseconds(sleep_for));
delta = loop.elapsedNs() / 1000000.f / 1000.f;
elapsed += delta;
}
void Server::packetReceived(ENetEvent& e) {
PacketView p(e.packet);
auto client = static_cast<ServerClient*>(e.peer->data);
auto player = PlayerPtr(clients.getPlayer(client->id));
// Handle the packet as a player and then return.
if (client->player) return playerPacketReceived(p, player);
// Function returns true if a player is to be created.
if (config.handlePacket(*client, p)) {
auto clientShared = clients.getClient(client->id);
if (clientShared) clients.createPlayer(clientShared, world->getDefaultDimension());
}
}
void Server::playerPacketReceived(PacketView& p, PlayerPtr player) {
// Pre-initialization because switch statements suck.
ivec3 pos;
u16 a, ind;
string source, list;
EVec face = EVec::NONE;
void Server::playerPacketReceived(PacketView& p, sptr<ServerPlayer> player) {
switch (p.type) {
default:
throw std::runtime_error("Unknown packet type " +
std::to_string(static_cast<u32>(p.type)) + " received.");
default: {
throw std::runtime_error("Unknown packet type: " + std::to_string(static_cast<u32>(p.type)));
}
case Packet::Type::THIS_PLAYER_INFO:
case Packet::Type::THIS_PLAYER_INFO: {
player->handleAssertion(p.d);
playersUpdated.emplace(player->getId());
break;
}
case Packet::Type::BLOCK_HIT:
p.d.read(pos).read(face);
case Packet::Type::BLOCK_HIT: {
ivec3 pos = p.d.read<ivec3>();
EVec face = p.d.read<EVec>();
player->getDim()->blockHit(Target(player->getDim(), pos, face), player);
break;
}
case Packet::Type::BLOCK_PLACE:
p.d.read(pos).read(face);
case Packet::Type::BLOCK_PLACE: {
ivec3 pos = p.d.read<ivec3>();
EVec face = p.d.read<EVec>();
player->getDim()->blockPlace(Target(player->getDim(), pos, face), player);
break;
}
case Packet::Type::BLOCK_INTERACT:
p.d.read(pos).read(face);
case Packet::Type::BLOCK_INTERACT: {
ivec3 pos = p.d.read<ivec3>();
EVec face = p.d.read<EVec>();
player->getDim()->blockInteract(Target(player->getDim(), pos, face), player);
break;
}
case Packet::Type::BLOCK_PLACE_OR_INTERACT:
p.d.read(pos).read(face);
case Packet::Type::BLOCK_PLACE_OR_INTERACT: {
ivec3 pos = p.d.read<ivec3>();
EVec face = p.d.read<EVec>();
player->getDim()->blockPlaceOrInteract(Target(player->getDim(), pos, face), player);
break;
}
case Packet::Type::WIELD_ITEM_USE:
case Packet::Type::WIELD_ITEM_USE: {
player->getDim()->wieldItemUse(Target(), player);
break;
}
case Packet::Type::INV_WATCH:
p.d.read<string>(source).read<string>(list);
case Packet::Type::INV_WATCH: {
string source = p.d.read<string>();
string list = p.d.read<string>();
if (!world->getRefs().s()->addWatcher(source, list, player->getId()))
Serializer().append(source).append(list).packet(Packet::Type::INV_INVALID)
.sendTo(player.s()->getPeer(), Packet::Channel::INTERACT);
.sendTo(player->getPeer(), Packet::Channel::INTERACT);
break;
}
case Packet::Type::INV_UNWATCH:
p.d.read<string>(source).read<string>(list);
case Packet::Type::INV_UNWATCH: {
string source = p.d.read<string>();
string list = p.d.read<string>();
if (!world->getRefs().s()->removeWatcher(source, list, player->getId()))
Serializer().append(source).append(list).packet(Packet::Type::INV_INVALID)
.sendTo(player.s()->getPeer(), Packet::Channel::INTERACT);
.sendTo(player->getPeer(), Packet::Channel::INTERACT);
break;
}
case Packet::Type::INV_INTERACT:
p.d.read<u16>(a).read<string>(source).read<string>(list).read<u16>(ind);
world->getRefs().s()->interact(a, source, list, ind, player->getId());
case Packet::Type::INV_INTERACT: {
bool primary = p.d.read<bool>();
string source = p.d.read<string>();
string list = p.d.read<string>();
u16 ind = p.d.read<u16>();
world->getRefs().s()->interact(primary, source, list, ind, player->getId());
break;
case Packet::Type::MOD_MESSAGE:
p.d.read<string>(source).read<string>(list);
}
case Packet::Type::MOD_MESSAGE: {
string source = p.d.read<string>();
string list = p.d.read<string>();
game->getParser().safe_function(game->getParser().core["trigger"], "message",
source, game->getParser().safe_function(game->getParser().core["deserialize"], list));
break;
}
}
}
void Server::cleanup() {

View File

@ -26,10 +26,10 @@ public:
~Server();
private:
void packetReceived(ENetEvent& e);
void playerPacketReceived(PacketView& p, PlayerPtr player);
private:
/** Handles a player packet. */
void playerPacketReceived(PacketView& p, sptr<ServerPlayer> player);
/** The server's port. */
u16 port = 0;
@ -53,7 +53,7 @@ public:
ServerClients clients;
/** A list of players who have been updated, to send to the other clients. */
std::unordered_set<u32> playersUpdated{};
std::unordered_set<u32> playersUpdated {};
/** The time elapsed since the start of the server. */
f64 elapsed = 0;

View File

@ -1,5 +0,0 @@
//
// Created by aurailus on 2020-07-30.
//
#include "ServerClient.h"

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 2020-07-30.
//
#pragma once
#include <enet/enet.h>
@ -10,10 +6,17 @@
class ServerPlayer;
/**
* A connected client, containing a reference
* to the raw ENet data it was initialized with.
* The ENetPeer is given a pointer to an instance of this struct on connection.
*/
class ServerClient {
public:
ServerClient(const string& username, ENetPeer* peer) :
username(username), peer(peer), address(peer->address), id(peer->connectID) {}
public:
ServerClient(const string& username, u32 id, ENetPeer* peer) :
username(username), peer(peer), address(peer->address), id(id) {}
u32 id = 0;
string username;
@ -21,5 +24,5 @@ class ServerClient {
ENetPeer* peer;
ENetAddress address;
std::shared_ptr<ServerPlayer> player = nullptr;
sptr<ServerPlayer> player = nullptr;
};

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 07/02/19.
//
#include <iostream>
#include "ServerClients.h"
@ -13,69 +9,49 @@
#include "util/net/NetHandler.h"
#include "world/player/ServerPlayer.h"
ServerClients::ServerClients(SubgamePtr game) :
game(game) {}
ServerClients::ServerClients(SubgamePtr game) : game(game) {}
void ServerClients::init(ServerWorld* world) {
this->world = world;
}
void ServerClients::handleConnect(ENetEvent e) {
auto client = std::make_shared<ServerClient>("TEMPORARY", e.peer);
client->peer->data = client.get();
clients.push_back(client);
const auto client = make_shared<ServerClient>("TEMP:" + NetHandler::intToIPString(e.peer->address.host)
+ ":" + std::to_string(e.peer->address.port), e.peer->connectID, e.peer);
e.peer->data = client.get();
clients.emplace(client->id, client);
std::cout << Log::info << NetHandler::intToIPString(client->address.host)
<< ":" << client->address.port << " connected." << Log::endl;
std::cout << Log::info << client->username << " connected." << Log::endl;
}
void ServerClients::handleDisconnect(ENetEvent e) {
unsigned int id = static_cast<ServerClient*>(e.peer->data)->id;
const auto client = static_cast<ServerClient*>(e.peer->data);
if (client->player) game.s()->getParser().playerDisconnected(client->player);
ENetAddress& addr = e.peer->address;
std::cout << Log::info << NetHandler::intToIPString(addr.host) << ":" << addr.port << " disconnected." << Log::endl;
// Disconnect the player, if it exists.
for (auto it = players.begin(); it != players.end();) {
if ((*it)->getId() == id) {
game.s()->getParser().playerDisconnected(*it);
players.erase(it);
break;
}
}
for (auto it = clients.begin(); it != clients.end();) {
if ((*it)->id == id) {
clients.erase(it);
break;
}
}
std::cout << Log::info << client->username << " disconnected." << Log::endl;
clients.erase(client->id);
}
void ServerClients::createPlayer(std::shared_ptr<ServerClient> client, DimensionPtr dimension) {
auto player = std::make_shared<ServerPlayer>(*client, dimension->getWorld(), game, dimension);
player->getInventory()->createList("cursor", 1, 1);
client->player = player;
players.push_back(player);
game.s()->getParser().playerConnected(player);
void ServerClients::createPlayer(sptr<ServerClient> client, DimensionPtr dimension) {
std::cout << "PLAYER CREATING" << std::endl;
client->player = make_shared<ServerPlayer>(*client, dimension->getWorld(), game, dimension);
player->setPos({ 32, -20, 32 }, true);
game.s()->getParser().playerConnected(client->player);
client->player->setPos({ 32, -20, 32 }, true);
Serializer()
.append(NetField::ID).append(player->getId())
.append(NetField::POS).append(player->getPos())
.append(NetField::LOOK_PITCH).append(player->getPitch())
.append(NetField::LOOK_YAW).append(player->getYaw())
.packet(Packet::Type::THIS_PLAYER_INFO).sendTo(player->getPeer(), Packet::Channel::INTERACT);
.append(NetField::ID).append(static_cast<u32>(client->player->getId()))
.append(NetField::POS).append(client->player->getPos())
.append(NetField::LOOK_PITCH).append(client->player->getPitch())
.append(NetField::LOOK_YAW).append(client->player->getYaw())
.packet(Packet::Type::THIS_PLAYER_INFO).sendTo(client->peer, Packet::Channel::INTERACT);
}
const std::shared_ptr<ServerClient> ServerClients::getClient(unsigned int id) const {
for (auto& c : clients) if (c->id == id) return c;
const sptr<ServerClient> ServerClients::getClient(u32 id) const {
if (clients.count(id)) return clients.at(id);
return nullptr;
}
const std::shared_ptr<ServerPlayer> ServerClients::getPlayer(unsigned int id) const {
for (auto& c : players) if (c->getId() == id) return c;
return nullptr;
}
const std::unordered_map<u32, sptr<ServerClient>>& ServerClients::getClients() const {
return clients;
}

View File

@ -1,45 +1,49 @@
//
// Created by aurailus on 07/02/19.
//
#pragma once
#include <list>
#include <memory>
#include <enet/enet.h>
#include <unordered_map>
#include "util/Types.h"
#include "util/CovariantPtr.h"
class ServerWorld;
class ServerClient;
class ServerPlayer;
class ServerSubgame;
class ServerDimension;
/**
* Manages creating and deleting clients on connection
* and disconnection, and handles creating client players.
*/
class ServerClients {
public:
public:
explicit ServerClients(SubgamePtr game);
void init(ServerWorld* world);
/** Creates a new client from the event specified. */
void handleConnect(ENetEvent e);
/** Removes a client from the event specified. */
void handleDisconnect(ENetEvent e);
void createPlayer(std::shared_ptr<ServerClient> client, DimensionPtr dimension);
/** Creates a player for the client specified. */
void createPlayer(sptr<ServerClient> client, DimensionPtr dimension);
/** Returns the server client for the id specified. */
const sptr<ServerClient> getClient(u32 id) const;
const std::shared_ptr<ServerClient> getClient(unsigned int id) const;
/** Returns the server clients map. */
const std::unordered_map<u32, sptr<ServerClient>>& getClients() const;
const std::shared_ptr<ServerPlayer> getPlayer(unsigned int id) const;
private:
std::list<std::shared_ptr<ServerClient>> clients;
std::list<std::shared_ptr<ServerPlayer>> players;
private:
SubgamePtr game;
ServerWorld* world = nullptr;
/** The internal clients map. */
std::unordered_map<u32, sptr<ServerClient>> clients;
};

View File

@ -15,46 +15,43 @@
ServerConfig::ServerConfig(SubgamePtr game) : game(game) {}
void ServerConfig::init() {
blockIdentifierList.reserve(static_cast<unsigned long>(game->getDefs().size()));
for (unsigned int i = 0; i < game->getDefs().size(); i++) {
blockIdentifierList.reserve(game->getDefs().size());
for (usize i = 0; i < game->getDefs().size(); i++)
blockIdentifierList.push_back(game->getDefs().fromId(i).identifier);
}
biomeIdentifierList.reserve(static_cast<unsigned long>(game->getBiomes().size()));
for (unsigned int i = 0; i < game->getBiomes().size(); i++) {
biomeIdentifierList.reserve( game->getBiomes().size());
for (usize i = 0; i < game->getBiomes().size(); i++)
biomeIdentifierList.push_back(game->getBiomes().biomeFromId(i).identifier);
}
}
bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
switch (r.type) {
default: break;
default:
break;
case Packet::Type::CONNECT_DATA_RECVD:
return true;
case Packet::Type::SERVER_INFO: {
case Packet::Type::SERVER_INFO:
Serializer()
.append(game.s()->getBiomes().seed)
.append(game.s()->getBiomes().getSeed())
.packet(Packet::Type::SERVER_INFO)
.sendTo(client.peer, Packet::Channel::CONNECT);
break;
}
case Packet::Type::BLOCK_IDENTIFIER_LIST: {
case Packet::Type::BLOCK_IDENTIFIER_LIST:
Serializer()
.append(blockIdentifierList)
.packet(Packet::Type::BLOCK_IDENTIFIER_LIST)
.sendTo(client.peer, Packet::Channel::CONNECT);
break;
}
case Packet::Type::BIOME_IDENTIFIER_LIST: {
case Packet::Type::BIOME_IDENTIFIER_LIST:
Serializer()
.append(biomeIdentifierList)
.packet(Packet::Type::BIOME_IDENTIFIER_LIST)
.sendTo(client.peer, Packet::Channel::CONNECT);
break;
}
case Packet::Type::MODS: {
game.s()->getParser().sendModsPacket(client.peer);
@ -62,14 +59,14 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
}
case Packet::Type::MEDIA: {
const unsigned int MAX_PACKET_SIZE = 32 * 1024;
unsigned int packetSize = 0;
const static usize MAX_PACKET_SIZE = 32 * 1024;
usize packetSize = 0;
Serializer s {};
for (ServerTexture& texture : game.s()->assets.textures) {
if (packetSize + 20 + texture.data.length() > MAX_PACKET_SIZE && packetSize != 0) {
s.append(static_cast<int>(AssetType::END));
s.append(AssetType::END);
Packet p(Packet::Type::MEDIA);
p.data = s.data;
@ -79,18 +76,18 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
p.sendTo(client.peer, Packet::Channel::CONNECT);
}
s.append(static_cast<int>(AssetType::TEXTURE))
.append(texture.name)
.append(texture.width)
.append(texture.height)
.append(texture.data);
s.append(AssetType::TEXTURE)
.append(texture.name)
.append(texture.width)
.append(texture.height)
.append(texture.data);
packetSize += texture.data.length() + 20;
}
for (SerializedModel& model : game.s()->assets.models) {
if (packetSize + 16 + model.data.length() > MAX_PACKET_SIZE && packetSize != 0) {
s.append(static_cast<int>(AssetType::END));
s.append(AssetType::END);
Packet p(Packet::Type::MEDIA);
p.data = s.data;
@ -100,15 +97,15 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
p.sendTo(client.peer, Packet::Channel::CONNECT);
}
s.append(static_cast<int>(AssetType::MODEL))
.append(model.name)
.append(model.format)
.append(model.data);
s.append(AssetType::MODEL)
.append(model.name)
.append(model.format)
.append(model.data);
packetSize += model.data.length() + 16;
}
s.append(static_cast<int>(AssetType::END));
s.append(AssetType::END);
Packet p(Packet::Type::MEDIA);
p.data = s.data;

View File

@ -8,22 +8,25 @@
#include "util/net/PacketView.h"
class PacketView;
class ServerClient;
class ServerSubgame;
class ServerConfig {
public:
public:
explicit ServerConfig(SubgamePtr game);
void init();
//Bool: Create player
/**
* Handles a packet requesting subgame data.
* Returns a boolean indicating if the client is done receiving all data.
*/
bool handlePacket(ServerClient& client, PacketView& p);
private:
private:
SubgamePtr game;
std::vector<std::string> blockIdentifierList{};
std::vector<std::string> biomeIdentifierList{};
vec<string> blockIdentifierList {};
vec<string> biomeIdentifierList {};
};

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 02/12/18.
//
#include <iostream>
#include "Timer.h"
@ -12,9 +8,9 @@ Timer::Timer() :
Timer::Timer(const std::string& name) :
name(name), start(std::chrono::high_resolution_clock::now()) {}
long Timer::elapsedNs() const {
u64 Timer::elapsedNs() const {
auto finish = std::chrono::high_resolution_clock::now();
long elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count();
u64 elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count();
return elapsed;
};

View File

@ -1,19 +1,21 @@
//
// Created by aurailus on 02/12/18.
//
#pragma once
#include <string>
#include <chrono>
#include "util/Types.h"
/**
* Tracks time at nanosecond precision, and provides methods to print
* and retrieve the elapsed time since initialization.
*/
class Timer {
public:
public:
explicit Timer();
explicit Timer(const std::string& name);
long elapsedNs() const;
u64 elapsedNs() const;
void printElapsedNs();
@ -21,8 +23,8 @@ class Timer {
void printElapsedSeconds();
private:
std::string name = "";
private:
string name = "";
std::chrono::high_resolution_clock::time_point start;
};

View File

@ -34,13 +34,19 @@ using u64f = uint_fast64_t;
using f32 = float;
using f64 = double;
using glm::vec2, glm::vec3, glm::vec4;
using vec2 = glm::f32vec2;
using vec3 = glm::f32vec3;
using vec4 = glm::f32vec4;
using glm::ivec2, glm::ivec3, glm::ivec4;
using ivec2 = glm::i32vec2;
using ivec3 = glm::i32vec3;
using ivec4 = glm::i32vec4;
using glm::i16vec2, glm::i16vec3, glm::i16vec4;
using glm::i8vec2, glm::i8vec3, glm::i8vec4;
using glm::uvec2, glm::uvec3, glm::uvec4;
using uvec2 = glm::u32vec2;
using uvec3 = glm::u32vec3;
using uvec4 = glm::u32vec4;
using glm::u16vec2, glm::u16vec3, glm::u16vec4;
using glm::u8vec2, glm::u8vec3, glm::u8vec4;

View File

@ -6,56 +6,57 @@
#include "Frustum.h"
void Frustum::setCamInternals(float fov, float ratio, float nearD, float farD) {
this->nearD = nearD;
this->farD = farD;
void Frustum::setCamInternals(f32 fov, f32 ratio, f32 nearDistance, f32 farDistance) {
this->nearDistance = nearDistance;
this->farDistance = farDistance;
nearH = std::tan(fov) * nearD;
nearW = nearH * ratio;
nearHeight = std::tan(fov) * nearDistance;
nearWidth = nearHeight * ratio;
farH = std::tan(fov) * farD;
farW = farH * ratio;
farHeight = std::tan(fov) * farDistance;
farWidth = farHeight * ratio;
}
void Frustum::update(glm::vec3& pos, glm::vec3& look, glm::vec3& up, glm::vec3& right) {
glm::vec3 fc = pos + (look * farD);
void Frustum::update(vec3& pos, vec3& look, vec3& up, vec3& right) {
glm::vec3 fc = pos + (look * farDistance);
ftl = fc + (up * (farH / 2.0f)) - (right * (farW / 2.0f));
ftr = fc + (up * (farH / 2.0f)) + (right * (farW / 2.0f));
fbl = fc - (up * (farH / 2.0f)) - (right * (farW / 2.0f));
fbr = fc - (up * (farH / 2.0f)) + (right * (farW / 2.0f));
ftl = fc + (up * (farHeight / 2.f)) - (right * (farWidth / 2.f));
ftr = fc + (up * (farHeight / 2.f)) + (right * (farWidth / 2.f));
fbl = fc - (up * (farHeight / 2.f)) - (right * (farWidth / 2.f));
fbr = fc - (up * (farHeight / 2.f)) + (right * (farWidth / 2.f));
glm::vec3 nc = pos + (look * nearD);
glm::vec3 nc = pos + (look * nearDistance);
ntl = nc + (up * (nearH / 2.0f)) - (right * (nearW / 2.0f));
ntr = nc + (up * (nearH / 2.0f)) + (right * (nearW / 2.0f));
nbl = nc - (up * (nearH / 2.0f)) - (right * (nearW / 2.0f));
nbr = nc - (up * (nearH / 2.0f)) + (right * (nearW / 2.0f));
ntl = nc + (up * (nearHeight / 2.f)) - (right * (nearWidth / 2.f));
ntr = nc + (up * (nearHeight / 2.f)) + (right * (nearWidth / 2.f));
nbl = nc - (up * (nearHeight / 2.f)) - (right * (nearWidth / 2.f));
nbr = nc - (up * (nearHeight / 2.f)) + (right * (nearWidth / 2.f));
planes[TOP].setPoints(ntr, ntl, ftl);
planes[BOTTOM].setPoints(nbl, nbr, fbr);
planes[LEFT].setPoints(ntl, nbl, fbl);
planes[RIGHT].setPoints(nbr, ntr, fbr);
planes[FNEAR].setPoints(ntl, ntr, nbr);
planes[FFAR].setPoints(ftr, ftl, fbl);
planes[static_cast<u8>(Direction::TOP )].setPoints(ntr, ntl, ftl);
planes[static_cast<u8>(Direction::BOTTOM)].setPoints(nbl, nbr, fbr);
planes[static_cast<u8>(Direction::LEFT )].setPoints(ntl, nbl, fbl);
planes[static_cast<u8>(Direction::RIGHT )].setPoints(nbr, ntr, fbr);
planes[static_cast<u8>(Direction::NEAR )].setPoints(ntl, ntr, nbr);
planes[static_cast<u8>(Direction::FAR )].setPoints(ftr, ftl, fbl);
}
int Frustum::pointInFrustum(glm::vec3& p) {
Frustum::Intersection Frustum::pointInFrustum(vec3& p) {
for (FrustumPlane& plane : planes) {
if (plane.distance(p) < 0) return OUTSIDE;
if (plane.distance(p) < 0) return Intersection::OUTSIDE;
}
return INSIDE;
return Intersection::INSIDE;
}
int Frustum::boxInFrustum(FrustumAABB& b) {
int result = INSIDE;
Frustum::Intersection Frustum::boxInFrustum(FrustumAABB& b) {
Intersection res = Intersection::INSIDE;
for (auto& plane : planes) {
glm::vec3 vertexP = b.getVertexP(plane.normal);
if (plane.distance(vertexP) < 0) return OUTSIDE;
vec3 vertexP = b.getVertexP(plane.normal);
if (plane.distance(vertexP) < 0) return Intersection::OUTSIDE;
glm::vec3 vertexN = b.getVertexN(plane.normal);
if (plane.distance(vertexN) < 0) result = INTERSECT;
vec3 vertexN = b.getVertexN(plane.normal);
if (plane.distance(vertexN) < 0) res = Intersection::INTERSECTS;
}
return result;
return res;
}

View File

@ -1,47 +1,39 @@
//
// Created by aurailus on 02/03/19.
//
#pragma once
#include <glm/vec3.hpp>
#include "FrustumPlane.h"
#include "FrustumAABB.h"
#include "util/Types.h"
#include "FrustumAABB.h"
#include "FrustumPlane.h"
/** Checks if boxes or points are within the camera's frustum cone. */
class Frustum {
private:
enum {
private:
enum class Direction {
TOP = 0,
BOTTOM,
LEFT,
RIGHT,
FNEAR,
FFAR
NEAR,
FAR
};
public:
enum {
OUTSIDE,
INSIDE,
INTERSECT
};
public:
enum class Intersection { OUTSIDE, INSIDE, INTERSECTS };
Frustum() = default;
void setCamInternals(f32 angle, f32 ratio, f32 nearDistance, f32 farDistance);
void setCamInternals(float angle, float ratio, float nearD, float farD);
void update(vec3& pos, vec3& look, vec3& up, vec3& right);
void update(glm::vec3& pos, glm::vec3& look, glm::vec3& up, glm::vec3& right);
Intersection pointInFrustum(vec3& p);
int pointInFrustum(glm::vec3& p);
int boxInFrustum(FrustumAABB& b);
Intersection boxInFrustum(FrustumAABB& b);
FrustumPlane planes[6];
float nearD, farD;
float nearW, nearH, farW, farH;
f32 nearDistance, farDistance;
f32 nearWidth, nearHeight, farWidth, farHeight;
glm::vec3 ntl, ntr, nbl, nbr,
ftl, ftr, fbl, fbr;
vec3 ntl, ntr, nbl, nbr, ftl, ftr, fbl, fbr;
};

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 03/03/19.
//
#include "FrustumAABB.h"
FrustumAABB::FrustumAABB(glm::vec3 a, glm::vec3 s) : corner(a), size(s) {}
@ -11,8 +7,8 @@ void FrustumAABB::set(glm::vec3 a, glm::vec3 s) {
size = s;
}
glm::vec3 FrustumAABB::getVertexP(glm::vec3& normal) {
glm::vec3 res = corner;
vec3 FrustumAABB::getVertexP(glm::vec3& normal) {
vec3 res = corner;
if (normal.x > 0) res.x += size.x;
if (normal.y > 0) res.y += size.y;
@ -21,8 +17,8 @@ glm::vec3 FrustumAABB::getVertexP(glm::vec3& normal) {
return res;
}
glm::vec3 FrustumAABB::getVertexN(glm::vec3& normal) {
glm::vec3 res = corner;
vec3 FrustumAABB::getVertexN(glm::vec3& normal) {
vec3 res = corner;
if (normal.x < 0) res.x += size.x;
if (normal.y < 0) res.y += size.y;

View File

@ -1,22 +1,19 @@
//
// Created by aurailus on 03/03/19.
//
#pragma once
#include <glm/vec3.hpp>
#include "util/Types.h"
/** An axis-aligned bounding box used in frustum calculations. */
class FrustumAABB {
public:
glm::vec3 corner;
glm::vec3 size;
public:
vec3 corner;
vec3 size;
FrustumAABB(glm::vec3 a, glm::vec3 b);
FrustumAABB(vec3 a, vec3 b);
void set(glm::vec3 a, glm::vec3 b);
void set(vec3 a, vec3 b);
glm::vec3 getVertexP(glm::vec3& normal);
vec3 getVertexP(vec3& normal);
glm::vec3 getVertexN(glm::vec3& normal);
vec3 getVertexN(vec3& normal);
};

View File

@ -8,12 +8,12 @@
#include "FrustumPlane.h"
void FrustumPlane::setPoints(glm::vec3& v1, glm::vec3& v2, glm::vec3& v3) {
void FrustumPlane::setPoints(vec3& v1, vec3& v2, vec3& v3) {
normal = glm::triangleNormal(v1, v2, v3);
point = v2;
d = -glm::dot(normal, point);
}
float FrustumPlane::distance(glm::vec3& p) {
float FrustumPlane::distance(vec3& p) {
return (d + glm::dot(normal, p));
}

View File

@ -1,20 +1,16 @@
//
// Created by aurailus on 02/03/19.
//
#pragma once
#include <glm/vec3.hpp>
#include "util/Types.h"
/** Represents a frustum plane. */
class FrustumPlane {
public:
glm::vec3 normal, point;
float d;
public:
vec3 normal;
vec3 point;
f32 d;
FrustumPlane() = default;
void setPoints(vec3& v1, vec3& v2, vec3& v3);
void setPoints(glm::vec3& v1, glm::vec3& v2, glm::vec3& v3);
float distance(glm::vec3& p);
f32 distance(vec3& p);
};

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 10/01/19.
//
#include "Packet.h"
#include "Serializer.h"
@ -9,7 +5,7 @@
Packet::Packet(Type type, bool reliable) : type(type), reliable(reliable) {}
ENetPacket* Packet::toENetPacket() const {
std::string serialized = Serializer().append(static_cast<unsigned int>(type)).data + data;
string serialized = Serializer().append(static_cast<u8>(type)).data + data;
ENetPacket* enet = enet_packet_create(serialized.data(), serialized.length(),
(reliable ? ENET_PACKET_FLAG_RELIABLE : 0));

View File

@ -1,16 +1,19 @@
//
// Packet implentation for easy manipulation.
// Can be converted into an ENet packet, or deserialized from one.
// Created by aurailus on 10/01/19.
//
#pragma once
#include <string>
#include <enet/enet.h>
#include "util/Types.h"
/**
* A packet stores data to send across a connection,
* allowing data transmission between the client and server.
* This class is used to create a packet,
* if the ability to read a sent packet is needed, use PacketView.
*/
class Packet {
public:
public:
/** An enum of packet channels that can be used. */
enum class Channel {
UNDEFINED = 0,
// Authentication
@ -21,6 +24,7 @@ class Packet {
WORLD, ENTITY, INTERACT
};
/** An enum of packet types that can be used. */
enum class Type {
UNDEFINED = 0,
// Information Request Types
@ -45,15 +49,24 @@ class Packet {
Packet() = default;
/** Creates a packet with the type specified. */
explicit Packet(Type type, bool reliable = true);
/** Converts the packet into a raw packet to transfer. */
ENetPacket* toENetPacket() const;
/** Sends the packet to the peer specified. */
void sendTo(ENetPeer* peer, Channel channel) const;
/** Sends the packet to the peer specified. */
void sendTo(const ENetPeer& peer, Channel channel) const;
/** The internal packet data. */
string data {};
Type type = Type::UNDEFINED;
std::string data{};
/** Whether or not the packet should be reliably sequenced. */
bool reliable = true;
/** The packet's type. */
Type type = Type::UNDEFINED;
};

View File

@ -1,11 +1,8 @@
//
// Created by aurailus on 2020-03-07.
//
#include "PacketView.h"
#include "Packet.h"
PacketView::PacketView(ENetPacket* packet) :
packet(packet, [](ENetPacket* p) { enet_packet_destroy(p); }),
d(reinterpret_cast<char*>(this->packet->data), this->packet->dataLength),
type(static_cast<Packet::Type>(d.read<unsigned int>())) {}
d(reinterpret_cast<char*>(packet->data), packet->dataLength),
type(static_cast<Packet::Type>(d.read<u8>())) {}

View File

@ -1,22 +1,30 @@
//
// Created by aurailus on 2020-03-07.
//
#pragma once
#include <memory>
#include <enet/enet.h>
#include "Deserializer.h"
#include "Packet.h"
#include "util/Types.h"
#include "Deserializer.h"
/**
* Provides a read-only view into a packet.
* Manages the internal ENetPacket's memory, only deleting it when the PacketView is destroyed.
* Initializes a deserializer instance with the packet's data.
*/
class PacketView {
public:
explicit PacketView(ENetPacket* packet);
public:
PacketView(const PacketView&) = delete;
std::shared_ptr<ENetPacket> packet;
explicit PacketView(ENetPacket* packet);
/** A deserializer to read the packet's data. */
Deserializer d;
/** The packet's type. */
Packet::Type type;
private:
/** An internal reference to the raw packet. */
sptr<ENetPacket> packet;
};

View File

@ -71,6 +71,7 @@ void LocalWorld::update(double delta) {
}
void LocalWorld::handleWorldPacket(std::unique_ptr<PacketView> p) {
std::cout << "world packet" << std::endl;
worldGenStream->queuePacket(std::move(p));
}

View File

@ -12,6 +12,7 @@
#include "game/def/BlockDef.h"
#include "lua/usertype/Target.h"
#include "util/net/Serializer.h"
#include "server/ServerClient.h"
#include "server/ServerClients.h"
#include "world/dim/chunk/Chunk.h"
#include "world/dim/chunk/MapBlock.h"
@ -89,11 +90,13 @@ void ServerWorld::update(double delta) {
auto finishedPackets = packetStream->update();
for (auto& data : *finishedPackets) {
for (auto& player : clients.players)
data->packet->sendTo(player->getPeer(), Packet::Channel::WORLD);
for (auto& client : clients.getClients()) {
if (!client.second->player) continue;
data->packet->sendTo(client.second->peer, Packet::Channel::WORLD);
}
}
this->generatedMapBlocks = genCount;
generatedMapBlocks = genCount;
// for (auto& chunkPos : updatedChunks) {
// glm::ivec3 mapBlockPos = Space::MapBlock::world::fromChunk(chunkPos);
@ -123,11 +126,12 @@ void ServerWorld::update(double delta) {
// }
// }
Packet r = Serializer().append(this->generatedMapBlocks).packet(Packet::Type::SERVER_INFO);
Packet r = Serializer().append(generatedMapBlocks).packet(Packet::Type::SERVER_INFO);
for (auto& player : clients.players) {
r.sendTo(player->getPeer(), Packet::Channel::SERVER);
if (player->changedMapBlocks) changedMapBlocks(*player);
for (auto& client : clients.getClients()) {
if (!client.second->player) return;
r.sendTo(client.second->player->getPeer(), Packet::Channel::SERVER);
if (client.second->player->changedMapBlocks) changedMapBlocks(*client.second->player);
}
for (auto& d : dimensions) {
@ -147,25 +151,22 @@ void ServerWorld::update(double delta) {
// Contains more than just the dimension identifier.
if (inf.data.size() > sizeof(u16)) {
auto p = inf.packet(Packet::Type::ENTITY_INFO);
for (auto& player : clients.players)
if (player->getDim()->getInd() == ind)
p.sendTo(player->getPeer(), Packet::Channel::ENTITY);
for (auto& client : clients.getClients())
if (client.second->player && client.second->player->getDim()->getInd() == ind)
p.sendTo(client.second->peer, Packet::Channel::ENTITY);
}
// Update clients with removed entities.
Serializer rem;
rem.append(ind);
for (i64 entity : dimension->getRemovedEntities()) {
rem.append<i64>(entity);
}
for (i64 entity : dimension->getRemovedEntities()) rem.append<i64>(entity);
if (rem.data.size() > sizeof(u16)) {
Packet p = rem.packet(Packet::Type::ENTITY_REMOVED);
for (auto& player : clients.players)
if (player->getDim()->getInd() == ind)
p.sendTo(player->getPeer(), Packet::Channel::ENTITY);
for (auto& client : clients.getClients())
if (client.second->player && client.second->player->getDim()->getInd() == ind)
p.sendTo(client.second->player->getPeer(), Packet::Channel::ENTITY);
}
dimension->clearRemovedEntities();
@ -240,6 +241,7 @@ void ServerWorld::sendChunksToPlayer(ServerPlayer& client) {
void ServerWorld::sendMessage(const string& channel, const string& message) {
auto p = Serializer().append(channel).append(message).packet(Packet::Type::MOD_MESSAGE);
for (auto& player : clients.players)
p.sendTo(player->getPeer(), Packet::Channel::ENTITY);
for (auto& client : clients.getClients())
if (client.second->player)
p.sendTo(client.second->player->getPeer(), Packet::Channel::ENTITY);
}

View File

@ -206,7 +206,7 @@ void LocalDimension::serverEntitiesInfo(Deserializer& e) {
std::shared_ptr<LocalLuaEntity> activeEntity;
if (entityRefs.count(id)) activeEntity = entityRefs.at(id)->entity.l();
else {
auto ent = std::make_shared<LocalLuaEntity>(game, world.getDimension(getInd()));
auto ent = make_shared<LocalLuaEntity>(game, world.getDimension(getInd()));
auto entity = Api::Usertype::Entity(ent);
ent->setId(id);
entities.push_back(entity);
@ -217,71 +217,83 @@ void LocalDimension::serverEntitiesInfo(Deserializer& e) {
while (!d.atEnd()) {
const auto field = d.read<NetField>();
switch (field) {
default:
default: {
std::cout << Log::err << "Entity received unhandled NetField, Type "
<< static_cast<int>(field) << "." << Log::endl;
break;
}
case NetField::POS:
case NetField::POS: {
activeEntity->setPos(d.read<vec3>());
break;
case NetField::VEL:
}
case NetField::VEL: {
activeEntity->setVel(d.read<vec3>());
break;
case NetField::ROT:
}
case NetField::ROT: {
activeEntity->setRot(d.read<vec3>());
break;
case NetField::SCALE:
}
case NetField::SCALE: {
activeEntity->setScale(d.read<vec3>());
break;
case NetField::VISUAL_OFF:
}
case NetField::VISUAL_OFF: {
activeEntity->setVisualOffset(d.read<vec3>());
break;
}
case NetField::DISPLAY: {
string mode, argA, argB;
d.read(mode).read(argA).read(argB);
activeEntity->setAppearance(mode, argA, argB);
break;
}
case NetField::ANIM_STATE: {
bool playing = d.read<bool>();
activeEntity->animation.setPlaying(playing);
break;
}
case NetField::ANIM_RANGE: {
bool loops;
uvec2 range;
d.read(range).read(loops);
uvec2 range = d.read<uvec2>();
bool loops = d.read<bool>();
activeEntity->animation.setAnim(range, 10, loops);
break;
}
case NetField::DIM:
case NetField::DIM: {
activeEntity->setDim(world.getDimension(d.read<u16>()));
break;
}
case NetField::COLLISION_BOX: {
bool hasCollisionBox = d.read<bool>();
if (hasCollisionBox) {
glm::vec3 a = d.read<glm::vec3>();
glm::vec3 b = d.read<glm::vec3>();
vec3 a = d.read<vec3>();
vec3 b = d.read<vec3>();
activeEntity->setCollisionBox({ a, b });
}
else activeEntity->removeCollisionBox();
break;
}
case NetField::COLLIDES:
case NetField::COLLIDES: {
activeEntity->setCollides(d.read<bool>());
break;
case NetField::GRAVITY:
activeEntity->setGravity(d.read<float>());
}
case NetField::GRAVITY: {
activeEntity->setGravity(d.read<f32>());
break;
}
}
}
}
}
@ -311,7 +323,7 @@ void LocalDimension::renderChunks(Renderer& renderer) {
lastMeshesDrawn = 0;
for (auto& renderElement : renderElems) {
FrustumAABB bbox(renderElement->getPos() * vec3(16), vec3(16));
if (renderer.camera.inFrustum(bbox) != Frustum::OUTSIDE) {
if (renderer.camera.inFrustum(bbox) != Frustum::Intersection::OUTSIDE) {
renderElement->draw(renderer);
lastMeshesDrawn++;
}

View File

@ -9,6 +9,7 @@
#include "game/ServerSubgame.h"
#include "lua/usertype/Player.h"
#include "lua/usertype/Target.h"
#include "server/ServerClient.h"
#include "server/ServerClients.h"
#include "world/dim/chunk/Chunk.h"
#include "world/dim/chunk/Region.h"
@ -29,10 +30,11 @@ void ServerDimension::update(double delta) {
if (!mb) continue;
bool clientNearby = false;
for (auto& player : static_cast<ServerWorld&>(world).getClients().players) {
for (auto& client : static_cast<ServerWorld&>(world).getClients().getClients()) {
if (!client.second->player) continue;
// TODO: Re-enable then **once** file saving is implemented.
// if (player->getDim()->getInd() == ind) {
auto clientPos = Space::MapBlock::world::fromBlock(player->getPos());
auto clientPos = Space::MapBlock::world::fromBlock(client.second->player->getPos());
if (abs(clientPos.x - mb->pos.x) <= discardRange.x + 1
&& abs(clientPos.y - mb->pos.y) <= discardRange.y + 1
&& abs(clientPos.z - mb->pos.z) <= discardRange.x + 1) {

View File

@ -1,79 +1,79 @@
#include "Entity.h"
#include "Collision.h"
long long Entity::getId() const {
i64 Entity::getId() const {
return id;
}
void Entity::setId(long long newId) {
void Entity::setId(i64 newId) {
id = newId;
}
glm::vec3 Entity::getPos() const {
vec3 Entity::getPos() const {
return pos;
}
void Entity::setPos(glm::vec3 newPos) {
void Entity::setPos(vec3 newPos) {
pos = newPos;
}
glm::vec3 Entity::getVel() const {
vec3 Entity::getVel() const {
return vel;
}
void Entity::setVel(glm::vec3 newVel) {
void Entity::setVel(vec3 newVel) {
vel = newVel;
}
glm::vec3 Entity::getRot() const {
vec3 Entity::getRot() const {
return rot;
}
void Entity::setRot(glm::vec3 newRot) {
void Entity::setRot(vec3 newRot) {
rot = newRot;
}
float Entity::getRotateX() const {
f32 Entity::getRotateX() const {
return rot.x;
}
void Entity::setRotateX(float newRotateX) {
void Entity::setRotateX(f32 newRotateX) {
rot.x = newRotateX;
}
float Entity::getRotateY() const {
f32 Entity::getRotateY() const {
return rot.y;
}
void Entity::setRotateY(float newRotateY) {
void Entity::setRotateY(f32 newRotateY) {
rot.y = newRotateY;
}
float Entity::getRotateZ() const {
f32 Entity::getRotateZ() const {
return rot.z;
}
void Entity::setRotateZ(float newRotateZ) {
void Entity::setRotateZ(f32 newRotateZ) {
rot.z = newRotateZ;
}
glm::vec3 Entity::getScale() const {
vec3 Entity::getScale() const {
return scale;
}
void Entity::setScale(float newScale) {
void Entity::setScale(f32 newScale) {
scale = glm::vec3(newScale);
}
void Entity::setScale(glm::vec3 newScale) {
void Entity::setScale(vec3 newScale) {
scale = newScale;
}
glm::vec3 Entity::getVisualOffset() const {
vec3 Entity::getVisualOffset() const {
return visualOff;
}
void Entity::setVisualOffset(glm::vec3 newVisualOff) {
void Entity::setVisualOffset(vec3 newVisualOff) {
visualOff = newVisualOff;
}
@ -105,11 +105,11 @@ void Entity::setCollides(bool newCollides) {
collides = newCollides;
}
float Entity::getGravity() const {
f32 Entity::getGravity() const {
return gravity;
}
void Entity::setGravity(float newGravity) {
void Entity::setGravity(f32 newGravity) {
gravity = newGravity;
}
@ -117,19 +117,20 @@ SubgamePtr Entity::getGame() const {
return game;
}
void Entity::update(double delta) {
static constexpr float TERMINAL_VELOCITY = 150.f;
void Entity::update(f64 delta) {
static constexpr f32 TERMINAL_VELOCITY = 150.f;
animation.update(delta);
if (vel.length() != 0) {
if (collides) {
glm::vec3 newPos, newVel;
std::tie(newPos, newVel) = Collision::applyVel(game, dim, *collisionBox, pos, vel, delta);
vec3 newPos, newVel;
std::tie(newPos, newVel) = Collision::applyVel(
game, dim, *collisionBox, pos, vel, delta);
setPos(newPos);
setVel(newVel);
}
else setPos(getPos() + vel * static_cast<float>(delta));
else setPos(getPos() + vel * static_cast<f32>(delta));
}
if (gravity) {

View File

@ -1,7 +1,6 @@
#pragma once
#include <glm/vec3.hpp>
#include "util/Types.h"
#include "AnimationState.h"
#include "util/CovariantPtr.h"
#include "game/def/mesh/SelectionBox.h"
@ -23,7 +22,7 @@ public:
* @returns the unique id.
*/
virtual long long getId() const;
virtual i64 getId() const;
/**
* Sets the unique ID of the entity.
@ -32,126 +31,126 @@ public:
* @param newId - The desired ID.
*/
virtual void setId(long long newId);
virtual void setId(i64 newId);
/**
* Gets the entity's current position.
* @returns the entity's current position as a vector.
*/
virtual glm::vec3 getPos() const;
virtual vec3 getPos() const;
/**
* Moves the entity to the specified position.
* @param newPos - The desired position as a vector.
*/
virtual void setPos(glm::vec3 newPos);
virtual void setPos(vec3 newPos);
/**
* Gets the entity's current velocity.
* @returns the entity's current velocity as a vector.
*/
virtual glm::vec3 getVel() const;
virtual vec3 getVel() const;
/**
* Moves the entity to the specified position.
* @param newVel - The desired velocity as a vector.
*/
virtual void setVel(glm::vec3 newVel);
virtual void setVel(vec3 newVel);
/**
* Returns the entity's current rotation across all 3 axises as a vector.
* @returns the entity's rotation.
*/
virtual glm::vec3 getRot() const;
virtual vec3 getRot() const;
/**
* Sets the entity's rotation across all three axises.
* @param newRot - The desired rotation of the entity.
*/
virtual void setRot(glm::vec3 newRot);
virtual void setRot(vec3 newRot);
/**
* Returns the X component of the entity's rotation vector.
* @returns the entity's X rotation.
*/
virtual float getRotateX() const;
virtual f32 getRotateX() const;
/**
* Sets the X component of the entity's rotation vector.
* @param newRotateX - The desired rotation, in radians.
*/
virtual void setRotateX(float newRotateX);
virtual void setRotateX(f32 newRotateX);
/**
* Returns the Y component of the entity's rotation vector.
* @returns the entity's Y rotation.
*/
virtual float getRotateY() const;
virtual f32 getRotateY() const;
/**
* Sets the Y component of the entity's rotation vector.
* @param newRotateY - The desired rotation, in radians.
*/
virtual void setRotateY(float newRotateY);
virtual void setRotateY(f32 newRotateY);
/**
* Returns the Z component of the entity's rotation vector.
* @returns the entity's Z rotation.
*/
virtual float getRotateZ() const;
virtual f32 getRotateZ() const;
/**
* Sets the Z component of the entity's rotation vector.
* @param newRotateZ - The desired rotation, in radians.
*/
virtual void setRotateZ(float newRotateZ);
virtual void setRotateZ(f32 newRotateZ);
/**
* Gets the entity's model scale.
* @returns the scale vector of the entity's model.
*/
virtual glm::vec3 getScale() const;
virtual vec3 getScale() const;
/**
* Sets the scale of the entity's model to a float value.
* @param newScale - The desired scale multiplier.
*/
virtual void setScale(float newScale);
virtual void setScale(f32 newScale);
/**
* Sets the scale of the entity's model to a vector.
* @param newScale - The desired scale multiplier.
*/
virtual void setScale(glm::vec3 newScale);
virtual void setScale(vec3 newScale);
/**
* Gets the entity's model's display offset relative to its position.
* @returns the visual offset of the entity.
*/
virtual glm::vec3 getVisualOffset() const;
virtual vec3 getVisualOffset() const;
/**
* Sets the entity's model's display offset relative to its position.
* @param newVisualOff - The desired visual offset for the entity.
*/
virtual void setVisualOffset(glm::vec3 newVisualOff);
virtual void setVisualOffset(vec3 newVisualOff);
/**
@ -208,7 +207,7 @@ public:
* @returns the entity's coefficient of gravity.
*/
virtual float getGravity() const;
virtual f32 getGravity() const;
/**
* Sets the entity's coefficient of gravity.
@ -216,7 +215,7 @@ public:
* @param newGravity - The desired coefficient of gravity.
*/
virtual void setGravity(float newGravity);
virtual void setGravity(f32 newGravity);
/**
@ -231,7 +230,7 @@ public:
* @param delta - The last frame's delta time.
*/
virtual void update(double delta);
virtual void update(f64 delta);
/** The animation state of the entity. */
AnimationState animation {};

View File

@ -88,62 +88,75 @@ std::string ServerLuaEntity::serialize() {
dirtyFields.erase(field);
switch (field) {
default:
default: {
std::cout << Log::err << "Entity tried to serialize unhandled NetField, Type "
<< static_cast<int>(field) << "." << Log::endl;
<< static_cast<int>(field) << "." << Log::endl;
break;
}
case NetField::ALL:
case NetField::POS:
case NetField::POS: {
s.append(NetField::POS).append(pos);
if (field != NetField::ALL) break;
}
case NetField::VEL:
case NetField::VEL: {
s.append(NetField::VEL).append(vel);
if (field != NetField::ALL) break;
}
case NetField::ROT:
case NetField::ROT: {
s.append(NetField::ROT).append(rot);
if (field != NetField::ALL) break;
}
case NetField::SCALE:
case NetField::SCALE: {
s.append(NetField::SCALE).append(scale);
if (field != NetField::ALL) break;
}
case NetField::VISUAL_OFF:
case NetField::VISUAL_OFF: {
s.append(NetField::VISUAL_OFF).append(visualOff);
if (field != NetField::ALL) break;
case NetField::DISPLAY:
}
case NetField::DISPLAY: {
s.append(NetField::DISPLAY).append(dMode).append(dArgA).append(dArgB);
if (field != NetField::ALL) break;
case NetField::ANIM_STATE:
}
case NetField::ANIM_STATE: {
s.append(NetField::ANIM_STATE).append<bool>(animation.isPlaying());
if (field != NetField::ALL) break;
case NetField::ANIM_RANGE:
}
case NetField::ANIM_RANGE: {
s.append(NetField::ANIM_RANGE).append(animation.getBounds()).append<bool>(animation.isLooping());
if (field != NetField::ALL) break;
case NetField::DIM:
}
case NetField::DIM: {
s.append(NetField::DIM).append(dim->getInd());
if (field != NetField::ALL) break;
}
case NetField::COLLISION_BOX:
case NetField::COLLISION_BOX: {
s.append(NetField::COLLISION_BOX).append<bool>(collisionBox.has_value());
if (collisionBox) s.append(collisionBox->a).append(collisionBox->b);
if (field != NetField::ALL) break;
}
case NetField::COLLIDES:
case NetField::COLLIDES: {
s.append(NetField::COLLIDES).append(collides);
if (field != NetField::ALL) break;
case NetField::GRAVITY:
}
case NetField::GRAVITY: {
s.append(NetField::GRAVITY).append(gravity);
if (field != NetField::ALL) break;
}
}
}
return s.data;

View File

@ -12,10 +12,10 @@
#include "world/dim/chunk/Chunk.h"
#include "game/atlas/DefinitionAtlas.h"
MapGen::MapGen(Subgame& game, World& world, unsigned int seed, std::unordered_set<std::string> biomes) :
MapGen::MapGen(Subgame& game, World& world, u32 seed, std::unordered_set<string> biomes) :
game(game), world(world), props(seed) {
std::unordered_set<unsigned int> biomeIndices {};
std::unordered_set<u16> biomeIndices {};
for (const auto& str : biomes) {
if (str[0] == '#')
for (auto& biome : game.getBiomes().biomesFromTag(str.substr(1, str.length() - 1)))
@ -26,22 +26,22 @@ MapGen::MapGen(Subgame& game, World& world, unsigned int seed, std::unordered_se
generateVoronoi(biomeIndices);
}
[[maybe_unused]] std::unique_ptr<MapGen::CreatedSet> MapGen::generateChunk(unsigned int dim, glm::ivec3 pos) {
[[maybe_unused]] uptr<MapGen::CreatedSet> MapGen::generateChunk(u16 dim, ivec3 pos) {
return generateArea(dim, pos, 1);
}
std::unique_ptr<MapGen::CreatedSet> MapGen::generateMapBlock(unsigned int dim, glm::ivec3 pos) {
return generateArea(dim, Space::Chunk::world::fromMapBlock(glm::vec3(pos)), 4);
uptr<MapGen::CreatedSet> MapGen::generateMapBlock(u16 dim, ivec3 pos) {
return generateArea(dim, Space::Chunk::world::fromMapBlock(pos), 4);
}
std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::ivec3 origin, unsigned int size) {
std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(u16 dim, ivec3 origin, u16 size) {
Job job(origin, size);
// Build Biome Prop Maps
const auto fill = [&](const noise::module::Module& s) {
return [&](glm::vec3 pos) {
glm::vec3 worldPos = glm::vec3(job.pos) + pos * static_cast<float>(job.size);
return [&](vec3 pos) {
vec3 worldPos = vec3(job.pos) + pos * static_cast<f32>(job.size);
return s.GetValue(worldPos.x, 0, worldPos.z);
};
};
@ -52,12 +52,12 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
// Generate Biome Topmap
std::vector<unsigned int> biomeMap {};
vec<u16> biomeMap {};
biomeMap.resize((job.size * 16 + 1) * (job.size * 16 + 1));
for (unsigned short i = 0; i < biomeMap.size(); i++) {
glm::vec3 indPos = { i / (job.size * 16 + 1), 0, i % (job.size * 16 + 1) };
glm::vec3 queryPos = indPos / 16.f / static_cast<float>(job.size);
for (usize i = 0; i < biomeMap.size(); i++) {
vec3 indPos = { i / (job.size * 16 + 1), 0, i % (job.size * 16 + 1) };
vec3 queryPos = indPos / 16.f / static_cast<f32>(job.size);
biomeMap[i] = getBiomeAt(job.temperature.get(queryPos),
job.humidity.get(queryPos), job.roughness.get(queryPos));
@ -65,34 +65,34 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
// Generate Heightmap and Volume
job.heightmap.populate([&](glm::vec3 pos) {
glm::ivec3 blockPos = glm::ivec3(pos * 16.f * static_cast<float>(job.size));
job.heightmap.populate([&](vec3 pos) {
ivec3 blockPos = ivec3(pos * 16.f * static_cast<f32>(job.size));
auto& biome = game.getBiomes().biomeFromId(biomeMap.at(blockPos.x * (job.size * 16 + 1) + blockPos.z));
glm::vec3 worldPos = glm::vec3(job.pos) + pos * static_cast<float>(job.size);
vec3 worldPos = vec3(job.pos) + pos * static_cast<f32>(job.size);
return biome.heightmap[biome.heightmap.size() - 1]->GetValue(worldPos.x, 0, worldPos.z);
});
job.volume.populate([&](glm::vec3 pos) {
glm::ivec3 blockPos = glm::ivec3(pos * 16.f * static_cast<float>(job.size));
job.volume.populate([&](vec3 pos) {
ivec3 blockPos = ivec3(pos * 16.f * static_cast<f32>(job.size));
auto& biome = game.getBiomes().biomeFromId(biomeMap.at(blockPos.x * (job.size * 16 + 1) + blockPos.z));
glm::vec3 worldPos = glm::vec3(job.pos) + pos * static_cast<float>(job.size);
vec3 worldPos = vec3(job.pos) + pos * static_cast<f32>(job.size);
return biome.volume[biome.volume.size() - 1]->GetValue(worldPos.x, worldPos.y, worldPos.z);
});
// Generate Chunks
glm::ivec3 pos {};
u16vec3 pos {};
for (pos.x = 0; pos.x < job.size; pos.x++) {
for (pos.z = 0; pos.z < job.size; pos.z++) {
std::unique_ptr<ChunkData> densityAbove = nullptr;
uptr<ChunkData> densityAbove = nullptr;
for (pos.y = job.size; pos.y >= 0; pos.y--) {
// if (pos.y == job.size) {
// densityAbove = populateChunkDensity(job, pos);
// continue;
// }
if (pos.y == job.size) {
densityAbove = populateChunkDensity(job, pos);
continue;
}
//
// std::unique_ptr<ChunkData> density = populateChunkDensity(job, pos);
// std::unique_ptr<ChunkData> depth = populateChunkDepth(density, std::move(densityAbove));
uptr<ChunkData> density = populateChunkDensity(job, pos);
// uptr<ChunkData> depth = populateChunkDepth(density, std::move(densityAbove));
//
// std::cout << "were out da function " << pos.x << ", " << pos.y << ", " << pos.z << std::endl;
// std::cout << &job << " " << &pos << " " << &biomeMap << " " << &depth << std::endl;
@ -100,8 +100,8 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
// generateChunkBlocks(job, pos, biomeMap, *depth);
// generateChunkDecorAndLight(job, pos, biomeMap, *depth);
glm::ivec3 chunkPos = job.pos + pos;
job.chunks->emplace(chunkPos, std::make_shared<Chunk>(chunkPos));
ivec3 chunkPos = job.pos + ivec3(pos);
job.chunks->emplace(chunkPos, make_shared<Chunk>(chunkPos));
// densityAbove = std::move(density);
}
@ -110,7 +110,7 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
propogateSunlightNodes(job);
auto created = std::make_unique<CreatedSet>();
auto created = make_unique<CreatedSet>();
for (const auto& chunk : *job.chunks) {
created->emplace(chunk.first);
// world.getDimension(dim)->setChunk(chunk.second);
@ -119,53 +119,51 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
return std::move(created);
}
void MapGen::generateVoronoi(const std::unordered_set<unsigned int>& biomes) {
std::vector<std::pair<glm::vec3, unsigned short>> points {};
void MapGen::generateVoronoi(const std::unordered_set<u16>& biomes) {
vec<std::pair<vec3, u16>> points {};
for (auto biomeInd : biomes) {
auto& biome = game.getBiomes().biomeFromId(biomeInd);
points.emplace_back(glm::vec3 {
static_cast<unsigned short>(std::fmin(voronoiSize - 1,
points.emplace_back(vec3 {
static_cast<u16>(std::fmin(voronoiSize - 1,
std::fmax(0, (biome.temperature + 1) / 2 * voronoiSize))),
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, biome.humidity * voronoiSize))),
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, biome.roughness * voronoiSize)))
static_cast<u16>(std::fmin(voronoiSize - 1, std::fmax(0, biome.humidity * voronoiSize))),
static_cast<u16>(std::fmin(voronoiSize - 1, std::fmax(0, biome.roughness * voronoiSize)))
}, biomeInd);
}
voronoi.setPoints(points);
}
unsigned int MapGen::getBiomeAt(float temperature, float humidity, float roughness) {
u16 MapGen::getBiomeAt(f32 temperature, f32 humidity, f32 roughness) {
return voronoi.getPoint(
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, (temperature + 1) / 2 * voronoiSize))),
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, humidity * voronoiSize))),
static_cast<unsigned short>(std::fmin(voronoiSize - 1, std::fmax(0, roughness * voronoiSize))));
static_cast<u16>(std::fmin(voronoiSize - 1, std::fmax(0, (temperature + 1) / 2 * voronoiSize))),
static_cast<u16>(std::fmin(voronoiSize - 1, std::fmax(0, humidity * voronoiSize))),
static_cast<u16>(std::fmin(voronoiSize - 1, std::fmax(0, roughness * voronoiSize))));
}
std::unique_ptr<MapGen::ChunkData> MapGen::populateChunkDensity(MapGen::Job& job, glm::ivec3 localPos) {
auto data = std::make_unique<ChunkData>();
uptr<MapGen::ChunkData> MapGen::populateChunkDensity(MapGen::Job& job, ivec3 localPos) {
auto data = make_unique<ChunkData>();
for (unsigned short i = 0; i < 4096; i++) {
glm::ivec3 indPos = Space::Block::fromIndex(i);
glm::vec3 queryPos = (glm::vec3(localPos) + glm::vec3(indPos) / 16.f) / static_cast<float>(job.size);
(*data)[i] = (job.volume.get(queryPos) + job.heightmap.get({ queryPos.x, 0, queryPos.z })) -
((job.pos.y + localPos.y) * 16 + indPos.y);
for (u16 i = 0; i < 4096; i++) {
ivec3 indPos = Space::Block::fromIndex(i);
vec3 queryPos = (vec3(localPos) + vec3(indPos) / 16.f) / static_cast<f32>(job.size);
(*data)[i] = (job.volume.get(queryPos) + job.heightmap.get({ queryPos.x, 0, queryPos.z }))
- ((job.pos.y + localPos.y) * 16 + indPos.y);
}
return data;
}
std::unique_ptr<MapGen::ChunkData> MapGen::populateChunkDepth(std::unique_ptr<ChunkData>& chunkDensity,
std::unique_ptr<ChunkData> chunkDensityAbove) {
uptr<MapGen::ChunkData> MapGen::populateChunkDepth(uptr<ChunkData>& chunkDensity, uptr<ChunkData> chunkDensityAbove) {
auto data = make_unique<ChunkData>();
auto data = std::make_unique<ChunkData>();
for (unsigned short i = 0; i < 256; i++) {
glm::ivec2 pos = { i / 16, i % 16 };
for (u16 i = 0; i < 256; i++) {
ivec2 pos = { i / 16, i % 16 };
short depth = 16;
if ((*chunkDensity)[Space::Block::index({ pos.x, 15, pos.y })] > 0) {
for (unsigned char j = 0; j < 16; j++) {
for (u8 j = 0; j < 16; j++) {
if ((*chunkDensityAbove)[Space::Block::index({ pos.x, j, pos.y })] <= 0) {
depth = j;
break;
@ -176,8 +174,8 @@ std::unique_ptr<MapGen::ChunkData> MapGen::populateChunkDepth(std::unique_ptr<Ch
depth = 0;
}
for (char y = 15; y >= 0; y--) {
unsigned int ind = Space::Block::index({ pos.x, y, pos.y });
for (i8 y = 15; y >= 0; y--) {
u16 ind = Space::Block::index({ pos.x, y, pos.y });
depth = ((*chunkDensity)[ind] > 0 ? std::min(depth + 1, 16) : 0);
(*data)[ind] = depth;
}
@ -186,34 +184,26 @@ std::unique_ptr<MapGen::ChunkData> MapGen::populateChunkDepth(std::unique_ptr<Ch
return data;
}
void MapGen::generateChunkBlocks(Job& job, glm::ivec3 localPos,
std::vector<unsigned int> biomeMap, ChunkData& depthMap) {
void MapGen::generateChunkBlocks(Job& job, ivec3 localPos, vec<u16> biomeMap, ChunkData& depthMap) {
std::cout << "were in da function " << std::endl;
glm::ivec3 chunkPos = job.pos + localPos;
ivec3 chunkPos = job.pos + localPos;
auto partial = (job.chunks->count(chunkPos) ? job.chunks->at(chunkPos) : nullptr);
if (partial) job.chunks->erase(chunkPos);
auto& chunk = *(*job.chunks->emplace(chunkPos, std::make_shared<Chunk>(chunkPos)).first).second;
unsigned int partialBlock = DefinitionAtlas::INVALID;
u16 partialBlock = DefinitionAtlas::INVALID;
for (unsigned short i = 0; i < 4096; i++) {
for (u16 i = 0; i < 4096; i++) {
ivec3 indPos = Space::Block::fromIndex(i);
unsigned int biomeID = biomeMap[(localPos.x * 16 + indPos.x) *
(job.size * 16 + 1) + (localPos.z * 16 + indPos.z)];
u16 biomeID = biomeMap[(localPos.x * 16 + indPos.x) * (job.size * 16 + 1) + (localPos.z * 16 + indPos.z)];
auto& biome = game.getBiomes().biomeFromId(biomeID);
//
// if (partial && i >= partialNextAt) {
// partialInd++;
// partialBlock = partial->d->blocks[partialInd * 2 + 1];
// partialNextAt = (partialInd * 2 + 2 >= partial->d->blocks.size()) ? 4096 : partial->d->blocks[partialInd * 2 + 2];
// }
float depth = depthMap[i];
unsigned int blockID =
f32 depth = depthMap[i];
u16 blockID =
partialBlock > DefinitionAtlas::INVALID ? partialBlock
: depth <= 1 ? DefinitionAtlas::AIR
: depth <= 2 ? biome.topBlock
@ -228,45 +218,45 @@ void MapGen::generateChunkBlocks(Job& job, glm::ivec3 localPos,
chunk.countRenderableBlocks();
}
void MapGen::generateChunkDecorAndLight(Job& job, glm::ivec3 localPos, std::vector<unsigned int> biomeMap,
void MapGen::generateChunkDecorAndLight(Job& job, ivec3 localPos, vec<u16> biomeMap,
ChunkData& depthMap) {
glm::vec3 posFloat = job.pos + localPos;
vec3 posFloat = job.pos + localPos;
std::default_random_engine generator(posFloat.x + posFloat.y * M_PI + posFloat.z * (M_PI * 2));
std::uniform_real_distribution<float> distribution(0, 1);
std::uniform_real_distribution<f32> distribution(0, 1);
auto& chunk = job.chunks->at(job.pos + localPos);
glm::ivec3 abovePos = job.pos + localPos + glm::ivec3 { 0, 1, 0 };
std::shared_ptr<Chunk> above = (localPos.y != job.size - 1) ?
ivec3 abovePos = job.pos + localPos + ivec3 { 0, 1, 0 };
sptr<Chunk> above = (localPos.y != job.size - 1) ?
job.chunks->count(abovePos) ? job.chunks->at(abovePos) : nullptr : nullptr;
for (unsigned short i = 0; i < 256; i++) {
glm::ivec3 indPos = { i / 16, 15, i % 16 };
for (u16 i = 0; i < 256; i++) {
ivec3 indPos = { i / 16, 15, i % 16 };
unsigned int biomeID = biomeMap[(localPos.x * 16 + indPos.x)
u16 biomeID = biomeMap[(localPos.x * 16 + indPos.x)
* (job.size * 16 + 1) + (localPos.z * 16 + indPos.z)];
auto& biome = game.getBiomes().biomeFromId(biomeID);
short schemID = -1;
for (short j = 0; j < biome.schematics.size(); j++) {
u16 schemID = -1;
for (u16 j = 0; j < biome.schematics.size(); j++) {
if (distribution(generator) > 1 - biome.schematics[j]->probability) {
schemID = j;
break;
}
}
char light = -1;
i8 light = -1;
for (; indPos.y >= 0 && (light || schemID > -1); indPos.y--) {
unsigned short ind = Space::Block::index(indPos);
u16 ind = Space::Block::index(indPos);
if (schemID > -1 && depthMap[ind] > 1 && depthMap[ind] <= 2) {
glm::ivec3 pos = (job.pos + localPos) * 16 + indPos;
if (schemID > UINT16_MAX && depthMap[ind] > 1 && depthMap[ind] <= 2) {
ivec3 pos = (job.pos + localPos) * 16 + indPos;
pos.y++; // Compensate for the fact that we're finding solid positions.
auto& schematic = biome.schematics[schemID];
for (unsigned int j = 0; j < schematic->length(); j++) {
glm::ivec3 off = schematic->getOffset(j);
for (usize j = 0; j < schematic->length(); j++) {
ivec3 off = schematic->getOffset(j);
setBlock(job, pos + off - schematic->origin, schematic->layout[j], chunk);
}
break;
@ -289,15 +279,15 @@ void MapGen::generateChunkDecorAndLight(Job& job, glm::ivec3 localPos, std::vect
chunk->generationState = Chunk::GenerationState::GENERATED;
}
void MapGen::setBlock(MapGen::Job& job, glm::ivec3 worldPos, unsigned int block, std::shared_ptr<Chunk> hint) {
void MapGen::setBlock(MapGen::Job& job, ivec3 worldPos, u16 block, sptr<Chunk> hint) {
if (block == DefinitionAtlas::INVALID) return;
unsigned int ind = Space::Block::index(worldPos);
u16 ind = Space::Block::index(worldPos);
if (hint && Space::Chunk::world::fromBlock(worldPos) == hint->getPos()) {
if (hint->getBlock(ind) <= DefinitionAtlas::AIR) hint->setBlock(ind, block);
}
else {
glm::ivec3 chunkPos = Space::Chunk::world::fromBlock(worldPos);
ivec3 chunkPos = Space::Chunk::world::fromBlock(worldPos);
auto& chunk = *(*job.chunks->emplace(chunkPos, std::make_shared<Chunk>(chunkPos, true)).first).second;
if (chunk.getBlock(ind) <= DefinitionAtlas::AIR) chunk.setBlock(ind, block);
}

View File

@ -26,22 +26,22 @@ class DefinitionAtlas;
class MapGen {
public:
/** The precision of the Biome map, as a divisor of the chunk size. */
constexpr static unsigned int BIOP = 4;
constexpr static u8 BIOP = 4;
/** The precision of the Terrain maps, as a divisor of the chunk size. */
constexpr static unsigned int TERP = 4;
constexpr static u8 TERP = 4;
/** A type alias for the returned list of chunk positions that were generated. */
typedef std::unordered_set<glm::ivec3, Vec::ivec3> CreatedSet;
typedef std::unordered_set<ivec3, Vec::ivec3> CreatedSet;
/**
* A struct representing a single position in a chunk at which sunlight should be updated at.
*/
struct SunlightNode {
SunlightNode(unsigned short index, Chunk* chunk) : index(index), chunk(chunk) {};
SunlightNode(u16 index, Chunk* chunk) : index(index), chunk(chunk) {};
unsigned short index;
u16 index;
Chunk* chunk;
};
@ -52,7 +52,7 @@ public:
struct Job {
/** A type alias for the type the map of Chunks stored in the Job. */
typedef std::unordered_map<glm::ivec3, std::shared_ptr<Chunk>, Vec::ivec3> ChunkMap;
typedef std::unordered_map<ivec3, std::shared_ptr<Chunk>, Vec::ivec3> ChunkMap;
/**
* Creates a new job with the root position and size specified, and initializes the NoiseSample params.
@ -60,22 +60,22 @@ public:
* @param size - The size in chunks of the job.
*/
Job(glm::ivec3 pos, unsigned int size) :
Job(ivec3 pos, u16 size) :
pos(pos), size(size),
volume {{ size * TERP, (size + 1) * TERP }, { 1, 1.25 }}, heightmap {{ size * TERP, 0 }},
temperature {{ size * BIOP, 0 }}, roughness {{ size * BIOP, 0 }}, humidity {{ size * BIOP, 0 }} {}
glm::ivec3 pos {};
unsigned int size {};
ivec3 pos {};
u16 size {};
std::unique_ptr<ChunkMap> chunks = std::make_unique<ChunkMap>();
uptr<ChunkMap> chunks = make_unique<ChunkMap>();
std::queue<SunlightNode> sunlightQueue {};
NoiseSample volume, heightmap;
NoiseSample temperature, humidity, roughness;
};
typedef std::array<float, 4096> ChunkData;
typedef array<f32, 4096> ChunkData;
MapGen(const MapGen& o) = delete;
@ -88,7 +88,7 @@ public:
* @param biomes - A list of biome identifiers or tags to include in generation.
*/
MapGen(Subgame& game, World& world, unsigned int seed, std::unordered_set<std::string> biomes);
MapGen(Subgame& game, World& world, u32 seed, std::unordered_set<string> biomes);
/**
* Generate a single chunk at the dimension and position provided.
@ -100,7 +100,7 @@ public:
* @returns a set of positions that were generated by this function call.
*/
[[maybe_unused]] std::unique_ptr<CreatedSet> generateChunk(unsigned int dim, glm::ivec3 pos);
[[maybe_unused]] uptr<CreatedSet> generateChunk(u16 dim, ivec3 pos);
/**
* Generate a mapblock at the dimension and position provided.
@ -112,7 +112,7 @@ public:
* @returns a set of positions that were generated by this function call.
*/
std::unique_ptr<CreatedSet> generateMapBlock(unsigned int dim, glm::ivec3 pos);
uptr<CreatedSet> generateMapBlock(u16 dim, ivec3 pos);
/**
* The underlying generate function called by both generateMapBlock and generateChunk.
@ -124,7 +124,7 @@ public:
* @return - A set of positions that were generated by this function call.
*/
std::unique_ptr<CreatedSet> generateArea(unsigned int dim, glm::ivec3 origin, unsigned int size = 1);
uptr<CreatedSet> generateArea(u16 dim, ivec3 origin, u16 size = 1);
private:
@ -138,7 +138,7 @@ private:
* @returns the biome index of the environmentally closest biome.
*/
unsigned int getBiomeAt(float temperature, float humidity, float roughness);
u16 getBiomeAt(f32 temperature, f32 humidity, f32 roughness);
/**
* Generate the Vonoroi biome map, using the biomes listed,
@ -147,7 +147,7 @@ private:
* @param biomes - The biomes to add to the map.
*/
void generateVoronoi(const std::unordered_set<unsigned int>& biomes);
void generateVoronoi(const std::unordered_set<u16>& biomes);
/**
* Create a density array for a chunk using a generation Job and an offset within it.
@ -158,7 +158,7 @@ private:
* @returns a ChunkData array containing the chunk's density.
*/
static std::unique_ptr<ChunkData> populateChunkDensity(Job& job, glm::ivec3 localPos);
static uptr<ChunkData> populateChunkDensity(Job& job, ivec3 localPos);
/**
* Create a depth array for a chunk using a generation Job and the chunk densities around it.
@ -169,8 +169,7 @@ private:
* @returns a ChunkData array containing the chunk's depth.
*/
static std::unique_ptr<ChunkData> populateChunkDepth(std::unique_ptr<ChunkData>& chunkDensity,
std::unique_ptr<ChunkData> chunkDensityAbove);
static uptr<ChunkData> populateChunkDepth(uptr<ChunkData>& chunkDensity, uptr<ChunkData> chunkDensityAbove);
/**
* Generates a chunk's blocks from a generation Job and an offset within it, and inserts it into the Job.
@ -185,7 +184,7 @@ private:
* @param depthMap - The depth map of the chunk being generated.
*/
void generateChunkBlocks(Job& job, glm::ivec3 localPos, std::vector<unsigned int> biomeMap, ChunkData& depthMap);
void generateChunkBlocks(Job& job, ivec3 localPos, vec<u16> biomeMap, ChunkData& depthMap);
/**
* Generates structures for a Chunk based on data within the generation job and an offset within it.
@ -198,8 +197,7 @@ private:
* @param depthMap - The depth map of the chunk being generated.
*/
void generateChunkDecorAndLight(Job& job, glm::ivec3 localPos,
std::vector<unsigned int> biomeMap, ChunkData& depthMap);
void generateChunkDecorAndLight(Job& job, ivec3 localPos, vec<u16> biomeMap, ChunkData& depthMap);
/**
* Sets a block at the position specified into the Job, if the block at said position is not filled by
@ -212,7 +210,7 @@ private:
* @param hint - An optional parameter that may speed up the function if set to the chunk to set to.
*/
static void setBlock(Job& job, glm::ivec3 worldPos, unsigned int block, std::shared_ptr<Chunk> hint);
static void setBlock(Job& job, ivec3 worldPos, u16 block, sptr<Chunk> hint);
/**
* Calculates and smooths sunlight for an entire Job's chunks.
@ -222,10 +220,10 @@ private:
void propogateSunlightNodes(Job& job);
u32 seed = 0;
MapGenProps props;
unsigned int seed = 0;
constexpr const static unsigned short voronoiSize = 64;
constexpr const static u16 voronoiSize = 64;
Voronoi3D voronoi { voronoiSize };
Subgame& game;

View File

@ -1,24 +1,20 @@
//
// Created by aurailus on 15/02/19.
//
#include "NoiseSample.h"
NoiseSample::NoiseSample(unsigned int precision, float scaleBy) : NoiseSample({ precision, precision },
{ scaleBy, scaleBy }) {}
NoiseSample::NoiseSample(u16 precision, f32 scaleBy) :
NoiseSample({ precision, precision }, { scaleBy, scaleBy }) {}
NoiseSample::NoiseSample(glm::ivec2 precision, glm::vec2 scaleBy) :
NoiseSample::NoiseSample(u16vec2 precision, glm::vec2 scaleBy) :
precision(precision.x, precision.y, precision.x),
scaleBy(scaleBy.x, scaleBy.y, scaleBy.x) {
data.resize((this->precision.x + 1) * (this->precision.y + 1) * (this->precision.z + 1));
}
void NoiseSample::populate(const NoiseSample::fill_function& fn) {
glm::vec3 pos;
for (pos.x = 0; pos.x <= precision.x; pos.x++)
for (pos.y = 0; pos.y <= precision.y; pos.y++)
for (pos.z = 0; pos.z <= precision.z; pos.z++) {
glm::vec3 queryPos = pos / glm::vec3(precision) * scaleBy;
vec3 pos {}, precisionFloat = vec3(precision);
for (pos.x = 0; pos.x <= precisionFloat.x; pos.x++)
for (pos.y = 0; pos.y <= precisionFloat.y; pos.y++)
for (pos.z = 0; pos.z <= precisionFloat.z; pos.z++) {
vec3 queryPos = pos / precisionFloat * scaleBy;
if (queryPos.y == NAN) queryPos.y = 0;
data[index(pos.x, pos.y, pos.z)] = fn(queryPos);
}

View File

@ -1,35 +1,31 @@
//
// Created by aurailus on 15/02/19.
//
#pragma once
#include <vector>
#include <functional>
#include <glm/glm.hpp>
#include "util/Types.h"
#include "util/Interp.h"
class NoiseSample {
public:
typedef std::function<float(glm::vec3 pos)> fill_function;
public:
typedef std::function<f32(vec3 pos)> fill_function;
NoiseSample(unsigned int precision, float scaleBy = 1);
NoiseSample(u16 precision, f32 scaleBy = 1);
NoiseSample(glm::ivec2 precision, glm::vec2 scaleBy = { 1, 1 });
NoiseSample(u16vec2 precision, vec2 scaleBy = vec2(1));
void populate(const fill_function& fn);
inline float get(glm::vec3 pos) {
glm::vec3 scaled = pos * glm::vec3(precision) / scaleBy;
inline f32 get(vec3 pos) {
vec3 scaled = pos * vec3(precision) / scaleBy;
glm::ivec3 a = { scaled.x, scaled.y, scaled.z };
glm::vec3 factor = { scaled.x - a.x, scaled.y - a.y, scaled.z - a.z };
glm::ivec3 b = { NoiseSample::min(int(std::ceil(scaled.x)), precision.x),
NoiseSample::min(int(std::ceil(scaled.y)), precision.y),
NoiseSample::min(int(std::ceil(scaled.z)), precision.z) };
ivec3 a = { scaled.x, scaled.y, scaled.z };
vec3 factor = { scaled.x - a.x, scaled.y - a.y, scaled.z - a.z };
ivec3 b = {
(std::min)(static_cast<i32>(std::ceil(scaled.x)), precision.x),
(std::min)(static_cast<i32>(std::ceil(scaled.y)), precision.y),
(std::min)(static_cast<i32>(std::ceil(scaled.z)), precision.z) };
// assert(a.x + factor.x <= precision.x && a.y + factor.y <= precision.y && a.z + factor.z <= precision.z);
assert(index(b.x, b.y, b.z) < data.size());
// No vertical interpolation
if (precision.y == 0)
@ -46,17 +42,13 @@ class NoiseSample {
factor.x, factor.z, factor.y);
}
private:
inline unsigned int index(int x, int y, int z) {
private:
inline u16 index(u16 x, u16 y, u16 z) {
return x * (precision.x + 1) * (precision.y + 1) + y * (precision.x + 1) + z;
};
static inline int min(int a, int b) {
return (a < b ? a : b);
}
std::vector<float> data{};
glm::ivec3 precision{};
glm::vec3 scaleBy;
std::vector<f32> data {};
ivec3 precision {};
vec3 scaleBy;
};

View File

@ -5,6 +5,7 @@
#include "ServerInventoryList.h"
#include "util/net/Packet.h"
#include "server/ServerClient.h"
#include "server/ServerClients.h"
#include "lua/usertype/ItemStack.h"
#include "world/player/ServerPlayer.h"
@ -19,10 +20,12 @@ void ServerInventoryList::manipulated() {
}
bool ServerInventoryList::addWatcher(unsigned int id) {
auto& client = clients.getPlayer(id);
if (!client || watchers.count(id)) return false;
if (watchers.count(id)) return false;
auto& client = clients.getClient(id);
if (!client || !client->player) return false;
sendTo(client->player);
watchers.insert(id);
sendTo(client);
return true;
}
@ -41,10 +44,10 @@ void ServerInventoryList::sendToAll() {
auto p = createPacket();
for (auto it = watchers.cbegin(); it != watchers.cend();) {
auto& player = clients.getPlayer(*it);
if (!player) it = watchers.erase(it);
auto& client = clients.getClient(*it);
if (!client || !client->player) it = watchers.erase(it);
else {
p.sendTo(player->getPeer(), Packet::Channel::INTERACT);
p.sendTo(client->peer, Packet::Channel::INTERACT);
it++;
}
}

View File

@ -140,51 +140,62 @@ void LocalPlayer::handleAssertion(Deserializer& d) {
while (!d.atEnd()) {
const auto field = d.read<NetField>();
switch (field) {
default:
default: {
std::cout << Log::err << "Player received unhandled NetField, Type "
<< static_cast<u32>(field) << "." << Log::endl;
break;
}
case NetField::ID:
case NetField::ID: {
setId(d.read<u32>());
break;
}
case NetField::POS:
case NetField::POS: {
setPos(d.read<vec3>());
break;
}
case NetField::VEL:
case NetField::VEL: {
setVel(d.read<vec3>());
break;
}
case NetField::DIM:
case NetField::DIM: {
setDim(world.getDimension(d.read<u16>()));
break;
}
case NetField::LOOK_PITCH:
case NetField::LOOK_PITCH: {
setPitch(d.read<f32>());
break;
}
case NetField::LOOK_YAW:
case NetField::LOOK_YAW: {
setYaw(d.read<f32>());
break;
}
case NetField::FLYING:
case NetField::FLYING: {
setFlying(d.read<bool>());
break;
}
case NetField::HAND_INV:
case NetField::HAND_INV: {
setHandList(d.read<string>());
break;
}
case NetField::WIELD_INV:
case NetField::WIELD_INV: {
setWieldList(d.read<string>());
break;
}
case NetField::WIELD_INDEX:
case NetField::WIELD_INDEX: {
setWieldIndex(d.read<u16>());
break;
}
}
}
}

View File

@ -15,39 +15,39 @@ void Player::setDim(DimensionPtr dim, bool assert) {
if (assert) assertField(Serializer().append(NetField::DIM).append(dim->getInd()).packet());
}
void Player::setPos(glm::vec3 pos, bool assert) {
void Player::setPos(vec3 pos, bool assert) {
Entity::setPos(pos);
if (assert) assertField(Serializer().append(NetField::POS).append(pos).packet());
}
void Player::setVel(glm::vec3 vel, bool assert) {
void Player::setVel(vec3 vel, bool assert) {
Entity::setVel(vel);
if (assert) assertField(Serializer().append(NetField::VEL).append(vel).packet());
}
float Player::getYaw() {
f32 Player::getYaw() {
return yaw;
}
void Player::setYaw(float yaw, bool assert) {
void Player::setYaw(f32 yaw, bool assert) {
this->yaw = yaw;
if (assert) assertField(Serializer().append(NetField::LOOK_YAW).append(yaw).packet());
}
float Player::getPitch() {
f32 Player::getPitch() {
return pitch;
}
void Player::setPitch(float pitch, bool assert) {
void Player::setPitch(f32 pitch, bool assert) {
this->pitch = pitch;
if (assert) assertField(Serializer().append(NetField::LOOK_PITCH).append(pitch).packet());
}
glm::vec3 Player::getLookOffset() {
vec3 Player::getLookOffset() {
return this->lookOffset;
}
void Player::setLookOffset(glm::vec3 lookOffset, bool assert) {
void Player::setLookOffset(vec3 lookOffset, bool assert) {
this->lookOffset = lookOffset;
if (assert) assertField(Serializer().append(NetField::LOOK_OFF).append(lookOffset).packet());
}
@ -62,29 +62,29 @@ void Player::setFlying(bool flying, bool assert) {
if (assert) assertField(Serializer().append(NetField::FLYING).append(flying).packet());
}
std::string Player::getHandList() {
string Player::getHandList() {
return handList;
}
void Player::setHandList(const std::string& list, bool assert) {
void Player::setHandList(const string& list, bool assert) {
handList = list;
if (assert) assertField(Serializer().append(NetField::HAND_INV).append(handList).packet());
}
std::string Player::getWieldList() {
string Player::getWieldList() {
return wieldList;
}
void Player::setWieldList(const std::string& list, bool assert) {
void Player::setWieldList(const string& list, bool assert) {
wieldList = list;
if (assert) assertField(Serializer().append(NetField::WIELD_INV).append(wieldList).packet());
}
unsigned short Player::getWieldIndex() {
u16 Player::getWieldIndex() {
return wieldIndex;
}
void Player::setWieldIndex(unsigned short index, bool assert) {
void Player::setWieldIndex(u16 index, bool assert) {
wieldIndex = index;
if (assert) assertField(Serializer().append(NetField::WIELD_INDEX).append(index).packet());
}

View File

@ -1,28 +1,16 @@
//
// Created by aurailus on 2020-07-28.
//
#pragma once
#include <memory>
#include <glm/vec3.hpp>
#include "util/Types.h"
#include "util/CovariantPtr.h"
#include "world/dim/ent/Entity.h"
#include "game/atlas/DefinitionAtlas.h"
class World;
class Packet;
class Subgame;
class Inventory;
class Dimension;
class Deserializer;
class InventoryList;
class Player : public virtual Entity {
@ -36,37 +24,37 @@ public:
virtual void setDim(DimensionPtr dim, bool assert = false);
virtual void setPos(glm::vec3 pos, bool assert = false);
virtual void setPos(vec3 pos, bool assert = false);
virtual void setVel(glm::vec3 vel, bool assert = false);
virtual void setVel(vec3 vel, bool assert = false);
virtual float getYaw();
virtual void setYaw(float yaw, bool assert = false);
virtual void setYaw(f32 yaw, bool assert = false);
virtual float getPitch();
virtual f32 getPitch();
virtual void setPitch(float pitch, bool assert = false);
virtual void setPitch(f32 pitch, bool assert = false);
virtual glm::vec3 getLookOffset();
virtual vec3 getLookOffset();
virtual void setLookOffset(glm::vec3 lookOffset, bool assert = false);
virtual void setLookOffset(vec3 lookOffset, bool assert = false);
virtual bool isFlying();
virtual void setFlying(bool flying, bool assert = false);
virtual std::string getHandList();
virtual string getHandList();
virtual void setHandList(const std::string& list, bool assert = false);
virtual void setHandList(const string& list, bool assert = false);
virtual std::string getWieldList();
virtual string getWieldList();
virtual void setWieldList(const std::string& list, bool assert = false);
virtual void setWieldList(const string& list, bool assert = false);
virtual unsigned short getWieldIndex();
virtual u16 getWieldIndex();
virtual void setWieldIndex(unsigned short index, bool assert = false);
virtual void setWieldIndex(u16 index, bool assert = false);
virtual InventoryPtr getInventory() = 0;

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 29/06/19.
//
#include "ServerPlayer.h"
#include "world/ServerWorld.h"
@ -13,7 +9,10 @@
ServerPlayer::ServerPlayer(ServerClient& client, World& world, SubgamePtr game, DimensionPtr dim) :
Player(game, world, dim, client.id), Entity(game, dim), client(client),
inventory(world.getRefs()->createInventory("player:" + std::to_string(id))) {}
inventory(world.getRefs()->createInventory("player:" + std::to_string(id))) {
inventory->createList("cursor", 1, 1);
}
void ServerPlayer::assertField(Packet packet) {
packet.type = Packet::Type::THIS_PLAYER_INFO;