|
@@ -57,27 +57,27 @@ bool ClientNetworkContentSocketHandler::
|
|
|
ci->filesize = p->Recv_uint32();
|
|
|
|
|
|
p->Recv_string(ci->name, lengthof(ci->name));
|
|
|
p->Recv_string(ci->version, lengthof(ci->version));
|
|
|
p->Recv_string(ci->url, lengthof(ci->url));
|
|
|
p->Recv_string(ci->description, lengthof(ci->description), SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE);
|
|
|
|
|
|
ci->unique_id = p->Recv_uint32();
|
|
|
for (uint j = 0; j < sizeof(ci->md5sum); j++) {
|
|
|
ci->md5sum[j] = p->Recv_uint8();
|
|
|
}
|
|
|
|
|
|
ci->dependency_count = p->Recv_uint8();
|
|
|
ci->dependencies = MallocT<ContentID>(ci->dependency_count);
|
|
|
for (uint i = 0; i < ci->dependency_count; i++) ci->dependencies[i] = (ContentID)p->Recv_uint32();
|
|
|
uint dependency_count = p->Recv_uint8();
|
|
|
ci->dependencies.reserve(dependency_count);
|
|
|
for (uint i = 0; i < dependency_count; i++) ci->dependencies.push_back((ContentID)p->Recv_uint32());
|
|
|
|
|
|
uint tag_count = p->Recv_uint8();
|
|
|
ci->tags.reserve(tag_count);
|
|
|
for (uint i = 0; i < tag_count; i++) ci->tags.push_back(p->Recv_string(NETWORK_CONTENT_TAG_LENGTH));
|
|
|
|
|
|
if (!ci->IsValid()) {
|
|
|
delete ci;
|
|
|
this->CloseConnection();
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
/* Find the appropriate check function */
|
|
@@ -918,26 +918,26 @@ void ClientNetworkContentSocketHandler::
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Reverse lookup the dependencies of (direct) parents over a given child.
|
|
|
* @param parents list to store all parents in (is not cleared)
|
|
|
* @param child the child to search the parents' dependencies for
|
|
|
*/
|
|
|
void ClientNetworkContentSocketHandler::ReverseLookupDependency(ConstContentVector &parents, const ContentInfo *child) const
|
|
|
{
|
|
|
for (const ContentInfo *ci : this->infos) {
|
|
|
if (ci == child) continue;
|
|
|
|
|
|
for (uint i = 0; i < ci->dependency_count; i++) {
|
|
|
if (ci->dependencies[i] == child->id) {
|
|
|
for (auto &dependency : ci->dependencies) {
|
|
|
if (dependency == child->id) {
|
|
|
parents.push_back(ci);
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Reverse lookup the dependencies of all parents over a given child.
|
|
|
* @param tree list to store all parents in (is not cleared)
|
|
|
* @param child the child to search the parents' dependencies for
|
|
|
*/
|
|
@@ -960,54 +960,54 @@ void ClientNetworkContentSocketHandler::
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Check the dependencies (recursively) of this content info
|
|
|
* @param ci the content info to check the dependencies of
|
|
|
*/
|
|
|
void ClientNetworkContentSocketHandler::CheckDependencyState(ContentInfo *ci)
|
|
|
{
|
|
|
if (ci->IsSelected() || ci->state == ContentInfo::ALREADY_HERE) {
|
|
|
/* Selection is easy; just walk all children and set the
|
|
|
* autoselected state. That way we can see what we automatically
|
|
|
* selected and thus can unselect when a dependency is removed. */
|
|
|
for (uint i = 0; i < ci->dependency_count; i++) {
|
|
|
ContentInfo *c = this->GetContent(ci->dependencies[i]);
|
|
|
for (auto &dependency : ci->dependencies) {
|
|
|
ContentInfo *c = this->GetContent(dependency);
|
|
|
if (c == nullptr) {
|
|
|
this->DownloadContentInfo(ci->dependencies[i]);
|
|
|
this->DownloadContentInfo(dependency);
|
|
|
} else if (c->state == ContentInfo::UNSELECTED) {
|
|
|
c->state = ContentInfo::AUTOSELECTED;
|
|
|
this->CheckDependencyState(c);
|
|
|
}
|
|
|
}
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (ci->state != ContentInfo::UNSELECTED) return;
|
|
|
|
|
|
/* For unselection we need to find the parents of us. We need to
|
|
|
* unselect them. After that we unselect all children that we
|
|
|
* depend on and are not used as dependency for us, but only when
|
|
|
* we automatically selected them. */
|
|
|
ConstContentVector parents;
|
|
|
this->ReverseLookupDependency(parents, ci);
|
|
|
for (const ContentInfo *c : parents) {
|
|
|
if (!c->IsSelected()) continue;
|
|
|
|
|
|
this->Unselect(c->id);
|
|
|
}
|
|
|
|
|
|
for (uint i = 0; i < ci->dependency_count; i++) {
|
|
|
const ContentInfo *c = this->GetContent(ci->dependencies[i]);
|
|
|
for (auto &dependency : ci->dependencies) {
|
|
|
const ContentInfo *c = this->GetContent(dependency);
|
|
|
if (c == nullptr) {
|
|
|
DownloadContentInfo(ci->dependencies[i]);
|
|
|
DownloadContentInfo(dependency);
|
|
|
continue;
|
|
|
}
|
|
|
if (c->state != ContentInfo::AUTOSELECTED) continue;
|
|
|
|
|
|
/* Only unselect when WE are the only parent. */
|
|
|
parents.clear();
|
|
|
this->ReverseLookupDependency(parents, c);
|
|
|
|
|
|
/* First check whether anything depends on us */
|
|
|
int sel_count = 0;
|
|
|
bool force_selection = false;
|
|
|
for (const ContentInfo *parent_ci : parents) {
|