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>
This commit is contained in:
rtm516
2026-03-07 19:55:44 +00:00
committed by GitHub
parent e5ad785803
commit 9cac3e0394
8 changed files with 207 additions and 133 deletions

View File

@@ -21,7 +21,7 @@ jobs:
- name: Setup msbuild
uses: microsoft/setup-msbuild@v2
- name: Build
run: MSBuild.exe MinecraftConsoles.sln /p:Configuration=Release /p:Platform="Windows64"
@@ -30,7 +30,6 @@ jobs:
- name: Update release
uses: andelf/nightly-release@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:

View File

@@ -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;
const wstring ClientConstants::VERSION_STRING = wstring(L"Minecraft LCE ") + VER_FILEVERSION_STR_W;//+ SharedConstants::VERSION_STRING;

View File

@@ -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

View File

@@ -859,89 +859,177 @@ 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;
vector<wstring> lines;
if(minecraft->level->dimension->id==0)
{
wstring wfeature[eTerrainFeature_Count];
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
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;
}
}
for( int i = eTerrainFeature_Stronghold; i < (int) eTerrainFeature_Count; i++ )
{
iYPos+=10;
font->drawShadow(wfeature[i], debugLeft, iYPos, 0xffffff);
}
// 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);
//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);
*/
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;
}
// 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;
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);
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))
// 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))
{
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);
LevelChunk *chunkAt = minecraft->level->getChunkAt(xBlockPos, zBlockPos);
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)");
lines.push_back(L"CH S: " + std::to_wstring(chunkAt->getHeightmap(xChunkOffset, zChunkOffset)));
Biome *biome = chunkAt->getBiome(xChunkOffset, zChunkOffset, minecraft->level->getBiomeSource());
lines.push_back(L"Biome: " + biome->m_name + L" (" + std::to_wstring(biome->id) + L")");
lines.push_back(L"Difficulty: " + std::to_wstring(minecraft->level->difficulty) + L" (Day " + std::to_wstring(minecraft->level->getGameTime() / Level::TICKS_PER_DAY) + L")");
}
// 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;
}
glPopMatrix();
}
MemSect(0);

View File

@@ -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>

View File

@@ -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;

View File

@@ -39,3 +39,5 @@ foreach ($copy in $copies) {
xcopy /q /y /i /s /e /d "$src" "$dst" 2>$null
}
}
git restore "**/BuildVer.h"

View File

@@ -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"