From 02bd52041b9773e7f6b64ac940be70919a968512 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Sat, 29 Jun 2024 13:13:59 +0200 Subject: [PATCH] extend map format --- Mods/vcmi/config/vcmi/english.json | 1 + Mods/vcmi/config/vcmi/german.json | 1 + client/lobby/SelectionTab.cpp | 11 +++++- client/windows/CMapOverview.cpp | 12 +++++-- client/windows/CMapOverview.h | 4 ++- config/widgets/mapOverview.json | 42 ++++++++++++++++++++--- lib/campaign/CampaignHandler.cpp | 8 +++++ lib/campaign/CampaignState.h | 11 ++++++ lib/mapping/CMapHeader.h | 11 ++++++ lib/mapping/MapFormatH3M.cpp | 4 +++ lib/mapping/MapFormatJson.cpp | 5 ++- lib/serializer/ESerializationVersion.h | 3 +- mapeditor/mapsettings/generalsettings.cpp | 8 +++++ mapeditor/mapsettings/generalsettings.ui | 40 +++++++++++++++++++++ 14 files changed, 151 insertions(+), 10 deletions(-) diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json index 47f490262..83be69324 100644 --- a/Mods/vcmi/config/vcmi/english.json +++ b/Mods/vcmi/config/vcmi/english.json @@ -72,6 +72,7 @@ "vcmi.lobby.noUnderground" : "no underground", "vcmi.lobby.sortDate" : "Sorts maps by change date", "vcmi.lobby.backToLobby" : "Return to lobby", + "vcmi.lobby.author" : "Author", "vcmi.lobby.login.title" : "VCMI Online Lobby", "vcmi.lobby.login.username" : "Username:", diff --git a/Mods/vcmi/config/vcmi/german.json b/Mods/vcmi/config/vcmi/german.json index 8aabb4e29..cda676453 100644 --- a/Mods/vcmi/config/vcmi/german.json +++ b/Mods/vcmi/config/vcmi/german.json @@ -72,6 +72,7 @@ "vcmi.lobby.noUnderground" : "Kein Untergrund", "vcmi.lobby.sortDate" : "Ordnet Karten nach Änderungsdatum", "vcmi.lobby.backToLobby" : "Zur Lobby zurückkehren", + "vcmi.lobby.author" : "Author", "vcmi.lobby.login.title" : "VCMI Online Lobby", "vcmi.lobby.login.username" : "Benutzername:", diff --git a/client/lobby/SelectionTab.cpp b/client/lobby/SelectionTab.cpp index 918bfc8cd..b4f86a2ce 100644 --- a/client/lobby/SelectionTab.cpp +++ b/client/lobby/SelectionTab.cpp @@ -44,6 +44,7 @@ #include "../../lib/mapping/CMapHeader.h" #include "../../lib/mapping/MapFormat.h" #include "../../lib/TerrainHandler.h" +#include "../../lib/TextOperations.h" bool mapSorter::operator()(const std::shared_ptr aaa, const std::shared_ptr bbb) { @@ -391,7 +392,15 @@ void SelectionTab::showPopupWindow(const Point & cursorPosition) return; if(!curItems[py]->isFolder) - GH.windows().createAndPushWindow(curItems[py]->getNameTranslated(), curItems[py]->fullFileURI, curItems[py]->date, ResourcePath(curItems[py]->fileURI), tabType); + GH.windows().createAndPushWindow( + curItems[py]->getNameTranslated(), + curItems[py]->fullFileURI, + tabType == ESelectionScreen::newGame && curItems[py]->mapHeader->creationDateTime ? TextOperations::getFormattedDateTimeLocal(curItems[py]->mapHeader->creationDateTime) : curItems[py]->date, + curItems[py]->mapHeader->author.toString() + (!curItems[py]->mapHeader->authorContact.toString().empty() ? (" <" + curItems[py]->mapHeader->authorContact.toString() + ">") : ""), + curItems[py]->mapHeader->mapVersion.toString(), + ResourcePath(curItems[py]->fileURI), + tabType + ); else CRClickPopup::createAndPush(curItems[py]->folderName); } diff --git a/client/windows/CMapOverview.cpp b/client/windows/CMapOverview.cpp index adb3ccafc..d2fae75df 100644 --- a/client/windows/CMapOverview.cpp +++ b/client/windows/CMapOverview.cpp @@ -43,8 +43,8 @@ #include "../../lib/rmg/CMapGenOptions.h" #include "../../lib/Languages.h" -CMapOverview::CMapOverview(std::string mapName, std::string fileName, std::string date, ResourcePath resource, ESelectionScreen tabType) - : CWindowObject(BORDERED | RCLICK_POPUP), resource(resource), mapName(mapName), fileName(fileName), date(date), tabType(tabType) +CMapOverview::CMapOverview(std::string mapName, std::string fileName, std::string date, std::string author, std::string version, ResourcePath resource, ESelectionScreen tabType) + : CWindowObject(BORDERED | RCLICK_POPUP), resource(resource), mapName(mapName), fileName(fileName), date(date), author(author), version(version), tabType(tabType) { OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE; @@ -204,6 +204,14 @@ CMapOverviewWidget::CMapOverviewWidget(CMapOverview& parent): else w->setText(p.date); } + if(auto w = widget("author")) + { + w->setText(p.author.empty() ? "-" : p.author); + } + if(auto w = widget("version")) + { + w->setText(p.version); + } if(auto w = widget("noUnderground")) { if(minimaps.size() == 0) diff --git a/client/windows/CMapOverview.h b/client/windows/CMapOverview.h index bbd0b0e79..fbb70a6df 100644 --- a/client/windows/CMapOverview.h +++ b/client/windows/CMapOverview.h @@ -53,7 +53,9 @@ public: const std::string mapName; const std::string fileName; const std::string date; + const std::string author; + const std::string version; const ESelectionScreen tabType; - CMapOverview(std::string mapName, std::string fileName, std::string date, ResourcePath resource, ESelectionScreen tabType); + CMapOverview(std::string mapName, std::string fileName, std::string date, std::string author, std::string version, ResourcePath resource, ESelectionScreen tabType); }; diff --git a/config/widgets/mapOverview.json b/config/widgets/mapOverview.json index 9aff4aab7..93b536906 100644 --- a/config/widgets/mapOverview.json +++ b/config/widgets/mapOverview.json @@ -7,7 +7,7 @@ "name": "background", "type": "texture", "image": "DIBOXBCK", - "rect": {"w": 428, "h": 379} + "rect": {"w": 428, "h": 429} }, { "type": "boxWithBackground", @@ -34,6 +34,15 @@ "text": "", "position": {"x": 214, "y": 40} }, + { + "type": "label", + "name": "version", + "font": "small", + "alignment": "right", + "color": "green", + "text": "", + "position": {"x": 418, "y": 40} + }, { "type": "boxWithBackground", "rect": {"x": 5, "y": 55, "w": 418, "h": 20} @@ -115,12 +124,37 @@ "font": "medium", "alignment": "center", "color": "yellow", - "text": "vcmi.lobby.filepath", + "text": "vcmi.lobby.author", "position": {"x": 214, "y": 314} }, { "type": "boxWithBackground", - "rect": {"x": 5, "y": 329, "w": 418, "h": 45} + "rect": {"x": 5, "y": 329, "w": 418, "h": 20} + }, + { + "type": "label", + "name": "author", + "font": "small", + "alignment": "center", + "color": "white", + "text": "", + "position": {"x": 214, "y": 339} + }, + { + "type": "boxWithBackground", + "rect": {"x": 5, "y": 354, "w": 418, "h": 20} + }, + { + "type": "label", + "font": "medium", + "alignment": "center", + "color": "yellow", + "text": "vcmi.lobby.filepath", + "position": {"x": 214, "y": 364} + }, + { + "type": "boxWithBackground", + "rect": {"x": 5, "y": 379, "w": 418, "h": 45} }, { "type": "textBox", @@ -129,7 +163,7 @@ "alignment": "center", "color": "white", "text": "", - "rect": {"x": 10, "y": 334, "w": 408, "h": 35} + "rect": {"x": 10, "y": 384, "w": 408, "h": 35} } ], diff --git a/lib/campaign/CampaignHandler.cpp b/lib/campaign/CampaignHandler.cpp index 89623fd52..686dbe982 100644 --- a/lib/campaign/CampaignHandler.cpp +++ b/lib/campaign/CampaignHandler.cpp @@ -151,6 +151,10 @@ void CampaignHandler::readHeaderFromJson(CampaignHeader & ret, JsonNode & reader ret.numberOfScenarios = reader["scenarios"].Vector().size(); ret.name.appendTextID(reader["name"].String()); ret.description.appendTextID(reader["description"].String()); + ret.author.appendRawString(reader["author"].String()); + ret.authorContact.appendRawString(reader["authorContact"].String()); + ret.mapVersion.appendRawString(reader["mapVersion"].String()); + ret.creationDateTime = reader["creationDateTime"].Integer(); ret.difficultyChosenByPlayer = reader["allowDifficultySelection"].Bool(); ret.music = AudioPath::fromJson(reader["music"]); ret.filename = filename; @@ -385,6 +389,10 @@ void CampaignHandler::readHeaderFromMemory( CampaignHeader & ret, CBinaryReader ret.loadLegacyData(campId); ret.name.appendTextID(readLocalizedString(ret, reader, filename, modName, encoding, "name")); ret.description.appendTextID(readLocalizedString(ret, reader, filename, modName, encoding, "description")); + ret.author.appendRawString(""); + ret.authorContact.appendRawString(""); + ret.mapVersion.appendRawString(""); + ret.creationDateTime = 0; if (ret.version > CampaignVersion::RoE) ret.difficultyChosenByPlayer = reader.readInt8(); else diff --git a/lib/campaign/CampaignState.h b/lib/campaign/CampaignState.h index 2e66c0567..a24383618 100644 --- a/lib/campaign/CampaignState.h +++ b/lib/campaign/CampaignState.h @@ -81,6 +81,10 @@ class DLL_LINKAGE CampaignHeader : public boost::noncopyable CampaignRegions campaignRegions; MetaString name; MetaString description; + MetaString author; + MetaString authorContact; + MetaString mapVersion; + std::time_t creationDateTime; AudioPath music; std::string filename; std::string modName; @@ -114,6 +118,13 @@ public: h & numberOfScenarios; h & name; h & description; + if (h.version >= Handler::Version::MAP_FORMAT_ADDITIONAL_INFOS) + { + h & author; + h & authorContact; + h & mapVersion; + h & creationDateTime; + } h & difficultyChosenByPlayer; h & filename; h & modName; diff --git a/lib/mapping/CMapHeader.h b/lib/mapping/CMapHeader.h index d0992b6f2..2f544b8cd 100644 --- a/lib/mapping/CMapHeader.h +++ b/lib/mapping/CMapHeader.h @@ -230,6 +230,10 @@ public: MetaString name; MetaString description; EMapDifficulty difficulty; + MetaString author; + MetaString authorContact; + MetaString mapVersion; + std::time_t creationDateTime; /// Specifies the maximum level to reach for a hero. A value of 0 states that there is no /// maximum level for heroes. This is the default value. ui8 levelLimit; @@ -263,6 +267,13 @@ public: h & mods; h & name; h & description; + if (h.version >= Handler::Version::MAP_FORMAT_ADDITIONAL_INFOS) + { + h & author; + h & authorContact; + h & mapVersion; + h & creationDateTime; + } h & width; h & height; h & twoLevel; diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index c9dab731e..28947e167 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -219,6 +219,10 @@ void CMapLoaderH3M::readHeader() mapHeader->twoLevel = reader->readBool(); mapHeader->name.appendTextID(readLocalizedString("header.name")); mapHeader->description.appendTextID(readLocalizedString("header.description")); + mapHeader->author.appendRawString(""); + mapHeader->authorContact.appendRawString(""); + mapHeader->mapVersion.appendRawString(""); + mapHeader->creationDateTime = 0; mapHeader->difficulty = static_cast(reader->readInt8Checked(0, 4)); if(features.levelAB) diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index a6ffd69c4..eaa966959 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -311,6 +311,10 @@ void CMapFormatJson::serializeHeader(JsonSerializeFormat & handler) { handler.serializeStruct("name", mapHeader->name); handler.serializeStruct("description", mapHeader->description); + handler.serializeStruct("author", mapHeader->author); + handler.serializeStruct("authorContact", mapHeader->authorContact); + handler.serializeStruct("mapVersion", mapHeader->mapVersion); + handler.serializeInt("creationDateTime", mapHeader->creationDateTime, 0); handler.serializeInt("heroLevelLimit", mapHeader->levelLimit, 0); //todo: support arbitrary percentage @@ -855,7 +859,6 @@ void CMapLoaderJson::readHeader(const bool complete) //todo: multilevel map load support { auto levels = handler.enterStruct("mapLevels"); - { auto surface = handler.enterStruct("surface"); handler.serializeInt("height", mapHeader->height); diff --git a/lib/serializer/ESerializationVersion.h b/lib/serializer/ESerializationVersion.h index 0072b0f5b..d7d830afc 100644 --- a/lib/serializer/ESerializationVersion.h +++ b/lib/serializer/ESerializationVersion.h @@ -55,6 +55,7 @@ enum class ESerializationVersion : int32_t COMPACT_INTEGER_SERIALIZATION, // 845 - serialize integers in forms similar to protobuf REMOVE_FOG_OF_WAR_POINTER, // 846 - fog of war is serialized as reference instead of pointer SIMPLE_TEXT_CONTAINER_SERIALIZATION, // 847 - text container is serialized using common routine instead of custom approach + MAP_FORMAT_ADDITIONAL_INFOS, // 848 - serialize new infos in map format - CURRENT = SIMPLE_TEXT_CONTAINER_SERIALIZATION + CURRENT = MAP_FORMAT_ADDITIONAL_INFOS }; diff --git a/mapeditor/mapsettings/generalsettings.cpp b/mapeditor/mapsettings/generalsettings.cpp index 74f405232..eda742d7e 100644 --- a/mapeditor/mapsettings/generalsettings.cpp +++ b/mapeditor/mapsettings/generalsettings.cpp @@ -29,6 +29,10 @@ void GeneralSettings::initialize(MapController & c) AbstractSettings::initialize(c); ui->mapNameEdit->setText(QString::fromStdString(controller->map()->name.toString())); ui->mapDescriptionEdit->setPlainText(QString::fromStdString(controller->map()->description.toString())); + ui->authorEdit->setText(QString::fromStdString(controller->map()->author.toString())); + ui->authorContactEdit->setText(QString::fromStdString(controller->map()->authorContact.toString())); + ui->mapCreationDateTimeEdit->setDateTime(QDateTime::fromTime_t(controller->map()->creationDateTime)); + ui->mapVersionEdit->setText(QString::fromStdString(controller->map()->mapVersion.toString())); ui->heroLevelLimit->setValue(controller->map()->levelLimit); ui->heroLevelLimitCheck->setChecked(controller->map()->levelLimit); @@ -61,6 +65,10 @@ void GeneralSettings::update() { controller->map()->name = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller->map(), TextIdentifier("header", "name"), ui->mapNameEdit->text().toStdString())); controller->map()->description = MetaString::createFromTextID(mapRegisterLocalizedString("map", *controller->map(), TextIdentifier("header", "description"), ui->mapDescriptionEdit->toPlainText().toStdString())); + controller->map()->author = MetaString::createFromRawString(ui->authorEdit->toPlainText().toStdString()); + controller->map()->authorContact = MetaString::createFromRawString(ui->authorContactEdit->toPlainText().toStdString()); + controller->map()->creationDateTime = ui->mapCreationDateTimeEdit->dateTime().toTime_t(); + controller->map()->mapVersion = MetaString::createFromRawString(ui->mapVersionEdit->toPlainText().toStdString()); if(ui->heroLevelLimitCheck->isChecked()) controller->map()->levelLimit = ui->heroLevelLimit->value(); else diff --git a/mapeditor/mapsettings/generalsettings.ui b/mapeditor/mapsettings/generalsettings.ui index e9759ff4f..1e8435100 100644 --- a/mapeditor/mapsettings/generalsettings.ui +++ b/mapeditor/mapsettings/generalsettings.ui @@ -46,6 +46,46 @@ + + + + Author + + + + + + + + + + Author contact (e.g. email) + + + + + + + + + + Map Creation Time + + + + + + + + + + Map Version + + + + + +