Supercharged Serialization, Fixed Size types

- Serialization classes can now handle **all** trivially copyable types, all vectors / arrays of trivially copyable types, strings (and vectors / arrays of strings), and enums.
- Serialization classes are way shorter and more readable.
- FIXED SIZE integrs, floating points, and vecs
- Shorthands for pointers, vectors, and arrays
- More efficient use of memory in many places
- A lot of network stuff is using fixed-size integers now.
master
Auri 2021-06-21 22:09:35 -07:00
parent 4b28437b80
commit 4487997b92
61 changed files with 1168 additions and 1358 deletions

View File

@ -324,6 +324,6 @@ add_library(Zepha_Core
lua/modules/Message.cpp
lua/modules/Message.h
lua/NoiseFromLua.cpp
lua/NoiseFromLua.h)
lua/NoiseFromLua.h util/Types.h)
target_include_directories(Zepha_Core PUBLIC .)

View File

@ -18,50 +18,13 @@
#pragma clang diagnostic pop
//#include "StartGame.h"
#include "StartGame.h"
/**
* Main entrance point to the program. (Am I really describing what the main function is?)
* Intentionally kept minimal to allow for testing. Real startup logic is done in StartGame.
*
* @param argc - Argument array length
* @param argv - Argument array
* @returns - A numerical value indicating exit status.
*/
#include <GLFW/glfw3.h>
#include <iostream>
int main(int argc, char* argv[]) {
// return StartGame(argc, argv);
Chunk a = Chunk();
for (int i = 0; i < 128; i++) {
const auto rnd = floor(rand() * 100);
for (int j = 0; j < 32; j++) {
a.setBlock(i * 32 + j, rnd);
a.setBiome(i * 32 + j, rnd * 2);
}
}
glfwInit();
auto start = glfwGetTime() * 1000;
for (int i = 0; i < 1000; i++) {
auto b = Chunk(a);
// auto l = a.compress();
// std::cout << b.isGenerated() << std::endl;
}
auto end = glfwGetTime() * 1000;
std::cout << (end - start) << std::endl;
// Chunk b = Chunk(a.compress());
// b.decompress();
//
//// std::cout << a.compress().length() << std::endl;
//
// for (int i = 0; i < 4096; i++) assert(a.getBlock(i) == b.getBlock(i));
return StartGame(argc, argv);
}

View File

