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
parent
4b28437b80
commit
4487997b92
|
@ -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 .)
|
41
src/Main.cpp
41
src/Main.cpp
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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.");
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
// }
|
||||
};
|
104
src/util/Space.h
104
src/util/Space.h
|
@ -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);
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
};
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 };
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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());
|
||||
}
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue