QcComponentFrames Namespace
The components of a saved entry (decision E-420): after the entry's header a count, then per component quint16 id, quint16 version, quint32 length, payload. More...
| Header: | #include <server/storage/QcComponentFrames.h> |
Classes
| class | FieldReader |
| struct | Known |
| struct | ReadComponents |
| class | Writer |
Variables
| const quint16 | firstModId |
| const quint32 | maxComponents |
| const quint32 | maxKept |
| const quint32 | maxKnown |
| const quint32 | maxLength |
Functions
| void | patchLength(QDataStream &stream, qint64 at, quint32 length) |
| std::optional<QcComponentFrames::ReadComponents> | read(QDataStream &stream, std::initializer_list<QcComponentFrames::Known> known, quint32 lengthLimit = maxLength) |
| std::optional<QByteArray> | readRaw(QDataStream &stream, qint64 length) |
| std::optional<QString> | readText(QDataStream &stream, qsizetype maxChars) |
Detailed Description
A reader skips what it does not know by its length and keeps it (QcEntityComponent), so saving again loses nothing.
Versions of a component only append fields: version n+1 is version n followed by new fields. A reader of version n reads an older payload with defaults for the fields it lacks, and of a newer one the fields it knows; the rest is kept as the component's tail and written back after them under the newer version. A change that cannot be made by appending is a new component id.
The tail goes back unchanged while the fields before it may have changed at runtime (a creature lost health). So a newer field must never depend on the contents of older fields (no count of an older list, no checksum, no value relative to an older one): such a field is a new component id.
Classes
class FieldReader
Reads the fields of a known component of a version from a stream: a reference to a callable that outlives the read, without the allocation of a std::function. More...
class Known
A component this version reads: its id, the version it writes and its reader. More...
class ReadComponents
What read() keeps of one entry's components besides the known fields, and how many unknown components it dropped beyond maxKept. More...
class Writer
Writes the components of one entry straight into the entry's stream: the known ones in the order they are added, each followed by its kept tail, then the kept components of unknown ids. More...
Variable Documentation
const quint16 QcComponentFrames::firstModId
The ids of components (QcEntityCodec::Component) and of block-entity tables (QcBlockEntityRecord::Table) from here on belong to mods, those below to the game (decision E-440). Either kind of unknown id is kept as it is.
const quint32 QcComponentFrames::maxComponents
Components of one entry at most; more is damaged data. Every version and every mod keeps this, together with the two limits below that make it hold for what a version writes back.
const quint32 QcComponentFrames::maxKept
Components of unknown ids one entry keeps at most; beyond that they are dropped with a warning, so the kept ones and the known ones of any version always fit into maxComponents.
const quint32 QcComponentFrames::maxKnown
Known components one kind writes at most, in any version (QcEntityCodec::Component).
const quint32 QcComponentFrames::maxLength
Bytes of one component at most; a valid world never comes close.
Function Documentation
void QcComponentFrames::patchLength(QDataStream &stream, qint64 at, quint32 length)
Overwrites the placeholder length at byte at of stream (which writes to a seekable device) with length: in place in the bytes of a QBuffer, else by seeking there and back.
std::optional<QcComponentFrames::ReadComponents> QcComponentFrames::read(QDataStream &stream, std::initializer_list<QcComponentFrames::Known> known, quint32 lengthLimit = maxLength)
Reads the components of one entry from stream: those of an id in known with its reader, read in place, the others kept as they are (beyond maxKept dropped and counted). Of a newer version of a known component the bytes after the known fields are kept as its tail. lengthLimit bounds one component (maxLength for entities; the tables of a chunk's block entities allow more, QcBlockEntityCodec). Returns the kept components and the number dropped; std::nullopt for damaged data: more components or longer ones than allowed, a length beyond the data, an id twice, version 0, a reader that fails or reads beyond its component, an older or the current version that holds more than its fields.
std::optional<QByteArray> QcComponentFrames::readRaw(QDataStream &stream, qint64 length)
Reads the raw bytes of length that follow in stream, checked against the data left before anything is allocated. Returns the bytes; std::nullopt when fewer are left or length is negative.
std::optional<QString> QcComponentFrames::readText(QDataStream &stream, qsizetype maxChars)
Reads from stream a QString written by QDataStream (byte length, then UTF-16) after checking its length: a damaged length of up to 4 GB is never allocated. Returns the text; std::nullopt for a damaged length or a text longer than maxChars (the stream turns corrupt).