aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client
diff options
context:
space:
mode:
authorrtm516 <rtm516@users.noreply.github.com>2026-03-07 19:55:44 +0000
committerGitHub <noreply@github.com>2026-03-07 13:55:44 -0600
commit9cac3e039483c59477bae2edc03a3780afe49bd6 (patch)
tree7f21f31b42b41438da81e11c07a9d9bb3cf4289a /Minecraft.Client
parente5ad785803ff5867b5d5c38efb85947819eb72db (diff)
Change F3 rendering and add git version information (#836)
* Change F3 rendering and add git version information * Change position, block, chunk and facing * Limit position decimal places * Move LCE unique to the bottom and add more java features * Fix chunk information disappearing after y256 * Add chunk count information * Move build number script to prebuild.ps1 * We dont need to specify vector and wstring are from std * Restore build number to fix multiplayer * Use short symbolic-ref * Restore original BuildVer.h --------- Co-authored-by: Loki <lokio.casebstv@gmail.com> Co-authored-by: Loki Rautio <lokirautio@gmail.com>
Diffstat (limited to 'Minecraft.Client')
-rw-r--r--Minecraft.Client/ClientConstants.cpp2
-rw-r--r--Minecraft.Client/Common/BuildVer.h59
-rw-r--r--Minecraft.Client/Gui.cpp236
-rw-r--r--Minecraft.Client/Minecraft.Client.vcxproj12
-rw-r--r--Minecraft.Client/Minecraft.cpp4
-rw-r--r--Minecraft.Client/postbuild.ps12
-rw-r--r--Minecraft.Client/prebuild.ps124
7 files changed, 207 insertions, 132 deletions
diff --git a/Minecraft.Client/ClientConstants.cpp b/Minecraft.Client/ClientConstants.cpp
index 41c4b125..43da4360 100644
--- a/Minecraft.Client/ClientConstants.cpp
+++ b/Minecraft.Client/ClientConstants.cpp
@@ -1,4 +1,4 @@
#include "stdafx.h"
#include "ClientConstants.h"
-const wstring ClientConstants::VERSION_STRING = wstring(L"Minecraft Xbox ") + VER_FILEVERSION_STR_W;//+ SharedConstants::VERSION_STRING; \ No newline at end of file
+const wstring ClientConstants::VERSION_STRING = wstring(L"Minecraft LCE ") + VER_FILEVERSION_STR_W;//+ SharedConstants::VERSION_STRING; \ No newline at end of file
diff --git a/Minecraft.Client/Common/BuildVer.h b/Minecraft.Client/Common/BuildVer.h
index 9248a8eb..babe7566 100644
--- a/Minecraft.Client/Common/BuildVer.h
+++ b/Minecraft.Client/Common/BuildVer.h
@@ -1,57 +1,6 @@
-
#pragma once
-
-#define VER_PRODUCTMAJORVERSION 0
-#define VER_PRODUCTMINORVERSION 0
-
-// This goes up with each build
-// 4J-JEV: This value is extracted with a regex so it can be placed as the version in the AppX manifest on Durango.
-#define VER_PRODUCTBUILD 560
-// This goes up if there is any change to network traffic or code in a build
-#define VER_NETWORK 560
-#define VER_PRODUCTBUILD_QFE 0
-
-#define VER_FILEVERSION_STRING "1.6"
-#define VER_PRODUCTVERSION_STRING VER_FILEVERSION_STRING
-#define VER_FILEVERSION_STRING_W L"1.6"
-#define VER_PRODUCTVERSION_STRING_W VER_FILEVERSION_STRING_W
-#define VER_FILEBETA_STR ""
-#undef VER_FILEVERSION
-#define VER_FILEVERSION VER_PRODUCTMAJORVERSION, VER_PRODUCTMINORVERSION, VER_PRODUCTBUILD, VER_PRODUCTBUILD_QFE
-#define VER_PRODUCTVERSION VER_PRODUCTMAJORVERSION, VER_PRODUCTMINORVERSION, VER_PRODUCTBUILD, VER_PRODUCTBUILD_QFE
-
-#if (VER_PRODUCTBUILD < 10)
-#define VER_FILEBPAD "000"
-#define VER_FILEBPAD_W L"000"
-#elif (VER_PRODUCTBUILD < 100)
-#define VER_FILEBPAD "00"
-#define VER_FILEBPAD_W L"00"
-#elif (VER_PRODUCTBUILD < 1000)
-#define VER_FILEBPAD "0"
-#define VER_FILEBPAD_W L"0"
-#else
-#define VER_FILEBPAD
-#define VER_FILEBPAD_W
-#endif
-
-#define VER_WIDE_PREFIX(x) L##x
-
-#define VER_FILEVERSION_STR2(x,y) VER_FILEVERSION_STRING "." VER_FILEBPAD #x "." #y
-#define VER_FILEVERSION_STR2_W(x,y) VER_FILEVERSION_STRING_W L"." VER_FILEBPAD_W VER_WIDE_PREFIX(#x) L"." VER_WIDE_PREFIX(#y)
-#define VER_FILEVERSION_STR1(x,y) VER_FILEVERSION_STR2(x, y)
-#define VER_FILEVERSION_STR1_W(x,y) VER_FILEVERSION_STR2_W(x, y)
-
-#undef VER_FILEVERSION_STR
-#define VER_FILEVERSION_STR VER_FILEVERSION_STR1(VER_PRODUCTBUILD, VER_PRODUCTBUILD_QFE)
-#define VER_PRODUCTVERSION_STR VER_FILEVERSION_STR1(VER_PRODUCTBUILD, VER_PRODUCTBUILD_QFE)
-
-#define VER_FILEVERSION_STR_W VER_FILEVERSION_STR1_W(VER_PRODUCTBUILD, VER_PRODUCTBUILD_QFE)
-#define VER_PRODUCTVERSION_STR_W VER_FILEVERSION_STR1_W(VER_PRODUCTBUILD, VER_PRODUCTBUILD_QFE)
-
-#if (VER_PRODUCTBUILD_QFE >= 256)
-#error "QFE number cannot exceed 255"
-#endif
-
-
-
+#define VER_PRODUCTBUILD 560
+#define VER_PRODUCTVERSION_STR_W L"DEV (unknown)"
+#define VER_FILEVERSION_STR_W VER_PRODUCTVERSION_STR_W
+#define VER_NETWORK VER_PRODUCTBUILD
diff --git a/Minecraft.Client/Gui.cpp b/Minecraft.Client/Gui.cpp
index 7353e802..f9810a36 100644
--- a/Minecraft.Client/Gui.cpp
+++ b/Minecraft.Client/Gui.cpp
@@ -859,88 +859,176 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
glTranslatef((float)debugLeft, (float)debugTop, 0.f);
glScalef(scale, scale, 1.f);
glTranslatef((float)-debugLeft, (float)-debugTop, 0.f);
- if (Minecraft::warezTime > 0) glTranslatef(0, 32, 0);
- font->drawShadow(ClientConstants::VERSION_STRING + L" (" + minecraft->fpsString + L")", debugLeft, debugTop, 0xffffff);
- font->drawShadow(L"Seed: " + std::to_wstring(minecraft->level->getLevelData()->getSeed() ), debugLeft, debugTop + 12, 0xffffff);
- font->drawShadow(minecraft->gatherStats1(), debugLeft, debugTop + 22, 0xffffff);
- font->drawShadow(minecraft->gatherStats2(), debugLeft, debugTop + 32, 0xffffff);
- font->drawShadow(minecraft->gatherStats3(), debugLeft, debugTop + 42, 0xffffff);
- font->drawShadow(minecraft->gatherStats4(), debugLeft, debugTop + 52, 0xffffff);
-
- // TERRAIN FEATURES
- int iYPos = debugTop + 62;
-
- if(minecraft->level->dimension->id==0)
+
+ vector<wstring> lines;
+
+ lines.push_back(ClientConstants::VERSION_STRING);
+ lines.push_back(minecraft->fpsString);
+ lines.push_back(L"E: " + std::to_wstring(minecraft->level->getAllEntities().size())); // Could maybe use entity::shouldRender to work out how many are rendered but thats like expensive
+ // TODO Add server information with packet counts - once multiplayer is more stable
+ int renderDistance = app.GetGameSettings(iPad, eGameSetting_RenderDistance);
+ // Calculate the chunk sections using 16 * (2n + 1)^2
+ lines.push_back(L"C: " + std::to_wstring(16 * (2 * renderDistance + 1) * (2 * renderDistance + 1)) + L" D: " + std::to_wstring(renderDistance));
+ lines.push_back(minecraft->gatherStats4()); // Chunk Cache
+
+ // Dimension
+ wstring dimension = L"unknown";
+ switch (minecraft->player->dimension)
+ {
+ case -1:
+ dimension = L"minecraft:the_nether";
+ break;
+ case 0:
+ dimension = L"minecraft:overworld";
+ break;
+ case 1:
+ dimension = L"minecraft:the_end";
+ break;
+ }
+ lines.push_back(dimension);
+
+ lines.push_back(L""); // Spacer
+
+ // Players block pos
+ int xBlockPos = Mth::floor(minecraft->player->x);
+ int yBlockPos = Mth::floor(minecraft->player->y);
+ int zBlockPos = Mth::floor(minecraft->player->z);
+
+ // Chunk player is in
+ int xChunkPos = minecraft->player->xChunk;
+ int yChunkPos = minecraft->player->yChunk;
+ int zChunkPos = minecraft->player->zChunk;
+
+ // Players offset within the chunk
+ int xChunkOffset = xBlockPos - xChunkPos * 16;
+ int yChunkOffset = yBlockPos - yChunkPos * 16;
+ int zChunkOffset = zBlockPos - zChunkPos * 16;
+
+ // Format the position like java with limited decumal places
+ WCHAR posString[44]; // Allows upto 7 digit positions (+-9_999_999)
+ swprintf(posString, 44, L"%.3f / %.5f / %.3f", minecraft->player->x, minecraft->player->y, minecraft->player->z);
+
+ lines.push_back(L"XYZ: " + std::wstring(posString));
+ lines.push_back(L"Block: " + std::to_wstring(static_cast<int>(xBlockPos)) + L" " + std::to_wstring(static_cast<int>(yBlockPos)) + L" " + std::to_wstring(static_cast<int>(zBlockPos)));
+ lines.push_back(L"Chunk: " + std::to_wstring(xChunkOffset) + L" " + std::to_wstring(yChunkOffset) + L" " + std::to_wstring(zChunkOffset) + L" in " + std::to_wstring(xChunkPos) + L" " + std::to_wstring(yChunkPos) + L" " + std::to_wstring(zChunkPos));
+
+ // Wrap the yRot to 360 then adjust to (-180 to 180) range to match java
+ float yRotDisplay = fmod(minecraft->player->yRot, 360.0f);
+ if (yRotDisplay > 180.0f)
+ {
+ yRotDisplay -= 360.0f;
+ }
+ if (yRotDisplay < -180.0f)
+ {
+ yRotDisplay += 360.0f;
+ }
+ // Generate the angle string in the format "yRot / xRot" with one decimal place, similar to java edition
+ WCHAR angleString[16];
+ swprintf(angleString, 16, L"%.1f / %.1f", yRotDisplay, minecraft->player->xRot);
+
+ // Work out the named direction
+ int direction = Mth::floor(minecraft->player->yRot * 4.0f / 360.0f + 0.5) & 0x3;
+ wstring cardinalDirection;
+ switch (direction)
+ {
+ case 0:
+ cardinalDirection = L"south";
+ break;
+ case 1:
+ cardinalDirection = L"west";
+ break;
+ case 2:
+ cardinalDirection = L"north";
+ break;
+ case 3:
+ cardinalDirection = L"east";
+ break;
+ }
+
+ lines.push_back(L"Facing: " + cardinalDirection + L" (" + angleString + L")");
+
+ // We have to limit y to 256 as we don't get any information past that
+ if (minecraft->level != NULL && minecraft->level->hasChunkAt(xBlockPos, fmod(yBlockPos, 256), zBlockPos))
{
- wstring wfeature[eTerrainFeature_Count];
+ LevelChunk *chunkAt = minecraft->level->getChunkAt(xBlockPos, zBlockPos);
- wfeature[eTerrainFeature_Stronghold] = L"Stronghold: ";
- wfeature[eTerrainFeature_Mineshaft] = L"Mineshaft: ";
- wfeature[eTerrainFeature_Village] = L"Village: ";
- wfeature[eTerrainFeature_Ravine] = L"Ravine: ";
+ int skyLight = chunkAt->getBrightness(LightLayer::Sky, xChunkOffset, yChunkOffset, zChunkOffset);
+ int blockLight = chunkAt->getBrightness(LightLayer::Block, xChunkOffset, yChunkOffset, zChunkOffset);
+ int maxLight = fmax(skyLight, blockLight);
+ lines.push_back(L"Light: " + std::to_wstring(maxLight) + L" (" + std::to_wstring(skyLight) + L" sky, " + std::to_wstring(blockLight) + L" block)");
- float maxW = (float)(screenWidth - debugLeft - 8) / scale;
- float maxWForContent = maxW - (float)font->width(L"...");
- bool truncated[eTerrainFeature_Count] = {};
+ lines.push_back(L"CH S: " + std::to_wstring(chunkAt->getHeightmap(xChunkOffset, zChunkOffset)));
- for (int i = 0; i < (int)app.m_vTerrainFeatures.size(); i++)
- {
- FEATURE_DATA *pFeatureData=app.m_vTerrainFeatures[i];
- int type = pFeatureData->eTerrainFeature;
- if (type < eTerrainFeature_Stronghold || type > eTerrainFeature_Ravine) continue;
- if (truncated[type]) continue;
-
- wstring itemInfo = L"[" + std::to_wstring( pFeatureData->x*16 ) + L", " + std::to_wstring( pFeatureData->z*16 ) + L"] ";
- if (font->width(wfeature[type] + itemInfo) <= maxWForContent)
- wfeature[type] += itemInfo;
- else
- {
- wfeature[type] += L"...";
- truncated[type] = true;
- }
- }
+ Biome *biome = chunkAt->getBiome(xChunkOffset, zChunkOffset, minecraft->level->getBiomeSource());
+ lines.push_back(L"Biome: " + biome->m_name + L" (" + std::to_wstring(biome->id) + L")");
- for( int i = eTerrainFeature_Stronghold; i < (int) eTerrainFeature_Count; i++ )
- {
- iYPos+=10;
- font->drawShadow(wfeature[i], debugLeft, iYPos, 0xffffff);
- }
+ lines.push_back(L"Difficulty: " + std::to_wstring(minecraft->level->difficulty) + L" (Day " + std::to_wstring(minecraft->level->getGameTime() / Level::TICKS_PER_DAY) + L")");
}
- //font->drawShadow(minecraft->gatherStats5(), iSafezoneXHalf+2, 32 + 10, 0xffffff);
- {
- /* 4J - removed
- long max = Runtime.getRuntime().maxMemory();
- long total = Runtime.getRuntime().totalMemory();
- long free = Runtime.getRuntime().freeMemory();
- long used = total - free;
- String msg = "Used memory: " + (used * 100 / max) + "% (" + (used / 1024 / 1024) + "MB) of " + (max / 1024 / 1024) + "MB";
- drawString(font, msg, screenWidth - font.width(msg) - 2, 2, 0xe0e0e0);
- msg = "Allocated memory: " + (total * 100 / max) + "% (" + (total / 1024 / 1024) + "MB)";
- drawString(font, msg, screenWidth - font.width(msg) - 2, 12, 0xe0e0e0);
- */
+
+ // This is all LCE only stuff, it was never on java
+ lines.push_back(L""); // Spacer
+ lines.push_back(L"Seed: " + std::to_wstring(minecraft->level->getLevelData()->getSeed()));
+ lines.push_back(minecraft->gatherStats1()); // Time to autosave
+ lines.push_back(minecraft->gatherStats2()); // Empty currently - CPlatformNetworkManagerStub::GatherStats()
+ lines.push_back(minecraft->gatherStats3()); // RTT
+
+#ifdef _DEBUG // Only show terrain features in debug builds not release
+ // TERRAIN FEATURES
+ if (minecraft->level->dimension->id == 0)
+ {
+ wstring wfeature[eTerrainFeature_Count];
+
+ wfeature[eTerrainFeature_Stronghold] = L"Stronghold: ";
+ wfeature[eTerrainFeature_Mineshaft] = L"Mineshaft: ";
+ wfeature[eTerrainFeature_Village] = L"Village: ";
+ wfeature[eTerrainFeature_Ravine] = L"Ravine: ";
+
+ float maxW = (float)(screenWidth - debugLeft - 8) / scale;
+ float maxWForContent = maxW - (float)font->width(L"...");
+ bool truncated[eTerrainFeature_Count] = {};
+
+ for (int i = 0; i < (int)app.m_vTerrainFeatures.size(); i++)
+ {
+ FEATURE_DATA *pFeatureData = app.m_vTerrainFeatures[i];
+ int type = pFeatureData->eTerrainFeature;
+ if (type < eTerrainFeature_Stronghold || type > eTerrainFeature_Ravine)
+ {
+ continue;
+ }
+ if (truncated[type])
+ {
+ continue;
+ }
+
+ wstring itemInfo = L"[" + std::to_wstring(pFeatureData->x * 16) + L", " + std::to_wstring(pFeatureData->z * 16) + L"] ";
+ if (font->width(wfeature[type] + itemInfo) <= maxWForContent)
+ {
+ wfeature[type] += itemInfo;
+ }
+ else
+ {
+ wfeature[type] += L"...";
+ truncated[type] = true;
+ }
+ }
+
+ lines.push_back(L""); // Add a spacer line
+ for (int i = eTerrainFeature_Stronghold; i <= (int)eTerrainFeature_Ravine; i++)
+ {
+ lines.push_back(wfeature[i]);
+ }
+ lines.push_back(L"");
+ }
+#endif
+
+ // Loop through the lines and draw them all on screen
+ int yPos = debugTop;
+ for (const auto &line : lines)
+ {
+ drawString(font, line, debugLeft, yPos, 0xffffff);
+ yPos += 10;
}
- // 4J Stu - Moved these so that they don't overlap
- double xBlockPos = floor(minecraft->player->x);
- double yBlockPos = floor(minecraft->player->y);
- double zBlockPos = floor(minecraft->player->z);
- drawString(font, L"x: " + std::to_wstring(minecraft->player->x) + L"/ Head: " + std::to_wstring(static_cast<int>(xBlockPos)) + L"/ Chunk: " + std::to_wstring(minecraft->player->xChunk), debugLeft, iYPos + 8 * 0, 0xe0e0e0);
- drawString(font, L"y: " + std::to_wstring(minecraft->player->y) + L"/ Head: " + std::to_wstring(static_cast<int>(yBlockPos)), debugLeft, iYPos + 8 * 1, 0xe0e0e0);
- drawString(font, L"z: " + std::to_wstring(minecraft->player->z) + L"/ Head: " + std::to_wstring(static_cast<int>(zBlockPos)) + L"/ Chunk: " + std::to_wstring(minecraft->player->zChunk), debugLeft, iYPos + 8 * 2, 0xe0e0e0);
- drawString(font, L"f: " + std::to_wstring(Mth::floor(minecraft->player->yRot * 4.0f / 360.0f + 0.5) & 0x3) + L"/ yRot: " + std::to_wstring(minecraft->player->yRot), debugLeft, iYPos + 8 * 3, 0xe0e0e0);
- iYPos += 8*4;
-
- int px = Mth::floor(minecraft->player->x);
- int py = Mth::floor(minecraft->player->y);
- int pz = Mth::floor(minecraft->player->z);
- if (minecraft->level != NULL && minecraft->level->hasChunkAt(px, py, pz))
- {
- LevelChunk *chunkAt = minecraft->level->getChunkAt(px, pz);
- Biome *biome = chunkAt->getBiome(px & 15, pz & 15, minecraft->level->getBiomeSource());
- drawString(
- font,
- L"b: " + biome->m_name + L" (" + std::to_wstring(biome->id) + L")", debugLeft, iYPos, 0xe0e0e0);
- }
glPopMatrix();
}
diff --git a/Minecraft.Client/Minecraft.Client.vcxproj b/Minecraft.Client/Minecraft.Client.vcxproj
index e574265d..d97cbc38 100644
--- a/Minecraft.Client/Minecraft.Client.vcxproj
+++ b/Minecraft.Client/Minecraft.Client.vcxproj
@@ -1596,6 +1596,12 @@ if not exist "$(TargetDir)\savedata" mkdir "$(TargetDir)\savedata"</Command>
<PostBuildEvent>
<Message>Run post-build script</Message>
</PostBuildEvent>
+ <PreBuildEvent>
+ <Command>powershell -ExecutionPolicy Bypass -File "$(ProjectDir)prebuild.ps1"</Command>
+ </PreBuildEvent>
+ <PreBuildEvent>
+ <Message>Run pre-build script</Message>
+ </PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64EC'">
<ClCompile>
@@ -1825,6 +1831,12 @@ xcopy /q /y /i /s /e $(ProjectDir)DurangoMedia\CU $(LayoutDir)Image\Loose\CU</C
<DeploymentType>CopyToHardDrive</DeploymentType>
<DeploymentFiles>$(RemoteRoot)=$(ImagePath);$(RemoteRoot)\res=Xbox\res;$(RemoteRoot)=Xbox\AvatarAwards;$(RemoteRoot)\Tutorial=Xbox\Tutorial\Tutorial;$(RemoteRoot)=Xbox\584111F70AAAAAAA;$(RemoteRoot)=Xbox\kinect\speech;$(RemoteRoot)=Xbox\XZP\TMSFiles.xzp</DeploymentFiles>
</Deploy>
+ <PreBuildEvent>
+ <Command>powershell -ExecutionPolicy Bypass -File "$(ProjectDir)prebuild.ps1"</Command>
+ </PreBuildEvent>
+ <PreBuildEvent>
+ <Message>Run pre-build script</Message>
+ </PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64EC'">
<ClCompile>
diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp
index f268ec50..46e8497a 100644
--- a/Minecraft.Client/Minecraft.cpp
+++ b/Minecraft.Client/Minecraft.cpp
@@ -742,7 +742,7 @@ void Minecraft::run()
while (System::currentTimeMillis() >= lastTime + 1000)
{
- fpsString = std::to_wstring(frames) + L" fps, " + std::to_wstring(Chunk::updates) + L" chunk updates";
+ fpsString = std::to_wstring(frames) + L" fps (" + std::to_wstring(Chunk::updates) + L" chunk updates)";
Chunk::updates = 0;
lastTime += 1000;
frames = 0;
@@ -2066,7 +2066,7 @@ void Minecraft::run_middle()
while (System::nanoTime() >= lastTime + 1000000000)
{
MemSect(31);
- fpsString = std::to_wstring(frames) + L" fps, " + std::to_wstring(Chunk::updates) + L" chunk updates";
+ fpsString = std::to_wstring(frames) + L" fps (" + std::to_wstring(Chunk::updates) + L" chunk updates)";
MemSect(0);
Chunk::updates = 0;
lastTime += 1000000000;
diff --git a/Minecraft.Client/postbuild.ps1 b/Minecraft.Client/postbuild.ps1
index b46df5aa..8ffc9b98 100644
--- a/Minecraft.Client/postbuild.ps1
+++ b/Minecraft.Client/postbuild.ps1
@@ -39,3 +39,5 @@ foreach ($copy in $copies) {
xcopy /q /y /i /s /e /d "$src" "$dst" 2>$null
}
}
+
+git restore "**/BuildVer.h" \ No newline at end of file
diff --git a/Minecraft.Client/prebuild.ps1 b/Minecraft.Client/prebuild.ps1
new file mode 100644
index 00000000..fa2c487c
--- /dev/null
+++ b/Minecraft.Client/prebuild.ps1
@@ -0,0 +1,24 @@
+$sha = (git rev-parse --short=7 HEAD)
+$ref = (git symbolic-ref --short HEAD)
+$build = 560 # Note: Build/network has to stay static for now, as without it builds wont be able to play together. We can change it later when we have a better versioning scheme in place.
+$suffix = ""
+
+# TODO Re-enable
+# If we are running in GitHub Actions, use the run number as the build number
+# if ($env:GITHUB_RUN_NUMBER) {
+# $build = $env:GITHUB_RUN_NUMBER
+# }
+
+# If we have uncommitted changes, add a suffix to the version string
+if (git status --porcelain) {
+ $suffix = "-dev"
+}
+
+@"
+#pragma once
+
+#define VER_PRODUCTBUILD $build
+#define VER_PRODUCTVERSION_STR_W L"$sha$suffix ($ref)"
+#define VER_FILEVERSION_STR_W VER_PRODUCTVERSION_STR_W
+#define VER_NETWORK VER_PRODUCTBUILD
+"@ | Set-Content "Common/BuildVer.h"