overte-JulianGro/assignment-client/src/entities/EntityServer.cpp

160 lines
6 KiB
C++

//
// EntityServer.cpp
// assignment-client/src/entities
//
// Created by Brad Hefta-Gaub on 4/29/14
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QTimer>
#include <EntityTree.h>
#include <SimpleEntitySimulation.h>
#include "EntityServer.h"
#include "EntityServerConsts.h"
#include "EntityNodeData.h"
const char* MODEL_SERVER_NAME = "Entity";
const char* MODEL_SERVER_LOGGING_TARGET_NAME = "entity-server";
const char* LOCAL_MODELS_PERSIST_FILE = "resources/models.svo";
EntityServer::EntityServer(const QByteArray& packet)
: OctreeServer(packet), _entitySimulation(NULL) {
// nothing special to do here...
}
EntityServer::~EntityServer() {
EntityTree* tree = (EntityTree*)_tree;
tree->removeNewlyCreatedHook(this);
}
OctreeQueryNode* EntityServer::createOctreeQueryNode() {
return new EntityNodeData();
}
Octree* EntityServer::createTree() {
EntityTree* tree = new EntityTree(true);
tree->addNewlyCreatedHook(this);
if (!_entitySimulation) {
SimpleEntitySimulation* simpleSimulation = new SimpleEntitySimulation();
simpleSimulation->setEntityTree(tree);
tree->setSimulation(simpleSimulation);
_entitySimulation = simpleSimulation;
}
return tree;
}
void EntityServer::beforeRun() {
QTimer* pruneDeletedEntitiesTimer = new QTimer(this);
connect(pruneDeletedEntitiesTimer, SIGNAL(timeout()), this, SLOT(pruneDeletedEntities()));
const int PRUNE_DELETED_MODELS_INTERVAL_MSECS = 1 * 1000; // once every second
pruneDeletedEntitiesTimer->start(PRUNE_DELETED_MODELS_INTERVAL_MSECS);
}
void EntityServer::entityCreated(const EntityItem& newEntity, const SharedNodePointer& senderNode) {
unsigned char outputBuffer[MAX_PACKET_SIZE];
unsigned char* copyAt = outputBuffer;
int numBytesPacketHeader = populatePacketHeader(reinterpret_cast<char*>(outputBuffer), PacketTypeEntityAddResponse);
int packetLength = numBytesPacketHeader;
copyAt += numBytesPacketHeader;
// encode the creatorTokenID
uint32_t creatorTokenID = newEntity.getCreatorTokenID();
memcpy(copyAt, &creatorTokenID, sizeof(creatorTokenID));
copyAt += sizeof(creatorTokenID);
packetLength += sizeof(creatorTokenID);
// encode the entity ID
QUuid entityID = newEntity.getID();
QByteArray encodedID = entityID.toRfc4122();
memcpy(copyAt, encodedID.constData(), encodedID.size());
copyAt += sizeof(entityID);
packetLength += sizeof(entityID);
DependencyManager::get<NodeList>()->writeDatagram((char*) outputBuffer, packetLength, senderNode);
}
// EntityServer will use the "special packets" to send list of recently deleted entities
bool EntityServer::hasSpecialPacketToSend(const SharedNodePointer& node) {
bool shouldSendDeletedEntities = false;
// check to see if any new entities have been added since we last sent to this node...
EntityNodeData* nodeData = static_cast<EntityNodeData*>(node->getLinkedData());
if (nodeData) {
quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt();
EntityTree* tree = static_cast<EntityTree*>(_tree);
shouldSendDeletedEntities = tree->hasEntitiesDeletedSince(deletedEntitiesSentAt);
}
return shouldSendDeletedEntities;
}
int EntityServer::sendSpecialPacket(const SharedNodePointer& node, OctreeQueryNode* queryNode, int& packetsSent) {
unsigned char outputBuffer[MAX_PACKET_SIZE];
size_t packetLength = 0;
EntityNodeData* nodeData = static_cast<EntityNodeData*>(node->getLinkedData());
if (nodeData) {
quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt();
quint64 deletePacketSentAt = usecTimestampNow();
EntityTree* tree = static_cast<EntityTree*>(_tree);
bool hasMoreToSend = true;
// TODO: is it possible to send too many of these packets? what if you deleted 1,000,000 entities?
packetsSent = 0;
while (hasMoreToSend) {
hasMoreToSend = tree->encodeEntitiesDeletedSince(queryNode->getSequenceNumber(), deletedEntitiesSentAt,
outputBuffer, MAX_PACKET_SIZE, packetLength);
DependencyManager::get<NodeList>()->writeDatagram((char*) outputBuffer, packetLength,
SharedNodePointer(node));
queryNode->packetSent(outputBuffer, packetLength);
packetsSent++;
}
nodeData->setLastDeletedEntitiesSentAt(deletePacketSentAt);
}
// TODO: caller is expecting a packetLength, what if we send more than one packet??
return packetLength;
}
void EntityServer::pruneDeletedEntities() {
EntityTree* tree = static_cast<EntityTree*>(_tree);
if (tree->hasAnyDeletedEntities()) {
quint64 earliestLastDeletedEntitiesSent = usecTimestampNow() + 1; // in the future
DependencyManager::get<NodeList>()->eachNode([&earliestLastDeletedEntitiesSent](const SharedNodePointer& node) {
if (node->getLinkedData()) {
EntityNodeData* nodeData = static_cast<EntityNodeData*>(node->getLinkedData());
quint64 nodeLastDeletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt();
if (nodeLastDeletedEntitiesSentAt < earliestLastDeletedEntitiesSent) {
earliestLastDeletedEntitiesSent = nodeLastDeletedEntitiesSentAt;
}
}
});
tree->forgetEntitiesDeletedBefore(earliestLastDeletedEntitiesSent);
}
}
void EntityServer::readAdditionalConfiguration(const QJsonObject& settingsSectionObject) {
bool wantEditLogging = false;
readOptionBool(QString("wantEditLogging"), settingsSectionObject, wantEditLogging);
qDebug("wantEditLogging=%s", debug::valueOf(wantEditLogging));
EntityTree* tree = static_cast<EntityTree*>(_tree);
tree->setWantEditLogging(wantEditLogging);
}