Changeset - r25617:39a04ee83963
[Not reviewed]
master
0 4 0
rubidium42 - 3 years ago 2021-05-30 10:53:42
rubidium@openttd.org
Codechange: [ContentInfo] Use a vector for dependencies instead of custom allocation
4 files changed with 16 insertions and 21 deletions:
0 comments (0 inline, 0 general)
src/network/core/tcp_content.cpp
Show inline comments
 
@@ -15,45 +15,43 @@
 
#include "../../base_media_base.h"
 
#include "../../ai/ai.hpp"
 
#include "../../game/game.hpp"
 
#include "../../fios.h"
 
#include "tcp_content.h"
 

	
 
#include "../../safeguards.h"
 

	
 
/** Clear everything in the struct */
 
ContentInfo::ContentInfo()
 
	: /* Temporary... will be removed later in the PR. */
 
	type((ContentType)0), id((ContentID)0), filesize(0), filename(""), name(""), version(""),
 
	url(""), description(""), unique_id(0), md5sum(""), dependency_count(0), dependencies(nullptr),
 
	url(""), description(""), unique_id(0), md5sum(""),
 
	state((State)0), upgrade(false)
 
{
 
}
 

	
 
/** Free everything allocated */
 
ContentInfo::~ContentInfo()
 
{
 
	free(this->dependencies);
 
}
 

	
 
/**
 
 * Copy data from other #ContentInfo and take ownership of allocated stuff.
 
 * @param other Source to copy from. #dependencies and #tags will be NULLed.
 
 */
 
void ContentInfo::TransferFrom(ContentInfo *other)
 
{
 
	if (other != this) {
 
		free(this->dependencies);
 
		*this = *other;
 
		other->dependencies = nullptr;
 
		other->dependencies.clear();
 
		other->tags.clear();
 
	}
 
}
 

	
 
/**
 
 * Is the state either selected or autoselected?
 
 * @return true iff that's the case
 
 */
 
bool ContentInfo::IsSelected() const
 
{
 
	switch (this->state) {
 
		case ContentInfo::SELECTED:
src/network/core/tcp_content_type.h
Show inline comments
 
@@ -58,26 +58,25 @@ struct ContentInfo {
 
	};
 

	
 
	ContentType type;        ///< Type of content
 
	ContentID id;            ///< Unique (server side) ID for the content
 
	uint32 filesize;         ///< Size of the file
 
	char filename[48];       ///< Filename (for the .tar.gz; only valid on download)
 
	char name[32];           ///< Name of the content
 
	char version[16];        ///< Version of the content
 
	char url[96];            ///< URL related to the content
 
	char description[512];   ///< Description of the content
 
	uint32 unique_id;        ///< Unique ID; either GRF ID or shortname
 
	byte md5sum[16];         ///< The MD5 checksum
 
	uint8 dependency_count;  ///< Number of dependencies
 
	ContentID *dependencies; ///< Malloced array of dependencies (unique server side ids)
 
	std::vector<ContentID> dependencies; ///< The dependencies (unique server side ids)
 
	StringList tags;         ///< Tags associated with the content
 
	State state;             ///< Whether the content info is selected (for download)
 
	bool upgrade;            ///< This item is an upgrade
 

	
 
	ContentInfo();
 
	~ContentInfo();
 

	
 
	void TransferFrom(ContentInfo *other);
 

	
 
	bool IsSelected() const;
 
	bool IsValid() const;
 
	const char *GetTextfile(TextfileType type) const;
src/network/network_content.cpp
Show inline comments
 
@@ -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) {
src/network/network_content_gui.cpp
Show inline comments
 
@@ -716,31 +716,29 @@ public:
 
		if (!StrEmpty(this->selected->url)) {
 
			SetDParamStr(0, this->selected->url);
 
			y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_URL);
 
		}
 

	
 
		SetDParam(0, STR_CONTENT_TYPE_BASE_GRAPHICS + this->selected->type - CONTENT_TYPE_BASE_GRAPHICS);
 
		y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_TYPE);
 

	
 
		y += WD_PAR_VSEP_WIDE;
 
		SetDParam(0, this->selected->filesize);
 
		y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_FILESIZE);
 

	
 
		if (this->selected->dependency_count != 0) {
 
		if (!this->selected->dependencies.empty()) {
 
			/* List dependencies */
 
			char buf[DRAW_STRING_BUFFER] = "";
 
			char *p = buf;
 
			for (uint i = 0; i < this->selected->dependency_count; i++) {
 
				ContentID cid = this->selected->dependencies[i];
 

	
 
			for (auto &cid : this->selected->dependencies) {
 
				/* Try to find the dependency */
 
				ConstContentIterator iter = _network_content_client.Begin();
 
				for (; iter != _network_content_client.End(); iter++) {
 
					const ContentInfo *ci = *iter;
 
					if (ci->id != cid) continue;
 

	
 
					p += seprintf(p, lastof(buf), p == buf ? "%s" : ", %s", (*iter)->name);
 
					break;
 
				}
 
			}
 
			SetDParamStr(0, buf);
 
			y = DrawStringMultiLine(r.left + DETAIL_LEFT, r.right - DETAIL_RIGHT, y, max_y, STR_CONTENT_DETAIL_DEPENDENCIES);
0 comments (0 inline, 0 general)