2019-02-01 16:12:37 -08:00
|
|
|
//
|
|
|
|
// Created by aurailus on 09/01/19.
|
|
|
|
//
|
|
|
|
|
2020-02-17 15:55:39 -08:00
|
|
|
#include <thread>
|
2020-07-06 18:34:59 -07:00
|
|
|
#include <iostream>
|
2020-02-17 15:55:39 -08:00
|
|
|
|
2019-02-01 16:12:37 -08:00
|
|
|
#include "Server.h"
|
|
|
|
|
2020-07-06 20:00:00 -07:00
|
|
|
#include "../Serializer.h"
|
|
|
|
#include "../../util/Timer.h"
|
|
|
|
#include "../PacketChannel.h"
|
2020-07-28 14:11:11 -07:00
|
|
|
#include "../../world/Target.h"
|
2020-07-06 20:00:00 -07:00
|
|
|
#include "../../def/item/BlockDef.h"
|
2020-07-26 19:59:03 -07:00
|
|
|
#include "../../lua/usertype/ServerLuaPlayer.h"
|
2020-02-28 13:03:19 -08:00
|
|
|
|
2020-02-26 13:42:15 -08:00
|
|
|
Server::Server(unsigned short port, const std::string& subgame) :
|
2020-06-16 22:36:12 -07:00
|
|
|
seed(69),
|
2019-05-27 23:01:22 -07:00
|
|
|
port(port),
|
2020-02-26 13:42:15 -08:00
|
|
|
config(defs),
|
2020-04-06 17:18:57 -07:00
|
|
|
defs(subgame, seed),
|
2020-02-26 13:42:15 -08:00
|
|
|
clientList(defs),
|
2019-07-07 20:36:55 -07:00
|
|
|
handler(port, 32),
|
2020-07-25 11:55:48 -07:00
|
|
|
refs(*defs.defs, &clientList),
|
2020-04-06 17:18:57 -07:00
|
|
|
world(seed, defs, clientList) {
|
2019-02-01 16:12:37 -08:00
|
|
|
|
2019-12-10 15:14:59 -08:00
|
|
|
defs.init(world);
|
2020-07-06 14:00:46 -07:00
|
|
|
world.init("world");
|
2019-07-11 23:50:24 -07:00
|
|
|
config.init();
|
2019-06-12 18:06:51 -07:00
|
|
|
|
2020-02-11 14:27:48 -08:00
|
|
|
std::cout << Log::info << "Server started successfully, listening for clients." << Log::endl;
|
2019-02-04 16:39:52 -08:00
|
|
|
while (alive) update();
|
2019-02-01 16:12:37 -08:00
|
|
|
}
|
|
|
|
|
2019-02-04 16:39:52 -08:00
|
|
|
void Server::update() {
|
2020-03-15 14:26:39 -07:00
|
|
|
const static long interval_ns = static_cast<long>((1000 / 60.f) * 1000000L);
|
2019-02-01 16:12:37 -08:00
|
|
|
Timer loop("");
|
|
|
|
|
2020-01-09 21:04:31 -08:00
|
|
|
world.update(0);
|
2020-02-19 15:20:59 -08:00
|
|
|
defs.update(deltaTime, clientList);
|
2020-02-27 17:23:42 -08:00
|
|
|
refs.update();
|
2019-03-07 17:43:05 -08:00
|
|
|
|
2019-02-04 16:39:52 -08:00
|
|
|
ENetEvent event;
|
2019-07-03 13:24:19 -07:00
|
|
|
while (handler.update(&event) && loop.elapsedNs() < interval_ns) {
|
2019-02-04 16:39:52 -08:00
|
|
|
switch (event.type) {
|
2019-07-03 13:24:19 -07:00
|
|
|
default:
|
2020-02-20 22:44:16 -08:00
|
|
|
case ENET_EVENT_TYPE_NONE: {
|
2019-10-11 15:13:46 -07:00
|
|
|
std::cout << "Unknown packet type: " << event.type << std::endl;
|
|
|
|
break;
|
2020-02-20 22:44:16 -08:00
|
|
|
}
|
2019-02-08 00:25:45 -08:00
|
|
|
case ENET_EVENT_TYPE_CONNECT: {
|
2020-02-27 17:23:42 -08:00
|
|
|
clientList.handleConnect(event, refs);
|
2019-02-04 16:39:52 -08:00
|
|
|
break;
|
2019-02-08 00:25:45 -08:00
|
|
|
}
|
2019-06-20 22:59:00 -07:00
|
|
|
case ENET_EVENT_TYPE_DISCONNECT: {
|
2019-07-03 13:24:19 -07:00
|
|
|
clientList.handleDisconnect(event);
|
2019-06-20 22:59:00 -07:00
|
|
|
break;
|
|
|
|
}
|
2019-02-08 00:25:45 -08:00
|
|
|
case ENET_EVENT_TYPE_RECEIVE: {
|
2020-03-15 14:26:39 -07:00
|
|
|
PacketView p(event.packet);
|
2019-07-22 01:22:40 -07:00
|
|
|
ServerClient* client = static_cast<ServerClient*>(event.peer->data);
|
2019-02-08 00:25:45 -08:00
|
|
|
|
2020-02-17 15:55:39 -08:00
|
|
|
if (client->hasPlayer) {
|
2019-07-03 13:24:19 -07:00
|
|
|
handlePlayerPacket(*client, p);
|
2019-08-14 01:54:51 -07:00
|
|
|
}
|
2019-07-03 13:24:19 -07:00
|
|
|
else {
|
2019-07-22 01:22:40 -07:00
|
|
|
bool done = config.handlePacket(*client, p);
|
|
|
|
if (done) {
|
2020-02-19 15:20:59 -08:00
|
|
|
std::shared_ptr<ServerClient> clientShared = nullptr;
|
|
|
|
for (auto& sClient : clientList.clients) {
|
|
|
|
if (sClient->cid == client->cid) {
|
|
|
|
clientShared = sClient;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!clientShared) break;
|
|
|
|
clientList.createPlayer(clientShared);
|
2019-07-22 01:22:40 -07:00
|
|
|
}
|
2019-02-08 00:25:45 -08:00
|
|
|
}
|
2019-02-04 16:39:52 -08:00
|
|
|
break;
|
2019-02-08 00:25:45 -08:00
|
|
|
}
|
2019-02-01 16:12:37 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-21 00:07:13 -08:00
|
|
|
for (auto& cid : playersUpdated) {
|
2020-02-20 22:44:16 -08:00
|
|
|
auto client = clientList.getClient(cid);
|
|
|
|
if (client == nullptr) continue;
|
|
|
|
|
2020-02-21 00:07:13 -08:00
|
|
|
Packet r(PacketType::PLAYER_INFO, false);
|
2020-02-20 22:44:16 -08:00
|
|
|
r.data = Serializer()
|
|
|
|
.append(client->cid)
|
|
|
|
.append(client->getPos())
|
|
|
|
.append(client->getPitch())
|
|
|
|
.append(client->getYaw())
|
|
|
|
.data;
|
|
|
|
|
|
|
|
for (auto& iter : clientList.clients)
|
|
|
|
if (iter->cid != cid && glm::distance(client->getPos(), iter->getPos()) < 200)
|
|
|
|
r.sendTo(iter->peer, PacketChannel::ENTITY);
|
|
|
|
}
|
|
|
|
playersUpdated.clear();
|
|
|
|
|
2019-06-27 16:59:16 -07:00
|
|
|
long sleep_for = interval_ns - loop.elapsedNs();
|
2019-07-03 13:24:19 -07:00
|
|
|
if (sleep_for > 0) std::this_thread::sleep_for(std::chrono::nanoseconds(sleep_for));
|
2019-06-27 16:59:16 -07:00
|
|
|
|
2019-10-11 15:13:46 -07:00
|
|
|
deltaTime = loop.elapsedNs() / 1000000.f / 1000.f;
|
2019-06-27 16:59:16 -07:00
|
|
|
elapsedSeconds += deltaTime;
|
2019-02-01 16:12:37 -08:00
|
|
|
}
|
|
|
|
|
2020-03-15 14:26:39 -07:00
|
|
|
void Server::handlePlayerPacket(ServerClient& client, PacketView& p) {
|
2019-07-03 13:24:19 -07:00
|
|
|
switch (p.type) {
|
|
|
|
default: {
|
2019-07-07 20:36:55 -07:00
|
|
|
std::cout << Log::err << "Invalid packet type (" << static_cast<int>(p.type) << ") recieved." << Log::endl;
|
2020-07-28 14:11:11 -07:00
|
|
|
break; }
|
|
|
|
|
2020-02-25 15:14:07 -08:00
|
|
|
case PacketType::PLAYER_INFO: {
|
2020-03-15 14:26:39 -07:00
|
|
|
client.setPos(p.d.read<glm::vec3>());
|
|
|
|
client.setPitch(p.d.read<float>());
|
|
|
|
client.setYaw(p.d.read<float>());
|
2019-07-03 13:24:19 -07:00
|
|
|
|
2020-02-21 00:07:13 -08:00
|
|
|
playersUpdated.emplace(client.cid);
|
2020-07-28 14:11:11 -07:00
|
|
|
break; }
|
|
|
|
|
|
|
|
case PacketType::THIS_PLAYER_INFO: {
|
|
|
|
client.handleAssertion(p.d);
|
|
|
|
break; }
|
|
|
|
|
2019-07-07 20:36:55 -07:00
|
|
|
case PacketType::BLOCK_SET: {
|
2020-03-15 14:26:39 -07:00
|
|
|
glm::ivec3 pos = p.d.read<glm::ivec3>();
|
|
|
|
unsigned int block = p.d.read<unsigned int>();
|
2019-07-03 13:24:19 -07:00
|
|
|
|
2020-01-08 14:42:14 -08:00
|
|
|
unsigned int worldBlock = (block == DefinitionAtlas::AIR ? world.getBlock(pos) : 0);
|
|
|
|
|
2020-02-28 13:03:19 -08:00
|
|
|
if (block == DefinitionAtlas::AIR) {
|
2020-07-25 20:19:18 -07:00
|
|
|
auto& def = defs.defs->blockFromId(worldBlock);
|
|
|
|
if (def.callbacks.count(Callback::BREAK)) defs.lua->safe_function(def.callbacks[Callback::BREAK], pos, ServerLuaPlayer(client));
|
|
|
|
defs.lua->safe_function(defs.lua->core["trigger"], "break", pos, ServerLuaPlayer(client));
|
2020-02-28 13:03:19 -08:00
|
|
|
}
|
|
|
|
else {
|
2020-07-25 20:19:18 -07:00
|
|
|
auto& def = defs.defs->blockFromId(block);
|
|
|
|
if (def.callbacks.count(Callback::PLACE)) defs.lua->safe_function(def.callbacks[Callback::PLACE], pos, ServerLuaPlayer(client));
|
2020-07-25 11:55:48 -07:00
|
|
|
defs.lua->safe_function(defs.lua->core["trigger"], "place", pos, ServerLuaPlayer(client));
|
2020-02-28 13:03:19 -08:00
|
|
|
}
|
|
|
|
|
2019-07-03 13:24:19 -07:00
|
|
|
world.setBlock(pos, block);
|
|
|
|
|
2020-01-07 16:49:39 -08:00
|
|
|
if (block == DefinitionAtlas::AIR) {
|
2020-07-25 20:19:18 -07:00
|
|
|
auto& def = defs.defs->blockFromId(worldBlock);
|
2020-07-23 18:54:11 -07:00
|
|
|
if (def.callbacks.count(Callback::AFTER_BREAK))
|
2020-07-25 11:55:48 -07:00
|
|
|
defs.lua->safe_function(def.callbacks[Callback::AFTER_BREAK], pos, ServerLuaPlayer(client));
|
|
|
|
defs.lua->safe_function(defs.lua->core["trigger"], "after_break", pos, ServerLuaPlayer(client));
|
2020-01-08 14:42:14 -08:00
|
|
|
}
|
|
|
|
else {
|
2020-07-25 20:19:18 -07:00
|
|
|
auto& def = defs.defs->blockFromId(block);
|
2020-07-23 18:54:11 -07:00
|
|
|
if (def.callbacks.count(Callback::AFTER_PLACE))
|
2020-07-25 11:55:48 -07:00
|
|
|
defs.lua->safe_function(def.callbacks[Callback::AFTER_PLACE], pos, ServerLuaPlayer(client));
|
|
|
|
defs.lua->safe_function(defs.lua->core["trigger"], "after_place", pos, ServerLuaPlayer(client));
|
2019-07-03 13:24:19 -07:00
|
|
|
}
|
2020-07-28 14:11:11 -07:00
|
|
|
break; }
|
|
|
|
|
|
|
|
case PacketType::BLOCK_PLACE: {
|
|
|
|
glm::ivec3 pos = p.d.read<glm::ivec3>();
|
|
|
|
auto face = static_cast<EVec>(p.d.read<unsigned short>());
|
|
|
|
world.blockPlace(Target(pos, face), client);
|
|
|
|
break; }
|
|
|
|
|
2020-07-21 19:33:26 -07:00
|
|
|
case PacketType::BLOCK_INTERACT: {
|
|
|
|
glm::ivec3 pos = p.d.read<glm::ivec3>();
|
2020-07-28 14:11:11 -07:00
|
|
|
auto face = static_cast<EVec>(p.d.read<unsigned short>());
|
|
|
|
world.blockInteract(Target(pos, face), client);
|
|
|
|
break; }
|
|
|
|
|
|
|
|
case PacketType::BLOCK_PLACE_OR_INTERACT: {
|
|
|
|
glm::ivec3 pos = p.d.read<glm::ivec3>();
|
|
|
|
auto face = static_cast<EVec>(p.d.read<unsigned short>());
|
|
|
|
world.blockPlaceOrInteract(Target(pos, face), client);
|
|
|
|
break; }
|
|
|
|
|
2020-03-01 14:33:47 -08:00
|
|
|
case PacketType::INV_WATCH: {
|
2020-03-15 14:26:39 -07:00
|
|
|
std::string source = p.d.read<std::string>();
|
|
|
|
std::string list = p.d.read<std::string>();
|
2020-02-27 17:23:42 -08:00
|
|
|
|
|
|
|
// TODO: When inventory saving / loading is implemented there will need to be a cross-save identifier.
|
|
|
|
if (source == "current_player") source = "player:" + std::to_string(client.cid);
|
|
|
|
|
|
|
|
bool exists = refs.addWatcher(source, list, client.cid);
|
2020-07-21 19:33:26 -07:00
|
|
|
if (!exists) Serializer().append(source).append(list)
|
|
|
|
.packet(PacketType::INV_INVALID).sendTo(client.peer, PacketChannel::INVENTORY);
|
2020-07-28 14:11:11 -07:00
|
|
|
break; }
|
|
|
|
|
2020-03-01 14:33:47 -08:00
|
|
|
case PacketType::INV_UNWATCH: {
|
2020-04-17 17:19:01 -07:00
|
|
|
std::string source = p.d.read<std::string>();
|
|
|
|
std::string list = p.d.read<std::string>();
|
2020-02-27 17:23:42 -08:00
|
|
|
|
|
|
|
// TODO: When inventory saving / loading is implemented there will need to be a cross-save identifier.
|
|
|
|
if (source == "current_player") source = "player:" + std::to_string(client.cid);
|
|
|
|
|
|
|
|
bool exists = refs.removeWatcher(source, list, client.cid);
|
|
|
|
if (!exists) {
|
|
|
|
Serializer().append(source).append(list)
|
|
|
|
.packet(PacketType::INV_INVALID).sendTo(client.peer, PacketChannel::INVENTORY);
|
|
|
|
break;
|
|
|
|
}
|
2020-02-26 13:42:15 -08:00
|
|
|
|
2020-07-28 14:11:11 -07:00
|
|
|
break; }
|
2020-03-01 14:33:47 -08:00
|
|
|
|
2020-07-28 14:11:11 -07:00
|
|
|
case PacketType::INV_INTERACT: {
|
2020-04-17 17:19:01 -07:00
|
|
|
unsigned short type = p.d.read<unsigned short>();
|
2020-03-01 14:33:47 -08:00
|
|
|
|
2020-04-17 17:19:01 -07:00
|
|
|
std::string source = p.d.read<std::string>();
|
|
|
|
std::string list = p.d.read<std::string>();
|
|
|
|
unsigned short ind = p.d.read<unsigned short>();
|
2020-03-01 14:33:47 -08:00
|
|
|
|
|
|
|
// TODO: When inventory saving / loading is implemented there will need to be a cross-save identifier.
|
|
|
|
if (source == "current_player") source = "player:" + std::to_string(client.cid);
|
|
|
|
|
|
|
|
if (type == 0) refs.primaryInteract(source, list, ind, client.cid);
|
|
|
|
else refs.secondaryInteract(source, list, ind, client.cid);
|
|
|
|
|
2020-07-28 14:11:11 -07:00
|
|
|
break; }
|
2019-07-03 13:24:19 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-01 16:12:37 -08:00
|
|
|
void Server::cleanup() {
|
|
|
|
alive = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
Server::~Server() {
|
|
|
|
cleanup();
|
|
|
|
}
|