@ -5,6 +5,7 @@
#pragma once
#include <iostream>
#include <execinfo.h>
#include "util/Log.h"
#include "util/Util.h"
@ -26,10 +27,10 @@ enum class Mode {
std::map<std::string, std::string> ParseArgs(int argc, char* argv[]) {
std::map<std::string, std::string> args;
for (int i = 1; i < argc; i++) {
for (usize i = 1; i < argc; i++) {
std::string arg(argv[i]);
size_t equals = arg.find('=');
usize equals = arg.find('=');
std::string first = (equals == -1) ? arg : arg.substr(0, equals);
if (args.count(first)) throw std::invalid_argument("Duplicate argument " + first + ".");
@ -53,8 +54,9 @@ std::map<std::string, std::string> ParseArgs(int argc, char* argv[]) {
int StartGame(int argc, char* argv[]) {
Mode mode = Mode::CLIENT;
try {
unsigned short port = Address::DEFAULT_PORT;
// try
{
u16 port = Address::DEFAULT_PORT;
std::string subgame = "";
bool ascii = true;
@ -80,13 +82,16 @@ int StartGame(int argc, char* argv[]) {
// addr.host = arg.second;
// break;
case Util::hash("--port"): port = static_cast<unsigned short>(stoi(arg.second));
case Util::hash("--port"):
port = static_cast<u16>(stoi(arg.second));
break;
case Util::hash("--subgame"): subgame = arg.second;
case Util::hash("--subgame"):
subgame = arg.second;
break;
case Util::hash("--noascii"): ascii = false;
case Util::hash("--noascii"):
ascii = false;
break;
}
}
@ -106,8 +111,13 @@ int StartGame(int argc, char* argv[]) {
return 0;
}
catch (const std::exception& e) {
std::cout << Log::err << "Zepha failed to start.\n" << e.what() << Log::endl;
return 1;
}
// catch (const std::exception& e) {
// void *array[10];
// size_t size;
// size = backtrace(array, 10);
// std::cout << Log::err << "Zepha crashed unexpectedly.\n" << e.what() << std::endl;
// backtrace_symbols_fd(array, size, STDERR_FILENO);
// std::cout << Log::endl;
// return 1;
// }
}

View File

@ -3,62 +3,37 @@
#include "Client.h"
#include "../util/Timer.h"
#include "LocalServerInstance.h"
//#include "LocalServerInstance.h"
#include "util/Types.h"
#include "util/Timer.h"
#include "scene/GameScene.h"
#include "scene/ConnectScene.h"
#include "scene/MainMenuScene.h"
/**
* Creates a client window and starts the main event loop.
* Initially opens to the main menu.
* @param window - The dimensions for the created window.
*/
Client::Client(glm::ivec2 window) :
Client::Client(ivec2 window) :
renderer(window) {
std::cout << Log::info << "Starting Zepha Client." << Log::endl;
scene.setScene(std::make_unique<MainMenuScene>(*this));
scene.setScene(make_unique<MainMenuScene>(*this));
while (!renderer.window.shouldClose()) loop();
}
/**
* Get the last frame's delta time.
* @returns the delta time.
*/
double Client::getDelta() {
f64 Client::getDelta() {
return delta;
}
/**
* Starts a local server and connects to it.
* @throws runtime_error if a local server is already running.
* @param subgame - The subgame for the local server to run.
*/
void Client::startLocalServer(const std::string& subgame) {
void Client::startLocalServer(const string& subgame) {
//TODO: Implement Local Server
// localServer = std::make_shared<LocalServerInstance>(executablePath, addr.port, state.subgame);
// localServer->start();
scene.setScene(std::make_unique<ConnectScene>(*this, Address{ "127.0.0.1", Address::DEFAULT_PORT }));
scene.setScene(make_unique<ConnectScene>(*this, Address { "127.0.0.1", Address::DEFAULT_PORT }));
}
/**
* The main event loop. Polls GLFW, and updates the scene and the renderer.
* Will be called by the Client constructor until render.window.shouldClose() returns true.
*/
void Client::loop() {
double now = glfwGetTime();
f64 now = glfwGetTime();
delta = now - timeElapsed;
timeElapsed = now;

View File

@ -16,27 +16,47 @@
class LocalServerInstance;
class Client {
public:
public:
Client(const Client& o) = delete;
explicit Client(glm::ivec2 window);
/**
* Creates a client window and starts the main event loop.
* Initially opens to the main menu.
* @param window - The dimensions for the created window.
*/
double getDelta();
explicit Client(ivec2 window);
void startLocalServer(const std::string& subgame);
/** Returns the last frame's delta time. */
f64 getDelta();
/**
* Starts a local server and connects to it.
* @throws runtime_error if a local server is already running.
* @param subgame - The subgame for the local server to run.
*/
void startLocalServer(const string& subgame);
Renderer renderer;
SceneManager scene;
ServerConnection connection{};
std::shared_ptr<LocalSubgame> game = std::make_shared<LocalSubgame>("../assets/textures");
sptr<LocalSubgame> game = make_shared<LocalSubgame>("../assets/textures");
private:
private:
/**
* The main event loop. Polls GLFW, and updates the scene and the renderer.
* Will be called by the Client constructor until render.window.shouldClose() returns true.
*/
void loop();
std::shared_ptr<LocalServerInstance> localServer = nullptr;
sptr<LocalServerInstance> localServer = nullptr;
double delta = 0;
double timeElapsed = 0;
f64 delta = 0;
f64 timeElapsed = 0;
};

View File

@ -37,7 +37,7 @@ void ClientNetworkInterpreter::update() {
break;
}
case ENET_EVENT_TYPE_RECEIVE: {
std::unique_ptr<PacketView> p = std::make_unique<PacketView>(event.packet);
auto p = make_unique<PacketView>(event.packet);
receivedPacket(std::move(p));
break;
}
@ -50,16 +50,18 @@ void ClientNetworkInterpreter::update() {
}
auto player = world.getPlayer();
if (player)
if (player) {
Serializer()
.appendEnum(NetField::POS).append(player->getPos())
.appendEnum(NetField::VEL).append(player->getVel())
.appendEnum(NetField::LOOK_PITCH).append(player->getPitch())
.appendEnum(NetField::LOOK_YAW).append(player->getYaw())
.packet(Packet::Type::THIS_PLAYER_INFO, false).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
.append(NetField::POS).append(player->getPos())
.append(NetField::VEL).append(player->getVel())
.append(NetField::LOOK_PITCH).append(player->getPitch())
.append(NetField::LOOK_YAW).append(player->getYaw())
.packet(Packet::Type::THIS_PLAYER_INFO, false)
.sendTo(connection.getPeer(), Packet::Channel::INTERACT);
}
}
void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<PacketView> p) {
void ClientNetworkInterpreter::receivedPacket(uptr<PacketView> p) {
switch (p->type) {
default:
std::cout << Log::err << "Received unknown packet of type " << static_cast<int>(p->type)
@ -67,7 +69,7 @@ void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<PacketView> p) {
break;
case Packet::Type::SERVER_INFO:
serverSideChunkGens = p->d.read<unsigned int>();
serverSideChunkGens = p->d.read<u32>();
break;
case Packet::Type::THIS_PLAYER_INFO:
@ -83,12 +85,12 @@ void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<PacketView> p) {
world.handleWorldPacket(std::move(p));
break;
case Packet::Type::BLOCK_SET: {
auto pos = p->d.read<glm::ivec3>();
auto block = p->d.read<unsigned int>();
world.getActiveDimension()->setBlock(pos, block);
break;
}
// case Packet::Type::BLOCK_SET: {
// auto pos = p->d.read<ivec3>();
// auto block = p->d.read<u16>();
// world.getActiveDimension()->setBlock(pos, block);
// break;
// }
case Packet::Type::ENTITY_INFO:
world.getActiveDimension().l()->serverEntitiesInfo(p->d);
@ -107,6 +109,7 @@ void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<PacketView> p) {
std::string list = p->d.read<std::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>();
@ -117,22 +120,22 @@ void ClientNetworkInterpreter::receivedPacket(std::unique_ptr<PacketView> p) {
}
void ClientNetworkInterpreter::blockHit(const Target& target) {
Serializer().append<glm::ivec3>(target.data.block.pos).append(static_cast<unsigned short>(target.data.block.face))
Serializer().append<ivec3>(target.data.block.pos).append(static_cast<unsigned short>(target.data.block.face))
.packet(Packet::Type::BLOCK_HIT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
}
void ClientNetworkInterpreter::blockPlace(const Target& target) {
Serializer().append<glm::ivec3>(target.data.block.pos).append(static_cast<unsigned short>(target.data.block.face))
Serializer().append<ivec3>(target.data.block.pos).append(static_cast<unsigned short>(target.data.block.face))
.packet(Packet::Type::BLOCK_PLACE).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
}
void ClientNetworkInterpreter::blockInteract(const Target& target) {
Serializer().append<glm::ivec3>(target.data.block.pos).append(static_cast<unsigned short>(target.data.block.face))
Serializer().append<ivec3>(target.data.block.pos).append(static_cast<unsigned short>(target.data.block.face))
.packet(Packet::Type::BLOCK_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
}
void ClientNetworkInterpreter::blockPlaceOrInteract(const Target& target) {
Serializer().append<glm::ivec3>(target.data.block.pos).append(static_cast<unsigned short>(target.data.block.face))
Serializer().append<ivec3>(target.data.block.pos).append(static_cast<unsigned short>(target.data.block.face))
.packet(Packet::Type::BLOCK_PLACE_OR_INTERACT).sendTo(connection.getPeer(), Packet::Channel::INTERACT);
}

View File

@ -22,12 +22,12 @@ class LocalSubgame;
enum class NetPlayerField;
class ClientNetworkInterpreter {
public:
public:
ClientNetworkInterpreter(const ClientNetworkInterpreter& other) = delete;
ClientNetworkInterpreter(ServerConnection& connection, LocalWorld& world);
void init(std::function<void(std::unique_ptr<PacketView>)> invCallback);
void init(std::function<void(uptr<PacketView>)> invCallback);
void update();
@ -41,22 +41,23 @@ class ClientNetworkInterpreter {
void wieldItemUse(const Target& target);
void invWatch(const std::string& inv, const std::string& list);
void invWatch(const string& inv, const string& list);
void invUnwatch(const std::string& inv, const std::string& list);
void invUnwatch(const string& inv, const string& list);
void invInteract(const std::string& inv, const std::string& list, bool primary, unsigned short ind);
void invInteract(const string& inv, const string& list, bool primary, u16 ind);
void sendPacket(const Packet& packet, Packet::Channel channel);
int recvPackets = 0;
int serverSideChunkGens = 0;
private:
void receivedPacket(std::unique_ptr<PacketView> ePacket);
u32 recvPackets = 0;
u32 serverSideChunkGens = 0;
private:
void receivedPacket(uptr<PacketView> ePacket);
LocalWorld& world;
ServerConnection& connection;
std::function<void(std::unique_ptr<PacketView>)> onInvPacket;
std::function<void(uptr<PacketView>)> onInvPacket;
};

View File

@ -38,7 +38,7 @@ class ServerConnection {
private:
unsigned long timeout = 1000;
unsigned int attempts = 10;
unsigned int attempts = 1000;
ENetHost* host = nullptr;
ENetPeer* peer = nullptr;

View File

@ -95,7 +95,7 @@ void ConnectScene::update() {
auto statusText = components.get<GuiText>("statusText");
statusText->setText(statusText->getText() + "Received block index-identifier table.\n");
client.game->getDefs().setIdentifiers(p.d.read<std::vector<std::string>>());
client.game->getDefs().setIdentifiers(p.d.read<vec<string>>());
Packet resp(Packet::Type::BIOME_IDENTIFIER_LIST);
resp.sendTo(connection.getPeer(), Packet::Channel::CONNECT);
@ -105,7 +105,7 @@ void ConnectScene::update() {
statusText->setText(
statusText->getText() + "Received biome index-identifier table.\nDownloading mods...\n");
client.game->getBiomes().setIdentifiers(p.d.read<std::vector<std::string>>());
client.game->getBiomes().setIdentifiers(p.d.read<vec<string>>());
connectState = State::MODS;
Packet resp(Packet::Type::MODS);
@ -129,7 +129,7 @@ void ConnectScene::update() {
client.game->getParser().getHandler().addLuaMod(std::move(luaMod));
}
else if (p.type == Packet::Type::MOD_ORDER) {
client.game->getParser().getHandler().setModsOrder(p.d.read<std::vector<std::string>>());
client.game->getParser().getHandler().setModsOrder(p.d.read<vec<string>>());
statusText->setText(
statusText->getText() + "Done downloading mods.\nReceived the mods order.\nDownloading media...\n");
@ -156,7 +156,7 @@ void ConnectScene::update() {
unsigned int count = 0;
while (t != AssetType::END) {
std::string assetName = p.d.read<std::string>();
std::string assetName = p.d.read<string>();
if (t == AssetType::TEXTURE) {
int width = p.d.read<unsigned int>();
@ -202,14 +202,17 @@ void ConnectScene::handleConnecting() {
switch (connection.getConnectionStatus()) {
default:throw std::runtime_error("Uncaught connection error.");
case ServerConnection::State::ENET_ERROR:throw std::runtime_error("Enet Initialization error.");
case ServerConnection::State::ENET_ERROR:
throw std::runtime_error("Enet Initialization error.");
break;
case ServerConnection::State::FAILED_CONNECT:connectState = State::FAILED_CONNECT;
case ServerConnection::State::FAILED_CONNECT:
connectState = State::FAILED_CONNECT;
statusText->setText(statusText->getText() + "\nFailed to connect :(\n");
break;
case ServerConnection::State::ATTEMPTING_CONNECT:connection.processConnecting();
case ServerConnection::State::ATTEMPTING_CONNECT:
connection.processConnecting();
dotsTime += client.getDelta();
if (dotsTime > 1) {

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 08/01/19.
//
#include <fstream>
#include <iostream>
#include <json/json.hpp>
@ -10,6 +6,7 @@
#include "MainMenuScene.h"
#include "util/Log.h"
#include "ConnectScene.h"
#include "client/Client.h"
#include "client/graph/Renderer.h"
#include "client/menu/SubgameDef.h"
@ -17,12 +14,11 @@
#include "game/atlas/asset/AtlasRef.h"
#include "client/gui/basic/GuiContainer.h"
#include "client/gui/compound/GuiImageButton.h"
#include "ConnectScene.h"
MainMenuScene::MainMenuScene(Client& client) :
Scene(client),
components(std::make_unique<GuiContainer>()),
menuContainer(std::make_shared<GuiContainer>("__menu")),
components(make_unique<GuiContainer>()),
menuContainer(make_shared<GuiContainer>("__menu")),
sandbox(sandboxArea, client, menuContainer) {
client.renderer.setClearColor(0, 0, 0);
@ -30,49 +26,50 @@ MainMenuScene::MainMenuScene(Client& client) :
Font f(client.game->textures, client.game->textures["font"]);
win = client.renderer.window.getSize();
sandboxArea = win - glm::ivec2(0, 18 * GS);
sandboxArea = win - ivec2(0, 18 * GS);
components->add(menuContainer);
branding = std::make_shared<GuiContainer>("zephaBranding");
branding = make_shared<GuiContainer>("zephaBranding");
components->add(branding);
{
auto zephaText = std::make_shared<GuiText>("zephaText");
auto zephaText = make_shared<GuiText>("zephaText");
zephaText->create({ GS, GS }, {}, {}, { 1, 1, 1, 1 }, f);
zephaText->setText("Zepha");
branding->add(zephaText);
auto alphaText = std::make_shared<GuiText>("alphaText");
auto alphaText = make_shared<GuiText>("alphaText");
alphaText->create({ GS, GS }, {}, {}, { 1, 0.5, 0.7, 1 }, f);
alphaText->setText("ALPHA");
alphaText->setPos({ 25 * GS, 0 });
branding->add(alphaText);
}
navigationBar = std::make_shared<GuiContainer>("navigationBar");
navigationBar->add(std::make_shared<GuiContainer>("navigationBarBg"));
navigationBar->add(std::make_shared<GuiContainer>("navigationBarIcons"));
navigationBar = make_shared<GuiContainer>("navigationBar");
navigationBar->add(make_shared<GuiContainer>("navigationBarBg"));
navigationBar->add(make_shared<GuiContainer>("navigationBarIcons"));
auto navigationBarIcons = navigationBar->get<GuiContainer>("navigationBarIcons");
components->add(navigationBar);
{
auto settingsButton = std::make_shared<GuiImageButton>("settingsButton");
auto settingsButton = make_shared<GuiImageButton>("settingsButton");
settingsButton->create({ 16 * GS, 16 * GS }, {},
client.game->textures["crop(0, 0, 16, 16, menu_flag_settings)"],
client.game->textures["crop(16, 0, 16, 16, menu_flag_settings)"]);
navigationBar->get<GuiContainer>("navigationBarIcons")->add(settingsButton);
auto closeButton = std::make_shared<GuiImageButton>("closeButton");
auto closeButton = make_shared<GuiImageButton>("closeButton");
closeButton->create({ 16 * GS, 16 * GS }, {},
client.game->textures["crop(0, 0, 16, 16, menu_flag_quit)"],
client.game->textures["crop(16, 0, 16, 16, menu_flag_quit)"]);
closeButton->setCallback(GuiComponent::CallbackType::PRIMARY, [](bool down, glm::ivec2) { if (down) exit(0); });
closeButton->setCallback(GuiComponent::CallbackType::PRIMARY,
[](bool down, ivec2) { if (down) exit(0); });
navigationBar->get<GuiContainer>("navigationBarIcons")->add(closeButton);
auto serversButton = std::make_shared<GuiImageButton>("serversButton");
auto serversButton = make_shared<GuiImageButton>("serversButton");
serversButton->create({ 16 * GS, 16 * GS }, {},
client.game->textures["crop(0, 0, 16, 16, menu_flag_multiplayer)"],
client.game->textures["crop(16, 0, 16, 16, menu_flag_multiplayer)"]);
@ -80,36 +77,36 @@ MainMenuScene::MainMenuScene(Client& client) :
serversButton->setPos({ GS, GS });
navigationBarIcons->add(serversButton);
auto contentButton = std::make_shared<GuiImageButton>("contentButton");
auto contentButton = make_shared<GuiImageButton>("contentButton");
contentButton->create({ 16 * GS, 16 * GS }, {},
client.game->textures["crop(0, 0, 16, 16, menu_flag_content)"],
client.game->textures["crop(16, 0, 16, 16, menu_flag_content)"]);
contentButton->setPos({ GS + GS * 18, GS });
contentButton->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, glm::ivec2) {
contentButton->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, ivec2) {
if (!down) return;
client.scene.setScene(std::make_unique<ConnectScene>(client, Address{ "127.0.0.1" }));
client.scene.setScene(make_unique<ConnectScene>(client, Address{ "127.0.0.1" }));
});
navigationBarIcons->add(contentButton);
auto divider = std::make_shared<GuiRect>("divider");
auto divider = make_shared<GuiRect>("divider");
divider->create({ GS, GS * 10 }, {}, { 1, 1, 1, 0.3 });
divider->setPos({ GS * 2 + GS * 18 * 2, GS * 4 });
navigationBarIcons->add(divider);
findSubgames();
for (unsigned int i = 0; i < subgames.size(); i++) {
for (usize i = 0; i < subgames.size(); i++) {
auto& subgame = subgames[i];
auto button = std::make_shared<GuiImageButton>(subgame.config.name);
auto button = make_shared<GuiImageButton>(subgame.config.name);
button->create({ 16 * GS, 16 * GS }, {},
client.game->textures["crop(0, 0, 16, 16, " + subgame.iconRef->name + ")"],
client.game->textures["crop(16, 0, 16, 16, " + subgame.iconRef->name + ")"]);
button->setPos({ GS * 7 + GS * 18 * (i + 2), GS });
button->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, glm::ivec2) {
button->setCallback(GuiComponent::CallbackType::PRIMARY, [&](bool down, ivec2) {
if (!down) return;
selectedSubgame = &subgame;
sandbox.load(*selectedSubgame);
@ -126,15 +123,15 @@ MainMenuScene::MainMenuScene(Client& client) :
positionElements();
client.renderer.window.addResizeCallback("mainmenu", [&](glm::ivec2 win) {
this->win = win;
sandboxArea = win - glm::ivec2(0, 18 * GS);
client.renderer.window.addResizeCallback("mainmenu", [&](ivec2 newWin) {
win = newWin;
sandboxArea = newWin - ivec2(0, 18 * GS);
positionElements();
});
}
void MainMenuScene::findSubgames() {
std::string subgamesPath = "../subgames";
string subgamesPath = "../subgames";
cf_dir_t subgamesDir;
cf_dir_open(&subgamesDir, subgamesPath.data());
@ -165,34 +162,34 @@ void MainMenuScene::findSubgames() {
if (!hasConf)
throw std::runtime_error(
std::string("Subgame ") + std::string(subgameFolder.name) + " is missing a conf.json.");
string("Subgame ") + string(subgameFolder.name) + " is missing a conf.json.");
if (!hasMods)
throw std::runtime_error(
std::string("Subgame ") + std::string(subgameFolder.name) + " is missing a 'mods' directory.");
string("Subgame ") + string(subgameFolder.name) + " is missing a 'mods' directory.");
nlohmann::json j{};
try {
std::ifstream(std::string(subgameFolder.path) + "/conf.json") >> j;
std::ifstream(string(subgameFolder.path) + "/conf.json") >> j;
}
catch (...) {
throw std::runtime_error(std::string(subgameFolder.name) + "/conf.json is not a valid JSON object.");
throw std::runtime_error(string(subgameFolder.name) + "/conf.json is not a valid JSON object.");
}
if (!j.is_object())
throw std::runtime_error(std::string(subgameFolder.name) + "/conf.json is not a valid JSON object.");
throw std::runtime_error(string(subgameFolder.name) + "/conf.json is not a valid JSON object.");
if (!j["name"].is_string() || j["name"] == "")
throw std::runtime_error(
"The 'name' property in " + std::string(subgameFolder.name) + "/conf.json is missing or invalid.");
"The 'name' property in " + string(subgameFolder.name) + "/conf.json is missing or invalid.");
if (!j["version"].is_string() || j["version"] == "")
throw std::runtime_error("The 'version' property in " + std::string(subgameFolder.name) +
throw std::runtime_error("The 'version' property in " + string(subgameFolder.name) +
"/conf.json is missing or invalid.");
std::string name = j["name"];
std::string description = (j["description"].is_string() ? j["description"] : "");
std::string version = j["version"];
string name = j["name"];
string description = (j["description"].is_string() ? j["description"] : "");
string version = j["version"];
std::shared_ptr<AtlasRef> icon = client.game->textures["menu_flag_missing"];
if (hasIcon) icon = client.game->textures.loadImage(std::string(subgameFolder.path) + "/icon.png", name);
if (hasIcon) icon = client.game->textures.loadImage(string(subgameFolder.path) + "/icon.png", name);
subgames.push_back({ icon, { name, description, version }, subgameFolder.path });
}
@ -216,8 +213,8 @@ void MainMenuScene::positionElements() {
navigationBar->setPos({ 0, win.y - 18 * GS });
auto navigationBarBg = navigationBar->get<GuiContainer>("navigationBarBg");
for (unsigned int i = 0; i < static_cast<float>(win.x) / 64.f / GS; i++) {
auto segment = std::make_shared<GuiRect>("segment_" + std::to_string(i));
for (usize i = 0; i < static_cast<f32>(win.x) / 64.f / GS; i++) {
auto segment = make_shared<GuiRect>("segment_" + std::to_string(i));
segment->create({ 64 * GS, 18 * GS }, {}, client.game->textures["menu_bar_bg"]);
segment->setPos({ i * 64 * GS, 0 });
navigationBarBg->add(segment);

View File

@ -1,18 +1,21 @@
//
// Created by aurailus on 08/01/19.
//
#pragma once
#include "Scene.h"
#include "util/Types.h"
#include "client/menu/SubgameDef.h"
#include "client/menu/MenuSandbox.h"
class Client;
/**
* Displays the main menu, which has a list of installed subgames which can be selected and played.
* Each subgame can have its own menu, which is displayed in the sandbox area.
*/
class MainMenuScene : public Scene {
public:
public:
explicit MainMenuScene(Client& client);
void update() override;
@ -21,24 +24,36 @@ class MainMenuScene : public Scene {
void cleanup() override;
private:
private:
/** Repositions elements after a window resize. */
void positionElements();
/** Finds valid subgames in the subgames folder. */
void findSubgames();
static constexpr float GS = 3;
/** The UI scaling, in pixels. */
static constexpr f32 GS = 3;
glm::ivec2 win{};
glm::ivec2 sandboxArea{};
/** The dimensions of the window. */
ivec2 win {};
std::unique_ptr<GuiContainer> components;
std::shared_ptr<GuiContainer> branding;
std::shared_ptr<GuiContainer> navigationBar;
std::shared_ptr<GuiContainer> menuContainer;
/** The dimensions of the sandbox area. */
ivec2 sandboxArea {};
/** Element references. */
uptr<GuiContainer> components;
sptr<GuiContainer> branding;
sptr<GuiContainer> navigationBar;
sptr<GuiContainer> menuContainer;
/** Provides the API for menu mods. */
MenuSandbox sandbox;
std::vector<SubgameDef> subgames;
/** A list of found subgames. */
vec<SubgameDef> subgames;
/** A reference to the currently selected subgame. */
SubgameDef* selectedSubgame = nullptr;
};

View File

@ -1,26 +1,29 @@
/*
* Scene abstract superclass, provides base scene methods for use by SceneManager.
* Stores a reference to the client, for children.
*
* - Auri, 03/11/20
*/
#pragma once
class Client;
/**
* Scene abstract class, provides base scene methods for use by SceneManager.
* Stores a reference to the client, for use by children.
*/
class Scene {
public:
public:
/** Creates the scene. */
explicit Scene(Client& client) : client(client) {}
/** Called every game loop to update internal state. */
virtual void update() = 0;
/** Called every game loop to draw objects. */
virtual void draw() = 0;
/** Called when the scene will be destroyed. */
virtual void cleanup() = 0;
virtual ~Scene() = default;
/** A reference to the client that created the scene. */
Client& client;
};

View File

@ -1,58 +1,21 @@
//
// Created by aurailus on 06/01/19.
//
#include "SceneManager.h"
/**
* Sets a new scene as the current scene.
* Cleans up the old scene.
* @param newScene - The new current scene.
*/
void SceneManager::setScene(std::unique_ptr<Scene> newScene) {
void SceneManager::setScene(uptr<Scene> newScene) {
cleanupScene();
scene = std::move(newScene);
}
/**
* Returns a reference to the current scene.
* @returns The current scene as a const reference.
*/
const Scene& SceneManager::getScene() {
return *scene;
}
/**
* Updates and renders the current scene, if there is one.
*/
void SceneManager::update() {
if (!scene) return;
scene->update();
scene->draw();
}
/**
* Cleans up the current scene and removes it.
* There will be no current scene after this method executes.
*/
void SceneManager::cleanupScene() {
if (scene) scene->cleanup();
scene = nullptr;
}
/*
* Clean up the scene on destruction.
*/
SceneManager::~SceneManager() {
cleanupScene();
}

View File

@ -1,26 +1,29 @@
//
// Created by aurailus on 06/01/19.
//
#pragma once
#include <memory>
#include "Scene.h"
#include "util/Types.h"
/**
* Handles updating and switching scenes.
*/
class SceneManager {
public:
void setScene(std::unique_ptr<Scene> scene);
public:
const Scene& getScene();
/** Sets the current scene to the one provided. */
void setScene(uptr<Scene> scene);
/** Updates the current scene. */
void update();
void cleanupScene();
~SceneManager();
private:
private:
/** Cleans up the current scene, and removes it. */
void cleanupScene();
/** A pointer to the current scene. */
std::unique_ptr<Scene> scene = nullptr;
};

View File

@ -1,14 +1,8 @@
/*
* The Local Subgame stores all local subgame data.
* Includes Block / Item definitions, biome definitions, the lua parser, models, and textures.
*
* - Auri, 03/11/20
*/
#pragma once
#include "Subgame.h"
#include "util/Types.h"
#include "util/CovariantPtr.h"
#include "lua/LocalLuaParser.h"
#include "game/atlas/TextureAtlas.h"
@ -17,13 +11,17 @@
#include "game/atlas/LocalDefinitionAtlas.h"
class Client;
class LocalWorld;
class LocalPlayer;
/**
* Stores all subgame data for a local client, including
* block & item definitions, the lua sandbox, models, and textures.
*/
class LocalSubgame : public Subgame {
public:
public:
explicit LocalSubgame(const std::string& baseAssets);
void init(WorldPtr world, PlayerPtr player, Client& client);
@ -39,9 +37,10 @@ class LocalSubgame : public Subgame {
ModelStore models;
TextureAtlas textures;
private:
std::shared_ptr<LocalLuaParser> lua;
std::shared_ptr<LocalBiomeAtlas> biomes;
std::shared_ptr<LocalDefinitionAtlas> defs;
private:
uptr<LocalLuaParser> lua;
uptr<LocalBiomeAtlas> biomes;
uptr<LocalDefinitionAtlas> defs;
};

View File

@ -8,12 +8,11 @@
#include "server/ServerClients.h"
ServerSubgame::ServerSubgame(const std::string& subgame, unsigned int seed) :
ServerSubgame::ServerSubgame(const string& subgame, usize seed) :
subgamePath("../subgames/" + subgame + "/"),
defs(std::make_unique<ServerDefinitionAtlas>()),
biomes(std::make_unique<ServerBiomeAtlas>(seed)),
lua(std::make_unique<ServerLuaParser>(*this)) {
defs(make_unique<ServerDefinitionAtlas>()),
biomes(make_unique<ServerBiomeAtlas>(seed)),
lua(make_unique<ServerLuaParser>(*this)) {
if (subgame.empty()) throw std::runtime_error("No subgame specified.");
else if (!cf_file_exists(subgamePath.data())) throw std::runtime_error("Subgame does not exist.");

View File

@ -1,33 +1,35 @@
//
// Created by aurailus on 10/06/19.
//
#pragma once
#include <memory>
#include "Subgame.h"
#include "util/Types.h"
#include "lua/ServerLuaParser.h"
#include "game/atlas/ServerBiomeAtlas.h"
#include "game/atlas/asset/AssetStorage.h"
#include "game/atlas/ServerDefinitionAtlas.h"
class ServerWorld;
class ServerClients;
/**
* Stores all subgame data for a server instance, including
* block & item definitions, the lua sandbox, assets, and textures.
*/
class ServerSubgame : public Subgame {
public:
ServerSubgame(const std::string& subgame, unsigned int seed);
public:
ServerSubgame(const string& subgame, usize seed);
~ServerSubgame();
void init(WorldPtr world);
void update(double delta);
void update(f64 delta);
std::string subgamePath;
string subgamePath;
ServerDefinitionAtlas& getDefs() override { return *defs; };
@ -37,10 +39,10 @@ class ServerSubgame : public Subgame {
AssetStorage assets;
private:
private:
std::unique_ptr<ServerLuaParser> lua;
std::unique_ptr<ServerBiomeAtlas> biomes;
std::unique_ptr<ServerDefinitionAtlas> defs;
uptr<ServerLuaParser> lua;
uptr<ServerBiomeAtlas> biomes;
uptr<ServerDefinitionAtlas> defs;
};

View File

@ -1,22 +1,24 @@
//
// Created by aurailus on 2020-07-24.
//
#pragma once
class World;
class LuaParser;
class BiomeAtlas;
class DefinitionAtlas;
/**
* An abstract class representing a subgame, which has
* methods to access block definitions, biomes, and the lua parser.
*/
class Subgame {
public:
public:
/** Gets the definition atlas. */
virtual DefinitionAtlas& getDefs() = 0;
/** Gets the biome atlas. */
virtual BiomeAtlas& getBiomes() = 0;
/** Gets the lua parser. */
virtual LuaParser& getParser() = 0;
};

View File

@ -11,7 +11,7 @@
LuaMod LuaMod::fromPacket(PacketView& p) {
LuaMod luaMod{};
auto serialized = p.d.read<std::string>();
auto serialized = p.d.read<string>();
std::string mod = gzip::decompress(serialized.c_str(), serialized.length());
luaMod.serialized = serialized;

View File

@ -107,10 +107,10 @@ void ServerLuaParser::loadApi(WorldPtr world) {
core["players"] = lua.create_table();
// Modules
modules.emplace_back(std::make_unique<Api::Module::Time>(Api::State::SERVER, lua, core));
modules.emplace_back(std::make_unique<Api::Module::Message>(Api::State::SERVER, core, game, *world.s()));
modules.emplace_back(std::make_unique<Api::Module::Dimension>(Api::State::SERVER, core, game, *world.s()));
modules.emplace_back(std::make_unique<Api::Module::Structure>(Api::State::SERVER, core, game, *world.s()));
modules.emplace_back(make_unique<Api::Module::Time>(Api::State::SERVER, lua, core));
modules.emplace_back(make_unique<Api::Module::Message>(Api::State::SERVER, core, game, *world.s()));
modules.emplace_back(make_unique<Api::Module::Dimension>(Api::State::SERVER, core, game, *world.s()));
modules.emplace_back(make_unique<Api::Module::Structure>(Api::State::SERVER, core, game, *world.s()));
// Register
auto& game = static_cast<ServerSubgame&>(this->game);

View File

@ -17,7 +17,7 @@ class ServerPlayer;
class ServerSubgame;
class ServerLuaParser : public LuaParser {
public:
public:
explicit ServerLuaParser(ServerSubgame& game);
void init(WorldPtr world, const std::string& rootPath);
@ -30,7 +30,7 @@ class ServerLuaParser : public LuaParser {
void playerDisconnected(std::shared_ptr<ServerPlayer> client);
private:
private:
void loadApi(WorldPtr world);
virtual sol::protected_function_result errorCallback(sol::protected_function_result r) const override;

View File

@ -16,14 +16,14 @@
#include "lua/usertype/Player.h"
#include "world/player/ServerPlayer.h"
Server::Server(unsigned short port, const std::string& subgame) :
Server::Server(u16 port, const std::string& subgame) :
seed(69),
port(port),
config(game),
clients(game),
handler(port, 32),
game(std::make_shared<ServerSubgame>(subgame, seed)),
world(std::make_shared<ServerWorld>(seed, game, clients)) {
game(make_shared<ServerSubgame>(subgame, seed)),
world(make_shared<ServerWorld>(seed, game, clients)) {
game.s()->init(world);
world.s()->init("world");
@ -34,7 +34,7 @@ Server::Server(unsigned short port, const std::string& subgame) :
}
void Server::update() {
const static long interval_ns = static_cast<long>((1000 / 60.f) * 1000000L);
const static i64 interval_ns = static_cast<long>((1000 / 60.f) * 1000000L);
Timer loop("");
world->update(delta);
@ -61,15 +61,15 @@ void Server::update() {
}
}
for (auto& id : playersUpdated) {
for (u32 id : playersUpdated) {
auto player = clients.getPlayer(id);
if (!player) continue;
Packet p = Serializer()
.appendEnum(NetField::ID).append(player->getId())
.appendEnum(NetField::POS).append(player->getPos())
.appendEnum(NetField::LOOK_YAW).append(player->getYaw())
.appendEnum(NetField::LOOK_PITCH).append(player->getPitch())
.append(NetField::ID).append(static_cast<u32>(player->getId()))
.append(NetField::POS).append(player->getPos())
.append(NetField::LOOK_YAW).append(player->getYaw())
.append(NetField::LOOK_PITCH).append(player->getPitch())
.packet(Packet::Type::PLAYER_ENT_INFO, false);
for (auto& iter : clients.players)
@ -79,7 +79,7 @@ void Server::update() {
playersUpdated.clear();
long sleep_for = interval_ns - loop.elapsedNs();
u64 sleep_for = interval_ns - loop.elapsedNs();
if (sleep_for > 0) std::this_thread::sleep_for(std::chrono::nanoseconds(sleep_for));
delta = loop.elapsedNs() / 1000000.f / 1000.f;
@ -103,32 +103,38 @@ void Server::packetReceived(ENetEvent& e) {
void Server::playerPacketReceived(PacketView& p, PlayerPtr player) {
// Pre-initialization because switch statements suck.
glm::ivec3 pos;
ivec3 pos;
u16 a, ind;
string source, list;
EVec face = EVec::NONE;
std::string source, list;
unsigned short a, ind;
switch (p.type) {
default:throw std::runtime_error("Unknown packet type " + std::to_string(static_cast<int>(p.type)) + " received.");
break;
default:
throw std::runtime_error("Unknown packet type " +
std::to_string(static_cast<u32>(p.type)) + " received.");
case Packet::Type::THIS_PLAYER_INFO:player->handleAssertion(p.d);
case Packet::Type::THIS_PLAYER_INFO:
player->handleAssertion(p.d);
playersUpdated.emplace(player->getId());
break;
case Packet::Type::BLOCK_HIT: p.d.read(pos).readEnum(face);
case Packet::Type::BLOCK_HIT:
p.d.read(pos).read(face);
player->getDim()->blockHit(Target(player->getDim(), pos, face), player);
break;
case Packet::Type::BLOCK_PLACE: p.d.read(pos).readEnum(face);
case Packet::Type::BLOCK_PLACE:
p.d.read(pos).read(face);
player->getDim()->blockPlace(Target(player->getDim(), pos, face), player);
break;
case Packet::Type::BLOCK_INTERACT: p.d.read(pos).readEnum(face);
case Packet::Type::BLOCK_INTERACT:
p.d.read(pos).read(face);
player->getDim()->blockInteract(Target(player->getDim(), pos, face), player);
break;
case Packet::Type::BLOCK_PLACE_OR_INTERACT: p.d.read(pos).readEnum(face);
case Packet::Type::BLOCK_PLACE_OR_INTERACT:
p.d.read(pos).read(face);
player->getDim()->blockPlaceOrInteract(Target(player->getDim(), pos, face), player);
break;
@ -137,26 +143,26 @@ void Server::playerPacketReceived(PacketView& p, PlayerPtr player) {
break;
case Packet::Type::INV_WATCH:
p.d.read<std::string>(source).read<std::string>(list);
p.d.read<string>(source).read<string>(list);
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);
break;
case Packet::Type::INV_UNWATCH:
p.d.read<std::string>(source).read<std::string>(list);
p.d.read<string>(source).read<string>(list);
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);
break;
case Packet::Type::INV_INTERACT:
p.d.read<unsigned short>(a).read<std::string>(source).read<std::string>(list).read<unsigned short>(ind);
p.d.read<u16>(a).read<string>(source).read<string>(list).read<u16>(ind);
world->getRefs().s()->interact(a, source, list, ind, player->getId());
break;
case Packet::Type::MOD_MESSAGE:
p.d.read<std::string>(source).read<std::string>(list);
p.d.read<string>(source).read<string>(list);
game->getParser().safe_function(game->getParser().core["trigger"], "message",
source, game->getParser().safe_function(game->getParser().core["deserialize"], list));
break;

View File

@ -4,6 +4,7 @@
#pragma once
#include "util/Types.h"
#include "world/ServerWorld.h"
#include "game/ServerSubgame.h"
#include "util/net/NetHandler.h"
@ -16,8 +17,8 @@ class ServerPlayer;
class Packet;
class Server {
public:
explicit Server(unsigned short port, const std::string& subgame);
public:
explicit Server(u16 port, const std::string& subgame);
void update();
@ -30,20 +31,37 @@ class Server {
void playerPacketReceived(PacketView& p, PlayerPtr player);
unsigned short port = 0;
unsigned int seed = 0;
/** The server's port. */
u16 port = 0;
/** The server's seed. */
u32 seed = 0;
/** The subgame instance, must be listed before world. */
SubgamePtr game;
ServerClients clients;
/** The world instance, needs to be after the subgame. */
WorldPtr world;
/** The network handler, manages client connections. */
NetHandler handler;
/** Handles passing data to newly connecting clients. TODO: Rename. */
ServerConfig config;
std::unordered_set<unsigned int> playersUpdated{};
/** A list of connected clients. */
ServerClients clients;
double elapsed = 0;
double delta = 0;
/** A list of players who have been updated, to send to the other clients. */
std::unordered_set<u32> playersUpdated{};
/** The time elapsed since the start of the server. */
f64 elapsed = 0;
/** The delta time of the last frame. */
f64 delta = 0;
/** Whether or not the server should be kept running. */
bool alive = true;
};

View File

@ -4,19 +4,19 @@
#pragma once
#include <string>
#include <memory>
#include <enet/enet.h>
#include "util/Types.h"
class ServerPlayer;
class ServerClient {
public:
ServerClient(const std::string& username, ENetPeer* peer) :
ServerClient(const string& username, ENetPeer* peer) :
username(username), peer(peer), address(peer->address), id(peer->connectID) {}
std::string username;
unsigned int id = 0;
u32 id = 0;
string username;
ENetPeer* peer;
ENetAddress address;

View File

@ -62,10 +62,10 @@ void ServerClients::createPlayer(std::shared_ptr<ServerClient> client, Dimension
player->setPos({ 32, -20, 32 }, true);
Serializer()
.appendEnum(NetField::ID).append(player->getId())
.appendEnum(NetField::POS).append(player->getPos())
.appendEnum(NetField::LOOK_PITCH).append(player->getPitch())
.appendEnum(NetField::LOOK_YAW).append(player->getYaw())
.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);
}

View File

@ -29,7 +29,8 @@ void ServerConfig::init() {
bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
switch (r.type) {
default: break;
case Packet::Type::CONNECT_DATA_RECVD:return true;
case Packet::Type::CONNECT_DATA_RECVD:
return true;
case Packet::Type::SERVER_INFO: {
Serializer()
@ -64,7 +65,7 @@ bool ServerConfig::handlePacket(ServerClient& client, PacketView& r) {
const unsigned int MAX_PACKET_SIZE = 32 * 1024;
unsigned int packetSize = 0;
Serializer s{};
Serializer s {};
for (ServerTexture& texture : game.s()->assets.textures) {
if (packetSize + 20 + texture.data.length() > MAX_PACKET_SIZE && packetSize != 0) {

View File

@ -1,6 +1,4 @@
//
// Created by aurailus on 2020-08-02.
//
/** Pointers that can contain Server or Client versions of common CoVariant types. */
#pragma once
@ -33,41 +31,41 @@ class ServerInventoryRefs;
template<typename B, typename L, typename S>
class CovariantPtr {
std::shared_ptr<B> b = nullptr;
std::shared_ptr<B> ptr = nullptr;
public:
public:
CovariantPtr() = default;
CovariantPtr(std::nullptr_t) {};
CovariantPtr(std::shared_ptr<B> ptr) : b(ptr) {}
CovariantPtr(std::shared_ptr<B> ptr) : ptr(ptr) {}
CovariantPtr(std::shared_ptr<L> ptr) : b(std::dynamic_pointer_cast<B>(ptr)) {}
CovariantPtr(std::shared_ptr<L> ptr) : ptr(std::dynamic_pointer_cast<B>(ptr)) {}
CovariantPtr(std::shared_ptr<S> ptr) : b(std::dynamic_pointer_cast<B>(ptr)) {}
CovariantPtr(std::shared_ptr<S> ptr) : ptr(std::dynamic_pointer_cast<B>(ptr)) {}
void operator=(std::nullptr_t) { b = nullptr; }
void operator=(std::nullptr_t) { ptr = nullptr; }
operator bool() { return b != nullptr; }
operator bool() { return ptr != nullptr; }
std::shared_ptr<B> operator*() { return b; }
std::shared_ptr<B> operator*() { return ptr; }
std::shared_ptr<B> operator->() { return b; }
std::shared_ptr<B> operator->() { return ptr; }
bool isL() const { return std::dynamic_pointer_cast<L>(b) != nullptr; }
bool isL() const { return std::dynamic_pointer_cast<L>(ptr) != nullptr; }
bool isS() const { return std::dynamic_pointer_cast<S>(b) != nullptr; }
bool isS() const { return std::dynamic_pointer_cast<S>(ptr) != nullptr; }
std::shared_ptr<L> l() {
auto ptr = std::dynamic_pointer_cast<L>(b);
if (!ptr) throw std::bad_cast();
return ptr;
auto converted = std::dynamic_pointer_cast<L>(ptr);
if (!converted) throw std::bad_cast();
return converted;
}
std::shared_ptr<S> s() {
auto ptr = std::dynamic_pointer_cast<S>(b);
if (!ptr) throw std::bad_cast();
return ptr;
auto converted = std::dynamic_pointer_cast<S>(ptr);
if (!converted) throw std::bad_cast();
return converted;
}
};

View File

@ -8,6 +8,7 @@
#include <vector>
#include <iostream>
#include <type_traits>
#include "Util.h"
struct RIE {
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
@ -152,52 +153,51 @@ struct RIE {
template<typename T, int L, typename = typename std::enable_if<std::is_integral<T>::value>::type>
static void expand(const std::vector<T>& rie, std::array<T, L>& expand) {
unsigned int rieI = 0;
unsigned int i = 0;
usize index = 0;
usize rieIndex = 0;
while (rieI * 2 < rie.size()) {
T nI = ((rieI * 2) + 2 < rie.size()) ? rie[(rieI * 2) + 2] : L;
T value = rie[(rieI * 2) + 1];
while (i < nI) expand[i++] = value;
rieI++;
while (rieIndex * 2 < rie.size()) {
usize endIndex = ((rieIndex * 2) + 2 < rie.size()) ? rie[(rieIndex * 2) + 2] : L;
T value = rie[(rieIndex * 2) + 1];
while (index < endIndex) expand[index++] = value;
// std::cout << index - 1 << ", " << expand[index - 1] << std::endl;
rieIndex++;
}
}
template<typename T, int L, typename = typename std::enable_if<std::is_integral<T>::value>::type>
static void encode(const std::array<T, L>& array, std::vector<T>& out) {
T len = 1;
T block = array[0];
for (unsigned int i = 1; i < array.size(); i++) {
out.push_back(0);
out.push_back(array[0]);
for (T i = 0; i < L; i++) {
T newBlock = array[i];
if (newBlock != block) {
out.push_back(len);
out.push_back(block);
out.push_back(i);
out.push_back(newBlock);
block = newBlock;
len = 0;
}
len++;
}
out.push_back(len);
out.push_back(block);
}
template<typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
static void encode(const std::vector<T>& array, std::vector<T>& out) {
T len = 1;
T block = array[0];
for (unsigned int i = 1; i < array.size(); i++) {
T newBlock = array[i];
if (newBlock != block) {
out.push_back(len);
out.push_back(block);
block = newBlock;
len = 0;
}
len++;
}
out.push_back(len);
out.push_back(block);
}
// template<typename T, typename = typename std::enable_if<std::is_integral<T>::value>::type>
// static void encode(const std::vector<T>& array, std::vector<T>& out) {
// T len = 1;
// T block = array[0];
//
// for (unsigned int i = 1; i < array.size(); i++) {
// T newBlock = array[i];
// if (newBlock != block) {
// out.push_back(len);
// out.push_back(block);
// block = newBlock;
// len = 0;
// }
// len++;
// }
// out.push_back(len);
// out.push_back(block);
// }
};

View File

@ -1,36 +1,37 @@
//
// Created by aurailus on 24/03/19.
//
#pragma once
#include <tgmath.h>
#include <glm/glm.hpp>
#include <glm/common.hpp>
#include "util/Types.h"
/**
* Static methods to convert between different coordinate spaces,
* and transform coordinates into indices and vice-versa.
*/
namespace Space {
const static int CHUNK_SIZE = 16;
const static int MAPBLOCK_SIZE = 4;
const static int REGION_SIZE = 4;
const static u16f CHUNK_SIZE = 16;
const static u16f MAPBLOCK_SIZE = 4;
const static u16f REGION_SIZE = 4;
const static int CHUNK_BLOCK_LENGTH = CHUNK_SIZE;
const static int MAPBLOCK_BLOCK_LENGTH = CHUNK_BLOCK_LENGTH * MAPBLOCK_SIZE;
const static int REGION_BLOCK_LENGTH = MAPBLOCK_BLOCK_LENGTH * REGION_SIZE;
const static u16f CHUNK_BLOCK_LENGTH = CHUNK_SIZE;
const static u16f MAPBLOCK_BLOCK_LENGTH = CHUNK_BLOCK_LENGTH * MAPBLOCK_SIZE;
const static u16f REGION_BLOCK_LENGTH = MAPBLOCK_BLOCK_LENGTH * REGION_SIZE;
const static int MAPBLOCK_CHUNK_LENGTH = MAPBLOCK_SIZE;
const static int REGION_CHUNK_LENGTH = MAPBLOCK_CHUNK_LENGTH * REGION_SIZE;
const static u16f MAPBLOCK_CHUNK_LENGTH = MAPBLOCK_SIZE;
const static u16f REGION_CHUNK_LENGTH = MAPBLOCK_CHUNK_LENGTH * REGION_SIZE;
// Private helper methods
namespace {
inline glm::ivec3 localFromGlobal(const glm::ivec3& pos, int size) {
return glm::vec3{
(pos.x < 0) ? size - 1 + static_cast<int>(pos.x + 1) % size : static_cast<int>(pos.x) % size,
(pos.y < 0) ? size - 1 + static_cast<int>(pos.y + 1) % size : static_cast<int>(pos.y) % size,
(pos.z < 0) ? size - 1 + static_cast<int>(pos.z + 1) % size : static_cast<int>(pos.z) % size
inline u16vec3 localFromGlobal(const ivec3& pos, u32 size) {
return u16vec3 {
size - 1 + (pos.x + (pos.x < 0 ? 1 : 0)) % size,
size - 1 + (pos.y + (pos.y < 0 ? 1 : 0)) % size,
size - 1 + (pos.z + (pos.z < 0 ? 1 : 0)) % size
};
}
inline glm::ivec3 sectionFromGlobal(glm::ivec3 pos, float size) {
inline ivec3 sectionFromGlobal(ivec3 pos, f32 size) {
return {
std::floor(static_cast<float>(pos.x) / size),
std::floor(static_cast<float>(pos.y) / size),
@ -42,17 +43,17 @@ namespace Space {
namespace Region {
namespace world {
// Get a Region world position from a MapBlock's world position.
static inline glm::ivec3 fromMapBlock(const glm::ivec3& pos) {
static inline ivec3 fromMapBlock(const ivec3& pos) {
return sectionFromGlobal(pos, REGION_SIZE);
}
// Get a Region world position from a Chunk's world position.
static inline glm::ivec3 fromChunk(const glm::ivec3& pos) {
static inline ivec3 fromChunk(const ivec3& pos) {
return sectionFromGlobal(pos, REGION_CHUNK_LENGTH);
}
// Get a Region world position from a Block's world position.
static inline glm::ivec3 fromBlock(const glm::ivec3& pos) {
static inline ivec3 fromBlock(const ivec3& pos) {
return sectionFromGlobal(pos, REGION_BLOCK_LENGTH);
}
}
@ -61,75 +62,74 @@ namespace Space {
namespace MapBlock {
namespace relative {
// Get a MapBlock's relative position in its Region from its world position.
static inline glm::ivec3 toRegion(const glm::ivec3& pos) {
static inline u8vec3 toRegion(const ivec3& pos) {
return localFromGlobal(pos, MAPBLOCK_SIZE);
}
}
namespace world {
// Get a MapBlock world position from a Region's world position.
static inline glm::ivec3 fromRegion(const glm::ivec3& pos) {
static inline ivec3 fromRegion(const ivec3& pos) {
return sectionFromGlobal(pos, 1.f / REGION_SIZE);
}
// Get a MapBlock world position from a Chunk's world position.
static inline glm::ivec3 fromChunk(const glm::ivec3& pos) {
static inline ivec3 fromChunk(const ivec3& pos) {
return sectionFromGlobal(pos, MAPBLOCK_SIZE);
}
// Get a MapBlock world position from a Block's world position.
static inline glm::ivec3 fromBlock(const glm::ivec3& pos) {
static inline ivec3 fromBlock(const ivec3& pos) {
return sectionFromGlobal(pos, MAPBLOCK_BLOCK_LENGTH);
}
}
// Get the index of a MapBlock within its Region from its local or world position.
static inline unsigned int index(const glm::ivec3& vec) {
glm::ivec3 local = MapBlock::relative::toRegion(vec);
unsigned int ind = static_cast<unsigned int>(local.x + REGION_SIZE * (local.y + REGION_SIZE * local.z));
return ind;
static inline u16 index(const ivec3& vec) {
u8vec3 local = MapBlock::relative::toRegion(vec);
return local.x + REGION_SIZE * (local.y + REGION_SIZE * local.z);
}
}
namespace Chunk {
namespace relative {
// Get a Chunk's relative position in its MapBlock from its world position.
static inline glm::ivec3 toMapBlock(const glm::ivec3& pos) {
static inline u8vec3 toMapBlock(const ivec3& pos) {
return localFromGlobal(pos, MAPBLOCK_CHUNK_LENGTH);
}
// Get a Chunk's relative position in its Region from its world position.
static inline glm::ivec3 toRegion(const glm::ivec3& pos) {
static inline u8vec3 toRegion(const ivec3& pos) {
return localFromGlobal(pos, REGION_CHUNK_LENGTH);
}
}
namespace world {
// Get a Chunk world position from a Regions's world position.
static inline glm::ivec3 fromRegion(const glm::ivec3& pos) {
static inline ivec3 fromRegion(const ivec3& pos) {
return sectionFromGlobal(pos, 1.f / REGION_CHUNK_LENGTH);
}
// Get a Chunk world position from a MapBlock's world position.
static inline glm::ivec3 fromMapBlock(const glm::ivec3& pos) {
static inline ivec3 fromMapBlock(const ivec3& pos) {
return sectionFromGlobal(pos, 1.f / MAPBLOCK_CHUNK_LENGTH);
}
// Get a Chunk world position from a Block's world position.
static inline glm::ivec3 fromBlock(const glm::ivec3& pos) {
static inline ivec3 fromBlock(const ivec3& pos) {
return sectionFromGlobal(pos, CHUNK_BLOCK_LENGTH);
}
}
// Get the index of a Chunk within its MapBlock from its local or world position.
static inline unsigned int index(const glm::ivec3& vec) {
glm::ivec3 local = Chunk::relative::toMapBlock(vec);
return static_cast<unsigned int>(local.x + MAPBLOCK_SIZE * (local.z + MAPBLOCK_SIZE * local.y));
static inline u16 index(const glm::ivec3& vec) {
u8vec3 local = Chunk::relative::toMapBlock(vec);
return local.x + MAPBLOCK_SIZE * (local.z + MAPBLOCK_SIZE * local.y);
}
// Return a local vector of an chunk within its mapblock.
static inline glm::ivec3 fromIndex(unsigned int ind) {
glm::ivec3 vec{};
static inline ivec3 fromIndex(u16 ind) {
u8vec3 vec {};
vec.y = ind / (MAPBLOCK_SIZE * MAPBLOCK_SIZE);
ind -= (static_cast<int>(vec.y) * MAPBLOCK_SIZE * MAPBLOCK_SIZE);
@ -143,47 +143,47 @@ namespace Space {
namespace Block {
namespace relative {
// Get a Block's relative position to its Chunk from its world position.
static inline glm::ivec3 toChunk(const glm::ivec3& pos) {
static inline u8vec3 toChunk(const ivec3& pos) {
return localFromGlobal(pos, CHUNK_BLOCK_LENGTH);
}
// Get a Block's relative position to its MapBlock from its world position.
static inline glm::ivec3 toMapBlock(const glm::ivec3& pos) {
static inline u16vec3 toMapBlock(const ivec3& pos) {
return localFromGlobal(pos, MAPBLOCK_BLOCK_LENGTH);
}
// Get a Block's relative position in its Region from its world position.
static inline glm::ivec3 toRegion(const glm::ivec3& pos) {
static inline u16vec3 toRegion(const ivec3& pos) {
return localFromGlobal(pos, REGION_BLOCK_LENGTH);
}
namespace World {
// Get a Block world position from a Regions's world position.
static inline glm::ivec3 fromRegion(const glm::ivec3& pos) {
static inline ivec3 fromRegion(const ivec3& pos) {
return sectionFromGlobal(pos, 1.f / REGION_BLOCK_LENGTH);
}
// Get a Block world position from a MapBlock's world position.
static inline glm::ivec3 fromMapBlock(const glm::ivec3& pos) {
static inline ivec3 fromMapBlock(const ivec3& pos) {
return sectionFromGlobal(pos, 1.f / MAPBLOCK_BLOCK_LENGTH);
}
// Get a Block world position from a Chunk's world position.
static inline glm::ivec3 fromChunk(const glm::ivec3& pos) {
static inline ivec3 fromChunk(const ivec3& pos) {
return sectionFromGlobal(pos, CHUNK_BLOCK_LENGTH);
}
}
}
// Get the index of a Block within its Chunk from its local or world position.
static inline unsigned int index(const glm::ivec3& vec) {
glm::ivec3 local = Block::relative::toChunk(vec);
return static_cast<unsigned int>(local.x + CHUNK_SIZE * (local.z + CHUNK_SIZE * local.y));
static inline u16 index(const ivec3& vec) {
u8vec3 local = Block::relative::toChunk(vec);
return local.x + CHUNK_SIZE * (local.z + CHUNK_SIZE * local.y);
}
// Return a local vector of an block within its chunk.
static inline glm::ivec3 fromIndex(unsigned int ind) {
glm::ivec3 vec{};
static inline u8vec3 fromIndex(u16 ind) {
u8vec3 vec {};
vec.y = ind / (CHUNK_SIZE * CHUNK_SIZE);
ind -= (static_cast<int>(vec.y) * CHUNK_SIZE * CHUNK_SIZE);

60
src/util/Types.h Normal file
View File

@ -0,0 +1,60 @@
/** Type aliases for integer types, vectors, and smart pointers. */
#pragma once
#pragma clang diagnostic push
#pragma ide diagnostic ignored "OCUnusedTypeAliasInspection"
#include <vector>
#include <string>
#include <memory>
#include <cstdint>
#include <glm/glm.hpp>
using i8 = int8_t;
using i16 = int16_t;
using i32 = int32_t;
using i64 = int64_t;
using i8f = int_fast8_t;
using i16f = int_fast16_t;
using i32f = int_fast32_t;
using i64f = int_fast64_t;
using u8 = uint8_t;
using u16 = uint16_t;
using u32 = uint32_t;
using u64 = uint64_t;
using usize = size_t;
using u8f = uint_fast8_t;
using u16f = uint_fast16_t;
using u32f = uint_fast32_t;
using u64f = uint_fast64_t;
using f32 = float;
using f64 = double;
using glm::vec2, glm::vec3, glm::vec4;
using glm::ivec2, glm::ivec3, glm::ivec4;
using glm::i16vec2, glm::i16vec3, glm::i16vec4;
using glm::i8vec2, glm::i8vec3, glm::i8vec4;
using glm::uvec2, glm::uvec3, glm::uvec4;
using glm::u16vec2, glm::u16vec3, glm::u16vec4;
using glm::u8vec2, glm::u8vec3, glm::u8vec4;
using std::array;
using std::string;
template <typename T>
using vec = std::vector<T>;
template <typename T>
using sptr = std::shared_ptr<T>;
template <typename T>
using uptr = std::unique_ptr<T>;
using std::make_shared, std::make_unique;
#pragma clang diagnostic pop

View File

@ -11,70 +11,89 @@
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>
#include "Log.h"
#include "util/Log.h"
#include "util/Types.h"
namespace Util {
struct EnumClassHash {
template<typename T>
std::size_t operator()(T t) const {
return static_cast<std::size_t>(t);
usize operator()(T t) const {
return static_cast<usize>(t);
}
};
static std::string floatToString(float val) {
static string floatToString(f32 val, u8 precision = 2) {
std::ostringstream out;
out.precision(2);
out.precision(precision);
out << std::fixed << val;
return out.str();
}
inline static std::string doubleToString(double val) {
return floatToString((float) val);
inline static string f(f64 val, u8 precision = 2) {
return floatToString(static_cast<f32>(val));
}
static std::string vecToString(glm::ivec3 vec) {
template <typename T, std::enable_if_t<std::is_fundamental_v<T>, bool> = true>
static string vectorToString(vec<T> vec) {
std::ostringstream out;
out << "[ ";
for (usize i = 0; i < vec.size(); i++) out << (i == 0 ? "" : ", ") << vec[i];
out << " ]";
return out.str();
}
template <typename T, usize L, std::enable_if_t<std::is_fundamental_v<T>, bool> = true>
static string arrayToString(array<T, L> arr) {
std::ostringstream out;
out << "[ ";
for (usize i = 0; i < arr.size(); i++) out << (i == 0 ? "" : ", ") << arr[i];
out << " ]";
return out.str();
}
static string vecToString(ivec3 vec) {
std::ostringstream out;
out << vec.x << ", " << vec.y << ", " << vec.z;
return out.str();
}
static std::string vecToString(glm::vec3 vec) {
static string vecToString(vec3 vec) {
std::ostringstream out;
out << vec.x << ", " << vec.y << ", " << vec.z;
return out.str();
}
static std::string floatVecToString(glm::vec3 vec) {
static string floatVecToString(vec3 vec, u8 precision = 2) {
std::ostringstream out;
out.precision(2);
out.precision(precision);
out << std::fixed << vec.x << ", " << std::fixed << vec.y << ", " << std::fixed << vec.z;
return out.str();
}
inline static float packFloat(const glm::vec3& vec) {
auto charX = static_cast<unsigned char>((vec.x + 1.0f) * 0.5f * 255.f);
auto charY = static_cast<unsigned char>((vec.y + 1.0f) * 0.5f * 255.f);
auto charZ = static_cast<unsigned char>((vec.z + 1.0f) * 0.5f * 255.f);
inline static f32 packFloat(const vec3& vec) {
auto charX = static_cast<u8>((vec.x + 1.0f) * 0.5f * 255.f);
auto charY = static_cast<u8>((vec.y + 1.0f) * 0.5f * 255.f);
auto charZ = static_cast<u8>((vec.z + 1.0f) * 0.5f * 255.f);
unsigned int packedInt = (charX << 16) | (charY << 8) | charZ;
return static_cast<float>(static_cast<double>(packedInt) / static_cast<double>(1 << 24));
u32 packedInt = (charX << 16) | (charY << 8) | charZ;
return static_cast<f32>(static_cast<f64>(packedInt) / static_cast<f64>(1 << 24));
}
inline static unsigned int intFromHexSegment(const std::string& t) {
unsigned int x;
inline static u32 intFromHexSegment(const string& t) {
u32 x;
std::stringstream ss;
ss << std::hex << t;
ss >> x;
return x;
}
static glm::vec4 hexToColorVec(std::string hex) {
glm::vec4 color{};
static vec4 hexToColorVec(string hex) {
vec4 color{};
if (hex[0] == '#') hex.erase(0, 1);
else std::cout << Log::err << "Color string does not begin with hash!" << Log::endl;
std::string r, g, b, a;
string r, g, b, a;
if (hex.length() == 3 || hex.length() == 4) {
r = hex.substr(0, 1);
@ -105,7 +124,7 @@ namespace Util {
return color;
}
static std::string getKeyStr(unsigned short key) {
static string getKeyStr(u16 key) {
switch (key) {
default: return "";
@ -244,12 +263,12 @@ namespace Util {
}
namespace {
constexpr static uint64_t mix(char m, uint64_t s) {
constexpr static u64 mix(char m, u64 s) {
return ((s << 7) + ~(s >> 3)) + ~m;
}
}
constexpr static uint64_t hash(const char* m) {
constexpr static u64 hash(const char* m) {
return (*m) ? mix(*m, hash(m + 1)) : 0;
}

View File

@ -6,10 +6,11 @@
#include <array>
#include <functional>
#include <glm/vec3.hpp>
#include <glm/glm.hpp>
#include <unordered_map>
#include "Space.h"
#include "util/Types.h"
#include "util/Space.h"
enum class EVec {
LEFT = 0, RIGHT = 1, BOTTOM = 2, TOP = 3, BACK = 4, FRONT = 5,
@ -25,19 +26,19 @@ namespace Vec {
struct vec3 {
size_t operator()(const glm::vec3& k) const {
return std::hash<float>()(k.x) ^ std::hash<float>()(k.y) ^ std::hash<float>()(k.z);
return std::hash<f32>()(k.x) ^ std::hash<f32>()(k.y) ^ std::hash<f32>()(k.z);
}
};
struct ivec3 {
size_t operator()(const glm::ivec3& k) const {
return std::hash<int>()(k.x) ^ std::hash<int>()(k.y) ^ std::hash<int>()(k.z);
return std::hash<u32>()(k.x) ^ std::hash<u32>()(k.y) ^ std::hash<u32>()(k.z);
}
};
struct ivec4 {
size_t operator()(const glm::ivec4& k) const {
return std::hash<int>()(k.x) ^ std::hash<int>()(k.y) ^ std::hash<int>()(k.z) ^ std::hash<int>()(k.w);
return std::hash<u32>()(k.x) ^ std::hash<u32>()(k.y) ^ std::hash<u32>()(k.z) ^ std::hash<u32>()(k.w);
}
};

View File

@ -1,21 +1,7 @@
//
// Created by auri on 2020-11-03.
//
#include <stdexcept>
#include "Address.h"
/**
* Returns an Address object from the provided address string.
* Address string should be in standard dot + optional colon notation, e.g: 192.168.0.1:8000, 127.0.0.1.
* @throws std::invalid_argument - There is a value after a colon that cannot be converted into a valid numeric value.
* @throws std::out_of_range - There is a numeric port specified, but it is greater than the maximum unsigned short.
* @param addressString - The string to parse.
* @returns - An Address object with the specified address.
*/
Address Address::fromString(const std::string& addressString) {
std::string address;
unsigned short port;

View File

@ -1,16 +1,29 @@
//
// Created by aurailus on 11/07/19.
//
#pragma once
#include <string>
struct Address {
std::string host;
unsigned short port = Address::DEFAULT_PORT;
#include "util/Types.h"
/**
* Represents an IP address + Port pair.
*/
class Address {
public:
/**
* Returns an Address object from the provided address string.
* Address string should be in standard dot + optional colon notation, e.g: 192.168.0.1:8000, 127.0.0.1.
* @throws std::invalid_argument - There is a value after a colon that cannot be converted into a valid numeric value.
* @throws std::out_of_range - There is a numeric port specified, but it is greater than the maximum unsigned short.
* @param addressString - The string to parse.
* @returns - An Address object with the specified address.
*/
static Address fromString(const string& addressString);
static Address fromString(const std::string& addressString);
string host;
u16 port = Address::DEFAULT_PORT;
constexpr static unsigned short DEFAULT_PORT = 13110;
constexpr static u16 DEFAULT_PORT = 13110;
};

View File

@ -1,233 +1,98 @@
//
// Created by aurailus on 2020-01-06.
//
#pragma once
#include <array>
#include <string>
#include <vector>
#include <cstring>
#include <stdexcept>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include <type_traits>
#include "util/Types.h"
class Deserializer {
public:
Deserializer(const std::string& data) : data(&data[0]), len(data.length()) {};
Deserializer(const char* start, size_t len) : data(start), len(len) {};
Deserializer(const string& data) : data(&data[0]), len(data.length()) {};
Deserializer(const char* start, usize len) : data(start), len(len) {};
/** Reads a value into a ref of it, returning the Deserializer for chaining. */
template<typename T>
inline T read() { throw std::runtime_error("Tried to append a non-serializable type"); };
template<typename T>
inline Deserializer& read(T& ref) {
ref = read<T>();
inline Deserializer& read(T& into) {
into = read<T>();
return *this;
};
}
template<typename T, int L>
inline std::array<T, L> readArr() {
auto oldInd = ind;
ind += L * sizeof(T);
std::array<T, L> res;
for (int i = 0; i < L; i++) res[i] = *reinterpret_cast<const T*>(&data[oldInd + i * sizeof(T)]);
/** Reads a trivial value. */
template<typename T, std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_enum_v<T>, bool> = true>
inline T read() {
T value;
std::memcpy(&value, &data[ind], sizeof(T));
ind += sizeof(T);
return value;
}
/** Reads a string. */
template<typename T, std::enable_if_t<std::is_same_v<string, T>, bool> = true>
inline string read() {
usize stringLen = read<usize>();
ind += stringLen;
return string(&data[ind - stringLen], stringLen);
}
/** Reads an array of trivial values. */
template<typename A,
std::enable_if_t<std::is_trivially_copyable_v<typename A::value_type> &&
std::is_same_v<array<typename A::value_type, A::size_type>, A>, bool> = true>
inline A read() {
usize startInd = ind;
ind += A::size_type * sizeof(typename A::value_type);
std::array<typename A::value_type, A::size_type> res;
for (int i = 0; i < A::size_type; i++) res[i] = *reinterpret_cast<const typename A::value_type*>(
&data[startInd + i * sizeof(A::value_type)]);
return res;
}
template<typename T, int L>
inline Deserializer& readArr(std::array<T, L>& ref) {
ref = readArr<T, L>();
return *this;
/** Reads a vector of trivial values. */
template<typename V,
std::enable_if_t<std::is_trivially_copyable_v<typename V::value_type> &&
std::is_same_v<vec<typename V::value_type>, V>, bool> = true>
inline V read() {
usize vecLen = read<usize>();
auto startInd = ind;
ind += vecLen * sizeof(typename V::value_type);
return vec<typename V::value_type>(
reinterpret_cast<const typename V::value_type*>(&data[startInd]),
reinterpret_cast<const typename V::value_type*>(&data[ind]));
}
template<typename T>
inline std::vector<T> readVec() {
unsigned int len = read<unsigned int>();
auto oldInd = ind;
ind += len * sizeof(T);
return std::vector<T>(
reinterpret_cast<const T*>(&data[oldInd]),
reinterpret_cast<const T*>(&data[ind]));
/** Reads a vector of strings. */
template<typename V,
std::enable_if_t<std::is_same_v<string, typename V::value_type> &&
std::is_same_v<vec<typename V::value_type>, V>, bool> = true>
inline V read() {
usize vecLen = read<usize>();
V dataVec = {};
dataVec.reserve(vecLen);
for (usize i = 0; i < vecLen; i++) dataVec.emplace_back(read<typename V::value_type>());
return dataVec;
}
template<typename T>
inline Deserializer& readVec(std::vector<T>& ref) {
ref = readVec<T>();
return *this;
}
template<typename E, typename = typename std::enable_if<std::is_enum<E>::value>::type>
inline E readEnum() {
return static_cast<E>(read<unsigned short>());
};
template<typename E, typename = typename std::enable_if<std::is_enum<E>::value>::type>
inline Deserializer& readEnum(E& ref) {
ref = static_cast<E>(read<unsigned short>());
return *this;
/** Reads an enum. */
template<typename E, std::enable_if_t<std::is_enum_v<E>, bool> = true>
inline E read() {
return static_cast<E>(read<u16>());
};
/** Returns true if there's no more data to be read. */
bool atEnd() {
return ind >= len;
};
/** A reference to the data. */
const char* data;
size_t len;
size_t ind = 0;
private:
typedef union {
int ln;
char bytes[8];
} long_long_union;
/** The length of the data. */
usize len;
typedef union {
int in;
char bytes[4];
} int_union;
typedef union {
unsigned int in;
char bytes[4];
} uint_union;
typedef union {
short sh;
char bytes[2];
} short_union;
typedef union {
unsigned short sh;
char bytes[2];
} ushort_union;
typedef union {
float fl;
char bytes[4];
} float_union;
};
template<>
inline long long Deserializer::read<long long>() {
long_long_union cv;
cv.bytes[0] = data[ind];
cv.bytes[1] = data[ind + 1];
cv.bytes[2] = data[ind + 2];
cv.bytes[3] = data[ind + 3];
cv.bytes[4] = data[ind + 4];
cv.bytes[5] = data[ind + 5];
cv.bytes[6] = data[ind + 6];
cv.bytes[7] = data[ind + 7];
ind += 8;
return cv.ln;
}
template<>
inline int Deserializer::read<int>() {
int_union cv;
cv.bytes[0] = data[ind];
cv.bytes[1] = data[ind + 1];
cv.bytes[2] = data[ind + 2];
cv.bytes[3] = data[ind + 3];
ind += 4;
return cv.in;
}
template<>
inline unsigned int Deserializer::read<unsigned int>() {
uint_union cv;
cv.bytes[0] = data[ind];
cv.bytes[1] = data[ind + 1];
cv.bytes[2] = data[ind + 2];
cv.bytes[3] = data[ind + 3];
ind += 4;
return cv.in;
}
template<>
inline short Deserializer::read<short>() {
short_union cv;
cv.bytes[0] = data[ind];
cv.bytes[1] = data[ind + 1];
ind += 2;
return cv.sh;
}
template<>
inline unsigned short Deserializer::read<unsigned short>() {
ushort_union cv;
cv.bytes[0] = data[ind];
cv.bytes[1] = data[ind + 1];
ind += 2;
return cv.sh;
}
template<>
inline char Deserializer::read<char>() {
return data[ind++];
}
template<>
inline unsigned char Deserializer::read<unsigned char>() {
return static_cast<unsigned char>(data[ind++]);
}
template<>
inline bool Deserializer::read<bool>() {
return read<char>();
}
template<>
inline float Deserializer::read<float>() {
float_union cv;
cv.bytes[0] = data[ind];
cv.bytes[1] = data[ind + 1];
cv.bytes[2] = data[ind + 2];
cv.bytes[3] = data[ind + 3];
ind += 4;
return cv.fl;
}
template<>
inline std::string Deserializer::read<std::string>() {
unsigned int len = read<unsigned int>();
size_t i = ind;
ind += len;
return std::string(&data[i], len);
}
template<>
inline glm::vec2 Deserializer::read<glm::vec2>() {
return {
read<float>(),
read<float>()
};
}
template<>
inline glm::ivec2 Deserializer::read<glm::ivec2>() {
return {
read<int>(),
read<int>()
};
}
template<>
inline glm::vec3 Deserializer::read<glm::vec3>() {
return {
read<float>(),
read<float>(),
read<float>()
};
}
template<>
inline glm::ivec3 Deserializer::read<glm::ivec3>() {
return {
read<int>(),
read<int>(),
read<int>()
};
}
/** The current index. */
usize ind = 0;
};

View File

@ -1,196 +1,80 @@
//
// Created by aurailus on 2020-01-06.
//
#pragma once
#include <array>
#include <string>
#include <vector>
#include <cstring>
#include <stdexcept>
#include <type_traits>
#include <glm/vec2.hpp>
#include <glm/vec3.hpp>
#include "Packet.h"
#include "util/Types.h"
class Serializer {
public:
std::string data{};
template<typename T>
inline Serializer& append(const T& elem) { throw std::runtime_error("Tried to append a non-serializable type"); };
template<typename T, size_t L>
inline Serializer& appendArr(const std::array<T, L>& elem) {
data.reserve(data.length() + elem.size() * sizeof(T));
data += std::string { reinterpret_cast<const char*>(&elem[0]), elem.size() * sizeof(T) };
string data {};
/** Appends a trivial value. */
template<typename T, std::enable_if_t<std::is_trivially_copyable_v<T> && !std::is_enum_v<T>, bool> = true>
inline Serializer& append(const T elem) {
data.reserve(data.length() + sizeof(T));
char c[sizeof(T)];
std::memcpy(c, &elem, sizeof(T));
data += std::string_view(c, sizeof(T));
return *this;
}
template<typename T>
inline Serializer& appendVec(const std::vector<T>& elem) {
data.reserve(data.length() + elem.size() * sizeof(T) + 4);
append<unsigned int>(elem.size());
data += std::string { reinterpret_cast<const char*>(&elem[0]), elem.size() * sizeof(T) };
/** Appends a string. */
template<typename T, std::enable_if_t<std::is_same_v<string, T>, bool> = true>
inline Serializer& append(const T& elem) {
data.reserve(data.length() + sizeof(usize) + elem.size());
append<usize>(elem.size());
data += elem;
return *this;
}
template<typename E, typename = typename std::enable_if<std::is_enum<E>::value>::type>
inline Serializer& appendEnum(const E& elem) {
append<unsigned short>(static_cast<unsigned short>(elem));
/** Appends an array of trivial values. */
template<typename A,
std::enable_if_t<std::is_trivially_copyable_v<typename A::value_type> &&
std::is_same_v<array<typename A::value_type, A::size_type>, A>, bool> = true>
inline Serializer& append(const A& elem) {
data.reserve(data.length() + elem.size() * sizeof(typename A::value_type));
data += string { reinterpret_cast<const char*>(&elem[0]), elem.size() * sizeof(A::value_type) };
return *this;
}
/** Appends a vector of trivial values. */
template<typename V,
std::enable_if_t<std::is_trivially_copyable_v<typename V::value_type> &&
std::is_same<vec<typename V::value_type>, V>::value, bool> = true>
inline Serializer& append(const V& elem) {
data.reserve(data.length() + elem.size() * sizeof(typename V::value_type) + sizeof(usize));
append<usize>(elem.size());
data += string { reinterpret_cast<const char*>(&elem[0]), elem.size() * sizeof(typename V::value_type) };
return *this;
}
/** Appends a vector of strings. */
template<typename V,
std::enable_if_t<std::is_same_v<string, typename V::value_type> &&
std::is_same<vec<typename V::value_type>, V>::value, bool> = true>
inline Serializer& append(const V& elem) {
append<usize>(elem.size());
for (usize i = 0; i < elem.size(); i++) append<typename V::value_type>(elem[i]);
return *this;
}
/** Appends an enum. */
template<typename E, std::enable_if_t<std::is_enum_v<E>, bool> = true>
inline Serializer& append(const E& elem) {
append<u16>(static_cast<u16>(elem));
return *this;
}
/** Creates a packet from the data supplied. */
Packet packet(Packet::Type p = Packet::Type::UNDEFINED, bool reliable = true) {
Packet packet(p, reliable);
packet.data = data;
return std::move(packet);
};
private:
typedef union {
long long ln;
char bytes[8];
} long_long_union;
typedef union {
int in;
char bytes[4];
} int_union;
typedef union {
unsigned int in;
char bytes[4];
} uint_union;
typedef union {
short sh;
char bytes[2];
} short_union;
typedef union {
unsigned short sh;
char bytes[2];
} ushort_union;
typedef union {
float fl;
char bytes[4];
} float_union;
};
template<>
inline Serializer& Serializer::append<long long>(const long long& elem) {
long_long_union cv = { elem };
data += cv.bytes[0];
data += cv.bytes[1];
data += cv.bytes[2];
data += cv.bytes[3];
data += cv.bytes[4];
data += cv.bytes[5];
data += cv.bytes[6];
data += cv.bytes[7];
return *this;
}
template<>
inline Serializer& Serializer::append<int>(const int& elem) {
int_union cv = { elem };
data += cv.bytes[0];
data += cv.bytes[1];
data += cv.bytes[2];
data += cv.bytes[3];
return *this;
}
template<>
inline Serializer& Serializer::append<unsigned int>(const unsigned int& elem) {
uint_union cv = { elem };
data += cv.bytes[0];
data += cv.bytes[1];
data += cv.bytes[2];
data += cv.bytes[3];
return *this;
}
template<>
inline Serializer& Serializer::append<short>(const short& elem) {
short_union cv = { elem };
data += cv.bytes[0];
data += cv.bytes[1];
return *this;
}
template<>
inline Serializer& Serializer::append<unsigned short>(const unsigned short& elem) {
ushort_union cv = { elem };
data += cv.bytes[0];
data += cv.bytes[1];
return *this;
}
template<>
inline Serializer& Serializer::append<char>(const char& elem) {
data += elem;
return *this;
}
template<>
inline Serializer& Serializer::append<unsigned char>(const unsigned char& elem) {
data += static_cast<char>(elem);
return *this;
}
template<>
inline Serializer& Serializer::append<bool>(const bool& elem) {
append<char>(elem);
return *this;
}
template<>
inline Serializer& Serializer::append<float>(const float& elem) {
float_union cv = { elem };
data += cv.bytes[0];
data += cv.bytes[1];
data += cv.bytes[2];
data += cv.bytes[3];
return *this;
}
template<>
inline Serializer& Serializer::append<std::string>(const std::string& elem) {
append<unsigned int>(elem.length());
data += elem;
return *this;
}
template<>
inline Serializer& Serializer::append<glm::vec2>(const glm::vec2& elem) {
append<float>(elem.x);
append<float>(elem.y);
return *this;
}
template<>
inline Serializer& Serializer::append<glm::ivec2>(const glm::ivec2& elem) {
append<int>(elem.x);
append<int>(elem.y);
return *this;
}
template<>
inline Serializer& Serializer::append<glm::vec3>(const glm::vec3& elem) {
append<float>(elem.x);
append<float>(elem.y);
append<float>(elem.z);
return *this;
}
template<>
inline Serializer& Serializer::append<glm::ivec3>(const glm::ivec3& elem) {
append<int>(elem.x);
append<int>(elem.y);
append<int>(elem.z);
return *this;
}
};

View File

@ -77,15 +77,15 @@ void LocalWorld::handleWorldPacket(std::unique_ptr<PacketView> p) {
void LocalWorld::handlePlayerEntPacket(std::unique_ptr<PacketView> p) {
if (!player) throw std::runtime_error("Received playerEnt info *before* the player was created.");
unsigned int id = p->d.read<unsigned int>();
u32 id = p->d.read<u32>();
if (player->getId() == id) return;
bool found = false;
for (auto& entity : getActiveDimension().l()->playerEntities) {
if (entity.getId() == id) {
entity.interpPos(p->d.read<glm::vec3>());
entity.interpRotateZ(-p->d.read<float>() + 90);
entity.interpRotateY(-p->d.read<float>() + 90);
entity.interpPos(p->d.read<vec3>());
entity.interpRotateZ(-p->d.read<f32>() + 90);
entity.interpRotateY(-p->d.read<f32>() + 90);
found = true;
break;

View File

@ -26,20 +26,19 @@ ServerWorld::ServerWorld(unsigned int seed, SubgamePtr game, ServerClients& clie
seed(seed),
clients(clients),
refs(std::make_shared<ServerInventoryRefs>(game, clients)) {
clients.init(this);
generateOrder.reserve(mapBlockGenRange.x * 2 + 1 * mapBlockGenRange.x * 2 + 1 * mapBlockGenRange.y * 2 + 1);
std::unordered_set<glm::ivec3, Vec::ivec3> found{};
std::queue<glm::ivec3> queue{};
std::unordered_set<glm::ivec3, Vec::ivec3> found {};
std::queue<glm::ivec3> queue {};
queue.emplace(0, 0, 0);
found.emplace(0, 0, 0);
const std::vector<glm::ivec3> dirs{
glm::ivec3{ 1, 0, 0 }, glm::ivec3{ -1, 0, 0 },
glm::ivec3{ 0, 1, 0 }, glm::ivec3{ 0, -1, 0 },
glm::ivec3{ 0, 0, 1 }, glm::ivec3{ 0, 0, -1 }};
ivec3 { 1, 0, 0 }, ivec3{ -1, 0, 0 },
ivec3 { 0, 1, 0 }, ivec3{ 0, -1, 0 },
ivec3 { 0, 0, 1 }, ivec3{ 0, 0, -1 }};
while (!queue.empty()) {
glm::ivec3 pos = queue.front();
@ -72,13 +71,13 @@ void ServerWorld::update(double delta) {
World::update(delta);
refs->update();
unsigned int genCount = 0;
std::unordered_set<glm::ivec4, Vec::ivec4> updatedChunks{};
u32 genCount = 0;
std::unordered_set<ivec4, Vec::ivec4> updatedChunks{};
auto finishedGen = genStream->update();
for (auto& data : *finishedGen) {
for (const auto& pos : *data.created)
updatedChunks.insert(glm::ivec4(pos, data.dim));
updatedChunks.insert(ivec4(pos, data.dim));
// Mapblock might have been pruned in between generation assignment and now.
auto mb = getDimension(data.dim)->getMapBlock(glm::ivec3(data.pos));
@ -133,7 +132,7 @@ void ServerWorld::update(double delta) {
for (auto& d : dimensions) {
auto dimension = std::static_pointer_cast<ServerDimension>(d);
unsigned int ind = dimension->getInd();
u16 ind = dimension->getInd();
// Update clients with new entity information.
@ -146,7 +145,7 @@ void ServerWorld::update(double delta) {
}
// Contains more than just the dimension identifier.
if (inf.data.size() > 4) {
if (inf.data.size() > sizeof(u16)) {
auto p = inf.packet(Packet::Type::ENTITY_INFO);
for (auto& player : clients.players)
if (player->getDim()->getInd() == ind)
@ -158,11 +157,11 @@ void ServerWorld::update(double delta) {
Serializer rem;
rem.append(ind);
for (unsigned int entity : dimension->getRemovedEntities()) {
rem.append<unsigned int>(entity);
for (i64 entity : dimension->getRemovedEntities()) {
rem.append<i64>(entity);
}
if (rem.data.size() > 4) {
if (rem.data.size() > sizeof(u16)) {
Packet p = rem.packet(Packet::Type::ENTITY_REMOVED);
for (auto& player : clients.players)
if (player->getDim()->getInd() == ind)
@ -239,7 +238,7 @@ void ServerWorld::sendChunksToPlayer(ServerPlayer& client) {
}
}
void ServerWorld::sendMessage(const std::string& channel, const std::string& message) {
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);

View File

@ -27,7 +27,7 @@ class ServerGenStream;
class ServerPacketStream;
class ServerWorld : public World {
public:
public:
explicit ServerWorld(unsigned int seed, SubgamePtr game, ServerClients& clients);
void init(const std::string& worldDir);
@ -47,7 +47,7 @@ class ServerWorld : public World {
virtual ServerClients& getClients();
private:
private:
void changedMapBlocks(ServerPlayer& player);
bool generateMapBlock(unsigned int dim, glm::ivec3 pos);
@ -59,18 +59,18 @@ class ServerWorld : public World {
std::shared_ptr<ServerGenStream> genStream = nullptr;
std::shared_ptr<ServerPacketStream> packetStream = nullptr;
unsigned int seed;
u32 seed;
ServerClients& clients;
std::shared_ptr<ServerInventoryRefs> refs;
// std::string worldDir;
// std::shared_ptr<FileManipulator> fileManip;
unsigned int generatedMapBlocks = 0;
std::vector<glm::ivec3> generateOrder;
u32 generatedMapBlocks = 0;
std::vector<ivec3> generateOrder;
const glm::ivec2 mapBlockGenRange = { 4, 4 };
const glm::ivec2 sendRange = { 4, 4 };
const glm::ivec2 activeChunkRange = { 16, 16 };
const ivec2 mapBlockGenRange = { 4, 4 };
const ivec2 sendRange = { 4, 4 };
const ivec2 activeChunkRange = { 16, 16 };
};

View File

@ -9,7 +9,7 @@
#include "game/def/BlockDef.h"
#include "game/atlas/DefinitionAtlas.h"
bool Dimension::setBlock(glm::ivec3 pos, unsigned int block) {
bool Dimension::setBlock(ivec3 pos, u16 block) {
auto l = getReadLock();
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
l.unlock();
@ -62,10 +62,10 @@ bool Dimension::setBlock(glm::ivec3 pos, unsigned int block) {
// return propogateRemoveNodes();
//}
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
std::unordered_set<ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
std::unordered_set<ivec3, Vec::ivec3> chunksUpdated {};
for (unsigned int channel = 0; channel < 4; channel++) {
for (u8 channel = 0; channel < 4; channel++) {
while (true) {
auto l = getWriteLock();
if (lightAddQueue[channel].empty()) break;
@ -77,10 +77,10 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
if (!chunksUpdated.count(chunk->getPos())) chunksUpdated.insert(chunk->getPos());
unsigned char lightLevel = node.chunk->getLight(node.index, channel);
glm::ivec3 worldPos = node.chunk->getPos() * 16 + Space::Block::fromIndex(node.index);
ivec3 worldPos = node.chunk->getPos() * 16 + ivec3(Space::Block::fromIndex(node.index));
for (const auto& i : Vec::TO_VEC) {
glm::ivec3 check = worldPos + i;
ivec3 check = worldPos + i;
unsigned int ind = Space::Block::index(check);
Chunk* chunk;
if (containsWorldPos(node.chunk, check)) chunk = node.chunk;
@ -110,10 +110,10 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateAddNodes() {
return chunksUpdated;
}
std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
std::unordered_set<glm::ivec3, Vec::ivec3> chunksUpdated {};
std::unordered_set<ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
std::unordered_set<ivec3, Vec::ivec3> chunksUpdated {};
for (unsigned int channel = 0; channel < 4; channel++) {
for (u8 channel = 0; channel < 4; channel++) {
while (true) {
auto l = getWriteLock();
if (lightRemoveQueue[channel].empty()) break;
@ -121,10 +121,10 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
lightRemoveQueue[channel].pop();
l.unlock();
glm::ivec3 worldPos = node.chunk->getPos() * 16 + Space::Block::fromIndex(node.index);
ivec3 worldPos = node.chunk->getPos() * 16 + ivec3(Space::Block::fromIndex(node.index));
for (const auto& i : Vec::TO_VEC) {
glm::ivec3 check = worldPos + i;
ivec3 check = worldPos + i;
unsigned int ind = Space::Block::index(check);
Chunk* chunk;
if (containsWorldPos(node.chunk, check)) chunk = node.chunk;
@ -137,7 +137,7 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
}
}
unsigned char checkLight = chunk->getLight(ind, channel);
u8 checkLight = chunk->getLight(ind, channel);
if (checkLight != 0 &&
(checkLight < node.value || (channel == SUNLIGHT_CHANNEL && i.y == -1 && node.value == 15))) {
unsigned int replaceLight = (channel == SUNLIGHT_CHANNEL ? 0 :
@ -169,48 +169,48 @@ std::unordered_set<glm::ivec3, Vec::ivec3> Dimension::propogateRemoveNodes() {
return chunksUpdated;
}
bool Dimension::containsWorldPos(Chunk* chunk, glm::ivec3 pos) {
bool Dimension::containsWorldPos(Chunk* chunk, ivec3 pos) {
return chunk && Space::Chunk::world::fromBlock(pos) == chunk->getPos();
}
glm::ivec4 Dimension::getLight(glm::ivec3 worldPos, Chunk* chunk) {
u8vec4 Dimension::getLight(ivec3 worldPos, Chunk* chunk) {
if (containsWorldPos(chunk, worldPos)) return chunk->getLight(Space::Block::index(worldPos));
auto oChunk = getChunk(Space::Chunk::world::fromBlock(worldPos)).get();
return (oChunk ? oChunk->getLight(Space::Block::index(worldPos)) : glm::ivec4 {});
return (oChunk ? oChunk->getLight(Space::Block::index(worldPos)) : u8vec4 {});
}
void Dimension::calculateHorizontalEdge(std::shared_ptr<Chunk> a, std::shared_ptr<Chunk> b) {
for (unsigned int j = 0; j < 256; j++) {
glm::ivec3 diff = a->getPos() - b->getPos();
void Dimension::calculateHorizontalEdge(sptr<Chunk> a, sptr<Chunk> b) {
for (u16 j = 0; j < 256; j++) {
ivec3 diff = a->getPos() - b->getPos();
glm::ivec3 aPos = {
ivec3 aPos = {
(diff.x == 0 ? j % 16 : diff.x == 1 ? 0 : 15), j / 16,
(diff.z == 0 ? j % 16 : diff.z == 1 ? 0 : 15) };
glm::ivec3 bPos = {
ivec3 bPos = {
(diff.x == 0 ? j % 16 : diff.x == 1 ? 15 : 0), j / 16,
(diff.z == 0 ? j % 16 : diff.z == 1 ? 15 : 0) };
auto lightA = a->getLight(Space::Block::index(aPos), 3);
auto lightB = b->getLight(Space::Block::index(bPos), 3);
u8 lightA = a->getLight(Space::Block::index(aPos), 3);
u8 lightB = b->getLight(Space::Block::index(bPos), 3);
if (lightA > lightB + 1) setAndReflowSunlight(b->getPos() * 16 + bPos, lightA - 1);
else if (lightB > lightA + 1) setAndReflowSunlight(a->getPos() * 16 + aPos, lightB - 1);
}
}
void Dimension::calculateVerticalEdge(std::shared_ptr<Chunk> above, std::shared_ptr<Chunk> below) {
for (unsigned int j = 0; j < 256; j++) {
unsigned int xx = j / 16;
unsigned int zz = j % 16;
void Dimension::calculateVerticalEdge(sptr<Chunk> above, sptr<Chunk> below) {
for (u16 j = 0; j < 256; j++) {
u32 x = j / 16;
u32 z = j % 16;
auto lightAbove = above->getLight(Space::Block::index({ xx, 0, zz }), 3);
auto lightBelow = below->getLight(Space::Block::index({ xx, 15, zz }), 3);
auto lightAbove = above->getLight(Space::Block::index({ x, 0, z }), 3);
auto lightBelow = below->getLight(Space::Block::index({ x, 15, z }), 3);
if (lightBelow > lightAbove) removeSunlight(below->getPos() * 16 + glm::ivec3 { xx, 15, zz });
if (lightBelow > lightAbove) removeSunlight(below->getPos() * 16 + glm::ivec3 { x, 15, z });
}
}
void Dimension::addBlockLight(glm::ivec3 pos, glm::ivec3 light) {
void Dimension::addBlockLight(ivec3 pos, ivec3 light) {
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
auto ind = Space::Block::index(pos);
@ -224,10 +224,10 @@ void Dimension::addBlockLight(glm::ivec3 pos, glm::ivec3 light) {
lightAddQueue[2].emplace(ind, startChunk.get());
}
void Dimension::removeBlockLight(glm::ivec3 pos) {
void Dimension::removeBlockLight(ivec3 pos) {
auto startChunk = getChunk(Space::Chunk::world::fromBlock(pos));
unsigned int ind = Space::Block::index(pos);
glm::ivec4 val = startChunk->getLight(ind);
u16 ind = Space::Block::index(pos);
ivec4 val = startChunk->getLight(ind);
startChunk->setLight(ind, 0, 0);
startChunk->setLight(ind, 1, 0);

View File

@ -12,23 +12,24 @@
#include "DimensionBase.h"
#include "util/Types.h"
class Target;
class Player;
class Dimension : public DimensionBase {
public:
typedef std::unordered_set<glm::ivec3, Vec::ivec3> relitChunks;
typedef std::unordered_set<ivec3, Vec::ivec3> relitChunks;
Dimension(const Dimension& o) = delete;
Dimension(SubgamePtr game, World& world, const std::string& identifier, unsigned int ind,
std::shared_ptr<MapGen> mapGen) :
Dimension(SubgamePtr game, World& world, const string& identifier, u16 ind, sptr<MapGen> mapGen) :
DimensionBase(game, world, identifier, ind, std::move(mapGen)) {}
// Override setBlock to update lighting.
bool setBlock(glm::ivec3 pos, unsigned int block) override;
bool setBlock(ivec3 pos, u16 block) override;
virtual double blockHit(const Target& target, PlayerPtr player) = 0;
virtual f64 blockHit(const Target& target, PlayerPtr player) = 0;
virtual void blockPlace(const Target& target, PlayerPtr player) = 0;
@ -38,7 +39,7 @@ public:
virtual void wieldItemUse(const Target& target, PlayerPtr player) = 0;
virtual long long nextEntityInd() = 0;
virtual i64 nextEntityInd() = 0;
// Calculate light propogation around MapBlock edges,
// Called after a new mapblock is inserted into the dimension.
@ -57,36 +58,36 @@ private:
static inline bool containsWorldPos(Chunk* chunk, glm::ivec3 pos);
inline glm::ivec4 getLight(glm::ivec3 worldPos, Chunk* chunk = nullptr);
inline u8vec4 getLight(ivec3 worldPos, Chunk* chunk = nullptr);
void calculateHorizontalEdge(std::shared_ptr<Chunk> a, std::shared_ptr<Chunk> b);
void calculateHorizontalEdge(sptr<Chunk> a, sptr<Chunk> b);
void calculateVerticalEdge(std::shared_ptr<Chunk> above, std::shared_ptr<Chunk> below);
void calculateVerticalEdge(sptr<Chunk> above, sptr<Chunk> below);
inline void addBlockLight(glm::ivec3 pos, glm::ivec3 light);
inline void addBlockLight(ivec3 pos, ivec3 light);
inline void removeBlockLight(glm::ivec3 pos);
inline void removeBlockLight(ivec3 pos);
inline void reflowLight(glm::ivec3 pos);
inline void reflowLight(ivec3 pos);
inline void removeSunlight(glm::ivec3 pos);
inline void removeSunlight(ivec3 pos);
inline void setAndReflowSunlight(glm::ivec3 pos, unsigned char level);
inline void setAndReflowSunlight(ivec3 pos, u8 level);
struct LightAddNode {
LightAddNode(unsigned short index, Chunk* chunk) : index(index), chunk(chunk) {};
unsigned short index;
LightAddNode(u16 index, Chunk* chunk) : index(index), chunk(chunk) {};
u16 index;
Chunk* chunk;
};
struct LightRemoveNode {
LightRemoveNode(unsigned short index, unsigned short value, Chunk* chunk) : index(index), value(value),
chunk(chunk) {};
unsigned short index, value;
LightRemoveNode(u16 index, u16 value, Chunk* chunk) : index(index), value(value), chunk(chunk) {};
u16 index;
u16 value;
Chunk* chunk;
};
static constexpr unsigned char SUNLIGHT_CHANNEL = 3;
std::array<std::queue<LightAddNode>, 4> lightAddQueue;
std::array<std::queue<LightRemoveNode>, 4> lightRemoveQueue;
static constexpr u8 SUNLIGHT_CHANNEL = 3;
array<std::queue<LightAddNode>, 4> lightAddQueue;
array<std::queue<LightRemoveNode>, 4> lightRemoveQueue;
};

View File

@ -12,36 +12,35 @@
#include "world/dim/chunk/MapBlock.h"
#include "game/atlas/DefinitionAtlas.h"
DimensionBase::DimensionBase(SubgamePtr game, World& world, const std::string& identifier,
unsigned int ind, std::shared_ptr<MapGen> mapGen) :
DimensionBase::DimensionBase(SubgamePtr game, World& world, const string& identifier, u16 ind, sptr<MapGen> mapGen) :
game(game), world(world), identifier(identifier), ind(ind), mapGen(std::move(mapGen)) {}
std::string DimensionBase::getIdentifier() const {
string DimensionBase::getIdentifier() const {
return identifier;
}
unsigned int DimensionBase::getInd() {
u16 DimensionBase::getInd() {
return ind;
}
std::shared_ptr<Region> DimensionBase::getRegion(glm::ivec3 regionPosition) const {
sptr<Region> DimensionBase::getRegion(ivec3 regionPosition) const {
auto _ = getReadLock();
if (!regions.count(regionPosition)) return nullptr;
return regions.at(regionPosition);
}
void DimensionBase::removeRegion(glm::ivec3 pos) {
void DimensionBase::removeRegion(ivec3 pos) {
auto _ = getWriteLock();
regions.erase(pos);
}
std::shared_ptr<MapBlock> DimensionBase::getMapBlock(glm::ivec3 mapBlockPosition) const {
sptr<MapBlock> DimensionBase::getMapBlock(ivec3 mapBlockPosition) const {
auto region = getRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
if (!region) return nullptr;
return region->get(Space::MapBlock::index(mapBlockPosition));
}
void DimensionBase::removeMapBlock(glm::ivec3 pos) {
void DimensionBase::removeMapBlock(ivec3 pos) {
auto region = getRegion(Space::Region::world::fromMapBlock(pos));
if (!region) return;
auto i = Space::MapBlock::index(pos);
@ -49,23 +48,23 @@ void DimensionBase::removeMapBlock(glm::ivec3 pos) {
if (region->count == 0) removeRegion(Space::Region::world::fromMapBlock(pos));
}
bool DimensionBase::mapBlockGenerated(glm::ivec3 mapBlockPosition) {
bool DimensionBase::mapBlockGenerated(ivec3 mapBlockPosition) {
auto mb = getMapBlock(mapBlockPosition);
return mb && mb->generated;
}
std::shared_ptr<Chunk> DimensionBase::getChunk(glm::ivec3 chunkPosition) const {
sptr<Chunk> DimensionBase::getChunk(ivec3 chunkPosition) const {
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(chunkPosition));
if (!mapBlock) return nullptr;
return mapBlock->get(Space::Chunk::index(chunkPosition));
}
void DimensionBase::setChunk(std::shared_ptr<Chunk> chunk) {
void DimensionBase::setChunk(sptr<Chunk> chunk) {
auto mapBlock = getOrCreateMapBlock(Space::MapBlock::world::fromChunk(chunk->getPos()));
mapBlock->set(Space::Chunk::index(chunk->getPos()), chunk);
}
void DimensionBase::removeChunk(glm::ivec3 pos) {
void DimensionBase::removeChunk(ivec3 pos) {
auto mapBlock = getMapBlock(Space::MapBlock::world::fromChunk(pos));
if (!mapBlock) return;
auto i = Space::Chunk::index(pos);
@ -73,14 +72,14 @@ void DimensionBase::removeChunk(glm::ivec3 pos) {
if (mapBlock->count == 0) removeMapBlock(Space::MapBlock::world::fromChunk(pos));
}
unsigned int DimensionBase::getBlock(glm::ivec3 pos) const {
u16 DimensionBase::getBlock(ivec3 pos) const {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return 0;
return chunk->getBlock(Space::Block::relative::toChunk(pos));
}
bool DimensionBase::setBlock(glm::ivec3 pos, unsigned int block) {
bool DimensionBase::setBlock(ivec3 pos, u16 block) {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return false;
@ -90,12 +89,12 @@ bool DimensionBase::setBlock(glm::ivec3 pos, unsigned int block) {
}
double DimensionBase::getBlockDamage(glm::ivec3 pos) const {
f64 DimensionBase::getBlockDamage(ivec3 pos) const {
auto _ = getReadLock();
return blockDamages.count(pos) ? blockDamages.at(pos).curr : 0;
}
double DimensionBase::setBlockDamage(glm::ivec3 pos, double damage) {
f64 DimensionBase::setBlockDamage(ivec3 pos, f64 damage) {
if (blockDamages.count(pos)) blockDamages[pos].curr = damage;
else {
double health = game->getDefs().blockFromId(getBlock(pos)).health;
@ -106,33 +105,33 @@ double DimensionBase::setBlockDamage(glm::ivec3 pos, double damage) {
return getBlockDamage(pos);
}
unsigned int DimensionBase::getBiome(glm::ivec3 pos) const {
u16 DimensionBase::getBiome(ivec3 pos) const {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return 0;
return chunk->getBiome(Space::Block::relative::toChunk(pos));
}
bool DimensionBase::setBiome(glm::ivec3 pos, unsigned int biome) {
bool DimensionBase::setBiome(ivec3 pos, u16 biome) {
auto chunk = getChunk(Space::Chunk::world::fromBlock(pos));
if (!chunk) return false;
return chunk->setBiome(Space::Block::relative::toChunk(pos), biome);
}
std::shared_ptr<Region> DimensionBase::getOrCreateRegion(glm::ivec3 pos) {
sptr<Region> DimensionBase::getOrCreateRegion(ivec3 pos) {
auto _ = getWriteLock();
if (regions[pos]) return regions[pos];
regions[pos] = std::make_shared<Region>(pos);
regions[pos] = make_shared<Region>(pos);
return regions[pos];
}
std::shared_ptr<MapBlock> DimensionBase::getOrCreateMapBlock(glm::ivec3 mapBlockPosition) {
sptr<MapBlock> DimensionBase::getOrCreateMapBlock(ivec3 mapBlockPosition) {
auto region = getOrCreateRegion(Space::Region::world::fromMapBlock(mapBlockPosition));
unsigned int index = Space::MapBlock::index(mapBlockPosition);
if (region->get(index) != nullptr) return region->get(index);
region->set(index, std::make_shared<MapBlock>(mapBlockPosition));
region->set(index, make_shared<MapBlock>(mapBlockPosition));
return region->get(index);
}
@ -144,11 +143,11 @@ World& DimensionBase::getWorld() {
return world;
}
std::shared_ptr<Chunk> DimensionBase::combineChunks(std::shared_ptr<Chunk> a, std::shared_ptr<Chunk> b) {
sptr<Chunk> DimensionBase::combineChunks(sptr<Chunk> a, sptr<Chunk> b) {
if (a->isGenerated()) return (a->combineWith(b), a);
else return (b->combineWith(a), b);
}
std::shared_ptr<MapGen> DimensionBase::getGen() {
sptr<MapGen> DimensionBase::getGen() {
return mapGen;
}

View File

@ -21,45 +21,44 @@ class MapBlock;
class DefinitionAtlas;
class DimensionBase : protected Lockable {
public:
DimensionBase(SubgamePtr game, World& world, const std::string& identifier, unsigned int ind,
std::shared_ptr<MapGen> mapGen);
public:
DimensionBase(SubgamePtr game, World& world, const string& identifier, u16 ind, sptr<MapGen> mapGen);
std::string getIdentifier() const;
string getIdentifier() const;
unsigned int getInd();
u16 getInd();
virtual void update(double delta) = 0;
virtual void update(f64 delta) = 0;
std::shared_ptr<Region> getRegion(glm::ivec3 regionPosition) const;
sptr<Region> getRegion(ivec3 regionPosition) const;
void removeRegion(glm::ivec3 pos);
void removeRegion(ivec3 pos);
std::shared_ptr<MapBlock> getMapBlock(glm::ivec3 mapBlockPosition) const;
sptr<MapBlock> getMapBlock(ivec3 mapBlockPosition) const;
virtual void removeMapBlock(glm::ivec3 pos);
virtual void removeMapBlock(ivec3 pos);
bool mapBlockGenerated(glm::ivec3 mapBlockPosition);
bool mapBlockGenerated(ivec3 mapBlockPosition);
std::shared_ptr<Chunk> getChunk(glm::ivec3 chunkPosition) const;
sptr<Chunk> getChunk(ivec3 chunkPosition) const;
virtual void setChunk(std::shared_ptr<Chunk> chunk);
virtual void setChunk(sptr<Chunk> chunk);
virtual void removeChunk(glm::ivec3 pos);
virtual void removeChunk(ivec3 pos);
unsigned int getBlock(glm::ivec3 pos) const;
u16 getBlock(ivec3 pos) const;
virtual bool setBlock(glm::ivec3 pos, unsigned int block);
virtual bool setBlock(ivec3 pos, u16 block);
virtual double getBlockDamage(glm::ivec3 pos) const;
virtual f64 getBlockDamage(ivec3 pos) const;
virtual double setBlockDamage(glm::ivec3 pos, double damage);
virtual f64 setBlockDamage(ivec3 pos, f64 damage);
unsigned int getBiome(glm::ivec3 pos) const;
u16 getBiome(ivec3 pos) const;
virtual bool setBiome(glm::ivec3 pos, unsigned int biome);
virtual bool setBiome(ivec3 pos, u16 biome);
std::shared_ptr<MapGen> getGen();
sptr<MapGen> getGen();
SubgamePtr getGame();
@ -68,26 +67,26 @@ class DimensionBase : protected Lockable {
protected:
// Combine two chunk partials, or a chunk and a chunk partial.
// If both are partials `b` takes preference, if one is a fully generated chunk the partial takes preference.
// TODO: Make this more efficient using proper RIE traversal.
static std::shared_ptr<Chunk> combineChunks(std::shared_ptr<Chunk> a, std::shared_ptr<Chunk> b);
static sptr<Chunk> combineChunks(sptr<Chunk> a, sptr<Chunk> b);
std::shared_ptr<MapGen> mapGen;
sptr<MapGen> mapGen;
SubgamePtr game;
World& world;
typedef std::unordered_map<glm::ivec3, std::shared_ptr<Region>, Vec::ivec3> block_region_map;
typedef std::unordered_map<ivec3, sptr<Region>, Vec::ivec3> block_region_map;
block_region_map regions;
std::string identifier;
unsigned int ind;
u16 ind;
string identifier;
struct Damage {
double curr, max;
f64 curr;
f64 max;
};
std::unordered_map<glm::ivec3, Damage, Vec::ivec3> blockDamages;
std::unordered_map<ivec3, Damage, Vec::ivec3> blockDamages;
private:
inline std::shared_ptr<Region> getOrCreateRegion(glm::ivec3 pos);
inline sptr<Region> getOrCreateRegion(ivec3 pos);
inline std::shared_ptr<MapBlock> getOrCreateMapBlock(glm::ivec3 mapBlockPosition);
inline sptr<MapBlock> getOrCreateMapBlock(ivec3 mapBlockPosition);
};

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 04/04/19.
//
#include "LocalDimension.h"
#include "world/LocalWorld.h"
@ -16,8 +12,8 @@
#include "client/stream/MeshGenStream.h"
#include "client/graph/mesh/MeshChunk.h"
LocalDimension::LocalDimension(SubgamePtr game, LocalWorld& world, const std::string& identifier,
unsigned int ind, std::shared_ptr<MapGen> mapGen) :
LocalDimension::LocalDimension(SubgamePtr game, LocalWorld& world,
const string& identifier, u16 ind, sptr<MapGen> mapGen) :
Dimension(game, static_cast<World&>(world), identifier, ind, std::move(mapGen)),
meshGenStream(std::make_shared<MeshGenStream>(game, *this)) {}
@ -81,7 +77,7 @@ void LocalDimension::setChunk(std::shared_ptr<Chunk> chunk) {
attemptMeshChunk(chunk);
}
bool LocalDimension::setBlock(glm::ivec3 pos, unsigned int block) {
bool LocalDimension::setBlock(ivec3 pos, u16 block) {
bool exists = Dimension::setBlock(pos, block);
if (!exists) return false;
@ -94,12 +90,12 @@ bool LocalDimension::setBlock(glm::ivec3 pos, unsigned int block) {
auto cp = Space::Chunk::world::fromBlock(pos);
std::shared_ptr<Chunk> tempChunk;
if (lp.x == 15 && (tempChunk = getChunk(cp + glm::ivec3{ 1, 0, 0 }))) tempChunk->setDirty(true);
else if (lp.x == 0 && (tempChunk = getChunk(cp + glm::ivec3{ -1, 0, 0 }))) tempChunk->setDirty(true);
if (lp.y == 15 && (tempChunk = getChunk(cp + glm::ivec3{ 0, 1, 0 }))) tempChunk->setDirty(true);
else if (lp.y == 0 && (tempChunk = getChunk(cp + glm::ivec3{ 0, -1, 0 }))) tempChunk->setDirty(true);
if (lp.z == 15 && (tempChunk = getChunk(cp + glm::ivec3{ 0, 0, 1 }))) tempChunk->setDirty(true);
else if (lp.z == 0 && (tempChunk = getChunk(cp + glm::ivec3{ 0, 0, -1 }))) tempChunk->setDirty(true);
if (lp.x == 15 && (tempChunk = getChunk(cp + ivec3{ 1, 0, 0 }))) tempChunk->setDirty(true);
else if (lp.x == 0 && (tempChunk = getChunk(cp + ivec3{ -1, 0, 0 }))) tempChunk->setDirty(true);
if (lp.y == 15 && (tempChunk = getChunk(cp + ivec3{ 0, 1, 0 }))) tempChunk->setDirty(true);
else if (lp.y == 0 && (tempChunk = getChunk(cp + ivec3{ 0, -1, 0 }))) tempChunk->setDirty(true);
if (lp.z == 15 && (tempChunk = getChunk(cp + ivec3{ 0, 0, 1 }))) tempChunk->setDirty(true);
else if (lp.z == 0 && (tempChunk = getChunk(cp + ivec3{ 0, 0, -1 }))) tempChunk->setDirty(true);
attemptMeshChunk(chunk, true);
return true;
@ -178,7 +174,7 @@ void LocalDimension::removeMeshChunk(const glm::ivec3& pos) {
}
}
long long LocalDimension::nextEntityInd() {
i64 LocalDimension::nextEntityInd() {
auto _ = getWriteLock();
return entityInd--;
}
@ -200,13 +196,13 @@ void LocalDimension::removeLocalEntity(Api::Usertype::Entity entity) {
}
void LocalDimension::serverEntitiesInfo(Deserializer& e) {
e.read<unsigned int>();
e.read<u16>();
while (!e.atEnd()) {
std::string dat = e.read<std::string>();
string dat = e.read<string>();
Deserializer d(dat);
auto id = d.read<long long>();
auto id = d.read<i64>();
std::shared_ptr<LocalLuaEntity> activeEntity;
if (entityRefs.count(id)) activeEntity = entityRefs.at(id)->entity.l();
else {
@ -219,7 +215,7 @@ void LocalDimension::serverEntitiesInfo(Deserializer& e) {
}
while (!d.atEnd()) {
const auto field = d.readEnum<NetField>();
const auto field = d.read<NetField>();
switch (field) {
default:
std::cout << Log::err << "Entity received unhandled NetField, Type "
@ -227,27 +223,27 @@ void LocalDimension::serverEntitiesInfo(Deserializer& e) {
break;
case NetField::POS:
activeEntity->setPos(d.read<glm::vec3>());
activeEntity->setPos(d.read<vec3>());
break;
case NetField::VEL:
activeEntity->setVel(d.read<glm::vec3>());
activeEntity->setVel(d.read<vec3>());
break;
case NetField::ROT:
activeEntity->setRot(d.read<glm::vec3>());
activeEntity->setRot(d.read<vec3>());
break;
case NetField::SCALE:
activeEntity->setScale(d.read<glm::vec3>());
activeEntity->setScale(d.read<vec3>());
break;
case NetField::VISUAL_OFF:
activeEntity->setVisualOffset(d.read<glm::vec3>());
activeEntity->setVisualOffset(d.read<vec3>());
break;
case NetField::DISPLAY: {
std::string mode, argA, argB;
string mode, argA, argB;
d.read(mode).read(argA).read(argB);
activeEntity->setAppearance(mode, argA, argB);
break;
@ -259,13 +255,13 @@ void LocalDimension::serverEntitiesInfo(Deserializer& e) {
}
case NetField::ANIM_RANGE: {
bool loops;
unsigned int x, y;
d.read(x).read(y).read(loops);
activeEntity->animation.setAnim(glm::ivec2 { x, y }, 10, loops);
uvec2 range;
d.read(range).read(loops);
activeEntity->animation.setAnim(range, 10, loops);
break;
}
case NetField::DIM:
activeEntity->setDim(world.getDimension(d.read<unsigned int>()));
activeEntity->setDim(world.getDimension(d.read<u16>()));
break;
case NetField::COLLISION_BOX: {
@ -291,9 +287,9 @@ void LocalDimension::serverEntitiesInfo(Deserializer& e) {
}
void LocalDimension::serverEntitiesRemoved(Deserializer& d) {
d.read<unsigned int>();
d.read<u16>();
while (!d.atEnd()) {
unsigned int id = d.read<unsigned int>();
i64 id = d.read<i64>();
if (!entityRefs.count(id)) continue;
auto refIter = entityRefs.at(id);
entities.erase(refIter);
@ -301,20 +297,20 @@ void LocalDimension::serverEntitiesRemoved(Deserializer& d) {
}
}
std::vector<Api::Usertype::Entity> LocalDimension::getEntitiesInRadius(glm::vec3 pos, float radius) {
std::vector<Api::Usertype::Entity> found {};
vec<Api::Usertype::Entity> LocalDimension::getEntitiesInRadius(vec3 pos, f32 radius) {
vec<Api::Usertype::Entity> found {};
for (auto& entity : entities) if (glm::distance(pos, entity.entity->getPos()) <= radius) found.push_back(entity);
return found;
}
Api::Usertype::Entity& LocalDimension::getEntityById(long long id) {
Api::Usertype::Entity& LocalDimension::getEntityById(i64 id) {
return *entityRefs.at(id);
}
void LocalDimension::renderChunks(Renderer& renderer) {
lastMeshesDrawn = 0;
for (auto& renderElement : renderElems) {
FrustumAABB bbox(renderElement->getPos() * glm::vec3(16), glm::vec3(16));
FrustumAABB bbox(renderElement->getPos() * vec3(16), vec3(16));
if (renderer.camera.inFrustum(bbox) != Frustum::OUTSIDE) {
renderElement->draw(renderer);
lastMeshesDrawn++;
@ -327,21 +323,21 @@ void LocalDimension::renderEntities(Renderer& renderer) {
for (auto& entity : playerEntities) entity.draw(renderer);
}
uint32_t LocalDimension::getMeshChunksDrawn() {
u32 LocalDimension::getMeshChunksDrawn() {
return lastMeshesDrawn;
}
uint32_t LocalDimension::getMeshChunksCommitted() {
u32 LocalDimension::getMeshChunksCommitted() {
return lastMeshesCommitted;
}
std::unordered_set<glm::ivec3, Vec::ivec3> LocalDimension::propogateAddNodes() {
std::unordered_set<ivec3, Vec::ivec3> LocalDimension::propogateAddNodes() {
auto updated = Dimension::propogateAddNodes();
for (auto& update : updated) attemptMeshChunk(getChunk(update));
return {};
}
std::unordered_set<glm::ivec3, Vec::ivec3> LocalDimension::propogateRemoveNodes() {
std::unordered_set<ivec3, Vec::ivec3> LocalDimension::propogateRemoveNodes() {
auto updated = Dimension::propogateRemoveNodes();
for (auto& update : updated) attemptMeshChunk(getChunk(update));
return {};
@ -366,7 +362,7 @@ void LocalDimension::finishMeshes() {
}
}
void LocalDimension::attemptMeshChunk(const std::shared_ptr<Chunk>& chunk, bool priority, bool updateAdjacents) {
void LocalDimension::attemptMeshChunk(const sptr<Chunk>& chunk, bool priority, bool updateAdjacents) {
bool renderable = true;
for (auto dir : Vec::TO_VEC) if (!getAdjacentExists(chunk->getPos() + dir, updateAdjacents)) renderable = false;
if (!renderable) return;
@ -378,7 +374,7 @@ void LocalDimension::attemptMeshChunk(const std::shared_ptr<Chunk>& chunk, bool
chunk->setDirty(false);
}
bool LocalDimension::getAdjacentExists(glm::vec3 pos, bool updateAdjacents) {
bool LocalDimension::getAdjacentExists(vec3 pos, bool updateAdjacents) {
auto chunk = getChunk(pos);
if (chunk == nullptr) return false;
if (updateAdjacents) attemptMeshChunk(chunk, false, false);

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 04/04/19.
//
#pragma once
#include <list>
@ -13,30 +9,30 @@
#include "client/entity/PlayerEntity.h"
class Renderer;
class MeshChunk;
class Deserializer;
class MeshGenStream;
class ChunkRenderElem;
/**
* A local representation of a dimension,
* contains all of the blocks and entities.
*/
class LocalDimension : public Dimension {
public:
const static int MB_STORE_H = 6;
const static int MB_STORE_V = 4;
const static u8 MB_STORE_H = 6;
const static u8 MB_STORE_V = 4;
LocalDimension(SubgamePtr game, LocalWorld& world, const std::string& identifier, unsigned int ind,
std::shared_ptr<MapGen> mapGen);
LocalDimension(SubgamePtr game, LocalWorld& world, const string& identifier, u16 ind, sptr<MapGen> mapGen);
void deactivate();
void update(double delta) override;
void update(f64 delta) override;
void setChunk(std::shared_ptr<Chunk> chunk) override;
void setChunk(sptr<Chunk> chunk) override;
bool setBlock(glm::ivec3 pos, unsigned int block) override;
bool setBlock(ivec3 pos, u16 block) override;
virtual void blockPlace(const Target& target, PlayerPtr player) override;
@ -48,11 +44,11 @@ public:
virtual void wieldItemUse(const Target& target, PlayerPtr player) override;
void setMeshChunk(std::shared_ptr<MeshChunk> chunk);
void setMeshChunk(sptr<MeshChunk> chunk);
void removeMeshChunk(const glm::ivec3& pos);
void removeMeshChunk(const ivec3& pos);
virtual long long nextEntityInd() override;
virtual i64 nextEntityInd() override;
void addLocalEntity(Api::Usertype::Entity entity);
@ -62,25 +58,25 @@ public:
void serverEntitiesRemoved(Deserializer& d);
std::vector<Api::Usertype::Entity> getEntitiesInRadius(glm::vec3 pos, float radius);
std::vector<Api::Usertype::Entity> getEntitiesInRadius(vec3 pos, f32 radius);
Api::Usertype::Entity& getEntityById(long long id);
Api::Usertype::Entity& getEntityById(i64 id);
void renderChunks(Renderer& renderer);
void renderEntities(Renderer& renderer);
uint32_t getMeshChunksDrawn();
uint32_t getMeshChunksCommitted();
u32 getMeshChunksDrawn();
u32 getMeshChunksCommitted();
int lastMeshesDrawn = 0;
int lastMeshesCommitted = 0;
std::vector<PlayerEntity> playerEntities;
u32 lastMeshesDrawn = 0;
u32 lastMeshesCommitted = 0;
vec<PlayerEntity> playerEntities;
protected:
std::unordered_set<glm::ivec3, Vec::ivec3> propogateAddNodes() override;
std::unordered_set<ivec3, Vec::ivec3> propogateAddNodes() override;
std::unordered_set<glm::ivec3, Vec::ivec3> propogateRemoveNodes() override;
std::unordered_set<ivec3, Vec::ivec3> propogateRemoveNodes() override;
private:
typedef std::list<Api::Usertype::Entity>::iterator ent_ref;
@ -88,18 +84,18 @@ private:
void finishMeshes();
void attemptMeshChunk(const std::shared_ptr<Chunk>& chunk, bool priority = false, bool updateAdjacents = true);
void attemptMeshChunk(const sptr<Chunk>& chunk, bool priority = false, bool updateAdjacents = true);
bool getAdjacentExists(glm::vec3 pos, bool updateAdjacents);
bool getAdjacentExists(vec3 pos, bool updateAdjacents);
std::shared_ptr<MeshGenStream> meshGenStream;
sptr<MeshGenStream> meshGenStream;
std::unordered_map<long long, ent_ref> entityRefs {};
std::unordered_map<i64, ent_ref> entityRefs {};
std::list<Api::Usertype::Entity> entities {};
std::unordered_map<glm::vec3, chunk_ref, Vec::vec3> renderRefs{};
std::list<std::shared_ptr<ChunkRenderElem>> renderElems{};
std::unordered_map<vec3, chunk_ref, Vec::vec3> renderRefs{};
std::list<sptr<ChunkRenderElem>> renderElems{};
long long entityInd = -1;
i64 entityInd = -1;
};

View File

@ -95,12 +95,12 @@ void ServerDimension::wieldItemUse(const Target& target, PlayerPtr player) {
}
void ServerDimension::setChunk(std::shared_ptr<Chunk> chunk) {
std::shared_ptr<Chunk> existing = getChunk(chunk->getPos());
if (existing) chunk = combineChunks(chunk, existing);
// std::shared_ptr<Chunk> existing = getChunk(chunk->getPos());
// if (existing) chunk = combineChunks(chunk, existing);
Dimension::setChunk(chunk);
}
long long ServerDimension::nextEntityInd() {
i64 ServerDimension::nextEntityInd() {
auto _ = getWriteLock();
return entityInd++;
};
@ -126,7 +126,7 @@ std::list<Api::Usertype::Entity>& ServerDimension::getLuaEntities() {
return luaEntities;
}
const std::list<unsigned int>& ServerDimension::getRemovedEntities() const {
const std::list<i64>& ServerDimension::getRemovedEntities() const {
return removedEntities;
}

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 01/10/19.
//
#pragma once
#include <list>
@ -11,13 +7,16 @@
#include "lua/usertype/Entity.h"
class ServerWorld;
class ServerPlayer;
class ServerSubgame;
/**
* A server representation of a dimension,
* contains all of the blocks and entities.
*/
class ServerDimension : public Dimension {
public:
public:
ServerDimension(SubgamePtr game, ServerWorld& world, const std::string& identifier, unsigned int ind,
std::shared_ptr<MapGen> mapGen);
@ -35,7 +34,7 @@ class ServerDimension : public Dimension {
virtual void wieldItemUse(const Target& target, PlayerPtr player) override;
virtual long long nextEntityInd() override;
virtual i64 nextEntityInd() override;
void addLuaEntity(Api::Usertype::Entity entity);
@ -43,18 +42,18 @@ class ServerDimension : public Dimension {
std::list<Api::Usertype::Entity>& getLuaEntities();
const std::list<unsigned int>& getRemovedEntities() const;
const std::list<i64>& getRemovedEntities() const;
void clearRemovedEntities();
private:
private:
typedef std::list<Api::Usertype::Entity>::iterator luaent_ref;
std::unordered_map<unsigned int, luaent_ref> luaEntityRefs{};
std::unordered_map<i64, luaent_ref> luaEntityRefs{};
std::list<Api::Usertype::Entity> luaEntities{};
std::list<unsigned int> removedEntities{};
std::list<i64> removedEntities{};
const glm::ivec2 discardRange = { 20, 20 };
long long entityInd = 1;
const ivec2 discardRange = { 20, 20 };
i64 entityInd = 1;
};

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 14/12/18.
//
#include <gzip/compress.hpp>
#include <gzip/decompress.hpp>
#include <gzip/utils.hpp>
@ -24,19 +20,19 @@ Chunk::Chunk(const Chunk& o) :
if (d != nullptr) *d = *o.d;
}
Chunk::Chunk(glm::ivec3 pos, bool partial) :
Chunk::Chunk(ivec3 pos, bool partial) :
pos(pos),
d(new ChunkData()),
compressionState(CompressionState::DECOMPRESSED),
generationState(partial ? GenerationState::PARTIAL : GenerationState::EMPTY) {}
Chunk::Chunk(const std::string& data) : c(data) {}
Chunk::Chunk(const string& data) : c(data) {}
Chunk::~Chunk() {
if (compressionState == CompressionState::DECOMPRESSED) delete d;
}
bool Chunk::setBlock(unsigned int ind, unsigned int blk) {
bool Chunk::setBlock(u16 ind, u16 blk) {
assertDecompressed();
if (ind > 4096) throw ChunkException(pos, "Index out of range.");
@ -49,18 +45,18 @@ bool Chunk::setBlock(unsigned int ind, unsigned int blk) {
return true;
}
const std::array<unsigned int, 4096>& Chunk::getBlocksArray() const {
const std::array<u16, 4096>& Chunk::getBlocksArray() const {
assertDecompressed();
return d->blocks;
}
const std::array<unsigned short, 4096>& Chunk::getBiomesArray() const {
const std::array<u16, 4096>& Chunk::getBiomesArray() const {
assertDecompressed();
return d->biomes;
}
void Chunk::combineWith(std::shared_ptr<Chunk> o) {
for (unsigned int i = 0; i < 4096; i++)
void Chunk::combineWith(sptr<Chunk> o) {
for (u16 i = 0; i < 4096; i++)
if (o->getBlock(i) > DefinitionAtlas::INVALID) setBlock(i, o->getBlock(i));
if (generationState == GenerationState::GENERATED || o->isGenerated()) {
@ -71,44 +67,61 @@ void Chunk::combineWith(std::shared_ptr<Chunk> o) {
else generationState = GenerationState::PARTIAL;
}
std::string Chunk::compress() {
string Chunk::compress() {
Serializer s;
std::vector<unsigned int> blocksRIE = {};
std::vector<unsigned short> biomesRIE = {};
std::vector<u16> blocksRIE = {};
std::vector<u16> biomesRIE = {};
RIE::encode<unsigned int, 4096>(d->blocks, blocksRIE);
RIE::encode<unsigned short, 4096>(d->biomes, biomesRIE);
RIE::encode<u16, 4096>(d->blocks, blocksRIE);
RIE::encode<u16, 4096>(d->biomes, biomesRIE);
std::string temp = Serializer().append(pos).appendVec(blocksRIE).appendVec(biomesRIE)
.appendArr(d->blockLight).appendArr(d->sunLight).data;
s.append<std::string>(gzip::compress(temp.data(), temp.size()));
// std::cout << "inr " << Util::vectorToString(blocksRIE) << std::endl;
// std::cout << "in " << Util::arrayToString(d->blocks) << std::endl;
string temp = Serializer()
.append(pos)
.append(blocksRIE)
.append(biomesRIE)
.append(d->blockLight)
.append(d->sunLight).data;
s.append<string>(gzip::compress(temp.data(), temp.size()));
return s.data;
}
void Chunk::decompress(const std::string& data) {
const auto& toDecompress = (data.length() ? data : c);
std::string gzipped = Deserializer(toDecompress).read<std::string>();
void Chunk::decompress(const string& data) {
const auto& toDecompress = data.length() ? data : c;
string gzipped = Deserializer(toDecompress).read<string>();
if (!gzip::is_compressed(gzipped.data(), gzipped.length()))
throw std::runtime_error("Chunk contains invalid gzipped data.");
throw ChunkException(pos, "Chunk contains invalid gzipped data.");
c = "";
d = new ChunkData {};
compressionState = CompressionState::DECOMPRESSED;
vec<u16> blocksRIE = {};
vec<u16> biomesRIE = {};
Deserializer(gzip::decompress(gzipped.data(), gzipped.length()))
.read<glm::ivec3>(pos)
.readArr<unsigned int, 4096>(d->blocks)
.readArr<unsigned short, 4096>(d->biomes)
.readArr<BlockLight, 4096>(d->blockLight)
.readArr<SunLight, 2048>(d->sunLight);
.read<ivec3>(pos)
.read<vec<u16>>(blocksRIE)
.read<vec<u16>>(biomesRIE)
.read<array<BlockLight, 4096>>(d->blockLight)
.read<array<SunLight, 2048>>(d->sunLight);
RIE::expand<u16, 4096>(blocksRIE, d->blocks);
RIE::expand<u16, 4096>(biomesRIE, d->biomes);
// std::cout << "outr" << Util::vectorToString(blocksRIE) << std::endl;
// std::cout << "out " << Util::arrayToString(d->blocks) << std::endl;
countRenderableBlocks();
}
void Chunk::countRenderableBlocks() {
renderableBlocks = 0;
for (int i = 0; i < d->blocks.size(); i++)
for (u16 i = 0; i < d->blocks.size(); i++)
if (d->blocks[i] != DefinitionAtlas::AIR) renderableBlocks++;
}
}

View File

@ -6,17 +6,18 @@
#include <memory>
#include <glm/vec3.hpp>
#include "util/Types.h"
#include "util/Space.h"
class Deserializer;
class ChunkException : public std::exception {
private:
glm::ivec3 pos;
std::string errorMessage;
ivec3 pos;
string errorMessage;
public:
ChunkException(glm::ivec3 pos, std::string errorMessage):
ChunkException(ivec3 pos, string errorMessage):
pos(pos), errorMessage(errorMessage) {}
const char* what() const throw() {
@ -48,12 +49,12 @@ public:
struct BlockLight {
/** RGB values, and an extra bit, to make the struct an even 2 bytes. */
unsigned char r: 5, g: 5, b: 5, : 1;
u8 r: 5, g: 5, b: 5, : 1;
};
/** A union for accessing a short as a BlockLight struct, or vice versa. */
typedef union {
short sh;
u16 sh;
BlockLight b;
} blocklight_union;
@ -65,12 +66,12 @@ public:
struct SunLight {
/** The two sunlight values stored in a struct. */
unsigned char a: 4, b: 4;
u8 a: 4, b: 4;
};
/** A union for accessing a char as a Sunlight struct, or vice versa. */
typedef union {
char ch;
u8 ch;
SunLight s;
} sunlight_union;
@ -78,19 +79,19 @@ public:
Chunk(const Chunk& o);
/** Basic chunk constructor, initializes an empty, ungenerated chunk. */
Chunk(glm::ivec3 pos = glm::ivec3(0), bool partial = false);
Chunk(ivec3 pos = { 0, 0, 0 }, bool partial = false);
/** Creates a chunk with the compressed data specified. */
Chunk(const std::string& data);
Chunk(const string& data);
/** Destroys chunk data pointer. */
~Chunk();
/** Returns the position of the chunk. */
inline glm::ivec3 getPos() const;
inline ivec3 getPos() const;
/** Sets the position of the chunk. */
inline void setPos(glm::ivec3 newPos);
inline void setPos(ivec3 newPos);
/**
* Returns the chunk's dirty state, which is whether it needs to be remeshed or not.
@ -118,62 +119,62 @@ public:
inline bool isGenerated() const;
/** Returns the block ID at the index specified. */
inline unsigned int getBlock(unsigned int ind) const;
inline u16 getBlock(u16 ind) const;
/**
* Sets the block ID at the index specified.
* @returns a boolean indicating if the newly placed block is different than the old one.
*/
bool setBlock(unsigned int ind, unsigned int blk);
bool setBlock(u16 ind, u16 blk);
/** Returns the block ID at the position specified, wrapping to local coordinates. */
inline unsigned int getBlock(const glm::ivec3& pos) const;
inline u16 getBlock(const ivec3& pos) const;
/**
* Sets the block ID at the position specified, wrapping to local coordinates.
* @returns a boolean indicating if the newly placed block is different than the old one.
*/
inline bool setBlock(const glm::ivec3& pos, unsigned int blk);
inline bool setBlock(const ivec3& pos, u16 blk);
/** Gets the biome ID at the index specified. */
inline unsigned short getBiome(unsigned int ind) const;
inline u16 getBiome(u16 ind) const;
/**
* Sets the biome ID at the index specified.
* @returns a boolean indicating if the newly placed biome is different than the old one.
*/
inline bool setBiome(unsigned int ind, unsigned short bio);
inline bool setBiome(u16 ind, u16 bio);
/** Returns the biome ID at the position specified, wrapping to local coordinates. */
inline unsigned short getBiome(const glm::ivec3& pos) const;
inline u16 getBiome(const ivec3& pos) const;
/**
* Sets the biome ID at the position specified, wrapping to local coordinates.
* @returns a boolean indicating if the newly placed biome is different than the old one.
*/
inline bool setBiome(const glm::ivec3& pos, unsigned short bio);
inline bool setBiome(const ivec3& pos, u16 bio);
/** Returns a constant reference to the chunk's raw blocks array. */
const std::array<unsigned int, 4096>& getBlocksArray() const;
const array<u16, 4096>& getBlocksArray() const;
/** Returns a constant reference to the chunk's raw biomes array. */
const std::array<unsigned short, 4096>& getBiomesArray() const;
const array<u16, 4096>& getBiomesArray() const;
/** Returns the light value at the specified index as a vector in R, G, B, Sunlight format. */
inline glm::ivec4 getLight(unsigned int ind);
inline u8vec4 getLight(u16 ind);
/** Sets the light value at the specified index to the vector specified in R, G, B, Sunlight format. */
inline void setLight(unsigned int ind, glm::ivec4 light);
inline void setLight(u16 ind, u8vec4 light);
/** Returns the specified channel of the light value at the specified index. */
inline unsigned char getLight(unsigned int ind, unsigned char channel);
inline u8 getLight(u16 ind, u8 channel);
/** Sets the specified channel of the light value at the specified index. */
inline void setLight(unsigned int ind, unsigned char channel, unsigned char light);
inline void setLight(u16 ind, u8 channel, u8 light);
/**
* Combines a chunk's blocks with another's, which may be a partial.
@ -181,38 +182,38 @@ public:
* Will update the chunk's state to generated one of the two was already generated.
*/
void combineWith(std::shared_ptr<Chunk> o);
void combineWith(sptr<Chunk> o);
/** Compresses the chunk, returning a string representing it. */
std::string compress();
string compress();
/** Decompresses a compressed chunk string, or itself. */
void decompress(const std::string& data = "");
void decompress(const string& data = "");
private:
/** Internal data of a decompressed chunk. */
struct ChunkData {
/** Internal block data. */
std::array<unsigned int, 4096> blocks {};
array<u16, 4096> blocks {};
/** Internal biome data. */
std::array<unsigned short, 4096> biomes {};
array<u16, 4096> biomes {};
/** Internal sunlight data. */
std::array<SunLight, 2048> sunLight {};
array<SunLight, 2048> sunLight {};
/** Internal blocklight data. */
std::array<BlockLight, 4096> blockLight {};
array<BlockLight, 4096> blockLight {};
};
/** Throws an exception if the chunk is compressed. */
inline void assertDecompressed() const;
/** Gets the sunlight intensity at the specified index. */
inline unsigned char getSunlight(unsigned int ind);
inline u8 getSunlight(u16 ind);
/** Sets the sunlight intensity at the specified index. */
inline void setSunlight(unsigned int ind, unsigned char val);
inline void setSunlight(u16 ind, u8 val);
/**
* Updates the internal Renderable Blocks count, which determines if a chunk should render.
@ -228,19 +229,19 @@ private:
GenerationState generationState = GenerationState::EMPTY;
/** The position of the chunk in its dimension. */
glm::ivec3 pos {};
ivec3 pos {};
/** Whether or not the chunk needs to be remeshed. */
bool dirty = true;
/** The number of non-transparent blocks in the chunk. */
unsigned short renderableBlocks = 0;
u16 renderableBlocks = 0;
/** Internal decompressed chunk data. */
ChunkData* d = nullptr;
/** Internal compressed chunk data. */
std::string c = "";
string c = "";
};
#include "Chunk.inl"

View File

@ -1,11 +1,11 @@
#include "Chunk.h"
//#include "Chunk.h"
glm::ivec3 Chunk::getPos() const {
ivec3 Chunk::getPos() const {
return pos;
}
void Chunk::setPos(glm::ivec3 newPos) {
void Chunk::setPos(ivec3 newPos) {
pos = newPos;
}
@ -29,31 +29,31 @@ bool Chunk::isGenerated() const {
return generationState == GenerationState::GENERATED;
}
inline unsigned int Chunk::getBlock(unsigned int ind) const {
inline u16 Chunk::getBlock(u16 ind) const {
assertDecompressed();
if (ind >= 4096) throw ChunkException(pos, "Index out of range.");
return d->blocks[ind];
}
inline unsigned int Chunk::getBlock(const glm::ivec3& reqPos) const {
inline u16 Chunk::getBlock(const ivec3& reqPos) const {
return getBlock(Space::Block::index(reqPos));
}
inline bool Chunk::setBlock(const glm::ivec3& newPos, unsigned int blk) {
inline bool Chunk::setBlock(const ivec3& newPos, u16 blk) {
return setBlock(Space::Block::index(newPos), blk);
}
inline unsigned short Chunk::getBiome(unsigned int ind) const {
inline u16 Chunk::getBiome(u16 ind) const {
assertDecompressed();
if (ind >= 4096) throw ChunkException(pos, "Index out of range.");
return d->biomes[ind];
}
inline unsigned short Chunk::getBiome(const glm::ivec3& reqPos) const {
inline u16 Chunk::getBiome(const ivec3& reqPos) const {
return getBiome(Space::Block::index(reqPos));
}
inline bool Chunk::setBiome(unsigned int ind, unsigned short bio) {
inline bool Chunk::setBiome(u16 ind, u16 bio) {
assertDecompressed();
if (ind > 4096) throw ChunkException(pos, "Index out of range.");
@ -62,28 +62,28 @@ inline bool Chunk::setBiome(unsigned int ind, unsigned short bio) {
return true;
}
inline bool Chunk::setBiome(const glm::ivec3& newPos, unsigned short bio) {
inline bool Chunk::setBiome(const ivec3& newPos, u16 bio) {
return setBiome(Space::Block::index(newPos), bio);
}
inline glm::ivec4 Chunk::getLight(unsigned int ind) {
inline u8vec4 Chunk::getLight(u16 ind) {
assertDecompressed();
return { d->blockLight[ind].r, d->blockLight[ind].g, d->blockLight[ind].b, getSunlight(ind) };
}
inline void Chunk::setLight(unsigned int ind, glm::ivec4 light) {
inline void Chunk::setLight(u16 ind, u8vec4 light) {
assertDecompressed();
if (ind > 4096) throw ChunkException(pos, "Index out of range.");
if (light.x > 31 || light.y > 31 || light.z > 31 || light.w > 15)
throw ChunkException(pos, "Light value out of range.");
d->blockLight[ind].r = static_cast<unsigned char>(light.x);
d->blockLight[ind].g = static_cast<unsigned char>(light.y);
d->blockLight[ind].b = static_cast<unsigned char>(light.z);
setSunlight(ind, static_cast<unsigned char>(light.w));
d->blockLight[ind].r = light.x;
d->blockLight[ind].g = light.y;
d->blockLight[ind].b = light.z;
setSunlight(ind, light.w);
}
inline unsigned char Chunk::getLight(unsigned int ind, unsigned char channel) {
inline u8 Chunk::getLight(u16 ind, u8 channel) {
assertDecompressed();
if (ind > 4096) throw ChunkException(pos, "Index out of range.");
@ -93,7 +93,7 @@ inline unsigned char Chunk::getLight(unsigned int ind, unsigned char channel) {
getSunlight(ind);
}
inline void Chunk::setLight(unsigned int ind, unsigned char channel, unsigned char light) {
inline void Chunk::setLight(u16 ind, u8 channel, u8 light) {
assertDecompressed();
if (ind > 4096) throw ChunkException(pos, "Index out of range.");
if ((channel < 4 && light > 31) || (channel == 4 && light > 15))
@ -110,12 +110,12 @@ void Chunk::assertDecompressed() const {
throw ChunkException(pos, "Chunk is compressed.");
}
inline unsigned char Chunk::getSunlight(unsigned int ind) {
inline u8 Chunk::getSunlight(u16 ind) {
if (ind % 2 == 0) return d->sunLight[ind / 2].a;
else return d->sunLight[ind / 2].b;
}
inline void Chunk::setSunlight(unsigned int ind, unsigned char val) {
inline void Chunk::setSunlight(u16 ind, u8 val) {
if (ind % 2 == 0) d->sunLight[ind / 2].a = val;
else d->sunLight[ind / 2].b = val;
}

View File

@ -4,9 +4,9 @@
#include "AnimationState.h"
#include "AnimationSegment.h"
#include "client/graph/Model.h"
#include "client/graph/ModelAnimation.h"
#include "AnimationSegment.h"
AnimationState::AnimationState(Model& source) {
const ModelAnimation& animation = source.getAnimation();
@ -15,15 +15,15 @@ AnimationState::AnimationState(Model& source) {
range = { 0, duration };
}
void AnimationState::setAnimations(const std::vector<AnimationSegment>& anims) {
void AnimationState::setAnimations(const vec<AnimationSegment>& anims) {
for (auto& anim : anims) defineAnimation(anim.name, anim.range);
}
void AnimationState::defineAnimation(const std::string& name, glm::ivec2 range) {
void AnimationState::defineAnimation(const string& name, uvec2 range) {
animations.emplace(name, AnimationSegment{ name, range });
}
void AnimationState::update(double delta) {
void AnimationState::update(f64 delta) {
if (playing) {
float frame = currentFrame + (delta * ticksPerSecond);
if (loop) frame = fmod(frame - range.x, range.y - range.x) + range.x;
@ -39,12 +39,12 @@ bool AnimationState::isLooping() {
return loop;
}
void AnimationState::setAnim(const std::string& name, double interp, bool loop) {
void AnimationState::setAnim(const string& name, f64 interp, bool loop) {
auto& anim = animations[name];
setAnim(anim.range, interp, loop);
}
void AnimationState::setAnim(glm::ivec2 range, double interp, bool loop) {
void AnimationState::setAnim(uvec2 range, f64 interp, bool loop) {
this->range = range;
this->loop = loop;
currentFrame = range.x;
@ -58,7 +58,7 @@ void AnimationState::setPlaying(bool playing) {
this->playing = playing;
}
void AnimationState::setFrame(double frame) {
void AnimationState::setFrame(f64 frame) {
currentFrame = frame;
}
@ -66,6 +66,6 @@ double AnimationState::getFrame() {
return currentFrame;
}
glm::ivec2 AnimationState::getBounds() {
uvec2 AnimationState::getBounds() {
return range;
}

View File

@ -5,10 +5,8 @@
#pragma once
#include <map>
#include <vector>
#include <string>
#include <glm/vec2.hpp>
#include "util/Types.h"
#include "AnimationSegment.h"
class Model;
@ -21,35 +19,35 @@ class AnimationState {
void update(double delta);
void setAnimations(const std::vector<AnimationSegment>& anims);
void setAnimations(const vec<AnimationSegment>& anims);
void defineAnimation(const std::string& name, glm::ivec2 range);
void defineAnimation(const string& name, uvec2 range);
bool isLooping();
void setAnim(const std::string& name, double interp, bool loop);
void setAnim(const string& name, f64 interp, bool loop);
void setAnim(glm::ivec2 range, double interp, bool loop);
void setAnim(uvec2 range, f64 interp, bool loop);
bool isPlaying();
void setPlaying(bool playing);
double getFrame();
f64 getFrame();
void setFrame(double frame);
void setFrame(f64 frame);
glm::ivec2 getBounds();
uvec2 getBounds();
private:
std::map<std::string, AnimationSegment> animations;
private:
std::map<string, AnimationSegment> animations;
glm::ivec2 range;
uvec2 range;
bool loop = false;
bool playing = false;
double currentFrame = 0;
double ticksPerSecond = 0;
unsigned int duration = 0;
f64 currentFrame = 0;
f64 ticksPerSecond = 0;
u32 duration = 0;
};

View File

@ -241,17 +241,17 @@ protected:
DimensionPtr dim = nullptr;
/** The entity's unique id, positive if it is a server-side entity, negative if it is client-side. */
long long id = 0;
i64 id = 0;
glm::vec3 pos {};
glm::vec3 vel {};
glm::vec3 rot {};
glm::vec3 visualOff {};
glm::vec3 scale { 1, 1, 1 };
vec3 pos {};
vec3 vel {};
vec3 rot {};
vec3 visualOff {};
vec3 scale { 1, 1, 1 };
std::optional<SelectionBox> selectionBox {};
std::optional<SelectionBox> collisionBox {};
float gravity = 0;
f32 gravity = 0;
bool collides = false;
};

View File

@ -81,7 +81,7 @@ std::string ServerLuaEntity::serialize() {
}
Serializer s;
s.append<long long>(id);
s.append<i64>(id);
while (!dirtyFields.empty()) {
const auto field = *dirtyFields.begin();
@ -95,43 +95,53 @@ std::string ServerLuaEntity::serialize() {
case NetField::ALL:
case NetField::POS: s.appendEnum(NetField::POS).append(pos);
case NetField::POS:
s.append(NetField::POS).append(pos);
if (field != NetField::ALL) break;
case NetField::VEL: s.appendEnum(NetField::VEL).append(vel);
case NetField::VEL:
s.append(NetField::VEL).append(vel);
if (field != NetField::ALL) break;
case NetField::ROT: s.appendEnum(NetField::ROT).append(rot);
case NetField::ROT:
s.append(NetField::ROT).append(rot);
if (field != NetField::ALL) break;
case NetField::SCALE: s.appendEnum(NetField::SCALE).append(scale);
case NetField::SCALE:
s.append(NetField::SCALE).append(scale);
if (field != NetField::ALL) break;
case NetField::VISUAL_OFF: s.appendEnum(NetField::VISUAL_OFF).append(visualOff);
case NetField::VISUAL_OFF:
s.append(NetField::VISUAL_OFF).append(visualOff);
if (field != NetField::ALL) break;
case NetField::DISPLAY: s.appendEnum(NetField::DISPLAY).append(dMode).append(dArgA).append(dArgB);
case NetField::DISPLAY:
s.append(NetField::DISPLAY).append(dMode).append(dArgA).append(dArgB);
if (field != NetField::ALL) break;
case NetField::ANIM_STATE: s.appendEnum(NetField::ANIM_STATE).append<bool>(animation.isPlaying());
case NetField::ANIM_STATE:
s.append(NetField::ANIM_STATE).append<bool>(animation.isPlaying());
if (field != NetField::ALL) break;
case NetField::ANIM_RANGE:
s.appendEnum(NetField::ANIM_RANGE).append<unsigned int>(animation.getBounds().x)
.append<unsigned int>(animation.getBounds().y).append<bool>(animation.isLooping());
s.append(NetField::ANIM_RANGE).append(animation.getBounds()).append<bool>(animation.isLooping());
if (field != NetField::ALL) break;
case NetField::DIM: s.appendEnum(NetField::DIM).append(dim->getInd());
case NetField::DIM:
s.append(NetField::DIM).append(dim->getInd());
if (field != NetField::ALL) break;
case NetField::COLLISION_BOX: s.appendEnum(NetField::COLLISION_BOX).append<bool>(collisionBox.has_value());
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: s.appendEnum(NetField::COLLIDES).append(collides);
case NetField::COLLIDES:
s.append(NetField::COLLIDES).append(collides);
if (field != NetField::ALL) break;
case NetField::GRAVITY: s.appendEnum(NetField::GRAVITY).append(gravity);
case NetField::GRAVITY:
s.append(NetField::GRAVITY).append(gravity);
if (field != NetField::ALL) break;
}
}

View File

@ -1,7 +1,3 @@
//
// Created by aurailus on 28/01/19.
//
#include <random>
#include "MapGen.h"
@ -90,18 +86,24 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
for (pos.z = 0; pos.z < job.size; pos.z++) {
std::unique_ptr<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));
//
// std::cout << "were out da function " << pos.x << ", " << pos.y << ", " << pos.z << std::endl;
// std::cout << &job << " " << &pos << " " << &biomeMap << " " << &depth << std::endl;
//
// generateChunkBlocks(job, pos, biomeMap, *depth);
// generateChunkDecorAndLight(job, pos, biomeMap, *depth);
std::unique_ptr<ChunkData> density = populateChunkDensity(job, pos);
std::unique_ptr<ChunkData> depth = populateChunkDepth(density, std::move(densityAbove));
generateChunkBlocks(job, pos, biomeMap, *depth);
generateChunkDecorAndLight(job, pos, biomeMap, *depth);
densityAbove = std::move(density);
glm::ivec3 chunkPos = job.pos + pos;
job.chunks->emplace(chunkPos, std::make_shared<Chunk>(chunkPos));
// densityAbove = std::move(density);
}
}
}
@ -111,7 +113,7 @@ std::unique_ptr<MapGen::CreatedSet> MapGen::generateArea(unsigned int dim, glm::
auto created = std::make_unique<CreatedSet>();
for (const auto& chunk : *job.chunks) {
created->emplace(chunk.first);
world.getDimension(dim)->setChunk(chunk.second);
// world.getDimension(dim)->setChunk(chunk.second);
}
return std::move(created);
@ -186,6 +188,7 @@ std::unique_ptr<MapGen::ChunkData> MapGen::populateChunkDepth(std::unique_ptr<Ch
void MapGen::generateChunkBlocks(Job& job, glm::ivec3 localPos,
std::vector<unsigned int> biomeMap, ChunkData& depthMap) {
std::cout << "were in da function " << std::endl;
glm::ivec3 chunkPos = job.pos + localPos;
@ -194,25 +197,20 @@ void MapGen::generateChunkBlocks(Job& job, glm::ivec3 localPos,
auto& chunk = *(*job.chunks->emplace(chunkPos, std::make_shared<Chunk>(chunkPos)).first).second;
unsigned int cBlockID = 0;
unsigned int cBiomeID = 0;
unsigned int partialBlock = DefinitionAtlas::INVALID;
int partialInd = -1;
unsigned int partialNextAt = 0;
for (unsigned short i = 0; i < 4096; i++) {
glm::ivec3 indPos = Space::Block::fromIndex(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)];
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];
}
//
// 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 =
@ -222,18 +220,9 @@ void MapGen::generateChunkBlocks(Job& job, glm::ivec3 localPos,
: depth <= 4 ? biome.soilBlock
: biome.rockBlock;
if (biomeID != cBiomeID) {
//TODO: Fix MapGen
// chunk.d->biomes.emplace_back(i);
// chunk.d->biomes.emplace_back(biomeID);
cBiomeID = biomeID;
}
if (chunk.d == nullptr) std::cout << "THE DATA ISNT LOADED." << std::endl;
chunk.d->blocks[i] = blockID;
if (blockID != cBlockID) {
// chunk.d->blocks.emplace_back(i);
// chunk.d->blocks.emplace_back(blockID);
cBlockID = blockID;
}
}
chunk.countRenderableBlocks();

View File

@ -28,14 +28,15 @@ LocalPlayer::LocalPlayer(SubgamePtr game, LocalWorld& world, DimensionPtr dim, R
renderer.window.addResizeCallback("player", [&](glm::ivec2 win) { gameGui.winResized(win); });
}
void LocalPlayer::update(Input& input, double delta, glm::vec2 mouseDelta) {
void LocalPlayer::update(Input& input, f64 delta, vec2 mouseDelta) {
gameGui.update(delta);
handItemModel.setVisible(gameGui.isVisible());
updatePhysics(input, delta, mouseDelta);
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);
@ -47,31 +48,31 @@ void LocalPlayer::update(Input& input, double delta, glm::vec2 mouseDelta) {
if (!gameGui.isInMenu()) updateInteract(input, delta);
}
void LocalPlayer::setPos(glm::vec3 pos, bool assert) {
void LocalPlayer::setPos(vec3 pos, bool assert) {
Player::setPos(pos, assert);
renderer.camera.setPos(pos + getLookOffset());
}
void LocalPlayer::setLookOffset(glm::vec3 eyeOffset, bool assert) {
void LocalPlayer::setLookOffset(vec3 eyeOffset, bool assert) {
Player::setLookOffset(eyeOffset, assert);
renderer.camera.setPos(pos + getLookOffset());
}
void LocalPlayer::setHandList(const std::string& list, bool assert) {
void LocalPlayer::setHandList(const string& list, bool assert) {
Player::setHandList(list, assert);
world.getRefs().l()->setHandList(list);
updateWieldAndHandItems();
}
void LocalPlayer::setWieldList(const std::string& list, bool assert) {
void LocalPlayer::setWieldList(const string& list, bool assert) {
Player::setWieldList(list, assert);
world.getRefs().l()->setWieldList(list);
setWieldIndex(wieldIndex);
updateWieldAndHandItems();
}
void LocalPlayer::setWieldIndex(unsigned short index, bool assert) {
void LocalPlayer::setWieldIndex(u16 index, bool assert) {
auto wieldList = world.getRefs().l()->getWieldList();
wieldIndex = index % std::max((wieldList ? wieldList->getLength() : 1), 1);
Player::setWieldIndex(wieldIndex, assert);
@ -95,7 +96,7 @@ bool LocalPlayer::isInMenu() {
return gameGui.isInMenu();
}
void LocalPlayer::showMenu(std::shared_ptr<LuaGuiElement> root) {
void LocalPlayer::showMenu(sptr<LuaGuiElement> root) {
gameGui.showMenu(root);
renderer.window.input.lockMouse(false);
}
@ -105,11 +106,11 @@ void LocalPlayer::closeMenu() {
renderer.window.input.lockMouse(true);
}
std::shared_ptr<LuaGuiElement> LocalPlayer::getHud() {
sptr<LuaGuiElement> LocalPlayer::getHud() {
return gameGui.getHud();
}
void LocalPlayer::setHud(std::shared_ptr<LuaGuiElement> hud) {
void LocalPlayer::setHud(sptr<LuaGuiElement> hud) {
gameGui.setHud(hud);
}
@ -137,35 +138,35 @@ void LocalPlayer::assertField(Packet packet) {
void LocalPlayer::handleAssertion(Deserializer& d) {
while (!d.atEnd()) {
const auto field = d.readEnum<NetField>();
const auto field = d.read<NetField>();
switch (field) {
default:
std::cout << Log::err << "Player received unhandled NetField, Type "
<< static_cast<int>(field) << "." << Log::endl;
<< static_cast<u32>(field) << "." << Log::endl;
break;
case NetField::ID:
setId(d.read<long long>());
setId(d.read<u32>());
break;
case NetField::POS:
setPos(d.read<glm::vec3>());
setPos(d.read<vec3>());
break;
case NetField::VEL:
setVel(d.read<glm::vec3>());
setVel(d.read<vec3>());
break;
case NetField::DIM:
setDim(world.getDimension(d.read<unsigned int>()));
setDim(world.getDimension(d.read<u16>()));
break;
case NetField::LOOK_PITCH:
setPitch(d.read<float>());
setPitch(d.read<f32>());
break;
case NetField::LOOK_YAW:
setYaw(d.read<float>());
setYaw(d.read<f32>());
break;
case NetField::FLYING:
@ -173,15 +174,15 @@ void LocalPlayer::handleAssertion(Deserializer& d) {
break;
case NetField::HAND_INV:
setHandList(d.read<std::string>());
setHandList(d.read<string>());
break;
case NetField::WIELD_INV:
setWieldList(d.read<std::string>());
setWieldList(d.read<string>());
break;
case NetField::WIELD_INDEX:
setWieldIndex(d.read<unsigned short>());
setWieldIndex(d.read<u16>());
break;
}
}
@ -199,7 +200,7 @@ bool LocalPlayer::getKey(Input& input, LocalPlayer::PlayerControl control) {
GLFW_KEY_LEFT_CONTROL);
}
void LocalPlayer::updatePhysics(Input& input, double delta, glm::vec2 mouseDelta) {
void LocalPlayer::updatePhysics(Input& input, f64 delta, vec2 mouseDelta) {
static constexpr float JUMP_VEL = 10.0f;
static constexpr float MOVE_VEL = 5.5f;
static constexpr float GRAVITY_ACCELERATION = 40.0f;
@ -278,19 +279,19 @@ void LocalPlayer::updateCamera() {
auto type = game->getDefs().fromId(wieldItem).type;
glm::vec3 eyesPos = pos + getLookOffset();
vec3 eyesPos = pos + getLookOffset();
renderer.camera.setPos(eyesPos);
float pitch = std::min(std::max(this->pitch, -89.9f), 89.9f);
glm::vec3 front = glm::normalize(glm::vec3{
vec3 front = glm::normalize(vec3{
cos(glm::radians(yaw)) * cos(glm::radians(pitch)),
sin(glm::radians(pitch)),
sin(glm::radians(yaw)) * cos(glm::radians(pitch)) });
glm::vec3 right = glm::normalize(glm::cross(front, { 0, 1, 0 }));
glm::vec3 up = glm::normalize(glm::cross(right, front));
glm::vec3 handPos =
vec3 right = glm::normalize(glm::cross(front, { 0, 1, 0 }));
vec3 up = glm::normalize(glm::cross(right, front));
vec3 handPos =
eyesPos + front * 0.25f + right * 0.25f + up * (type == ItemDef::Type::CRAFTITEM ? -0.15f : -0.2f);
handModel.setRotateY(-yaw);
@ -314,13 +315,13 @@ void LocalPlayer::updateCamera() {
void LocalPlayer::updateWireframe() {
if (gameGui.isVisible() && target.type != Target::Type::NOTHING) {
std::vector<SelectionBox> boxes {};
glm::vec3 thicknessOffset {};
glm::vec3 renderPos {};
vec3 thicknessOffset {};
vec3 renderPos {};
if (target.type == Target::Type::BLOCK) {
boxes = game->getDefs().blockFromId(dim->getBlock(target.data.block.pos)).sBoxes;
renderPos = target.data.block.pos;
thicknessOffset = glm::vec3(0.5);
thicknessOffset = vec3(0.5);
}
else {
const auto& entity = **dim.l()->getEntityById(target.data.entity.id).entity;
@ -359,10 +360,10 @@ void LocalPlayer::findTarget(Input& input) {
float maxDistance = LOOK_DISTANCE;
for (Ray ray(*this); ray.getLength() < maxDistance; ray.step(LOOK_PRECISION)) {
glm::vec3 rayEnd = ray.getEnd();
glm::vec3 roundedPos = glm::floor(rayEnd);
vec3 rayEnd = ray.getEnd();
vec3 roundedPos = glm::floor(rayEnd);
glm::ivec3 currChunkPos = Space::Chunk::world::fromBlock(roundedPos);
ivec3 currChunkPos = Space::Chunk::world::fromBlock(roundedPos);
if (currChunkPos != chunkPos || chunk == nullptr) {
chunkPos = currChunkPos;
chunk = dim->getChunk(chunkPos);
@ -402,7 +403,7 @@ void LocalPlayer::findTarget(Input& input) {
target = newTarget;
}
void LocalPlayer::updateInteract(Input& input, double delta) {
void LocalPlayer::updateInteract(Input& input, f64 delta) {
if (breakTime > 0) breakTime += delta;
if (breakTime > breakInterval) breakTime = 0;

View File

@ -44,19 +44,19 @@ public:
* @param mouseDelta - The mouse offset from the center of the screen.
*/
void update(Input& input, double delta, glm::vec2 mouseDelta);
void update(Input& input, f64 delta, vec2 mouseDelta);
/** The following setters call Player setters, but updates some rendering-related information. */
virtual void setPos(glm::vec3 pos, bool assert = false) override;
virtual void setPos(vec3 pos, bool assert = false) override;
virtual void setLookOffset(glm::vec3 eyeOffset, bool assert = false) override;
virtual void setLookOffset(vec3 eyeOffset, bool assert = false) override;
virtual void setHandList(const std::string& list, bool assert = false) override;
virtual void setHandList(const string& list, bool assert = false) override;
virtual void setWieldList(const std::string& list, bool assert = false) override;
virtual void setWieldList(const string& list, bool assert = false) override;
virtual void setWieldIndex(unsigned short index, bool assert = false) override;
virtual void setWieldIndex(u16 index, bool assert = false) override;
virtual void setDim(DimensionPtr dim) override;
@ -86,7 +86,7 @@ public:
* @param root - The root GUI element to display.
*/
void showMenu(std::shared_ptr<LuaGuiElement> root);
void showMenu(sptr<LuaGuiElement> root);
/**
* Closes the currently open menu.
@ -99,7 +99,7 @@ public:
* @returns the root GUI element of the hud.
*/
std::shared_ptr<LuaGuiElement> getHud();
sptr<LuaGuiElement> getHud();
/**
* Sets the HUD to the specified GUI tree. The hud does not constitute
@ -108,7 +108,7 @@ public:
* @param hud - The root GUI element to display.
*/
void setHud(std::shared_ptr<LuaGuiElement> hud);
void setHud(sptr<LuaGuiElement> hud);
/**
* Sets the visibility state of the HUD.
@ -180,7 +180,7 @@ private:
* @param mouseDelta - The offset of the mouse from the center of the screen.
*/
void updatePhysics(Input& input, double delta, glm::vec2 mouseDelta);
void updatePhysics(Input& input, f64 delta, vec2 mouseDelta);
/**
* Moves the camera to the player's position, and updates the wield model.
@ -216,22 +216,26 @@ private:
* @param delta - The delta time elapsed in the last frame.
*/
void updateInteract(Input& input, double delta);
void updateInteract(Input& input, f64 delta);
GameGui gameGui;
Renderer& renderer;
/** The player's current target. */
Target target;
/** The time remaining until the next hit. */
double breakTime = 0;
f64 breakTime = 0;
/** The interval at which the currently wielded tool can hit. */
double breakInterval = 0;
f64 breakInterval = 0;
/** The targeted wireframe entity. */
WireframeEntity wireframe;
/** A wrapper for the wield-item, translated to the bottom right of the player's viewport. */
DrawableEntity handModel;
/** The actual wield-item model, set to the currently held item. */
DrawableEntity handItemModel;
};

View File

@ -12,17 +12,17 @@
void Player::setDim(DimensionPtr dim, bool assert) {
Entity::setDim(dim);
if (assert) assertField(Serializer().appendEnum(NetField::DIM).append(dim->getInd()).packet());
if (assert) assertField(Serializer().append(NetField::DIM).append(dim->getInd()).packet());
}
void Player::setPos(glm::vec3 pos, bool assert) {
Entity::setPos(pos);
if (assert) assertField(Serializer().appendEnum(NetField::POS).append(pos).packet());
if (assert) assertField(Serializer().append(NetField::POS).append(pos).packet());
}
void Player::setVel(glm::vec3 vel, bool assert) {
Entity::setVel(vel);
if (assert) assertField(Serializer().appendEnum(NetField::VEL).append(vel).packet());
if (assert) assertField(Serializer().append(NetField::VEL).append(vel).packet());
}
float Player::getYaw() {
@ -31,7 +31,7 @@ float Player::getYaw() {
void Player::setYaw(float yaw, bool assert) {
this->yaw = yaw;
if (assert) assertField(Serializer().appendEnum(NetField::LOOK_YAW).append(yaw).packet());
if (assert) assertField(Serializer().append(NetField::LOOK_YAW).append(yaw).packet());
}
float Player::getPitch() {
@ -40,7 +40,7 @@ float Player::getPitch() {
void Player::setPitch(float pitch, bool assert) {
this->pitch = pitch;
if (assert) assertField(Serializer().appendEnum(NetField::LOOK_PITCH).append(pitch).packet());
if (assert) assertField(Serializer().append(NetField::LOOK_PITCH).append(pitch).packet());
}
glm::vec3 Player::getLookOffset() {
@ -49,7 +49,7 @@ glm::vec3 Player::getLookOffset() {
void Player::setLookOffset(glm::vec3 lookOffset, bool assert) {
this->lookOffset = lookOffset;
if (assert) assertField(Serializer().appendEnum(NetField::LOOK_OFF).append(lookOffset).packet());
if (assert) assertField(Serializer().append(NetField::LOOK_OFF).append(lookOffset).packet());
}
@ -59,7 +59,7 @@ bool Player::isFlying() {
void Player::setFlying(bool flying, bool assert) {
this->flying = flying;
if (assert) assertField(Serializer().appendEnum(NetField::FLYING).append(flying).packet());
if (assert) assertField(Serializer().append(NetField::FLYING).append(flying).packet());
}
std::string Player::getHandList() {
@ -68,7 +68,7 @@ std::string Player::getHandList() {
void Player::setHandList(const std::string& list, bool assert) {
handList = list;
if (assert) assertField(Serializer().appendEnum(NetField::HAND_INV).append(handList).packet());
if (assert) assertField(Serializer().append(NetField::HAND_INV).append(handList).packet());
}
std::string Player::getWieldList() {
@ -77,7 +77,7 @@ std::string Player::getWieldList() {
void Player::setWieldList(const std::string& list, bool assert) {
wieldList = list;
if (assert) assertField(Serializer().appendEnum(NetField::WIELD_INV).append(wieldList).packet());
if (assert) assertField(Serializer().append(NetField::WIELD_INV).append(wieldList).packet());
}
unsigned short Player::getWieldIndex() {
@ -86,5 +86,5 @@ unsigned short Player::getWieldIndex() {
void Player::setWieldIndex(unsigned short index, bool assert) {
wieldIndex = index;
if (assert) assertField(Serializer().appendEnum(NetField::WIELD_INDEX).append(index).packet());
if (assert) assertField(Serializer().append(NetField::WIELD_INDEX).append(index).packet());
}

View File

@ -26,8 +26,8 @@ class Deserializer;
class InventoryList;
class Player : public virtual Entity {
public:
Player(SubgamePtr game, World& world, DimensionPtr dim, unsigned int id = 0) :
public:
Player(SubgamePtr game, World& world, DimensionPtr dim, u32 id = 0) :
Entity(game, dim),
world(world), lookOffset(0, 1.65, 0) {
collisionBox = {{ -0.3, 0, -0.3 }, { 0.3, 1.8, 0.3 }};
@ -72,23 +72,23 @@ class Player : public virtual Entity {
virtual void handleAssertion(Deserializer& d) = 0;
protected:
protected:
virtual void assertField(Packet packet) = 0;
World& world;
float yaw = 0;
float pitch = 0;
f32 yaw = 0;
f32 pitch = 0;
glm::vec3 lookOffset{};
vec3 lookOffset{};
bool flying = false;
std::string handList = "";
std::string wieldList = "";
string handList = "";
string wieldList = "";
unsigned int handItem = DefinitionAtlas::AIR;
unsigned int wieldItem = DefinitionAtlas::AIR;
u16 handItem = DefinitionAtlas::AIR;
u16 wieldItem = DefinitionAtlas::AIR;
unsigned int wieldIndex = 0;
u16 wieldIndex = 0;
};

View File

@ -22,27 +22,27 @@ void ServerPlayer::assertField(Packet packet) {
void ServerPlayer::handleAssertion(Deserializer& d) {
while (!d.atEnd()) {
const auto field = d.readEnum<NetField>();
const auto field = d.read<NetField>();
switch (field) {
default:
std::cout << Log::err << "Player received unhandled NetField, Type "
<< static_cast<int>(field) << "." << Log::endl;
<< static_cast<u32>(field) << "." << Log::endl;
break;
case NetField::POS:
setPos(d.read<glm::vec3>());
setPos(d.read<vec3>());
break;
case NetField::VEL:
setVel(d.read<glm::vec3>());
setVel(d.read<vec3>());
break;
case NetField::LOOK_YAW:
setPitch(d.read<float>());
setPitch(d.read<f32>());
break;
case NetField::LOOK_PITCH:
setYaw(d.read<float>());
setYaw(d.read<f32>());
break;
case NetField::FLYING:
@ -50,15 +50,15 @@ void ServerPlayer::handleAssertion(Deserializer& d) {
break;
case NetField::HAND_INV:
setHandList(d.read<std::string>());
setHandList(d.read<string>());
break;
case NetField::WIELD_INV:
setWieldList(d.read<std::string>());
setWieldList(d.read<string>());
break;
case NetField::WIELD_INDEX:
setWieldIndex(d.read<unsigned short>());
setWieldIndex(d.read<u16>());
break;
}
}
@ -68,13 +68,13 @@ void ServerPlayer::setDim(DimensionPtr dim, bool assert) {
Player::setDim(dim, assert);
// Force a generation flush.
lastPos = glm::vec3(INFINITY);
lastPos = vec3(INFINITY);
changedMapBlocks = true;
}
void ServerPlayer::setPos(glm::vec3 pos, bool assert) {
glm::vec3 lastMapBlock = Space::MapBlock::world::fromBlock(this->pos);
glm::vec3 newMapBlock = Space::MapBlock::world::fromBlock(pos);
void ServerPlayer::setPos(vec3 pos, bool assert) {
vec3 lastMapBlock = Space::MapBlock::world::fromBlock(this->pos);
vec3 newMapBlock = Space::MapBlock::world::fromBlock(pos);
Player::setPos(pos, assert);

View File

@ -14,17 +14,13 @@
#include "world/inv/ServerInventory.h"
class ServerClient;
class Deserializer;
class ServerSubgame;
class ServerInventoryRefs;
enum class NetPlayerField;
class ServerPlayer : public Player {
public:
public:
ServerPlayer(ServerClient& client, World& world, SubgamePtr game, DimensionPtr dim);
virtual void assertField(Packet packet) override;
@ -33,16 +29,16 @@ class ServerPlayer : public Player {
virtual void setDim(DimensionPtr dim, bool assert = false) override;
virtual void setPos(glm::vec3 pos, bool assert = false) override;
virtual void setPos(vec3 pos, bool assert = false) override;
virtual InventoryPtr getInventory() override;
ENetPeer* getPeer();
bool changedMapBlocks = true;
glm::vec3 lastPos = glm::vec3(INFINITY);
vec3 lastPos = vec3(INFINITY);
private:
private:
ServerClient& client;
InventoryPtr inventory;
};