Sort out version info
The idea is to have the following version information included: - 1-component save version - 2-component under the hood but the minor component shouldn't ever change again - see currentVersionMajor in GameSave.cpp - 1-component website API version - again, currently 2-component because that's what the website code expects - see apiVersion in requestmanager/Common.cpp - 2-component display version, entirely cosmetic - exposed as meson options display_version_major and display_version_minor - see APP_VERSION in Config.template.h - 1-component business logic version aka build number - exposed as meson option build_num - see APP_VERSION in Config.template.h - variant id aka mod id, tightly coupled with the build number - exposed as meson option mod_id - see MOD_ID in Config.template.h - display and business logic versions repeated for the upstream - exposed as meson options upstream_version_major, upstream_version_minor, and upstream_build_num - we'll have to update these alongside display_version_major, display_version_minor, and build_num, but mod owners can just merge our changes - see UPSTREAM_VERSION in Config.template.h - update channel, makes sense in the context of the variant (and yes, this would later enable mod snapshots) - currently not exposed as a meson option but derived from meson options snapshot and mod_id - see IDENT_RELTYPE in Config.template.h - vcs tag aka git commit hash - set by build.sh in ghactions workflows - see VCS_TAG in VcsTag.tempalte.h Rather importantly, the save and website API versions are now allowed to change independently of the display version. These changes also allowed me to remove the ugly sed hacks in build.sh used to provision some manifest files; they are now provisioned by meson. Also add version info for windows and android.
This commit is contained in:
parent
7f0f9ad132
commit
7fc3fb4c15
36
.github/build.sh
vendored
36
.github/build.sh
vendored
@ -87,18 +87,6 @@ function inplace_sed() {
|
||||
fi
|
||||
}
|
||||
|
||||
function subst_version() {
|
||||
local path=$1
|
||||
if [[ $BSH_HOST_PLATFORM == darwin ]]; then
|
||||
inplace_sed "s|SUBST_MACOS_MIN_VER|$macos_min_ver|g" $path
|
||||
else
|
||||
inplace_sed "s|SUBST_DATE|$(date --iso-8601)|g" $path
|
||||
fi
|
||||
inplace_sed "s|SUBST_SAVE_VERSION|$save_version|g" $path
|
||||
inplace_sed "s|SUBST_MINOR_VERSION|$minor_version|g" $path
|
||||
inplace_sed "s|SUBST_BUILD_NUM|$build_num|g" $path
|
||||
}
|
||||
|
||||
if [[ $BSH_HOST_PLATFORM == android ]]; then
|
||||
android_platform=android-30
|
||||
if [[ -z "${JAVA_HOME_8_X64-}" ]]; then
|
||||
@ -189,6 +177,11 @@ meson_configure=meson$'\t'setup
|
||||
if [[ $BSH_DEBUG_RELEASE == release ]]; then
|
||||
meson_configure+=$'\t'-Dbuildtype=debugoptimized
|
||||
fi
|
||||
if [[ $BSH_HOST_PLATFORM == darwin ]]; then
|
||||
meson_configure+=$'\t'-Dmanifest_macos_min_ver=$macos_min_ver
|
||||
else
|
||||
meson_configure+=$'\t'-Dmanifest_date=$(date --iso-8601)
|
||||
fi
|
||||
meson_configure+=$'\t'-Dapp_name=$APP_NAME
|
||||
meson_configure+=$'\t'-Dapp_comment=$APP_COMMENT
|
||||
meson_configure+=$'\t'-Dapp_exe=$APP_EXE
|
||||
@ -251,19 +244,10 @@ fi
|
||||
if [[ $RELEASE_TYPE == stable ]]; then
|
||||
stable_or_beta=yes
|
||||
fi
|
||||
set +e
|
||||
save_version=$(cat src/Config.template.h | sed -n 's/constexpr int SAVE_VERSION * = \([^;]*\);/\1/p')
|
||||
minor_version=$(cat src/Config.template.h | sed -n 's/constexpr int MINOR_VERSION * = \([^;]*\);/\1/p')
|
||||
build_num=$(cat src/Config.template.h | sed -n 's/constexpr int BUILD_NUM * = \([^;]*\);/\1/p')
|
||||
if [[ -z ${save_version-} ]] || [[ -z ${minor_version-} ]] || [[ -z ${build_num-} ]]; then
|
||||
>&2 echo "failed to extract version from Config.template.h"
|
||||
exit 1
|
||||
fi
|
||||
set -e
|
||||
if [[ $stable_or_beta == yes ]] && [[ $MOD_ID != 0 ]]; then
|
||||
save_version=$(echo $RELEASE_NAME | cut -d '.' -f 1)
|
||||
minor_version=$(echo $RELEASE_NAME | cut -d '.' -f 2)
|
||||
build_num=$(echo $RELEASE_NAME | cut -d '.' -f 3)
|
||||
if [[ $stable_or_beta == yes ]]; then
|
||||
meson_configure+=$'\t'-Ddisplay_version_major=$(echo $RELEASE_NAME | cut -d '.' -f 1)
|
||||
meson_configure+=$'\t'-Ddisplay_version_minor=$(echo $RELEASE_NAME | cut -d '.' -f 2)
|
||||
meson_configure+=$'\t'-Dbuild_num=$(echo $RELEASE_NAME | cut -d '.' -f 3)
|
||||
fi
|
||||
if [[ $RELEASE_TYPE == snapshot ]]; then
|
||||
meson_configure+=$'\t'-Dsnapshot=true
|
||||
@ -426,7 +410,6 @@ if [[ $PACKAGE_MODE == dmg ]]; then
|
||||
mkdir $appdir
|
||||
mkdir $appdir/Contents
|
||||
cp resources/Info.plist $appdir/Contents/Info.plist
|
||||
subst_version $appdir/Contents/Info.plist
|
||||
mkdir $appdir/Contents/MacOS
|
||||
cp $APP_EXE $appdir/Contents/MacOS/$APP_EXE
|
||||
mkdir $appdir/Contents/Resources
|
||||
@ -471,7 +454,6 @@ elif [[ $PACKAGE_MODE == appimage ]]; then
|
||||
cp ../resources/icon_exe.svg $appdir/$APP_VENDOR-$APP_EXE.svg
|
||||
cp resources/powder.desktop $appdir/$APP_ID.desktop
|
||||
cp resources/appdata.xml $appdir/usr/share/metainfo/$APP_ID.appdata.xml
|
||||
subst_version $appdir/usr/share/metainfo/$APP_ID.appdata.xml
|
||||
cp $appdir/$APP_VENDOR-$APP_EXE.svg $appdir/usr/share/icons/$APP_VENDOR-$APP_EXE.svg
|
||||
cp $appdir/$APP_ID.desktop $appdir/usr/share/applications/$APP_ID.desktop
|
||||
./appimagetool $appdir $ASSET_PATH
|
||||
|
@ -2,8 +2,8 @@
|
||||
<manifest
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="@APPID@"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0"
|
||||
android:versionCode="@BUILD_NUM@"
|
||||
android:versionName="@DISPLAY_VERSION_MAJOR@.@DISPLAY_VERSION_MINOR@.@BUILD_NUM@"
|
||||
android:installLocation="auto"
|
||||
>
|
||||
<uses-sdk
|
||||
|
@ -43,6 +43,48 @@ option(
|
||||
value: 0,
|
||||
description: 'Snapshot ID, only relevant if \'snapshot\' is true'
|
||||
)
|
||||
option(
|
||||
'display_version_major',
|
||||
type: 'integer',
|
||||
min: 0,
|
||||
value: 97,
|
||||
description: 'Major component of the display version, should more or less map to the MINOR version in semantic versioning'
|
||||
)
|
||||
option(
|
||||
'display_version_minor',
|
||||
type: 'integer',
|
||||
min: 0,
|
||||
value: 0,
|
||||
description: 'Minor component of the display version, should more or less map to the PATCH version in semantic versioning'
|
||||
)
|
||||
option(
|
||||
'build_num',
|
||||
type: 'integer',
|
||||
min: 0,
|
||||
value: 352,
|
||||
description: 'Build number, should be strictly monotonously increasing across public releases'
|
||||
)
|
||||
option(
|
||||
'upstream_version_major',
|
||||
type: 'integer',
|
||||
min: 0,
|
||||
value: 97,
|
||||
description: 'Major component of the upstream display version, mod owners should not change this but merge upstream changes to it'
|
||||
)
|
||||
option(
|
||||
'upstream_version_minor',
|
||||
type: 'integer',
|
||||
min: 0,
|
||||
value: 0,
|
||||
description: 'Minor component of the upstream display version, mod owners should not change this but merge upstream changes to it'
|
||||
)
|
||||
option(
|
||||
'upstream_build_num',
|
||||
type: 'integer',
|
||||
min: 0,
|
||||
value: 352,
|
||||
description: 'Upstream build number, mod owners should not change this but merge upstream changes to it'
|
||||
)
|
||||
option(
|
||||
'mod_id',
|
||||
type: 'integer',
|
||||
@ -227,3 +269,21 @@ option(
|
||||
value: 'static_release_only',
|
||||
description: 'Enable VCS tag resolution, introduces an always-stale custom target'
|
||||
)
|
||||
option(
|
||||
'manifest_copyright',
|
||||
type: 'string',
|
||||
value: 'Copyright © 2008-2011 Stanislaw K Skowrenek, Copyright © 2011-2023 Simon Robertshaw, Copyright © 2016-2023 jacob1',
|
||||
description: 'Copyright string, don\'t take too seriously, subject to change'
|
||||
)
|
||||
option(
|
||||
'manifest_macos_min_ver',
|
||||
type: 'string',
|
||||
value: '',
|
||||
description: 'MacOS minimum allowed platform version string, used by ghactions workflows, not useful otherwise'
|
||||
)
|
||||
option(
|
||||
'manifest_date',
|
||||
type: 'string',
|
||||
value: '',
|
||||
description: 'Build date string, used by ghactions workflows, not useful otherwise'
|
||||
)
|
||||
|
@ -18,7 +18,7 @@
|
||||
<key>CFBundleIconFile</key>
|
||||
<string>icon_exe.icns</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright © 2008-2011 Stanislaw K Skowrenek, Copyright © 2011-2023 Simon Robertshaw, Copyright © 2016-2023 jacob1</string>
|
||||
<string>@MANIFEST_COPYRIGHT@</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
@ -57,13 +57,13 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>SUBST_SAVE_VERSION.SUBST_MINOR_VERSION</string>
|
||||
<string>@DISPLAY_VERSION_MAJOR@.@DISPLAY_VERSION_MINOR@</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>SUBST_SAVE_VERSION.SUBST_MINOR_VERSION (build SUBST_BUILD_NUM)</string>
|
||||
<string>@DISPLAY_VERSION_MAJOR@.@DISPLAY_VERSION_MINOR@ (build @BUILD_NUM@)</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>SUBST_MACOS_MIN_VER</string>
|
||||
<string>@MANIFEST_MACOS_MIN_VER@</string>
|
||||
<key>NSPrincipalClass</key>
|
||||
<string>NSApplication</string>
|
||||
</dict>
|
||||
|
@ -29,6 +29,6 @@
|
||||
<url type="bugtracker">https://github.com/The-Powder-Toy/The-Powder-Toy/issues</url>
|
||||
<url type="help">https://powdertoy.co.uk/Wiki/W/Main_Page.html</url>
|
||||
<releases>
|
||||
<release date="SUBST_DATE" version="SUBST_SAVE_VERSION.SUBST_MINOR_VERSION.SUBST_BUILD_NUM" />
|
||||
<release date="@MANIFEST_DATE@" version="@DISPLAY_VERSION_MAJOR@.@DISPLAY_VERSION_MINOR@.@BUILD_NUM@" />
|
||||
</releases>
|
||||
</component>
|
||||
|
@ -52,8 +52,18 @@ if host_platform == 'windows'
|
||||
command: command,
|
||||
) }
|
||||
endforeach
|
||||
rc_conf_data = configuration_data()
|
||||
rc_conf_data.merge_from(conf_data)
|
||||
rc_conf_data.set('RESOUCE_H', join_paths(meson.current_source_dir(), 'resource.h'))
|
||||
rc_conf_data.set('WINUTF8_XML', join_paths(meson.current_source_dir(), 'winutf8.xml'))
|
||||
rc_conf_data.set('ICON_EXE_ICO', join_paths(meson.current_build_dir(), 'icon_exe.ico'))
|
||||
rc_conf_data.set('ICON_CPS_ICO', join_paths(meson.current_build_dir(), 'icon_cps.ico'))
|
||||
powder_files += windows_mod.compile_resources(
|
||||
'powder-res.rc',
|
||||
configure_file(
|
||||
input: 'powder-res.template.rc',
|
||||
output: 'powder-res.rc',
|
||||
configuration: rc_conf_data,
|
||||
),
|
||||
depends: [
|
||||
generated_win_icos['icon_exe'],
|
||||
generated_win_icos['icon_cps'],
|
||||
|
@ -1,6 +0,0 @@
|
||||
#include "resource.h"
|
||||
#include <winuser.h>
|
||||
|
||||
IDI_ICON ICON DISCARDABLE "icon_exe.ico"
|
||||
IDI_DOC_ICON ICON DISCARDABLE "icon_cps.ico"
|
||||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "winutf8.xml"
|
32
resources/powder-res.template.rc
Normal file
32
resources/powder-res.template.rc
Normal file
@ -0,0 +1,32 @@
|
||||
#include "@RESOUCE_H@"
|
||||
#include <winuser.h>
|
||||
#include <winver.h>
|
||||
#include <ntdef.h>
|
||||
|
||||
IDI_ICON ICON DISCARDABLE "@ICON_EXE_ICO@"
|
||||
IDI_DOC_ICON ICON DISCARDABLE "@ICON_CPS_ICO@"
|
||||
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "@WINUTF8_XML@"
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION @DISPLAY_VERSION_MAJOR@,@DISPLAY_VERSION_MINOR@,0,@BUILD_NUM@
|
||||
PRODUCTVERSION @DISPLAY_VERSION_MAJOR@,@DISPLAY_VERSION_MINOR@,0,@BUILD_NUM@
|
||||
{
|
||||
BLOCK "StringFileInfo"
|
||||
{
|
||||
BLOCK "040904b0"
|
||||
{
|
||||
VALUE "CompanyName", "https://powdertoy.co.uk/\0"
|
||||
VALUE "FileDescription", "@APPCOMMENT@\0"
|
||||
VALUE "FileVersion", "@DISPLAY_VERSION_MAJOR@.@DISPLAY_VERSION_MINOR@.0.@BUILD_NUM@\0"
|
||||
VALUE "OriginalFilename", "@APPEXE@.exe\0"
|
||||
VALUE "LegalCopyright", "@MANIFEST_COPYRIGHT@\0"
|
||||
VALUE "ProductName", "@APPNAME@\0"
|
||||
VALUE "ProductVersion", "@DISPLAY_VERSION_MAJOR@.@DISPLAY_VERSION_MINOR@.0.@BUILD_NUM@\0"
|
||||
VALUE "InternalName", "@APPID@\0"
|
||||
}
|
||||
}
|
||||
BLOCK "VarFileInfo"
|
||||
{
|
||||
VALUE "Translation", 0x409, 65001
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "VcsTag.h"
|
||||
#include "common/Version.h"
|
||||
|
||||
constexpr bool SET_WINDOW_ICON = @SET_WINDOW_ICON@;
|
||||
constexpr bool DEBUG = @DEBUG@;
|
||||
@ -44,13 +45,18 @@ constexpr char APPID[] = "@APPID@";
|
||||
constexpr char APPDATA[] = "@APPDATA@";
|
||||
constexpr char APPVENDOR[] = "@APPVENDOR@";
|
||||
|
||||
constexpr int SAVE_VERSION = 97;
|
||||
constexpr int MINOR_VERSION = 0;
|
||||
constexpr int BUILD_NUM = 352;
|
||||
constexpr int SNAPSHOT_ID = @SNAPSHOT_ID@;
|
||||
constexpr int MOD_ID = @MOD_ID@;
|
||||
constexpr int FUTURE_SAVE_VERSION = 98;
|
||||
constexpr int FUTURE_MINOR_VERSION = 0;
|
||||
|
||||
struct DisplayVersionWithBuild
|
||||
{
|
||||
Version<2> displayVersion;
|
||||
size_t build;
|
||||
};
|
||||
constexpr DisplayVersionWithBuild APP_VERSION = { { @DISPLAY_VERSION_MAJOR@, @DISPLAY_VERSION_MINOR@ }, @BUILD_NUM@ };
|
||||
constexpr DisplayVersionWithBuild UPSTREAM_VERSION = { { @UPSTREAM_VERSION_MAJOR@, @UPSTREAM_VERSION_MINOR@ }, @UPSTREAM_BUILD_NUM@ };
|
||||
|
||||
constexpr auto DISPLAY_VERSION = APP_VERSION.displayVersion;
|
||||
|
||||
constexpr char IDENT_RELTYPE = SNAPSHOT ? 'S' : (BETA ? 'B' : 'R');
|
||||
|
||||
|
@ -325,8 +325,8 @@ ByteString Client::AddStamp(std::unique_ptr<GameSave> saveData)
|
||||
}
|
||||
saveData->authors = stampInfo;
|
||||
|
||||
auto [ fromNewerVersion, gameData ] = saveData->Serialise();
|
||||
(void)fromNewerVersion;
|
||||
std::vector<char> gameData;
|
||||
std::tie(std::ignore, gameData) = saveData->Serialise();
|
||||
if (!gameData.size())
|
||||
return "";
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "simulation/Simulation.h"
|
||||
#include "simulation/ElementClasses.h"
|
||||
#include "common/tpt-compat.h"
|
||||
#include "common/Version.h"
|
||||
#include "bson/BSON.h"
|
||||
#include "graphics/Renderer.h"
|
||||
#include "Config.h"
|
||||
@ -16,6 +15,9 @@
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
constexpr auto currentVersionMajor = 97;
|
||||
constexpr auto nextVersionMajor = currentVersionMajor + 1;
|
||||
|
||||
static void ConvertJsonToBson(bson *b, Json::Value j, int depth = 0);
|
||||
static void ConvertBsonToJson(bson_iterator *b, Json::Value *j, int depth = 0);
|
||||
static void CheckBsonFieldUser(bson_iterator iter, const char *field, unsigned char **data, unsigned int *fieldLen);
|
||||
@ -326,6 +328,9 @@ static void CheckBsonFieldFloat(bson_iterator iter, const char *field, float *se
|
||||
|
||||
void GameSave::readOPS(const std::vector<char> &data)
|
||||
{
|
||||
constexpr auto currentVersion = Version(currentVersionMajor, 0);
|
||||
constexpr auto nextVersion = Version(nextVersionMajor, 0);
|
||||
|
||||
Renderer::PopulateTables();
|
||||
|
||||
unsigned char *inputData = (unsigned char*)&data[0], *partsData = NULL, *partsPosData = NULL, *fanData = NULL, *wallData = NULL, *soapLinkData = NULL;
|
||||
@ -333,9 +338,8 @@ void GameSave::readOPS(const std::vector<char> &data)
|
||||
unsigned int inputDataLen = data.size(), bsonDataLen = 0, partsDataLen, partsPosDataLen, fanDataLen, wallDataLen, soapLinkDataLen;
|
||||
unsigned int pressDataLen, vxDataLen, vyDataLen, ambientDataLen, blockAirDataLen;
|
||||
unsigned partsCount = 0;
|
||||
int savedVersion = inputData[4];
|
||||
majorVersion = savedVersion;
|
||||
minorVersion = 0;
|
||||
unsigned int savedVersion = inputData[4];
|
||||
version = { savedVersion, 0 };
|
||||
bool fakeNewerVersion = false; // used for development builds only
|
||||
|
||||
bson b;
|
||||
@ -354,7 +358,7 @@ void GameSave::readOPS(const std::vector<char> &data)
|
||||
auto partS = blockS * CELL;
|
||||
|
||||
//From newer version
|
||||
if (savedVersion > SAVE_VERSION)
|
||||
if (savedVersion > currentVersion[0])
|
||||
{
|
||||
fromNewerVersion = true;
|
||||
//throw ParseException(ParseException::WrongVersion, "Save from newer version");
|
||||
@ -470,7 +474,7 @@ void GameSave::readOPS(const std::vector<char> &data)
|
||||
if (!strcmp(bson_iterator_key(&signiter), "text") && bson_iterator_type(&signiter) == BSON_STRING)
|
||||
{
|
||||
tempSign.text = format::CleanString(ByteString(bson_iterator_string(&signiter)).FromUtf8(), true, true, true).Substr(0, 45);
|
||||
if (majorVersion < 94 || (majorVersion == 94 && minorVersion < 2))
|
||||
if (version < Version(94, 2))
|
||||
{
|
||||
if (tempSign.text == "{t}")
|
||||
{
|
||||
@ -582,7 +586,7 @@ void GameSave::readOPS(const std::vector<char> &data)
|
||||
{
|
||||
if (!strcmp(bson_iterator_key(&subiter), "minorVersion"))
|
||||
{
|
||||
minorVersion = bson_iterator_int(&subiter);
|
||||
version[1] = bson_iterator_int(&subiter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -596,27 +600,30 @@ void GameSave::readOPS(const std::vector<char> &data)
|
||||
{
|
||||
if (bson_iterator_type(&iter) == BSON_OBJECT)
|
||||
{
|
||||
int major = INT_MAX, minor = INT_MAX;
|
||||
bson_iterator subiter;
|
||||
bson_iterator_subiterator(&iter, &subiter);
|
||||
while (bson_iterator_next(&subiter))
|
||||
Version<2> version;
|
||||
{
|
||||
if (bson_iterator_type(&subiter) == BSON_INT)
|
||||
int major = INT_MAX, minor = INT_MAX;
|
||||
bson_iterator subiter;
|
||||
bson_iterator_subiterator(&iter, &subiter);
|
||||
while (bson_iterator_next(&subiter))
|
||||
{
|
||||
if (!strcmp(bson_iterator_key(&subiter), "major"))
|
||||
major = bson_iterator_int(&subiter);
|
||||
else if (!strcmp(bson_iterator_key(&subiter), "minor"))
|
||||
minor = bson_iterator_int(&subiter);
|
||||
if (bson_iterator_type(&subiter) == BSON_INT)
|
||||
{
|
||||
if (!strcmp(bson_iterator_key(&subiter), "major"))
|
||||
major = bson_iterator_int(&subiter);
|
||||
else if (!strcmp(bson_iterator_key(&subiter), "minor"))
|
||||
minor = bson_iterator_int(&subiter);
|
||||
}
|
||||
}
|
||||
version = Version(major, minor);
|
||||
}
|
||||
auto majorToCheck = ALLOW_FAKE_NEWER_VERSION ? FUTURE_SAVE_VERSION : SAVE_VERSION;
|
||||
auto minorToCheck = ALLOW_FAKE_NEWER_VERSION ? FUTURE_MINOR_VERSION : MINOR_VERSION;
|
||||
if (major > majorToCheck || (major == majorToCheck && minor > minorToCheck))
|
||||
auto versionToCheck = ALLOW_FAKE_NEWER_VERSION ? nextVersion : currentVersion;
|
||||
if (versionToCheck < version)
|
||||
{
|
||||
String errorMessage = String::Build("Save from a newer version: Requires version ", major, ".", minor);
|
||||
String errorMessage = String::Build("Save from a newer version: Requires version ", version[0], ".", version[1]);
|
||||
throw ParseException(ParseException::WrongVersion, errorMessage);
|
||||
}
|
||||
else if (ALLOW_FAKE_NEWER_VERSION && (major > SAVE_VERSION || (major == SAVE_VERSION && minor > MINOR_VERSION)))
|
||||
else if (ALLOW_FAKE_NEWER_VERSION && currentVersion < version)
|
||||
{
|
||||
fakeNewerVersion = true;
|
||||
}
|
||||
@ -642,8 +649,8 @@ void GameSave::readOPS(const std::vector<char> &data)
|
||||
}
|
||||
}
|
||||
|
||||
auto paletteRemap = [this, saveVersion = Version(majorVersion, minorVersion)](auto maxVersion, ByteString from, ByteString to) {
|
||||
if (saveVersion <= maxVersion)
|
||||
auto paletteRemap = [this](auto maxVersion, ByteString from, ByteString to) {
|
||||
if (version <= maxVersion)
|
||||
{
|
||||
auto it = std::find_if(palette.begin(), palette.end(), [&from](auto &item) {
|
||||
return item.first == from;
|
||||
@ -1182,7 +1189,7 @@ void GameSave::readPSv(const std::vector<char> &dataVec)
|
||||
|
||||
unsigned char * saveData = (unsigned char *)&dataVec[0];
|
||||
auto dataLength = int(dataVec.size());
|
||||
int q,p=0, ver, pty, ty, legacy_beta=0;
|
||||
int q,p=0, pty, ty, legacy_beta=0;
|
||||
Vec2<int> blockP = { 0, 0 };
|
||||
int new_format = 0, ttv = 0;
|
||||
|
||||
@ -1202,11 +1209,10 @@ void GameSave::readPSv(const std::vector<char> &dataVec)
|
||||
if (saveData[2]==0x76 && saveData[1]==0x53 && saveData[0]==0x50) {
|
||||
new_format = 1;
|
||||
}
|
||||
if (saveData[4]>SAVE_VERSION)
|
||||
if (saveData[4]>97) // this used to respect currentVersion but no valid PSv will ever have a version > 97 so it's ok to hardcode
|
||||
throw ParseException(ParseException::WrongVersion, "Save from newer version");
|
||||
ver = saveData[4];
|
||||
majorVersion = saveData[4];
|
||||
minorVersion = 0;
|
||||
version = { saveData[4], 0 };
|
||||
auto ver = version[0];
|
||||
|
||||
if (ver<34)
|
||||
{
|
||||
@ -1818,16 +1824,18 @@ void GameSave::readPSv(const std::vector<char> &dataVec)
|
||||
|
||||
std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
|
||||
{
|
||||
constexpr auto currentVersion = Version(currentVersionMajor, 0);
|
||||
|
||||
// minimum version this save is compatible with
|
||||
// when building, this number may be increased depending on what elements are used
|
||||
// or what properties are detected
|
||||
int minimumMajorVersion = 90, minimumMinorVersion = 2;
|
||||
auto RESTRICTVERSION = [&minimumMajorVersion, &minimumMinorVersion](int major, int minor) {
|
||||
auto minimumVersion = Version(90, 2);
|
||||
auto RESTRICTVERSION = [&minimumVersion](auto major, auto minor = 0) {
|
||||
// restrict the minimum version this save can be opened with
|
||||
if (major > minimumMajorVersion || ((major == minimumMajorVersion && minor > minimumMinorVersion)))
|
||||
auto version = Version(major, minor);
|
||||
if (minimumVersion < version)
|
||||
{
|
||||
minimumMajorVersion = major;
|
||||
minimumMinorVersion = minor;
|
||||
minimumVersion = version;
|
||||
}
|
||||
};
|
||||
|
||||
@ -2295,7 +2303,7 @@ std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
|
||||
}
|
||||
|
||||
// Mark save as incompatible with latest release
|
||||
bool fakeFromNewerVersion = ALLOW_FAKE_NEWER_VERSION && (minimumMajorVersion > SAVE_VERSION || (minimumMajorVersion == SAVE_VERSION && minimumMinorVersion > MINOR_VERSION));
|
||||
bool fakeFromNewerVersion = ALLOW_FAKE_NEWER_VERSION && currentVersion < minimumVersion;
|
||||
|
||||
bson b;
|
||||
b.data = NULL;
|
||||
@ -2306,9 +2314,9 @@ std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
|
||||
set_bson_err_handler([](const char* err) { throw BuildException("BSON error when parsing save: " + ByteString(err).FromUtf8()); });
|
||||
bson_init(&b);
|
||||
bson_append_start_object(&b, "origin");
|
||||
bson_append_int(&b, "majorVersion", SAVE_VERSION);
|
||||
bson_append_int(&b, "minorVersion", MINOR_VERSION);
|
||||
bson_append_int(&b, "buildNum", BUILD_NUM);
|
||||
bson_append_int(&b, "majorVersion", int(currentVersion[0]));
|
||||
bson_append_int(&b, "minorVersion", int(currentVersion[1]));
|
||||
bson_append_int(&b, "buildNum", APP_VERSION.build);
|
||||
bson_append_int(&b, "snapshotId", SNAPSHOT_ID);
|
||||
bson_append_int(&b, "modId", MOD_ID);
|
||||
bson_append_string(&b, "releaseType", ByteString(1, IDENT_RELTYPE).c_str());
|
||||
@ -2322,8 +2330,8 @@ std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
|
||||
RESTRICTVERSION(97, 0);
|
||||
}
|
||||
bson_append_start_object(&b, "minimumVersion");
|
||||
bson_append_int(&b, "major", minimumMajorVersion);
|
||||
bson_append_int(&b, "minor", minimumMinorVersion);
|
||||
bson_append_int(&b, "major", int(minimumVersion[0]));
|
||||
bson_append_int(&b, "minor", int(minimumVersion[1]));
|
||||
bson_append_finish_object(&b);
|
||||
|
||||
|
||||
@ -2467,7 +2475,7 @@ std::pair<bool, std::vector<char>> GameSave::serialiseOPS() const
|
||||
header[1] = 'P';
|
||||
header[2] = 'S';
|
||||
header[3] = '1';
|
||||
header[4] = SAVE_VERSION;
|
||||
header[4] = currentVersion[0];
|
||||
header[5] = CELL;
|
||||
header[6] = blockS.X;
|
||||
header[7] = blockS.Y;
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include "common/Plane.h"
|
||||
#include "common/String.h"
|
||||
#include "common/tpt-rand.h"
|
||||
#include "common/Version.h"
|
||||
#include "simulation/Sign.h"
|
||||
#include "simulation/Particle.h"
|
||||
#include "Misc.h"
|
||||
@ -64,8 +65,7 @@ class GameSave
|
||||
public:
|
||||
Vec2<int> blockSize = { 0, 0 };
|
||||
bool fromNewerVersion = false;
|
||||
int majorVersion = 0;
|
||||
int minorVersion = 0;
|
||||
Version<2> version{};
|
||||
bool hasPressure = false;
|
||||
bool hasAmbientHeat = false;
|
||||
bool hasBlockAirMaps = false; // only written by readOPS, never read
|
||||
|
@ -82,12 +82,12 @@ namespace http
|
||||
else
|
||||
{
|
||||
parseUpdate("Stable", UpdateInfo::channelStable, [](int build) -> bool {
|
||||
return build > BUILD_NUM;
|
||||
return size_t(build) > APP_VERSION.build;
|
||||
});
|
||||
if (!startupInfo.updateInfo.has_value())
|
||||
{
|
||||
parseUpdate("Beta", UpdateInfo::channelBeta, [](int build) -> bool {
|
||||
return build > BUILD_NUM;
|
||||
return size_t(build) > APP_VERSION.build;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -10,13 +10,14 @@ namespace http
|
||||
capath(newCapath),
|
||||
disableNetwork(newDisableNetwork)
|
||||
{
|
||||
auto apiVersion = Version(97, 0);
|
||||
userAgent = ByteString::Build(
|
||||
"PowderToy/", SAVE_VERSION, ".", MINOR_VERSION,
|
||||
"PowderToy/", DISPLAY_VERSION[0], ".", DISPLAY_VERSION[1],
|
||||
" (", IDENT_PLATFORM,
|
||||
"; NO", // Unused, used to be SSE level.
|
||||
"; M", MOD_ID,
|
||||
"; ", IDENT,
|
||||
") TPTPP/", SAVE_VERSION, ".", MINOR_VERSION, ".", BUILD_NUM, IDENT_RELTYPE, ".", SNAPSHOT_ID
|
||||
") TPTPP/", apiVersion[0], ".", apiVersion[1], ".", APP_VERSION.build, IDENT_RELTYPE, ".", SNAPSHOT_ID
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,16 @@ struct Version
|
||||
{
|
||||
return *this < other || *this == other;
|
||||
}
|
||||
|
||||
constexpr size_t operator [](size_t index) const
|
||||
{
|
||||
return components[index];
|
||||
}
|
||||
|
||||
size_t &operator [](size_t index)
|
||||
{
|
||||
return components[index];
|
||||
}
|
||||
};
|
||||
|
||||
template<class ...Args>
|
||||
|
@ -1204,10 +1204,10 @@ void GameController::OpenLocalSaveWindow(bool asCurrent)
|
||||
gameSave->authors = localSaveInfo;
|
||||
|
||||
Platform::MakeDirectory(LOCAL_SAVE_DIR);
|
||||
auto [ fromNewerVersion, saveData ] = gameSave->Serialise();
|
||||
std::vector<char> saveData;
|
||||
std::tie(std::ignore, saveData) = gameSave->Serialise();
|
||||
tempSave->SetGameSave(std::move(gameSave));
|
||||
gameModel->SetSaveFile(std::move(tempSave), gameView->ShiftBehaviour());
|
||||
(void)fromNewerVersion;
|
||||
if (saveData.size() == 0)
|
||||
new ErrorMessage("Error", "Unable to serialize game data.");
|
||||
else if (!Platform::WriteFile(saveData, gameModel->GetSaveFile()->GetName()))
|
||||
@ -1611,11 +1611,11 @@ void GameController::NotifyUpdateAvailable(Client * sender)
|
||||
}
|
||||
else if constexpr (BETA)
|
||||
{
|
||||
updateMessage << SAVE_VERSION << "." << MINOR_VERSION << " Beta, Build " << BUILD_NUM;
|
||||
updateMessage << DISPLAY_VERSION[0] << "." << DISPLAY_VERSION[1] << " Beta, Build " << APP_VERSION.build;
|
||||
}
|
||||
else
|
||||
{
|
||||
updateMessage << SAVE_VERSION << "." << MINOR_VERSION << " Stable, Build " << BUILD_NUM;
|
||||
updateMessage << DISPLAY_VERSION[0] << "." << DISPLAY_VERSION[1] << " Stable, Build " << APP_VERSION.build;
|
||||
}
|
||||
|
||||
updateMessage << "\nNew version:\n ";
|
||||
|
@ -5,7 +5,7 @@
|
||||
inline ByteString VersionInfo()
|
||||
{
|
||||
ByteStringBuilder sb;
|
||||
sb << SAVE_VERSION << "." << MINOR_VERSION << "." << BUILD_NUM << " " << IDENT;
|
||||
sb << DISPLAY_VERSION[0] << "." << DISPLAY_VERSION[1] << "." << APP_VERSION.build << " " << IDENT;
|
||||
if constexpr (SNAPSHOT)
|
||||
{
|
||||
sb << " SNAPSHOT " << SNAPSHOT_ID;
|
||||
@ -39,7 +39,7 @@ inline ByteString VersionInfo()
|
||||
inline ByteString IntroText()
|
||||
{
|
||||
ByteStringBuilder sb;
|
||||
sb << "\bl\bU" << APPNAME << "\bU - Version " << SAVE_VERSION << "." << MINOR_VERSION << " - https://powdertoy.co.uk, irc.libera.chat #powder, https://tpt.io/discord\n"
|
||||
sb << "\bl\bU" << APPNAME << "\bU - Version " << DISPLAY_VERSION[0] << "." << DISPLAY_VERSION[1] << " - https://powdertoy.co.uk, irc.libera.chat #powder, https://tpt.io/discord\n"
|
||||
"\n"
|
||||
"\n"
|
||||
"\bgControl+C/V/X are Copy, Paste and cut respectively.\n"
|
||||
|
@ -115,8 +115,8 @@ void LocalSaveActivity::saveWrite(ByteString finalFilename)
|
||||
gameSave->authors = localSaveInfo;
|
||||
save->SetGameSave(std::move(gameSave));
|
||||
}
|
||||
auto [ fromNewerVersion, saveData ] = save->GetGameSave()->Serialise();
|
||||
(void)fromNewerVersion;
|
||||
std::vector<char> saveData;
|
||||
std::tie(std::ignore, saveData) = save->GetGameSave()->Serialise();
|
||||
if (saveData.size() == 0)
|
||||
new ErrorMessage("Error", "Unable to serialize game data.");
|
||||
else if (!Platform::WriteFile(saveData, finalFilename))
|
||||
|
@ -403,12 +403,18 @@ LuaScriptInterface::LuaScriptInterface(GameController * c, GameModel * m):
|
||||
|
||||
lua_newtable(l);
|
||||
tptPropertiesVersion = lua_gettop(l);
|
||||
lua_pushinteger(l, SAVE_VERSION);
|
||||
lua_pushinteger(l, DISPLAY_VERSION[0]);
|
||||
lua_setfield(l, tptPropertiesVersion, "major");
|
||||
lua_pushinteger(l, MINOR_VERSION);
|
||||
lua_pushinteger(l, DISPLAY_VERSION[1]);
|
||||
lua_setfield(l, tptPropertiesVersion, "minor");
|
||||
lua_pushinteger(l, BUILD_NUM);
|
||||
lua_pushinteger(l, APP_VERSION.build);
|
||||
lua_setfield(l, tptPropertiesVersion, "build");
|
||||
lua_pushinteger(l, UPSTREAM_VERSION.displayVersion[0]);
|
||||
lua_setfield(l, tptPropertiesVersion, "upstream_major");
|
||||
lua_pushinteger(l, UPSTREAM_VERSION.displayVersion[1]);
|
||||
lua_setfield(l, tptPropertiesVersion, "upstream_minor");
|
||||
lua_pushinteger(l, UPSTREAM_VERSION.build);
|
||||
lua_setfield(l, tptPropertiesVersion, "upstream_build");
|
||||
if constexpr (SNAPSHOT || MOD)
|
||||
{
|
||||
lua_pushinteger(l, SNAPSHOT_ID);
|
||||
|
@ -12,6 +12,15 @@ conf_data.set('DEBUG', is_debug.to_string())
|
||||
conf_data.set('MOD', is_mod.to_string())
|
||||
conf_data.set('SNAPSHOT', is_snapshot.to_string())
|
||||
conf_data.set('SNAPSHOT_ID', get_option('snapshot_id'))
|
||||
conf_data.set('DISPLAY_VERSION_MAJOR', get_option('display_version_major'))
|
||||
conf_data.set('DISPLAY_VERSION_MINOR', get_option('display_version_minor'))
|
||||
conf_data.set('BUILD_NUM', get_option('build_num'))
|
||||
conf_data.set('UPSTREAM_VERSION_MAJOR', get_option('upstream_version_major'))
|
||||
conf_data.set('UPSTREAM_VERSION_MINOR', get_option('upstream_version_minor'))
|
||||
conf_data.set('UPSTREAM_BUILD_NUM', get_option('upstream_build_num'))
|
||||
conf_data.set('MANIFEST_COPYRIGHT', get_option('manifest_copyright'))
|
||||
conf_data.set('MANIFEST_MACOS_MIN_VER', get_option('manifest_macos_min_ver'))
|
||||
conf_data.set('MANIFEST_DATE', get_option('manifest_date'))
|
||||
conf_data.set('ALLOW_FAKE_NEWER_VERSION', (is_snapshot or is_beta or is_debug or is_mod).to_string())
|
||||
conf_data.set('IDENT_PLATFORM', ident_platform)
|
||||
conf_data.set('IDENT', '@0@-@1@-@2@'.format(host_arch, host_platform, host_libc).to_upper())
|
||||
|
@ -151,8 +151,8 @@ std::vector<ByteString> Simulation::Load(const GameSave *save, bool includePress
|
||||
player.spwn = 1;
|
||||
player.elem = PT_DUST;
|
||||
|
||||
if ((save->majorVersion < 93 && parts[i].ctype == SPC_AIR) ||
|
||||
(save->majorVersion < 88 && parts[i].ctype == OLD_SPC_AIR))
|
||||
if ((save->version < Version(93, 0) && parts[i].ctype == SPC_AIR) ||
|
||||
(save->version < Version(88, 0) && parts[i].ctype == OLD_SPC_AIR))
|
||||
{
|
||||
player.fan = true;
|
||||
}
|
||||
@ -165,8 +165,8 @@ std::vector<ByteString> Simulation::Load(const GameSave *save, bool includePress
|
||||
Element_STKM_init_legs(this, &player2, i);
|
||||
player2.spwn = 1;
|
||||
player2.elem = PT_DUST;
|
||||
if ((save->majorVersion < 93 && parts[i].ctype == SPC_AIR) ||
|
||||
(save->majorVersion < 88 && parts[i].ctype == OLD_SPC_AIR))
|
||||
if ((save->version < Version(93, 0) && parts[i].ctype == SPC_AIR) ||
|
||||
(save->version < Version(88, 0) && parts[i].ctype == OLD_SPC_AIR))
|
||||
{
|
||||
player2.fan = true;
|
||||
}
|
||||
@ -189,8 +189,8 @@ std::vector<ByteString> Simulation::Load(const GameSave *save, bool includePress
|
||||
if (parts[i].tmp >= 0)
|
||||
{
|
||||
bool fan = false;
|
||||
if ((save->majorVersion < 93 && parts[i].ctype == SPC_AIR)
|
||||
|| (save->majorVersion < 88 && parts[i].ctype == OLD_SPC_AIR))
|
||||
if ((save->version < Version(93, 0) && parts[i].ctype == SPC_AIR)
|
||||
|| (save->version < Version(88, 0) && parts[i].ctype == OLD_SPC_AIR))
|
||||
{
|
||||
fan = true;
|
||||
parts[i].ctype = 0;
|
||||
|
Loading…
Reference in New Issue
Block a user