OpenTTD Source 20260109-master-g241b5fcdfe
tcp_content.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "../../stdafx.h"
11#include "../../textfile_gui.h"
12#include "../../newgrf_config.h"
13#include "../../base_media_base.h"
14#include "../../base_media_graphics.h"
15#include "../../base_media_music.h"
16#include "../../base_media_sounds.h"
17#include "../../ai/ai.hpp"
18#include "../../game/game.hpp"
19#include "../../fios.h"
20#include "tcp_content.h"
21
22#include "table/strings.h"
23
24#include "../../safeguards.h"
25
31{
32 switch (this->state) {
36 return true;
37
38 default:
39 return false;
40 }
41}
42
48{
49 return this->state < ContentInfo::State::Invalid && this->type >= CONTENT_TYPE_BEGIN && this->type < CONTENT_TYPE_END;
50}
51
57std::optional<std::string> ContentInfo::GetTextfile(TextfileType type) const
58{
59 if (this->state == ContentInfo::State::Invalid) return std::nullopt;
60 std::optional<std::string_view> tmp;
61 switch (this->type) {
62 default: NOT_REACHED();
63 case CONTENT_TYPE_AI:
64 tmp = AI::GetScannerInfo()->FindMainScript(*this, true);
65 break;
67 tmp = AI::GetScannerLibrary()->FindMainScript(*this, true);
68 break;
70 tmp = Game::GetScannerInfo()->FindMainScript(*this, true);
71 break;
73 tmp = Game::GetScannerLibrary()->FindMainScript(*this, true);
74 break;
76 const GRFConfig *gc = FindGRFConfig(std::byteswap(this->unique_id), FGCM_EXACT, &this->md5sum);
77 if (gc != nullptr) tmp = gc->filename;
78 break;
79 }
82 break;
85 break;
88 break;
91 tmp = FindScenario(*this, true);
92 break;
93 }
94 if (!tmp.has_value()) return std::nullopt;
95 return ::GetTextfile(type, GetContentInfoSubDir(this->type), *tmp);
96}
97
105{
107
108 switch (this->HasClientQuit() ? PACKET_CONTENT_END : type) {
116
117 default:
118 if (this->HasClientQuit()) {
119 Debug(net, 0, "[tcp/content] Received invalid packet type {}", type);
120 } else {
121 Debug(net, 0, "[tcp/content] Received illegal packet");
122 }
123 return false;
124 }
125}
126
132{
133 /*
134 * We read only a few of the packets. This as receiving packets can be expensive
135 * due to the re-resolving of the parent/child relations and checking the toggle
136 * state of all bits. We cannot do this all in one go, as we want to show the
137 * user what we already received. Otherwise, it can take very long before any
138 * progress is shown to the end user that something has been received.
139 * It is also the case that we request extra content from the content server in
140 * case there is an unknown (in the content list) piece of content. These will
141 * come in after the main lists have been requested. As a result, we won't be
142 * getting everything reliably in one batch. Thus, we need to make subsequent
143 * updates in that case as well.
144 *
145 * As a result, we simple handle an arbitrary number of packets in one cycle,
146 * and let the rest be handled in subsequent cycles. These are ran, almost,
147 * immediately after this cycle so in speed it does not matter much, except
148 * that the user interface will appear better responding.
149 *
150 * What arbitrary number to choose is the ultimate question though.
151 */
152 std::unique_ptr<Packet> p;
153 static const int MAX_PACKETS_TO_RECEIVE = 42;
154 int i = MAX_PACKETS_TO_RECEIVE;
155 while (--i != 0 && (p = this->ReceivePacket()) != nullptr) {
156 bool cont = this->HandlePacket(*p);
157 if (!cont) return true;
158 }
159
160 return i != MAX_PACKETS_TO_RECEIVE - 1;
161}
162
163
170{
171 Debug(net, 0, "[tcp/content] Received illegal packet type {}", type);
172 return false;
173}
174
182
189{
190 switch (type) {
191 default: return NO_DIRECTORY;
192 case CONTENT_TYPE_AI: return AI_DIR;
194 case CONTENT_TYPE_GAME: return GAME_DIR;
196 case CONTENT_TYPE_NEWGRF: return NEWGRF_DIR;
197
201 return BASESET_DIR;
202
205 }
206}
std::optional< std::string_view > TryGetBaseSetFile(const ContentInfo &ci, bool md5sum, std::span< const std::unique_ptr< Tbase_set > > sets)
Check whether there's a base set matching some information.
static AIScannerLibrary * GetScannerLibrary()
Gets the ScriptScanner instance that is used to find AI Libraries.
Definition ai_core.cpp:352
static AIScannerInfo * GetScannerInfo()
Gets the ScriptScanner instance that is used to find AIs.
Definition ai_core.cpp:347
static std::span< const std::unique_ptr< GraphicsSet > > GetAvailableSets()
Return the available sets.
static GameScannerLibrary * GetScannerLibrary()
Gets the ScriptScanner instance that is used to find Game Libraries.
static GameScannerInfo * GetScannerInfo()
Gets the ScriptScanner instance that is used to find Game scripts.
virtual bool Receive_CLIENT_CONTENT(Packet &p)
Client requesting the actual content: uint16_t count of unique ids uint32_t unique id (count times)
virtual bool Receive_CLIENT_INFO_EXTID(Packet &p)
Client requesting a list of content info based on an external 'unique' id; GRF ID for NewGRFS,...
virtual bool Receive_CLIENT_INFO_EXTID_MD5(Packet &p)
Client requesting a list of content info based on an external 'unique' id; GRF ID + MD5 checksum for ...
virtual bool Receive_SERVER_INFO(Packet &p)
Server sending list of content info: uint8_t type (invalid ID == does not exist) uint32_t id uint32_t...
virtual bool Receive_CLIENT_INFO_ID(Packet &p)
Client requesting a list of content info: uint16_t count of ids uint32_t id (count times)
virtual bool Receive_SERVER_CONTENT(Packet &p)
Server sending list of content info: uint32_t unique id uint32_t file size (0 == does not exist) stri...
bool ReceivePackets()
Receive a packet at TCP level.
virtual bool Receive_CLIENT_INFO_LIST(Packet &p)
Client requesting a list of content info: uint8_t type uint32_t openttd version (or 0xFFFFFFFF if usi...
bool ReceiveInvalidPacket(PacketContentType type)
Helper for logging receiving invalid packets.
bool HandlePacket(Packet &p)
Handle the given packet, i.e.
bool HasClientQuit() const
Whether the current client connected to the socket has quit.
Definition core.h:72
virtual std::unique_ptr< Packet > ReceivePacket()
Receives a packet for the given client.
Definition tcp.cpp:117
std::optional< std::string_view > FindMainScript(const ContentInfo &ci, bool md5sum)
Find a script of a ContentInfo.
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
Subdirectory
The different kinds of subdirectories OpenTTD uses.
Definition fileio_type.h:88
@ NO_DIRECTORY
A path without any base directory.
@ AI_LIBRARY_DIR
Subdirectory for all AI libraries.
@ GAME_LIBRARY_DIR
Subdirectory for all GS libraries.
@ AI_DIR
Subdirectory for all AI files.
Definition fileio_type.h:99
@ SCENARIO_DIR
Base directory for all scenarios.
Definition fileio_type.h:92
@ HEIGHTMAP_DIR
Subdirectory of scenario for heightmaps.
Definition fileio_type.h:93
@ NEWGRF_DIR
Subdirectory for all NewGRFs.
Definition fileio_type.h:97
@ BASESET_DIR
Subdirectory for all base data (base sets, intro game)
Definition fileio_type.h:96
@ GAME_DIR
Subdirectory for all game scripts.
std::optional< std::string_view > FindScenario(const ContentInfo &ci, bool md5sum)
Find a given scenario based on its unique ID.
Definition fios.cpp:661
const GRFConfig * FindGRFConfig(uint32_t grfid, FindGRFConfigMode mode, const MD5Hash *md5sum, uint32_t desired_version)
Find a NewGRF in the scanned list.
@ FGCM_EXACT
Only find Grfs matching md5sum.
uint32_t unique_id
Unique ID; either GRF ID or shortname.
bool IsValid() const
Is the information from this content info valid?
MD5Hash md5sum
The MD5 checksum.
State state
Whether the content info is selected (for download)
std::optional< std::string > GetTextfile(TextfileType type) const
Search a textfile file next to this file in the content list.
bool IsSelected() const
Is the state either selected or autoselected?
ContentType type
Type of content.
@ Invalid
The content's invalid.
@ AlreadyHere
The content is already at the client side.
@ Selected
The content has been manually selected.
@ Autoselected
The content has been selected as dependency.
Information about GRF, used in the game and (part of it) in savegames.
std::string filename
Filename - either with or without full path.
Internal entity of a packet.
Definition packet.h:41
uint8_t Recv_uint8()
Read a 8 bits integer from the packet.
Definition packet.cpp:316
Subdirectory GetContentInfoSubDir(ContentType type)
Helper to get the subdirectory a ContentInfo is located in.
Basic functions to receive and send TCP packets to/from the content server.
ContentType
The values in the enum are important; they are used as database 'keys'.
@ CONTENT_TYPE_AI_LIBRARY
The content consists of an AI library.
@ CONTENT_TYPE_BASE_SOUNDS
The content consists of base sounds.
@ CONTENT_TYPE_GAME_LIBRARY
The content consists of a GS library.
@ CONTENT_TYPE_BASE_GRAPHICS
The content consists of base graphics.
@ CONTENT_TYPE_AI
The content consists of an AI.
@ CONTENT_TYPE_SCENARIO
The content consists of a scenario.
@ CONTENT_TYPE_NEWGRF
The content consists of a NewGRF.
@ CONTENT_TYPE_BEGIN
Helper to mark the begin of the types.
@ CONTENT_TYPE_BASE_MUSIC
The content consists of base music.
@ CONTENT_TYPE_GAME
The content consists of a game script.
@ CONTENT_TYPE_END
Helper to mark the end of the types.
@ CONTENT_TYPE_HEIGHTMAP
The content consists of a heightmap.
PacketContentType
Enum with all types of TCP content packets.
@ PACKET_CONTENT_CLIENT_CONTENT
Request a content file given an internal ID.
@ PACKET_CONTENT_END
Must ALWAYS be on the end of this list!! (period)
@ PACKET_CONTENT_CLIENT_INFO_LIST
Queries the content server for a list of info of a given content type.
@ PACKET_CONTENT_CLIENT_INFO_EXTID_MD5
Queries the content server for information about a list of external IDs and MD5.
@ PACKET_CONTENT_SERVER_INFO
Reply of content server with information about content.
@ PACKET_CONTENT_SERVER_CONTENT
Reply with the content of the given ID.
@ PACKET_CONTENT_CLIENT_INFO_ID
Queries the content server for information about a list of internal IDs.
@ PACKET_CONTENT_CLIENT_INFO_EXTID
Queries the content server for information about a list of external IDs.
TextfileType
Additional text files accompanying Tar archives.