diff --git a/.github/workflows/build-linux.yml b/.github/workflows/build-linux.yml
index 7d73c103d..ece858d39 100644
--- a/.github/workflows/build-linux.yml
+++ b/.github/workflows/build-linux.yml
@@ -1,41 +1,40 @@
-name: Build (Linux, x86_64)
+name: Build (Linux, x86-64)
on:
push:
- paths:
+ paths: &workflow_paths
- '**.cpp'
- '**.h'
- '**.c'
- - '**/meson.build'
- - 'meson.build'
- - '**/CMakeLists.txt'
- - 'CMakeLists.txt'
+ - '**.cc'
+ - '**.cxx'
+ - '**.hh'
+ - '**.hpp'
+ - '**.hxx'
+ - '**.inl'
+ - "**meson.build"
+ - "flake.nix"
- '.github/workflows/build-linux.yml'
+
pull_request:
- paths:
- - '**.cpp'
- - '**.h'
- - '**.c'
- - '**/meson.build'
- - 'meson.build'
- - '**/CMakeLists.txt'
- - 'CMakeLists.txt'
- - '.github/workflows/build-linux.yml'
+ paths: *workflow_paths
jobs:
build-linux:
runs-on: ubuntu-latest
+
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
- name: Install system dependencies
run: |
sudo apt-get update
- sudo apt-get install -y build-essential ccache python3 python3-pip ninja-build libsdl2-dev libgl-dev libglu1-mesa-dev libpthread-stubs0-dev
+ sudo apt-get install -y build-essential ccache python3 python3-pip ninja-build libsdl2-dev libgl-dev libglu1-mesa-dev libpthread-stubs0-dev libglm-dev
python -m pip install meson
# Set a reasonable ccache size
ccache -M 5G || true
+ python -m pip install meson
- name: Restore ccache
uses: actions/cache@v4
@@ -57,7 +56,7 @@ jobs:
run: |
mkdir -p "$CCACHE_DIR"
export CCACHE_DIR="$CCACHE_DIR"
- meson setup build_release --wipe --buildtype=release --native-file=./scripts/llvm_native.txt
+ meson setup build --wipe --native-file=./scripts/llvm_native.txt
- name: Build with Meson
env:
@@ -67,7 +66,7 @@ jobs:
run: |
export CCACHE_DIR="${{ runner.temp }}/ccache"
# Use all available cores for faster parallel builds
- meson compile -C build_release -j $(nproc) -v Minecraft.Client
+ meson compile -C build -j $(nproc) -v Minecraft.Client
- name: Install patchelf
run: sudo apt-get install -y patchelf
@@ -75,58 +74,6 @@ jobs:
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
- name: minecraft-client-linux-release_exe-${{ github.sha }}
- path: build_release/Minecraft.Client/Minecraft.Client
- retention-days: 7
- build-linux-debug:
- runs-on: ubuntu-latest
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- - name: Install system dependencies
- run: |
- sudo apt-get update
- sudo apt-get install -y build-essential ccache python3 python3-pip ninja-build libsdl2-dev libgl-dev libglu1-mesa-dev libpthread-stubs0-dev
- python -m pip install meson
- # Set a reasonable ccache size
- ccache -M 5G || true
-
- - name: Restore ccache
- uses: actions/cache@v4
- with:
- path: ~/.ccache
- key: ${{ runner.os }}-ccache-debug-${{ hashFiles('**/meson.build') }}
-
- - name: Restore meson cache
- uses: actions/cache@v4
- with:
- path: ~/.cache/meson
- key: ${{ runner.os }}-meson-debug-${{ hashFiles('**/meson.build') }}
-
- - name: Configure Meson (debug)
- env:
- CC: "ccache clang"
- CXX: "ccache clang++"
- CCACHE_DIR: ${{ runner.temp }}/ccache
- run: |
- mkdir -p "$CCACHE_DIR"
- export CCACHE_DIR="$CCACHE_DIR"
- meson setup build_debug --wipe --buildtype=debug --native-file=./scripts/llvm_native.txt
-
- - name: Build Debug with Meson
- env:
- CC: "ccache clang"
- CXX: "ccache clang++"
- CCACHE_DIR: ${{ runner.temp }}/ccache
- run: |
- export CCACHE_DIR="${{ runner.temp }}/ccache"
- # Use all available cores for faster parallel builds
- meson compile -C build_debug -j $(nproc) -v Minecraft.Client
-
- - name: Upload debug executable
- uses: actions/upload-artifact@v4
- with:
- name: minecraft-client-linux-debug_exe-${{ github.sha }}
- path: build_debug/Minecraft.Client/Minecraft.Client
- retention-days: 7
+ name: minecraft-client-linux-${{ github.sha }}
+ path: build/Minecraft.Client/Minecraft.Client
+ retention-days: 7
\ No newline at end of file
diff --git a/.github/workflows/clang-format.yml b/.github/workflows/clang-format.yml
index 4965d4b15..84820ad88 100644
--- a/.github/workflows/clang-format.yml
+++ b/.github/workflows/clang-format.yml
@@ -1,22 +1,8 @@
-name: Clang Format
+name: Format Check
on:
push:
- paths:
- - '**.cpp'
- - '**.h'
- - '**.c'
- - '**.cc'
- - '**.cxx'
- - '**.hh'
- - '**.hpp'
- - '**.hxx'
- - '**.inl'
- - '.clang-format'
- - '.github/workflows/clang-format.yml'
- - '.github/scripts/check-clang-format.sh'
- pull_request:
- paths:
+ paths: &workflow_paths
- '**.cpp'
- '**.h'
- '**.c'
@@ -30,26 +16,29 @@ on:
- '.github/workflows/clang-format.yml'
- '.github/scripts/check-clang-format.sh'
+ pull_request:
+ paths: *workflow_paths
+
jobs:
clang-format:
- runs-on: ubuntu-24.04
+ runs-on: ubuntu-latest
concurrency:
group: clang-format-${{ github.ref }}
cancel-in-progress: true
steps:
- name: Checkout repository
- uses: actions/checkout@v4
+ uses: actions/checkout@v6
with:
- fetch-depth: 0
+ fetch-depth: 2
- name: Install clang-format
- run: |
- sudo apt-get update
- sudo apt-get install -y clang-format-19
+ uses: daaku/gh-action-apt-install@v4
+ with:
+ packages: clang-format
- name: Check changed files
env:
- CLANG_FORMAT_BIN: clang-format-19
+ CLANG_FORMAT_BIN: clang-format
EVENT_NAME: ${{ github.event_name }}
PR_BASE_REF: ${{ github.event.pull_request.base.ref }}
PR_BASE_SHA: ${{ github.event.pull_request.base.sha }}
diff --git a/Minecraft.Assets/Common/res/1_2_2/gui/anvil.png b/Minecraft.Assets/Common/res/1_2_2/gui/anvil.png
new file mode 100644
index 000000000..34e8f9f9f
Binary files /dev/null and b/Minecraft.Assets/Common/res/1_2_2/gui/anvil.png differ
diff --git a/Minecraft.Assets/Common/res/1_2_2/gui/beacon.png b/Minecraft.Assets/Common/res/1_2_2/gui/beacon.png
new file mode 100644
index 000000000..f51a2ef51
Binary files /dev/null and b/Minecraft.Assets/Common/res/1_2_2/gui/beacon.png differ
diff --git a/Minecraft.Assets/Common/res/1_2_2/gui/brewing_stand.png b/Minecraft.Assets/Common/res/1_2_2/gui/brewing_stand.png
new file mode 100644
index 000000000..e7dc2031a
Binary files /dev/null and b/Minecraft.Assets/Common/res/1_2_2/gui/brewing_stand.png differ
diff --git a/Minecraft.Assets/Common/res/1_2_2/gui/hopper.png b/Minecraft.Assets/Common/res/1_2_2/gui/hopper.png
new file mode 100644
index 000000000..3d0054790
Binary files /dev/null and b/Minecraft.Assets/Common/res/1_2_2/gui/hopper.png differ
diff --git a/Minecraft.Assets/Common/res/1_2_2/gui/horse.png b/Minecraft.Assets/Common/res/1_2_2/gui/horse.png
new file mode 100644
index 000000000..194cc6bf6
Binary files /dev/null and b/Minecraft.Assets/Common/res/1_2_2/gui/horse.png differ
diff --git a/Minecraft.Assets/Common/res/1_2_2/gui/inventory.png b/Minecraft.Assets/Common/res/1_2_2/gui/inventory.png
index 4d9911690..d553c4f73 100644
Binary files a/Minecraft.Assets/Common/res/1_2_2/gui/inventory.png and b/Minecraft.Assets/Common/res/1_2_2/gui/inventory.png differ
diff --git a/Minecraft.Assets/Common/res/1_2_2/gui/villager.png b/Minecraft.Assets/Common/res/1_2_2/gui/villager.png
new file mode 100644
index 000000000..3211a7a00
Binary files /dev/null and b/Minecraft.Assets/Common/res/1_2_2/gui/villager.png differ
diff --git a/Minecraft.Assets/Common/res/1_2_2/title/bg/panorama.png b/Minecraft.Assets/Common/res/1_2_2/title/bg/panorama.png
new file mode 100644
index 000000000..65ae6070c
Binary files /dev/null and b/Minecraft.Assets/Common/res/1_2_2/title/bg/panorama.png differ
diff --git a/Minecraft.Assets/Common/res/lang/en_US.lang b/Minecraft.Assets/Common/res/lang/en_US.lang
index 752a60f39..44040b2b7 100644
--- a/Minecraft.Assets/Common/res/lang/en_US.lang
+++ b/Minecraft.Assets/Common/res/lang/en_US.lang
@@ -435,6 +435,9 @@ tile.oreEmerald.name=Emerald Ore
tile.blockEmerald.name=Block of Emerald
tile.tripWire.name=Tripwire
tile.tripWireSource.name=Tripwire Hook
+tile.beacon.name=Beacon
+tile.beacon.primary=Primary Power
+tile.beacon.secondary=Secondary Power
item.shovelIron.name=Iron Shovel
item.pickaxeIron.name=Iron Pickaxe
@@ -595,6 +598,9 @@ container.crafting=Crafting
container.dispenser=Dispenser
container.furnace=Furnace
container.enchant=Enchant
+container.repair=Repair & Name
+container.repair.cost=Enchantment Cost: %d
+container.repair.expensive=Too Expensive!
container.creative=Item Selection
container.brewing=Brewing Stand
container.chest=Chest
diff --git a/Minecraft.Assets/Windows64Media/loc/en-EN/strings.lang b/Minecraft.Assets/Windows64Media/loc/en-EN/strings.lang
index 752552227..f29d1e6a8 100644
--- a/Minecraft.Assets/Windows64Media/loc/en-EN/strings.lang
+++ b/Minecraft.Assets/Windows64Media/loc/en-EN/strings.lang
@@ -4760,6 +4760,9 @@ Would you like to unlock the full game?
Food
+
+ Search Items
+
Structures
@@ -7068,6 +7071,9 @@ All Ender Chests in a world are linked. Items placed into an Ender Chest are acc
OK
+
+ Cancel
+
SELECT
@@ -7195,6 +7201,9 @@ You can upload a world save to the save transfer area using Minecraft: PlayStati
Exit Game
+
+ Are you sure you want to exit the game?
+
You have been returned to the title screen because your Xbox profile was signed out
diff --git a/Minecraft.Assets/Windows64Media/loc/stringsGeneric.xml b/Minecraft.Assets/Windows64Media/loc/stringsGeneric.xml
index 36b521dd0..ec3b88e28 100644
--- a/Minecraft.Assets/Windows64Media/loc/stringsGeneric.xml
+++ b/Minecraft.Assets/Windows64Media/loc/stringsGeneric.xml
@@ -1,4 +1,4 @@
-
+
New Downloadable Content is available! Access it from the Minecraft Store button on the Main Menu.
@@ -6044,6 +6044,10 @@ Would you like to unlock the full game now?
Food
+
+ Search Items
+
+
Structures
@@ -8811,4 +8815,4 @@ All Ender Chests in a world are linked. Items placed into an Ender Chest are acc
Cure
-
\ No newline at end of file
+
diff --git a/Minecraft.Client/GameState/Options.cpp b/Minecraft.Client/GameState/Options.cpp
index 0723f7690..9013e52b6 100644
--- a/Minecraft.Client/GameState/Options.cpp
+++ b/Minecraft.Client/GameState/Options.cpp
@@ -89,8 +89,15 @@ const std::wstring Options::DIFFICULTY_NAMES[] = {
const std::wstring Options::GUI_SCALE[] = {
L"options.guiScale.auto", L"options.guiScale.small",
L"options.guiScale.normal", L"options.guiScale.large"};
+
+#ifdef ENABLE_VSYNC
const std::wstring Options::FRAMERATE_LIMITS[] = {
L"performance.max", L"performance.balanced", L"performance.powersaver"};
+#else
+const std::wstring Options::FRAMERATE_LIMITS[] = {
+ L"performance.max", L"performance.balanced", L"performance.powersaver",
+ L"performance.unlimited"};
+#endif
const std::wstring Options::PARTICLES[] = {L"options.particles.all",
L"options.particles.decreased",
@@ -223,21 +230,24 @@ void Options::toggle(const Options::Option* option, int dir) {
if (option == Option::PARTICLES) particles = (particles + dir) % 3;
// 4J-PB - changing
- // if (option == Option::VIEW_BOBBING) bobView = !bobView;
- if (option == Option::VIEW_BOBBING)
- ((dir == 0) ? bobView = false : bobView = true);
+ // 4jcraft: uncommented this so that the view bobbing option works
+ if (option == Option::VIEW_BOBBING) bobView = !bobView;
if (option == Option::RENDER_CLOUDS) renderClouds = !renderClouds;
if (option == Option::ADVANCED_OPENGL) {
advancedOpengl = !advancedOpengl;
- // 4jcraft: ensure level exists before applying
- if(minecraft->level) minecraft->levelRenderer->allChanged();
+ // 4jcraft: ensure level exists before applying
+ if (minecraft->level) minecraft->levelRenderer->allChanged();
}
if (option == Option::ANAGLYPH) {
anaglyph3d = !anaglyph3d;
minecraft->textures->reloadAll();
}
if (option == Option::FRAMERATE_LIMIT)
+#ifdef ENABLE_VSYNC
framerateLimit = (framerateLimit + dir + 3) % 3;
+#else
+ framerateLimit = (framerateLimit + dir + 4) % 4;
+#endif
// 4J-PB - Change for Xbox
// if (option == Option::DIFFICULTY) difficulty = (difficulty + dir) & 3;
@@ -247,13 +257,13 @@ void Options::toggle(const Options::Option* option, int dir) {
if (option == Option::GRAPHICS) {
fancyGraphics = !fancyGraphics;
- // 4jcraft: ensure level exists before applying
- if(minecraft->level) minecraft->levelRenderer->allChanged();
+ // 4jcraft: ensure level exists before applying
+ if (minecraft->level) minecraft->levelRenderer->allChanged();
}
if (option == Option::AMBIENT_OCCLUSION) {
ambientOcclusion = !ambientOcclusion;
- // 4jcraft: ensure level exists before applying
- if(minecraft->level) minecraft->levelRenderer->allChanged();
+ // 4jcraft: ensure level exists before applying
+ if (minecraft->level) minecraft->levelRenderer->allChanged();
}
// 4J-PB - don't do the file save on the xbox
diff --git a/Minecraft.Client/Level/ServerLevel.cpp b/Minecraft.Client/Level/ServerLevel.cpp
index 7ca06e9b1..00e943a91 100644
--- a/Minecraft.Client/Level/ServerLevel.cpp
+++ b/Minecraft.Client/Level/ServerLevel.cpp
@@ -1,3 +1,6 @@
+#include
+#include
+
#include "../Platform/stdafx.h"
#include "ServerLevel.h"
#include "../MinecraftServer.h"
@@ -1091,13 +1094,13 @@ std::shared_ptr ServerLevel::explode(std::shared_ptr source,
}
if (player->distanceToSqr(x, y, z) < 64 * 64) {
- Vec3* knockbackVec = explosion->getHitPlayerKnockback(player);
+ Vec3 knockbackVec = explosion->getHitPlayerKnockback(player);
// app.DebugPrintf("Sending %s with knockback (%f,%f,%f)\n",
// knockbackOnly?"knockbackOnly":"allExplosion",knockbackVec->x,knockbackVec->y,knockbackVec->z);
// If the player is not the primary on the system, then we only
// want to send info for the knockback
player->connection->send(std::shared_ptr(
- new ExplodePacket(x, y, z, r, &explosion->toBlow, knockbackVec,
+ new ExplodePacket(x, y, z, r, &explosion->toBlow, &knockbackVec,
knockbackOnly)));
sentTo.push_back(player);
}
diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp
index e416094ad..58677c90a 100644
--- a/Minecraft.Client/Minecraft.cpp
+++ b/Minecraft.Client/Minecraft.cpp
@@ -1,3 +1,6 @@
+#include
+#include
+
#include "Platform/stdafx.h"
#include "Minecraft.h"
#include "GameState/GameMode.h"
@@ -997,8 +1000,6 @@ void Minecraft::run_middle() {
// try { // 4J - removed try/catch
// if (minecraftApplet != null &&
// !minecraftApplet.isActive()) break; // 4J - removed
- AABB::resetPool();
- Vec3::resetPool();
// if (parent == NULL && Display.isCloseRequested()) {
// // 4J - removed
@@ -1496,13 +1497,16 @@ void Minecraft::run_middle() {
// clear the stored button downs since the tick for this
// player will now have actioned them
player->ullButtonsPressed = 0LL;
+ } else if (screen != NULL) {
+ screen->updateEvents();
+ // 4jcraft: this fixes the title screen panorama running
+ // faster than it should
+ if (!idx) {
+ screen->tick();
+ }
}
}
- if (screen != NULL) {
- screen->updateEvents();
- }
-
ui.HandleGameTick();
setLocalPlayerIdx(ProfileManager.GetPrimaryPad());
@@ -1625,7 +1629,7 @@ void Minecraft::run_middle() {
{
this->toggleFullScreen();
}
- Sleep(10);
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
*/
@@ -1654,7 +1658,10 @@ void Minecraft::run_middle() {
achievementPopup->render();
PIXBeginNamedEvent(0, "Sleeping");
- Sleep(0); // 4J - was Thread.yield()
+ std::this_thread::yield(); // 4jcraft added now that we have
+ // portable thread yield.
+ // std::this_thread::sleep_for(
+ // std::chrono::milliseconds(0)); // 4J - was Thread.yield())
PIXEndNamedEvent();
// if (Keyboard::isKeyDown(Keyboard::KEY_F7))
@@ -1735,8 +1742,6 @@ void Minecraft::run_end() { destroy(); }
void Minecraft::emergencySave() {
// 4J - lots of try/catches removed here, and garbage collector things
levelRenderer->clear();
- AABB::clearPool();
- Vec3::clearPool();
setLevel(NULL);
}
@@ -1912,8 +1917,6 @@ void Minecraft::levelTickUpdateFunc(void* pParam) {
}
void Minecraft::levelTickThreadInitFunc() {
- AABB::CreateNewThreadStorage();
- Vec3::CreateNewThreadStorage();
Compression::UseDefaultThreadStorage();
}
@@ -2247,7 +2250,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) {
// 4J-PB - Call the useItemOn with the TestOnly flag set
bool bUseItemOn = gameMode->useItemOn(
player, level, itemInstance, x, y, z, face,
- hitResult->pos, true);
+ &hitResult->pos, true);
/* 4J-Jev:
* Moved this here so we have item tooltips to
@@ -3391,7 +3394,7 @@ void Minecraft::tick(bool bFirst, bool bUpdateTextures) {
bool usedItem = false;
gameMode->useItemOn(player, level, nullptr, hitResult->x,
hitResult->y, hitResult->z, 0,
- hitResult->pos, false, &usedItem);
+ &hitResult->pos, false, &usedItem);
} else {
ui.PlayUISFX(eSFX_Press);
app.LoadCrafting2x2Menu(iPad, player);
diff --git a/Minecraft.Client/MinecraftServer.cpp b/Minecraft.Client/MinecraftServer.cpp
index 7440acca3..144419181 100644
--- a/Minecraft.Client/MinecraftServer.cpp
+++ b/Minecraft.Client/MinecraftServer.cpp
@@ -2,6 +2,8 @@
// #include "Minecraft.h"
#include
+#include
+#include
#include "Input/ConsoleInput.h"
#include "Level/DerivedServerLevel.h"
@@ -165,7 +167,7 @@ bool MinecraftServer::initServer(__int64 seed, NetworkGameInitData* initData,
// 4J-JEV: Need to wait for levelGenerationOptions to load.
while (app.getLevelGenerationOptions() != NULL &&
!app.getLevelGenerationOptions()->hasLoadedData())
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
if (app.getLevelGenerationOptions() != NULL &&
!app.getLevelGenerationOptions()->ready()) {
@@ -235,8 +237,6 @@ int MinecraftServer::runPostUpdate(void* lpParam) {
MinecraftServer* server = (MinecraftServer*)lpParam;
Entity::useSmallIds(); // This thread can end up spawning entities as
// resources
- AABB::CreateNewThreadStorage();
- Vec3::CreateNewThreadStorage();
Compression::UseDefaultThreadStorage();
Level::enableLightingCache();
Tile::CreateNewThreadStorage();
@@ -257,7 +257,7 @@ int MinecraftServer::runPostUpdate(void* lpParam) {
} else {
LeaveCriticalSection(&server->m_postProcessCS);
}
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
} while (!server->m_postUpdateTerminate &&
ShutdownManager::ShouldRun(ShutdownManager::ePostProcessThread));
// #ifndef 0
@@ -277,8 +277,6 @@ int MinecraftServer::runPostUpdate(void* lpParam) {
LeaveCriticalSection(&server->m_postProcessCS);
// #endif //0
Tile::ReleaseThreadStorage();
- AABB::ReleaseThreadStorage();
- Vec3::ReleaseThreadStorage();
Level::destroyLightingCache();
ShutdownManager::HasFinished(ShutdownManager::ePostProcessThread);
@@ -1365,7 +1363,7 @@ void MinecraftServer::run(int64_t seed, void* lpParameter) {
app.SetXuiServerAction(i, eXuiServerAction_Idle);
}
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
// else
@@ -1373,7 +1371,7 @@ void MinecraftServer::run(int64_t seed, void* lpParameter) {
// while (running)
// {
// handleConsoleInputs();
- // Sleep(10);
+ // std::this_thread::sleep_for(std::chrono::milliseconds(10));
// }
// }
@@ -1410,9 +1408,6 @@ void MinecraftServer::tick() {
ironTimers.erase(toRemove[i]);
}
- AABB::resetPool();
- Vec3::resetPool();
-
tickCount++;
// 4J We need to update client difficulty levels based on the servers
diff --git a/Minecraft.Client/Network/ClientConnection.cpp b/Minecraft.Client/Network/ClientConnection.cpp
index f2a6662cc..120ea51bb 100644
--- a/Minecraft.Client/Network/ClientConnection.cpp
+++ b/Minecraft.Client/Network/ClientConnection.cpp
@@ -46,6 +46,7 @@
#include "../ClientConstants.h"
#include "../../Minecraft.World/Util/SoundTypes.h"
#include "../Textures/Packs/TexturePackRepository.h"
+#include "UI/Screens/MerchantScreen.h"
#include "../Platform/Common/UI/UI.h"
#include "../Textures/Packs/DLCTexturePack.h"
@@ -945,7 +946,7 @@ void ClientConnection::handleMovePlayer(
player->xd = player->yd = player->zd = 0;
player->absMoveTo(x, y, z, yRot, xRot);
packet->x = player->x;
- packet->y = player->bb->y0;
+ packet->y = player->bb.y0;
packet->z = player->z;
packet->yView = player->y;
connection->send(packet);
@@ -3235,6 +3236,17 @@ void ClientConnection::handleCustomPayload(
ByteArrayInputStream bais(customPayloadPacket->data);
DataInputStream input(&bais);
int containerId = input.readInt();
+#ifdef ENABLE_JAVA_GUIS
+ // 4jcraft: use the java gui getMerchant() to get trader as we don't
+ // have iggy's screen anymore
+ if (minecraft->screen &&
+ dynamic_cast(minecraft->screen) &&
+ containerId == minecraft->localplayers[m_userIndex]
+ ->containerMenu->containerId) {
+ std::shared_ptr trader = nullptr;
+ MerchantScreen* screen = (MerchantScreen*)minecraft->screen;
+ trader = screen->getMerchant();
+#else
if (ui.IsSceneInStack(m_userIndex, eUIScene_TradingMenu) &&
containerId == minecraft->localplayers[m_userIndex]
->containerMenu->containerId) {
@@ -3243,7 +3255,8 @@ void ClientConnection::handleCustomPayload(
UIScene* scene = ui.GetTopScene(m_userIndex, eUILayer_Scene);
UIScene_TradingMenu* screen = (UIScene_TradingMenu*)scene;
trader = screen->getMerchant();
-
+#endif
+#endif
MerchantRecipeList* recipeList =
MerchantRecipeList::createFromStream(&input);
trader->overrideOffers(recipeList);
diff --git a/Minecraft.Client/Network/PlayerConnection.cpp b/Minecraft.Client/Network/PlayerConnection.cpp
index e09bc00ef..e5323972e 100644
--- a/Minecraft.Client/Network/PlayerConnection.cpp
+++ b/Minecraft.Client/Network/PlayerConnection.cpp
@@ -272,8 +272,9 @@ void PlayerConnection::handleMovePlayer(
*/
float r = 1 / 16.0f;
+ AABB shrunk = player->bb.shrink(r, r, r);
bool oldOk =
- level->getCubes(player, player->bb->copy()->shrink(r, r, r))
+ level->getCubes(player, &shrunk)
->empty();
if (player->onGround && !packet->onGround && yDist > 0) {
@@ -324,17 +325,19 @@ void PlayerConnection::handleMovePlayer(
}
player->absMoveTo(xt, yt, zt, yRotT, xRotT);
+ // TODO: check if this can be elided
+ shrunk = player->bb.shrink(r, r, r);
bool newOk =
- level->getCubes(player, player->bb->copy()->shrink(r, r, r))
+ level->getCubes(player, &shrunk)
->empty();
if (oldOk && (fail || !newOk) && !player->isSleeping()) {
teleport(xLastOk, yLastOk, zLastOk, yRotT, xRotT);
return;
}
- AABB* testBox = player->bb->copy()->grow(r, r, r)->expand(0, -0.55, 0);
+ AABB testBox = player->bb.grow(r, r, r).expand(0, -0.55, 0);
// && server.level.getCubes(player, testBox).size() == 0
if (!server->isFlightAllowed() && !player->gameMode->isCreative() &&
- !level->containsAnyBlocks(testBox) && !player->isAllowedToFly()) {
+ !level->containsAnyBlocks(&testBox) && !player->isAllowedToFly()) {
if (oyDist >= (-0.5f / 16.0f)) {
aboveGroundTickCount++;
if (aboveGroundTickCount > 80) {
@@ -1517,7 +1520,8 @@ void PlayerConnection::handlePlayerAbilities(
// StringBuilder result = new StringBuilder();
// for (String candidate : server.getAutoCompletions(player,
-//packet.getMessage())) { if (result.length() > 0) result.append("\0");
+// packet.getMessage())) { if (result.length() > 0)
+// result.append("\0");
// result.append(candidate);
// }
diff --git a/Minecraft.Client/Network/PlayerList.cpp b/Minecraft.Client/Network/PlayerList.cpp
index cce086cba..74e1c4fa9 100644
--- a/Minecraft.Client/Network/PlayerList.cpp
+++ b/Minecraft.Client/Network/PlayerList.cpp
@@ -398,7 +398,7 @@ void PlayerList::validatePlayerSpawnPosition(
player->y, player->z, player->dimension);
ServerLevel* level = server->getLevel(player->dimension);
- while (level->getCubes(player, player->bb)->size() != 0) {
+ while (level->getCubes(player, &player->bb)->size() != 0) {
player->setPos(player->x, player->y + 1, player->z);
}
app.DebugPrintf("Final pos is %f, %f, %f in dimension %d\n", player->x,
@@ -438,7 +438,7 @@ void PlayerList::validatePlayerSpawnPosition(
}
delete bedPosition;
}
- while (level->getCubes(player, player->bb)->size() != 0) {
+ while (level->getCubes(player, &player->bb)->size() != 0) {
player->setPos(player->x, player->y + 1, player->z);
}
@@ -731,7 +731,7 @@ std::shared_ptr PlayerList::respawn(
// Ensure the area the player is spawning in is loaded!
level->cache->create(((int)player->x) >> 4, ((int)player->z) >> 4);
- while (!level->getCubes(player, player->bb)->empty()) {
+ while (!level->getCubes(player, &player->bb)->empty()) {
player->setPos(player->x, player->y + 1, player->z);
}
diff --git a/Minecraft.Client/Network/ServerChunkCache.cpp b/Minecraft.Client/Network/ServerChunkCache.cpp
index 5fda09389..b72c07d57 100644
--- a/Minecraft.Client/Network/ServerChunkCache.cpp
+++ b/Minecraft.Client/Network/ServerChunkCache.cpp
@@ -1,3 +1,6 @@
+#include
+#include
+
#include "../Platform/stdafx.h"
#include "ServerChunkCache.h"
#include "../Level/ServerLevel.h"
diff --git a/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp b/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp
index c997aa7d4..4ca675569 100644
--- a/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp
+++ b/Minecraft.Client/Platform/Common/Audio/SoundEngine.cpp
@@ -1,6 +1,6 @@
#include "../../Minecraft.World/Platform/stdafx.h"
-
#include "SoundEngine.h"
+#include "PathHelper.h"
#include "../Consoles_App.h"
#include "../../Minecraft.Client/Player/MultiPlayerLocalPlayer.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.h"
@@ -79,8 +79,8 @@ const char* SoundEngine::m_szStreamFileA[eStream_Max] = {"calm1",
"ward",
"where_are_we_now"};
#if defined(__linux__)
-char SoundEngine::m_szSoundPath[] = {"Sound/"};
-char SoundEngine::m_szMusicPath[] = {"music/"};
+char SoundEngine::m_szSoundPath[] = {"Common/Sound/"};
+char SoundEngine::m_szMusicPath[] = {"Common/"};
char SoundEngine::m_szRedistName[] = {"redist64"};
#endif
@@ -150,170 +150,121 @@ void SoundEngine::init(Options* pOptions) {
m_bSystemMusicPlaying = false;
}
void SoundEngine::destroy() { ma_engine_uninit(&m_engine); }
+
void SoundEngine::play(int iSound, float x, float y, float z, float volume,
float pitch) {
- char szSoundName[256] = "Sound/Minecraft/";
+ if (iSound == -1) return;
+ char szId[256];
+ wcstombs(szId, wchSoundNames[iSound], 255);
+ for (int i = 0; szId[i]; i++)
+ if (szId[i] == '.') szId[i] = '/';
- if (iSound == -1) {
- app.DebugPrintf(6, "PlaySound with sound of -1 !!!!!!!!!!!!!!!\n");
- return;
- }
- wcstombs(szSoundName + 16, wchSoundNames[iSound],
- sizeof(szSoundName) - 16 - 1);
- szSoundName[sizeof(szSoundName) - 1] = '\0';
-
- char finalPath[256];
- const char* extensions[] = {".ogg", ".wav", ".mp3"};
- size_t extCount = sizeof(extensions) / sizeof(extensions[0]);
+ std::string base = PathHelper::GetExecutableDirA() + "/";
+ const char* roots[] = {"Sound/Minecraft/", "Common/Sound/Minecraft/",
+ "Common/res/TitleUpdate/res/Sound/Minecraft/"};
+ char finalPath[512] = {0};
bool found = false;
- for (size_t extIdx = 0; extIdx < extCount; extIdx++) {
- char basePlusExt[256];
- sprintf_s(basePlusExt, "%s%s", szSoundName, extensions[extIdx]);
-
- DWORD attr = GetFileAttributesA(basePlusExt);
- if (attr != INVALID_FILE_ATTRIBUTES &&
- !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
- sprintf_s(finalPath, "%s", basePlusExt);
- found = true;
- break;
- }
- }
- if (!found) {
- int count = 0;
-
- for (size_t extIdx = 0; extIdx < extCount; extIdx++) {
- for (size_t i = 1; i < 32; i++) {
- char numberedPath[256];
- sprintf_s(numberedPath, "%s%d%s", szSoundName, i,
- extensions[extIdx]);
-
- DWORD attr = GetFileAttributesA(numberedPath);
- if (attr != INVALID_FILE_ATTRIBUTES &&
- !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
+ for (const char* root : roots) {
+ std::string fullRoot = base + root;
+ for (const char* ext : {".ogg", ".wav"}) {
+ int count = 0;
+ for (int i = 1; i <= 16; i++) {
+ char tryP[512];
+ snprintf(tryP, 512, "%s%s%d%s", fullRoot.c_str(), szId, i, ext);
+ if (access(tryP, F_OK) != -1)
count = i;
- }
- }
- }
-
- if (count > 0) {
- int chosen = (rand() % count) + 1;
- for (size_t extIdx = 0; extIdx < extCount; extIdx++) {
- char numberedPath[256];
- sprintf_s(numberedPath, "%s%d%s", szSoundName, chosen,
- extensions[extIdx]);
-
- DWORD attr = GetFileAttributesA(numberedPath);
- if (attr != INVALID_FILE_ATTRIBUTES &&
- !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
- sprintf_s(finalPath, "%s", numberedPath);
- found = true;
+ else
break;
- }
}
- if (!found) {
- sprintf_s(finalPath, "%s%d.ogg", szSoundName, chosen);
+ if (count > 0) {
+ snprintf(finalPath, 512, "%s%s%d%s", fullRoot.c_str(), szId,
+ (rand() % count) + 1, ext);
+ found = true;
+ break;
+ }
+ char tryP[512];
+ snprintf(tryP, 512, "%s%s%s", fullRoot.c_str(), szId, ext);
+ if (access(tryP, F_OK) != -1) {
+ strncpy(finalPath, tryP, 511);
+ found = true;
+ break;
}
}
+ if (found) break;
}
+
if (!found) return;
MiniAudioSound* s = new MiniAudioSound();
memset(&s->info, 0, sizeof(AUDIO_INFO));
-
s->info.x = x;
s->info.y = y;
s->info.z = z;
-
s->info.volume = volume;
s->info.pitch = pitch;
s->info.bIs3D = true;
- s->info.bUseSoundsPitchVal = false;
- s->info.iSound = iSound + eSFX_MAX;
if (ma_sound_init_from_file(&m_engine, finalPath, MA_SOUND_FLAG_ASYNC,
- nullptr, nullptr, &s->sound) != MA_SUCCESS) {
- app.DebugPrintf("Failed to load sound ID : %i from %S\n", iSound,
- wchSoundNames[iSound]);
+ nullptr, nullptr, &s->sound) == MA_SUCCESS) {
+ ma_sound_set_spatialization_enabled(&s->sound, MA_TRUE);
+ ma_sound_set_min_distance(&s->sound, 2.0f);
+ ma_sound_set_max_distance(&s->sound, 48.0f);
+ ma_sound_set_volume(&s->sound, volume * m_MasterEffectsVolume);
+ ma_sound_set_position(&s->sound, x, y, z);
+ ma_sound_start(&s->sound);
+ m_activeSounds.push_back(s);
+ } else
delete s;
- return;
- }
-
- ma_sound_set_spatialization_enabled(&s->sound, MA_TRUE);
- ma_sound_set_min_distance(&s->sound, SFX_3D_MIN_DISTANCE);
- ma_sound_set_max_distance(&s->sound, SFX_3D_MAX_DISTANCE);
- ma_sound_set_rolloff(&s->sound, SFX_3D_ROLLOFF);
-
- float finalVolume = volume * m_MasterEffectsVolume * SFX_VOLUME_MULTIPLIER;
- if (finalVolume > SFX_MAX_GAIN) finalVolume = SFX_MAX_GAIN;
-
- ma_sound_set_volume(&s->sound, finalVolume);
- ma_sound_set_pitch(&s->sound, pitch);
- ma_sound_set_position(&s->sound, x, y, z);
-
- ma_sound_start(&s->sound);
-
- m_activeSounds.push_back(s);
}
void SoundEngine::playUI(int iSound, float volume, float pitch) {
- char szSoundName[256];
- wstring name;
-
- if (iSound >= eSFX_MAX) {
- strcpy(szSoundName, "Sound/Minecraft/");
- name = wchSoundNames[iSound];
- } else {
- strcpy(szSoundName, "Sound/Minecraft/UI/");
- name = wchUISoundNames[iSound];
- }
- wcstombs(szSoundName + strlen(szSoundName), name.c_str(),
- sizeof(szSoundName) - strlen(szSoundName) - 1);
- char finalPath[256];
- const char* extensions[] = {".ogg", ".wav", ".mp3"};
- size_t extCount = sizeof(extensions) / sizeof(extensions[0]);
+ char szIdentifier[256];
+ if (iSound >= eSFX_MAX)
+ wcstombs(szIdentifier, wchSoundNames[iSound], 255);
+ else
+ wcstombs(szIdentifier, wchUISoundNames[iSound], 255);
+ for (int i = 0; szIdentifier[i]; i++)
+ if (szIdentifier[i] == '.') szIdentifier[i] = '/';
+ std::string base = PathHelper::GetExecutableDirA() + "/";
+ const char* roots[] = {
+ "Sound/Minecraft/UI/",
+ "Sound/Minecraft/",
+ "Common/Sound/Minecraft/UI/",
+ "Common/Sound/Minecraft/",
+ };
+ char finalPath[512] = {0};
bool found = false;
- for (size_t extIdx = 0; extIdx < extCount; extIdx++) {
- char basePlusExt[256];
- sprintf_s(basePlusExt, "%s%s", szSoundName, extensions[extIdx]);
-
- DWORD attr = GetFileAttributesA(basePlusExt);
- if (attr != INVALID_FILE_ATTRIBUTES &&
- !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
- sprintf_s(finalPath, "%s", basePlusExt);
- found = true;
- break;
+ for (const char* root : roots) {
+ for (const char* ext : {".ogg", ".wav", ".mp3"}) {
+ char tryP[512];
+ snprintf(tryP, 512, "%s%s%s%s", base.c_str(), root, szIdentifier,
+ ext);
+ if (access(tryP, F_OK) != -1) {
+ strncpy(finalPath, tryP, 511);
+ found = true;
+ break;
+ }
}
+ if (found) break;
}
+
if (!found) return;
MiniAudioSound* s = new MiniAudioSound();
memset(&s->info, 0, sizeof(AUDIO_INFO));
-
s->info.volume = volume;
s->info.pitch = pitch;
s->info.bIs3D = false;
- s->info.bUseSoundsPitchVal = true;
if (ma_sound_init_from_file(&m_engine, finalPath, MA_SOUND_FLAG_ASYNC,
- nullptr, nullptr, &s->sound) != MA_SUCCESS) {
+ nullptr, nullptr, &s->sound) == MA_SUCCESS) {
+ ma_sound_set_spatialization_enabled(&s->sound, MA_FALSE);
+ ma_sound_set_volume(&s->sound, volume * m_MasterEffectsVolume);
+ ma_sound_set_pitch(&s->sound, pitch);
+ ma_sound_start(&s->sound);
+ m_activeSounds.push_back(s);
+ } else
delete s;
- app.DebugPrintf("ma_sound_init_from_file failed: %s\n", finalPath);
- return;
- }
-
- ma_sound_set_spatialization_enabled(&s->sound, MA_FALSE);
-
- float finalVolume = volume * m_MasterEffectsVolume;
- if (finalVolume > 1.0f) finalVolume = 1.0f;
- printf("UI Sound volume set to %f\nEffects volume: %f\n", finalVolume,
- m_MasterEffectsVolume);
-
- ma_sound_set_volume(&s->sound, finalVolume);
- ma_sound_set_pitch(&s->sound, pitch);
-
- ma_sound_start(&s->sound);
-
- m_activeSounds.push_back(s);
}
int SoundEngine::getMusicID(int iDomain) {
@@ -330,9 +281,10 @@ int SoundEngine::getMusicID(int iDomain) {
if (pMinecraft->skins->isUsingDefaultSkin()) {
switch (iDomain) {
case LevelData::DIMENSION_END:
- // the end isn't random - it has different music depending on
- // whether the dragon is alive or not, but we've not added the
- // dead dragon music yet
+ // the end isn't random - it has different music depending
+ // whether the dragon is alive or not, but we've not
+ // added the dead dragon music yet
+ // haha they said wheter
return m_iStream_End_Min;
case LevelData::DIMENSION_NETHER:
return GetRandomishTrack(m_iStream_Nether_Min,
@@ -450,7 +402,8 @@ int SoundEngine::OpenStreamThreadProc(void* lpParameter) {
if (result != MA_SUCCESS) {
app.DebugPrintf(
- "SoundEngine::OpenStreamThreadProc - Failed to open stream: %s\n",
+ "SoundEngine::OpenStreamThreadProc - Failed to open stream: "
+ "%s\n",
soundEngine->m_szStreamName);
return 0;
}
@@ -462,149 +415,63 @@ int SoundEngine::OpenStreamThreadProc(void* lpParameter) {
return 0;
}
-
void SoundEngine::playMusicTick() {
static float fMusicVol = 0.0f;
fMusicVol = getMasterMusicVolume();
switch (m_StreamState) {
case eMusicStreamState_Idle:
-
- // start a stream playing
if (m_iMusicDelay > 0) {
m_iMusicDelay--;
return;
}
-
- if (m_musicStreamActive) {
- app.DebugPrintf(
- "WARNING: m_musicStreamActive already true in Idle state, "
- "resetting to Playing\n");
- m_StreamState = eMusicStreamState_Playing;
- return;
- }
-
if (m_musicID != -1) {
- // start playing it
+ std::string base = PathHelper::GetExecutableDirA() + "/";
+ bool isCD = (m_musicID >= m_iStream_CD_1);
+ const char* folder = isCD ? "cds/" : "music/";
+ const char* track = m_szStreamFileA[m_musicID];
+ bool found = false;
+ m_szStreamName[0] = '\0';
- strcpy((char*)m_szStreamName, m_szMusicPath);
- // are we using a mash-up pack?
- // if(pMinecraft && !pMinecraft->skins->isUsingDefaultSkin() &&
- // pMinecraft->skins->getSelected()->hasAudio())
- if (Minecraft::GetInstance()
- ->skins->getSelected()
- ->hasAudio()) {
- // It's a mash-up - need to use the DLC path for the music
- TexturePack* pTexPack =
- Minecraft::GetInstance()->skins->getSelected();
- DLCTexturePack* pDLCTexPack = (DLCTexturePack*)pTexPack;
- DLCPack* pack = pDLCTexPack->getDLCInfoParentPack();
- DLCAudioFile* dlcAudioFile = (DLCAudioFile*)pack->getFile(
- DLCManager::e_DLCType_Audio, 0);
+ const char* roots[] = {"Common/music/", "music/", "./"};
- app.DebugPrintf("Mashup pack \n");
-
- // build the name
-
- // if the music ID is beyond the end of the texture pack
- // music files, then it's a CD
- if (m_musicID < m_iStream_CD_1) {
- SetIsPlayingStreamingGameMusic(true);
- SetIsPlayingStreamingCDMusic(false);
- m_MusicType = eMusicType_Game;
- m_StreamingAudioInfo.bIs3D = false;
-
- wstring& wstrSoundName =
- dlcAudioFile->GetSoundName(m_musicID);
-
- char szName[255];
- wcstombs(szName, wstrSoundName.c_str(), 255);
-
- string strFile =
- "TPACK:\\Data\\" + string(szName) + ".wav";
-
- std::string mountedPath =
- StorageManager.GetMountedPath(strFile);
- strcpy(m_szStreamName, mountedPath.c_str());
- } else {
- SetIsPlayingStreamingGameMusic(false);
- SetIsPlayingStreamingCDMusic(true);
- m_MusicType = eMusicType_CD;
- m_StreamingAudioInfo.bIs3D = true;
-
- // Need to adjust to index into the cds in the game's
- // m_szStreamFileA
- strcat((char*)m_szStreamName, "cds/");
- strcat((char*)m_szStreamName,
- m_szStreamFileA[m_musicID - m_iStream_CD_1 +
- eStream_CD_1]);
- strcat((char*)m_szStreamName, ".wav");
- }
- } else {
- if (m_musicID < m_iStream_CD_1) {
- SetIsPlayingStreamingGameMusic(true);
- SetIsPlayingStreamingCDMusic(false);
- m_MusicType = eMusicType_Game;
- m_StreamingAudioInfo.bIs3D = false;
- // build the name
- strcat((char*)m_szStreamName, "music/");
- } else {
- SetIsPlayingStreamingGameMusic(false);
- SetIsPlayingStreamingCDMusic(true);
- m_MusicType = eMusicType_CD;
- m_StreamingAudioInfo.bIs3D = true;
- // build the name
- strcat((char*)m_szStreamName, "cds/");
- }
- strcat((char*)m_szStreamName, m_szStreamFileA[m_musicID]);
- strcat((char*)m_szStreamName, ".wav");
- }
-
- FILE* pFile = nullptr;
- pFile = fopen(reinterpret_cast(m_szStreamName), "rb");
- if (pFile) {
- fclose(pFile);
- } else {
- const char* extensions[] = {".ogg", ".mp3", ".wav"};
- size_t extCount =
- sizeof(extensions) / sizeof(extensions[0]);
- bool found = false;
-
- char* dotPos =
- strrchr(reinterpret_cast(m_szStreamName), '.');
- if (dotPos != nullptr &&
- (dotPos - reinterpret_cast(m_szStreamName)) <
- 250) {
- for (size_t i = 0; i < extCount; i++) {
- strncpy(dotPos, extensions[i], 5);
- app.DebugPrintf("Checking %s\n", m_szStreamName);
- pFile = fopen(
- reinterpret_cast(m_szStreamName), "rb");
- if (pFile) {
- fclose(pFile);
- found = true;
- break;
- }
+ for (const char* r : roots) {
+ for (const char* e : {".ogg", ".mp3", ".wav"}) {
+ char c[512];
+ // try with folder prefix (music/ or cds/)
+ snprintf(c, 512, "%s%s%s%s%s", base.c_str(), r, folder,
+ track, e);
+ if (access(c, F_OK) != -1) {
+ strncpy(m_szStreamName, c, 511);
+ found = true;
+ break;
+ }
+ // try without folder prefix
+ snprintf(c, 512, "%s%s%s%s", base.c_str(), r, track, e);
+ if (access(c, F_OK) != -1) {
+ strncpy(m_szStreamName, c, 511);
+ found = true;
+ break;
}
}
-
- if (!found) {
- if (dotPos != nullptr) {
- strncpy(dotPos, ".wav", 5);
- }
- app.DebugPrintf(
- "WARNING: No audio file found for music ID %d "
- "(tried .ogg, .mp3, .wav)\n",
- m_musicID);
- return;
- }
+ if (found) break;
}
- app.DebugPrintf("Starting streaming - %s\n", m_szStreamName);
- m_openStreamThread = new C4JThread(OpenStreamThreadProc, this,
- "OpenStreamThreadProc");
- m_openStreamThread->Run();
- m_StreamState = eMusicStreamState_Opening;
+ if (found) {
+ SetIsPlayingStreamingGameMusic(!isCD);
+ SetIsPlayingStreamingCDMusic(isCD);
+ m_openStreamThread = new C4JThread(
+ OpenStreamThreadProc, this, "OpenStreamThreadProc");
+ m_openStreamThread->Run();
+ m_StreamState = eMusicStreamState_Opening;
+ } else {
+ app.DebugPrintf(
+ "[SoundEngine] oh noes couldn't find music track '%s', "
+ "retrying "
+ "in 1min\n",
+ track);
+ m_iMusicDelay = 20 * 60;
+ }
}
break;
@@ -613,64 +480,30 @@ void SoundEngine::playMusicTick() {
delete m_openStreamThread;
m_openStreamThread = nullptr;
- app.DebugPrintf(
- "OpenStreamThreadProc finished. m_musicStreamActive=%d\n",
- m_musicStreamActive);
-
if (!m_musicStreamActive) {
- const char* currentExt =
- strrchr(reinterpret_cast(m_szStreamName), '.');
- if (currentExt && _stricmp(currentExt, ".wav") == 0) {
- const bool isCD = (m_musicID >= m_iStream_CD_1);
- const char* folder = isCD ? "cds/" : "music/";
-
- int n =
- sprintf_s(reinterpret_cast(m_szStreamName),
- 512, "%s%s%s.wav", m_szMusicPath, folder,
- m_szStreamFileA[m_musicID]);
-
- if (n > 0) {
- FILE* pFile = fopen(
- reinterpret_cast(m_szStreamName), "rb");
- if (pFile) {
- fclose(pFile);
-
- m_openStreamThread =
- new C4JThread(OpenStreamThreadProc, this,
- "OpenStreamThreadProc");
- m_openStreamThread->Run();
- break;
- }
- }
- }
-
m_StreamState = eMusicStreamState_Idle;
break;
}
+ ma_sound_set_spatialization_enabled(
+ &m_musicStream,
+ m_StreamingAudioInfo.bIs3D ? MA_TRUE : MA_FALSE);
if (m_StreamingAudioInfo.bIs3D) {
- ma_sound_set_spatialization_enabled(&m_musicStream,
- MA_TRUE);
ma_sound_set_position(
&m_musicStream, m_StreamingAudioInfo.x,
m_StreamingAudioInfo.y, m_StreamingAudioInfo.z);
- } else {
- ma_sound_set_spatialization_enabled(&m_musicStream,
- MA_FALSE);
}
ma_sound_set_pitch(&m_musicStream, m_StreamingAudioInfo.pitch);
-
- float finalVolume =
- m_StreamingAudioInfo.volume * getMasterMusicVolume();
-
- ma_sound_set_volume(&m_musicStream, finalVolume);
- ma_result startResult = ma_sound_start(&m_musicStream);
- app.DebugPrintf("ma_sound_start result: %d\n", startResult);
+ ma_sound_set_volume(
+ &m_musicStream,
+ m_StreamingAudioInfo.volume * getMasterMusicVolume());
+ ma_sound_start(&m_musicStream);
m_StreamState = eMusicStreamState_Playing;
}
break;
+
case eMusicStreamState_OpeningCancel:
if (!m_openStreamThread->isRunning()) {
delete m_openStreamThread;
@@ -678,200 +511,130 @@ void SoundEngine::playMusicTick() {
m_StreamState = eMusicStreamState_Stop;
}
break;
+
case eMusicStreamState_Stop:
if (m_musicStreamActive) {
ma_sound_stop(&m_musicStream);
ma_sound_uninit(&m_musicStream);
m_musicStreamActive = false;
}
-
SetIsPlayingStreamingCDMusic(false);
SetIsPlayingStreamingGameMusic(false);
-
m_StreamState = eMusicStreamState_Idle;
break;
- case eMusicStreamState_Stopping:
- break;
- case eMusicStreamState_Play:
- break;
- case eMusicStreamState_Playing: {
- static int frameCount = 0;
- if (frameCount++ % 60 == 0) {
- if (m_musicStreamActive) {
- bool isPlaying = ma_sound_is_playing(&m_musicStream);
- float vol = ma_sound_get_volume(&m_musicStream);
- bool isAtEnd = ma_sound_at_end(&m_musicStream);
- }
- }
- }
+
+ case eMusicStreamState_Playing:
if (GetIsPlayingStreamingGameMusic()) {
- {
- bool playerInEnd = false;
- bool playerInNether = false;
- Minecraft* pMinecraft = Minecraft::GetInstance();
- for (unsigned int i = 0; i < MAX_LOCAL_PLAYERS; ++i) {
- if (pMinecraft->localplayers[i] != nullptr) {
- if (pMinecraft->localplayers[i]->dimension ==
- LevelData::DIMENSION_END) {
- playerInEnd = true;
- } else if (pMinecraft->localplayers[i]->dimension ==
- LevelData::DIMENSION_NETHER) {
- playerInNether = true;
- }
- }
- }
+ bool playerInEnd = false, playerInNether = false;
+ Minecraft* pMinecraft = Minecraft::GetInstance();
- if (playerInEnd && !GetIsPlayingEndMusic()) {
- m_StreamState = eMusicStreamState_Stop;
-
- // Set the end track
- m_musicID = getMusicID(LevelData::DIMENSION_END);
- SetIsPlayingEndMusic(true);
- SetIsPlayingNetherMusic(false);
- } else if (!playerInEnd && GetIsPlayingEndMusic()) {
- if (playerInNether) {
- m_StreamState = eMusicStreamState_Stop;
-
- // Set the end track
- m_musicID = getMusicID(LevelData::DIMENSION_NETHER);
- SetIsPlayingEndMusic(false);
- SetIsPlayingNetherMusic(true);
- } else {
- m_StreamState = eMusicStreamState_Stop;
-
- // Set the end track
- m_musicID =
- getMusicID(LevelData::DIMENSION_OVERWORLD);
- SetIsPlayingEndMusic(false);
- SetIsPlayingNetherMusic(false);
- }
- } else if (playerInNether && !GetIsPlayingNetherMusic()) {
- m_StreamState = eMusicStreamState_Stop;
- // set the Nether track
- m_musicID = getMusicID(LevelData::DIMENSION_NETHER);
- SetIsPlayingNetherMusic(true);
- SetIsPlayingEndMusic(false);
- } else if (!playerInNether && GetIsPlayingNetherMusic()) {
- if (playerInEnd) {
- m_StreamState = eMusicStreamState_Stop;
- // set the Nether track
- m_musicID = getMusicID(LevelData::DIMENSION_END);
- SetIsPlayingNetherMusic(false);
- SetIsPlayingEndMusic(true);
- } else {
- m_StreamState = eMusicStreamState_Stop;
- // set the Nether track
- m_musicID =
- getMusicID(LevelData::DIMENSION_OVERWORLD);
- SetIsPlayingNetherMusic(false);
- SetIsPlayingEndMusic(false);
- }
- }
-
- // volume change required?
- if (m_musicStreamActive) {
- float finalVolume =
- m_StreamingAudioInfo.volume * fMusicVol;
-
- ma_sound_set_volume(&m_musicStream, finalVolume);
+ for (unsigned int i = 0; i < MAX_LOCAL_PLAYERS; ++i) {
+ if (pMinecraft->localplayers[i]) {
+ if (pMinecraft->localplayers[i]->dimension ==
+ LevelData::DIMENSION_END)
+ playerInEnd = true;
+ else if (pMinecraft->localplayers[i]->dimension ==
+ LevelData::DIMENSION_NETHER)
+ playerInNether = true;
}
}
- } else {
- // Music disc playing - if it's a 3D stream, then set the
- // position - we don't have any streaming audio in the world
- // that moves, so this isn't required unless we have more than
- // one listener, and are setting the listening position to the
- // origin and setting a fake position for the sound down the z
- // axis
- if (m_StreamingAudioInfo.bIs3D && m_validListenerCount > 1) {
- int iClosestListener = 0;
- float fClosestDist = 1e6f;
- for (size_t i = 0; i < MAX_LOCAL_PLAYERS; i++) {
- if (m_ListenerA[i].bValid) {
- float dx = m_StreamingAudioInfo.x -
- m_ListenerA[i].vPosition.x;
- float dy = m_StreamingAudioInfo.y -
- m_ListenerA[i].vPosition.y;
- float dz = m_StreamingAudioInfo.z -
- m_ListenerA[i].vPosition.z;
- float dist = sqrtf(dx * dx + dy * dy + dz * dz);
+ // Handle Dimension Switching
+ bool needsStop = false;
+ if (playerInEnd && !GetIsPlayingEndMusic()) {
+ m_musicID = getMusicID(LevelData::DIMENSION_END);
+ SetIsPlayingEndMusic(true);
+ SetIsPlayingNetherMusic(false);
+ needsStop = true;
+ } else if (!playerInEnd && GetIsPlayingEndMusic()) {
+ m_musicID =
+ playerInNether
+ ? getMusicID(LevelData::DIMENSION_NETHER)
+ : getMusicID(LevelData::DIMENSION_OVERWORLD);
+ SetIsPlayingEndMusic(false);
+ SetIsPlayingNetherMusic(playerInNether);
+ needsStop = true;
+ } else if (playerInNether && !GetIsPlayingNetherMusic()) {
+ m_musicID = getMusicID(LevelData::DIMENSION_NETHER);
+ SetIsPlayingNetherMusic(true);
+ SetIsPlayingEndMusic(false);
+ needsStop = true;
+ } else if (!playerInNether && GetIsPlayingNetherMusic()) {
+ m_musicID =
+ playerInEnd
+ ? getMusicID(LevelData::DIMENSION_END)
+ : getMusicID(LevelData::DIMENSION_OVERWORLD);
+ SetIsPlayingNetherMusic(false);
+ SetIsPlayingEndMusic(playerInEnd);
+ needsStop = true;
+ }
- if (dist < fClosestDist) {
- fClosestDist = dist;
- iClosestListener = i;
- }
+ if (needsStop) m_StreamState = eMusicStreamState_Stop;
+
+ // volume change required?
+ if (m_musicStreamActive)
+ ma_sound_set_volume(
+ &m_musicStream,
+ m_StreamingAudioInfo.volume * fMusicVol);
+
+ } else if (m_StreamingAudioInfo.bIs3D && m_validListenerCount > 1 &&
+ m_musicStreamActive) {
+ float fClosestDist = 1e6f;
+ int iClosest = 0;
+ for (size_t i = 0; i < MAX_LOCAL_PLAYERS; i++) {
+ if (m_ListenerA[i].bValid) {
+ float dist = sqrtf(powf(m_StreamingAudioInfo.x -
+ m_ListenerA[i].vPosition.x,
+ 2) +
+ powf(m_StreamingAudioInfo.y -
+ m_ListenerA[i].vPosition.y,
+ 2) +
+ powf(m_StreamingAudioInfo.z -
+ m_ListenerA[i].vPosition.z,
+ 2));
+ if (dist < fClosestDist) {
+ fClosestDist = dist;
+ iClosest = i;
}
}
-
- float relX = m_StreamingAudioInfo.x -
- m_ListenerA[iClosestListener].vPosition.x;
- float relY = m_StreamingAudioInfo.y -
- m_ListenerA[iClosestListener].vPosition.y;
- float relZ = m_StreamingAudioInfo.z -
- m_ListenerA[iClosestListener].vPosition.z;
-
- if (m_musicStreamActive) {
- ma_sound_set_position(&m_musicStream, relX, relY, relZ);
- }
}
+ ma_sound_set_position(
+ &m_musicStream,
+ m_StreamingAudioInfo.x - m_ListenerA[iClosest].vPosition.x,
+ m_StreamingAudioInfo.y - m_ListenerA[iClosest].vPosition.y,
+ m_StreamingAudioInfo.z - m_ListenerA[iClosest].vPosition.z);
}
-
break;
- case eMusicStreamState_Completed: {
- // random delay of up to 3 minutes for music
- m_iMusicDelay = random->nextInt(
- 20 * 60 * 3); // random->nextInt(20 * 60 * 10) + 20 * 60 * 10;
- // Check if we have a local player in The Nether or in The End, and
- // play that music if they are
- Minecraft* pMinecraft = Minecraft::GetInstance();
- bool playerInEnd = false;
- bool playerInNether = false;
-
- for (unsigned int i = 0; i < MAX_LOCAL_PLAYERS; i++) {
- if (pMinecraft->localplayers[i] != nullptr) {
- if (pMinecraft->localplayers[i]->dimension ==
- LevelData::DIMENSION_END) {
- playerInEnd = true;
- } else if (pMinecraft->localplayers[i]->dimension ==
- LevelData::DIMENSION_NETHER) {
- playerInNether = true;
+ case eMusicStreamState_Completed:
+ m_iMusicDelay = random->nextInt(20 * 60 * 3);
+ {
+ int dim = LevelData::DIMENSION_OVERWORLD;
+ Minecraft* pMc = Minecraft::GetInstance();
+ for (int i = 0; i < MAX_LOCAL_PLAYERS; i++) {
+ if (pMc->localplayers[i]) {
+ dim = pMc->localplayers[i]->dimension;
+ break;
}
}
+ m_musicID = getMusicID(dim);
+ SetIsPlayingEndMusic(dim == LevelData::DIMENSION_END);
+ SetIsPlayingNetherMusic(dim == LevelData::DIMENSION_NETHER);
}
- if (playerInEnd) {
- m_musicID = getMusicID(LevelData::DIMENSION_END);
- SetIsPlayingEndMusic(true);
- SetIsPlayingNetherMusic(false);
- } else if (playerInNether) {
- m_musicID = getMusicID(LevelData::DIMENSION_NETHER);
- SetIsPlayingNetherMusic(true);
- SetIsPlayingEndMusic(false);
- } else {
- m_musicID = getMusicID(LevelData::DIMENSION_OVERWORLD);
- SetIsPlayingNetherMusic(false);
- SetIsPlayingEndMusic(false);
- }
-
m_StreamState = eMusicStreamState_Idle;
- } break;
+ break;
}
// check the status of the stream - this is for when a track completes
// rather than is stopped by the user action
- if (m_musicStreamActive) {
- if (!ma_sound_is_playing(&m_musicStream) &&
- ma_sound_at_end(&m_musicStream)) {
- ma_sound_uninit(&m_musicStream);
- m_musicStreamActive = false;
-
- SetIsPlayingStreamingCDMusic(false);
- SetIsPlayingStreamingGameMusic(false);
-
- m_StreamState = eMusicStreamState_Completed;
- }
+ if (m_musicStreamActive && !ma_sound_is_playing(&m_musicStream) &&
+ ma_sound_at_end(&m_musicStream)) {
+ ma_sound_uninit(&m_musicStream);
+ m_musicStreamActive = false;
+ SetIsPlayingStreamingCDMusic(false);
+ SetIsPlayingStreamingGameMusic(false);
+ m_StreamState = eMusicStreamState_Completed;
}
}
@@ -2053,7 +1816,8 @@ F32 AILCALLBACK custom_falloff_function(HSAMPLE S, F32 distance,
}
#endif
-// Universal, these functions shouldn't need platform specific implementations
+// Universal, these functions shouldn't need platform specific
+// implementations
void SoundEngine::updateMusicVolume(float fVal) { m_MasterMusicVolume = fVal; }
void SoundEngine::updateSystemMusicPlaying(bool isPlaying) {
m_bSystemMusicPlaying = isPlaying;
diff --git a/Minecraft.Client/Platform/Common/Consoles_App.cpp b/Minecraft.Client/Platform/Common/Consoles_App.cpp
index dd7dfd6c4..aca1a1f6d 100644
--- a/Minecraft.Client/Platform/Common/Consoles_App.cpp
+++ b/Minecraft.Client/Platform/Common/Consoles_App.cpp
@@ -50,9 +50,16 @@
#include "../Minecraft.Client/Utils/StringTable.h"
#include "../Minecraft.Client/Utils/ArchiveFile.h"
#include "../Minecraft.Client/Minecraft.h"
+#if defined(__linux__)
+#include
+#include
+#endif
#include "UI/UI.h"
#include "UI/UIScene_PauseMenu.h"
+#include
+#include
+
#include "Leaderboards/LeaderboardManager.h"
// CMinecraftApp app;
@@ -3672,7 +3679,6 @@ int CMinecraftApp::BannedLevelDialogReturned(
return 0;
}
-
void CMinecraftApp::loadMediaArchive() {
std::wstring mediapath = L"";
@@ -3683,7 +3689,18 @@ void CMinecraftApp::loadMediaArchive() {
#endif
if (!mediapath.empty()) {
+ // boom headshot
+#if defined(__linux__)
+ std::wstring exeDirW = PathHelper::GetExecutableDirW();
+ std::wstring candidate = exeDirW + File::pathSeparator + mediapath;
+ if (File(candidate).exists()) {
+ m_mediaArchive = new ArchiveFile(File(candidate));
+ } else {
+ m_mediaArchive = new ArchiveFile(File(mediapath));
+ }
+#else
m_mediaArchive = new ArchiveFile(File(mediapath));
+#endif
}
}
@@ -3744,8 +3761,6 @@ int CMinecraftApp::EthernetDisconnectReturned(
int CMinecraftApp::SignoutExitWorldThreadProc(void* lpParameter) {
// Share AABB & Vec3 pools with default (main thread) - should be ok as long
// as we don't tick the main thread whilst this thread is running
- AABB::UseDefaultThreadStorage();
- Vec3::UseDefaultThreadStorage();
Compression::UseDefaultThreadStorage();
// app.SetGameStarted(false);
@@ -3850,7 +3865,7 @@ int CMinecraftApp::SignoutExitWorldThreadProc(void* lpParameter) {
// We can't start/join a new game until the session is destroyed, so wait
// for it to be idle again
while (g_NetworkManager.IsInSession()) {
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
return S_OK;
@@ -5717,8 +5732,6 @@ void CMinecraftApp::LeaveSaveNotificationSection() {
int CMinecraftApp::RemoteSaveThreadProc(void* lpParameter) {
// The game should be stopped while we are doing this, but the connections
// ticks may try to create some AABB's or Vec3's
- AABB::UseDefaultThreadStorage();
- Vec3::UseDefaultThreadStorage();
Compression::UseDefaultThreadStorage();
// 4J-PB - Xbox 360 - 163153 - [CRASH] TU17: Code: Multiplayer: During the
@@ -5746,7 +5759,7 @@ int CMinecraftApp::RemoteSaveThreadProc(void* lpParameter) {
eAppAction_WaitRemoteServerSaveComplete) {
// Tick all the games connections
pMinecraft->tickAllConnections();
- Sleep(100);
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
if (app.GetXuiAction(ProfileManager.GetPrimaryPad()) !=
diff --git a/Minecraft.Client/Platform/Common/GameRules/ApplySchematicRuleDefinition.cpp b/Minecraft.Client/Platform/Common/GameRules/ApplySchematicRuleDefinition.cpp
index e7f25cf69..2101756d7 100644
--- a/Minecraft.Client/Platform/Common/GameRules/ApplySchematicRuleDefinition.cpp
+++ b/Minecraft.Client/Platform/Common/GameRules/ApplySchematicRuleDefinition.cpp
@@ -8,12 +8,13 @@
#include "ApplySchematicRuleDefinition.h"
#include "LevelGenerationOptions.h"
#include "ConsoleSchematicFile.h"
+#include "../../Minecraft.World/Util/AABB.h"
ApplySchematicRuleDefinition::ApplySchematicRuleDefinition(
LevelGenerationOptions* levelGenOptions) {
m_levelGenOptions = levelGenOptions;
- m_location = Vec3::newPermanent(0, 0, 0);
- m_locationBox = NULL;
+ m_location = Vec3(0, 0, 0);
+ m_locationBox = std::nullopt;
m_totalBlocksChanged = 0;
m_totalBlocksChangedLighting = 0;
m_rotation = ConsoleSchematicFile::eSchematicRot_0;
@@ -26,7 +27,6 @@ ApplySchematicRuleDefinition::~ApplySchematicRuleDefinition() {
app.DebugPrintf("Deleting ApplySchematicRuleDefinition.\n");
if (!m_completed) m_levelGenOptions->releaseSchematicFile(m_schematicName);
m_schematic = NULL;
- delete m_location;
}
void ApplySchematicRuleDefinition::writeAttributes(DataOutputStream* dos,
@@ -36,11 +36,11 @@ void ApplySchematicRuleDefinition::writeAttributes(DataOutputStream* dos,
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_filename);
dos->writeUTF(m_schematicName);
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_x);
- dos->writeUTF(_toString(m_location->x));
+ dos->writeUTF(_toString(m_location.x));
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_y);
- dos->writeUTF(_toString(m_location->y));
+ dos->writeUTF(_toString(m_location.y));
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_z);
- dos->writeUTF(_toString(m_location->z));
+ dos->writeUTF(_toString(m_location.z));
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_rot);
switch (m_rotation) {
@@ -76,19 +76,19 @@ void ApplySchematicRuleDefinition::addAttribute(
m_schematic = m_levelGenOptions->getSchematicFile(m_schematicName);
}
} else if (attributeName.compare(L"x") == 0) {
- m_location->x = _fromString(attributeValue);
- if (((int)abs(m_location->x)) % 2 != 0) m_location->x -= 1;
+ m_location.x = _fromString(attributeValue);
+ if (((int)abs(m_location.x)) % 2 != 0) m_location.x -= 1;
// app.DebugPrintf("ApplySchematicRuleDefinition: Adding parameter
// x=%f\n",m_location->x);
} else if (attributeName.compare(L"y") == 0) {
- m_location->y = _fromString(attributeValue);
- if (((int)abs(m_location->y)) % 2 != 0) m_location->y -= 1;
- if (m_location->y < 0) m_location->y = 0;
+ m_location.y = _fromString(attributeValue);
+ if (((int)abs(m_location.y)) % 2 != 0) m_location.y -= 1;
+ if (m_location.y < 0) m_location.y = 0;
// app.DebugPrintf("ApplySchematicRuleDefinition: Adding parameter
// y=%f\n",m_location->y);
} else if (attributeName.compare(L"z") == 0) {
- m_location->z = _fromString(attributeValue);
- if (((int)abs(m_location->z)) % 2 != 0) m_location->z -= 1;
+ m_location.z = _fromString(attributeValue);
+ if (((int)abs(m_location.z)) % 2 != 0) m_location.z -= 1;
// app.DebugPrintf("ApplySchematicRuleDefinition: Adding parameter
// z=%f\n",m_location->z);
} else if (attributeName.compare(L"rot") == 0) {
@@ -131,25 +131,25 @@ void ApplySchematicRuleDefinition::updateLocationBox() {
if (m_schematic == NULL)
m_schematic = m_levelGenOptions->getSchematicFile(m_schematicName);
- m_locationBox = AABB::newPermanent(0, 0, 0, 0, 0, 0);
+ m_locationBox = AABB(0, 0, 0, 0, 0, 0);
- m_locationBox->x0 = m_location->x;
- m_locationBox->y0 = m_location->y;
- m_locationBox->z0 = m_location->z;
+ m_locationBox->x0 = m_location.x;
+ m_locationBox->y0 = m_location.y;
+ m_locationBox->z0 = m_location.z;
- m_locationBox->y1 = m_location->y + m_schematic->getYSize();
+ m_locationBox->y1 = m_location.y + m_schematic->getYSize();
switch (m_rotation) {
case ConsoleSchematicFile::eSchematicRot_90:
case ConsoleSchematicFile::eSchematicRot_270:
- m_locationBox->x1 = m_location->x + m_schematic->getZSize();
- m_locationBox->z1 = m_location->z + m_schematic->getXSize();
+ m_locationBox->x1 = m_location.x + m_schematic->getZSize();
+ m_locationBox->z1 = m_location.z + m_schematic->getXSize();
break;
case ConsoleSchematicFile::eSchematicRot_0:
case ConsoleSchematicFile::eSchematicRot_180:
default:
- m_locationBox->x1 = m_location->x + m_schematic->getXSize();
- m_locationBox->z1 = m_location->z + m_schematic->getZSize();
+ m_locationBox->x1 = m_location.x + m_schematic->getXSize();
+ m_locationBox->z1 = m_location.z + m_schematic->getZSize();
break;
};
}
@@ -163,8 +163,8 @@ void ApplySchematicRuleDefinition::processSchematic(AABB* chunkBox,
if (m_schematic == NULL)
m_schematic = m_levelGenOptions->getSchematicFile(m_schematicName);
- if (m_locationBox == NULL) updateLocationBox();
- if (chunkBox->intersects(m_locationBox)) {
+ if (!m_locationBox.has_value()) updateLocationBox();
+ if (chunkBox->intersects(*m_locationBox)) {
m_locationBox->y1 =
std::min((double)Level::maxBuildHeight, m_locationBox->y1);
@@ -174,12 +174,12 @@ void ApplySchematicRuleDefinition::processSchematic(AABB* chunkBox,
#endif
PIXBeginNamedEvent(0, "Applying blocks and data");
m_totalBlocksChanged += m_schematic->applyBlocksAndData(
- chunk, chunkBox, m_locationBox, m_rotation);
+ chunk, chunkBox, &*m_locationBox, m_rotation);
PIXEndNamedEvent();
// Add the tileEntities
PIXBeginNamedEvent(0, "Applying tile entities");
- m_schematic->applyTileEntities(chunk, chunkBox, m_locationBox,
+ m_schematic->applyTileEntities(chunk, chunkBox, &*m_locationBox,
m_rotation);
PIXEndNamedEvent();
@@ -207,8 +207,8 @@ void ApplySchematicRuleDefinition::processSchematicLighting(AABB* chunkBox,
if (m_schematic == NULL)
m_schematic = m_levelGenOptions->getSchematicFile(m_schematicName);
- if (m_locationBox == NULL) updateLocationBox();
- if (chunkBox->intersects(m_locationBox)) {
+ if (!m_locationBox.has_value()) updateLocationBox();
+ if (chunkBox->intersects(*m_locationBox)) {
m_locationBox->y1 =
std::min((double)Level::maxBuildHeight, m_locationBox->y1);
@@ -218,7 +218,7 @@ void ApplySchematicRuleDefinition::processSchematicLighting(AABB* chunkBox,
#endif
PIXBeginNamedEvent(0, "Patching lighting");
m_totalBlocksChangedLighting += m_schematic->applyLighting(
- chunk, chunkBox, m_locationBox, m_rotation);
+ chunk, chunkBox, &*m_locationBox, m_rotation);
PIXEndNamedEvent();
// TODO This does not take into account things that go outside the
@@ -238,12 +238,12 @@ void ApplySchematicRuleDefinition::processSchematicLighting(AABB* chunkBox,
bool ApplySchematicRuleDefinition::checkIntersects(int x0, int y0, int z0,
int x1, int y1, int z1) {
- if (m_locationBox == NULL) updateLocationBox();
+ if (!m_locationBox.has_value()) updateLocationBox();
return m_locationBox->intersects(x0, y0, z0, x1, y1, z1);
}
int ApplySchematicRuleDefinition::getMinY() {
- if (m_locationBox == NULL) updateLocationBox();
+ if (!m_locationBox.has_value()) updateLocationBox();
return m_locationBox->y0;
}
@@ -251,4 +251,4 @@ void ApplySchematicRuleDefinition::reset() {
m_totalBlocksChanged = 0;
m_totalBlocksChangedLighting = 0;
m_completed = false;
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Platform/Common/GameRules/ApplySchematicRuleDefinition.h b/Minecraft.Client/Platform/Common/GameRules/ApplySchematicRuleDefinition.h
index e3c5b425f..1f5a5cbc1 100644
--- a/Minecraft.Client/Platform/Common/GameRules/ApplySchematicRuleDefinition.h
+++ b/Minecraft.Client/Platform/Common/GameRules/ApplySchematicRuleDefinition.h
@@ -1,6 +1,8 @@
#pragma once
+#include
#include "GameRuleDefinition.h"
#include "ConsoleSchematicFile.h"
+#include "../../Minecraft.World/Util/AABB.h"
class AABB;
class Vec3;
@@ -13,8 +15,8 @@ private:
LevelGenerationOptions* m_levelGenOptions;
std::wstring m_schematicName;
ConsoleSchematicFile* m_schematic;
- Vec3* m_location;
- AABB* m_locationBox;
+ Vec3 m_location;
+ std::optional m_locationBox;
ConsoleSchematicFile::ESchematicRotation m_rotation;
int m_dimension;
@@ -51,4 +53,4 @@ public:
* Reset any state to how it should be before a new game.
*/
void reset();
-};
\ No newline at end of file
+};
diff --git a/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.cpp b/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.cpp
index 04d7015c9..3ba460f65 100644
--- a/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.cpp
+++ b/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.cpp
@@ -155,8 +155,8 @@ void ConsoleSchematicFile::load(DataInputStream* dis) {
// app.DebugPrintf(1,"Loaded entity type %d at
// (%f,%f,%f)\n",(int)type,x,y,z);
#endif
- m_entities.push_back(std::pair(
- Vec3::newPermanent(x, y, z), (CompoundTag*)eTag->copy()));
+ m_entities.push_back(std::pair(
+ Vec3(x, y, z), (CompoundTag*)eTag->copy()));
}
}
delete tag;
@@ -463,7 +463,7 @@ void ConsoleSchematicFile::applyTileEntities(LevelChunk* chunk, AABB* chunkBox,
schematicCoordToChunkCoord(destinationBox, te->x, te->z, rot, targetX,
targetZ);
- Vec3* pos = Vec3::newTemp(targetX, targetY, targetZ);
+ Vec3 pos(targetX, targetY, targetZ);
if (chunkBox->containsIncludingLowerBound(pos)) {
std::shared_ptr teCopy = chunk->getTileEntity(
(int)targetX & 15, (int)targetY & 15, (int)targetZ & 15);
@@ -500,18 +500,17 @@ void ConsoleSchematicFile::applyTileEntities(LevelChunk* chunk, AABB* chunkBox,
}
}
for (AUTO_VAR(it, m_entities.begin()); it != m_entities.end();) {
- Vec3* source = it->first;
+ Vec3 source = it->first;
- double targetX = source->x;
- double targetY = source->y + destinationBox->y0;
- double targetZ = source->z;
- schematicCoordToChunkCoord(destinationBox, source->x, source->z, rot,
+ double targetX = source.x;
+ double targetY = source.y + destinationBox->y0;
+ double targetZ = source.z;
+ schematicCoordToChunkCoord(destinationBox, source.x, source.z, rot,
targetX, targetZ);
// Add 0.01 as the AABB::contains function returns false if a value is
// <= the lower bound
- Vec3* pos =
- Vec3::newTemp(targetX + 0.01, targetY + 0.01, targetZ + 0.01);
+ Vec3 pos(targetX + 0.01, targetY + 0.01, targetZ + 0.01);
if (!chunkBox->containsIncludingLowerBound(pos)) {
++it;
continue;
@@ -734,9 +733,9 @@ void ConsoleSchematicFile::generateSchematicFile(
}
tag.put(L"TileEntities", tileEntitiesTag);
- AABB* bb = AABB::newTemp(xStart, yStart, zStart, xEnd, yEnd, zEnd);
+ AABB bb(xStart, yStart, zStart, xEnd, yEnd, zEnd);
std::vector >* entities =
- level->getEntities(nullptr, bb);
+ level->getEntities(nullptr, &bb);
ListTag* entitiesTag = new ListTag(L"entities");
for (AUTO_VAR(it, entities->begin()); it != entities->end(); ++it) {
@@ -800,8 +799,8 @@ void ConsoleSchematicFile::getBlocksAndData(LevelChunk* chunk, byteArray* data,
// if (xs * ys * zs == LevelChunk::BLOCKS_LENGTH)
//{
// byteArray blockData = byteArray(data->data + blocksP,
- //Level::CHUNK_TILE_COUNT); chunk->getBlockData(blockData); blocksP +=
- //blockData.length;
+ // Level::CHUNK_TILE_COUNT); chunk->getBlockData(blockData);
+ // blocksP += blockData.length;
// byteArray dataData = byteArray(data->data + dataP, 16384);
// chunk->getBlockLightData(dataData);
diff --git a/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.h b/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.h
index 1990328a8..adf862a0b 100644
--- a/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.h
+++ b/Minecraft.Client/Platform/Common/GameRules/ConsoleSchematicFile.h
@@ -54,7 +54,7 @@ public:
private:
int m_xSize, m_ySize, m_zSize;
std::vector > m_tileEntities;
- std::vector > m_entities;
+ std::vector > m_entities;
public:
byteArray m_data;
diff --git a/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp b/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp
index d6a7dc9fd..f8e13ae50 100644
--- a/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp
+++ b/Minecraft.Client/Platform/Common/GameRules/LevelGenerationOptions.cpp
@@ -253,13 +253,12 @@ void LevelGenerationOptions::addAttribute(const std::wstring& attributeName,
void LevelGenerationOptions::processSchematics(LevelChunk* chunk) {
PIXBeginNamedEvent(0, "Processing schematics for chunk (%d,%d)", chunk->x,
chunk->z);
- AABB* chunkBox =
- AABB::newTemp(chunk->x * 16, 0, chunk->z * 16, chunk->x * 16 + 16,
- Level::maxBuildHeight, chunk->z * 16 + 16);
+ AABB chunkBox(chunk->x * 16, 0, chunk->z * 16, chunk->x * 16 + 16,
+ Level::maxBuildHeight, chunk->z * 16 + 16);
for (AUTO_VAR(it, m_schematicRules.begin()); it != m_schematicRules.end();
++it) {
ApplySchematicRuleDefinition* rule = *it;
- rule->processSchematic(chunkBox, chunk);
+ rule->processSchematic(&chunkBox, chunk);
}
int cx = (chunk->x << 4);
@@ -282,13 +281,12 @@ void LevelGenerationOptions::processSchematics(LevelChunk* chunk) {
void LevelGenerationOptions::processSchematicsLighting(LevelChunk* chunk) {
PIXBeginNamedEvent(0, "Processing schematics (lighting) for chunk (%d,%d)",
chunk->x, chunk->z);
- AABB* chunkBox =
- AABB::newTemp(chunk->x * 16, 0, chunk->z * 16, chunk->x * 16 + 16,
- Level::maxBuildHeight, chunk->z * 16 + 16);
+ AABB chunkBox(chunk->x * 16, 0, chunk->z * 16, chunk->x * 16 + 16,
+ Level::maxBuildHeight, chunk->z * 16 + 16);
for (AUTO_VAR(it, m_schematicRules.begin()); it != m_schematicRules.end();
++it) {
ApplySchematicRuleDefinition* rule = *it;
- rule->processSchematicLighting(chunkBox, chunk);
+ rule->processSchematicLighting(&chunkBox, chunk);
}
PIXEndNamedEvent();
}
diff --git a/Minecraft.Client/Platform/Common/GameRules/NamedAreaRuleDefinition.cpp b/Minecraft.Client/Platform/Common/GameRules/NamedAreaRuleDefinition.cpp
index b09982ae9..da0524ff7 100644
--- a/Minecraft.Client/Platform/Common/GameRules/NamedAreaRuleDefinition.cpp
+++ b/Minecraft.Client/Platform/Common/GameRules/NamedAreaRuleDefinition.cpp
@@ -5,11 +5,9 @@
NamedAreaRuleDefinition::NamedAreaRuleDefinition() {
m_name = L"";
- m_area = AABB::newPermanent(0, 0, 0, 0, 0, 0);
+ m_area = AABB(0, 0, 0, 0, 0, 0);
}
-NamedAreaRuleDefinition::~NamedAreaRuleDefinition() { delete m_area; }
-
void NamedAreaRuleDefinition::writeAttributes(DataOutputStream* dos,
unsigned int numAttributes) {
GameRuleDefinition::writeAttributes(dos, numAttributes + 7);
@@ -18,18 +16,18 @@ void NamedAreaRuleDefinition::writeAttributes(DataOutputStream* dos,
dos->writeUTF(m_name);
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_x0);
- dos->writeUTF(_toString(m_area->x0));
+ dos->writeUTF(_toString(m_area.x0));
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_y0);
- dos->writeUTF(_toString(m_area->y0));
+ dos->writeUTF(_toString(m_area.y0));
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_z0);
- dos->writeUTF(_toString(m_area->z0));
+ dos->writeUTF(_toString(m_area.z0));
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_x1);
- dos->writeUTF(_toString(m_area->x1));
+ dos->writeUTF(_toString(m_area.x1));
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_y1);
- dos->writeUTF(_toString(m_area->y1));
+ dos->writeUTF(_toString(m_area.y1));
ConsoleGameRules::write(dos, ConsoleGameRules::eGameRuleAttr_z1);
- dos->writeUTF(_toString(m_area->z1));
+ dos->writeUTF(_toString(m_area.z1));
}
void NamedAreaRuleDefinition::addAttribute(const std::wstring& attributeName,
@@ -41,31 +39,31 @@ void NamedAreaRuleDefinition::addAttribute(const std::wstring& attributeName,
m_name.c_str());
#endif
} else if (attributeName.compare(L"x0") == 0) {
- m_area->x0 = _fromString(attributeValue);
+ m_area.x0 = _fromString(attributeValue);
app.DebugPrintf("NamedAreaRuleDefinition: Adding parameter x0=%f\n",
- m_area->x0);
+ m_area.x0);
} else if (attributeName.compare(L"y0") == 0) {
- m_area->y0 = _fromString(attributeValue);
- if (m_area->y0 < 0) m_area->y0 = 0;
+ m_area.y0 = _fromString(attributeValue);
+ if (m_area.y0 < 0) m_area.y0 = 0;
app.DebugPrintf("NamedAreaRuleDefinition: Adding parameter y0=%f\n",
- m_area->y0);
+ m_area.y0);
} else if (attributeName.compare(L"z0") == 0) {
- m_area->z0 = _fromString(attributeValue);
+ m_area.z0 = _fromString(attributeValue);
app.DebugPrintf("NamedAreaRuleDefinition: Adding parameter z0=%f\n",
- m_area->z0);
+ m_area.z0);
} else if (attributeName.compare(L"x1") == 0) {
- m_area->x1 = _fromString(attributeValue);
+ m_area.x1 = _fromString(attributeValue);
app.DebugPrintf("NamedAreaRuleDefinition: Adding parameter x1=%f\n",
- m_area->x1);
+ m_area.x1);
} else if (attributeName.compare(L"y1") == 0) {
- m_area->y1 = _fromString(attributeValue);
- if (m_area->y1 < 0) m_area->y1 = 0;
+ m_area.y1 = _fromString(attributeValue);
+ if (m_area.y1 < 0) m_area.y1 = 0;
app.DebugPrintf("NamedAreaRuleDefinition: Adding parameter y1=%f\n",
- m_area->y1);
+ m_area.y1);
} else if (attributeName.compare(L"z1") == 0) {
- m_area->z1 = _fromString(attributeValue);
+ m_area.z1 = _fromString(attributeValue);
app.DebugPrintf("NamedAreaRuleDefinition: Adding parameter z1=%f\n",
- m_area->z1);
+ m_area.z1);
} else {
GameRuleDefinition::addAttribute(attributeName, attributeValue);
}
diff --git a/Minecraft.Client/Platform/Common/GameRules/NamedAreaRuleDefinition.h b/Minecraft.Client/Platform/Common/GameRules/NamedAreaRuleDefinition.h
index 93f8a0c47..81be6c4bc 100644
--- a/Minecraft.Client/Platform/Common/GameRules/NamedAreaRuleDefinition.h
+++ b/Minecraft.Client/Platform/Common/GameRules/NamedAreaRuleDefinition.h
@@ -1,15 +1,15 @@
#pragma once
#include "GameRuleDefinition.h"
+#include "../../Minecraft.World/Util/AABB.h"
class NamedAreaRuleDefinition : public GameRuleDefinition {
private:
std::wstring m_name;
- AABB* m_area;
+ AABB m_area;
public:
NamedAreaRuleDefinition();
- ~NamedAreaRuleDefinition();
virtual void writeAttributes(DataOutputStream* dos,
unsigned int numAttributes);
@@ -21,6 +21,6 @@ public:
virtual void addAttribute(const std::wstring& attributeName,
const std::wstring& attributeValue);
- AABB* getArea() { return m_area; }
+ AABB* getArea() { return &m_area; }
std::wstring getName() { return m_name; }
};
diff --git a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp
index fad568f89..03cba8312 100644
--- a/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp
+++ b/Minecraft.Client/Platform/Common/Leaderboards/SonyLeaderboardManager.cpp
@@ -1,5 +1,7 @@
#include "../../stdafx.h"
+#include
+#include
#include
#include
// #include
@@ -43,7 +45,7 @@ SonyLeaderboardManager::~SonyLeaderboardManager() {
// 4J-JEV: Wait for thread to stop and hope it doesn't take too long.
long long startShutdown = System::currentTimeMillis();
while (m_threadScoreboard->isRunning()) {
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
assert((System::currentTimeMillis() - startShutdown) < 16);
}
@@ -76,7 +78,8 @@ int SonyLeaderboardManager::scoreboardThreadEntry(LPVOID lpParam) {
}
if ((!needsWriting) && (self->m_eStatsState != eStatsState_Getting)) {
- Sleep(50); // 4J-JEV: When we're not reading or writing.
+ std::this_thread::sleep_for(std::chrono::milliseconds(
+ 50)); // 4J-JEV: When we're not reading or writing.
}
} while ((self->m_running || self->m_eStatsState == eStatsState_Getting ||
diff --git a/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp b/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp
index e88a072fc..4b9a519cc 100644
--- a/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp
+++ b/Minecraft.Client/Platform/Common/Network/GameNetworkManager.cpp
@@ -1,3 +1,6 @@
+#include
+#include
+
#include "../../Minecraft.World/Platform/stdafx.h"
#include "../../Minecraft.World/Util/StringHelpers.h"
#include "../../Minecraft.World/Util/AABB.h"
@@ -246,7 +249,7 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft* minecraft,
// message I could find
pMinecraft->progressRenderer->progressStagePercentage(
g_NetworkManager.GetJoiningReadyPercentage());
- Sleep(10);
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
if (changedMessage) {
pMinecraft->progressRenderer->progressStagePercentage(100);
@@ -268,7 +271,7 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft* minecraft,
// this
while (!app.DLCInstallProcessCompleted() && app.DLCInstallPending() &&
!g_NetworkManager.IsLeavingGame()) {
- Sleep(10);
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
if (g_NetworkManager.IsLeavingGame()) {
MinecraftServer::HaltServer();
@@ -349,7 +352,7 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft* minecraft,
// 4J Stu - We were ticking this way too fast which could cause the
// connection to time out The connections should tick at 20 per second
- Sleep(50);
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
} while ((IsInSession() && !connection->isStarted() &&
!connection->isClosed() && !g_NetworkManager.IsLeavingGame()) ||
tPack->isLoadingData() ||
@@ -449,7 +452,7 @@ bool CGameNetworkManager::StartNetworkGame(Minecraft* minecraft,
// 4J Stu - We were ticking this way too fast which could cause
// the connection to time out The connections should tick at 20
// per second
- Sleep(50);
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
app.DebugPrintf("<***> %d %d %d %d %d\n", IsInSession(),
!connection->isStarted(),
!connection->isClosed(),
@@ -804,8 +807,6 @@ bool CGameNetworkManager::IsNetworkThreadRunning() {
int CGameNetworkManager::RunNetworkGameThreadProc(void* lpParameter) {
// Share AABB & Vec3 pools with default (main thread) - should be ok as long
// as we don't tick the main thread whilst this thread is running
- AABB::UseDefaultThreadStorage();
- Vec3::UseDefaultThreadStorage();
Compression::UseDefaultThreadStorage();
Tile::CreateNewThreadStorage();
@@ -817,7 +818,7 @@ int CGameNetworkManager::RunNetworkGameThreadProc(void* lpParameter) {
while (tPack->isLoadingData() ||
(Minecraft::GetInstance()->skins->needsUIUpdate() ||
ui.IsReloadingSkin())) {
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
ui.CleanUpSkinReload();
if (app.GetDisconnectReason() == DisconnectPacket::eDisconnect_None) {
@@ -852,15 +853,13 @@ int CGameNetworkManager::ServerThreadProc(void* lpParameter) {
param->texturePackId)) {
while ((Minecraft::GetInstance()->skins->needsUIUpdate() ||
ui.IsReloadingSkin())) {
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
param->levelGen->loadBaseSaveData();
}
}
SetThreadName(-1, "Minecraft Server thread");
- AABB::CreateNewThreadStorage();
- Vec3::CreateNewThreadStorage();
Compression::UseDefaultThreadStorage();
OldChunkStorage::UseDefaultThreadStorage();
Entity::useSmallIds();
@@ -873,8 +872,6 @@ int CGameNetworkManager::ServerThreadProc(void* lpParameter) {
lpParameter); // saveData, app.GetGameHostOption(eGameHostOption_All));
Tile::ReleaseThreadStorage();
- AABB::ReleaseThreadStorage();
- Vec3::ReleaseThreadStorage();
Level::destroyLightingCache();
if (lpParameter != NULL) delete (NetworkGameInitData*)lpParameter;
@@ -885,15 +882,13 @@ int CGameNetworkManager::ServerThreadProc(void* lpParameter) {
int CGameNetworkManager::ExitAndJoinFromInviteThreadProc(void* lpParam) {
// Share AABB & Vec3 pools with default (main thread) - should be ok as long
// as we don't tick the main thread whilst this thread is running
- AABB::UseDefaultThreadStorage();
- Vec3::UseDefaultThreadStorage();
Compression::UseDefaultThreadStorage();
// app.SetGameStarted(false);
UIScene_PauseMenu::_ExitWorld(NULL);
while (g_NetworkManager.IsInSession()) {
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
// Xbox should always be online when receiving invites - on PS3 we need to
@@ -912,8 +907,6 @@ void CGameNetworkManager::_LeaveGame() {
int CGameNetworkManager::ChangeSessionTypeThreadProc(void* lpParam) {
// Share AABB & Vec3 pools with default (main thread) - should be ok as long
// as we don't tick the main thread whilst this thread is running
- AABB::UseDefaultThreadStorage();
- Vec3::UseDefaultThreadStorage();
Compression::UseDefaultThreadStorage();
Minecraft* pMinecraft = Minecraft::GetInstance();
@@ -927,7 +920,7 @@ int CGameNetworkManager::ChangeSessionTypeThreadProc(void* lpParam) {
while (app.GetXuiServerAction(ProfileManager.GetPrimaryPad()) !=
eXuiServerAction_Idle &&
!MinecraftServer::serverHalted()) {
- Sleep(10);
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
app.SetXuiServerAction(ProfileManager.GetPrimaryPad(),
eXuiServerAction_PauseServer, (void*)TRUE);
@@ -970,7 +963,7 @@ int CGameNetworkManager::ChangeSessionTypeThreadProc(void* lpParam) {
// wait for the current session to end
while (g_NetworkManager.IsInSession()) {
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
// Reset this flag as the we don't need to know that we only lost the room
@@ -1000,7 +993,7 @@ int CGameNetworkManager::ChangeSessionTypeThreadProc(void* lpParam) {
// Wait for all the local players to rejoin the session
while (g_NetworkManager.GetPlayerCount() < numLocalPlayers) {
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
// Restore the network player of all the server players that are local
@@ -1046,14 +1039,14 @@ int CGameNetworkManager::ChangeSessionTypeThreadProc(void* lpParam) {
// Make sure that we have transitioned through any joining/creating stages
// so we're actually ready to set to play
while (!s_pPlatformNetworkManager->IsReadyToPlayOrIdle()) {
- Sleep(10);
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
s_pPlatformNetworkManager->_StartGame();
// Wait until the message box has been closed
while (ui.IsSceneInStack(XUSER_INDEX_ANY, eUIScene_MessageBox)) {
- Sleep(10);
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
// Start the game again
diff --git a/Minecraft.Client/Platform/Common/Tutorial/AreaConstraint.cpp b/Minecraft.Client/Platform/Common/Tutorial/AreaConstraint.cpp
index ddd57b539..2cf4ab5ee 100644
--- a/Minecraft.Client/Platform/Common/Tutorial/AreaConstraint.cpp
+++ b/Minecraft.Client/Platform/Common/Tutorial/AreaConstraint.cpp
@@ -10,23 +10,19 @@ AreaConstraint::AreaConstraint(int descriptionId, double x0, double y0,
bool contains /*= true*/,
bool restrictsMovement /*=true*/)
: TutorialConstraint(descriptionId) {
- messageArea =
- AABB::newPermanent(x0 + 2, y0 + 2, z0 + 2, x1 - 2, y1 - 2, z1 - 2);
- movementArea = AABB::newPermanent(x0, y0, z0, x1, y1, z1);
+ messageArea = AABB(x0 + 2, y0 + 2, z0 + 2, x1 - 2, y1 - 2, z1 - 2);
+ movementArea = AABB(x0, y0, z0, x1, y1, z1);
this->contains = contains;
m_restrictsMovement = restrictsMovement;
}
-AreaConstraint::~AreaConstraint() {
- delete messageArea;
- delete movementArea;
-}
-
bool AreaConstraint::isConstraintSatisfied(int iPad) {
Minecraft* minecraft = Minecraft::GetInstance();
- return messageArea->contains(minecraft->localplayers[iPad]->getPos(1)) ==
- contains;
+
+ // TODO: check if this can be elided
+ Vec3 ipad_player = minecraft->localplayers[iPad]->getPos(1);
+ return messageArea.contains(ipad_player) == contains;
}
bool AreaConstraint::isConstraintRestrictive(int iPad) {
@@ -37,15 +33,15 @@ bool AreaConstraint::canMoveToPosition(double xo, double yo, double zo,
double xt, double yt, double zt) {
if (!m_restrictsMovement) return true;
- Vec3* targetPos = Vec3::newTemp(xt, yt, zt);
+ Vec3 targetPos(xt, yt, zt);
Minecraft* minecraft = Minecraft::GetInstance();
- if (movementArea->contains(targetPos) == contains) {
+ if (movementArea.contains(targetPos) == contains) {
return true;
}
- Vec3* origPos = Vec3::newTemp(xo, yo, zo);
+ Vec3 origPos(xo, yo, zo);
- double currDist = origPos->distanceTo(movementArea);
- double targetDist = targetPos->distanceTo(movementArea);
+ double currDist = origPos.distanceTo(&movementArea);
+ double targetDist = targetPos.distanceTo(&movementArea);
return targetDist < currDist;
}
diff --git a/Minecraft.Client/Platform/Common/Tutorial/AreaConstraint.h b/Minecraft.Client/Platform/Common/Tutorial/AreaConstraint.h
index 721ab6eb1..05265b73f 100644
--- a/Minecraft.Client/Platform/Common/Tutorial/AreaConstraint.h
+++ b/Minecraft.Client/Platform/Common/Tutorial/AreaConstraint.h
@@ -6,8 +6,8 @@ class AABB;
class AreaConstraint : public TutorialConstraint {
private:
- AABB* movementArea;
- AABB* messageArea;
+ AABB movementArea;
+ AABB messageArea;
bool contains; // If true we must stay in this area, if false must stay out
// of this area
bool m_restrictsMovement;
@@ -18,10 +18,9 @@ public:
AreaConstraint(int descriptionId, double x0, double y0, double z0,
double x1, double y1, double z1, bool contains = true,
bool restrictsMovement = true);
- ~AreaConstraint();
virtual bool isConstraintSatisfied(int iPad);
virtual bool isConstraintRestrictive(int iPad);
virtual bool canMoveToPosition(double xo, double yo, double zo, double xt,
double yt, double zt);
-};
\ No newline at end of file
+};
diff --git a/Minecraft.Client/Platform/Common/Tutorial/AreaHint.cpp b/Minecraft.Client/Platform/Common/Tutorial/AreaHint.cpp
index 729b361d0..b3ebdf65a 100644
--- a/Minecraft.Client/Platform/Common/Tutorial/AreaHint.cpp
+++ b/Minecraft.Client/Platform/Common/Tutorial/AreaHint.cpp
@@ -12,7 +12,7 @@ AreaHint::AreaHint(eTutorial_Hint id, Tutorial* tutorial,
double x1, double y1, double z1, bool allowFade /*= false*/,
bool contains /*= true*/)
: TutorialHint(id, tutorial, descriptionId, e_Hint_Area, allowFade) {
- area = AABB::newPermanent(x0, y0, z0, x1, y1, z1);
+ area = AABB(x0, y0, z0, x1, y1, z1);
this->contains = contains;
@@ -20,14 +20,13 @@ AreaHint::AreaHint(eTutorial_Hint id, Tutorial* tutorial,
m_completeState = completeState;
}
-AreaHint::~AreaHint() { delete area; }
-
int AreaHint::tick() {
Minecraft* minecraft = Minecraft::GetInstance();
+ Vec3 player_pos = minecraft->player->getPos(1);
+
if ((m_displayState == e_Tutorial_State_Any ||
m_tutorial->getCurrentState() == m_displayState) &&
- m_hintNeeded &&
- area->contains(minecraft->player->getPos(1)) == contains) {
+ m_hintNeeded && area.contains(player_pos) == contains) {
if (m_completeState == e_Tutorial_State_None) {
m_hintNeeded = false;
} else if (m_tutorial->isStateCompleted(m_completeState)) {
diff --git a/Minecraft.Client/Platform/Common/Tutorial/AreaHint.h b/Minecraft.Client/Platform/Common/Tutorial/AreaHint.h
index 71d8219f2..68ec72ba5 100644
--- a/Minecraft.Client/Platform/Common/Tutorial/AreaHint.h
+++ b/Minecraft.Client/Platform/Common/Tutorial/AreaHint.h
@@ -6,7 +6,7 @@ class AABB;
class AreaHint : public TutorialHint {
private:
- AABB* area;
+ AABB area;
bool contains; // If true we must stay in this area, if false must stay out
// of this area
@@ -21,7 +21,6 @@ public:
eTutorial_State displayState, eTutorial_State completeState,
int descriptionId, double x0, double y0, double z0, double x1,
double y1, double z1, bool allowFade = true, bool contains = true);
- ~AreaHint();
virtual int tick();
-};
\ No newline at end of file
+};
diff --git a/Minecraft.Client/Platform/Common/Tutorial/ChangeStateConstraint.cpp b/Minecraft.Client/Platform/Common/Tutorial/ChangeStateConstraint.cpp
index 9d8d75e1d..4296a04bd 100644
--- a/Minecraft.Client/Platform/Common/Tutorial/ChangeStateConstraint.cpp
+++ b/Minecraft.Client/Platform/Common/Tutorial/ChangeStateConstraint.cpp
@@ -16,7 +16,7 @@ ChangeStateConstraint::ChangeStateConstraint(
bool contains /*= true*/, bool changeGameMode /*= false*/,
GameType* targetGameMode /*= 0*/)
: TutorialConstraint(-1) {
- movementArea = AABB::newPermanent(x0, y0, z0, x1, y1, z1);
+ movementArea = AABB(x0, y0, z0, x1, y1, z1);
this->contains = contains;
@@ -40,7 +40,6 @@ ChangeStateConstraint::ChangeStateConstraint(
}
ChangeStateConstraint::~ChangeStateConstraint() {
- delete movementArea;
if (m_sourceStatesCount > 0) delete[] m_sourceStates;
}
@@ -85,9 +84,11 @@ void ChangeStateConstraint::tick(int iPad) {
break;
}
}
+
+ // TODO: check if this can be elided
+ Vec3 ipad_player = minecraft->localplayers[iPad]->getPos(1);
if (!m_bHasChanged && inASourceState &&
- movementArea->contains(minecraft->localplayers[iPad]->getPos(1)) ==
- contains) {
+ movementArea.contains(ipad_player) == contains) {
m_bHasChanged = true;
m_changedFromState = m_tutorial->getCurrentState();
m_tutorial->changeTutorialState(m_targetState);
@@ -125,8 +126,7 @@ void ChangeStateConstraint::tick(int iPad) {
}
}
} else if (m_bHasChanged &&
- movementArea->contains(
- minecraft->localplayers[iPad]->getPos(1)) != contains) {
+ movementArea.contains(ipad_player) != contains) {
m_bHasChanged = false;
m_tutorial->changeTutorialState(m_changedFromState);
diff --git a/Minecraft.Client/Platform/Common/Tutorial/ChangeStateConstraint.h b/Minecraft.Client/Platform/Common/Tutorial/ChangeStateConstraint.h
index 5ec51d437..44c9b410b 100644
--- a/Minecraft.Client/Platform/Common/Tutorial/ChangeStateConstraint.h
+++ b/Minecraft.Client/Platform/Common/Tutorial/ChangeStateConstraint.h
@@ -11,7 +11,7 @@ class GameType;
class ChangeStateConstraint : public TutorialConstraint {
private:
- AABB* movementArea;
+ AABB movementArea;
bool contains; // If true we must stay in this area, if false must stay out
// of this area
bool m_changeGameMode;
diff --git a/Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.cpp b/Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.cpp
index 9c7c8061b..47c28d4c6 100644
--- a/Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.cpp
+++ b/Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.cpp
@@ -434,6 +434,11 @@ void IUIScene_CreativeMenu::staticCtor() {
ITEM(Item::carrotGolden_Id)
ITEM(Item::pumpkinPie_Id)
+// 4jcraft: Search
+#ifdef ENABLE_JAVA_GUIS
+ DEF(eCreativeInventory_Search)
+#endif
+
// Tools, Armour and Weapons (Complete)
DEF(eCreativeInventory_ToolsArmourWeapons)
ITEM(Item::compass_Id)
@@ -821,6 +826,13 @@ void IUIScene_CreativeMenu::staticCtor() {
specs[eCreativeInventoryTab_Food] =
new TabSpec(L"Food", IDS_GROUPNAME_FOOD, 1, foodGroup);
+// 4jcraft
+#ifdef ENABLE_JAVA_GUIS
+ ECreative_Inventory_Groups searchGroup[] = {eCreativeInventory_Search};
+ specs[eCreativeInventoryTab_Search] =
+ new TabSpec(L"Search Items", IDS_GROUPNAME_SEARCH, 1, searchGroup);
+#endif
+
ECreative_Inventory_Groups toolsGroup[] = {
eCreativeInventory_ToolsArmourWeapons};
specs[eCreativeInventoryTab_ToolsWeaponsArmor] =
@@ -863,7 +875,7 @@ IUIScene_CreativeMenu::IUIScene_CreativeMenu() {
m_bCarryingCreativeItem = false;
m_creativeSlotX = m_creativeSlotY = m_inventorySlotX = m_inventorySlotY = 0;
- // 4J JEV - Settup Tabs
+ // 4J JEV - Setup Tabs
for (int i = 0; i < eCreativeInventoryTab_COUNT; i++) {
m_tabDynamicPos[i] = 0;
m_tabPage[i] = 0;
@@ -1488,4 +1500,4 @@ void IUIScene_CreativeMenu::BuildFirework(
}
list->push_back(firework);
-}
+}
\ No newline at end of file
diff --git a/Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.h b/Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.h
index 02967ac5a..fc2cb071e 100644
--- a/Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.h
+++ b/Minecraft.Client/Platform/Common/UI/IUIScene_CreativeMenu.h
@@ -7,20 +7,24 @@ class SimpleContainer;
class IUIScene_CreativeMenu : public virtual IUIScene_AbstractContainerMenu {
public:
- // 4J Stu - These map directly to the tabs seenon the screen
+ // 4J Stu - These map directly to the tabs seen on the screen
enum ECreativeInventoryTabs {
eCreativeInventoryTab_BuildingBlocks = 0,
eCreativeInventoryTab_Decorations,
eCreativeInventoryTab_RedstoneAndTransport,
eCreativeInventoryTab_Materials,
eCreativeInventoryTab_Food,
+// 4jcraft: java search tab
+#ifdef ENABLE_JAVA_GUIS
+ eCreativeInventoryTab_Search,
+#endif
eCreativeInventoryTab_ToolsWeaponsArmor,
eCreativeInventoryTab_Brewing,
eCreativeInventoryTab_Misc,
eCreativeInventoryTab_COUNT,
};
- // 4J Stu - These are logical groupings of items, and be be combined for
+ // 4J Stu - These are logical groupings of items, and are combined for
// tabs on-screen
enum ECreative_Inventory_Groups {
eCreativeInventory_BuildingBlocks,
@@ -29,6 +33,10 @@ public:
eCreativeInventory_Transport,
eCreativeInventory_Materials,
eCreativeInventory_Food,
+// 4jcraft
+#ifdef ENABLE_JAVA_GUIS
+ eCreativeInventory_Search,
+#endif
eCreativeInventory_ToolsArmourWeapons,
eCreativeInventory_Brewing,
eCreativeInventory_Potions_Basic,
@@ -97,7 +105,7 @@ public:
virtual void loopClick(int slotIndex, int buttonNum, bool quickKeyHeld,
std::shared_ptr player) {} // do nothing
}* itemPickerMenu;
-
+
// 4jcraft: changed these two from public to protected for the java UI
static std::vector >
categoryGroups[eCreativeInventoryGroupsCount];
@@ -148,4 +156,4 @@ protected:
static void BuildFirework(std::vector >* list,
uint8_t type, int color, int sulphur,
bool flicker, bool trail, int fadeColor = -1);
-};
\ No newline at end of file
+};
diff --git a/Minecraft.Client/Platform/Common/UI/IUIScene_PauseMenu.cpp b/Minecraft.Client/Platform/Common/UI/IUIScene_PauseMenu.cpp
index e96bd4c91..6c51d1bfb 100644
--- a/Minecraft.Client/Platform/Common/UI/IUIScene_PauseMenu.cpp
+++ b/Minecraft.Client/Platform/Common/UI/IUIScene_PauseMenu.cpp
@@ -1,3 +1,6 @@
+#include
+#include
+
#include "../../Minecraft.World/Platform/stdafx.h"
#include "IUIScene_PauseMenu.h"
#include "UIScene.h"
@@ -207,8 +210,6 @@ int IUIScene_PauseMenu::SaveWorldThreadProc(void* lpParameter) {
// Share AABB & Vec3 pools with default (main thread) - should be ok as long
// as we don't tick the main thread whilst this thread is running
- AABB::UseDefaultThreadStorage();
- Vec3::UseDefaultThreadStorage();
Compression::UseDefaultThreadStorage();
Minecraft* pMinecraft = Minecraft::GetInstance();
@@ -221,7 +222,7 @@ int IUIScene_PauseMenu::SaveWorldThreadProc(void* lpParameter) {
while (app.GetXuiServerAction(ProfileManager.GetPrimaryPad()) !=
eXuiServerAction_Idle &&
!MinecraftServer::serverHalted()) {
- Sleep(10);
+ std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
if (!MinecraftServer::serverHalted() && !app.GetChangingSessionType())
@@ -241,8 +242,6 @@ int IUIScene_PauseMenu::SaveWorldThreadProc(void* lpParameter) {
int IUIScene_PauseMenu::ExitWorldThreadProc(void* lpParameter) {
// Share AABB & Vec3 pools with default (main thread) - should be ok as long
// as we don't tick the main thread whilst this thread is running
- AABB::UseDefaultThreadStorage();
- Vec3::UseDefaultThreadStorage();
Compression::UseDefaultThreadStorage();
// app.SetGameStarted(false);
@@ -418,7 +417,7 @@ void IUIScene_PauseMenu::_ExitWorld(void* lpParameter) {
// multiplayer client if host of the game will exit during the clients
// loading to created world.
while (g_NetworkManager.IsNetworkThreadRunning()) {
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
pMinecraft->setLevel(NULL, exitReasonStringId, nullptr, saveStats);
@@ -438,7 +437,7 @@ void IUIScene_PauseMenu::_ExitWorld(void* lpParameter) {
// loads saved data We can't start/join a new game until the session is
// destroyed, so wait for it to be idle again
while (g_NetworkManager.IsInSession()) {
- Sleep(1);
+ std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
app.SetChangingSessionType(false);
diff --git a/Minecraft.Client/Platform/Common/UI/UIControl.cpp b/Minecraft.Client/Platform/Common/UI/UIControl.cpp
index fa31261e5..f915cf574 100644
--- a/Minecraft.Client/Platform/Common/UI/UIControl.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIControl.cpp
@@ -10,7 +10,12 @@ UIControl::UIControl() {
m_controlName = "";
m_isVisible = true;
m_bHidden = false;
+ m_isValid = false;
m_eControlType = eNoControl;
+ m_x = 0;
+ m_y = 0;
+ m_width = 0;
+ m_height = 0;
}
bool UIControl::setupControl(UIScene* scene, IggyValuePath* parent,
@@ -20,6 +25,7 @@ bool UIControl::setupControl(UIScene* scene, IggyValuePath* parent,
rrbool res =
IggyValuePathMakeNameRef(&m_iggyPath, parent, controlName.c_str());
+ m_isValid = res ? true : false;
m_nameXPos = registerFastName(L"x");
m_nameYPos = registerFastName(L"y");
@@ -28,22 +34,40 @@ bool UIControl::setupControl(UIScene* scene, IggyValuePath* parent,
m_funcSetAlpha = registerFastName(L"SetControlAlpha");
m_nameVisible = registerFastName(L"visible");
- F64 fx, fy, fwidth, fheight;
- IggyValueGetF64RS(getIggyValuePath(), m_nameXPos, NULL, &fx);
- IggyValueGetF64RS(getIggyValuePath(), m_nameYPos, NULL, &fy);
- IggyValueGetF64RS(getIggyValuePath(), m_nameWidth, NULL, &fwidth);
- IggyValueGetF64RS(getIggyValuePath(), m_nameHeight, NULL, &fheight);
+ if (m_isValid) {
+ IggyDatatype controlType = IGGY_DATATYPE__invalid_request;
+ IggyResult typeResult =
+ IggyValueGetTypeRS(getIggyValuePath(), 0, NULL, &controlType);
+ m_isValid = typeResult == IGGY_RESULT_SUCCESS &&
+ controlType != IGGY_DATATYPE__invalid_request &&
+ controlType != IGGY_DATATYPE_undefined;
+ }
- m_x = (S32)fx;
- m_y = (S32)fy;
- m_width = (S32)Math::round(fwidth);
- m_height = (S32)Math::round(fheight);
+ if (m_isValid) {
+ F64 fx, fy, fwidth, fheight;
+ IggyValueGetF64RS(getIggyValuePath(), m_nameXPos, NULL, &fx);
+ IggyValueGetF64RS(getIggyValuePath(), m_nameYPos, NULL, &fy);
+ IggyValueGetF64RS(getIggyValuePath(), m_nameWidth, NULL, &fwidth);
+ IggyValueGetF64RS(getIggyValuePath(), m_nameHeight, NULL, &fheight);
+
+ m_x = (S32)fx;
+ m_y = (S32)fy;
+ m_width = (S32)Math::round(fwidth);
+ m_height = (S32)Math::round(fheight);
+ } else {
+ m_x = 0;
+ m_y = 0;
+ m_width = 0;
+ m_height = 0;
+ }
return res;
}
void UIControl::ReInit() {
+ if (!m_isValid) return;
+
if (m_lastOpacity != 1.0f) {
IggyDataValue result;
IggyDataValue value[2];
@@ -78,6 +102,7 @@ S32 UIControl::getHeight() { return m_height; }
void UIControl::setOpacity(float percent) {
if (percent != m_lastOpacity) {
m_lastOpacity = percent;
+ if (!m_isValid) return;
IggyDataValue result;
IggyDataValue value[2];
@@ -99,6 +124,11 @@ void UIControl::setOpacity(float percent) {
void UIControl::setVisible(bool visible) {
if (visible != m_isVisible) {
+ if (!m_isValid) {
+ m_isVisible = visible;
+ return;
+ }
+
rrbool succ = IggyValueSetBooleanRS(getIggyValuePath(), m_nameVisible,
NULL, visible);
if (succ)
@@ -109,6 +139,8 @@ void UIControl::setVisible(bool visible) {
}
bool UIControl::getVisible() {
+ if (!m_isValid) return m_isVisible;
+
rrbool bVisible = false;
IggyResult result = IggyValueGetBooleanRS(getIggyValuePath(), m_nameVisible,
diff --git a/Minecraft.Client/Platform/Common/UI/UIControl.h b/Minecraft.Client/Platform/Common/UI/UIControl.h
index 36922bc3e..a8df8d792 100644
--- a/Minecraft.Client/Platform/Common/UI/UIControl.h
+++ b/Minecraft.Client/Platform/Common/UI/UIControl.h
@@ -34,6 +34,7 @@ protected:
eUIControlType m_eControlType;
int m_id;
bool m_bHidden; // set by the Remove call
+ bool m_isValid;
public:
void setControlType(eUIControlType eType) { m_eControlType = eType; }
@@ -78,6 +79,7 @@ public:
void setVisible(bool visible);
bool getVisible();
bool isVisible() { return m_isVisible; }
+ bool isValid() { return m_isValid; }
virtual bool hasFocus() { return false; }
diff --git a/Minecraft.Client/Platform/Common/UI/UIController.cpp b/Minecraft.Client/Platform/Common/UI/UIController.cpp
index 75efb9cfc..9f1ea23a3 100644
--- a/Minecraft.Client/Platform/Common/UI/UIController.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIController.cpp
@@ -63,6 +63,16 @@ static void RADLINK WarningCallback(void* user_callback_data, Iggy* player,
// IGGY_RESULT_Error_UndefinedEntity = 504,
// IGGY_RESULT_Error_OutOfMemory = 1001,};
+ if (message != NULL) {
+ // 4jcraft: Some Linux movie variants do not ship these optional
+ // hooks/controls. We guard the call sites, so drop the residual Iggy
+ // warning noise.
+ if (strstr(message, "LabelGamertag") != NULL ||
+ strstr(message, "Method SetSafeZone was not a function") != NULL) {
+ return;
+ }
+ }
+
switch (code) {
case IGGY_RESULT_Warning_CannotSustainFrameRate:
// Ignore warning
@@ -2282,4 +2292,3 @@ UIScene* UIController::FindScene(EUIScene sceneType) {
return pScene;
}
-
diff --git a/Minecraft.Client/Platform/Common/UI/UIScene.cpp b/Minecraft.Client/Platform/Common/UI/UIScene.cpp
index 39ee814c0..5173bb516 100644
--- a/Minecraft.Client/Platform/Common/UI/UIScene.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIScene.cpp
@@ -19,6 +19,7 @@ UIScene::UIScene(int iPad, UILayer* parentLayer) {
m_bVisible = true;
m_bCanHandleInput = false;
m_bIsReloading = false;
+ m_hasSetSafeZoneMethod = false;
m_iFocusControl = -1;
m_iFocusChild = 0;
@@ -53,6 +54,7 @@ void UIScene::destroyMovie() {
/* Destroy the Iggy player. */
IggyPlayerDestroy(swf);
swf = NULL;
+ m_hasSetSafeZoneMethod = false;
// Clear out the controls collection (doesn't delete the controls, and they
// get re-setup later)
@@ -76,6 +78,7 @@ void UIScene::reloadMovie(bool force) {
// Clear out the controls collection (doesn't delete the controls, and
// they get re-setup later)
m_controls.clear();
+ m_hasSetSafeZoneMethod = false;
// Clear out all the fast names for the current movie
m_fastNames.clear();
@@ -190,6 +193,8 @@ void UIScene::updateSafeZone() {
void UIScene::setSafeZone(S32 safeTop, S32 safeBottom, S32 safeLeft,
S32 safeRight) {
+ if (!m_hasSetSafeZoneMethod) return;
+
IggyDataValue result;
IggyDataValue value[4];
@@ -230,6 +235,13 @@ bool UIScene::mapElementsAndNames() {
m_funcSetAlpha = registerFastName(L"SetAlpha");
m_funcSetFocus = registerFastName(L"SetFocus");
m_funcHorizontalResizeCheck = registerFastName(L"DoHorizontalResizeCheck");
+
+ IggyDatatype safeZoneType = IGGY_DATATYPE__invalid_request;
+ IggyResult safeZoneResult = IggyValueGetTypeRS(
+ m_rootPath, m_funcSetSafeZone, NULL, &safeZoneType);
+ m_hasSetSafeZoneMethod =
+ safeZoneResult == IGGY_RESULT_SUCCESS &&
+ safeZoneType == IGGY_DATATYPE_function;
return true;
}
@@ -633,7 +645,7 @@ void UIScene::_customDrawSlotControl(CustomDrawData* region, int iPad,
}
glEnable(GL_RESCALE_NORMAL);
glPushMatrix();
- Lighting::turnOnGui();
+ Lighting::turnOn();
glRotatef(120, 1, 0, 0);
glPopMatrix();
diff --git a/Minecraft.Client/Platform/Common/UI/UIScene.h b/Minecraft.Client/Platform/Common/UI/UIScene.h
index d6c92fe66..f52d73ac4 100644
--- a/Minecraft.Client/Platform/Common/UI/UIScene.h
+++ b/Minecraft.Client/Platform/Common/UI/UIScene.h
@@ -72,6 +72,7 @@ private:
bool m_bUpdateOpacity;
bool m_bVisible;
bool m_bCanHandleInput;
+ bool m_hasSetSafeZoneMethod;
UIScene* m_backScene;
size_t m_callbackUniqueId;
diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_AnvilMenu.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_AnvilMenu.cpp
index 6a11deb2a..bc8cfaa79 100644
--- a/Minecraft.Client/Platform/Common/UI/UIScene_AnvilMenu.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIScene_AnvilMenu.cpp
@@ -4,6 +4,7 @@
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h"
#include "../../Minecraft.Client/Player/MultiPlayerLocalPlayer.h"
#include "../../Minecraft.Client/Minecraft.h"
+#include "../../Minecraft.World/Util/StringHelpers.h"
#include "UIScene_AnvilMenu.h"
UIScene_AnvilMenu::UIScene_AnvilMenu(int iPad, void* _initData,
@@ -297,11 +298,9 @@ int UIScene_AnvilMenu::KeyboardCompleteCallback(void* lpParam, bool bRes) {
pClass->setIgnoreInput(false);
if (bRes) {
- uint16_t pchText[128];
- ZeroMemory(pchText, 128 * sizeof(uint16_t));
- InputManager.GetText(pchText);
- pClass->setEditNameValue((wchar_t*)pchText);
- pClass->m_itemName = (wchar_t*)pchText;
+ std::wstring str = convStringToWstring(InputManager.GetText());
+ pClass->setEditNameValue(str);
+ pClass->m_itemName = std::move(str);
pClass->updateItemName();
}
return 0;
diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_CreateWorldMenu.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_CreateWorldMenu.cpp
index 39dd3e911..1d7b0d614 100644
--- a/Minecraft.Client/Platform/Common/UI/UIScene_CreateWorldMenu.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIScene_CreateWorldMenu.cpp
@@ -549,13 +549,10 @@ int UIScene_CreateWorldMenu::KeyboardCompleteWorldNameCallback(void* lpParam,
pClass->m_bIgnoreInput = false;
// 4J HEG - No reason to set value if keyboard was cancelled
if (bRes) {
- uint16_t pchText[128];
- ZeroMemory(pchText, 128 * sizeof(uint16_t));
- InputManager.GetText(pchText);
-
- if (pchText[0] != 0) {
- pClass->m_editWorldName.setLabel((wchar_t*)pchText);
- pClass->m_worldName = (wchar_t*)pchText;
+ std::wstring str = convStringToWstring(InputManager.GetText());
+ if (!str.empty()) {
+ pClass->m_editWorldName.setLabel(str);
+ pClass->m_worldName = std::move(str);
}
pClass->m_buttonCreateWorld.setEnable(!pClass->m_worldName.empty());
@@ -628,9 +625,9 @@ void UIScene_CreateWorldMenu::checkStateAndStartGame() {
bool pccFriendsAllowed = true;
bool bContentRestricted = false;
- ProfileManager.AllowedPlayerCreatedContent(
- ProfileManager.GetPrimaryPad(), false, &pccAllowed,
- &pccFriendsAllowed);
+ GetAllowedPlayerCreatedContentFlags(ProfileManager.GetPrimaryPad(),
+ false, &pccAllowed,
+ &pccFriendsAllowed);
noUGC = !pccAllowed && !pccFriendsAllowed;
@@ -934,9 +931,9 @@ int UIScene_CreateWorldMenu::StartGame_SignInReturned(void* pParam,
bool pccAllowed = true;
bool pccFriendsAllowed = true;
- ProfileManager.AllowedPlayerCreatedContent(
- ProfileManager.GetPrimaryPad(), false, &pccAllowed,
- &pccFriendsAllowed);
+ GetAllowedPlayerCreatedContentFlags(ProfileManager.GetPrimaryPad(),
+ false, &pccAllowed,
+ &pccFriendsAllowed);
if (!pccAllowed && !pccFriendsAllowed) noUGC = true;
if (isOnlineGame && (noPrivileges || noUGC)) {
diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_DebugCreateSchematic.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_DebugCreateSchematic.cpp
index 3e2d56504..6eb2c7bb4 100644
--- a/Minecraft.Client/Platform/Common/UI/UIScene_DebugCreateSchematic.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIScene_DebugCreateSchematic.cpp
@@ -141,12 +141,9 @@ int UIScene_DebugCreateSchematic::KeyboardCompleteCallback(void* lpParam,
UIScene_DebugCreateSchematic* pClass =
(UIScene_DebugCreateSchematic*)lpParam;
- uint16_t pchText[128];
- ZeroMemory(pchText, 128 * sizeof(uint16_t));
- InputManager.GetText(pchText);
-
- if (pchText[0] != 0) {
- std::wstring value = (wchar_t*)pchText;
+ const char* text = InputManager.GetText();
+ if (text[0] != '\0') {
+ std::wstring value = convStringToWstring(text);
int iVal = 0;
if (!value.empty()) iVal = _fromString(value);
switch (pClass->m_keyboardCallbackControl) {
diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_DebugSetCamera.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_DebugSetCamera.cpp
index 89e872eb9..74787f726 100644
--- a/Minecraft.Client/Platform/Common/UI/UIScene_DebugSetCamera.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIScene_DebugSetCamera.cpp
@@ -19,13 +19,13 @@ UIScene_DebugSetCamera::UIScene_DebugSetCamera(int iPad, void* initData,
Minecraft* pMinecraft = Minecraft::GetInstance();
if (pMinecraft != NULL) {
- Vec3* vec = pMinecraft->localplayers[playerNo]->getPos(1.0);
+ Vec3 vec = pMinecraft->localplayers[playerNo]->getPos(1.0);
- currentPosition->m_camX = vec->x;
+ currentPosition->m_camX = vec.x;
currentPosition->m_camY =
- vec->y -
+ vec.y -
1.62; // pMinecraft->localplayers[playerNo]->getHeadHeight();
- currentPosition->m_camZ = vec->z;
+ currentPosition->m_camZ = vec.z;
currentPosition->m_yRot = pMinecraft->localplayers[playerNo]->yRot;
currentPosition->m_elev = pMinecraft->localplayers[playerNo]->xRot;
@@ -119,12 +119,9 @@ void UIScene_DebugSetCamera::handleCheckboxToggled(F64 controlId,
int UIScene_DebugSetCamera::KeyboardCompleteCallback(void* lpParam, bool bRes) {
UIScene_DebugSetCamera* pClass = (UIScene_DebugSetCamera*)lpParam;
- uint16_t pchText[2048]; //[128];
- ZeroMemory(pchText, 2048 /*128*/ * sizeof(uint16_t));
- InputManager.GetText(pchText);
-
- if (pchText[0] != 0) {
- std::wstring value = (wchar_t*)pchText;
+ const char* text = InputManager.GetText();
+ if (text[0] != '\0') {
+ std::wstring value = convStringToWstring(text);
double val = 0;
if (!value.empty()) val = _fromString(value);
switch (pClass->m_keyboardCallbackControl) {
diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_EnchantingMenu.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_EnchantingMenu.cpp
index e13edeb67..a04cc003b 100644
--- a/Minecraft.Client/Platform/Common/UI/UIScene_EnchantingMenu.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIScene_EnchantingMenu.cpp
@@ -4,6 +4,8 @@
#include "../../Minecraft.World/Headers/net.minecraft.world.inventory.h"
#include "../../Minecraft.Client/Minecraft.h"
#include "UIScene_EnchantingMenu.h"
+
+
UIScene_EnchantingMenu::UIScene_EnchantingMenu(int iPad, void* _initData,
UILayer* parentLayer)
: UIScene_AbstractContainerMenu(iPad, parentLayer) {
diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp
index 9b9d1869f..96bd32945 100644
--- a/Minecraft.Client/Platform/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIScene_LaunchMoreOptionsMenu.cpp
@@ -1,5 +1,6 @@
#include "../../Minecraft.World/Platform/stdafx.h"
#include "UI.h"
+#include "../../Minecraft.World/Util/StringHelpers.h"
#include "UIScene_LaunchMoreOptionsMenu.h"
#define GAME_CREATE_ONLINE_TIMER_ID 0
@@ -527,15 +528,13 @@ int UIScene_LaunchMoreOptionsMenu::KeyboardCompleteSeedCallback(void* lpParam,
bool bRes) {
UIScene_LaunchMoreOptionsMenu* pClass =
(UIScene_LaunchMoreOptionsMenu*)lpParam;
- pClass->m_bIgnoreInput = false;
// 4J HEG - No reason to set value if keyboard was cancelled
if (bRes) {
- uint16_t pchText[128];
- ZeroMemory(pchText, 128 * sizeof(uint16_t));
- InputManager.GetText(pchText);
- pClass->m_editSeed.setLabel((wchar_t*)pchText);
- pClass->m_params->seed = (wchar_t*)pchText;
+ std::wstring str = convStringToWstring(InputManager.GetText());
+ pClass->m_editSeed.setLabel(str);
+ pClass->m_params->seed = std::move(str);
}
+ pClass->m_bIgnoreInput = false;
return 0;
}
diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_LoadOrJoinMenu.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_LoadOrJoinMenu.cpp
index 281c3cd8b..33d63d33a 100644
--- a/Minecraft.Client/Platform/Common/UI/UIScene_LoadOrJoinMenu.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIScene_LoadOrJoinMenu.cpp
@@ -1,3 +1,6 @@
+#include
+#include
+
#include "../../Minecraft.World/Platform/stdafx.h"
#include "UI.h"
#include "UIScene_LoadOrJoinMenu.h"
@@ -837,12 +840,9 @@ int UIScene_LoadOrJoinMenu::KeyboardCompleteWorldNameCallback(void* lpParam,
UIScene_LoadOrJoinMenu* pClass = (UIScene_LoadOrJoinMenu*)lpParam;
pClass->m_bIgnoreInput = false;
if (bRes) {
- std::uint16_t ui16Text[128];
- ZeroMemory(ui16Text, 128 * sizeof(std::uint16_t));
- InputManager.GetText(ui16Text);
-
+ const char* text = InputManager.GetText();
// check the name is valid
- if (ui16Text[0] != 0) {
+ if (text[0] != '\0') {
} else {
pClass->m_bIgnoreInput = false;
pClass->updateTooltips();
@@ -2122,7 +2122,7 @@ int UIScene_LoadOrJoinMenu::DownloadSonyCrossSaveThreadProc(void* lpParameter) {
// waiting to dismiss the dialog
break;
}
- Sleep(50);
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
m_bSaveTransferRunning = false;
return 0;
@@ -2271,7 +2271,7 @@ int UIScene_LoadOrJoinMenu::UploadSonyCrossSaveThreadProc(void* lpParameter) {
// waiting for dialog to be dismissed
break;
}
- Sleep(50);
+ std::this_thread::sleep_for(std::chrono::milliseconds(50));
}
return 0;
@@ -2322,7 +2322,3 @@ int UIScene_LoadOrJoinMenu::SaveTransferDialogReturned(
}
return 0;
}
-#endif
-
-
-
diff --git a/Minecraft.Client/Platform/Common/UI/UIScene_SignEntryMenu.cpp b/Minecraft.Client/Platform/Common/UI/UIScene_SignEntryMenu.cpp
index 85b4a8666..474fe4446 100644
--- a/Minecraft.Client/Platform/Common/UI/UIScene_SignEntryMenu.cpp
+++ b/Minecraft.Client/Platform/Common/UI/UIScene_SignEntryMenu.cpp
@@ -1,5 +1,6 @@
#include "../../Minecraft.World/Platform/stdafx.h"
#include "UI.h"
+#include "../../Minecraft.World/Util/StringHelpers.h"
#include "UIScene_SignEntryMenu.h"
#include "../../Minecraft.Client/Minecraft.h"
#include "../../Minecraft.Client/Player/MultiPlayerLocalPlayer.h"
@@ -17,6 +18,7 @@ UIScene_SignEntryMenu::UIScene_SignEntryMenu(int iPad, void* _initData,
SignEntryScreenInput* initData = (SignEntryScreenInput*)_initData;
m_sign = initData->sign;
+ m_iEditingLine = 0;
m_bConfirmed = false;
m_bIgnoreInput = false;
@@ -137,12 +139,10 @@ int UIScene_SignEntryMenu::KeyboardCompleteCallback(void* lpParam, bool bRes) {
// 4J HEG - No reason to set value if keyboard was cancelled
UIScene_SignEntryMenu* pClass = (UIScene_SignEntryMenu*)lpParam;
pClass->m_bIgnoreInput = false;
- if (bRes) {
- uint16_t pchText[128];
- ZeroMemory(pchText, 128 * sizeof(uint16_t));
- InputManager.GetText(pchText);
- pClass->m_textInputLines[pClass->m_iEditingLine].setLabel(
- (wchar_t*)pchText);
+ if (bRes && pClass->m_iEditingLine >= 0 && pClass->m_iEditingLine < 4) {
+ std::wstring str = convStringToWstring(InputManager.GetText());
+ if (str.size() > 15) str.resize(15);
+ pClass->m_textInputLines[pClass->m_iEditingLine].setLabel(str);
}
return 0;
}
diff --git a/Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw.c b/Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw.c
new file mode 100644
index 000000000..4fde9a91f
--- /dev/null
+++ b/Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw.c
@@ -0,0 +1,835 @@
+#define GDRAW_ASSERTS
+
+#include "../../../Windows64/Iggy/include/iggy.h"
+#include "../../../Windows64/Iggy/include/gdraw.h"
+#include "gdraw.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define true 1
+#define false 0
+
+#ifndef _ENABLEIGGY
+void* IggyGDrawMallocAnnotated(SINTa size, const char* file, int line) {
+ (void)file;
+ (void)line;
+ return malloc((size_t)size);
+}
+
+void IggyGDrawFree(void* ptr) { free(ptr); }
+
+void IggyGDrawSendWarning(Iggy* f, char const* message, ...) {
+ (void)f;
+ va_list args;
+ va_start(args, message);
+ fprintf(stderr, "[Iggy GDraw Warning] ");
+ vfprintf(stderr, message, args);
+ fprintf(stderr, "\n");
+ va_end(args);
+}
+
+void IggyDiscardVertexBufferCallback(void* owner, void* buf) {
+ (void)owner;
+ (void)buf;
+}
+#endif
+
+static void* get_gl_proc(const char* name) {
+ void* p = SDL_GL_GetProcAddress(name);
+ if (!p) p = dlsym(RTLD_DEFAULT, name);
+ if (!p) {
+ char buf[256];
+ strncpy(buf, name, sizeof(buf) - 1);
+ buf[255] = '\0';
+ char* ext = strstr(buf, "ARB");
+ if (!ext) ext = strstr(buf, "EXT");
+ if (ext && ext == buf + strlen(buf) - 3) {
+ *ext = '\0';
+ p = SDL_GL_GetProcAddress(buf);
+ if (!p) p = dlsym(RTLD_DEFAULT, buf);
+ }
+ }
+ return p;
+}
+
+#define GDRAW_GL_EXTENSION_LIST \
+ /* identifier import procname */ \
+ /* GL_ARB_vertex_buffer_object */ \
+ GLE(GenBuffers, "GenBuffersARB", GENBUFFERSARB) \
+ GLE(DeleteBuffers, "DeleteBuffersARB", DELETEBUFFERSARB) \
+ GLE(BindBuffer, "BindBufferARB", BINDBUFFERARB) \
+ GLE(BufferData, "BufferDataARB", BUFFERDATAARB) \
+ GLE(MapBuffer, "MapBufferARB", MAPBUFFERARB) \
+ GLE(UnmapBuffer, "UnmapBufferARB", UNMAPBUFFERARB) \
+ GLE(VertexAttribPointer, "VertexAttribPointerARB", VERTEXATTRIBPOINTERARB) \
+ GLE(EnableVertexAttribArray, "EnableVertexAttribArrayARB", \
+ ENABLEVERTEXATTRIBARRAYARB) \
+ GLE(DisableVertexAttribArray, "DisableVertexAttribArrayARB", \
+ DISABLEVERTEXATTRIBARRAYARB) \
+ /* GL_ARB_shader_objects */ \
+ GLE(CreateShader, "CreateShaderObjectARB", CREATESHADEROBJECTARB) \
+ GLE(DeleteShader, "DeleteObjectARB", DELETEOBJECTARB) \
+ GLE(ShaderSource, "ShaderSourceARB", SHADERSOURCEARB) \
+ GLE(CompileShader, "CompileShaderARB", COMPILESHADERARB) \
+ GLE(GetShaderiv, "GetObjectParameterivARB", GETOBJECTPARAMETERIVARB) \
+ GLE(GetShaderInfoLog, "GetInfoLogARB", GETINFOLOGARB) \
+ GLE(CreateProgram, "CreateProgramObjectARB", CREATEPROGRAMOBJECTARB) \
+ GLE(DeleteProgram, "DeleteObjectARB", DELETEOBJECTARB) \
+ GLE(AttachShader, "AttachObjectARB", ATTACHOBJECTARB) \
+ GLE(LinkProgram, "LinkProgramARB", LINKPROGRAMARB) \
+ GLE(GetUniformLocation, "GetUniformLocationARB", GETUNIFORMLOCATIONARB) \
+ GLE(UseProgram, "UseProgramObjectARB", USEPROGRAMOBJECTARB) \
+ GLE(GetProgramiv, "GetObjectParameterivARB", GETOBJECTPARAMETERIVARB) \
+ GLE(GetProgramInfoLog, "GetInfoLogARB", GETINFOLOGARB) \
+ GLE(Uniform1i, "Uniform1iARB", UNIFORM1IARB) \
+ GLE(Uniform4f, "Uniform4fARB", UNIFORM4FARB) \
+ GLE(Uniform4fv, "Uniform4fvARB", UNIFORM4FVARB) \
+ /* GL_ARB_vertex_shader */ \
+ GLE(BindAttribLocation, "BindAttribLocationARB", BINDATTRIBLOCATIONARB) \
+ /* Missing from WGL but needed by shared code */ \
+ GLE(Uniform1f, "Uniform1fARB", UNIFORM1FARB) \
+ /* GL_EXT_framebuffer_object */ \
+ GLE(GenRenderbuffers, "GenRenderbuffersEXT", GENRENDERBUFFERSEXT) \
+ GLE(DeleteRenderbuffers, "DeleteRenderbuffersEXT", DELETERENDERBUFFERSEXT) \
+ GLE(BindRenderbuffer, "BindRenderbufferEXT", BINDRENDERBUFFEREXT) \
+ GLE(RenderbufferStorage, "RenderbufferStorageEXT", RENDERBUFFERSTORAGEEXT) \
+ GLE(GenFramebuffers, "GenFramebuffersEXT", GENFRAMEBUFFERSEXT) \
+ GLE(DeleteFramebuffers, "DeleteFramebuffersEXT", DELETEFRAMEBUFFERSEXT) \
+ GLE(BindFramebuffer, "BindFramebufferEXT", BINDFRAMEBUFFEREXT) \
+ GLE(CheckFramebufferStatus, "CheckFramebufferStatusEXT", \
+ CHECKFRAMEBUFFERSTATUSEXT) \
+ GLE(FramebufferRenderbuffer, "FramebufferRenderbufferEXT", \
+ FRAMEBUFFERRENDERBUFFEREXT) \
+ GLE(FramebufferTexture2D, "FramebufferTexture2DEXT", \
+ FRAMEBUFFERTEXTURE2DEXT) \
+ GLE(GenerateMipmap, "GenerateMipmapEXT", GENERATEMIPMAPEXT) \
+ /* GL_EXT_framebuffer_blit */ \
+ GLE(BlitFramebuffer, "BlitFramebufferEXT", BLITFRAMEBUFFEREXT) \
+ /* GL_EXT_framebuffer_multisample */ \
+ GLE(RenderbufferStorageMultisample, "RenderbufferStorageMultisampleEXT", \
+ RENDERBUFFERSTORAGEMULTISAMPLEEXT) \
+ /* */
+
+// Shared .inl
+#define gdraw_GLx_(id) gdraw_GL_##id
+#define GDRAW_GLx_(id) GDRAW_GL_##id
+#define GDRAW_SHADERS "gdraw_gl_shaders.inl"
+
+// GLhandleARB is void* but shader functions use GLuint values.
+// homework stolen from gdraw_gl_shared.inl.
+#define GDrawGLProgram GLuint
+typedef GLuint GLhandle;
+typedef gdraw_gl_resourcetype gdraw_resourcetype;
+
+#define GLE(id, import, procname) static PFNGL##procname##PROC gl##id;
+GDRAW_GL_EXTENSION_LIST
+#undef GLE
+
+typedef const GLubyte*(APIENTRYP PFNGLGETSTRINGIPROC_)(GLenum name,
+ GLuint index);
+static PFNGLGETSTRINGIPROC_ gdraw_glGetStringi = NULL;
+
+typedef void(APIENTRYP PFNGLGENVERTEXARRAYSPROC_)(GLsizei n, GLuint* arrays);
+typedef void(APIENTRYP PFNGLBINDVERTEXARRAYPROC_)(GLuint array);
+static PFNGLGENVERTEXARRAYSPROC_ gdraw_glGenVertexArrays = NULL;
+static PFNGLBINDVERTEXARRAYPROC_ gdraw_glBindVertexArray = NULL;
+static GLuint gdraw_vao = 0;
+
+typedef void(APIENTRYP gdraw_vtxattrib_fn)(GLuint, GLint, GLenum, GLboolean,
+ GLsizei, const void*);
+static gdraw_vtxattrib_fn gdraw_real_vtxattrib = NULL;
+static GLuint gdraw_screenvbo = 0;
+static const void* gdraw_screenvbo_base = NULL;
+static size_t gdraw_expected_vbo_size = 0;
+
+typedef void(APIENTRYP gdraw_drawelements_fn)(GLenum mode, GLsizei count,
+ GLenum type, const void* indices);
+static gdraw_drawelements_fn gdraw_real_drawelements = NULL;
+static GLuint gdraw_screenibo = 0;
+
+typedef GLuint(APIENTRYP gdraw_createshader_fn)(GLenum);
+typedef void(APIENTRYP gdraw_shadersource_fn)(GLuint, GLsizei, const GLchar**,
+ const GLint*);
+typedef void(APIENTRYP gdraw_compileshader_fn)(GLuint);
+typedef void(APIENTRYP gdraw_linkprogram_fn)(GLuint);
+static gdraw_createshader_fn gdraw_real_createshader = NULL;
+static gdraw_shadersource_fn gdraw_real_shadersource = NULL;
+static gdraw_compileshader_fn gdraw_real_compileshader = NULL;
+static gdraw_linkprogram_fn gdraw_real_linkprogram = NULL;
+
+// some core reject p0
+
+typedef void(APIENTRYP gdraw_useprogram_fn)(GLuint);
+static gdraw_useprogram_fn gdraw_real_useprogram = NULL;
+static GLuint gdraw_null_program = 0;
+
+typedef void(APIENTRYP gdraw_teximage2d_fn)(GLenum, GLint, GLint, GLsizei,
+ GLsizei, GLint, GLenum, GLenum,
+ const void*);
+typedef void(APIENTRYP gdraw_texsubimage2d_fn)(GLenum, GLint, GLint, GLint,
+ GLsizei, GLsizei, GLenum, GLenum,
+ const void*);
+static gdraw_teximage2d_fn gdraw_real_teximage2d = NULL;
+static gdraw_texsubimage2d_fn gdraw_real_texsubimage2d = NULL;
+
+#define TRY(ptr, arb, core) \
+ do { \
+ void* _p = get_gl_proc(core); \
+ if (!_p) _p = get_gl_proc(arb); \
+ *(void**)&(ptr) = _p; \
+ } while (0)
+
+static void load_extensions(void) {
+// gl_shared requires ts shit ugh
+#define GLE(id, import, procname) \
+ gl##id = (PFNGL##procname##PROC)get_gl_proc("gl" import);
+ GDRAW_GL_EXTENSION_LIST
+#undef GLE
+
+ TRY(glCreateShader, "glCreateShaderObjectARB", "glCreateShader");
+ TRY(glDeleteShader, "glDeleteObjectARB", "glDeleteShader");
+ TRY(glShaderSource, "glShaderSourceARB", "glShaderSource");
+ TRY(glCompileShader, "glCompileShaderARB", "glCompileShader");
+ TRY(glGetShaderiv, "glGetObjectParameterivARB", "glGetShaderiv");
+ TRY(glGetShaderInfoLog, "glGetInfoLogARB", "glGetShaderInfoLog");
+ TRY(glCreateProgram, "glCreateProgramObjectARB", "glCreateProgram");
+ TRY(glDeleteProgram, "glDeleteObjectARB", "glDeleteProgram");
+ TRY(glAttachShader, "glAttachObjectARB", "glAttachShader");
+ TRY(glLinkProgram, "glLinkProgramARB", "glLinkProgram");
+ TRY(glGetUniformLocation, "glGetUniformLocationARB",
+ "glGetUniformLocation");
+ TRY(glUseProgram, "glUseProgramObjectARB", "glUseProgram");
+ TRY(glGetProgramiv, "glGetObjectParameterivARB", "glGetProgramiv");
+ TRY(glGetProgramInfoLog, "glGetInfoLogARB", "glGetProgramInfoLog");
+ TRY(glUniform1i, "glUniform1iARB", "glUniform1i");
+ TRY(glUniform4f, "glUniform4fARB", "glUniform4f");
+ TRY(glUniform4fv, "glUniform4fvARB", "glUniform4fv");
+ TRY(glUniform1f, "glUniform1fARB", "glUniform1f");
+ TRY(glBindAttribLocation, "glBindAttribLocationARB",
+ "glBindAttribLocation");
+
+ TRY(glGenBuffers, "glGenBuffersARB", "glGenBuffers");
+ TRY(glDeleteBuffers, "glDeleteBuffersARB", "glDeleteBuffers");
+ TRY(glBindBuffer, "glBindBufferARB", "glBindBuffer");
+ TRY(glBufferData, "glBufferDataARB", "glBufferData");
+ TRY(glMapBuffer, "glMapBufferARB", "glMapBuffer");
+ TRY(glUnmapBuffer, "glUnmapBufferARB", "glUnmapBuffer");
+ TRY(glVertexAttribPointer, "glVertexAttribPointerARB",
+ "glVertexAttribPointer");
+ TRY(glEnableVertexAttribArray, "glEnableVertexAttribArrayARB",
+ "glEnableVertexAttribArray");
+ TRY(glDisableVertexAttribArray, "glDisableVertexAttribArrayARB",
+ "glDisableVertexAttribArray");
+
+ TRY(glGenRenderbuffers, "glGenRenderbuffersEXT", "glGenRenderbuffers");
+ TRY(glDeleteRenderbuffers, "glDeleteRenderbuffersEXT",
+ "glDeleteRenderbuffers");
+ TRY(glBindRenderbuffer, "glBindRenderbufferEXT", "glBindRenderbuffer");
+ TRY(glRenderbufferStorage, "glRenderbufferStorageEXT",
+ "glRenderbufferStorage");
+ TRY(glGenFramebuffers, "glGenFramebuffersEXT", "glGenFramebuffers");
+ TRY(glDeleteFramebuffers, "glDeleteFramebuffersEXT",
+ "glDeleteFramebuffers");
+ TRY(glBindFramebuffer, "glBindFramebufferEXT", "glBindFramebuffer");
+ TRY(glCheckFramebufferStatus, "glCheckFramebufferStatusEXT",
+ "glCheckFramebufferStatus");
+ TRY(glFramebufferRenderbuffer, "glFramebufferRenderbufferEXT",
+ "glFramebufferRenderbuffer");
+ TRY(glFramebufferTexture2D, "glFramebufferTexture2DEXT",
+ "glFramebufferTexture2D");
+ TRY(glGenerateMipmap, "glGenerateMipmapEXT", "glGenerateMipmap");
+ TRY(glBlitFramebuffer, "glBlitFramebufferEXT", "glBlitFramebuffer");
+ TRY(glRenderbufferStorageMultisample, "glRenderbufferStorageMultisampleEXT",
+ "glRenderbufferStorageMultisample");
+
+ // Save raw pointers before we #define over the names below
+ gdraw_real_vtxattrib =
+ (gdraw_vtxattrib_fn)get_gl_proc("glVertexAttribPointer");
+ gdraw_real_createshader =
+ (gdraw_createshader_fn)get_gl_proc("glCreateShader");
+ gdraw_real_shadersource =
+ (gdraw_shadersource_fn)get_gl_proc("glShaderSource");
+ gdraw_real_compileshader =
+ (gdraw_compileshader_fn)get_gl_proc("glCompileShader");
+ gdraw_real_linkprogram = (gdraw_linkprogram_fn)get_gl_proc("glLinkProgram");
+ gdraw_real_teximage2d = (gdraw_teximage2d_fn)get_gl_proc("glTexImage2D");
+ gdraw_real_texsubimage2d =
+ (gdraw_texsubimage2d_fn)get_gl_proc("glTexSubImage2D");
+ gdraw_real_useprogram = (gdraw_useprogram_fn)get_gl_proc("glUseProgram");
+ gdraw_real_drawelements =
+ (gdraw_drawelements_fn)get_gl_proc("glDrawElements");
+
+ gdraw_glGetStringi = (PFNGLGETSTRINGIPROC_)get_gl_proc("glGetStringi");
+ gdraw_glGenVertexArrays =
+ (PFNGLGENVERTEXARRAYSPROC_)get_gl_proc("glGenVertexArrays");
+ gdraw_glBindVertexArray =
+ (PFNGLBINDVERTEXARRAYPROC_)get_gl_proc("glBindVertexArray");
+
+ if (gdraw_glGenVertexArrays && gdraw_glBindVertexArray && gdraw_vao == 0) {
+ gdraw_glGenVertexArrays(1, &gdraw_vao);
+ gdraw_glBindVertexArray(gdraw_vao);
+ }
+}
+
+#undef TRY
+
+// rebind vbo
+
+static void clear_renderstate_platform_specific(void) {
+ if (gdraw_glBindVertexArray && gdraw_vao)
+ gdraw_glBindVertexArray(gdraw_vao);
+}
+
+static void error_msg_platform_specific(const char* msg) {
+ fprintf(stderr, "[GDraw] %s\n", msg);
+}
+
+#define GDRAW_PLATFORM_REPORT_GL_SITE(site) \
+ do { \
+ if ((site) != NULL) \
+ fprintf(stderr, "[GDraw] GL error site: %s\n", (site)); \
+ } while (0)
+
+#define GDRAW_MULTISAMPLING
+
+// i wish i could improve this function
+#ifdef RR_BREAK
+#undef RR_BREAK
+#endif
+#define RR_BREAK() \
+ do { \
+ fprintf(stderr, "[GDraw] GL error at %s:%d\n", __FILE__, __LINE__); \
+ } while (0)
+
+// the magic number that tropical told me
+#define GDRAW_MAX_SHADERS 64
+static struct {
+ GLuint handle;
+ GLenum type;
+} gdraw_shader_types[GDRAW_MAX_SHADERS];
+static int gdraw_shader_type_count = 0;
+
+static GLenum gdraw_get_shader_type(GLuint shader) {
+ for (int i = 0; i < gdraw_shader_type_count; i++)
+ if (gdraw_shader_types[i].handle == shader)
+ return gdraw_shader_types[i].type;
+ return GL_FRAGMENT_SHADER;
+}
+
+static GLuint gdraw_CreateShaderTracked(GLenum type) {
+ GLuint h = gdraw_real_createshader(type);
+ if (h && gdraw_shader_type_count < GDRAW_MAX_SHADERS) {
+ gdraw_shader_types[gdraw_shader_type_count].handle = h;
+ gdraw_shader_types[gdraw_shader_type_count].type = type;
+ gdraw_shader_type_count++;
+ }
+ return h;
+}
+
+static void gdraw_CompileShaderAndLog(GLuint shader) {
+ GLint status = 0;
+ gdraw_real_compileshader(shader);
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
+ if (!status) {
+ char log[2048];
+ GLint len = 0;
+ glGetShaderInfoLog(shader, (GLsizei)sizeof(log) - 1, &len, log);
+ log[len] = '\0';
+ fprintf(stderr, "[GDraw GLSL] compile FAILED shader=%u:\n%s\n", shader,
+ log);
+ }
+}
+
+static void gdraw_LinkProgramAndLog(GLuint program) {
+ GLint status = 0;
+ gdraw_real_linkprogram(program);
+ glGetProgramiv(program, GL_LINK_STATUS, &status);
+ if (!status) {
+ char log[2048];
+ GLint len = 0;
+ glGetProgramInfoLog(program, (GLsizei)sizeof(log) - 1, &len, log);
+ log[len] = '\0';
+ fprintf(stderr, "[GDraw GLSL] link FAILED program=%u:\n%s\n", program,
+ log);
+ }
+}
+
+#undef glCreateShader
+#define glCreateShader gdraw_CreateShaderTracked
+
+// This is the part that turns the old ugly shaders to 330
+static char* gdraw_strreplace(char* src, const char* find, const char* rep) {
+ char* result;
+ char* pos;
+ char* base = src;
+ size_t find_len = strlen(find);
+ size_t rep_len = strlen(rep);
+ size_t count = 0;
+ char* tmp = src;
+
+ while ((tmp = strstr(tmp, find))) {
+ count++;
+ tmp += find_len;
+ }
+ if (!count) return src;
+
+ result = (char*)malloc(strlen(src) + count * (rep_len + 1) + 1);
+ if (!result) return src;
+
+ tmp = result;
+ while ((pos = strstr(src, find))) {
+ size_t before = (size_t)(pos - src);
+ memcpy(tmp, src, before);
+ tmp += before;
+ memcpy(tmp, rep, rep_len);
+ tmp += rep_len;
+ src = pos + find_len;
+ }
+ strcpy(tmp, src);
+ free(base);
+ return result;
+}
+
+static void gdraw_ShaderSourceUpgraded(GLuint shader, GLsizei count,
+ const GLchar** strings,
+ const GLint* lengths) {
+ size_t total = 0;
+ for (int i = 0; i < count; i++)
+ total += lengths ? (lengths[i] >= 0 ? (size_t)lengths[i]
+ : strlen(strings[i]))
+ : strlen(strings[i]);
+
+ char* src = (char*)malloc(total + 1);
+ if (!src) {
+ gdraw_real_shadersource(shader, count, strings, lengths);
+ return;
+ }
+
+ src[0] = '\0';
+ for (int i = 0; i < count; i++) {
+ size_t len = lengths ? (lengths[i] >= 0 ? (size_t)lengths[i]
+ : strlen(strings[i]))
+ : strlen(strings[i]);
+ strncat(src, strings[i], len);
+ }
+
+ int is_vert = (gdraw_get_shader_type(shader) == GL_VERTEX_SHADER);
+
+ // Strip any existing #version directive as i'll add our own
+ {
+ char* vp = strstr(src, "#version");
+ if (vp) {
+ char* nl = strchr(vp, '\n');
+ if (nl)
+ memmove(vp, nl + 1, strlen(nl + 1) + 1);
+ else
+ *vp = '\0';
+ }
+ }
+
+ // Texture built-ins
+ src = gdraw_strreplace(src, "texture2DRect", "texture");
+ src = gdraw_strreplace(src, "texture2D", "texture");
+
+ // Attribute -> in
+ src = gdraw_strreplace(src, "attribute ", "in ");
+ src = gdraw_strreplace(src, "attribute\t", "in\t");
+ src = gdraw_strreplace(src, "attribute\n", "in\n");
+
+ // Varying -> out (vert) / in (frag)
+ if (is_vert) {
+ src = gdraw_strreplace(src, "varying ", "out ");
+ src = gdraw_strreplace(src, "varying\t", "out\t");
+ src = gdraw_strreplace(src, "varying\n", "out\n");
+ } else {
+ src = gdraw_strreplace(src, "varying ", "in ");
+ src = gdraw_strreplace(src, "varying\t", "in\t");
+ src = gdraw_strreplace(src, "varying\n", "in\n");
+ src = gdraw_strreplace(src, "gl_FragData[0]", "_gdraw_frag_out");
+ src = gdraw_strreplace(src, "gl_FragColor", "_gdraw_frag_out");
+ }
+
+ const char* header = is_vert
+ ? "#version 330 core\n"
+ : "#version 330 core\nout vec4 _gdraw_frag_out;\n";
+ char* patched = (char*)malloc(strlen(header) + strlen(src) + 2);
+ if (!patched) {
+ free(src);
+ gdraw_real_shadersource(shader, count, strings, lengths);
+ return;
+ }
+ strcpy(patched, header);
+ strcat(patched, src);
+ free(src);
+
+ const GLchar* patched_ptr = (const GLchar*)patched;
+ gdraw_real_shadersource(shader, 1, &patched_ptr, NULL);
+ free(patched);
+}
+
+#undef glShaderSource
+#define glShaderSource gdraw_ShaderSourceUpgraded
+
+// Remap all the deprecated internal formats to their modern equivalents
+// (idk why but just the word "swizzle" is cracking me up)
+static void gdraw_apply_swizzle(GLenum internal_fmt) {
+ if (internal_fmt == 0x1906 /* GL_ALPHA */ || internal_fmt == GL_RED) {
+ GLint sw[4] = {GL_ZERO, GL_ZERO, GL_ZERO, GL_RED};
+ glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, sw);
+ } else if (internal_fmt == 0x1909 /* GL_LUMINANCE */) {
+ GLint sw[4] = {GL_RED, GL_RED, GL_RED, GL_ONE};
+ glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, sw);
+ } else if (internal_fmt == 0x190A /* GL_LUMINANCE_ALPHA */) {
+ GLint sw[4] = {GL_RED, GL_RED, GL_RED, GL_GREEN};
+ glTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_RGBA, sw);
+ }
+}
+
+static GLenum gdraw_remap_fmt(GLenum fmt) {
+ switch (fmt) {
+ case 0x1906:
+ return GL_RED; // GL_ALPHA
+ case 0x1909:
+ return GL_RED; // GL_LUMINANCE
+ case 0x190A:
+ return GL_RG; // GL_LUMINANCE_ALPHA
+ case 0x8033:
+ return GL_RG; // GL_LUMINANCE4_ALPHA4
+ case 0x8045:
+ return GL_R8; // GL_LUMINANCE8
+ case 0x8048:
+ return GL_RG8; // GL_LUMINANCE8_ALPHA8
+ case 0x804F:
+ return GL_R8; // GL_INTENSITY4
+ case 0x8050:
+ return GL_R8; // GL_INTENSITY8
+ default:
+ return fmt;
+ }
+}
+
+static void gdraw_TexImage2D(GLenum target, GLint level, GLint ifmt, GLsizei w,
+ GLsizei h, GLint border, GLenum fmt, GLenum type,
+ const void* data) {
+ // ES strictly requires explicitly sized formats & stuff
+ if (ifmt == GL_RGBA && data == NULL) ifmt = GL_RGBA8;
+
+ GLenum new_ifmt = gdraw_remap_fmt((GLenum)ifmt);
+ GLenum new_fmt = gdraw_remap_fmt(fmt);
+ gdraw_real_teximage2d(target, level, (GLint)new_ifmt, w, h, border, new_fmt,
+ type, data);
+ if (new_ifmt != (GLenum)ifmt) gdraw_apply_swizzle((GLenum)ifmt);
+}
+
+static void gdraw_TexSubImage2D(GLenum target, GLint level, GLint xoff,
+ GLint yoff, GLsizei w, GLsizei h, GLenum fmt,
+ GLenum type, const void* data) {
+ GLenum new_fmt = gdraw_remap_fmt(fmt);
+ gdraw_real_texsubimage2d(target, level, xoff, yoff, w, h, new_fmt, type,
+ data);
+}
+
+#undef glTexImage2D
+#define glTexImage2D gdraw_TexImage2D
+#undef glTexSubImage2D
+#define glTexSubImage2D gdraw_TexSubImage2D
+
+// vbo emu
+static void gdraw_ClientVertexAttribPointer(GLuint index, GLint size,
+ GLenum type, GLboolean normalized,
+ GLsizei stride,
+ const void* pointer) {
+ if (gdraw_glBindVertexArray && gdraw_vao) {
+ GLint current_vao = 0;
+ glGetIntegerv(GL_VERTEX_ARRAY_BINDING, ¤t_vao);
+ if ((GLuint)current_vao != gdraw_vao)
+ gdraw_glBindVertexArray(gdraw_vao);
+ }
+
+ GLint current_vbo = 0;
+ glGetIntegerv(GL_ARRAY_BUFFER_BINDING, ¤t_vbo);
+
+ if (current_vbo != 0 && current_vbo != (GLint)gdraw_screenvbo) {
+ // no touchies
+ gdraw_real_vtxattrib(index, size, type, normalized, stride, pointer);
+ return;
+ }
+
+ if (pointer == NULL) {
+ gdraw_real_vtxattrib(index, size, type, normalized, stride, pointer);
+ return;
+ }
+
+ ptrdiff_t offset =
+ gdraw_screenvbo_base
+ ? ((const char*)pointer - (const char*)gdraw_screenvbo_base)
+ : -1;
+
+ if (gdraw_screenvbo_base == NULL || offset < 0 ||
+ offset >= (ptrdiff_t)gdraw_expected_vbo_size) {
+ if (!gdraw_screenvbo) glGenBuffers(1, &gdraw_screenvbo);
+ glBindBuffer(GL_ARRAY_BUFFER, gdraw_screenvbo);
+
+ size_t upload_size = gdraw_expected_vbo_size > 0
+ ? (gdraw_expected_vbo_size + 256)
+ : 65536;
+ glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)upload_size, pointer,
+ GL_STREAM_DRAW);
+
+ gdraw_screenvbo_base = pointer;
+ gdraw_real_vtxattrib(index, size, type, normalized, stride,
+ (const void*)0);
+ } else {
+ glBindBuffer(GL_ARRAY_BUFFER, gdraw_screenvbo);
+ gdraw_real_vtxattrib(index, size, type, normalized, stride,
+ (const void*)offset);
+ }
+}
+
+#undef glVertexAttribPointer
+#define glVertexAttribPointer gdraw_ClientVertexAttribPointer
+
+// fake ibo
+static void hooked_glDrawElements(GLenum mode, GLsizei count, GLenum type,
+ const void* indices) {
+ GLint current_ibo = 0;
+ glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, ¤t_ibo);
+
+ if (current_ibo == 0 && indices != NULL) {
+ if (!gdraw_screenibo) glGenBuffers(1, &gdraw_screenibo);
+ glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, gdraw_screenibo);
+
+ size_t index_size = (type == GL_UNSIGNED_SHORT) ? 2
+ : (type == GL_UNSIGNED_BYTE) ? 1
+ : 4;
+ glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)(count * index_size),
+ indices, GL_STREAM_DRAW);
+
+ gdraw_real_drawelements(mode, count, type, (const void*)0);
+ } else {
+ gdraw_real_drawelements(mode, count, type, indices);
+ }
+}
+
+#define glDrawElements hooked_glDrawElements
+
+// dummy shader for glUseProgram(0) safety
+static void gdraw_UseProgramSafe(GLuint program) {
+ if (!program) {
+ if (!gdraw_null_program && gdraw_real_useprogram) {
+ const char* vs =
+ "#version 330 core\nvoid main(){gl_Position=vec4(0);}";
+ const char* fs =
+ "#version 330 core\nout vec4 c;\nvoid main(){c=vec4(0);}";
+ GLuint v = gdraw_real_createshader(GL_VERTEX_SHADER);
+ GLuint f = gdraw_real_createshader(GL_FRAGMENT_SHADER);
+ gdraw_real_shadersource(v, 1, &vs, NULL);
+ gdraw_real_shadersource(f, 1, &fs, NULL);
+ gdraw_real_compileshader(v);
+ gdraw_real_compileshader(f);
+ gdraw_null_program = glCreateProgram();
+ glAttachShader(gdraw_null_program, v);
+ glAttachShader(gdraw_null_program, f);
+ gdraw_real_linkprogram(gdraw_null_program);
+ glDeleteShader(v);
+ glDeleteShader(f);
+ }
+ gdraw_real_useprogram(gdraw_null_program);
+ return;
+ }
+ gdraw_real_useprogram(program);
+}
+
+#undef glUseProgram
+#define glUseProgram gdraw_UseProgramSafe
+#undef glCompileShader
+#define glCompileShader gdraw_CompileShaderAndLog
+#undef glLinkProgram
+#define glLinkProgram gdraw_LinkProgramAndLog
+
+static void gdraw_FramebufferRenderbufferSafe(GLenum target, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer) {
+ static GLuint last_depth_rb = 0;
+
+ if (attachment == GL_DEPTH_ATTACHMENT) {
+ last_depth_rb = renderbuffer;
+ (glFramebufferRenderbuffer)(target, attachment, renderbuffertarget,
+ renderbuffer);
+ } else if (attachment == GL_STENCIL_ATTACHMENT) {
+ if (renderbuffer == last_depth_rb && renderbuffer != 0) {
+ // If identical, bind as packed depth-stencil to satisfy strict GLES
+ // ^ how greedy -n-
+ (glFramebufferRenderbuffer)(
+ target, 0x821A /* GL_DEPTH_STENCIL_ATTACHMENT */,
+ renderbuffertarget, renderbuffer);
+ } else {
+ (glFramebufferRenderbuffer)(target, attachment, renderbuffertarget,
+ renderbuffer);
+ }
+ } else {
+ (glFramebufferRenderbuffer)(target, attachment, renderbuffertarget,
+ renderbuffer);
+ }
+}
+#define glFramebufferRenderbuffer_SAFE gdraw_FramebufferRenderbufferSafe
+#define glFramebufferRenderbuffer glFramebufferRenderbuffer_SAFE
+
+#include "../../../Windows64/Iggy/gdraw/gdraw_gl_shared.inl"
+#undef glVertexAttribPointer
+#define glVertexAttribPointer gdraw_real_vtxattrib
+
+static int hasext_core(const char* name) {
+ GLint n = 0;
+ if (!gdraw_glGetStringi) return 0;
+ glGetIntegerv(GL_NUM_EXTENSIONS, &n);
+ for (GLint i = 0; i < n; i++) {
+ const char* e =
+ (const char*)gdraw_glGetStringi(GL_EXTENSIONS, (GLuint)i);
+ if (e && strcmp(e, name) == 0) return 1;
+ }
+ return 0;
+}
+
+static gdraw_draw_indexed_triangles* real_DrawIndexedTriangles = NULL;
+
+static void RADLINK hooked_DrawIndexedTriangles(GDrawRenderState* r,
+ GDrawPrimitive* prim,
+ GDrawVertexBuffer* buf,
+ GDrawStats* stats) {
+ if (buf == NULL && prim != NULL && prim->vertices != NULL) {
+ size_t stride = 8;
+ if (prim->vertex_format == GDRAW_vformat_v2aa)
+ stride = 16;
+ else if (prim->vertex_format == GDRAW_vformat_v2tc2)
+ stride = 16;
+ else if (prim->vertex_format == GDRAW_vformat_ihud1)
+ stride = 20;
+ gdraw_expected_vbo_size = prim->num_vertices * stride;
+ } else {
+ gdraw_expected_vbo_size = 0;
+ }
+ gdraw_screenvbo_base = NULL; // Force VBO re-upload for each primitive
+ real_DrawIndexedTriangles(r, prim, buf, stats);
+}
+
+static gdraw_filter_quad* real_FilterQuad = NULL;
+
+static void RADLINK hooked_FilterQuad(GDrawRenderState* r, S32 x0, S32 y0,
+ S32 x1, S32 y1, GDrawStats* stats) {
+ gdraw_expected_vbo_size = 4 * 20; // 4 vertices, max stride
+ gdraw_screenvbo_base = NULL;
+ real_FilterQuad(r, x0, y0, x1, y1, stats);
+}
+
+static gdraw_rendering_begin* real_RenderingBegin = NULL;
+
+// stupid hack
+static void RADLINK hooked_RenderingBegin(void) {
+ if (real_RenderingBegin) real_RenderingBegin();
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_CULL_FACE);
+ OPENGL_CHECK_SITE("hooked_RenderingBegin:post_state");
+}
+
+// Creating the context
+GDrawFunctions* gdraw_GL_CreateContext(S32 w, S32 h, S32 msaa_samples) {
+ static const TextureFormatDesc tex_formats[] = {
+ {IFT_FORMAT_rgba_8888, 1, 1, 4, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE},
+ {IFT_FORMAT_rgba_4444_LE, 1, 1, 2, GL_RGBA4, GL_RGBA,
+ GL_UNSIGNED_SHORT_4_4_4_4},
+ {IFT_FORMAT_rgba_5551_LE, 1, 1, 2, GL_RGB5_A1, GL_RGBA,
+ GL_UNSIGNED_SHORT_5_5_5_1},
+ {IFT_FORMAT_la_88, 1, 1, 2, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA,
+ GL_UNSIGNED_BYTE},
+ {IFT_FORMAT_la_44, 1, 1, 1, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA,
+ GL_UNSIGNED_BYTE},
+ {IFT_FORMAT_i_8, 1, 1, 1, GL_INTENSITY8, GL_ALPHA, GL_UNSIGNED_BYTE},
+ {IFT_FORMAT_i_4, 1, 1, 1, GL_INTENSITY4, GL_ALPHA, GL_UNSIGNED_BYTE},
+ {IFT_FORMAT_l_8, 1, 1, 1, GL_LUMINANCE8, GL_LUMINANCE,
+ GL_UNSIGNED_BYTE},
+ {IFT_FORMAT_l_4, 1, 1, 1, GL_LUMINANCE4, GL_LUMINANCE,
+ GL_UNSIGNED_BYTE},
+ {IFT_FORMAT_DXT1, 4, 4, 8, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0,
+ GL_UNSIGNED_BYTE},
+ {IFT_FORMAT_DXT3, 4, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0,
+ GL_UNSIGNED_BYTE},
+ {IFT_FORMAT_DXT5, 4, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0,
+ GL_UNSIGNED_BYTE},
+ {0, 0, 0, 0, 0, 0, 0},
+ };
+
+ GLint major = 0, minor = 0;
+ glGetIntegerv(GL_MAJOR_VERSION, &major);
+ glGetIntegerv(GL_MINOR_VERSION, &minor);
+ if (major < 3) {
+ fprintf(stderr, "[GDraw] GL 3.0 or higher required (got %d.%d)\n",
+ major, minor);
+ return NULL;
+ }
+
+ load_extensions();
+
+ if (gdraw_glBindVertexArray && gdraw_vao)
+ gdraw_glBindVertexArray(gdraw_vao);
+
+ GDrawFunctions* funcs = create_context(w, h);
+ if (!funcs) return NULL;
+
+ // hook the vtable entries for VBO reset and render state
+ real_DrawIndexedTriangles = funcs->DrawIndexedTriangles;
+ funcs->DrawIndexedTriangles = hooked_DrawIndexedTriangles;
+
+ real_FilterQuad = funcs->FilterQuad;
+ funcs->FilterQuad = hooked_FilterQuad;
+
+ real_RenderingBegin = funcs->RenderingBegin;
+ funcs->RenderingBegin = hooked_RenderingBegin;
+ funcs->ClearID = gdraw_ClearID;
+
+ gdraw->tex_formats = tex_formats;
+ gdraw->has_mapbuffer = false;
+ gdraw->has_depth24 = true;
+ gdraw->has_texture_max_level = true;
+
+ gdraw->has_packed_depth_stencil = true;
+
+ GLint n = 0;
+ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &n);
+ gdraw->has_conditional_non_power_of_two = (n < 8192);
+
+ if (msaa_samples > 1) {
+ glGetIntegerv(GL_MAX_SAMPLES, &n);
+ gdraw->multisampling = RR_MIN(msaa_samples, n);
+ }
+
+ opengl_check();
+ fprintf(stderr, "[GDraw] Context created successfully (%dx%d, msaa=%d)\n",
+ w, h, msaa_samples);
+ return funcs;
+}
+
+// Custom draw callbacks
+void gdraw_GL_BeginCustomDraw_4J(IggyCustomDrawCallbackRegion* region,
+ F32* matrix) {
+ // rebind vbo
+ if (gdraw_glBindVertexArray && gdraw_vao)
+ gdraw_glBindVertexArray(gdraw_vao);
+ clear_renderstate();
+ gdraw_GetObjectSpaceMatrix(matrix, region->o2w, gdraw->projection,
+ depth_from_id(0), 0);
+}
+
+void gdraw_GL_CalculateCustomDraw_4J(IggyCustomDrawCallbackRegion* region,
+ F32* matrix) {
+ gdraw_GetObjectSpaceMatrix(matrix, region->o2w, gdraw->projection, 0.0f, 0);
+}
diff --git a/Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw_sdl.h b/Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw.h
similarity index 94%
rename from Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw_sdl.h
rename to Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw.h
index 063660297..326d5c5a5 100644
--- a/Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw_sdl.h
+++ b/Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw.h
@@ -1,7 +1,9 @@
-#ifndef __RAD_INCLUDE_GDRAW_SDL_H__
-#define __RAD_INCLUDE_GDRAW_SDL_H__
+#ifndef __LINUX_IGGY_GDRAW_H__
+#define __LINUX_IGGY_GDRAW_H__
+
#include "../../../Windows64/Iggy/include/gdraw.h"
#include "../../../Windows64/Iggy/include/iggy.h"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -34,4 +36,5 @@ extern void gdraw_GL_DestroyTextureFromResource(GDrawTexture *tex);
#ifdef __cplusplus
}
#endif
-#endif // __RAD_INCLUDE_GDRAW_SDL_H__
\ No newline at end of file
+
+#endif // __LINUX_IGGY_GDRAW_H__
\ No newline at end of file
diff --git a/Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw_sdl.c b/Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw_sdl.c
deleted file mode 100644
index 7e3506367..000000000
--- a/Minecraft.Client/Platform/Linux/Iggy/gdraw/gdraw_sdl.c
+++ /dev/null
@@ -1,240 +0,0 @@
-// Rewrite of gdraw_GLFW to gdraw_SDL
-// I hope iggy gets fully implemented rrlllly quickly <3
-#define GDRAW_ASSERTS
-
-#include "../../../Windows64/Iggy/include/iggy.h"
-#include "../../../Windows64/Iggy/include/gdraw.h"
-#include "gdraw_sdl.h"
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#define true 1
-#define false 0
-
-// Say hi to sdl
-
-#ifndef _ENABLEIGGY
-void *IggyGDrawMallocAnnotated(SINTa size, const char *file, int line)
-{
- (void)file; (void)line;
- return malloc((size_t)size);
-}
-
-void IggyGDrawFree(void *ptr)
-{
- free(ptr);
-}
-
-void IggyGDrawSendWarning(Iggy *f, char const *message, ...)
-{
- (void)f;
- va_list args;
- va_start(args, message);
- fprintf(stderr, "[Iggy GDraw Warning] ");
- vfprintf(stderr, message, args);
- fprintf(stderr, "\n");
- va_end(args);
-}
-
-void IggyDiscardVertexBufferCallback(void *owner, void *buf)
-{
- (void)owner; (void)buf;
-}
-#endif
-
-// glActiveTexture and glCompressedTexImage2D are core GL 1.3+ on Linux and
-// are declared directly in , so they are omitted from this list.
-#define GDRAW_GL_EXTENSION_LIST \
-/* identifier import procname */ \
-/* GL_ARB_vertex_buffer_object */ \
-GLE(GenBuffers, "GenBuffersARB", GENBUFFERSARB) \
-GLE(DeleteBuffers, "DeleteBuffersARB", DELETEBUFFERSARB) \
-GLE(BindBuffer, "BindBufferARB", BINDBUFFERARB) \
-GLE(BufferData, "BufferDataARB", BUFFERDATAARB) \
-GLE(MapBuffer, "MapBufferARB", MAPBUFFERARB) \
-GLE(UnmapBuffer, "UnmapBufferARB", UNMAPBUFFERARB) \
-GLE(VertexAttribPointer, "VertexAttribPointerARB", VERTEXATTRIBPOINTERARB) \
-GLE(EnableVertexAttribArray, "EnableVertexAttribArrayARB", ENABLEVERTEXATTRIBARRAYARB) \
-GLE(DisableVertexAttribArray, "DisableVertexAttribArrayARB", DISABLEVERTEXATTRIBARRAYARB) \
-/* GL_ARB_shader_objects */ \
-GLE(CreateShader, "CreateShaderObjectARB", CREATESHADEROBJECTARB) \
-GLE(DeleteShader, "DeleteObjectARB", DELETEOBJECTARB) \
-GLE(ShaderSource, "ShaderSourceARB", SHADERSOURCEARB) \
-GLE(CompileShader, "CompileShaderARB", COMPILESHADERARB) \
-GLE(GetShaderiv, "GetObjectParameterivARB", GETOBJECTPARAMETERIVARB) \
-GLE(GetShaderInfoLog, "GetInfoLogARB", GETINFOLOGARB) \
-GLE(CreateProgram, "CreateProgramObjectARB", CREATEPROGRAMOBJECTARB) \
-GLE(DeleteProgram, "DeleteObjectARB", DELETEOBJECTARB) \
-GLE(AttachShader, "AttachObjectARB", ATTACHOBJECTARB) \
-GLE(LinkProgram, "LinkProgramARB", LINKPROGRAMARB) \
-GLE(GetUniformLocation, "GetUniformLocationARB", GETUNIFORMLOCATIONARB) \
-GLE(UseProgram, "UseProgramObjectARB", USEPROGRAMOBJECTARB) \
-GLE(GetProgramiv, "GetObjectParameterivARB", GETOBJECTPARAMETERIVARB) \
-GLE(GetProgramInfoLog, "GetInfoLogARB", GETINFOLOGARB) \
-GLE(Uniform1i, "Uniform1iARB", UNIFORM1IARB) \
-GLE(Uniform4f, "Uniform4fARB", UNIFORM4FARB) \
-GLE(Uniform4fv, "Uniform4fvARB", UNIFORM4FVARB) \
-/* GL_ARB_vertex_shader */ \
-GLE(BindAttribLocation, "BindAttribLocationARB", BINDATTRIBLOCATIONARB) \
-/* Missing from WGL but needed by shared code */ \
-GLE(Uniform1f, "Uniform1fARB", UNIFORM1FARB) \
-/* GL_EXT_framebuffer_object */ \
-GLE(GenRenderbuffers, "GenRenderbuffersEXT", GENRENDERBUFFERSEXT) \
-GLE(DeleteRenderbuffers, "DeleteRenderbuffersEXT", DELETERENDERBUFFERSEXT) \
-GLE(BindRenderbuffer, "BindRenderbufferEXT", BINDRENDERBUFFEREXT) \
-GLE(RenderbufferStorage, "RenderbufferStorageEXT", RENDERBUFFERSTORAGEEXT) \
-GLE(GenFramebuffers, "GenFramebuffersEXT", GENFRAMEBUFFERSEXT) \
-GLE(DeleteFramebuffers, "DeleteFramebuffersEXT", DELETEFRAMEBUFFERSEXT) \
-GLE(BindFramebuffer, "BindFramebufferEXT", BINDFRAMEBUFFEREXT) \
-GLE(CheckFramebufferStatus, "CheckFramebufferStatusEXT", CHECKFRAMEBUFFERSTATUSEXT) \
-GLE(FramebufferRenderbuffer, "FramebufferRenderbufferEXT", FRAMEBUFFERRENDERBUFFEREXT) \
-GLE(FramebufferTexture2D, "FramebufferTexture2DEXT", FRAMEBUFFERTEXTURE2DEXT) \
-GLE(GenerateMipmap, "GenerateMipmapEXT", GENERATEMIPMAPEXT) \
-/* GL_EXT_framebuffer_blit */ \
-GLE(BlitFramebuffer, "BlitFramebufferEXT", BLITFRAMEBUFFEREXT) \
-/* GL_EXT_framebuffer_multisample */ \
-GLE(RenderbufferStorageMultisample, "RenderbufferStorageMultisampleEXT",RENDERBUFFERSTORAGEMULTISAMPLEEXT) \
-/* */
-
-#define gdraw_GLx_(id) gdraw_GL_##id
-#define GDRAW_GLx_(id) GDRAW_GL_##id
-#define GDRAW_SHADERS "gdraw_gl_shaders.inl"
-
-// On Linux, GLhandleARB is void* but shader functions use GLuint values.
-// Use GLuint as our handle type, matching the Mac pattern from gdraw_gl_shared.inl.
-#define GDrawGLProgram GLuint
-typedef GLuint GLhandle;
-typedef gdraw_gl_resourcetype gdraw_resourcetype;
-
-// Declare extension function pointers
-#define GLE(id, import, procname) static PFNGL##procname##PROC gl##id;
-GDRAW_GL_EXTENSION_LIST
-#undef GLE
-
-static void load_extensions(void)
-{
- #define GLE(id, import, procname) \
- gl##id = (PFNGL##procname##PROC) SDL_GL_GetProcAddress("gl" import);
- GDRAW_GL_EXTENSION_LIST
- #undef GLE
-}
-
-static void clear_renderstate_platform_specific(void)
-{
- glDisable(GL_ALPHA_TEST);
-}
-
-static void error_msg_platform_specific(const char *msg)
-{
- fprintf(stderr, "[GDraw SDL] %s\n", msg);
-}
-
-#define GDRAW_MULTISAMPLING
-
-// Suppress SIGTRAP from GL debug assertions on Linux
-#ifdef RR_BREAK
-#undef RR_BREAK
-#endif
-#define RR_BREAK() \
- do { fprintf(stderr, "[GDraw] RR_BREAK suppressed (GL error)\n"); } while(0)
-
-#include "../../../Windows64/Iggy/gdraw/gdraw_gl_shared.inl"
-
-// Context creation and management
-
-GDrawFunctions *gdraw_GL_CreateContext(S32 w, S32 h, S32 msaa_samples)
-{
- static const TextureFormatDesc tex_formats[] = {
- { IFT_FORMAT_rgba_8888, 1, 1, 4, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE },
- { IFT_FORMAT_rgba_4444_LE, 1, 1, 2, GL_RGBA4, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4 },
- { IFT_FORMAT_rgba_5551_LE, 1, 1, 2, GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1 },
- { IFT_FORMAT_la_88, 1, 1, 2, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
- { IFT_FORMAT_la_44, 1, 1, 1, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE },
- { IFT_FORMAT_i_8, 1, 1, 1, GL_INTENSITY8, GL_ALPHA, GL_UNSIGNED_BYTE },
- { IFT_FORMAT_i_4, 1, 1, 1, GL_INTENSITY4, GL_ALPHA, GL_UNSIGNED_BYTE },
- { IFT_FORMAT_l_8, 1, 1, 1, GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE },
- { IFT_FORMAT_l_4, 1, 1, 1, GL_LUMINANCE4, GL_LUMINANCE, GL_UNSIGNED_BYTE },
- { IFT_FORMAT_DXT1, 4, 4, 8, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0, GL_UNSIGNED_BYTE },
- { IFT_FORMAT_DXT3, 4, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 0, GL_UNSIGNED_BYTE },
- { IFT_FORMAT_DXT5, 4, 4, 16, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0, GL_UNSIGNED_BYTE },
- { 0, 0, 0, 0, 0, 0, 0 },
- };
-
- GDrawFunctions *funcs;
- const char *s;
- GLint n;
-
- // A current SDL2 GL context must be active before calling this, if it doesn't exist, just throw an warning-
- s = (const char *) glGetString(GL_EXTENSIONS);
- if (!s) {
- fprintf(stderr, "[GDraw SDL] glGetString(GL_EXTENSIONS) returned NULL - "
- "SDL GL context not current?\n");
- assert(s != NULL);
- return NULL;
- }
-
- // Verify required extensions
- if (!hasext(s, "GL_ARB_multitexture") ||
- !hasext(s, "GL_ARB_texture_compression") ||
- !hasext(s, "GL_ARB_texture_mirrored_repeat") ||
- !hasext(s, "GL_ARB_texture_non_power_of_two") ||
- !hasext(s, "GL_ARB_vertex_buffer_object") ||
- !hasext(s, "GL_EXT_framebuffer_object") ||
- !hasext(s, "GL_ARB_shader_objects") ||
- !hasext(s, "GL_ARB_vertex_shader") ||
- !hasext(s, "GL_ARB_fragment_shader"))
- {
- fprintf(stderr, "[GDraw SDL] Required GL extensions not available\n");
- return NULL;
- }
-
- if (!hasext(s, "GL_EXT_framebuffer_multisample") && msaa_samples > 1)
- return NULL;
-
- load_extensions();
- funcs = create_context(w, h);
- if (!funcs)
- return NULL;
-
- gdraw->tex_formats = tex_formats;
-
- gdraw->has_mapbuffer = true; // core in ARB_vertex_buffer_object
- gdraw->has_depth24 = true;
- gdraw->has_texture_max_level = true; // core GL
-
- if (hasext(s, "GL_EXT_packed_depth_stencil"))
- gdraw->has_packed_depth_stencil = true;
-
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &n);
- gdraw->has_conditional_non_power_of_two = (n < 8192);
-
- if (msaa_samples > 1) {
- glGetIntegerv(GL_MAX_SAMPLES, &n);
- gdraw->multisampling = RR_MIN(msaa_samples, n);
- }
-
- opengl_check();
-
- fprintf(stderr, "[GDraw SDL] Context created successfully (%dx%d, msaa=%d)\n",
- w, h, msaa_samples);
- return funcs;
-}
-
-void gdraw_GL_BeginCustomDraw_4J(IggyCustomDrawCallbackRegion *region, F32 *matrix)
-{
- clear_renderstate();
- gdraw_GetObjectSpaceMatrix(matrix, region->o2w, gdraw->projection, depth_from_id(0), 0);
-}
-
-void gdraw_GL_CalculateCustomDraw_4J(IggyCustomDrawCallbackRegion *region, F32 *matrix)
-{
- gdraw_GetObjectSpaceMatrix(matrix, region->o2w, gdraw->projection, 0.0f, 0);
-}
diff --git a/Minecraft.Client/Platform/Linux/LinuxGL.cpp b/Minecraft.Client/Platform/Linux/LinuxGL.cpp
index 351bb5d24..c7fff72d5 100644
--- a/Minecraft.Client/Platform/Linux/LinuxGL.cpp
+++ b/Minecraft.Client/Platform/Linux/LinuxGL.cpp
@@ -1,135 +1,113 @@
#ifdef __linux__
#include "../stdafx.h"
-
-#include
-#include
-#include
-#include
+#include "4J_Render.h"
#include "../../Minecraft.World/IO/Streams/IntBuffer.h"
#include "../../Minecraft.World/IO/Streams/FloatBuffer.h"
#include "../../Minecraft.World/IO/Streams/ByteBuffer.h"
-void LinuxGLLogLightmapState(const char* stage, int textureId, bool scaleLight) {
- static int logCount = 0;
- if (logCount >= 16) return;
+extern C4JRender RenderManager;
- ++logCount;
+#ifdef GLES
+extern "C" {
+extern void glClearDepthf(float depth);
+void glClearDepth(double depth) { glClearDepthf((float)depth); }
+void glTexGeni(unsigned int, unsigned int, int) {}
+void glTexGenfv(unsigned int, unsigned int, const float*) {}
+void glTexCoordPointer(int, unsigned int, int, const void*) {}
+void glNormalPointer(unsigned int, int, const void*) {}
+void glColorPointer(int, unsigned int, int, const void*) {}
+void glVertexPointer(int, unsigned int, int, const void*) {}
+void glEndList(void) {}
+void glCallLists(int, unsigned int, const void*) {}
+}
+#endif
- static bool loggedSymbols = false;
- if (!loggedSymbols) {
- loggedSymbols = true;
- app.DebugPrintf(
- "[linux-lightmap] linuxgl symbols glActiveTexture=%p "
- "glClientActiveTexture=%p glMultiTexCoord2f=%p\n",
- reinterpret_cast(::glActiveTexture),
- reinterpret_cast(::glClientActiveTexture),
- reinterpret_cast(::glMultiTexCoord2f));
+inline int* getIntPtr(IntBuffer* buf) {
+ return buf ? (int*)buf->getBuffer() + buf->position() : nullptr;
+}
+inline void* getBytePtr(ByteBuffer* buf) {
+ return buf ? (char*)buf->getBuffer() + buf->position() : nullptr;
+}
+
+void glGenTextures_4J(IntBuffer* buf) {
+ if (!buf) return;
+ int n = buf->limit() - buf->position();
+ int* dst = getIntPtr(buf);
+ for (int i = 0; i < n; i++) dst[i] = RenderManager.TextureCreate();
+}
+
+void glDeleteTextures_4J(IntBuffer* buf) {
+ if (!buf) return;
+ int n = buf->limit() - buf->position();
+ int* src = getIntPtr(buf);
+ for (int i = 0; i < n; i++) RenderManager.TextureFree(src[i]);
+}
+
+void glTexImage2D_4J(int target, int level, int internalformat, int width,
+ int height, int border, int format, int type,
+ ByteBuffer* pixels) {
+ (void)target;
+ (void)internalformat;
+ (void)border;
+ (void)format;
+ (void)type;
+ RenderManager.TextureData(width, height, getBytePtr(pixels), level,
+ C4JRender::TEXTURE_FORMAT_RxGyBzAw);
+}
+
+void glLight_4J(int light, int pname, FloatBuffer* params) {
+ const float* p = params->_getDataPointer();
+ int idx = (light == 0x4001) ? 1 : 0;
+ if (pname == 0x1203)
+ RenderManager.StateSetLightDirection(idx, p[0], p[1], p[2]);
+ else if (pname == 0x1201)
+ RenderManager.StateSetLightColour(idx, p[0], p[1], p[2]);
+ else if (pname == 0x1200)
+ RenderManager.StateSetLightAmbientColour(p[0], p[1], p[2]);
+}
+
+void glLightModel_4J(int pname, FloatBuffer* params) {
+ if (pname == 0x0B53) {
+ const float* p = params->_getDataPointer();
+ RenderManager.StateSetLightAmbientColour(p[0], p[1], p[2]);
}
-
- GLint activeTexture = 0;
- GLint matrixMode = 0;
- ::glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture);
- ::glGetIntegerv(GL_MATRIX_MODE, &matrixMode);
-
- const GLint restoreTexture = activeTexture;
- ::glActiveTexture(GL_TEXTURE1);
-
- GLint unit1Binding = 0;
- ::glGetIntegerv(GL_TEXTURE_BINDING_2D, &unit1Binding);
- const bool unit1Enabled = (::glIsEnabled(GL_TEXTURE_2D) == GL_TRUE);
-
- GLfloat textureMatrix[16];
- ::glGetFloatv(GL_TEXTURE_MATRIX, textureMatrix);
-
- ::glActiveTexture(restoreTexture);
-
- app.DebugPrintf(
- "[linux-lightmap] %s tex=%d scale=%d active=%#x matrixMode=%#x "
- "unit1Bound=%d unit1Enabled=%d texMatrix=[%.4f %.4f %.4f %.4f]\n",
- stage, textureId, scaleLight ? 1 : 0, activeTexture, matrixMode,
- unit1Binding, unit1Enabled ? 1 : 0, textureMatrix[0], textureMatrix[5],
- textureMatrix[12], textureMatrix[13]);
}
-int glGenTextures() {
- GLuint id = 0;
- ::glGenTextures(1, &id);
- return (int)id;
+void glFog_4J(int pname, FloatBuffer* params) {
+ const float* p = params->_getDataPointer();
+ if (pname == 0x0B66) RenderManager.StateSetFogColour(p[0], p[1], p[2]);
}
-void glGenTextures(IntBuffer* buf) {
- GLuint id = 0;
- ::glGenTextures(1, &id);
- buf->put((int)id);
- buf->flip();
+void glGetFloat_4J(int pname, FloatBuffer* params) {
+ const float* m = RenderManager.MatrixGet(pname);
+ if (m) memcpy(params->_getDataPointer(), m, 16 * sizeof(float));
}
-void glDeleteTextures(int id) {
- GLuint uid = (GLuint)id;
- ::glDeleteTextures(1, &uid);
-}
-
-void glDeleteTextures(IntBuffer* buf) {
- int id = buf->get(0);
- GLuint uid = (GLuint)id;
- ::glDeleteTextures(1, &uid);
-}
-
-void glLight(int light, int pname, FloatBuffer* params) {
- ::glLightfv((GLenum)light, (GLenum)pname, params->_getDataPointer());
-}
-
-void glLightModel(int pname, FloatBuffer* params) {
- ::glLightModelfv((GLenum)pname, params->_getDataPointer());
-}
-
-void glGetFloat(int pname, FloatBuffer* params) {
- ::glGetFloatv((GLenum)pname, params->_getDataPointer());
-}
-
-void glTexGen(int coord, int pname, FloatBuffer* params) {
- ::glTexGenfv((GLenum)coord, (GLenum)pname, params->_getDataPointer());
-}
-
-void glFog(int pname, FloatBuffer* params) {
- ::glFogfv((GLenum)pname, params->_getDataPointer());
-}
-
-void glTexCoordPointer(int size, int type, FloatBuffer* pointer) {
- ::glTexCoordPointer(size, (GLenum)type, 0, pointer->_getDataPointer());
-}
-
-void glNormalPointer(int type, ByteBuffer* pointer) {
- ::glNormalPointer((GLenum)type, 0, pointer->getBuffer());
-}
-
-void glColorPointer(int size, bool normalized, int stride,
- ByteBuffer* pointer) {
- (void)normalized;
- ::glColorPointer(size, GL_UNSIGNED_BYTE, stride, pointer->getBuffer());
-}
-
-void glVertexPointer(int size, int type, FloatBuffer* pointer) {
- ::glVertexPointer(size, (GLenum)type, 0, pointer->_getDataPointer());
-}
-
-void glEndList(int) { ::glEndList(); }
-
-void glTexImage2D(int target, int level, int internalformat, int width,
- int height, int border, int format, int type,
- ByteBuffer* pixels) {
- void* data = pixels ? pixels->getBuffer() : nullptr;
- ::glTexImage2D((GLenum)target, level, internalformat, width, height, border,
- (GLenum)format, (GLenum)type, data);
-}
-
-void glCallLists(IntBuffer* lists) {
+void glCallLists_4J(IntBuffer* lists) {
+ if (!lists) return;
int count = lists->limit() - lists->position();
- ::glCallLists(count, GL_INT, lists->getBuffer());
+ int* ids = getIntPtr(lists);
+ for (int i = 0; i < count; i++) RenderManager.CBuffCall(ids[i], false);
}
+void glReadPixels_4J(int x, int y, int w, int h, int f, int t, ByteBuffer* p) {
+ (void)f;
+ (void)t;
+ RenderManager.ReadPixels(x, y, w, h, getBytePtr(p));
+}
+
+// dead stubs
+void glTexCoordPointer_4J(int, int, FloatBuffer*) {}
+void glNormalPointer_4J(int, ByteBuffer*) {}
+void glColorPointer_4J(int, bool, int, ByteBuffer*) {}
+void glVertexPointer_4J(int, int, FloatBuffer*) {}
+void glEndList_4J(int) {}
+void glTexGen_4J(int, int, FloatBuffer*) {}
+
+// query objects
+#include
static PFNGLGENQUERIESARBPROC _glGenQueriesARB = nullptr;
static PFNGLBEGINQUERYARBPROC _glBeginQueryARB = nullptr;
static PFNGLENDQUERYARBPROC _glEndQueryARB = nullptr;
@@ -148,40 +126,41 @@ static void initQueryFuncs() {
RTLD_DEFAULT, "glGetQueryObjectuivARB");
}
-void glGenQueriesARB(IntBuffer* buf) {
+void glGenQueriesARB_4J(IntBuffer* buf) {
initQueryFuncs();
- if (_glGenQueriesARB) {
- GLuint id = 0;
- _glGenQueriesARB(1, &id);
- buf->put((int)id);
- buf->flip();
+ if (_glGenQueriesARB && buf) {
+ int n = buf->limit() - buf->position();
+ if (n > 0) _glGenQueriesARB(n, (GLuint*)getIntPtr(buf));
}
}
-void glBeginQueryARB(int target, int id) {
+void glBeginQueryARB_4J(int target, int id) {
initQueryFuncs();
if (_glBeginQueryARB) _glBeginQueryARB((GLenum)target, (GLuint)id);
}
-void glEndQueryARB(int target) {
+void glEndQueryARB_4J(int target) {
initQueryFuncs();
if (_glEndQueryARB) _glEndQueryARB((GLenum)target);
}
-void glGetQueryObjectuARB(int id, int pname, IntBuffer* params) {
+void glGetQueryObjectuARB_4J(int id, int pname, IntBuffer* params) {
initQueryFuncs();
- if (_glGetQueryObjectuivARB) {
- GLuint val = 0;
- _glGetQueryObjectuivARB((GLuint)id, (GLenum)pname, &val);
- params->put((int)val);
- params->flip();
- }
+ if (_glGetQueryObjectuivARB && params)
+ // LWJGL does not change limits/positions during these calls, it
+ // reads/writes exactly at pointer!!
+ _glGetQueryObjectuivARB((GLuint)id, (GLenum)pname,
+ (GLuint*)getIntPtr(params));
}
-
-void glReadPixels(int x, int y, int width, int height, int format, int type,
- ByteBuffer* pixels) {
- ::glReadPixels(x, y, width, height, (GLenum)format, (GLenum)type,
- pixels->getBuffer());
+void glGetFloat(int pname, FloatBuffer* params) {
+ glGetFloat_4J(pname, params);
}
-
-#endif
+void LinuxGLLogLightmapState(const char* stage, int textureId,
+ bool scaleLight) {
+ static int logCount = 0;
+ if (logCount >= 16) return;
+ ++logCount;
+ fprintf(stderr, "[linux-lightmap] %s tex=%d scale=%d\n", stage, textureId,
+ scaleLight ? 1 : 0);
+}
+#endif
\ No newline at end of file
diff --git a/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp b/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp
index a99f4d637..ca55472dd 100644
--- a/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp
+++ b/Minecraft.Client/Platform/Linux/Linux_Minecraft.cpp
@@ -5,7 +5,6 @@
#include
// #include
-#include
#if defined(__linux__) && defined(__GLIBC__)
#include
#include
@@ -659,16 +658,6 @@ void CleanupDevice() {
}
#endif
-int StartMinecraftThreadProc(void* lpParameter) {
- Vec3::UseDefaultThreadStorage();
- AABB::UseDefaultThreadStorage();
- Tesselator::CreateNewThreadStorage(1024 * 1024);
- RenderManager.InitialiseContext();
- Minecraft::start(std::wstring(), std::wstring());
- delete Tesselator::getInstance();
- return 0;
-}
-
int main(int argc, const char* argv[]) {
#if defined(__linux__) && defined(__GLIBC__)
struct sigaction sa;
@@ -774,8 +763,6 @@ int main(int argc, const char* argv[]) {
// Initialise TLS for tesselator, for this main thread
Tesselator::CreateNewThreadStorage(1024 * 1024);
// Initialise TLS for AABB and Vec3 pools, for this main thread
- AABB::CreateNewThreadStorage();
- Vec3::CreateNewThreadStorage();
Compression::CreateNewThreadStorage();
OldChunkStorage::CreateNewThreadStorage();
Level::enableLightingCache();
@@ -954,9 +941,6 @@ int main(int argc, const char* argv[]) {
}
// Fix for #7318 - Title crashes after short soak in the leaderboards
- // menu A memory leak was caused because the icon renderer kept creating
- // new Vec3's because the pool wasn't reset
- Vec3::resetPool();
} // end game loop
// Graceful shutdown: destroy GL context and GLFW before any C++ dtors run.
@@ -1053,7 +1037,7 @@ void FreeRichPresenceStrings() {
vRichPresenceStrings.clear();
}
-#if defined(MEMORY_TRACKING)
+#if 0 // #ifdef MEMORY_TRACKING
int totalAllocGen = 0;
std::unordered_map allocCounts;
diff --git a/Minecraft.Client/Platform/Linux/Linux_UIController.cpp b/Minecraft.Client/Platform/Linux/Linux_UIController.cpp
index 4a39e85ef..855c10b9d 100644
--- a/Minecraft.Client/Platform/Linux/Linux_UIController.cpp
+++ b/Minecraft.Client/Platform/Linux/Linux_UIController.cpp
@@ -1,12 +1,8 @@
#include "../../../Minecraft.World/Platform/stdafx.h"
#include "Linux_UIController.h"
-// Temp
-#include "../../Minecraft.h"
-#include "../../Textures/Textures.h"
-
// GDraw GL backend for Linux
-#include "Iggy/gdraw/gdraw_sdl.h"
+#include "Iggy/gdraw/gdraw.h"
ConsoleUIController ui;
@@ -22,14 +18,12 @@ static void restoreFixedFunctionStateAfterIggy() {
glClientActiveTexture(GL_TEXTURE1);
glActiveTexture(GL_TEXTURE1);
glDisable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
glClientActiveTexture(GL_TEXTURE0);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
- glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glMatrixMode(GL_TEXTURE);
glLoadIdentity();
@@ -54,7 +48,7 @@ void ConsoleUIController::init(S32 w, S32 h) {
gdraw_GL_SetResourceLimits(GDRAW_GL_RESOURCE_texture, 5000,
128 * 1024 * 1024);
gdraw_GL_SetResourceLimits(GDRAW_GL_RESOURCE_rendertarget, 10,
- 32 * 1024 * 1024);
+ 64 * 1024 * 1024);
IggySetGDraw(gdraw_funcs);
#endif
diff --git a/Minecraft.Client/Platform/Linux/Stubs/iggy_stubs.h b/Minecraft.Client/Platform/Linux/Stubs/iggy_stubs.h
index 701ad994f..ca0c47ff1 100644
--- a/Minecraft.Client/Platform/Linux/Stubs/iggy_stubs.h
+++ b/Minecraft.Client/Platform/Linux/Stubs/iggy_stubs.h
@@ -254,6 +254,14 @@ RADEXPFUNC inline void* RADEXPLINK IggyPerfmonCreate(
}
RADEXPFUNC inline void RADEXPLINK IggyInstallPerfmon(void* perfmon) { STUBBED; }
+RADEXPFUNC inline IggyResult RADEXPLINK IggyValueGetTypeRS(IggyValuePath* var,
+ IggyName sub_name,
+ char const* sub_name_utf8,
+ IggyDatatype* result) {
+ STUBBED;
+ return IGGY_RESULT_SUCCESS;
+}
+
// GDraw memory/warning functions are defined in gdraw_glfw.c (C linkage)
// Juicey you stupid idiot do NOT define them here
diff --git a/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h b/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h
index 452562fad..ca2741f9c 100644
--- a/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h
+++ b/Minecraft.Client/Platform/Linux/Stubs/winapi_stubs.h
@@ -306,28 +306,6 @@ static inline ULONG TryEnterCriticalSection(
return pthread_mutex_trylock(CriticalSection) == 0;
}
-// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsalloc
-static inline DWORD TlsAlloc(VOID) {
- pthread_key_t key;
- if (pthread_key_create(&key, NULL) == 0) return key;
- return TLS_OUT_OF_INDEXES;
-}
-
-// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsfree
-static inline BOOL TlsFree(DWORD dwTlsIndex) {
- return pthread_key_delete(dwTlsIndex) == 0;
-}
-
-// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlsgetvalue
-static inline LPVOID TlsGetValue(DWORD dwTlsIndex) {
- return pthread_getspecific(dwTlsIndex);
-}
-
-// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-tlssetvalue
-static inline BOOL TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue) {
- return pthread_setspecific(dwTlsIndex, lpTlsValue) == 0;
-}
-
// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-globalmemorystatus
static inline VOID GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer) {
// TODO: Parse /proc/meminfo and set lpBuffer based on that. Probably will
@@ -336,17 +314,7 @@ static inline VOID GlobalMemoryStatus(LPMEMORYSTATUS lpBuffer) {
static inline DWORD GetLastError(VOID) { return errno; }
-static inline VOID Sleep(DWORD dwMilliseconds) {
- struct timespec ts;
- ts.tv_nsec = (dwMilliseconds * 1000000) % 1000000000;
- ts.tv_sec = dwMilliseconds / 1000;
-
- int ret;
- do {
- ret = nanosleep(&ts, &ts);
- } while (ret == -1 && errno == EINTR);
-}
-
+#ifdef __LP64__
static inline LONG64 InterlockedCompareExchangeRelease64(
LONG64 volatile* Destination, LONG64 Exchange, LONG64 Comperand) {
LONG64 expected = Comperand;
@@ -354,6 +322,15 @@ static inline LONG64 InterlockedCompareExchangeRelease64(
__ATOMIC_RELEASE, __ATOMIC_RELAXED);
return expected;
}
+#else
+static inline LONG64 InterlockedCompareExchangeRelease(
+ LONG volatile* Destination, LONG Exchange, LONG Comperand) {
+ LONG expected = Comperand;
+ __atomic_compare_exchange_n(Destination, &expected, Exchange, false,
+ __ATOMIC_RELEASE, __ATOMIC_RELAXED);
+ return expected;
+}
+#endif
// internal helper: convert time_t to FILETIME (100ns intervals since
// 1601-01-01)
diff --git a/Minecraft.Client/Platform/Windows64/Iggy/gdraw/gdraw_gl_shared.inl b/Minecraft.Client/Platform/Windows64/Iggy/gdraw/gdraw_gl_shared.inl
index c22517041..e24dd7202 100644
--- a/Minecraft.Client/Platform/Windows64/Iggy/gdraw/gdraw_gl_shared.inl
+++ b/Minecraft.Client/Platform/Windows64/Iggy/gdraw/gdraw_gl_shared.inl
@@ -57,6 +57,10 @@ static RADINLINE void break_on_err(GLint e)
#endif
}
+#ifndef GDRAW_PLATFORM_REPORT_GL_SITE
+#define GDRAW_PLATFORM_REPORT_GL_SITE(site) ((void)0)
+#endif
+
static void report_err(GLint e)
{
break_on_err(e);
@@ -74,17 +78,31 @@ static void eat_gl_err(void)
while (glGetError() != GL_NO_ERROR);
}
+static void opengl_check_site(const char *site);
+
static void opengl_check(void)
+{
+ opengl_check_site(NULL);
+}
+
+static void opengl_check_site(const char *site)
{
#ifdef _DEBUG
GLint e = glGetError();
if (e != GL_NO_ERROR) {
+ GDRAW_PLATFORM_REPORT_GL_SITE(site);
report_err(e);
eat_gl_err();
}
+#else
+ (void) site;
#endif
}
+#ifndef OPENGL_CHECK_SITE
+#define OPENGL_CHECK_SITE(site) opengl_check_site(site)
+#endif
+
static U32 is_pow2(S32 n)
{
return ((U32) n & (U32) (n-1)) == 0;
@@ -635,6 +653,90 @@ static void RADLINK gdraw_DescribeVertexBuffer(GDrawVertexBuffer *vbuf, GDraw_Ve
// Create/free (or cache) render targets
//
+#ifdef __linux__
+typedef struct
+{
+ S32 free_count;
+ S32 live_count;
+ S32 locked_count;
+ S32 dead_count;
+ S32 pinned_count;
+ S32 user_owned_count;
+ S32 alloc_count;
+} GDrawHandleStateCounts;
+
+enum
+{
+ GDRAW_RT_DIAG_color_memory = 1 << 0,
+ GDRAW_RT_DIAG_color_handles = 1 << 1,
+ GDRAW_RT_DIAG_cache_bitmap = 1 << 2,
+ GDRAW_RT_DIAG_stack_depth = 1 << 3,
+ GDRAW_RT_DIAG_empty_request = 1 << 4,
+};
+
+static U32 gdraw_rt_diag_emitted = 0;
+
+static void gdraw_CountHandleStates(GDrawHandleCache *cache,
+ GDrawHandleStateCounts *counts)
+{
+ S32 i;
+ counts->free_count = 0;
+ counts->live_count = 0;
+ counts->locked_count = 0;
+ counts->dead_count = 0;
+ counts->pinned_count = 0;
+ counts->user_owned_count = 0;
+ counts->alloc_count = 0;
+
+ if (!cache)
+ return;
+
+ for (i = 0; i < cache->max_handles; ++i) {
+ switch (cache->handle[i].state) {
+ case GDRAW_HANDLE_STATE_free: ++counts->free_count; break;
+ case GDRAW_HANDLE_STATE_live: ++counts->live_count; break;
+ case GDRAW_HANDLE_STATE_locked: ++counts->locked_count; break;
+ case GDRAW_HANDLE_STATE_dead: ++counts->dead_count; break;
+ case GDRAW_HANDLE_STATE_pinned: ++counts->pinned_count; break;
+ case GDRAW_HANDLE_STATE_user_owned: ++counts->user_owned_count; break;
+ case GDRAW_HANDLE_STATE_alloc: ++counts->alloc_count; break;
+ default: break;
+ }
+ }
+}
+
+static void gdraw_ReportHandleCacheDiag(char const *label,
+ GDrawHandleCache *cache,
+ U32 once_bit,
+ S32 req_w,
+ S32 req_h)
+{
+ GDrawHandleStateCounts counts;
+
+ if (gdraw_rt_diag_emitted & once_bit)
+ return;
+ gdraw_rt_diag_emitted |= once_bit;
+
+ gdraw_CountHandleStates(cache, &counts);
+ IggyGDrawSendWarning(NULL,
+ "GDraw[%s] diag: frame=%dx%d tile=%dx%d padded=%dx%d req=%dx%d depth=%d bytes_free=%d total_bytes=%d handles free=%d live=%d locked=%d dead=%d pinned=%d user=%d alloc=%d",
+ label,
+ gdraw->frametex_width, gdraw->frametex_height,
+ gdraw->tw, gdraw->th,
+ gdraw->tpw, gdraw->tph,
+ req_w, req_h,
+ (int) (gdraw->cur - gdraw->frame),
+ cache ? cache->bytes_free : 0,
+ cache ? cache->total_bytes : 0,
+ counts.free_count, counts.live_count, counts.locked_count,
+ counts.dead_count, counts.pinned_count, counts.user_owned_count,
+ counts.alloc_count);
+}
+#else
+#define gdraw_ReportHandleCacheDiag(label, cache, once_bit, req_w, req_h) \
+ ((void) 0)
+#endif
+
static GDrawHandle *get_rendertarget_texture(int width, int height, void *owner, GDrawStats *gstats)
{
S32 size;
@@ -678,13 +780,17 @@ static GDrawHandle *get_color_rendertarget(GDrawStats *gstats)
// ran out of RTs, allocate a new one
size = gdraw->frametex_width * gdraw->frametex_height * 4;
if (gdraw->rendertargets.bytes_free < size) {
- IggyGDrawSendWarning(NULL, "GDraw exceeded available rendertarget memory");
+ gdraw_ReportHandleCacheDiag("rt-color-memory", &gdraw->rendertargets,
+ GDRAW_RT_DIAG_color_memory, gdraw->tpw, gdraw->tph);
+ IggyGDrawSendWarning(NULL, "GDraw[rt-color] exceeded available rendertarget memory");
return NULL;
}
t = gdraw_HandleCacheAllocateBegin(&gdraw->rendertargets);
if (!t) {
- IggyGDrawSendWarning(NULL, "GDraw exceeded available rendertarget handles");
+ gdraw_ReportHandleCacheDiag("rt-color-handles", &gdraw->rendertargets,
+ GDRAW_RT_DIAG_color_handles, gdraw->tpw, gdraw->tph);
+ IggyGDrawSendWarning(NULL, "GDraw[rt-color] exceeded available rendertarget handles");
return t;
}
@@ -992,25 +1098,31 @@ static rrbool RADLINK gdraw_TextureDrawBufferBegin(gswf_recti *region, gdraw_tex
GDrawHandle *t;
int k;
if (gdraw->tw == 0 || gdraw->th == 0) {
- IggyGDrawSendWarning(NULL, "GDraw got a request for an empty rendertarget");
+ gdraw_ReportHandleCacheDiag("rt-empty", &gdraw->rendertargets,
+ GDRAW_RT_DIAG_empty_request, region->x1 - region->x0, region->y1 - region->y0);
+ IggyGDrawSendWarning(NULL, "GDraw[rt-stack] got a request for an empty rendertarget");
return false;
}
if (n >= &gdraw->frame[MAX_RENDER_STACK_DEPTH]) {
- IggyGDrawSendWarning(NULL, "GDraw rendertarget nesting exceeded MAX_RENDER_STACK_DEPTH");
+ gdraw_ReportHandleCacheDiag("rt-stack-depth", &gdraw->rendertargets,
+ GDRAW_RT_DIAG_stack_depth, region->x1 - region->x0, region->y1 - region->y0);
+ IggyGDrawSendWarning(NULL, "GDraw[rt-stack] rendertarget nesting exceeded MAX_RENDER_STACK_DEPTH");
return false;
}
if (owner) {
t = get_rendertarget_texture(region->x1 - region->x0, region->y1 - region->y0, owner, gstats);
if (!t) {
- IggyGDrawSendWarning(NULL, "GDraw ran out of rendertargets for cacheAsBItmap");
+ gdraw_ReportHandleCacheDiag("rt-cacheAsBitmap", gdraw->texturecache,
+ GDRAW_RT_DIAG_cache_bitmap, region->x1 - region->x0, region->y1 - region->y0);
+ IggyGDrawSendWarning(NULL, "GDraw[rt-cacheAsBitmap] ran out of rendertargets");
return false;
}
} else {
t = get_color_rendertarget(gstats);
if (!t) {
- IggyGDrawSendWarning(NULL, "GDraw ran out of rendertargets");
+ IggyGDrawSendWarning(NULL, "GDraw[rt-color] ran out of rendertargets");
return false;
}
}
@@ -1355,18 +1467,18 @@ static int set_render_state(GDrawRenderState *r, S32 vformat, const int **ovvars
}
use_lazy_shader(prg);
- opengl_check();
+ OPENGL_CHECK_SITE("set_render_state:use_lazy_shader");
fvars = prg->vars[0];
vvars = prg->vars[1];
if (vformat == GDRAW_vformat_ihud1) {
F32 wv[2][4] = { 1.0f/960,0,0,-1.0, 0,-1.0f/540,0,+1.0 };
glUniform4fv(vvars[VAR_ihudv_worldview], 2, wv[0]);
- opengl_check();
+ OPENGL_CHECK_SITE("set_render_state:ihud_worldview");
glUniform4fv(vvars[VAR_ihudv_material], p->uniform_count, p->uniforms);
- opengl_check();
+ OPENGL_CHECK_SITE("set_render_state:ihud_material");
glUniform1f(vvars[VAR_ihudv_textmode], p->drawprim_mode ? 0.0f : 1.0f);
- opengl_check();
+ OPENGL_CHECK_SITE("set_render_state:ihud_textmode");
} else {
// set vertex shader constants
@@ -1393,7 +1505,7 @@ static int set_render_state(GDrawRenderState *r, S32 vformat, const int **ovvars
// texture stuff
set_texture(0, r->tex[0]);
- opengl_check();
+ OPENGL_CHECK_SITE("set_render_state:set_texture0");
if (r->tex[0] && gdraw->has_conditional_non_power_of_two && ((GDrawHandle*) r->tex[0])->handle.tex.nonpow2) {
// only wrap mode allowed in conditional nonpow2 is clamp; this should
@@ -1490,7 +1602,7 @@ static int set_render_state(GDrawRenderState *r, S32 vformat, const int **ovvars
else
glDepthMask(GL_FALSE);
- opengl_check();
+ OPENGL_CHECK_SITE("set_render_state:final");
if (ovvars)
*ovvars = vvars;
@@ -1611,7 +1723,7 @@ static void RADLINK gdraw_DrawIndexedTriangles(GDrawRenderState *r, GDrawPrimiti
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
- opengl_check();
+ OPENGL_CHECK_SITE("gdraw_DrawIndexedTriangles:final");
tag_resources(vb, r->tex[0], r->tex[1]);
}
@@ -1628,33 +1740,33 @@ static void do_screen_quad(gswf_recti *s, F32 *tc, const int *vvars, GDrawStats
F32 vert[4][4];
F32 world[2*4];
- opengl_check();
+ OPENGL_CHECK_SITE("do_screen_quad:begin");
vert[0][0] = px0; vert[0][1] = py0; vert[0][2] = s0; vert[0][3] = t0;
vert[1][0] = px1; vert[1][1] = py0; vert[1][2] = s1; vert[1][3] = t0;
vert[2][0] = px1; vert[2][1] = py1; vert[2][2] = s1; vert[2][3] = t1;
vert[3][0] = px0; vert[3][1] = py1; vert[3][2] = s0; vert[3][3] = t1;
- opengl_check();
+ OPENGL_CHECK_SITE("do_screen_quad:after_vertices");
gdraw_PixelSpace(world);
world[2] = depth;
set_world_projection(vvars, world);
- opengl_check();
+ OPENGL_CHECK_SITE("do_screen_quad:after_projection");
set_vertex_format(GDRAW_vformat_v2tc2, vert[0]);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
- opengl_check();
+ OPENGL_CHECK_SITE("do_screen_quad:before_draw");
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
reset_vertex_format(GDRAW_vformat_v2tc2);
- opengl_check();
+ OPENGL_CHECK_SITE("do_screen_quad:after_draw");
gstats->nonzero_flags |= GDRAW_STATS_batches;
gstats->num_batches += 1;
gstats->drawn_vertices += 4;
gstats->drawn_indices += 6;
- opengl_check();
+ OPENGL_CHECK_SITE("do_screen_quad:final");
}
#ifdef GDRAW_FEWER_CLEARS
@@ -1805,7 +1917,7 @@ static void RADLINK gdraw_FilterQuad(GDrawRenderState *r, S32 x0, S32 y0, S32 x1
glColorMask(1,1,1,1);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
- opengl_check();
+ OPENGL_CHECK_SITE("gdraw_FilterQuad:pre_filter");
if (r->blend_mode == GDRAW_BLEND_filter) {
switch (r->filter) {
diff --git a/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp
index 6b99c167b..06a0aa2d0 100644
--- a/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp
+++ b/Minecraft.Client/Platform/Windows64/Windows64_Minecraft.cpp
@@ -772,8 +772,6 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
// Initialise TLS for tesselator, for this main thread
Tesselator::CreateNewThreadStorage(1024 * 1024);
// Initialise TLS for AABB and Vec3 pools, for this main thread
- AABB::CreateNewThreadStorage();
- Vec3::CreateNewThreadStorage();
Compression::CreateNewThreadStorage();
OldChunkStorage::CreateNewThreadStorage();
Level::enableLightingCache();
@@ -918,9 +916,6 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
}
// Fix for #7318 - Title crashes after short soak in the leaderboards
- // menu A memory leak was caused because the icon renderer kept creating
- // new Vec3's because the pool wasn't reset
- Vec3::resetPool();
}
// Free resources, unregister custom classes, and exit.
diff --git a/Minecraft.Client/Platform/stdafx.h b/Minecraft.Client/Platform/stdafx.h
index c6d17eb4e..9befa0cbe 100644
--- a/Minecraft.Client/Platform/stdafx.h
+++ b/Minecraft.Client/Platform/stdafx.h
@@ -5,8 +5,8 @@
#pragma once
-//#include
-//#include
+// #include
+// #include
#define __STR2__(x) #x
#define __STR1__(x) __STR2__(x)
@@ -39,6 +39,7 @@ using namespace DirectX;
#define HRESULT_SUCCEEDED(hr) (((HRESULT)(hr)) >= 0)
#endif
+
#include "../../Minecraft.World/Platform/x64headers/extraX64.h"
#include
diff --git a/Minecraft.Client/Platform/stubs.h b/Minecraft.Client/Platform/stubs.h
index 91464c6a8..9841637ca 100644
--- a/Minecraft.Client/Platform/stubs.h
+++ b/Minecraft.Client/Platform/stubs.h
@@ -13,30 +13,32 @@ class FloatBuffer;
class IntBuffer;
class ByteBuffer;
-void glGenTextures(IntBuffer *);
+void glGenTextures(IntBuffer*);
int glGenTextures();
-void glDeleteTextures(IntBuffer *);
+void glDeleteTextures(IntBuffer*);
void glDeleteTextures(int);
-void glLight(int, int, FloatBuffer *);
-void glLightModel(int, FloatBuffer *);
-void glGetFloat(int, FloatBuffer *);
-void glTexGen(int, int, FloatBuffer *);
-void glFog(int, FloatBuffer *);
-void glTexCoordPointer(int, int, FloatBuffer *);
-void glNormalPointer(int, ByteBuffer *);
-void glColorPointer(int, bool, int, ByteBuffer *);
-void glVertexPointer(int, int, FloatBuffer *);
-void glEndList(int);
-void glTexImage2D(int, int, int, int, int, int, int, int, ByteBuffer *);
-void glCallLists(IntBuffer *);
-void glGenQueriesARB(IntBuffer *);
+void glLight(int, int, FloatBuffer*);
+void glLightModel(int, FloatBuffer*);
+void glGetFloat(int, FloatBuffer*);
+void glTexGen(int, int, FloatBuffer*);
+void glFog(int, FloatBuffer*);
+void glTexCoordPointer(int, int, FloatBuffer*);
+void glNormalPointer(int, ByteBuffer*);
+void glColorPointer(int, bool, int, ByteBuffer*);
+void glVertexPointer(int, int, FloatBuffer*);
+
+void glEndList_4J(int vertexCount = 0);
+
+void glTexImage2D(int, int, int, int, int, int, int, int, ByteBuffer*);
+void glCallLists(IntBuffer*);
+void glGenQueriesARB(IntBuffer*);
void glBeginQueryARB(int, int);
void glEndQueryARB(int);
-void glGetQueryObjectuARB(int, int, IntBuffer *);
-void glReadPixels(int, int, int, int, int, int, ByteBuffer *);
+void glGetQueryObjectuARB(int, int, IntBuffer*);
+void glReadPixels(int, int, int, int, int, int, ByteBuffer*);
+
void LinuxGLLogLightmapState(const char* stage, int textureId, bool scaleLight);
void LinuxLogStubLightmapProbe();
-
#else
const int GL_BYTE = 0;
@@ -54,13 +56,9 @@ const int GL_NORMALIZE = 0;
const int GL_RESCALE_NORMAL = 0;
-
-
const int GL_SMOOTH = 0;
const int GL_FLAT = 0;
-
-
const int GL_RGBA = 0;
const int GL_BGRA = 1;
const int GL_BGR = 0;
@@ -83,73 +81,73 @@ const int GL_TEXTURE1 = 0;
const int GL_TEXTURE0 = 1;
void glFlush();
-void glTexGeni(int,int,int);
-void glTexGen(int,int,FloatBuffer *);
-void glReadPixels(int,int, int, int, int, int, ByteBuffer *);
+void glTexGeni(int, int, int);
+void glTexGen(int, int, FloatBuffer*);
+void glReadPixels(int, int, int, int, int, int, ByteBuffer*);
void glClearDepth(double);
void glCullFace(int);
-void glDeleteLists(int,int);
-void glGenTextures(IntBuffer *);
+void glDeleteLists(int, int);
+void glGenTextures(IntBuffer*);
int glGenTextures();
int glGenLists(int);
-void glLight(int, int,FloatBuffer *);
-void glLightModel(int, FloatBuffer *);
-void glGetFloat(int a, FloatBuffer *b);
+void glLight(int, int, FloatBuffer*);
+void glLightModel(int, FloatBuffer*);
+void glGetFloat(int a, FloatBuffer* b);
void glTexCoordPointer(int, int, int, int);
-void glTexCoordPointer(int, int, FloatBuffer *);
+void glTexCoordPointer(int, int, FloatBuffer*);
void glNormalPointer(int, int, int);
-void glNormalPointer(int, ByteBuffer *);
+void glNormalPointer(int, ByteBuffer*);
void glEnableClientState(int);
void glDisableClientState(int);
-void glColorPointer(int, bool, int, ByteBuffer *);
+void glColorPointer(int, bool, int, ByteBuffer*);
void glColorPointer(int, int, int, int);
void glVertexPointer(int, int, int, int);
-void glVertexPointer(int, int, FloatBuffer *);
-void glDrawArrays(int,int,int);
-void glTranslatef(float,float,float);
-void glRotatef(float,float,float,float);
-void glNewList(int,int);
+void glVertexPointer(int, int, FloatBuffer*);
+void glDrawArrays(int, int, int);
+void glTranslatef(float, float, float);
+void glRotatef(float, float, float, float);
+void glNewList(int, int);
void glEndList(int vertexCount = 0);
void glCallList(int);
void glPopMatrix();
void glPushMatrix();
-void glColor3f(float,float,float);
-void glScalef(float,float,float);
-void glMultMatrixf(float *);
-void glColor4f(float,float,float,float);
+void glColor3f(float, float, float);
+void glScalef(float, float, float);
+void glMultMatrixf(float*);
+void glColor4f(float, float, float, float);
void glDisable(int);
void glEnable(int);
-void glBlendFunc(int,int);
+void glBlendFunc(int, int);
void glDepthMask(bool);
-void glNormal3f(float,float,float);
+void glNormal3f(float, float, float);
void glDepthFunc(int);
void glMatrixMode(int);
void glLoadIdentity();
-void glBindTexture(int,int);
-void glTexParameteri(int,int,int);
-void glTexImage2D(int,int,int,int,int,int,int,int,ByteBuffer *);
-void glDeleteTextures(IntBuffer *);
+void glBindTexture(int, int);
+void glTexParameteri(int, int, int);
+void glTexImage2D(int, int, int, int, int, int, int, int, ByteBuffer*);
+void glDeleteTextures(IntBuffer*);
void glDeleteTextures(int);
-void glCallLists(IntBuffer *);
-void glGenQueriesARB(IntBuffer *);
-void glColorMask(bool,bool,bool,bool);
-void glBeginQueryARB(int,int);
+void glCallLists(IntBuffer*);
+void glGenQueriesARB(IntBuffer*);
+void glColorMask(bool, bool, bool, bool);
+void glBeginQueryARB(int, int);
void glEndQueryARB(int);
-void glGetQueryObjectuARB(int,int,IntBuffer *);
+void glGetQueryObjectuARB(int, int, IntBuffer*);
void glShadeModel(int);
-void glPolygonOffset(float,float);
+void glPolygonOffset(float, float);
void glLineWidth(float);
-void glScaled(double,double,double);
-void gluPerspective(float,float,float,float);
+void glScaled(double, double, double);
+void gluPerspective(float, float, float, float);
void glClear(int);
-void glViewport(int,int,int,int);
-void glAlphaFunc(int,float);
-void glOrtho(float,float,float,float,float,float);
-void glClearColor(float,float,float,float);
-void glFogi(int,int);
-void glFogf(int,float);
-void glFog(int,FloatBuffer *);
-void glColorMaterial(int,int);
+void glViewport(int, int, int, int);
+void glAlphaFunc(int, float);
+void glOrtho(float, float, float, float, float, float);
+void glClearColor(float, float, float, float);
+void glFogi(int, int);
+void glFogf(int, float);
+void glFog(int, FloatBuffer*);
+void glColorMaterial(int, int);
void glMultiTexCoord2f(int, float, float);
void glClientActiveTexture(int);
@@ -158,164 +156,150 @@ void glActiveTexture(int);
#endif
#ifdef __linux__
-class GL11
-{
-public:
- static const int GL_SMOOTH = 0x1D01;
- static const int GL_FLAT = 0x1D00;
- static void glShadeModel(int mode) { ::glShadeModel(mode); }
-};
+class GL11 {
+public:
+ static const int GL_SMOOTH = 0x1D01;
+ static const int GL_FLAT = 0x1D00;
+#undef glShadeModel
+#define GL_SHADEMODEL_IS_FUNCTION
+ static void glShadeModel(int mode) { ::glShadeModel(mode); }
+};
#undef GL_ARRAY_BUFFER_ARB
#undef GL_STREAM_DRAW_ARB
-class ARBVertexBufferObject
-{
+class ARBVertexBufferObject {
public:
- static const int GL_ARRAY_BUFFER_ARB = 0x8892;
- static const int GL_STREAM_DRAW_ARB = 0x88E0;
- static void glBindBufferARB(int, int) {}
- static void glBufferDataARB(int, ByteBuffer *, int) {}
- static void glGenBuffersARB(IntBuffer *) {}
+ static const int GL_ARRAY_BUFFER_ARB = 0x8892;
+ static const int GL_STREAM_DRAW_ARB = 0x88E0;
+ static void glBindBufferARB(int, int) {}
+ static void glBufferDataARB(int, ByteBuffer*, int) {}
+ static void glGenBuffersARB(IntBuffer*) {}
};
#else
-class GL11
-{
+class GL11 {
public:
- static const int GL_SMOOTH = 0;
- static const int GL_FLAT = 0;
- static void glShadeModel(int) {};
+ static const int GL_SMOOTH = 0;
+ static const int GL_FLAT = 0;
+ static void glShadeModel(int) {};
};
-class ARBVertexBufferObject
-{
+class ARBVertexBufferObject {
public:
- static const int GL_ARRAY_BUFFER_ARB = 0;
- static const int GL_STREAM_DRAW_ARB = 0;
- static void glBindBufferARB(int, int) {}
- static void glBufferDataARB(int, ByteBuffer *, int) {}
- static void glGenBuffersARB(IntBuffer *) {}
+ static const int GL_ARRAY_BUFFER_ARB = 0;
+ static const int GL_STREAM_DRAW_ARB = 0;
+ static void glBindBufferARB(int, int) {}
+ static void glBufferDataARB(int, ByteBuffer*, int) {}
+ static void glGenBuffersARB(IntBuffer*) {}
};
#endif
-
class Level;
class Player;
class Textures;
class Font;
class MapItemSavedData;
class Mob;
-class Particles
-{
+class Particles {
public:
- void render(float) {}
- void tick() {}
+ void render(float) {}
+ void tick() {}
};
class BufferedImage;
-class Graphics
-{
+class Graphics {
public:
- void drawImage(BufferedImage *, int, int, void *) {}
- void dispose() {}
+ void drawImage(BufferedImage*, int, int, void*) {}
+ void dispose() {}
};
-class ZipEntry
-{
-};
+class ZipEntry {};
class InputStream;
class File;
-class ZipFile
-{
+class ZipFile {
public:
- ZipFile(File *file) {}
- InputStream *getInputStream(ZipEntry *entry) { return NULL; }
- ZipEntry *getEntry(const std::wstring& name) {return NULL;}
- void close() {}
+ ZipFile(File* file) {}
+ InputStream* getInputStream(ZipEntry* entry) { return NULL; }
+ ZipEntry* getEntry(const std::wstring& name) { return NULL; }
+ void close() {}
};
-class ImageIO
-{
+class ImageIO {
public:
- static BufferedImage *read(InputStream *in) { return NULL; }
+ static BufferedImage* read(InputStream* in) { return NULL; }
};
-class Keyboard
-{
+class Keyboard {
public:
- static void create() {}
- static void destroy() {}
- static bool isKeyDown(int) {return false;}
- static std::wstring getKeyName(int) { return L"KEYNAME"; }
- static void enableRepeatEvents(bool) {}
- static const int KEY_A = 0;
- static const int KEY_B = 1;
- static const int KEY_C = 2;
- static const int KEY_D = 3;
- static const int KEY_E = 4;
- static const int KEY_F = 5;
- static const int KEY_G = 6;
- static const int KEY_H = 7;
- static const int KEY_I = 8;
- static const int KEY_J = 9;
- static const int KEY_K = 10;
- static const int KEY_L = 11;
- static const int KEY_M = 12;
- static const int KEY_N = 13;
- static const int KEY_O = 14;
- static const int KEY_P = 15;
- static const int KEY_Q = 16;
- static const int KEY_R = 17;
- static const int KEY_S = 18;
- static const int KEY_T = 19;
- static const int KEY_U = 20;
- static const int KEY_V = 21;
- static const int KEY_W = 22;
- static const int KEY_X = 23;
- static const int KEY_Y = 24;
- static const int KEY_Z = 25;
- static const int KEY_SPACE = 26;
- static const int KEY_LSHIFT = 27;
- static const int KEY_ESCAPE = 28;
- static const int KEY_BACK = 29;
- static const int KEY_RETURN = 30;
- static const int KEY_RSHIFT = 31;
- static const int KEY_UP = 32;
- static const int KEY_DOWN = 33;
- static const int KEY_TAB = 34;
+ static void create() {}
+ static void destroy() {}
+ static bool isKeyDown(int) { return false; }
+ static std::wstring getKeyName(int) { return L"KEYNAME"; }
+ static void enableRepeatEvents(bool) {}
+ static const int KEY_A = 0;
+ static const int KEY_B = 1;
+ static const int KEY_C = 2;
+ static const int KEY_D = 3;
+ static const int KEY_E = 4;
+ static const int KEY_F = 5;
+ static const int KEY_G = 6;
+ static const int KEY_H = 7;
+ static const int KEY_I = 8;
+ static const int KEY_J = 9;
+ static const int KEY_K = 10;
+ static const int KEY_L = 11;
+ static const int KEY_M = 12;
+ static const int KEY_N = 13;
+ static const int KEY_O = 14;
+ static const int KEY_P = 15;
+ static const int KEY_Q = 16;
+ static const int KEY_R = 17;
+ static const int KEY_S = 18;
+ static const int KEY_T = 19;
+ static const int KEY_U = 20;
+ static const int KEY_V = 21;
+ static const int KEY_W = 22;
+ static const int KEY_X = 23;
+ static const int KEY_Y = 24;
+ static const int KEY_Z = 25;
+ static const int KEY_SPACE = 26;
+ static const int KEY_LSHIFT = 27;
+ static const int KEY_ESCAPE = 28;
+ static const int KEY_BACK = 29;
+ static const int KEY_RETURN = 30;
+ static const int KEY_RSHIFT = 31;
+ static const int KEY_UP = 32;
+ static const int KEY_DOWN = 33;
+ static const int KEY_TAB = 34;
};
-class Mouse
-{
+class Mouse {
public:
- static void create() {}
- static void destroy() {}
- static int getX() { return 0; }
- static int getY() { return 0; }
- static bool isButtonDown(int) { return false; }
+ static void create() {}
+ static void destroy() {}
+ static int getX() { return 0; }
+ static int getY() { return 0; }
+ static bool isButtonDown(int) { return false; }
};
-class Display
-{
+class Display {
public:
- static bool isActive() {return true;}
- static void update();
- static void swapBuffers();
- static void destroy() {}
+ static bool isActive() { return true; }
+ static void update();
+ static void swapBuffers();
+ static void destroy() {}
};
-class BackgroundDownloader
-{
+class BackgroundDownloader {
public:
- BackgroundDownloader(File workDir, Minecraft* minecraft) {}
- void start() {}
- void halt() {}
- void forceReload() {}
+ BackgroundDownloader(File workDir, Minecraft* minecraft) {}
+ void start() {}
+ void halt() {}
+ void forceReload() {}
};
-class Color
-{
+class Color {
public:
- static int HSBtoRGB(float,float,float) {return 0;}
+ static int HSBtoRGB(float, float, float) { return 0; }
};
diff --git a/Minecraft.Client/Player/LocalPlayer.cpp b/Minecraft.Client/Player/LocalPlayer.cpp
index 4efe76482..56049fef4 100644
--- a/Minecraft.Client/Player/LocalPlayer.cpp
+++ b/Minecraft.Client/Player/LocalPlayer.cpp
@@ -1,5 +1,12 @@
#include "../Platform/stdafx.h"
#include "LocalPlayer.h"
+#include "UI/Screens/BeaconScreen.h"
+#include "UI/Screens/BrewingStandScreen.h"
+#include "UI/Screens/EnchantmentScreen.h"
+#include "UI/Screens/HopperScreen.h"
+#include "UI/Screens/HorseInventoryScreen.h"
+#include "UI/Screens/MerchantScreen.h"
+#include "UI/Screens/RepairScreen.h"
#include "User.h"
#include "../Input/Input.h"
#include "../GameState/StatsCounter.h"
@@ -243,10 +250,10 @@ void LocalPlayer::aiStep() {
if (ySlideOffset < 0.2f) ySlideOffset = 0.2f;
}
- checkInTile(x - bbWidth * 0.35, bb->y0 + 0.5, z + bbWidth * 0.35);
- checkInTile(x - bbWidth * 0.35, bb->y0 + 0.5, z - bbWidth * 0.35);
- checkInTile(x + bbWidth * 0.35, bb->y0 + 0.5, z - bbWidth * 0.35);
- checkInTile(x + bbWidth * 0.35, bb->y0 + 0.5, z + bbWidth * 0.35);
+ checkInTile(x - bbWidth * 0.35, bb.y0 + 0.5, z + bbWidth * 0.35);
+ checkInTile(x - bbWidth * 0.35, bb.y0 + 0.5, z - bbWidth * 0.35);
+ checkInTile(x + bbWidth * 0.35, bb.y0 + 0.5, z - bbWidth * 0.35);
+ checkInTile(x + bbWidth * 0.35, bb.y0 + 0.5, z + bbWidth * 0.35);
bool enoughFoodToSprint =
getFoodData()->getFoodLevel() >
@@ -402,25 +409,25 @@ void LocalPlayer::aiStep() {
if (abilities.flying) // minecraft->options->isFlying )
{
- Vec3* viewVector = getViewVector(1.0f);
+ Vec3 viewVector = getViewVector(1.0f);
// 4J-PB - To let the player build easily while flying, we need to
// change this
#if defined(_DEBUG_MENUS_ENABLED)
if (abilities.debugflying) {
- flyX = (float)viewVector->x * input->ya;
- flyY = (float)viewVector->y * input->ya;
- flyZ = (float)viewVector->z * input->ya;
+ flyX = (float)viewVector.x * input->ya;
+ flyY = (float)viewVector.y * input->ya;
+ flyZ = (float)viewVector.z * input->ya;
} else
#endif
{
if (isSprinting()) {
// Accelrate up to full speed if we are sprinting, moving in the
// direction of the view vector
- flyX = (float)viewVector->x * input->ya;
- flyY = (float)viewVector->y * input->ya;
- flyZ = (float)viewVector->z * input->ya;
+ flyX = (float)viewVector.x * input->ya;
+ flyY = (float)viewVector.y * input->ya;
+ flyZ = (float)viewVector.z * input->ya;
float scale = ((float)(SPRINT_DURATION - sprintTime)) / 10.0f;
scale = scale * scale;
@@ -548,7 +555,8 @@ void LocalPlayer::closeContainer() {
void LocalPlayer::openTextEdit(std::shared_ptr tileEntity) {
#if defined(ENABLE_JAVA_GUIS)
if (tileEntity->GetType() == eTYPE_SIGNTILEENTITY) {
- minecraft->setScreen(new TextEditScreen(std::dynamic_pointer_cast(tileEntity)));
+ minecraft->setScreen(new TextEditScreen(
+ std::dynamic_pointer_cast(tileEntity)));
bool success = true;
}
#else
@@ -581,25 +589,36 @@ bool LocalPlayer::openContainer(std::shared_ptr container) {
}
bool LocalPlayer::openHopper(std::shared_ptr container) {
- // minecraft->setScreen(new HopperScreen(inventory, container));
+#ifdef ENABLE_JAVA_GUIS
+ minecraft->setScreen(new HopperScreen(inventory, container));
+ bool success = true;
+#else
bool success = app.LoadHopperMenu(GetXboxPad(), inventory, container);
if (success) ui.PlayUISFX(eSFX_Press);
+#endif
return success;
}
bool LocalPlayer::openHopper(std::shared_ptr container) {
- // minecraft->setScreen(new HopperScreen(inventory, container));
+#ifdef ENABLE_JAVA_GUIS
+ minecraft->setScreen(new HopperScreen(inventory, container));
+ bool success = true;
+#else
bool success = app.LoadHopperMenu(GetXboxPad(), inventory, container);
if (success) ui.PlayUISFX(eSFX_Press);
+#endif
return success;
}
bool LocalPlayer::openHorseInventory(std::shared_ptr horse,
std::shared_ptr container) {
- // minecraft->setScreen(new HorseInventoryScreen(inventory, container,
- // horse));
+#ifdef ENABLE_JAVA_GUIS
+ minecraft->setScreen(new HorseInventoryScreen(inventory, container, horse));
+ bool success = true;
+#else
bool success = app.LoadHorseMenu(GetXboxPad(), inventory, container, horse);
if (success) ui.PlayUISFX(eSFX_Press);
+#endif
return success;
}
@@ -628,17 +647,20 @@ bool LocalPlayer::openFireworks(int x, int y, int z) {
bool LocalPlayer::startEnchanting(int x, int y, int z,
const std::wstring& name) {
+#ifdef ENABLE_JAVA_GUIS
+ minecraft->setScreen(new EnchantmentScreen(inventory, level, x, y, z));
+ bool success = true;
+#else
bool success =
app.LoadEnchantingMenu(GetXboxPad(), inventory, x, y, z, level, name);
if (success) ui.PlayUISFX(eSFX_Press);
- // minecraft.setScreen(new EnchantmentScreen(inventory, level, x, y, z));
+#endif
return success;
}
bool LocalPlayer::startRepairing(int x, int y, int z) {
-#if defined(ENABLE_JAVA_GUIS)
- // minecraft.setScreen(new RepairScreen(inventory, level, x, y, z));
- // FUCK YOU 4J FIRST AND FOREMOST
+#ifdef ENABLE_JAVA_GUIS
+ minecraft->setScreen(new RepairScreen(inventory, level, x, y, z));
bool success = true;
#else
bool success =
@@ -661,33 +683,49 @@ bool LocalPlayer::openFurnace(std::shared_ptr furnace) {
bool LocalPlayer::openBrewingStand(
std::shared_ptr brewingStand) {
+#ifdef ENABLE_JAVA_GUIS
+ minecraft->setScreen(new BrewingStandScreen(inventory, brewingStand));
+ bool success = true;
+#else
bool success =
app.LoadBrewingStandMenu(GetXboxPad(), inventory, brewingStand);
if (success) ui.PlayUISFX(eSFX_Press);
- // minecraft.setScreen(new BrewingStandScreen(inventory, brewingStand));
+#endif
return success;
}
bool LocalPlayer::openBeacon(std::shared_ptr beacon) {
- // minecraft->setScreen(new BeaconScreen(inventory, beacon));
+#ifdef ENABLE_JAVA_GUIS
+ minecraft->setScreen(new BeaconScreen(inventory, beacon));
+ bool success = true;
+#else
bool success = app.LoadBeaconMenu(GetXboxPad(), inventory, beacon);
if (success) ui.PlayUISFX(eSFX_Press);
+#endif
return success;
}
bool LocalPlayer::openTrap(std::shared_ptr trap) {
+#ifdef ENABLE_JAVA_GUIS
+ minecraft->setScreen(new TrapScreen(inventory, trap));
+ bool success = true;
+#else
bool success = app.LoadTrapMenu(GetXboxPad(), inventory, trap);
if (success) ui.PlayUISFX(eSFX_Press);
- // minecraft->setScreen(new TrapScreen(inventory, trap));
+#endif
return success;
}
bool LocalPlayer::openTrading(std::shared_ptr traderTarget,
const std::wstring& name) {
+#ifdef ENABLE_JAVA_GUIS
+ minecraft->setScreen(new MerchantScreen(inventory, traderTarget, level));
+ bool success = true;
+#else
bool success =
app.LoadTradingMenu(GetXboxPad(), inventory, traderTarget, level, name);
if (success) ui.PlayUISFX(eSFX_Press);
- // minecraft.setScreen(new MerchantScreen(inventory, traderTarget, level));
+#endif
return success;
}
@@ -771,8 +809,7 @@ void LocalPlayer::awardStat(Stat* stat, byteArray param) {
// storage device, so needs a primary player, and the player may not
// have been a primary player when they first 'got' the award so let the
// award manager figure it out
- if (!minecraft->stats[m_iPad]->hasTaken(ach))
- {
+ if (!minecraft->stats[m_iPad]->hasTaken(ach)) {
// 4J-PB - Don't display the java popup
#if defined(ENABLE_JAVA_GUIS)
minecraft->achievementPopup->popup(ach);
@@ -1475,7 +1512,7 @@ bool LocalPlayer::handleMouseClick(int button) {
bool usedItem = false;
if (minecraft->gameMode->useItemOn(
minecraft->localplayers[GetXboxPad()], level, item, x, y, z,
- face, minecraft->hitResult->pos, false, &usedItem)) {
+ face, &minecraft->hitResult->pos, false, &usedItem)) {
// Presume that if we actually used the held item, then we've
// placed it
if (usedItem) {
diff --git a/Minecraft.Client/Player/MultiPlayerLocalPlayer.cpp b/Minecraft.Client/Player/MultiPlayerLocalPlayer.cpp
index 63f91dca7..54e00b811 100644
--- a/Minecraft.Client/Player/MultiPlayerLocalPlayer.cpp
+++ b/Minecraft.Client/Player/MultiPlayerLocalPlayer.cpp
@@ -140,7 +140,7 @@ void MultiplayerLocalPlayer::sendPosition() {
}
double xdd = x - xLast;
- double ydd1 = bb->y0 - yLast1;
+ double ydd1 = bb.y0 - yLast1;
double zdd = z - zLast;
double rydd = yRot - yRotLast;
@@ -158,11 +158,11 @@ void MultiplayerLocalPlayer::sendPosition() {
if (move && rot) {
connection->send(
std::shared_ptr(new MovePlayerPacket::PosRot(
- x, bb->y0, y, z, yRot, xRot, onGround, abilities.flying)));
+ x, bb.y0, y, z, yRot, xRot, onGround, abilities.flying)));
} else if (move) {
connection->send(
std::shared_ptr(new MovePlayerPacket::Pos(
- x, bb->y0, y, z, onGround, abilities.flying)));
+ x, bb.y0, y, z, onGround, abilities.flying)));
} else if (rot) {
connection->send(
std::shared_ptr(new MovePlayerPacket::Rot(
@@ -178,7 +178,7 @@ void MultiplayerLocalPlayer::sendPosition() {
if (move) {
xLast = x;
- yLast1 = bb->y0;
+ yLast1 = bb.y0;
yLast2 = y;
zLast = z;
positionReminder = 0;
diff --git a/Minecraft.Client/Rendering/Camera.cpp b/Minecraft.Client/Rendering/Camera.cpp
index cc6bc9b41..f95c729b4 100644
--- a/Minecraft.Client/Rendering/Camera.cpp
+++ b/Minecraft.Client/Rendering/Camera.cpp
@@ -73,10 +73,11 @@ zPlayerOffs = position->get(2);
TilePos* Camera::getCameraTilePos(std::shared_ptr player,
double alpha) {
- return new TilePos(getCameraPos(player, alpha));
+ Vec3 cam_pos = getCameraPos(player, alpha);
+ return new TilePos(&cam_pos);
}
-Vec3* Camera::getCameraPos(std::shared_ptr player, double alpha) {
+Vec3 Camera::getCameraPos(std::shared_ptr player, double alpha) {
double xx = player->xo + (player->x - player->xo) * alpha;
double yy =
player->yo + (player->y - player->yo) * alpha + player->getHeadHeight();
@@ -86,21 +87,21 @@ Vec3* Camera::getCameraPos(std::shared_ptr player, double alpha) {
double yt = yy + Camera::yPlayerOffs * 1;
double zt = zz + Camera::zPlayerOffs * 1;
- return Vec3::newTemp(xt, yt, zt);
+ return Vec3(xt, yt, zt);
}
int Camera::getBlockAt(Level* level, std::shared_ptr player,
float alpha) {
- Vec3* p = Camera::getCameraPos(player, alpha);
- TilePos tp = TilePos(p);
+ Vec3 p = Camera::getCameraPos(player, alpha);
+ TilePos tp = TilePos(&p);
int t = level->getTile(tp.x, tp.y, tp.z);
if (t != 0 && Tile::tiles[t]->material->isLiquid()) {
float hh =
LiquidTile::getHeight(level->getData(tp.x, tp.y, tp.z)) - 1 / 9.0f;
float h = tp.y + 1 - hh;
- if (p->y >= h) {
+ if (p.y >= h) {
t = level->getTile(tp.x, tp.y + 1, tp.z);
}
}
return t;
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/Camera.h b/Minecraft.Client/Rendering/Camera.h
index ce2dcb6ce..894a01967 100644
--- a/Minecraft.Client/Rendering/Camera.h
+++ b/Minecraft.Client/Rendering/Camera.h
@@ -26,8 +26,8 @@ public:
static TilePos* getCameraTilePos(std::shared_ptr player,
double alpha);
- static Vec3* getCameraPos(std::shared_ptr player,
- double alpha);
+ static Vec3 getCameraPos(std::shared_ptr player,
+ double alpha);
static int getBlockAt(Level* level, std::shared_ptr player,
float alpha);
-};
\ No newline at end of file
+};
diff --git a/Minecraft.Client/Rendering/Chunk.cpp b/Minecraft.Client/Rendering/Chunk.cpp
index 0659ea722..e2716cb5f 100644
--- a/Minecraft.Client/Rendering/Chunk.cpp
+++ b/Minecraft.Client/Rendering/Chunk.cpp
@@ -7,6 +7,8 @@
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.h"
#include "../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h"
#include "LevelRenderer.h"
+#include "../Utils/FrameProfiler.h"
+#include
int Chunk::updates = 0;
@@ -27,6 +29,66 @@ Tesselator* Chunk::t = Tesselator::getInstance();
#endif
LevelRenderer* Chunk::levelRenderer;
+void Chunk::reconcileRenderableTileEntities(
+ const std::vector >& renderableTileEntities) {
+ int key =
+ levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
+ AUTO_VAR(it, globalRenderableTileEntities->find(key));
+ if (!renderableTileEntities.empty()) {
+ std::unordered_set currentRenderableTileEntitySet;
+ currentRenderableTileEntitySet.reserve(renderableTileEntities.size());
+ for (size_t i = 0; i < renderableTileEntities.size(); i++) {
+ currentRenderableTileEntitySet.insert(renderableTileEntities[i].get());
+ }
+
+ if (it != globalRenderableTileEntities->end()) {
+ LevelRenderer::RenderableTileEntityBucket& existingBucket =
+ it->second;
+
+ for (AUTO_VAR(it2, existingBucket.tiles.begin());
+ it2 != existingBucket.tiles.end(); it2++) {
+ TileEntity* tileEntity = (*it2).get();
+ if (currentRenderableTileEntitySet.find(tileEntity) ==
+ currentRenderableTileEntitySet.end()) {
+ (*it2)->setRenderRemoveStage(
+ TileEntity::e_RenderRemoveStageFlaggedAtChunk);
+ levelRenderer->queueRenderableTileEntityForRemoval_Locked(
+ key, tileEntity);
+ } else {
+ (*it2)->setRenderRemoveStage(
+ TileEntity::e_RenderRemoveStageKeep);
+ }
+ }
+
+ for (size_t i = 0; i < renderableTileEntities.size(); i++) {
+ renderableTileEntities[i]->setRenderRemoveStage(
+ TileEntity::e_RenderRemoveStageKeep);
+ if (existingBucket.indexByTile.find(renderableTileEntities[i].get()) ==
+ existingBucket.indexByTile.end()) {
+ levelRenderer->addRenderableTileEntity_Locked(
+ key, renderableTileEntities[i]);
+ }
+ }
+ } else {
+ for (size_t i = 0; i < renderableTileEntities.size(); i++) {
+ renderableTileEntities[i]->setRenderRemoveStage(
+ TileEntity::e_RenderRemoveStageKeep);
+ levelRenderer->addRenderableTileEntity_Locked(
+ key, renderableTileEntities[i]);
+ }
+ }
+ } else if (it != globalRenderableTileEntities->end()) {
+ for (AUTO_VAR(it2, it->second.tiles.begin());
+ it2 != it->second.tiles.end();
+ it2++) {
+ (*it2)->setRenderRemoveStage(
+ TileEntity::e_RenderRemoveStageFlaggedAtChunk);
+ levelRenderer->queueRenderableTileEntityForRemoval_Locked(key,
+ (*it2).get());
+ }
+ }
+}
+
// TODO - 4J see how input entity vector is set up and decide what way is best
// to pass this to the function
Chunk::Chunk(Level* level, LevelRenderer::rteMap& globalRenderableTileEntities,
@@ -35,7 +97,8 @@ Chunk::Chunk(Level* level, LevelRenderer::rteMap& globalRenderableTileEntities,
: globalRenderableTileEntities(&globalRenderableTileEntities),
globalRenderableTileEntities_cs(&globalRenderableTileEntities_cs) {
clipChunk->visible = false;
- bb = NULL;
+ const double g = 6;
+ bb = AABB(-g, -g, -g, XZSIZE + g, SIZE + g, XZSIZE + g);
id = 0;
this->level = level;
@@ -63,6 +126,7 @@ void Chunk::setPos(int x, int y, int z) {
clipChunk->globalIdx =
LevelRenderer::getGlobalIndexForChunk(x, y, z, level);
+ levelRenderer->setGlobalChunkConnectivity(clipChunk->globalIdx, ~0ULL);
// 4J - we're not using offsetted renderlists anymore, so just set the full
// position of this chunk into x/y/zRenderOffs where it will be used
@@ -75,21 +139,13 @@ void Chunk::setPos(int x, int y, int z) {
zRender = 0;
float g = 6.0f;
- // 4J - changed to just set the value rather than make a new one, if we've
- // already created storage
- if (bb == NULL) {
- bb = AABB::newPermanent(-g, -g, -g, XZSIZE + g, SIZE + g, XZSIZE + g);
- } else {
- // 4J MGH - bounds are relative to the position now, so the AABB will be
- // setup already, either above, or from the tesselator bounds.
- // bb->set(-g, -g, -g, SIZE+g, SIZE+g, SIZE+g);
- }
- clipChunk->aabb[0] = bb->x0 + x;
- clipChunk->aabb[1] = bb->y0 + y;
- clipChunk->aabb[2] = bb->z0 + z;
- clipChunk->aabb[3] = bb->x1 + x;
- clipChunk->aabb[4] = bb->y1 + y;
- clipChunk->aabb[5] = bb->z1 + z;
+
+ clipChunk->aabb[0] = bb.x0 + x;
+ clipChunk->aabb[1] = bb.y0 + y;
+ clipChunk->aabb[2] = bb.z0 + z;
+ clipChunk->aabb[3] = bb.x1 + x;
+ clipChunk->aabb[4] = bb.y1 + y;
+ clipChunk->aabb[5] = bb.z1 + z;
assigned = true;
@@ -229,94 +285,97 @@ void Chunk::rebuild() {
// into this category. By far the largest category of these are tiles in
// solid regions of rock.
bool empty = true;
- for (int yy = y0; yy < y1; yy++) {
- for (int zz = 0; zz < 16; zz++) {
- for (int xx = 0; xx < 16; xx++) {
- // 4J Stu - tile data is ordered in 128 blocks of full width,
- // lower 128 then upper 128
- int indexY = yy;
- int offset = 0;
- if (indexY >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
- indexY -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
- offset = Level::COMPRESSED_CHUNK_SECTION_TILES;
- }
-
- unsigned char tileId =
- tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
- (indexY + 0))];
- if (tileId > 0) empty = false;
-
- // Don't bother trying to work out neighbours for this tile if
- // we are at the edge of the chunk - apart from the very bottom
- // of the world where we shouldn't ever be able to see
- if (yy == (Level::maxBuildHeight - 1)) continue;
- if ((xx == 0) || (xx == 15)) continue;
- if ((zz == 0) || (zz == 15)) continue;
-
- // Establish whether this tile and its neighbours are all made
- // of rock, dirt, unbreakable tiles, or have already been
- // determined to meet this criteria themselves and have a tile
- // of 255 set.
- if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
- (tileId == Tile::unbreakable_Id) || (tileId == 255)))
- continue;
- tileId = tileIds[offset + (((xx - 1) << 11) | ((zz + 0) << 7) |
- (indexY + 0))];
- if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
- (tileId == Tile::unbreakable_Id) || (tileId == 255)))
- continue;
- tileId = tileIds[offset + (((xx + 1) << 11) | ((zz + 0) << 7) |
- (indexY + 0))];
- if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
- (tileId == Tile::unbreakable_Id) || (tileId == 255)))
- continue;
- tileId = tileIds[offset + (((xx + 0) << 11) | ((zz - 1) << 7) |
- (indexY + 0))];
- if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
- (tileId == Tile::unbreakable_Id) || (tileId == 255)))
- continue;
- tileId = tileIds[offset + (((xx + 0) << 11) | ((zz + 1) << 7) |
- (indexY + 0))];
- if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
- (tileId == Tile::unbreakable_Id) || (tileId == 255)))
- continue;
- // Treat the bottom of the world differently - we shouldn't ever
- // be able to look up at this, so consider tiles as invisible if
- // they are surrounded on sides other than the bottom
- if (yy > 0) {
- int indexYMinusOne = yy - 1;
- int yMinusOneOffset = 0;
- if (indexYMinusOne >=
- Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
- indexYMinusOne -=
- Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
- yMinusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
+ {
+ FRAME_PROFILE_SCOPE(ChunkPrepass);
+ for (int yy = y0; yy < y1; yy++) {
+ for (int zz = 0; zz < 16; zz++) {
+ for (int xx = 0; xx < 16; xx++) {
+ // 4J Stu - tile data is ordered in 128 blocks of full width,
+ // lower 128 then upper 128
+ int indexY = yy;
+ int offset = 0;
+ if (indexY >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
+ indexY -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
+ offset = Level::COMPRESSED_CHUNK_SECTION_TILES;
}
- tileId = tileIds[yMinusOneOffset + (((xx + 0) << 11) |
- ((zz + 0) << 7) |
- indexYMinusOne)];
- if (!((tileId == Tile::stone_Id) ||
- (tileId == Tile::dirt_Id) ||
+
+ unsigned char tileId =
+ tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
+ (indexY + 0))];
+ if (tileId > 0) empty = false;
+
+ // Don't bother trying to work out neighbours for this tile if
+ // we are at the edge of the chunk - apart from the very bottom
+ // of the world where we shouldn't ever be able to see
+ if (yy == (Level::maxBuildHeight - 1)) continue;
+ if ((xx == 0) || (xx == 15)) continue;
+ if ((zz == 0) || (zz == 15)) continue;
+
+ // Establish whether this tile and its neighbours are all made
+ // of rock, dirt, unbreakable tiles, or have already been
+ // determined to meet this criteria themselves and have a tile
+ // of 255 set.
+ if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
+ (tileId == Tile::unbreakable_Id) || (tileId == 255)))
+ continue;
+ tileId = tileIds[offset + (((xx - 1) << 11) | ((zz + 0) << 7) |
+ (indexY + 0))];
+ if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
+ (tileId == Tile::unbreakable_Id) || (tileId == 255)))
+ continue;
+ tileId = tileIds[offset + (((xx + 1) << 11) | ((zz + 0) << 7) |
+ (indexY + 0))];
+ if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
+ (tileId == Tile::unbreakable_Id) || (tileId == 255)))
+ continue;
+ tileId = tileIds[offset + (((xx + 0) << 11) | ((zz - 1) << 7) |
+ (indexY + 0))];
+ if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
+ (tileId == Tile::unbreakable_Id) || (tileId == 255)))
+ continue;
+ tileId = tileIds[offset + (((xx + 0) << 11) | ((zz + 1) << 7) |
+ (indexY + 0))];
+ if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
+ (tileId == Tile::unbreakable_Id) || (tileId == 255)))
+ continue;
+ // Treat the bottom of the world differently - we shouldn't ever
+ // be able to look up at this, so consider tiles as invisible if
+ // they are surrounded on sides other than the bottom
+ if (yy > 0) {
+ int indexYMinusOne = yy - 1;
+ int yMinusOneOffset = 0;
+ if (indexYMinusOne >=
+ Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
+ indexYMinusOne -=
+ Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
+ yMinusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
+ }
+ tileId = tileIds[yMinusOneOffset + (((xx + 0) << 11) |
+ ((zz + 0) << 7) |
+ indexYMinusOne)];
+ if (!((tileId == Tile::stone_Id) ||
+ (tileId == Tile::dirt_Id) ||
+ (tileId == Tile::unbreakable_Id) || (tileId == 255)))
+ continue;
+ }
+ int indexYPlusOne = yy + 1;
+ int yPlusOneOffset = 0;
+ if (indexYPlusOne >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
+ indexYPlusOne -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
+ yPlusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
+ }
+ tileId =
+ tileIds[yPlusOneOffset + (((xx + 0) << 11) |
+ ((zz + 0) << 7) | indexYPlusOne)];
+ if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
(tileId == Tile::unbreakable_Id) || (tileId == 255)))
continue;
- }
- int indexYPlusOne = yy + 1;
- int yPlusOneOffset = 0;
- if (indexYPlusOne >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
- indexYPlusOne -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
- yPlusOneOffset = Level::COMPRESSED_CHUNK_SECTION_TILES;
- }
- tileId =
- tileIds[yPlusOneOffset + (((xx + 0) << 11) |
- ((zz + 0) << 7) | indexYPlusOne)];
- if (!((tileId == Tile::stone_Id) || (tileId == Tile::dirt_Id) ||
- (tileId == Tile::unbreakable_Id) || (tileId == 255)))
- continue;
- // This tile is surrounded. Flag it as not requiring to be
- // rendered by setting its id to 255.
- tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
- (indexY + 0))] = 0xff;
+ // This tile is surrounded. Flag it as not requiring to be
+ // rendered by setting its id to 255.
+ tileIds[offset + (((xx + 0) << 11) | ((zz + 0) << 7) |
+ (indexY + 0))] = 0xff;
+ }
}
}
}
@@ -331,6 +390,12 @@ void Chunk::rebuild() {
RenderManager.CBuffClear(lists + currentLayer);
}
+ int globalIdx = levelRenderer->getGlobalIndexForChunk(this->x, this->y,
+ this->z, level);
+ levelRenderer->setGlobalChunkConnectivity(globalIdx, ~0ULL);
+ levelRenderer->setGlobalChunkFlag(this->x, this->y, this->z, level,
+ LevelRenderer::CHUNK_FLAG_COMPILED);
+
delete region;
delete tileRenderer;
return;
@@ -387,15 +452,8 @@ void Chunk::rebuild() {
MemSect(31);
glNewList(lists + currentLayer, GL_COMPILE);
MemSect(0);
- glPushMatrix();
glDepthMask(true); // 4J added
t->useCompactVertices(true); // 4J added
- translateToPos();
- float ss = 1.000001f;
- // 4J - have removed this scale as I don't think we
- // should need it, and have now optimised the vertex
- // shader so it doesn't do anything other than
- // translate with this matrix anyway
t->begin();
t->offset((float)(-this->x), (float)(-this->y),
(float)(-this->z));
@@ -427,7 +485,6 @@ void Chunk::rebuild() {
if (started) {
t->end();
bounds.addBounds(t->bounds); // 4J MGH - added
- glPopMatrix();
glEndList();
t->useCompactVertices(false); // 4J added
t->offset(0, 0, 0);
@@ -457,11 +514,13 @@ void Chunk::rebuild() {
// 4J MGH - added this to take the bound from the value calc'd in the
// tesselator
- if (bb) {
- bb->set(bounds.boundingBox[0], bounds.boundingBox[1],
- bounds.boundingBox[2], bounds.boundingBox[3],
- bounds.boundingBox[4], bounds.boundingBox[5]);
- }
+ bb = {bounds.boundingBox[0], bounds.boundingBox[1], bounds.boundingBox[2],
+ bounds.boundingBox[3], bounds.boundingBox[4], bounds.boundingBox[5]};
+
+ uint64_t conn = computeConnectivity(tileIds); // pass tileIds
+ int globalIdx =
+ levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
+ levelRenderer->setGlobalChunkConnectivity(globalIdx, conn);
delete tileRenderer;
delete region;
@@ -474,57 +533,8 @@ void Chunk::rebuild() {
// globally in the levelrenderer, in a hashmap with a special key made up
// from the dimension and chunk position (using same index as is used for
// global flags)
- int key =
- levelRenderer->getGlobalIndexForChunk(this->x, this->y, this->z, level);
EnterCriticalSection(globalRenderableTileEntities_cs);
- if (renderableTileEntities.size()) {
- AUTO_VAR(it, globalRenderableTileEntities->find(key));
- if (it != globalRenderableTileEntities->end()) {
- // We've got some renderable tile entities that we want associated
- // with this chunk, and an existing list of things that used to be.
- // We need to flag any that we don't need any more to be removed,
- // keep those that we do, and add any new ones
-
- // First pass - flag everything already existing to be removed
- for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
- it2++) {
- (*it2)->setRenderRemoveStage(
- TileEntity::e_RenderRemoveStageFlaggedAtChunk);
- }
-
- // Now go through the current list. If these are already in the
- // list, then unflag the remove flag. If they aren't, then add
- for (int i = 0; i < renderableTileEntities.size(); i++) {
- AUTO_VAR(it2, find(it->second.begin(), it->second.end(),
- renderableTileEntities[i]));
- if (it2 == it->second.end()) {
- (*globalRenderableTileEntities)[key].push_back(
- renderableTileEntities[i]);
- } else {
- (*it2)->setRenderRemoveStage(
- TileEntity::e_RenderRemoveStageKeep);
- }
- }
- } else {
- // Easy case - nothing already existing for this chunk. Add them all
- // in.
- for (int i = 0; i < renderableTileEntities.size(); i++) {
- (*globalRenderableTileEntities)[key].push_back(
- renderableTileEntities[i]);
- }
- }
- } else {
- // Another easy case - we don't want any renderable tile entities
- // associated with this chunk. Flag all to be removed.
- AUTO_VAR(it, globalRenderableTileEntities->find(key));
- if (it != globalRenderableTileEntities->end()) {
- for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
- it2++) {
- (*it2)->setRenderRemoveStage(
- TileEntity::e_RenderRemoveStageFlaggedAtChunk);
- }
- }
- }
+ reconcileRenderableTileEntities(renderableTileEntities);
LeaveCriticalSection(globalRenderableTileEntities_cs);
PIXEndNamedEvent();
@@ -559,17 +569,157 @@ float Chunk::squishedDistanceToSqr(std::shared_ptr player) {
return xd * xd + yd * yd + zd * zd;
}
+uint64_t Chunk::computeConnectivity(const uint8_t* tileIds) {
+ const int W = 16;
+ const int H = 16;
+ const int VOLUME = W * H * W;
+
+ auto idx = [&](int x, int y, int z) -> int {
+ return y * W * W + z * W + x;
+ };
+
+ auto isOpen = [&](int lx, int ly, int lz) -> bool {
+ int worldY = this->y + ly;
+ int offset = 0;
+ int indexY = worldY;
+ if (indexY >= Level::COMPRESSED_CHUNK_SECTION_HEIGHT) {
+ indexY -= Level::COMPRESSED_CHUNK_SECTION_HEIGHT;
+ offset = Level::COMPRESSED_CHUNK_SECTION_TILES;
+ }
+
+ uint8_t tileId = tileIds[offset + ((lx << 11) | (lz << 7) | indexY)];
+
+ if (tileId == 0) return true; // air
+ if (tileId == 0xFF) return false; // hidden tile (yeah)
+
+ Tile* t = Tile::tiles[tileId];
+ return (t == nullptr) || !t->isSolidRender();
+ };
+
+ uint8_t visited[6][512];
+ memset(visited, 0, sizeof(visited));
+
+ static const int FX[6] = {1, -1, 0, 0, 0, 0};
+ static const int FY[6] = {0, 0, 1, -1, 0, 0};
+ static const int FZ[6] = {0, 0, 0, 0, 1, -1};
+
+ struct Cell {
+ int8_t x, y, z;
+ };
+ static thread_local std::vector| queue;
+
+ uint64_t result = 0;
+
+ for (int entryFace = 0; entryFace < 6; entryFace++) {
+ uint8_t* vis = visited[entryFace];
+ queue.clear();
+ int x0s, x1s, y0s, y1s, z0s, z1s;
+ switch (entryFace) {
+ case 0:
+ x0s = W - 1;
+ x1s = W - 1;
+ y0s = 0;
+ y1s = H - 1;
+ z0s = 0;
+ z1s = W - 1;
+ break; // +X
+ case 1:
+ x0s = 0;
+ x1s = 0;
+ y0s = 0;
+ y1s = H - 1;
+ z0s = 0;
+ z1s = W - 1;
+ break; // -X
+ case 2:
+ x0s = 0;
+ x1s = W - 1;
+ y0s = H - 1;
+ y1s = H - 1;
+ z0s = 0;
+ z1s = W - 1;
+ break; // +Y
+ case 3:
+ x0s = 0;
+ x1s = W - 1;
+ y0s = 0;
+ y1s = 0;
+ z0s = 0;
+ z1s = W - 1;
+ break; // -Y
+ case 4:
+ x0s = 0;
+ x1s = W - 1;
+ y0s = 0;
+ y1s = H - 1;
+ z0s = W - 1;
+ z1s = W - 1;
+ break; // +Z
+ case 5:
+ x0s = 0;
+ x1s = W - 1;
+ y0s = 0;
+ y1s = H - 1;
+ z0s = 0;
+ z1s = 0;
+ break; // -Z
+ default:
+ continue;
+ }
+
+ for (int sy = y0s; sy <= y1s; sy++)
+ for (int sz = z0s; sz <= z1s; sz++)
+ for (int sx = x0s; sx <= x1s; sx++) {
+ if (!isOpen(sx, sy, sz)) continue;
+ int i = idx(sx, sy, sz);
+ if (vis[i >> 3] & (1 << (i & 7))) continue;
+ vis[i >> 3] |= (1 << (i & 7));
+ queue.push_back({(int8_t)sx, (int8_t)sy, (int8_t)sz});
+ }
+
+ for (int qi = 0; qi < (int)queue.size(); qi++) {
+ Cell cur = queue[qi];
+
+ for (int nb = 0; nb < 6; nb++) {
+ int nx = cur.x + FX[nb];
+ int ny = cur.y + FY[nb];
+ int nz = cur.z + FZ[nb];
+
+ // entry exit conn
+ if (nx < 0 || nx >= W || ny < 0 || ny >= H || nz < 0 ||
+ nz >= W) {
+ // nb IS the exit face because FX,FY,FZ are aligned
+ result |= ((uint64_t)1 << (entryFace * 6 + nb));
+ continue;
+ }
+
+ if (!isOpen(nx, ny, nz)) continue;
+
+ int i = idx(nx, ny, nz);
+ if (vis[i >> 3] & (1 << (i & 7))) continue;
+ vis[i >> 3] |= (1 << (i & 7));
+ queue.push_back({(int8_t)nx, (int8_t)ny, (int8_t)nz});
+ }
+ }
+ }
+
+ return result;
+}
void Chunk::reset() {
if (assigned) {
+ int oldKey = -1;
+ bool retireRenderableTileEntities = false;
+
EnterCriticalSection(&levelRenderer->m_csDirtyChunks);
+ oldKey = levelRenderer->getGlobalIndexForChunk(x, y, z, level);
unsigned char refCount =
levelRenderer->decGlobalChunkRefCount(x, y, z, level);
assigned = false;
// printf("\t\t [dec] refcount %d at %d, %d,
//%d\n",refCount,x,y,z);
- if (refCount == 0) {
- int lists =
- levelRenderer->getGlobalIndexForChunk(x, y, z, level) * 2;
+ if (refCount == 0 && oldKey != -1) {
+ retireRenderableTileEntities = true;
+ int lists = oldKey * 2;
if (lists >= 0) {
lists += levelRenderer->chunkLists;
for (int i = 0; i < 2; i++) {
@@ -581,6 +731,10 @@ void Chunk::reset() {
}
}
LeaveCriticalSection(&levelRenderer->m_csDirtyChunks);
+
+ if (retireRenderableTileEntities) {
+ levelRenderer->retireRenderableTileEntitiesForChunkKey(oldKey);
+ }
}
clipChunk->visible = false;
@@ -603,7 +757,11 @@ int Chunk::getList(int layer) {
return -1;
}
-void Chunk::cull(Culler* culler) { clipChunk->visible = culler->isVisible(bb); }
+void Chunk::cull(Culler* culler) {
+ if (clipChunk->visible) {
+ clipChunk->visible = culler->isVisible(&bb);
+ }
+}
void Chunk::renderBB() {
// glCallList(lists + 2); // 4J - removed - TODO put back in
@@ -634,8 +792,6 @@ void Chunk::clearDirty() {
#endif
}
-Chunk::~Chunk() { delete bb; }
-
bool Chunk::emptyFlagSet(int layer) {
return levelRenderer->getGlobalChunkFlag(
x, y, z, level, LevelRenderer::CHUNK_FLAG_EMPTY0, layer);
diff --git a/Minecraft.Client/Rendering/Chunk.h b/Minecraft.Client/Rendering/Chunk.h
index 2a1896ed3..ea24723b7 100644
--- a/Minecraft.Client/Rendering/Chunk.h
+++ b/Minecraft.Client/Rendering/Chunk.h
@@ -46,9 +46,9 @@ public:
int xRenderOffs, yRenderOffs, zRenderOffs;
int xm, ym, zm;
- AABB* bb;
+ AABB bb;
ClipChunk* clipChunk;
-
+ uint64_t computeConnectivity(const uint8_t* tileIds);
int id;
// public:
// std::vector > renderableTileEntities;
@@ -69,6 +69,8 @@ public:
private:
void translateToPos();
+ void reconcileRenderableTileEntities(
+ const std::vector >& renderableTileEntities);
public:
void makeCopyForRebuild(Chunk* source);
@@ -85,5 +87,4 @@ public:
void setDirty();
void clearDirty(); // 4J added
bool emptyFlagSet(int layer);
- ~Chunk();
};
diff --git a/Minecraft.Client/Rendering/Cube.cpp b/Minecraft.Client/Rendering/Cube.cpp
index 259eb9cac..b091fa158 100644
--- a/Minecraft.Client/Rendering/Cube.cpp
+++ b/Minecraft.Client/Rendering/Cube.cpp
@@ -1,18 +1,9 @@
#include "../Platform/stdafx.h"
#include "Models/Model.h"
#include "Models/ModelPart.h"
+#include "Rendering/Vertex.h"
#include "Cube.h"
-
-// 4J - added - helper function to set up vertex arrays
-VertexArray Cube::VertexArray4(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3) {
- VertexArray ret = VertexArray(4);
- ret[0] = v0;
- ret[1] = v1;
- ret[2] = v2;
- ret[3] = v3;
-
- return ret;
-}
+#include
// void Cube::addBox(float x0, float y0, float z0, int w, int h, int d, float g)
Cube::Cube(ModelPart* modelPart, int xTexOffs, int yTexOffs, float x0, float y0,
@@ -25,17 +16,12 @@ Cube::Cube(ModelPart* modelPart, int xTexOffs, int yTexOffs, float x0, float y0,
z0(z0),
x1(x0 + w),
y1(y0 + h),
- z1(z0 + d) {
- // this->x0 = x0;
- // this->y0 = y0;
- // this->z0 = z0;
- // this->x1 = x0 + w;
- // this->y1 = y0 + h;
- // this->z1 = z0 + d;
-
- vertices = VertexArray(8);
- polygons = PolygonArray(6);
-
+ z1(z0 + d),
+ vertices({Vertex{0, 0, 0, 0, 0}, Vertex{0, 0, 0, 0, 0},
+ Vertex{0, 0, 0, 0, 0}, Vertex{0, 0, 0, 0, 0},
+ Vertex{0, 0, 0, 0, 0}, Vertex{0, 0, 0, 0, 0},
+ Vertex{0, 0, 0, 0, 0}, Vertex{0, 0, 0, 0, 0}}),
+ polygons({}) {
float x1 = x0 + w;
float y1 = y0 + h;
float z1 = z0 + d;
@@ -53,15 +39,15 @@ Cube::Cube(ModelPart* modelPart, int xTexOffs, int yTexOffs, float x0, float y0,
x0 = tmp;
}
- Vertex* u0 = new Vertex(x0, y0, z0, 0, 0);
- Vertex* u1 = new Vertex(x1, y0, z0, 0, 8);
- Vertex* u2 = new Vertex(x1, y1, z0, 8, 8);
- Vertex* u3 = new Vertex(x0, y1, z0, 8, 0);
+ const Vertex u0 = Vertex(x0, y0, z0, 0, 0);
+ const Vertex u1 = Vertex(x1, y0, z0, 0, 8);
+ const Vertex u2 = Vertex(x1, y1, z0, 8, 8);
+ const Vertex u3 = Vertex(x0, y1, z0, 8, 0);
- Vertex* l0 = new Vertex(x0, y0, z1, 0, 0);
- Vertex* l1 = new Vertex(x1, y0, z1, 0, 8);
- Vertex* l2 = new Vertex(x1, y1, z1, 8, 8);
- Vertex* l3 = new Vertex(x0, y1, z1, 8, 0);
+ const Vertex l0 = Vertex(x0, y0, z1, 0, 0);
+ const Vertex l1 = Vertex(x1, y0, z1, 0, 8);
+ const Vertex l2 = Vertex(x1, y1, z1, 8, 8);
+ const Vertex l3 = Vertex(x0, y1, z1, 8, 0);
vertices[0] = u0;
vertices[1] = u1;
@@ -73,56 +59,55 @@ Cube::Cube(ModelPart* modelPart, int xTexOffs, int yTexOffs, float x0, float y0,
vertices[7] = l3;
// 4J - added ability to mask individual faces
- int faceCount = 0;
+ faceCount = 0;
if (faceMask & 1)
- polygons[faceCount++] =
- new _Polygon(VertexArray4(l1, u1, u2, l2), xTexOffs + d + w,
- yTexOffs + d, xTexOffs + d + w + d, yTexOffs + d + h,
- modelPart->xTexSize, modelPart->yTexSize); // Right
+ polygons[faceCount++] = _Polygon(
+ std::array{l1, u1, u2, l2}, xTexOffs + d + w,
+ yTexOffs + d, xTexOffs + d + w + d, yTexOffs + d + h,
+ modelPart->xTexSize, modelPart->yTexSize); // Right
if (faceMask & 2)
- polygons[faceCount++] =
- new _Polygon(VertexArray4(u0, l0, l3, u3), xTexOffs + 0,
- yTexOffs + d, xTexOffs + d, yTexOffs + d + h,
- modelPart->xTexSize, modelPart->yTexSize); // Left
+ polygons[faceCount++] = _Polygon(
+ std::array{u0, l0, l3, u3}, xTexOffs + 0,
+ yTexOffs + d, xTexOffs + d, yTexOffs + d + h, modelPart->xTexSize,
+ modelPart->yTexSize); // Left
if (faceMask & 4)
- polygons[faceCount++] =
- new _Polygon(VertexArray4(l1, l0, u0, u1), xTexOffs + d,
- yTexOffs + 0, xTexOffs + d + w, yTexOffs + d,
- modelPart->xTexSize, modelPart->yTexSize); // Up
+ polygons[faceCount++] = _Polygon(
+ std::array{l1, l0, u0, u1}, xTexOffs + d,
+ yTexOffs + 0, xTexOffs + d + w, yTexOffs + d, modelPart->xTexSize,
+ modelPart->yTexSize); // Up
if (bFlipPoly3UVs) {
if (faceMask & 8)
- polygons[faceCount++] =
- new _Polygon(VertexArray4(u2, u3, l3, l2), xTexOffs + d + w,
- yTexOffs + 0, xTexOffs + d + w + w, yTexOffs + d,
- modelPart->xTexSize, modelPart->yTexSize); // Down
+ polygons[faceCount++] = _Polygon(
+ std::array{u2, u3, l3, l2}, xTexOffs + d + w,
+ yTexOffs + 0, xTexOffs + d + w + w, yTexOffs + d,
+ modelPart->xTexSize, modelPart->yTexSize); // Down
} else {
if (faceMask & 8)
- polygons[faceCount++] =
- new _Polygon(VertexArray4(u2, u3, l3, l2), xTexOffs + d + w,
- yTexOffs + d, xTexOffs + d + w + w, yTexOffs + 0,
- modelPart->xTexSize, modelPart->yTexSize); // Down
+ polygons[faceCount++] = _Polygon(
+ std::array{u2, u3, l3, l2}, xTexOffs + d + w,
+ yTexOffs + d, xTexOffs + d + w + w, yTexOffs + 0,
+ modelPart->xTexSize, modelPart->yTexSize); // Down
}
if (faceMask & 16)
polygons[faceCount++] =
- new _Polygon(VertexArray4(u1, u0, u3, u2), xTexOffs + d,
- yTexOffs + d, xTexOffs + d + w, yTexOffs + d + h,
- modelPart->xTexSize, modelPart->yTexSize); // Front
+ _Polygon(std::array{u1, u0, u3, u2}, xTexOffs + d,
+ yTexOffs + d, xTexOffs + d + w, yTexOffs + d + h,
+ modelPart->xTexSize, modelPart->yTexSize); // Front
if (faceMask & 32)
- polygons[faceCount++] = new _Polygon(
- VertexArray4(l0, l1, l2, l3), xTexOffs + d + w + d, yTexOffs + d,
- xTexOffs + d + w + d + w, yTexOffs + d + h, modelPart->xTexSize,
+ polygons[faceCount++] = _Polygon(
+ std::array{l0, l1, l2, l3}, xTexOffs + d + w + d,
+ yTexOffs + d, xTexOffs + d + w + d + w, yTexOffs + d + h,
+ modelPart->xTexSize,
modelPart->yTexSize); // Back
- polygons.length = faceCount;
if (modelPart->bMirror) {
- for (unsigned int i = 0; i < polygons.length; i++)
- polygons[i]->mirror();
+ for (unsigned int i = 0; i < polygons.size(); i++) polygons[i].mirror();
}
}
void Cube::render(Tesselator* t, float scale) {
- for (int i = 0; i < polygons.length; i++) {
- polygons[i]->render(t, scale);
+ for (int i = 0; i < faceCount; i++) {
+ polygons[i].render(t, scale);
}
}
diff --git a/Minecraft.Client/Rendering/Cube.h b/Minecraft.Client/Rendering/Cube.h
index 549672e45..9075d0950 100644
--- a/Minecraft.Client/Rendering/Cube.h
+++ b/Minecraft.Client/Rendering/Cube.h
@@ -1,4 +1,6 @@
#pragma once
+#include
+#include
#include "../../Minecraft.World/Util/ArrayWithLength.h"
#include "Vertex.h"
#include "Polygon.h"
@@ -7,8 +9,9 @@ class Model;
class Cube {
private:
- VertexArray vertices;
- PolygonArray polygons;
+ std::array vertices;
+ std::array<_Polygon, 6> polygons;
+ uint8_t faceCount;
public:
const float x0, y0, z0, x1, y1, z1;
@@ -19,11 +22,6 @@ public:
float z0, int w, int h, int d, float g, int faceMask = 63,
bool bFlipPoly3UVs = false); // 4J - added faceMask
-private:
- VertexArray VertexArray4(Vertex* v0, Vertex* v1, Vertex* v2,
- Vertex* v3); // 4J added
-
-public:
void render(Tesselator* t, float scale);
Cube* setId(const std::wstring& id);
};
diff --git a/Minecraft.Client/Rendering/Culling/DirtyChunkSorter.cpp b/Minecraft.Client/Rendering/Culling/DirtyChunkSorter.cpp
index 9901135a6..ed12da6ef 100644
--- a/Minecraft.Client/Rendering/Culling/DirtyChunkSorter.cpp
+++ b/Minecraft.Client/Rendering/Culling/DirtyChunkSorter.cpp
@@ -23,4 +23,4 @@ bool DirtyChunkSorter::operator()(const Chunk* c0, const Chunk* c1) const {
if (d0 > d1) return true;
return c0->id >= c1->id; // 4J - was c0.id < c1.id ? 1 : -1
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/EntityRenderers/EntityRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/EntityRenderer.cpp
index 9b4d7bda3..86c76a334 100644
--- a/Minecraft.Client/Rendering/EntityRenderers/EntityRenderer.cpp
+++ b/Minecraft.Client/Rendering/EntityRenderers/EntityRenderer.cpp
@@ -91,7 +91,7 @@ void EntityRenderer::renderFlame(std::shared_ptr e, double x, double y,
float xo = 0.0f;
float h = e->bbHeight / s;
- float yo = (float)(e->y - e->bb->y0);
+ float yo = (float)(e->y - e->bb.y0);
glRotatef(-entityRenderDispatcher->playerRotY, 0, 1, 0);
@@ -394,4 +394,4 @@ void EntityRenderer::registerTerrainTextures(IconRegister* iconRegister) {}
ResourceLocation* EntityRenderer::getTextureLocation(
std::shared_ptr mob) {
return NULL;
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/EntityRenderers/FireballRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/FireballRenderer.cpp
index 87251b8c9..fd1dce90c 100644
--- a/Minecraft.Client/Rendering/EntityRenderers/FireballRenderer.cpp
+++ b/Minecraft.Client/Rendering/EntityRenderers/FireballRenderer.cpp
@@ -78,7 +78,7 @@ void FireballRenderer::renderFlame(std::shared_ptr e, double x,
// float yo = 0.0f;
float h = e->bbHeight / s;
- float yo = (float)(e->y - e->bb->y0);
+ float yo = (float)(e->y - e->bb.y0);
// glRotatef(-entityRenderDispatcher->playerRotY, 0, 1, 0);
@@ -118,4 +118,4 @@ void FireballRenderer::renderFlame(std::shared_ptr e, double x,
ResourceLocation* FireballRenderer::getTextureLocation(
std::shared_ptr mob) {
return &TextureAtlas::LOCATION_ITEMS;
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/EntityRenderers/FishingHookRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/FishingHookRenderer.cpp
index 9d4b7e0f1..1bd178e64 100644
--- a/Minecraft.Client/Rendering/EntityRenderers/FishingHookRenderer.cpp
+++ b/Minecraft.Client/Rendering/EntityRenderers/FishingHookRenderer.cpp
@@ -58,22 +58,22 @@ void FishingHookRenderer::render(std::shared_ptr _hook, double x,
float swing = hook->owner->getAttackAnim(a);
float swing2 = (float)Mth::sin(sqrt(swing) * PI);
- Vec3* vv = Vec3::newTemp(-0.5, 0.03, 0.8);
- vv->xRot(-(hook->owner->xRotO +
- (hook->owner->xRot - hook->owner->xRotO) * a) *
- PI / 180);
- vv->yRot(-(hook->owner->yRotO +
- (hook->owner->yRot - hook->owner->yRotO) * a) *
- PI / 180);
- vv->yRot(swing2 * 0.5f);
- vv->xRot(-swing2 * 0.7f);
+ Vec3 vv(-0.5, 0.03, 0.8);
+ vv.xRot(-(hook->owner->xRotO +
+ (hook->owner->xRot - hook->owner->xRotO) * a) *
+ PI / 180);
+ vv.yRot(-(hook->owner->yRotO +
+ (hook->owner->yRot - hook->owner->yRotO) * a) *
+ PI / 180);
+ vv.yRot(swing2 * 0.5f);
+ vv.xRot(-swing2 * 0.7f);
double xp =
- hook->owner->xo + (hook->owner->x - hook->owner->xo) * a + vv->x;
+ hook->owner->xo + (hook->owner->x - hook->owner->xo) * a + vv.x;
double yp =
- hook->owner->yo + (hook->owner->y - hook->owner->yo) * a + vv->y;
+ hook->owner->yo + (hook->owner->y - hook->owner->yo) * a + vv.y;
double zp =
- hook->owner->zo + (hook->owner->z - hook->owner->zo) * a + vv->z;
+ hook->owner->zo + (hook->owner->z - hook->owner->zo) * a + vv.z;
double yOffset = hook->owner == std::dynamic_pointer_cast(
Minecraft::GetInstance()->player)
? 0
diff --git a/Minecraft.Client/Rendering/EntityRenderers/ItemRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/ItemRenderer.cpp
index ec95f67fa..4662c2632 100644
--- a/Minecraft.Client/Rendering/EntityRenderers/ItemRenderer.cpp
+++ b/Minecraft.Client/Rendering/EntityRenderers/ItemRenderer.cpp
@@ -351,18 +351,19 @@ void ItemRenderer::renderGuiItem(Font* font, Textures* textures,
glPushMatrix();
// 4J - original code left here for reference
// 4jcraft: original code reused for proper lighting
- glTranslatef((float)(x), (float)(y), 0.0f);
- glScalef(fScaleX, fScaleY, 1.0f);
- glTranslatef(-2.0f,3.0f, -3.0f + blitOffset);
- glScalef(10.0f, 10.0f, 10.0f);
+ glTranslatef((float)(x), (float)(y), 0.0f);
+ glScalef(fScaleX, fScaleY, 1.0f);
+ glTranslatef(-2.0f, 3.0f, -3.0f + blitOffset);
+ glScalef(10.0f, 10.0f, 10.0f);
glTranslatef(1.0f, 0.5f, 8.0f);
glScalef(1.0f, 1.0f, -1.0f);
glRotatef(180.0f + 30.0f, 1.0f, 0.0f, 0.0f);
glRotatef(45.0f, 0.0f, 1.0f, 0.0f);
- // 4J-PB - pass the alpha value in - the grass block
- // render has the top surface coloured differently to
- // the rest of the block
+ // 4J-PB - pass the alpha value in - the grass block
+ // render has the top surface coloured differently to
+ // the rest of the block
glRotatef(-90.0f, 0.0f, 1.0f, 0.0f);
+
tileRenderer->renderTile(tile, itemAuxValue, 1, fAlpha, useCompiled);
glPopMatrix();
diff --git a/Minecraft.Client/Rendering/EntityRenderers/LivingEntityRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/LivingEntityRenderer.cpp
index 81f24cc87..33e7ba4ab 100644
--- a/Minecraft.Client/Rendering/EntityRenderers/LivingEntityRenderer.cpp
+++ b/Minecraft.Client/Rendering/EntityRenderers/LivingEntityRenderer.cpp
@@ -588,4 +588,4 @@ void LivingEntityRenderer::renderNameTag(std::shared_ptr mob,
glDisable(GL_BLEND);
glColor4f(1, 1, 1, 1);
glPopMatrix();
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/EntityRenderers/MinecartRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/MinecartRenderer.cpp
index f1d7cd569..5868a654e 100644
--- a/Minecraft.Client/Rendering/EntityRenderers/MinecartRenderer.cpp
+++ b/Minecraft.Client/Rendering/EntityRenderers/MinecartRenderer.cpp
@@ -1,5 +1,6 @@
#include "../../Platform/stdafx.h"
#include "MinecartRenderer.h"
+#include
#include "../Models/MinecartModel.h"
#include "../../Textures/TextureAtlas.h"
#include "../../../Minecraft.World/Headers/net.minecraft.world.entity.item.h"
@@ -40,26 +41,27 @@ void MinecartRenderer::render(std::shared_ptr _cart, double x, double y,
double r = 0.3f;
- Vec3* p = cart->getPos(xx, yy, zz);
+ std::optional p = cart->getPos(xx, yy, zz);
float xRot = cart->xRotO + (cart->xRot - cart->xRotO) * a;
- if (p != NULL) {
- Vec3* p0 = cart->getPosOffs(xx, yy, zz, r);
- Vec3* p1 = cart->getPosOffs(xx, yy, zz, -r);
- if (p0 == NULL) p0 = p;
- if (p1 == NULL) p1 = p;
+ if (p.has_value()) {
+ auto p0 = cart->getPosOffs(xx, yy, zz, r);
+ auto p1 = cart->getPosOffs(xx, yy, zz, -r);
+ if (!p0.has_value()) p0 = p;
+ if (!p1.has_value()) p1 = p;
x += p->x - xx;
y += (p0->y + p1->y) / 2 - yy;
z += p->z - zz;
- Vec3* dir = p1->add(-p0->x, -p0->y, -p0->z);
- if (dir->length() == 0) {
+ Vec3 dir(-p0->x, -p0->y, -p0->z);
+ dir = dir.add(p1->x, p1->y, p1->z);
+ if (dir.length() == 0) {
} else {
- dir = dir->normalize();
- rot = (float)(atan2(dir->z, dir->x) * 180 / PI);
- xRot = (float)(atan(dir->y) * 73);
+ dir = dir.normalize();
+ rot = (float)(atan2(dir.z, dir.x) * 180 / PI);
+ xRot = (float)(atan(dir.y) * 73);
}
}
glTranslatef((float)x, (float)y, (float)z);
@@ -146,4 +148,4 @@ void MinecartRenderer::renderMinecartContents(std::shared_ptr cart,
glPushMatrix();
renderer->renderTile(tile, tileData, brightness);
glPopMatrix();
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/EntityRenderers/TileRenderer.cpp b/Minecraft.Client/Rendering/EntityRenderers/TileRenderer.cpp
index f7a2f2e2e..90d2e0854 100644
--- a/Minecraft.Client/Rendering/EntityRenderers/TileRenderer.cpp
+++ b/Minecraft.Client/Rendering/EntityRenderers/TileRenderer.cpp
@@ -1,6 +1,7 @@
#include "../../Platform/stdafx.h"
#include "TileRenderer.h"
+#include
#include "../GameRenderer.h"
#include "../../Minecraft.h"
#include "../../Textures/Textures.h"
@@ -10,6 +11,7 @@
#include "../../../Minecraft.World/Headers/net.minecraft.h"
#include "../../../Minecraft.World/Headers/net.minecraft.world.h"
#include "../Tesselator.h"
+#include "../../Utils/FrameProfiler.h"
#include "EntityTileRenderer.h"
#include "../../GameState/Options.h"
@@ -258,7 +260,12 @@ bool TileRenderer::tesselateInWorld(
{
Tesselator* t = Tesselator::getInstance();
int shape = tt->getRenderShape();
- tt->updateShape(level, x, y, z, forceData, forceEntity);
+ if (shape == Tile::SHAPE_BLOCK) {
+ FRAME_PROFILE_SCOPE(ChunkBlockShape);
+ tt->updateShape(level, x, y, z, forceData, forceEntity);
+ } else {
+ tt->updateShape(level, x, y, z, forceData, forceEntity);
+ }
// AP - now that the culling is done earlier we don't need to call setShape
// until later on (only for SHAPE_BLOCK)
if (shape != Tile::SHAPE_BLOCK) {
@@ -269,6 +276,11 @@ bool TileRenderer::tesselateInWorld(
bool retVal = false;
switch (shape) {
case Tile::SHAPE_BLOCK: {
+ {
+ FRAME_PROFILE_SCOPE(ChunkBlockShape);
+ setShape(tt);
+ }
+
// 4J - added these faceFlags so we can detect whether this block is
// going to have no visible faces and early out the original code
// checked noCulling and shouldRenderFace directly where faceFlags
@@ -281,6 +293,7 @@ bool TileRenderer::tesselateInWorld(
if (noCulling) {
faceFlags = 0x3f;
} else {
+ FRAME_PROFILE_SCOPE(ChunkBlockFaceCull);
// these block types can take advantage of a faster version of
// shouldRenderFace there are others but this is an easy check
// which covers the majority Note: This now covers rock, grass,
@@ -310,9 +323,6 @@ bool TileRenderer::tesselateInWorld(
break;
}
- // now we need to set the shape
- setShape(tt);
-
retVal = tesselateBlockInWorld(tt, x, y, z, faceFlags);
} break;
case Tile::SHAPE_TREE:
@@ -1037,9 +1047,8 @@ bool TileRenderer::tesselateAnvilInWorld(AnvilTile* tt, int x, int y, int z,
float TileRenderer::tesselateAnvilPiece(AnvilTile* tt, int x, int y, int z,
int part, float bottom, float width,
- float height, float length,
- bool rotate, bool render,
- int data) {
+ float height, float length, bool rotate,
+ bool render, int data) {
if (rotate) {
float swap = width;
width = length;
@@ -1810,58 +1819,58 @@ bool TileRenderer::tesselateLeverInWorld(Tile* tt, int x, int y, int z) {
float u1 = tex->getU1(true);
float v1 = tex->getV1(true);
- Vec3* corners[8];
+ std::array corners;
float xv = 1.0f / 16.0f;
float zv = 1.0f / 16.0f;
float yv = 10.0f / 16.0f;
- corners[0] = Vec3::newTemp(-xv, -0, -zv);
- corners[1] = Vec3::newTemp(+xv, -0, -zv);
- corners[2] = Vec3::newTemp(+xv, -0, +zv);
- corners[3] = Vec3::newTemp(-xv, -0, +zv);
- corners[4] = Vec3::newTemp(-xv, +yv, -zv);
- corners[5] = Vec3::newTemp(+xv, +yv, -zv);
- corners[6] = Vec3::newTemp(+xv, +yv, +zv);
- corners[7] = Vec3::newTemp(-xv, +yv, +zv);
+ corners[0] = Vec3(-xv, -0, -zv);
+ corners[1] = Vec3(+xv, -0, -zv);
+ corners[2] = Vec3(+xv, -0, +zv);
+ corners[3] = Vec3(-xv, -0, +zv);
+ corners[4] = Vec3(-xv, +yv, -zv);
+ corners[5] = Vec3(+xv, +yv, -zv);
+ corners[6] = Vec3(+xv, +yv, +zv);
+ corners[7] = Vec3(-xv, +yv, +zv);
for (int i = 0; i < 8; i++) {
if (flipped) {
- corners[i]->z -= 1 / 16.0f;
- corners[i]->xRot(40 * PI / 180);
+ corners[i].z -= 1 / 16.0f;
+ corners[i].xRot(40 * PI / 180);
} else {
- corners[i]->z += 1 / 16.0f;
- corners[i]->xRot(-40 * PI / 180);
+ corners[i].z += 1 / 16.0f;
+ corners[i].xRot(-40 * PI / 180);
}
if (dir == 0 || dir == 7) {
- corners[i]->zRot(180 * PI / 180);
+ corners[i].zRot(180 * PI / 180);
}
if (dir == 6 || dir == 0) {
- corners[i]->yRot(90 * PI / 180);
+ corners[i].yRot(90 * PI / 180);
}
if (dir > 0 && dir < 5) {
- corners[i]->y -= 6 / 16.0f;
- corners[i]->xRot(90 * PI / 180);
+ corners[i].y -= 6 / 16.0f;
+ corners[i].xRot(90 * PI / 180);
- if (dir == 4) corners[i]->yRot(0 * PI / 180);
- if (dir == 3) corners[i]->yRot(180 * PI / 180);
- if (dir == 2) corners[i]->yRot(90 * PI / 180);
- if (dir == 1) corners[i]->yRot(-90 * PI / 180);
+ if (dir == 4) corners[i].yRot(0 * PI / 180);
+ if (dir == 3) corners[i].yRot(180 * PI / 180);
+ if (dir == 2) corners[i].yRot(90 * PI / 180);
+ if (dir == 1) corners[i].yRot(-90 * PI / 180);
- corners[i]->x += x + 0.5;
- corners[i]->y += y + 8 / 16.0f;
- corners[i]->z += z + 0.5;
+ corners[i].x += x + 0.5;
+ corners[i].y += y + 8 / 16.0f;
+ corners[i].z += z + 0.5;
} else if (dir == 0 || dir == 7) {
- corners[i]->x += x + 0.5;
- corners[i]->y += y + 14 / 16.0f;
- corners[i]->z += z + 0.5;
+ corners[i].x += x + 0.5;
+ corners[i].y += y + 14 / 16.0f;
+ corners[i].z += z + 0.5;
} else {
- corners[i]->x += x + 0.5;
- corners[i]->y += y + 2 / 16.0f;
- corners[i]->z += z + 0.5;
+ corners[i].x += x + 0.5;
+ corners[i].y += y + 2 / 16.0f;
+ corners[i].z += z + 0.5;
}
}
- Vec3 *c0 = NULL, *c1 = NULL, *c2 = NULL, *c3 = NULL;
+ Vec3 c0, c1, c2, c3;
for (int i = 0; i < 6; i++) {
if (i == 0) {
u0 = tex->getU(7, true);
@@ -1905,13 +1914,13 @@ bool TileRenderer::tesselateLeverInWorld(Tile* tt, int x, int y, int z) {
c2 = corners[7];
c3 = corners[4];
}
- t->vertexUV((float)(c0->x), (float)(c0->y), (float)(c0->z), (float)(u0),
+ t->vertexUV((float)(c0.x), (float)(c0.y), (float)(c0.z), (float)(u0),
(float)(v1));
- t->vertexUV((float)(c1->x), (float)(c1->y), (float)(c1->z), (float)(u1),
+ t->vertexUV((float)(c1.x), (float)(c1.y), (float)(c1.z), (float)(u1),
(float)(v1));
- t->vertexUV((float)(c2->x), (float)(c2->y), (float)(c2->z), (float)(u1),
+ t->vertexUV((float)(c2.x), (float)(c2.y), (float)(c2.z), (float)(u1),
(float)(v0));
- t->vertexUV((float)(c3->x), (float)(c3->y), (float)(c3->z), (float)(u0),
+ t->vertexUV((float)(c3.x), (float)(c3.y), (float)(c3.z), (float)(u0),
(float)(v0));
}
return true;
@@ -1969,46 +1978,46 @@ bool TileRenderer::tesselateTripwireSourceInWorld(Tile* tt, int x, int y,
double u1 = tex->getU1();
double v1 = tex->getV1();
- Vec3* corners[8];
+ std::array corners;
float stickWidth = 0.75f / 16.0f;
float stickHeight = 0.75f / 16.0f;
float stickLength = 5 / 16.0f;
- corners[0] = Vec3::newTemp(-stickWidth, -0, -stickHeight);
- corners[1] = Vec3::newTemp(+stickWidth, -0, -stickHeight);
- corners[2] = Vec3::newTemp(+stickWidth, -0, +stickHeight);
- corners[3] = Vec3::newTemp(-stickWidth, -0, +stickHeight);
- corners[4] = Vec3::newTemp(-stickWidth, +stickLength, -stickHeight);
- corners[5] = Vec3::newTemp(+stickWidth, +stickLength, -stickHeight);
- corners[6] = Vec3::newTemp(+stickWidth, +stickLength, +stickHeight);
- corners[7] = Vec3::newTemp(-stickWidth, +stickLength, +stickHeight);
+ corners[0] = Vec3(-stickWidth, -0, -stickHeight);
+ corners[1] = Vec3(+stickWidth, -0, -stickHeight);
+ corners[2] = Vec3(+stickWidth, -0, +stickHeight);
+ corners[3] = Vec3(-stickWidth, -0, +stickHeight);
+ corners[4] = Vec3(-stickWidth, +stickLength, -stickHeight);
+ corners[5] = Vec3(+stickWidth, +stickLength, -stickHeight);
+ corners[6] = Vec3(+stickWidth, +stickLength, +stickHeight);
+ corners[7] = Vec3(-stickWidth, +stickLength, +stickHeight);
for (int i = 0; i < 8; i++) {
- corners[i]->z += 1 / 16.0f;
+ corners[i].z += 1 / 16.0f;
if (powered) {
- corners[i]->xRot(30 * PI / 180);
- corners[i]->y -= 7 / 16.0f;
+ corners[i].xRot(30 * PI / 180);
+ corners[i].y -= 7 / 16.0f;
} else if (attached) {
- corners[i]->xRot(5 * PI / 180);
- corners[i]->y -= 7 / 16.0f;
+ corners[i].xRot(5 * PI / 180);
+ corners[i].y -= 7 / 16.0f;
} else {
- corners[i]->xRot(-40 * PI / 180);
- corners[i]->y -= 6 / 16.0f;
+ corners[i].xRot(-40 * PI / 180);
+ corners[i].y -= 6 / 16.0f;
}
- corners[i]->xRot(90 * PI / 180);
+ corners[i].xRot(90 * PI / 180);
- if (dir == Direction::NORTH) corners[i]->yRot(0 * PI / 180);
- if (dir == Direction::SOUTH) corners[i]->yRot(180 * PI / 180);
- if (dir == Direction::WEST) corners[i]->yRot(90 * PI / 180);
- if (dir == Direction::EAST) corners[i]->yRot(-90 * PI / 180);
+ if (dir == Direction::NORTH) corners[i].yRot(0 * PI / 180);
+ if (dir == Direction::SOUTH) corners[i].yRot(180 * PI / 180);
+ if (dir == Direction::WEST) corners[i].yRot(90 * PI / 180);
+ if (dir == Direction::EAST) corners[i].yRot(-90 * PI / 180);
- corners[i]->x += x + 0.5;
- corners[i]->y += y + 5 / 16.0f;
- corners[i]->z += z + 0.5;
+ corners[i].x += x + 0.5;
+ corners[i].y += y + 5 / 16.0f;
+ corners[i].z += z + 0.5;
}
- Vec3 *c0 = NULL, *c1 = NULL, *c2 = NULL, *c3 = NULL;
+ Vec3 c0, c1, c2, c3;
int stickX0 = 7;
int stickX1 = 9;
int stickY0 = 9;
@@ -2054,47 +2063,47 @@ bool TileRenderer::tesselateTripwireSourceInWorld(Tile* tt, int x, int y,
c2 = corners[7];
c3 = corners[4];
}
- t->vertexUV(c0->x, c0->y, c0->z, u0, v1);
- t->vertexUV(c1->x, c1->y, c1->z, u1, v1);
- t->vertexUV(c2->x, c2->y, c2->z, u1, v0);
- t->vertexUV(c3->x, c3->y, c3->z, u0, v0);
+ t->vertexUV(c0.x, c0.y, c0.z, u0, v1);
+ t->vertexUV(c1.x, c1.y, c1.z, u1, v1);
+ t->vertexUV(c2.x, c2.y, c2.z, u1, v0);
+ t->vertexUV(c3.x, c3.y, c3.z, u0, v0);
}
float hoopWidth = 1.5f / 16.0f;
float hoopHeight = 1.5f / 16.0f;
float hoopLength = 0.5f / 16.0f;
- corners[0] = Vec3::newTemp(-hoopWidth, -0, -hoopHeight);
- corners[1] = Vec3::newTemp(+hoopWidth, -0, -hoopHeight);
- corners[2] = Vec3::newTemp(+hoopWidth, -0, +hoopHeight);
- corners[3] = Vec3::newTemp(-hoopWidth, -0, +hoopHeight);
- corners[4] = Vec3::newTemp(-hoopWidth, +hoopLength, -hoopHeight);
- corners[5] = Vec3::newTemp(+hoopWidth, +hoopLength, -hoopHeight);
- corners[6] = Vec3::newTemp(+hoopWidth, +hoopLength, +hoopHeight);
- corners[7] = Vec3::newTemp(-hoopWidth, +hoopLength, +hoopHeight);
+ corners[0] = Vec3(-hoopWidth, -0, -hoopHeight);
+ corners[1] = Vec3(+hoopWidth, -0, -hoopHeight);
+ corners[2] = Vec3(+hoopWidth, -0, +hoopHeight);
+ corners[3] = Vec3(-hoopWidth, -0, +hoopHeight);
+ corners[4] = Vec3(-hoopWidth, +hoopLength, -hoopHeight);
+ corners[5] = Vec3(+hoopWidth, +hoopLength, -hoopHeight);
+ corners[6] = Vec3(+hoopWidth, +hoopLength, +hoopHeight);
+ corners[7] = Vec3(-hoopWidth, +hoopLength, +hoopHeight);
for (int i = 0; i < 8; i++) {
- corners[i]->z += 3.5f / 16.0f;
+ corners[i].z += 3.5f / 16.0f;
if (powered) {
- corners[i]->y -= 1.5 / 16.0f;
- corners[i]->z -= 2.6 / 16.0f;
- corners[i]->xRot(0 * PI / 180);
+ corners[i].y -= 1.5 / 16.0f;
+ corners[i].z -= 2.6 / 16.0f;
+ corners[i].xRot(0 * PI / 180);
} else if (attached) {
- corners[i]->y += 0.25 / 16.0f;
- corners[i]->z -= 2.75 / 16.0f;
- corners[i]->xRot(10 * PI / 180);
+ corners[i].y += 0.25 / 16.0f;
+ corners[i].z -= 2.75 / 16.0f;
+ corners[i].xRot(10 * PI / 180);
} else {
- corners[i]->xRot(50 * PI / 180);
+ corners[i].xRot(50 * PI / 180);
}
- if (dir == Direction::NORTH) corners[i]->yRot(0 * PI / 180);
- if (dir == Direction::SOUTH) corners[i]->yRot(180 * PI / 180);
- if (dir == Direction::WEST) corners[i]->yRot(90 * PI / 180);
- if (dir == Direction::EAST) corners[i]->yRot(-90 * PI / 180);
+ if (dir == Direction::NORTH) corners[i].yRot(0 * PI / 180);
+ if (dir == Direction::SOUTH) corners[i].yRot(180 * PI / 180);
+ if (dir == Direction::WEST) corners[i].yRot(90 * PI / 180);
+ if (dir == Direction::EAST) corners[i].yRot(-90 * PI / 180);
- corners[i]->x += x + 0.5;
- corners[i]->y += y + 5 / 16.0f;
- corners[i]->z += z + 0.5;
+ corners[i].x += x + 0.5;
+ corners[i].y += y + 5 / 16.0f;
+ corners[i].z += z + 0.5;
}
int hoopX0 = 5;
@@ -2142,14 +2151,14 @@ bool TileRenderer::tesselateTripwireSourceInWorld(Tile* tt, int x, int y,
c2 = corners[7];
c3 = corners[4];
}
- t->vertexUV(c0->x, c0->y, c0->z, u0, v1);
- t->vertexUV(c1->x, c1->y, c1->z, u1, v1);
- t->vertexUV(c2->x, c2->y, c2->z, u1, v0);
- t->vertexUV(c3->x, c3->y, c3->z, u0, v0);
+ t->vertexUV(c0.x, c0.y, c0.z, u0, v1);
+ t->vertexUV(c1.x, c1.y, c1.z, u1, v1);
+ t->vertexUV(c2.x, c2.y, c2.z, u1, v0);
+ t->vertexUV(c3.x, c3.y, c3.z, u0, v0);
}
if (attached) {
- double hoopBottomY = corners[0]->y;
+ double hoopBottomY = corners[0].y;
float width = 0.5f / 16.0f;
float top = 0.5f - (width / 2);
float bottom = top + width;
@@ -4060,9 +4069,11 @@ bool TileRenderer::tesselateCrossInWorld(Tile* tt, int x, int y, int z) {
float zt = (float)z;
if (tt == Tile::tallgrass) {
- // 4jcraft add a bunch of casts to prevent overflow (i pray to god)
- int64_t seed = ((int64_t)x * 3129871) ^ ((int64_t)z * 116129781L) ^ ((int64_t)y);
- seed = (int64_t)(((uint64_t)seed * (uint64_t)seed * 42317861ULL) + ((uint64_t)seed * 11ULL));
+ // 4jcraft add a bunch of casts to prevent overflow (i pray to god)
+ int64_t seed =
+ ((int64_t)x * 3129871) ^ ((int64_t)z * 116129781L) ^ ((int64_t)y);
+ seed = (int64_t)(((uint64_t)seed * (uint64_t)seed * 42317861ULL) +
+ ((uint64_t)seed * 11ULL));
xt += ((((seed >> 16) & 0xf) / 15.0f) - 0.5f) * 0.5f;
yt += ((((seed >> 20) & 0xf) / 15.0f) - 1.0f) * 0.2f;
@@ -4318,8 +4329,10 @@ bool TileRenderer::tesselateLilypadInWorld(Tile* tt, int x, int y, int z) {
float v1 = tex->getV1(true);
// 4jcraft add a bunch of casts to prevent overflow (i pray to god)
- int64_t seed = ((int64_t)x * 3129871) ^ ((int64_t)z * 116129781L) ^ ((int64_t)y);
- seed = (int64_t)(((uint64_t)seed * (uint64_t)seed * 42317861ULL) + ((uint64_t)seed * 11ULL));
+ int64_t seed =
+ ((int64_t)x * 3129871) ^ ((int64_t)z * 116129781L) ^ ((int64_t)y);
+ seed = (int64_t)(((uint64_t)seed * (uint64_t)seed * 42317861ULL) +
+ ((uint64_t)seed * 11ULL));
int dir = (int)((seed >> 16) & 0x3);
@@ -4816,9 +4829,11 @@ bool TileRenderer::tesselateBlockInWorld(Tile* tt, int x, int y, int z) {
if (Tile::lightEmission[tt->id] ==
0) // 4J - TODO/remove (Minecraft::useAmbientOcclusion())
{
+ FRAME_PROFILE_SCOPE(ChunkBlockLighting);
return tesselateBlockInWorldWithAmbienceOcclusionTexLighting(
tt, x, y, z, r, g, b, 0, smoothShapeLighting);
} else {
+ FRAME_PROFILE_SCOPE(ChunkBlockLighting);
return tesselateBlockInWorld(tt, x, y, z, r, g, b);
}
}
@@ -4844,9 +4859,11 @@ bool TileRenderer::tesselateBlockInWorld(Tile* tt, int x, int y, int z,
if (Tile::lightEmission[tt->id] ==
0) // 4J - TODO/remove (Minecraft::useAmbientOcclusion())
{
+ FRAME_PROFILE_SCOPE(ChunkBlockLighting);
return tesselateBlockInWorldWithAmbienceOcclusionTexLighting(
tt, x, y, z, r, g, b, faceFlags, smoothShapeLighting);
} else {
+ FRAME_PROFILE_SCOPE(ChunkBlockLighting);
return tesselateBlockInWorld(tt, x, y, z, r, g, b);
}
}
@@ -7037,6 +7054,7 @@ bool TileRenderer::tesselateDoorInWorld(Tile* tt, int x, int y, int z) {
void TileRenderer::renderFaceDown(Tile* tt, double x, double y, double z,
Icon* tex) {
+ FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
@@ -7143,6 +7161,7 @@ void TileRenderer::renderFaceDown(Tile* tt, double x, double y, double z,
void TileRenderer::renderFaceUp(Tile* tt, double x, double y, double z,
Icon* tex) {
+ FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
@@ -7250,6 +7269,7 @@ void TileRenderer::renderFaceUp(Tile* tt, double x, double y, double z,
void TileRenderer::renderNorth(Tile* tt, double x, double y, double z,
Icon* tex) {
+ FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
@@ -7362,6 +7382,7 @@ void TileRenderer::renderNorth(Tile* tt, double x, double y, double z,
void TileRenderer::renderSouth(Tile* tt, double x, double y, double z,
Icon* tex) {
+ FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
@@ -7474,6 +7495,7 @@ void TileRenderer::renderSouth(Tile* tt, double x, double y, double z,
void TileRenderer::renderWest(Tile* tt, double x, double y, double z,
Icon* tex) {
+ FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
@@ -7586,6 +7608,7 @@ void TileRenderer::renderWest(Tile* tt, double x, double y, double z,
void TileRenderer::renderEast(Tile* tt, double x, double y, double z,
Icon* tex) {
+ FRAME_PROFILE_SCOPE(ChunkBlockEmit);
Tesselator* t = Tesselator::getInstance();
if (hasFixedTexture()) tex = fixedTexture;
diff --git a/Minecraft.Client/Rendering/Frustum.cpp b/Minecraft.Client/Rendering/Frustum.cpp
index 1144a7d5f..3d2e562ea 100644
--- a/Minecraft.Client/Rendering/Frustum.cpp
+++ b/Minecraft.Client/Rendering/Frustum.cpp
@@ -1,9 +1,11 @@
#include "../Platform/stdafx.h"
#include "../../Minecraft.World/IO/Streams/FloatBuffer.h"
#include "Frustum.h"
+#include "Camera.h"
Frustum* Frustum::frustum = new Frustum();
+// those are now unused but i still gotta do testing.
Frustum::Frustum() {
_proj = MemoryTracker::createFloatBuffer(16);
_modl = MemoryTracker::createFloatBuffer(16);
@@ -43,63 +45,38 @@ void Frustum::normalizePlane(float** frustum, int side) {
}
void Frustum::calculateFrustum() {
- _proj->clear();
- _modl->clear();
- _clip->clear();
+ // 4jcraft: GL 3.3 core removed GL_MODELVIEW_MATRIX / GL_PROJECTION_MATRIX
+ // queries.
+ // Camera::prepare() already captures both matrices every frame :)
+ // i spent an ungodly amount of time on this simple fix.
+ memcpy(proj.data, RenderManager.MatrixGet(GL_PROJECTION_MATRIX),
+ 16 * sizeof(float));
+ memcpy(modl.data, RenderManager.MatrixGet(GL_MODELVIEW_MATRIX),
+ 16 * sizeof(float));
- // glGetFloatv() is used to extract information about our OpenGL world.
- // Below, we pass in GL_PROJECTION_MATRIX to abstract our projection matrix.
- // It then stores the matrix into an array of [16].
- glGetFloat(GL_PROJECTION_MATRIX, _proj);
+ float* p = proj.data;
+ float* m = modl.data;
+ float* c = clip.data;
- // By passing in GL_MODELVIEW_MATRIX, we can abstract our model view matrix.
- // This also stores it in an array of [16].
- glGetFloat(GL_MODELVIEW_MATRIX, _modl);
+ c[0] = m[0] * p[0] + m[1] * p[4] + m[2] * p[8] + m[3] * p[12];
+ c[1] = m[0] * p[1] + m[1] * p[5] + m[2] * p[9] + m[3] * p[13];
+ c[2] = m[0] * p[2] + m[1] * p[6] + m[2] * p[10] + m[3] * p[14];
+ c[3] = m[0] * p[3] + m[1] * p[7] + m[2] * p[11] + m[3] * p[15];
- _proj->flip()->limit(16);
- _proj->get(&proj);
- _modl->flip()->limit(16);
- _modl->get(&modl);
+ c[4] = m[4] * p[0] + m[5] * p[4] + m[6] * p[8] + m[7] * p[12];
+ c[5] = m[4] * p[1] + m[5] * p[5] + m[6] * p[9] + m[7] * p[13];
+ c[6] = m[4] * p[2] + m[5] * p[6] + m[6] * p[10] + m[7] * p[14];
+ c[7] = m[4] * p[3] + m[5] * p[7] + m[6] * p[11] + m[7] * p[15];
- // Now that we have our modelview and projection matrix, if we combine these
- // 2 matrices, it will give us our clipping planes. To combine 2 matrices,
- // we multiply them.
+ c[8] = m[8] * p[0] + m[9] * p[4] + m[10] * p[8] + m[11] * p[12];
+ c[9] = m[8] * p[1] + m[9] * p[5] + m[10] * p[9] + m[11] * p[13];
+ c[10] = m[8] * p[2] + m[9] * p[6] + m[10] * p[10] + m[11] * p[14];
+ c[11] = m[8] * p[3] + m[9] * p[7] + m[10] * p[11] + m[11] * p[15];
- clip[0] = modl[0] * proj[0] + modl[1] * proj[4] + modl[2] * proj[8] +
- modl[3] * proj[12];
- clip[1] = modl[0] * proj[1] + modl[1] * proj[5] + modl[2] * proj[9] +
- modl[3] * proj[13];
- clip[2] = modl[0] * proj[2] + modl[1] * proj[6] + modl[2] * proj[10] +
- modl[3] * proj[14];
- clip[3] = modl[0] * proj[3] + modl[1] * proj[7] + modl[2] * proj[11] +
- modl[3] * proj[15];
-
- clip[4] = modl[4] * proj[0] + modl[5] * proj[4] + modl[6] * proj[8] +
- modl[7] * proj[12];
- clip[5] = modl[4] * proj[1] + modl[5] * proj[5] + modl[6] * proj[9] +
- modl[7] * proj[13];
- clip[6] = modl[4] * proj[2] + modl[5] * proj[6] + modl[6] * proj[10] +
- modl[7] * proj[14];
- clip[7] = modl[4] * proj[3] + modl[5] * proj[7] + modl[6] * proj[11] +
- modl[7] * proj[15];
-
- clip[8] = modl[8] * proj[0] + modl[9] * proj[4] + modl[10] * proj[8] +
- modl[11] * proj[12];
- clip[9] = modl[8] * proj[1] + modl[9] * proj[5] + modl[10] * proj[9] +
- modl[11] * proj[13];
- clip[10] = modl[8] * proj[2] + modl[9] * proj[6] + modl[10] * proj[10] +
- modl[11] * proj[14];
- clip[11] = modl[8] * proj[3] + modl[9] * proj[7] + modl[10] * proj[11] +
- modl[11] * proj[15];
-
- clip[12] = modl[12] * proj[0] + modl[13] * proj[4] + modl[14] * proj[8] +
- modl[15] * proj[12];
- clip[13] = modl[12] * proj[1] + modl[13] * proj[5] + modl[14] * proj[9] +
- modl[15] * proj[13];
- clip[14] = modl[12] * proj[2] + modl[13] * proj[6] + modl[14] * proj[10] +
- modl[15] * proj[14];
- clip[15] = modl[12] * proj[3] + modl[13] * proj[7] + modl[14] * proj[11] +
- modl[15] * proj[15];
+ c[12] = m[12] * p[0] + m[13] * p[4] + m[14] * p[8] + m[15] * p[12];
+ c[13] = m[12] * p[1] + m[13] * p[5] + m[14] * p[9] + m[15] * p[13];
+ c[14] = m[12] * p[2] + m[13] * p[6] + m[14] * p[10] + m[15] * p[14];
+ c[15] = m[12] * p[3] + m[13] * p[7] + m[14] * p[11] + m[15] * p[15];
// Now we actually want to get the sides of the frustum. To do this we take
// the clipping planes we received above and extract the sides from them.
diff --git a/Minecraft.Client/Rendering/FrustumData.cpp b/Minecraft.Client/Rendering/FrustumData.cpp
index a5f11b768..140fa4772 100644
--- a/Minecraft.Client/Rendering/FrustumData.cpp
+++ b/Minecraft.Client/Rendering/FrustumData.cpp
@@ -1,11 +1,13 @@
#include "../Platform/stdafx.h"
#include "FrustumData.h"
-float** m_Frustum;
+// float** m_Frustum;
FrustumData::FrustumData() {
- m_Frustum = new float*[16];
- for (int i = 0; i < 16; i++) m_Frustum[i] = new float[16];
+ this->m_Frustum = new float*[6];
+ for (int i = 0; i < 6; i++) {
+ this->m_Frustum[i] = new float[4];
+ }
proj = floatArray(16);
modl = floatArray(16);
clip = floatArray(16);
@@ -15,7 +17,7 @@ FrustumData::~FrustumData() {
delete[] proj.data;
delete[] modl.data;
delete[] clip.data;
- for (int i = 0; i < 16; i++) delete[] m_Frustum[i];
+ for (int i = 0; i < 6; i++) delete[] m_Frustum[i];
delete[] m_Frustum;
}
@@ -128,4 +130,4 @@ bool FrustumData::cubeInFrustum(double x1, double y1, double z1, double x2,
bool FrustumData::isVisible(AABB* aabb) {
return cubeInFrustum(aabb->x0, aabb->y0, aabb->z0, aabb->x1, aabb->y1,
aabb->z1);
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/GameRenderer.cpp b/Minecraft.Client/Rendering/GameRenderer.cpp
index 5eef3ccc8..979d578c1 100644
--- a/Minecraft.Client/Rendering/GameRenderer.cpp
+++ b/Minecraft.Client/Rendering/GameRenderer.cpp
@@ -50,6 +50,7 @@
#include "../Textures/Packs/TexturePackRepository.h"
#include "../Textures/Packs/TexturePack.h"
#include "../Textures/TextureAtlas.h"
+#include "../Utils/FrameProfiler.h"
bool GameRenderer::anaglyph3d = false;
int GameRenderer::anaglyphPass = 0;
@@ -72,6 +73,9 @@ ResourceLocation GameRenderer::RAIN_LOCATION =
ResourceLocation GameRenderer::SNOW_LOCATION =
ResourceLocation(TN_ENVIRONMENT_SNOW);
+// dirty light tracking
+static bool s_lightTexDirty[XUSER_MAX_COUNT] = {true, true, true, true};
+
GameRenderer::GameRenderer(Minecraft* mc) {
// 4J - added this block of initialisers
renderDistance = 0;
@@ -90,7 +94,7 @@ GameRenderer::GameRenderer(Minecraft* mc) {
tickSmoothYO = 0;
lastTickA = 0;
- cameraPos = Vec3::newPermanent(0.0f, 0.0f, 0.0f);
+ cameraPos = Vec3(0.0f, 0.0f, 0.0f);
fovOffset = 0;
fovOffsetO = 0;
@@ -280,7 +284,7 @@ void GameRenderer::pick(float a) {
}
double dist = range;
- Vec3* from = mc->cameraTargetPlayer->getPos(a);
+ Vec3 from = mc->cameraTargetPlayer->getPos(a);
if (mc->gameMode->hasFarPickRange()) {
dist = range = 6;
@@ -290,18 +294,20 @@ void GameRenderer::pick(float a) {
}
if (mc->hitResult != NULL) {
- dist = mc->hitResult->pos->distanceTo(from);
+ dist = mc->hitResult->pos.distanceTo(from);
}
- Vec3* b = mc->cameraTargetPlayer->getViewVector(a);
- Vec3* to = from->add(b->x * range, b->y * range, b->z * range);
+ Vec3 b = mc->cameraTargetPlayer->getViewVector(a);
+ Vec3 to(b.x * range, b.y * range, b.z * range);
+ to = to.add(from.x, from.y, from.z);
hovered = nullptr;
float overlap = 1;
- std::vector >* objects = mc->level->getEntities(
- mc->cameraTargetPlayer,
- mc->cameraTargetPlayer->bb
- ->expand(b->x * (range), b->y * (range), b->z * (range))
- ->grow(overlap, overlap, overlap));
+ AABB grown = mc->cameraTargetPlayer->bb
+ .expand(b.x * (range), b.y * (range), b.z * (range))
+ .grow(overlap, overlap, overlap);
+
+ std::vector >* objects =
+ mc->level->getEntities(mc->cameraTargetPlayer, &grown);
double nearest = dist;
AUTO_VAR(itEnd, objects->end());
@@ -310,15 +316,15 @@ void GameRenderer::pick(float a) {
if (!e->isPickable()) continue;
float rr = e->getPickRadius();
- AABB* bb = e->bb->grow(rr, rr, rr);
- HitResult* p = bb->clip(from, to);
- if (bb->contains(from)) {
+ AABB bb = e->bb.grow(rr, rr, rr);
+ HitResult* p = bb.clip(from, to);
+ if (bb.contains(from)) {
if (0 < nearest || nearest == 0) {
hovered = e;
nearest = 0;
}
} else if (p != NULL) {
- double dd = from->distanceTo(p->pos);
+ double dd = from.distanceTo(p->pos);
std::shared_ptr ridingEntity =
mc->cameraTargetPlayer->riding;
// 4jcraft: compare the mounted entity explicitly so riding the hit
@@ -512,11 +518,12 @@ void GameRenderer::moveCameraToPlayer(float a) {
// 4J - corrected bug here where zo was also added to x
// component
- HitResult* hr = mc->level->clip(
- Vec3::newTemp(x + xo, y + yo, z + zo),
- Vec3::newTemp(x - xd + xo, y - yd + yo, z - zd + zo));
+ Vec3 a(x + xo, y + yo, z + zo);
+ Vec3 b(x - xd + xo, y - yd + yo, z - zd + zo);
+ HitResult* hr = mc->level->clip(&a, &b);
if (hr != NULL) {
- double dist = hr->pos->distanceTo(Vec3::newTemp(x, y, z));
+ Vec3 p(x, y, z);
+ double dist = hr->pos.distanceTo(p);
if (dist < cameraDist) cameraDist = dist;
delete hr;
}
@@ -658,6 +665,11 @@ void GameRenderer::setupCamera(float a, int eye) {
void GameRenderer::renderItemInHand(float a, int eye) {
if (cameraFlip > 0) return;
+ // 4jcraft: this function sometimes causes a segfault (was hell to catch
+ // this in gdb) because of itemInHandRenderer not being initialized so let's
+ // add a nullcheck
+ if (itemInHandRenderer == nullptr) return;
+
// 4J-JEV: I'm fairly confident this method would crash if the cameratarget
// isnt a local player anyway, but oh well.
std::shared_ptr localplayer =
@@ -754,6 +766,7 @@ void GameRenderer::renderItemInHand(float a, int eye) {
// 4J - change brought forward from 1.8.2
void GameRenderer::turnOffLightLayer(double alpha) { // 4J - TODO
+ FRAME_PROFILE_SCOPE(Lightmap);
#if defined(__linux__)
if (SharedConstants::TEXTURE_LIGHTING) {
LinuxLogStubLightmapProbe();
@@ -781,6 +794,7 @@ void GameRenderer::turnOffLightLayer(double alpha) { // 4J - TODO
void GameRenderer::turnOnLightLayer(
double alpha,
bool scaleLight) { // 4jcraft: added scaleLight for entity lighting
+ FRAME_PROFILE_SCOPE(Lightmap);
#if defined(__linux__)
if (!SharedConstants::TEXTURE_LIGHTING) return;
@@ -815,9 +829,14 @@ void GameRenderer::tickLightTexture() {
blr += (blrt - blr) * 1;
blg += (blgt - blg) * 1;
_updateLightTexture = true;
+
+ // Mark all players dirty so updateLightTexture() knows when it actually
+ // needs to tick, preventz unessesary player recompute
+ for (int j = 0; j < XUSER_MAX_COUNT; j++) s_lightTexDirty[j] = true;
}
void GameRenderer::updateLightTexture(float a) {
+ FRAME_PROFILE_SCOPE(Lightmap);
// 4J-JEV: Now doing light textures on PER PLAYER basis.
// 4J - we *had* added separate light textures for all dimensions, and this
// loop to update them all here
@@ -827,8 +846,10 @@ void GameRenderer::updateLightTexture(float a) {
Minecraft::GetInstance()->localplayers[j];
if (player == NULL) continue;
- Level* level = player->level; // 4J - was mc->level when it was just to
- // update the one light texture
+ if (!s_lightTexDirty[j]) continue;
+ s_lightTexDirty[j] = false;
+
+ Level* level = player->level;
float skyDarken1 = level->getSkyDarken((float)1);
for (int i = 0; i < 256; i++) {
@@ -908,10 +929,10 @@ void GameRenderer::updateLightTexture(float a) {
_b = _b * 0.96f + 0.03f;
if (_r > 1) _r = 1;
- if (_g > 1) _g = 1;
- if (_b > 1) _b = 1;
if (_r < 0) _r = 0;
+ if (_g > 1) _g = 1;
if (_g < 0) _g = 0;
+ if (_b > 1) _b = 1;
if (_b < 0) _b = 0;
int alpha = 255;
@@ -958,6 +979,8 @@ int GameRenderer::getLightTexture(int iPad, Level* level) {
}
void GameRenderer::render(float a, bool bFirst) {
+ FRAME_PROFILE_FRAME_SCOPE();
+
if (_updateLightTexture && bFirst) updateLightTexture(a);
if (Display::isActive()) {
lastActiveTime = System::currentTimeMillis();
@@ -981,7 +1004,11 @@ void GameRenderer::render(float a, bool bFirst) {
int maxFps = getFpsCap(mc->options->framerateLimit);
if (mc->level != NULL) {
- if (mc->options->framerateLimit == 0) {
+ if (mc->options->framerateLimit == 0
+#ifndef ENABLE_VSYNC
+ || mc->options->framerateLimit == 3
+#endif
+ ) {
renderLevel(a, 0);
} else {
renderLevel(a, lastNsTime + 1000000000 / maxFps);
@@ -990,6 +1017,7 @@ void GameRenderer::render(float a, bool bFirst) {
lastNsTime = System::nanoTime();
if (!mc->options->hideGui || mc->screen != NULL) {
+ FRAME_PROFILE_SCOPE(UIHud);
mc->gui->render(a, mc->screen != NULL, xMouse, yMouse);
}
} else {
@@ -1004,6 +1032,7 @@ void GameRenderer::render(float a, bool bFirst) {
}
if (mc->screen != NULL) {
+ FRAME_PROFILE_SCOPE(UIHud);
glClear(GL_DEPTH_BUFFER_BIT);
mc->screen->render(xMouse, yMouse, a);
if (mc->screen != NULL && mc->screen->particles != NULL)
@@ -1041,8 +1070,6 @@ void GameRenderer::FinishedReassigning() {
int GameRenderer::runUpdate(void* lpParam) {
Minecraft* minecraft = Minecraft::GetInstance();
- Vec3::CreateNewThreadStorage();
- AABB::CreateNewThreadStorage();
Tesselator::CreateNewThreadStorage(1024 * 1024);
Compression::UseDefaultThreadStorage();
RenderManager.InitialiseContext();
@@ -1098,31 +1125,24 @@ int GameRenderer::runUpdate(void* lpParam) {
// We've got stacks for things that can only safely be deleted whilst
// this thread isn't updating things - delete those things now
EnterCriticalSection(&m_csDeleteStack);
- for (unsigned int i = 0; i < m_deleteStackByte.size(); i++) {
+ for (unsigned int i = 0; i < m_deleteStackByte.size(); i++)
delete m_deleteStackByte[i];
- }
m_deleteStackByte.clear();
for (unsigned int i = 0; i < m_deleteStackSparseLightStorage.size();
- i++) {
+ i++)
delete m_deleteStackSparseLightStorage[i];
- }
m_deleteStackSparseLightStorage.clear();
for (unsigned int i = 0; i < m_deleteStackCompressedTileStorage.size();
- i++) {
+ i++)
delete m_deleteStackCompressedTileStorage[i];
- }
m_deleteStackCompressedTileStorage.clear();
- for (unsigned int i = 0; i < m_deleteStackSparseDataStorage.size();
- i++) {
+ for (unsigned int i = 0; i < m_deleteStackSparseDataStorage.size(); i++)
delete m_deleteStackSparseDataStorage[i];
- }
m_deleteStackSparseDataStorage.clear();
LeaveCriticalSection(&m_csDeleteStack);
// PIXEndNamedEvent();
- AABB::resetPool();
- Vec3::resetPool();
m_updateEvents->Set(eUpdateEventIsFinished);
}
@@ -1160,6 +1180,8 @@ void GameRenderer::DisableUpdateThread() {
}
void GameRenderer::renderLevel(float a, int64_t until) {
+ FRAME_PROFILE_SCOPE(World);
+
// if (updateLightTexture) updateLightTexture(); // 4J - TODO -
// Java 1.0.1 has this line enabled, should check why - don't want to put it
// in now in case it breaks split-screen
@@ -1212,9 +1234,12 @@ void GameRenderer::renderLevel(float a, int64_t until) {
Frustum::getFrustum();
if (mc->options->viewDistance < 2) {
setupFog(-1, a);
- levelRenderer->renderSky(a);
- if (mc->skins->getSelected()->getId() == 1026)
- levelRenderer->renderHaloRing(a);
+ {
+ FRAME_PROFILE_SCOPE(WeatherSky);
+ levelRenderer->renderSky(a);
+ if (mc->skins->getSelected()->getId() == 1026)
+ levelRenderer->renderHaloRing(a);
+ }
}
// 4jcraft: needs to be enabled for proper transparent texturing on low
// render dists this was done in renderSky() for the far and normal
@@ -1236,7 +1261,10 @@ void GameRenderer::renderLevel(float a, int64_t until) {
MemSect(0);
frustum->prepare(xOff, yOff, zOff);
- mc->levelRenderer->cull(frustum, a);
+ {
+ FRAME_PROFILE_SCOPE(ChunkCull);
+ mc->levelRenderer->cull(frustum, a);
+ }
PIXEndNamedEvent();
#if !defined(MULTITHREAD_ENABLE)
@@ -1263,6 +1291,7 @@ void GameRenderer::renderLevel(float a, int64_t until) {
#endif
if (cameraEntity->y < Level::genDepth) {
+ FRAME_PROFILE_SCOPE(WeatherSky);
prepareAndRenderClouds(levelRenderer, a);
}
Frustum::getFrustum(); // 4J added - re-calculate frustum as rendering
@@ -1297,20 +1326,29 @@ void GameRenderer::renderLevel(float a, int64_t until) {
// storing the camera position Fix for #77745 - TU9: Content:
// Gameplay: Items and mobs not belonging to end world are
// disappearing when Enderdragon is damaged.
- Vec3* cameraPosTemp = cameraEntity->getPos(a);
- cameraPos->x = cameraPosTemp->x;
- cameraPos->y = cameraPosTemp->y;
- cameraPos->z = cameraPosTemp->z;
- levelRenderer->renderEntities(cameraPos, frustum, a);
+ Vec3 cameraPosTemp = cameraEntity->getPos(a);
+ cameraPos.x = cameraPosTemp.x;
+ cameraPos.y = cameraPosTemp.y;
+ cameraPos.z = cameraPosTemp.z;
+ {
+ FRAME_PROFILE_SCOPE(Entity);
+ levelRenderer->renderEntities(&cameraPos, frustum, a);
+ }
PIXEndNamedEvent();
PIXBeginNamedEvent(0, "Particle render");
turnOnLightLayer(a); // 4J - brought forward from 1.8.2
- particleEngine->renderLit(cameraEntity, a,
- ParticleEngine::OPAQUE_LIST);
+ {
+ FRAME_PROFILE_SCOPE(Particle);
+ particleEngine->renderLit(cameraEntity, a,
+ ParticleEngine::OPAQUE_LIST);
+ }
Lighting::turnOff();
setupFog(0, a);
- particleEngine->render(cameraEntity, a,
- ParticleEngine::OPAQUE_LIST);
+ {
+ FRAME_PROFILE_SCOPE(Particle);
+ particleEngine->render(cameraEntity, a,
+ ParticleEngine::OPAQUE_LIST);
+ }
PIXEndNamedEvent();
turnOffLightLayer(a); // 4J - brought forward from 1.8.2
@@ -1379,12 +1417,18 @@ void GameRenderer::renderLevel(float a, int64_t until) {
PIXBeginNamedEvent(0, "Particle render (translucent)");
Lighting::turnOn();
turnOnLightLayer(a); // 4J - brought forward from 1.8.2
- particleEngine->renderLit(cameraEntity, a,
- ParticleEngine::TRANSLUCENT_LIST);
+ {
+ FRAME_PROFILE_SCOPE(Particle);
+ particleEngine->renderLit(cameraEntity, a,
+ ParticleEngine::TRANSLUCENT_LIST);
+ }
Lighting::turnOff();
setupFog(0, a);
- particleEngine->render(cameraEntity, a,
- ParticleEngine::TRANSLUCENT_LIST);
+ {
+ FRAME_PROFILE_SCOPE(Particle);
+ particleEngine->render(cameraEntity, a,
+ ParticleEngine::TRANSLUCENT_LIST);
+ }
PIXEndNamedEvent();
turnOffLightLayer(a); // 4J - brought forward from 1.8.2
////////////////////////// End of 4J added section
@@ -1415,12 +1459,16 @@ void GameRenderer::renderLevel(float a, int64_t until) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE);
- levelRenderer->renderDestroyAnimation(
- Tesselator::getInstance(),
- std::dynamic_pointer_cast(cameraEntity), a);
+ {
+ FRAME_PROFILE_SCOPE(WeatherSky);
+ levelRenderer->renderDestroyAnimation(
+ Tesselator::getInstance(),
+ std::dynamic_pointer_cast(cameraEntity), a);
+ }
glDisable(GL_BLEND);
if (cameraEntity->y >= Level::genDepth) {
+ FRAME_PROFILE_SCOPE(WeatherSky);
prepareAndRenderClouds(levelRenderer, a);
}
@@ -1429,7 +1477,10 @@ void GameRenderer::renderLevel(float a, int64_t until) {
setupFog(0, a);
glEnable(GL_FOG);
PIXBeginNamedEvent(0, "Rendering snow and rain");
- renderSnowAndRain(a);
+ {
+ FRAME_PROFILE_SCOPE(WeatherSky);
+ renderSnowAndRain(a);
+ }
PIXEndNamedEvent();
glDisable(GL_FOG);
@@ -1616,105 +1667,133 @@ void GameRenderer::renderSnowAndRain(float a) {
glColor4f(1, 1, 1, 1);
- for (int x = x0 - r; x <= x0 + r; x++)
+ // two snow/rain rendering
+ mc->textures->bindTexture(&RAIN_LOCATION);
+ t->begin();
+ for (int x = x0 - r; x <= x0 + r; x++) {
for (int z = z0 - r; z <= z0 + r; z++) {
int rainSlot = (z - z0 + 16) * 32 + (x - x0 + 16);
float xa = rainXa[rainSlot] * 0.5f;
float za = rainZa[rainSlot] * 0.5f;
- // 4J - changes here brought forward from 1.8.2
Biome* b = level->getBiome(x, z);
if (!b->hasRain() && !b->hasSnow()) continue;
int floor = level->getTopRainBlock(x, z);
-
int yy0 = y0 - r;
int yy1 = y0 + r;
-
if (yy0 < floor) yy0 = floor;
if (yy1 < floor) yy1 = floor;
- float s = 1;
+ if (yy0 == yy1) continue;
int yl = floor;
if (yl < yMin) yl = yMin;
- if (yy0 != yy1) {
- random->setSeed((x * x * 3121 + x * 45238971) ^
- (z * z * 418711 + z * 13761));
+ float temp = b->getTemperature();
+ if (level->getBiomeSource()->scaleTemp(temp, floor) < 0.15f)
+ continue;
- // 4J - changes here brought forward from 1.8.2
- float temp = b->getTemperature();
- if (level->getBiomeSource()->scaleTemp(temp, floor) >= 0.15f) {
- if (mode != 0) {
- if (mode >= 0) t->end();
- mode = 0;
- mc->textures->bindTexture(&RAIN_LOCATION);
- t->begin();
- }
+ random->setSeed((x * x * 3121 + x * 45238971) ^
+ (z * z * 418711 + z * 13761));
- float ra = (((_tick + x * x * 3121 + x * 45238971 +
- z * z * 418711 + z * 13761) &
- 31) +
- a) /
- 32.0f * (3 + random->nextFloat());
+ float ra = (((_tick + x * x * 3121 + x * 45238971 + z * z * 418711 +
+ z * 13761) &
+ 31) +
+ a) /
+ 32.0f * (3 + random->nextFloat());
- double xd = (x + 0.5f) - player->x;
- double zd = (z + 0.5f) - player->z;
- float dd = (float)Mth::sqrt(xd * xd + zd * zd) / r;
+ double xd = (x + 0.5f) - player->x;
+ double zd = (z + 0.5f) - player->z;
+ float dd = (float)Mth::sqrt(xd * xd + zd * zd) / r;
- float br = 1;
- t->offset(-xo * 1, -yo * 1, -zo * 1);
- t->tex2(level->getLightColor(x, yl, z, 0));
- t->color(br, br, br,
- ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel);
- t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s,
- yy0 * s / 4.0f + ra * s);
- t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s,
- yy0 * s / 4.0f + ra * s);
- // 4jcraft: this color call made rain invisible
- // t->color(br, br, br, 0.0f);
- // // 4J - added to soften the top visible edge of the rain
- t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s,
- yy1 * s / 4.0f + ra * s);
- t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s,
- yy1 * s / 4.0f + ra * s);
- t->offset(0, 0, 0);
- t->end();
- } else {
- if (mode != 1) {
- if (mode >= 0) t->end();
- mode = 1;
- mc->textures->bindTexture(&SNOW_LOCATION);
- t->begin();
- }
- float ra = (((_tick) & 511) + a) / 512.0f;
- float uo = random->nextFloat() +
- time * 0.01f * (float)random->nextGaussian();
- float vo = random->nextFloat() +
- time * (float)random->nextGaussian() * 0.001f;
- double xd = (x + 0.5f) - player->x;
- double zd = (z + 0.5f) - player->z;
- float dd = (float)sqrt(xd * xd + zd * zd) / r;
- float br = 1;
- t->offset(-xo * 1, -yo * 1, -zo * 1);
- t->tex2((level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) /
- 4);
- t->color(br, br, br,
- ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel);
- t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo,
- yy0 * s / 4.0f + ra * s + vo);
- t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo,
- yy0 * s / 4.0f + ra * s + vo);
- t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo,
- yy1 * s / 4.0f + ra * s + vo);
- t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo,
- yy1 * s / 4.0f + ra * s + vo);
- t->offset(0, 0, 0);
- }
- }
+ float br = 1.0f;
+ float s = 1.0f;
+ t->offset(-xo, -yo, -zo);
+ t->tex2(level->getLightColor(x, yl, z, 0));
+ t->color(br, br, br, ((1 - dd * dd) * 0.5f + 0.5f) * rainLevel);
+ t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s,
+ yy0 * s / 4.0f + ra * s);
+ t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s,
+ yy0 * s / 4.0f + ra * s);
+ t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s,
+ yy1 * s / 4.0f + ra * s);
+ t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s,
+ yy1 * s / 4.0f + ra * s);
+ t->offset(0, 0, 0);
}
+ }
+ t->end(); // single submit for all rain geometry
+ // sno time
+ mc->textures->bindTexture(&SNOW_LOCATION);
+ t->begin();
+ for (int x = x0 - r; x <= x0 + r; x++) {
+ for (int z = z0 - r; z <= z0 + r; z++) {
+ int rainSlot = (z - z0 + 16) * 32 + (x - x0 + 16);
+ float xa = rainXa[rainSlot] * 0.5f;
+ float za = rainZa[rainSlot] * 0.5f;
+
+ Biome* b = level->getBiome(x, z);
+ if (!b->hasRain() && !b->hasSnow()) continue;
+
+ int floor = level->getTopRainBlock(x, z);
+ int yy0 = y0 - r;
+ int yy1 = y0 + r;
+ if (yy0 < floor) yy0 = floor;
+ if (yy1 < floor) yy1 = floor;
+ if (yy0 == yy1) continue;
+
+ int yl = floor;
+ if (yl < yMin) yl = yMin;
+
+ float temp = b->getTemperature();
+ // only draw snow (not rain) in this pass
+ if (level->getBiomeSource()->scaleTemp(temp, floor) >= 0.15f)
+ continue;
+
+ random->setSeed((x * x * 3121 + x * 45238971) ^
+ (z * z * 418711 + z * 13761));
+
+ float ra = (((_tick) & 511) + a) / 512.0f;
+ float uo = random->nextFloat() +
+ time * 0.01f * (float)random->nextGaussian();
+ float vo = random->nextFloat() +
+ time * (float)random->nextGaussian() * 0.001f;
+
+ double xd = (x + 0.5f) - player->x;
+ double zd = (z + 0.5f) - player->z;
+ float dd = (float)sqrt(xd * xd + zd * zd) / r;
+
+ float br = 1.0f;
+ float s = 1.0f;
+ t->offset(-xo, -yo, -zo);
+#ifdef __PSVITA__
+ float Alpha = ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel;
+ int tex2 = (level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4;
+ t->tileRainQuad(
+ x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo,
+ yy0 * s / 4.0f + ra * s + vo, x + xa + 0.5, yy0, z + za + 0.5,
+ 1 * s + uo, yy0 * s / 4.0f + ra * s + vo, x + xa + 0.5, yy1,
+ z + za + 0.5, 1 * s + uo, yy1 * s / 4.0f + ra * s + vo,
+ x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo,
+ yy1 * s / 4.0f + ra * s + vo, br, br, br, Alpha, br, br, br,
+ Alpha, tex2);
+#else
+ t->tex2((level->getLightColor(x, yl, z, 0) * 3 + 0xf000f0) / 4);
+ t->color(br, br, br, ((1 - dd * dd) * 0.3f + 0.5f) * rainLevel);
+ t->vertexUV(x - xa + 0.5, yy0, z - za + 0.5, 0 * s + uo,
+ yy0 * s / 4.0f + ra * s + vo);
+ t->vertexUV(x + xa + 0.5, yy0, z + za + 0.5, 1 * s + uo,
+ yy0 * s / 4.0f + ra * s + vo);
+ t->vertexUV(x + xa + 0.5, yy1, z + za + 0.5, 1 * s + uo,
+ yy1 * s / 4.0f + ra * s + vo);
+ t->vertexUV(x - xa + 0.5, yy1, z - za + 0.5, 0 * s + uo,
+ yy1 * s / 4.0f + ra * s + vo);
+#endif
+ t->offset(0, 0, 0);
+ }
+ }
+ t->end(); // single submit for all snow geometry
- if (mode >= 0) t->end();
glEnable(GL_CULL_FACE);
glDisable(GL_BLEND);
glAlphaFunc(GL_GREATER, 0.1f);
@@ -1731,6 +1810,35 @@ void GameRenderer::setupGuiScreen(int forceScale /*=-1*/) {
// 4jcraft: use actual framebuffer dimensions instead of mc->width/height
// to ensure GUI scales correctly after a window resize.
ScreenSizeCalculator ssc(mc->options, fbw, fbh, forceScale);
+
+ // 4jcraft: Java GUI screens still assume a clean 2D fixed-function style
+ // state.
+ RenderManager.StateSetFaceCull(false);
+ glDisable(GL_LIGHTING);
+ glDisable(GL_FOG);
+ glColor4f(1, 1, 1, 1);
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(GL_GREATER, 0.1f);
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glDepthMask(true);
+
+ RenderManager.TextureBindVertex(-1);
+
+ glClientActiveTexture(GL_TEXTURE1);
+ glActiveTexture(GL_TEXTURE1);
+ glDisable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+
+ glClientActiveTexture(GL_TEXTURE0);
+ glActiveTexture(GL_TEXTURE0);
+ glEnable(GL_TEXTURE_2D);
+ glMatrixMode(GL_TEXTURE);
+ glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+
glClear(GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
@@ -1747,21 +1855,20 @@ void GameRenderer::setupClearColor(float a) {
float whiteness = 1.0f / (4 - mc->options->viewDistance);
whiteness = 1 - (float)pow((double)whiteness, 0.25);
- Vec3* skyColor = level->getSkyColor(mc->cameraTargetPlayer, a);
- float sr = (float)skyColor->x;
- float sg = (float)skyColor->y;
- float sb = (float)skyColor->z;
+ Vec3 skyColor = level->getSkyColor(mc->cameraTargetPlayer, a);
+ float sr = (float)skyColor.x;
+ float sg = (float)skyColor.y;
+ float sb = (float)skyColor.z;
- Vec3* fogColor = level->getFogColor(a);
- fr = (float)fogColor->x;
- fg = (float)fogColor->y;
- fb = (float)fogColor->z;
+ Vec3 fogColor = level->getFogColor(a);
+ fr = (float)fogColor.x;
+ fg = (float)fogColor.y;
+ fb = (float)fogColor.z;
if (mc->options->viewDistance < 2) {
- Vec3* sunAngle = Mth::sin(level->getSunAngle(a)) > 0
- ? Vec3::newTemp(-1, 0, 0)
- : Vec3::newTemp(1, 0, 0);
- float d = (float)player->getViewVector(a)->dot(sunAngle);
+ Vec3 sunAngle = Mth::sin(level->getSunAngle(a)) > 0 ? Vec3(-1, 0, 0)
+ : Vec3(1, 0, 0);
+ float d = (float)player->getViewVector(a).dot(sunAngle);
if (d < 0) d = 0;
if (d > 0) {
float* c =
@@ -1797,10 +1904,10 @@ void GameRenderer::setupClearColor(float a) {
int t = Camera::getBlockAt(mc->level, player, a);
if (isInClouds) {
- Vec3* cc = level->getCloudColor(a);
- fr = (float)cc->x;
- fg = (float)cc->y;
- fb = (float)cc->z;
+ Vec3 cc = level->getCloudColor(a);
+ fr = (float)cc.x;
+ fg = (float)cc.y;
+ fb = (float)cc.z;
} else if (t != 0 && Tile::tiles[t]->material == Material::water) {
float clearness = EnchantmentHelper::getOxygenBonus(player) * 0.2f;
@@ -2024,6 +2131,9 @@ int GameRenderer::getFpsCap(int option) {
int maxFps = 200;
if (option == 1) maxFps = 120;
if (option == 2) maxFps = 35;
+#ifndef ENABLE_VSYNC
+ if (option == 3) maxFps = std::numeric_limits::max();
+#endif
return maxFps;
}
diff --git a/Minecraft.Client/Rendering/GameRenderer.h b/Minecraft.Client/Rendering/GameRenderer.h
index e3b4c0ca7..c359e45e2 100644
--- a/Minecraft.Client/Rendering/GameRenderer.h
+++ b/Minecraft.Client/Rendering/GameRenderer.h
@@ -50,7 +50,7 @@ private:
float thirdTiltO;
float accumulatedSmoothXO, accumulatedSmoothYO;
float tickSmoothXO, tickSmoothYO, lastTickA;
- Vec3* cameraPos; // 4J added
+ Vec3 cameraPos; // 4J added
// fov modification
float fovOffset;
diff --git a/Minecraft.Client/Rendering/LevelRenderer.cpp b/Minecraft.Client/Rendering/LevelRenderer.cpp
index 937c33c33..da8d28fa8 100644
--- a/Minecraft.Client/Rendering/LevelRenderer.cpp
+++ b/Minecraft.Client/Rendering/LevelRenderer.cpp
@@ -1,3 +1,7 @@
+#include
+#include
+#include
+
#include "../Platform/stdafx.h"
#include "LevelRenderer.h"
#include
@@ -60,6 +64,7 @@
#include "../Level/MultiPlayerLevel.h"
#include "../../Minecraft.World/Util/SoundTypes.h"
#include "FrustumCuller.h"
+#include "../Utils/FrameProfiler.h"
// #define DISABLE_SPU_CODE
@@ -76,6 +81,9 @@ ResourceLocation LevelRenderer::END_SKY_LOCATION =
const unsigned int HALO_RING_RADIUS = 100;
+uint64_t* LevelRenderer::globalChunkConnectivity =
+ nullptr; // bad placement do bettr juicey
+
#if defined(_LARGE_WORLDS)
Chunk LevelRenderer::permaChunk[MAX_CONCURRENT_CHUNK_REBUILDS];
C4JThread* LevelRenderer::rebuildThreads[MAX_CHUNK_REBUILD_THREADS];
@@ -174,6 +182,10 @@ LevelRenderer::LevelRenderer(Minecraft* mc, Textures* textures) {
globalChunkFlags = new unsigned char[getGlobalChunkCount()];
memset(globalChunkFlags, 0, getGlobalChunkCount());
+ globalChunkConnectivity = new uint64_t[getGlobalChunkCount()];
+ memset(globalChunkConnectivity, 0xFF,
+ getGlobalChunkCount() * sizeof(uint64_t)); // 0xFF >> Fully open
+
starList = MemoryTracker::genLists(4);
glPushMatrix();
@@ -382,8 +394,12 @@ void LevelRenderer::setLevel(int playerIndex, MultiPlayerLevel* level) {
// tile entities in the world dissappear We should only do this when
// actually exiting the game, so only when the primary player sets there
// level to NULL
- if (playerIndex == ProfileManager.GetPrimaryPad())
+ if (playerIndex == ProfileManager.GetPrimaryPad()) {
+ EnterCriticalSection(&m_csRenderableTileEntities);
renderableTileEntities.clear();
+ m_renderableTileEntitiesPendingRemoval.clear();
+ LeaveCriticalSection(&m_csRenderableTileEntities);
+ }
}
}
@@ -563,14 +579,14 @@ void LevelRenderer::renderEntities(Vec3* cam, Culler* culler, float a) {
bool shouldRender =
(entity->shouldRender(cam) &&
- (entity->noCulling || culler->isVisible(entity->bb)));
+ (entity->noCulling || culler->isVisible(&entity->bb)));
// Render the mob if the mob's leash holder is within the culler
if (!shouldRender && entity->instanceof(eTYPE_MOB)) {
std::shared_ptr mob = std::dynamic_pointer_cast(entity);
if (mob->isLeashed() && (mob->getLeashHolder() != NULL)) {
std::shared_ptr leashHolder = mob->getLeashHolder();
- shouldRender = culler->isVisible(leashHolder->bb);
+ shouldRender = culler->isVisible(&leashHolder->bb);
}
}
@@ -610,35 +626,12 @@ void LevelRenderer::renderEntities(Vec3* cam, Culler* culler, float a) {
// Don't render if it isn't in the same dimension as this player
if (!isGlobalIndexInSameDimension(idx, level[playerIndex])) continue;
- for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();
- it2++) {
+ for (AUTO_VAR(it2, it->second.tiles.begin());
+ it2 != it->second.tiles.end(); it2++) {
TileEntityRenderDispatcher::instance->render(*it2, a);
}
}
- // Now consider if any of these renderable tile entities have been flagged
- // for removal, and if so, remove
- for (AUTO_VAR(it, renderableTileEntities.begin());
- it != renderableTileEntities.end();) {
- int idx = it->first;
-
- for (AUTO_VAR(it2, it->second.begin()); it2 != it->second.end();) {
- // If it has been flagged for removal, remove
- if ((*it2)->shouldRemoveForRender()) {
- it2 = it->second.erase(it2);
- } else {
- it2++;
- }
- }
-
- // If there aren't any entities left for this key, then delete the key
- if (it->second.size() == 0) {
- it = renderableTileEntities.erase(it);
- } else {
- it++;
- }
- }
-
LeaveCriticalSection(&m_csRenderableTileEntities);
mc->gameRenderer->turnOffLightLayer(a); // 4J - brought forward from 1.8.2
@@ -714,6 +707,8 @@ void LevelRenderer::resortChunks(int xc, int yc, int zc) {
int LevelRenderer::render(std::shared_ptr player, int layer,
double alpha, bool updateChunks) {
+ FRAME_PROFILE_SCOPE(Terrain);
+
int playerIndex = mc->player->GetXboxPad();
// 4J - added - if the number of players has changed, we need to rebuild
@@ -753,62 +748,98 @@ int LevelRenderer::render(std::shared_ptr player, int layer,
}
Lighting::turnOff();
glColor4f(1, 1, 1, 1);
- glColor4f(1, 1, 1, 1);
+ mc->gameRenderer->turnOnLightLayer(alpha);
int count = renderChunks(0, (int)chunks[playerIndex].length, layer, alpha);
-
+ mc->gameRenderer->turnOffLightLayer(alpha);
return count;
}
-
int LevelRenderer::renderChunks(int from, int to, int layer, double alpha) {
- int playerIndex = mc->player->GetXboxPad(); // 4J added
-
- // 4J - cut down version, we're not using offsetted render lists, or a
- // sorted chunk list, anymore
- mc->gameRenderer->turnOnLightLayer(
- alpha); // 4J - brought forward from 1.8.2
+ int playerIndex = mc->player->GetXboxPad();
+ if (chunks[playerIndex].data == NULL) return 0;
+ mc->gameRenderer->turnOnLightLayer(alpha);
std::shared_ptr player = mc->cameraTargetPlayer;
double xOff = player->xOld + (player->x - player->xOld) * alpha;
double yOff = player->yOld + (player->y - player->yOld) * alpha;
double zOff = player->zOld + (player->z - player->zOld) * alpha;
glPushMatrix();
+
glTranslatef((float)-xOff, (float)-yOff, (float)-zOff);
+
bool first = true;
int count = 0;
ClipChunk* pClipChunk = chunks[playerIndex].data;
unsigned char emptyFlag = LevelRenderer::CHUNK_FLAG_EMPTY0 << layer;
- for (int i = 0; i < chunks[playerIndex].length; i++, pClipChunk++) {
- if (!pClipChunk->visible)
- continue; // This will be set if the chunk isn't visible, or isn't
- // compiled, or has both empty flags set
- if (pClipChunk->globalIdx == -1)
- continue; // Not sure if we should ever encounter this... TODO
- // check
- if ((globalChunkFlags[pClipChunk->globalIdx] & emptyFlag) == emptyFlag)
- continue; // Check that this particular layer isn't empty
+ static thread_local std::vector sortList;
+ sortList.clear();
+ if (sortList.capacity() < (size_t)chunks[playerIndex].length) {
+ sortList.reserve(chunks[playerIndex].length);
+ }
+ {
+ FRAME_PROFILE_SCOPE(ChunkCollect);
+ for (int i = 0; i < chunks[playerIndex].length; i++, pClipChunk++) {
+ if (!pClipChunk->visible)
+ continue; // This will be set if the chunk isn't visible, or
+ // isn't compiled, or has both empty flags set
+ if (pClipChunk->globalIdx == -1)
+ continue; // Not sure if we should ever encounter this...
+ // TODO check
+ if ((globalChunkFlags[pClipChunk->globalIdx] & emptyFlag) ==
+ emptyFlag)
+ continue;
- // List can be calculated directly from the chunk's global idex
- int list = pClipChunk->globalIdx * 2 + layer;
- list += chunkLists;
-
- if (RenderManager.CBuffCall(list, first)) {
- first = false;
+ sortList.push_back(pClipChunk);
}
- count++;
+ // he sorts me till i
+ std::sort(sortList.begin(), sortList.end(),
+ [xOff, yOff, zOff, layer](ClipChunk* a, ClipChunk* b) {
+ float dxA = (float)((a->chunk->x + 8.0f) - xOff);
+ float dyA = (float)((a->chunk->y + 8.0f) - yOff);
+ float dzA = (float)((a->chunk->z + 8.0f) - zOff);
+ float distSqA = dxA * dxA + dyA * dyA + dzA * dzA;
+
+ float dxB = (float)((b->chunk->x + 8.0f) - xOff);
+ float dyB = (float)((b->chunk->y + 8.0f) - yOff);
+ float dzB = (float)((b->chunk->z + 8.0f) - zOff);
+ float distSqB = dxB * dxB + dyB * dyB + dzB * dzB;
+
+ if (layer == 0)
+ return distSqA < distSqB; // Opaque: Closest first
+ return distSqA > distSqB; // Transparent: Furthest
+ // first
+ });
+ }
+
+ {
+ FRAME_PROFILE_SCOPE(ChunkPlayback);
+ for (ClipChunk* chunk : sortList) {
+ int list = chunk->globalIdx * 2 + layer;
+ list += chunkLists;
+
+ // 4jcraft: replaced glPushMatrix/glTranslatef/glPopMatrix per chunk
+ // no more full MVP upload per chunk, can also be bkwards compat
+ RenderManager.SetChunkOffset((float)chunk->chunk->x,
+ (float)chunk->chunk->y,
+ (float)chunk->chunk->z);
+
+ if (RenderManager.CBuffCall(list, first)) {
+ first = false;
+ }
+ count++;
+ }
+ RenderManager.SetChunkOffset(0.f, 0.f, 0.f);
}
glPopMatrix();
- mc->gameRenderer->turnOffLightLayer(
- alpha); // 4J - brought forward from 1.8.2
-
+ mc->gameRenderer->turnOffLightLayer(alpha);
return count;
}
@@ -882,10 +913,10 @@ void LevelRenderer::renderSky(float alpha) {
glDisable(GL_TEXTURE_2D);
int playerIndex = mc->player->GetXboxPad();
- Vec3* sc = level[playerIndex]->getSkyColor(mc->cameraTargetPlayer, alpha);
- float sr = (float)sc->x;
- float sg = (float)sc->y;
- float sb = (float)sc->z;
+ Vec3 sc = level[playerIndex]->getSkyColor(mc->cameraTargetPlayer, alpha);
+ float sr = (float)sc.x;
+ float sg = (float)sc.y;
+ float sb = (float)sc.z;
if (mc->options->anaglyph3d) {
float srr = (sr * 30 + sg * 59 + sb * 11) / 100;
@@ -1024,7 +1055,7 @@ void LevelRenderer::renderSky(float alpha) {
glColor3f(0, 0, 0);
double yy =
- mc->player->getPos(alpha)->y -
+ mc->player->getPos(alpha).y -
level[playerIndex]->getHorizonHeight(); // 4J - getHorizonHeight moved
// forward from 1.2.3
if (yy < 0) {
@@ -1062,10 +1093,10 @@ void LevelRenderer::renderHaloRing(float alpha) {
int playerIndex = mc->player->GetXboxPad();
- Vec3* sc = level[playerIndex]->getSkyColor(mc->cameraTargetPlayer, alpha);
- float sr = (float)sc->x;
- float sg = (float)sc->y;
- float sb = (float)sc->z;
+ Vec3 sc = level[playerIndex]->getSkyColor(mc->cameraTargetPlayer, alpha);
+ float sr = (float)sc.x;
+ float sg = (float)sc.y;
+ float sb = (float)sc.z;
// Rough lumninance calculation
float Y = (sr + sr + sb + sg + sg + sg) / 6;
@@ -1137,10 +1168,10 @@ void LevelRenderer::renderClouds(float alpha) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- Vec3* cc = level[playerIndex]->getCloudColor(alpha);
- float cr = (float)cc->x;
- float cg = (float)cc->y;
- float cb = (float)cc->z;
+ Vec3 cc = level[playerIndex]->getCloudColor(alpha);
+ float cr = (float)cc.x;
+ float cg = (float)cc.y;
+ float cb = (float)cc.z;
if (mc->options->anaglyph3d) {
float crr = (cr * 30 + cg * 59 + cb * 11) / 100;
@@ -1434,10 +1465,10 @@ void LevelRenderer::renderAdvancedClouds(float alpha) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- Vec3* cc = level[playerIndex]->getCloudColor(alpha);
- float cr = (float)cc->x;
- float cg = (float)cc->y;
- float cb = (float)cc->z;
+ Vec3 cc = level[playerIndex]->getCloudColor(alpha);
+ float cr = (float)cc.x;
+ float cg = (float)cc.y;
+ float cb = (float)cc.z;
if (mc->options->anaglyph3d) {
float crr = (cr * 30 + cg * 59 + cb * 11) / 100;
@@ -1642,7 +1673,40 @@ void LevelRenderer::renderAdvancedClouds(float alpha) {
bool LevelRenderer::updateDirtyChunks() {
#if defined(_LARGE_WORLDS)
- std::list > nearestClipChunks;
+ struct NearestClipChunkSet {
+ std::array, MAX_CONCURRENT_CHUNK_REBUILDS>
+ items;
+ int count = 0;
+
+ bool empty() const noexcept { return count == 0; }
+ int size() const noexcept { return count; }
+
+ bool wouldAccept(int distSqWeighted) const noexcept {
+ return (count < MAX_CONCURRENT_CHUNK_REBUILDS) ||
+ (distSqWeighted < items[count - 1].second);
+ }
+
+ void insert(ClipChunk* chunk, int distSqWeighted) noexcept {
+ int pos = 0;
+ while ((pos < count) && (items[pos].second <= distSqWeighted)) {
+ ++pos;
+ }
+
+ if ((count == MAX_CONCURRENT_CHUNK_REBUILDS) &&
+ (pos >= MAX_CONCURRENT_CHUNK_REBUILDS)) {
+ return;
+ }
+
+ const int newCount = (count < MAX_CONCURRENT_CHUNK_REBUILDS)
+ ? (count + 1)
+ : MAX_CONCURRENT_CHUNK_REBUILDS;
+ for (int i = newCount - 1; i > pos; --i) {
+ items[i] = items[i - 1];
+ }
+ items[pos] = std::pair(chunk, distSqWeighted);
+ count = newCount;
+ }
+ } nearestClipChunks;
#endif
ClipChunk* nearChunk = NULL; // Nearest chunk that is dirty
@@ -1651,225 +1715,313 @@ bool LevelRenderer::updateDirtyChunks() {
// Set a flag if we should only rebuild existing chunks, not create anything
// new
- unsigned int memAlloc = RenderManager.CBuffSize(-1);
- /*
- static int throttle = 0;
- if( ( throttle % 100 ) == 0 )
{
- app.DebugPrintf("CBuffSize: %d\n",memAlloc/(1024*1024));
- }
- throttle++;
- */
- PIXAddNamedCounter(((float)memAlloc) / (1024.0f * 1024.0f),
- "Command buffer allocations");
- bool onlyRebuild = (memAlloc >= MAX_COMMANDBUFFER_ALLOCATIONS);
- EnterCriticalSection(&m_csDirtyChunks);
+ FRAME_PROFILE_SCOPE(ChunkDirtyScan);
- // Move any dirty chunks stored in the lock free stack into global flags
- int index = 0;
-
- do {
- // See comment on dirtyChunksLockFreeStack.Push() regarding details of
- // this casting/subtracting -2.
- index = (size_t)dirtyChunksLockFreeStack.Pop();
-#if defined(_CRITICAL_CHUNKS)
- int oldIndex = index;
- index &= 0x0fffffff; // remove the top bit that marked the chunk as
- // non-critical
-#endif
- if (index == 1)
- dirtyChunkPresent =
- true; // 1 is a special value passed to let this thread know
- // that a chunk which isn't on this stack has been set to
- // dirty
- else if (index > 1) {
- int i2 = index - 2;
- if (i2 >= DIMENSION_OFFSETS[2]) {
- i2 -= DIMENSION_OFFSETS[2];
- int y2 = i2 & (CHUNK_Y_COUNT - 1);
- i2 /= CHUNK_Y_COUNT;
- int z2 = i2 / MAX_LEVEL_RENDER_SIZE[2];
- int x2 = i2 - z2 * MAX_LEVEL_RENDER_SIZE[2];
- x2 -= MAX_LEVEL_RENDER_SIZE[2] / 2;
- z2 -= MAX_LEVEL_RENDER_SIZE[2] / 2;
- }
- setGlobalChunkFlag(index - 2, CHUNK_FLAG_DIRTY);
-
-#if defined(_CRITICAL_CHUNKS)
- if (!(oldIndex & 0x10000000)) // was this chunk not marked as
- // non-critical. Ugh double negatives
- {
- setGlobalChunkFlag(index - 2, CHUNK_FLAG_CRITICAL);
- }
-#endif
-
- dirtyChunkPresent = true;
+ unsigned int memAlloc = RenderManager.CBuffSize(-1);
+ /*
+ static int throttle = 0;
+ if( ( throttle % 100 ) == 0 )
+ {
+ app.DebugPrintf("CBuffSize: %d\n",memAlloc/(1024*1024));
}
- } while (index);
+ throttle++;
+ */
+ PIXAddNamedCounter(((float)memAlloc) / (1024.0f * 1024.0f),
+ "Command buffer allocations");
+ bool onlyRebuild = (memAlloc >= MAX_COMMANDBUFFER_ALLOCATIONS);
+ EnterCriticalSection(&m_csDirtyChunks);
- // Only bother searching round all the chunks if we have some dirty chunk(s)
- if (dirtyChunkPresent) {
- lastDirtyChunkFound = System::currentTimeMillis();
- PIXBeginNamedEvent(0, "Finding nearest chunk\n");
+ // Move any dirty chunks stored in the lock free stack into global flags
+ int index = 0;
-#if defined(_LARGE_WORLDS)
- int maxNearestChunks = MAX_CONCURRENT_CHUNK_REBUILDS;
- // 4J Stu - On XboxOne we should cut this down if in a constrained state
- // so the saving threads get more time
+ do {
+ // See comment on dirtyChunksLockFreeStack.Push() regarding details
+ // of this casting/subtracting -2.
+ index = (size_t)dirtyChunksLockFreeStack.Pop();
+#ifdef _CRITICAL_CHUNKS
+ int oldIndex = index;
+ index &= 0x0fffffff; // remove the top bit that marked the chunk as
+ // non-critical
#endif
- // Find nearest chunk that is dirty
- for (int p = 0; p < XUSER_MAX_COUNT; p++) {
- // It's possible that the localplayers member can be set to NULL on
- // the main thread when a player chooses to exit the game So take a
- // reference to the player object now. As it is a shared_ptr it
- // should live as long as we need it
- std::shared_ptr player = mc->localplayers[p];
- if (player == NULL) continue;
- if (chunks[p].data == NULL) continue;
- if (level[p] == NULL) continue;
- if (chunks[p].length != xChunks * zChunks * CHUNK_Y_COUNT) continue;
- int px = (int)player->x;
- int py = (int)player->y;
- int pz = (int)player->z;
+ if (index == 1)
+ dirtyChunkPresent =
+ true; // 1 is a special value passed to let this thread
+ // know that a chunk which isn't on this stack has
+ // been set to dirty
+ else if (index > 1) {
+ int i2 = index - 2;
+ if (i2 >= DIMENSION_OFFSETS[2]) {
+ i2 -= DIMENSION_OFFSETS[2];
+ int y2 = i2 & (CHUNK_Y_COUNT - 1);
+ i2 /= CHUNK_Y_COUNT;
+ int z2 = i2 / MAX_LEVEL_RENDER_SIZE[2];
+ int x2 = i2 - z2 * MAX_LEVEL_RENDER_SIZE[2];
+ x2 -= MAX_LEVEL_RENDER_SIZE[2] / 2;
+ z2 -= MAX_LEVEL_RENDER_SIZE[2] / 2;
+ }
+ setGlobalChunkFlag(index - 2, CHUNK_FLAG_DIRTY);
- // app.DebugPrintf("!! %d %d %d, %d %d %d {%d,%d}
- //",px,py,pz,stackChunkDirty,nonStackChunkDirty,onlyRebuild,
- // xChunks, zChunks);
+#ifdef _CRITICAL_CHUNKS
+ if (!(oldIndex &
+ 0x10000000)) // was this chunk not marked as
+ // non-critical. Ugh double negatives
+ {
+ setGlobalChunkFlag(index - 2, CHUNK_FLAG_CRITICAL);
+ }
+#endif
- int considered = 0;
- int wouldBeNearButEmpty = 0;
- for (int x = 0; x < xChunks; x++) {
- for (int z = 0; z < zChunks; z++) {
- for (int y = 0; y < CHUNK_Y_COUNT; y++) {
- ClipChunk* pClipChunk =
- &chunks[p][(z * yChunks + y) * xChunks + x];
- // Get distance to this chunk - deliberately not calling
- // the chunk's method of doing this to avoid overheads
- // (passing entitie, type conversion etc.) that this
- // involves
- int xd = pClipChunk->xm - px;
- int yd = pClipChunk->ym - py;
- int zd = pClipChunk->zm - pz;
- int distSq = xd * xd + yd * yd + zd * zd;
- int distSqWeighted =
- xd * xd + yd * yd * 4 +
- zd *
- zd; // Weighting against y to prioritise things
- // in same x/z plane as player first
+ dirtyChunkPresent = true;
+ }
+ } while (index);
- if (globalChunkFlags[pClipChunk->globalIdx] &
- CHUNK_FLAG_DIRTY) {
- if ((!onlyRebuild) ||
- globalChunkFlags[pClipChunk->globalIdx] &
- CHUNK_FLAG_COMPILED ||
- (distSq <
- 20 * 20)) // Always rebuild really near things
- // or else building (say) at tower
- // up into empty blocks when we are
- // low on memory will not create
- // render data
- {
- considered++;
- // Is this chunk nearer than our nearest?
+ // Only bother searching round all the chunks if we have some dirty
+ // chunk(s)
+ if (dirtyChunkPresent) {
+ lastDirtyChunkFound = System::currentTimeMillis();
+ PIXBeginNamedEvent(0, "Finding nearest chunk\n");
+
+ // Find nearest chunk that is dirty
+ for (int p = 0; p < XUSER_MAX_COUNT; p++) {
+ // It's possible that the localplayers member can be set to NULL
+ // on the main thread when a player chooses to exit the game So
+ // take a reference to the player object now. As it is a
+ // shared_ptr it should live as long as we need it
+ std::shared_ptr player = mc->localplayers[p];
+ if (player == NULL) continue;
+ if (chunks[p].data == NULL) continue;
+ if (level[p] == NULL) continue;
+ if (chunks[p].length != xChunks * zChunks * CHUNK_Y_COUNT)
+ continue;
+ int px = (int)player->x;
+ int py = (int)player->y;
+ int pz = (int)player->z;
+
+ // app.DebugPrintf("!! %d %d %d, %d %d %d
+ //{%d,%d}
+ //",px,py,pz,stackChunkDirty,nonStackChunkDirty,onlyRebuild,
+ // xChunks, zChunks);
+
+ int considered = 0;
+ int wouldBeNearButEmpty = 0;
+ for (int x = 0; x < xChunks; x++) {
+ for (int z = 0; z < zChunks; z++) {
+ for (int y = 0; y < CHUNK_Y_COUNT; y++) {
+ ClipChunk* pClipChunk =
+ &chunks[p][(z * yChunks + y) * xChunks + x];
+ // Get distance to this chunk - deliberately not
+ // calling the chunk's method of doing this to avoid
+ // overheads (passing entitie, type conversion etc.)
+ // that this involves
+ int xd = pClipChunk->xm - px;
+ int yd = pClipChunk->ym - py;
+ int zd = pClipChunk->zm - pz;
+ int distSq = xd * xd + yd * yd + zd * zd;
+ int distSqWeighted =
+ xd * xd + yd * yd * 4 +
+ zd * zd; // Weighting against y to prioritise
+ // things in same x/z plane as player
+ // first
+
+ if (globalChunkFlags[pClipChunk->globalIdx] &
+ CHUNK_FLAG_DIRTY) {
+ if ((!onlyRebuild) ||
+ globalChunkFlags[pClipChunk->globalIdx] &
+ CHUNK_FLAG_COMPILED ||
+ (distSq <
+ 20 * 20)) // Always rebuild really near
+ // things or else building (say)
+ // at tower up into empty blocks
+ // when we are low on memory
+ // will not create render data
+ {
+ considered++;
+ // Is this chunk nearer than our nearest?
#if defined(_LARGE_WORLDS)
- bool isNearer = nearestClipChunks.empty();
- AUTO_VAR(itNearest, nearestClipChunks.begin());
- for (; itNearest != nearestClipChunks.end();
- ++itNearest) {
- isNearer =
- distSqWeighted < itNearest->second;
- if (isNearer) break;
- }
- isNearer =
- isNearer || (nearestClipChunks.size() <
- maxNearestChunks);
+ bool isNearer =
+ nearestClipChunks.wouldAccept(
+ distSqWeighted);
#else
- bool isNearer = distSqWeighted < minDistSq;
+ bool isNearer = distSqWeighted < minDistSq;
#endif
#if defined(_CRITICAL_CHUNKS)
- // AP - this will make sure that if a deferred
- // grouping has started, only critical chunks go
- // into that grouping, even if a non-critical
- // chunk is closer.
- if ((!veryNearCount && isNearer) ||
- (distSq < 20 * 20 &&
- (globalChunkFlags[pClipChunk->globalIdx] &
- CHUNK_FLAG_CRITICAL)))
+ // AP - this will make sure that if a
+ // deferred grouping has started, only
+ // critical chunks go into that grouping,
+ // even if a non-critical chunk is closer.
+ if ((!veryNearCount && isNearer) ||
+ (distSq < 20 * 20 &&
+ (globalChunkFlags[pClipChunk
+ ->globalIdx] &
+ CHUNK_FLAG_CRITICAL)))
#else
- if (isNearer)
+ if (isNearer)
#endif
- {
- // At this point we've got a chunk that we
- // would like to consider for rendering, at
- // least based on its proximity to the
- // player(s). Its *quite* quick to generate
- // empty render data for render chunks, but
- // if we let the rebuilding do that then the
- // after rebuilding we will have to start
- // searching for the next nearest chunk from
- // scratch again. Instead, its better to
- // detect empty chunks at this stage, flag
- // them up as not dirty (and empty), and
- // carry on. The levelchunk's
- // isRenderChunkEmpty method can be quite
- // optimal as it can make use of the chunk's
- // data compression to detect emptiness
- // without actually testing as many data
- // items as uncompressed data would.
- Chunk* chunk = pClipChunk->chunk;
- LevelChunk* lc = level[p]->getChunkAt(
- chunk->x, chunk->z);
- if (!lc->isRenderChunkEmpty(y * 16)) {
- nearChunk = pClipChunk;
- minDistSq = distSqWeighted;
+ {
+ // At this point we've got a chunk that
+ // we would like to consider for
+ // rendering, at least based on its
+ // proximity to the player(s). Its
+ // *quite* quick to generate empty
+ // render data for render chunks, but if
+ // we let the rebuilding do that then
+ // the after rebuilding we will have to
+ // start searching for the next nearest
+ // chunk from scratch again. Instead,
+ // its better to detect empty chunks at
+ // this stage, flag them up as not dirty
+ // (and empty), and carry on. The
+ // levelchunk's isRenderChunkEmpty
+ // method can be quite optimal as it can
+ // make use of the chunk's data
+ // compression to detect emptiness
+ // without actually testing as many data
+ // items as uncompressed data would.
+ Chunk* chunk = pClipChunk->chunk;
+ LevelChunk* lc = level[p]->getChunkAt(
+ chunk->x, chunk->z);
+ if (!lc->isRenderChunkEmpty(y * 16)) {
+ nearChunk = pClipChunk;
+ minDistSq = distSqWeighted;
#if defined(_LARGE_WORLDS)
- nearestClipChunks.insert(
- itNearest,
- std::pair(
- nearChunk, minDistSq));
- if (nearestClipChunks.size() >
- maxNearestChunks) {
- nearestClipChunks.pop_back();
+ nearestClipChunks.insert(nearChunk,
+ minDistSq);
+#endif
+ } else {
+ chunk->clearDirty();
+ globalChunkFlags[pClipChunk
+ ->globalIdx] |=
+ CHUNK_FLAG_EMPTYBOTH;
+ wouldBeNearButEmpty++;
}
-#endif
- } else {
- chunk->clearDirty();
- globalChunkFlags[pClipChunk
- ->globalIdx] |=
- CHUNK_FLAG_EMPTYBOTH;
- wouldBeNearButEmpty++;
}
- }
#if defined(_CRITICAL_CHUNKS)
- // AP - is the chunk near and also critical
- if (distSq < 20 * 20 &&
- ((globalChunkFlags[pClipChunk->globalIdx] &
- CHUNK_FLAG_CRITICAL)))
+ // AP - is the chunk near and also critical
+ if (distSq < 20 * 20 &&
+ ((globalChunkFlags[pClipChunk
+ ->globalIdx] &
+ CHUNK_FLAG_CRITICAL)))
#else
- if (distSq < 20 * 20)
+ if (distSq < 20 * 20)
#endif
- {
- veryNearCount++;
+ {
+ veryNearCount++;
+ }
}
}
}
}
}
+ // app.DebugPrintf("[%d,%d,%d]\n",nearestClipChunks.empty(),considered,wouldBeNearButEmpty);
}
- // app.DebugPrintf("[%d,%d,%d]\n",nearestClipChunks.empty(),considered,wouldBeNearButEmpty);
+ PIXEndNamedEvent();
}
- PIXEndNamedEvent();
}
Chunk* chunk = NULL;
#if defined(_LARGE_WORLDS)
if (!nearestClipChunks.empty()) {
int index = 0;
- for (AUTO_VAR(it, nearestClipChunks.begin());
- it != nearestClipChunks.end(); ++it) {
- chunk = it->first->chunk;
+ {
+ FRAME_PROFILE_SCOPE(ChunkRebuildSchedule);
+ for (int i = 0; i < nearestClipChunks.size(); ++i) {
+ chunk = nearestClipChunks.items[i].first->chunk;
+ // If this chunk is very near, then move the renderer into a
+ // deferred mode. This won't commit any command buffers for
+ // rendering until we call CBuffDeferredModeEnd(), allowing us
+ // to group any near changes into an atomic unit. This is
+ // essential so we don't temporarily create any holes in the
+ // environment whilst updating one chunk and not the neighbours.
+ // The "ver near" aspect of this is just a cosmetic nicety -
+ // exactly the same thing would happen further away, but we just
+ // don't care about it so much from terms of visual impact.
+ if (veryNearCount > 0) {
+ RenderManager.CBuffDeferredModeStart();
+ }
+ // Build this chunk & return false to continue processing
+ chunk->clearDirty();
+ // Take a copy of the details that are required for chunk
+ // rebuilding, and rebuild That instead of the original chunk
+ // data. This is done within the m_csDirtyChunks critical
+ // section, which means that any chunks can't be repositioned
+ // whilst we are doing this copy. The copy will then be
+ // guaranteed to be consistent whilst rebuilding takes place
+ // outside of that critical section.
+ permaChunk[index].makeCopyForRebuild(chunk);
+ ++index;
+ }
+ LeaveCriticalSection(&m_csDirtyChunks);
+
+ --index; // Bring it back into 0 counted range
+
+ for (int i = MAX_CHUNK_REBUILD_THREADS - 1; i >= 0; --i) {
+ // Set the events that won't run
+ if ((i + 1) > index)
+ s_rebuildCompleteEvents->Set(i);
+ else
+ break;
+ }
+ }
+
+ for (; index >= 0; --index) {
+ bool bAtomic = false;
+ if ((veryNearCount > 0))
+ bAtomic = true; // MGH - if veryNearCount, then we're trying
+ // to rebuild atomically, so do it all on the
+ // main thread
+
+ if (bAtomic || (index == 0)) {
+ // PIXBeginNamedEvent(0,"Rebuilding near chunk %d %d
+ // %d",chunk->x, chunk->y, chunk->z); static int64_t
+ // totalTime =
+ // 0; static int64_t countTime = 0;
+ // int64_t startTime = System::currentTimeMillis();
+
+ // app.DebugPrintf("Rebuilding permaChunk %d\n", index);
+
+ {
+ FRAME_PROFILE_SCOPE(ChunkRebuildBody);
+ permaChunk[index].rebuild();
+ }
+
+ if (index != 0) {
+ FRAME_PROFILE_SCOPE(ChunkRebuildSchedule);
+ s_rebuildCompleteEvents->Set(
+ index - 1); // MGH - this rebuild happening on the main
+ // thread instead, mark the thread it
+ // should have been running on as complete
+ }
+
+ // int64_t endTime = System::currentTimeMillis();
+ // totalTime += (endTime - startTime);
+ // countTime++;
+ // printf("%d : %f\n", countTime, (float)totalTime
+ /// (float)countTime); PIXEndNamedEvent();
+ }
+ // 4J Stu - Ignore this path when in constrained mode on Xbox One
+ else {
+ // Activate thread to rebuild this chunk
+ FRAME_PROFILE_SCOPE(ChunkRebuildSchedule);
+ s_activationEventA[index - 1]->Set();
+ }
+ }
+
+ // Wait for the other threads to be done as well
+ {
+ FRAME_PROFILE_SCOPE(ChunkRebuildSchedule);
+ s_rebuildCompleteEvents->WaitForAll(INFINITE);
+ }
+ }
+#else
+ if (nearChunk) {
+ chunk = nearChunk->chunk;
+ PIXBeginNamedEvent(0, "Rebuilding near chunk %d %d %d", chunk->x,
+ chunk->y, chunk->z);
+ static Chunk permaChunk;
+ {
+ FRAME_PROFILE_SCOPE(ChunkRebuildSchedule);
// If this chunk is very near, then move the renderer into a
// deferred mode. This won't commit any command buffers for
// rendering until we call CBuffDeferredModeEnd(), allowing us to
@@ -1890,92 +2042,16 @@ bool LevelRenderer::updateDirtyChunks() {
// means that any chunks can't be repositioned whilst we are doing
// this copy. The copy will then be guaranteed to be consistent
// whilst rebuilding takes place outside of that critical section.
- permaChunk[index].makeCopyForRebuild(chunk);
- ++index;
+ permaChunk.makeCopyForRebuild(chunk);
+ LeaveCriticalSection(&m_csDirtyChunks);
}
- LeaveCriticalSection(&m_csDirtyChunks);
-
- --index; // Bring it back into 0 counted range
-
- for (int i = MAX_CHUNK_REBUILD_THREADS - 1; i >= 0; --i) {
- // Set the events that won't run
- if ((i + 1) > index)
- s_rebuildCompleteEvents->Set(i);
- else
- break;
- }
-
- for (; index >= 0; --index) {
- bool bAtomic = false;
- if ((veryNearCount > 0))
- bAtomic = true; // MGH - if veryNearCount, then we're trying
- // to rebuild atomically, so do it all on the
- // main thread
-
- if (bAtomic || (index == 0)) {
- // PIXBeginNamedEvent(0,"Rebuilding near chunk %d %d
- // %d",chunk->x, chunk->y, chunk->z); static int64_t
- // totalTime =
- // 0; static int64_t countTime = 0;
- // int64_t startTime = System::currentTimeMillis();
-
- // app.DebugPrintf("Rebuilding permaChunk %d\n", index);
-
- permaChunk[index].rebuild();
-
- if (index != 0)
- s_rebuildCompleteEvents->Set(
- index - 1); // MGH - this rebuild happening on the main
- // thread instead, mark the thread it
- // should have been running on as complete
-
- // int64_t endTime = System::currentTimeMillis();
- // totalTime += (endTime - startTime);
- // countTime++;
- // printf("%d : %f\n", countTime, (float)totalTime
- /// (float)countTime); PIXEndNamedEvent();
- }
- // 4J Stu - Ignore this path when in constrained mode on Xbox One
- else {
- // Activate thread to rebuild this chunk
- s_activationEventA[index - 1]->Set();
- }
- }
-
- // Wait for the other threads to be done as well
- s_rebuildCompleteEvents->WaitForAll(INFINITE);
- }
-#else
- if (nearChunk) {
- chunk = nearChunk->chunk;
- PIXBeginNamedEvent(0, "Rebuilding near chunk %d %d %d", chunk->x,
- chunk->y, chunk->z);
- // If this chunk is very near, then move the renderer into a deferred
- // mode. This won't commit any command buffers for rendering until we
- // call CBuffDeferredModeEnd(), allowing us to group any near changes
- // into an atomic unit. This is essential so we don't temporarily create
- // any holes in the environment whilst updating one chunk and not the
- // neighbours. The "ver near" aspect of this is just a cosmetic nicety -
- // exactly the same thing would happen further away, but we just don't
- // care about it so much from terms of visual impact.
- if (veryNearCount > 0) {
- RenderManager.CBuffDeferredModeStart();
- }
- // Build this chunk & return false to continue processing
- chunk->clearDirty();
- // Take a copy of the details that are required for chunk rebuilding,
- // and rebuild That instead of the original chunk data. This is done
- // within the m_csDirtyChunks critical section, which means that any
- // chunks can't be repositioned whilst we are doing this copy. The copy
- // will then be guaranteed to be consistent whilst rebuilding takes
- // place outside of that critical section.
- static Chunk permaChunk;
- permaChunk.makeCopyForRebuild(chunk);
- LeaveCriticalSection(&m_csDirtyChunks);
// static int64_t totalTime = 0;
// static int64_t countTime = 0;
// int64_t startTime = System::currentTimeMillis();
- permaChunk.rebuild();
+ {
+ FRAME_PROFILE_SCOPE(ChunkRebuildBody);
+ permaChunk.rebuild();
+ }
// int64_t endTime = System::currentTimeMillis();
// totalTime += (endTime - startTime);
// countTime++;
@@ -2117,22 +2193,27 @@ void LevelRenderer::renderDestroyAnimation(Tesselator* t,
glPopMatrix();
}
}
-
void LevelRenderer::renderHitOutline(std::shared_ptr player,
HitResult* h, int mode, float a) {
if (mode == 0 && h->type == HitResult::TILE) {
int iPad = mc->player->GetXboxPad(); // 4J added
+ const float ss = 0.002f;
+
// 4J-PB - If Display HUD is false, don't render the hit outline
if (app.GetGameSettings(iPad, eGameSetting_DisplayHUD) == 0) return;
-
- glEnable(GL_BLEND);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glColor4f(0, 0, 0, 0.4f);
- glLineWidth(2.0f);
+ RenderManager.StateSetLightingEnable(false);
glDisable(GL_TEXTURE_2D);
- glDepthMask(false);
- float ss = 0.002f;
+
+ // draw hit outline
+ RenderManager.StateSetColour(0.0f, 0.0f, 0.0f, 0.4f);
+ RenderManager.StateSetLineWidth(1.0f);
+
+ // hack
+ glDepthFunc(GL_LEQUAL);
+ glEnable(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(-2.0f, -2.0f);
+
int tileId = level[iPad]->getTile(h->x, h->y, h->z);
if (tileId > 0) {
@@ -2140,46 +2221,71 @@ void LevelRenderer::renderHitOutline(std::shared_ptr player,
double xo = player->xOld + (player->x - player->xOld) * a;
double yo = player->yOld + (player->y - player->yOld) * a;
double zo = player->zOld + (player->z - player->zOld) * a;
- render(Tile::tiles[tileId]
- ->getTileAABB(level[iPad], h->x, h->y, h->z)
- ->grow(ss, ss, ss)
- ->cloneMove(-xo, -yo, -zo));
+
+ AABB bb = Tile::tiles[tileId]
+ ->getTileAABB(level[iPad], h->x, h->y, h->z)
+ .grow(ss, ss, ss)
+ .move(-xo, -yo, -zo);
+
+ render(&bb);
}
- glDepthMask(true);
+
+ // restore
+ glDisable(GL_POLYGON_OFFSET_LINE);
+ RenderManager.StateSetColour(1.0f, 1.0f, 1.0f, 1.0f);
glEnable(GL_TEXTURE_2D);
- glDisable(GL_BLEND);
+ RenderManager.StateSetLightingEnable(true);
}
}
void LevelRenderer::render(AABB* b) {
Tesselator* t = Tesselator::getInstance();
+ RenderManager.StateSetLightingEnable(false);
+ glDisable(GL_TEXTURE_2D);
+ RenderManager.StateSetColour(0.0f, 0.0f, 0.0f, 0.4f);
- t->begin(GL_LINE_STRIP);
- t->vertex((float)(b->x0), (float)(b->y0), (float)(b->z0));
- t->vertex((float)(b->x1), (float)(b->y0), (float)(b->z0));
- t->vertex((float)(b->x1), (float)(b->y0), (float)(b->z1));
- t->vertex((float)(b->x0), (float)(b->y0), (float)(b->z1));
- t->vertex((float)(b->x0), (float)(b->y0), (float)(b->z0));
- t->end();
-
- t->begin(GL_LINE_STRIP);
- t->vertex((float)(b->x0), (float)(b->y1), (float)(b->z0));
- t->vertex((float)(b->x1), (float)(b->y1), (float)(b->z0));
- t->vertex((float)(b->x1), (float)(b->y1), (float)(b->z1));
- t->vertex((float)(b->x0), (float)(b->y1), (float)(b->z1));
- t->vertex((float)(b->x0), (float)(b->y1), (float)(b->z0));
- t->end();
+ // prevent zfight
+ glEnable(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(-2.0f, -2.0f);
+ // One call please!
t->begin(GL_LINES);
- t->vertex((float)(b->x0), (float)(b->y0), (float)(b->z0));
- t->vertex((float)(b->x0), (float)(b->y1), (float)(b->z0));
- t->vertex((float)(b->x1), (float)(b->y0), (float)(b->z0));
- t->vertex((float)(b->x1), (float)(b->y1), (float)(b->z0));
- t->vertex((float)(b->x1), (float)(b->y0), (float)(b->z1));
- t->vertex((float)(b->x1), (float)(b->y1), (float)(b->z1));
- t->vertex((float)(b->x0), (float)(b->y0), (float)(b->z1));
- t->vertex((float)(b->x0), (float)(b->y1), (float)(b->z1));
+
+ // Bottom
+ t->vertex(b->x0, b->y0, b->z0);
+ t->vertex(b->x1, b->y0, b->z0);
+ t->vertex(b->x1, b->y0, b->z0);
+ t->vertex(b->x1, b->y0, b->z1);
+ t->vertex(b->x1, b->y0, b->z1);
+ t->vertex(b->x0, b->y0, b->z1);
+ t->vertex(b->x0, b->y0, b->z1);
+ t->vertex(b->x0, b->y0, b->z0);
+
+ // Top
+ t->vertex(b->x0, b->y1, b->z0);
+ t->vertex(b->x1, b->y1, b->z0);
+ t->vertex(b->x1, b->y1, b->z0);
+ t->vertex(b->x1, b->y1, b->z1);
+ t->vertex(b->x1, b->y1, b->z1);
+ t->vertex(b->x0, b->y1, b->z1);
+ t->vertex(b->x0, b->y1, b->z1);
+ t->vertex(b->x0, b->y1, b->z0);
+
+ // Vertical
+ t->vertex(b->x0, b->y0, b->z0);
+ t->vertex(b->x0, b->y1, b->z0);
+ t->vertex(b->x1, b->y0, b->z0);
+ t->vertex(b->x1, b->y1, b->z0);
+ t->vertex(b->x1, b->y0, b->z1);
+ t->vertex(b->x1, b->y1, b->z1);
+ t->vertex(b->x0, b->y0, b->z1);
+ t->vertex(b->x0, b->y1, b->z1);
+
t->end();
+ glDisable(GL_POLYGON_OFFSET_LINE);
+ RenderManager.StateSetLightingEnable(true);
+ glEnable(GL_TEXTURE_2D);
+ RenderManager.StateSetColour(1.0f, 1.0f, 1.0f, 1.0f);
}
void LevelRenderer::setDirty(int x0, int y0, int z0, int x1, int y1, int z1,
@@ -2339,8 +2445,11 @@ bool inline clip(float* bb, float* frustum) {
}
+// 4jcraft: optional occlusion culling system, i hope to upgrade it soon
+// gives better performances but mostly breaks chunk rendering
void LevelRenderer::cull(Culler* culler, float a) {
- int playerIndex = mc->player->GetXboxPad(); // 4J added
+ int playerIndex = mc->player->GetXboxPad();
+ if (chunks[playerIndex].data == nullptr) return;
FrustumCuller* fc = (FrustumCuller*)culler;
@@ -2357,28 +2466,310 @@ void LevelRenderer::cull(Culler* culler, float a) {
(fy * -fc->yOff) + (fz * -fc->zOff));
}
- ClipChunk* pClipChunk = chunks[playerIndex].data;
- int vis = 0;
- int total = 0;
- int numWrong = 0;
+#if defined(OCCLUSION_MODE_NONE)
+ // just check if chunk is compiled and non-empty
for (unsigned int i = 0; i < chunks[playerIndex].length; i++) {
- unsigned char flags = pClipChunk->globalIdx == -1
- ? 0
- : globalChunkFlags[pClipChunk->globalIdx];
-
- if ((flags & CHUNK_FLAG_COMPILED) &&
- ((flags & CHUNK_FLAG_EMPTYBOTH) != CHUNK_FLAG_EMPTYBOTH)) {
- bool clipres = clip(pClipChunk->aabb, fdraw);
- pClipChunk->visible = clipres;
- if (pClipChunk->visible) vis++;
- total++;
- } else {
- pClipChunk->visible = false;
+ ClipChunk* cc = &chunks[playerIndex][i];
+ if (cc->globalIdx < 0) {
+ cc->visible = false;
+ continue;
}
- pClipChunk++;
- }
-}
+ unsigned char flags = globalChunkFlags[cc->globalIdx];
+ bool isCompiled = (flags & CHUNK_FLAG_COMPILED) != 0;
+ bool isEmptyBoth =
+ (flags & CHUNK_FLAG_EMPTYBOTH) == CHUNK_FLAG_EMPTYBOTH;
+
+ cc->visible = isCompiled && !isEmptyBoth;
+ }
+
+#elif defined(OCCLUSION_MODE_FRUSTUM)
+ // Just ~~monika~~ frustum culling
+ for (unsigned int i = 0; i < chunks[playerIndex].length; i++) {
+ ClipChunk* cc = &chunks[playerIndex][i];
+ if (cc->globalIdx < 0) {
+ cc->visible = false;
+ continue;
+ }
+
+ unsigned char flags = globalChunkFlags[cc->globalIdx];
+ bool isCompiled = (flags & CHUNK_FLAG_COMPILED) != 0;
+ bool isEmptyBoth =
+ (flags & CHUNK_FLAG_EMPTYBOTH) == CHUNK_FLAG_EMPTYBOTH;
+
+ if (isCompiled && !isEmptyBoth) {
+ float cellBounds[6] = {(float)cc->chunk->x - 0.1f,
+ (float)cc->chunk->y - 0.1f,
+ (float)cc->chunk->z - 0.1f,
+ (float)cc->chunk->x + CHUNK_XZSIZE + 0.1f,
+ (float)cc->chunk->y + CHUNK_SIZE + 0.1f,
+ (float)cc->chunk->z + CHUNK_XZSIZE + 0.1f};
+ cc->visible = clip(cellBounds, fdraw);
+ } else {
+ cc->visible = false;
+ }
+ }
+
+#elif defined(OCCLUSION_MODE_HARDWARE)
+// TODO: Hardware occlusion culling using GPU queries
+// For now, fall back to frustum culling
+#warning \
+ "OCCLUSION_MODE_HARDWARE is not implemented yet, falling back to frustum culling"
+ for (unsigned int i = 0; i < chunks[playerIndex].length; i++) {
+ ClipChunk* cc = &chunks[playerIndex][i];
+ if (cc->globalIdx < 0) {
+ cc->visible = false;
+ continue;
+ }
+
+ unsigned char flags = globalChunkFlags[cc->globalIdx];
+ bool isCompiled = (flags & CHUNK_FLAG_COMPILED) != 0;
+ bool isEmptyBoth =
+ (flags & CHUNK_FLAG_EMPTYBOTH) == CHUNK_FLAG_EMPTYBOTH;
+
+ if (isCompiled && !isEmptyBoth) {
+ float cellBounds[6] = {(float)cc->chunk->x - 0.1f,
+ (float)cc->chunk->y - 0.1f,
+ (float)cc->chunk->z - 0.1f,
+ (float)cc->chunk->x + CHUNK_XZSIZE + 0.1f,
+ (float)cc->chunk->y + CHUNK_SIZE + 0.1f,
+ (float)cc->chunk->z + CHUNK_XZSIZE + 0.1f};
+ cc->visible = clip(cellBounds, fdraw);
+ } else {
+ cc->visible = false;
+ }
+ }
+
+#elif defined(OCCLUSION_MODE_BFS)
+ // Experimental BFS occlusion culling.
+ // Check https://tomcc.github.io/2014/08/31/visibility-1.html
+ // And https://tomcc.github.io/2014/08/31/visibility-2.html
+ // And finally https://en.wikipedia.org/wiki/Breadth-first_search
+ std::shared_ptr player = mc->cameraTargetPlayer;
+ float camX = (float)(player->xOld + (player->x - player->xOld) * a);
+ float camY = (float)(player->yOld + (player->y - player->yOld) * a);
+ float camZ = (float)(player->zOld + (player->z - player->zOld) * a);
+
+ auto intFloorDiv = [](int v, int div) {
+ if (v < 0 && v % div != 0) return (v / div) - 1;
+ return v / div;
+ };
+
+ auto floatFloorDiv = [](float v, int div) {
+ int iv = (int)v;
+ if (v < 0 && v != iv) iv--;
+ if (iv < 0 && iv % div != 0) return (iv / div) - 1;
+ return iv / div;
+ };
+
+ int minCx = INT_MAX, minCy = INT_MAX, minCz = INT_MAX;
+ int maxCx = INT_MIN, maxCy = INT_MIN, maxCz = INT_MIN;
+
+ for (unsigned int i = 0; i < chunks[playerIndex].length; i++) {
+ ClipChunk* cc = &chunks[playerIndex][i];
+ cc->visible = false;
+ if (cc->globalIdx < 0) continue;
+
+ int cx = intFloorDiv(cc->chunk->x, CHUNK_XZSIZE);
+ int cy = intFloorDiv(cc->chunk->y, CHUNK_SIZE);
+ int cz = intFloorDiv(cc->chunk->z, CHUNK_XZSIZE);
+
+ if (cx < minCx) minCx = cx;
+ if (cy < minCy) minCy = cy;
+ if (cz < minCz) minCz = cz;
+ if (cx > maxCx) maxCx = cx;
+ if (cy > maxCy) maxCy = cy;
+ if (cz > maxCz) maxCz = cz;
+ }
+
+ if (minCx > maxCx) return;
+
+ int sizeX = maxCx - minCx + 1;
+ int sizeY = maxCy - minCy + 1;
+ int sizeZ = maxCz - minCz + 1;
+ int gridSize = sizeX * sizeY * sizeZ;
+
+ if (m_bfsGrid.size() < gridSize) {
+ m_bfsGrid.resize(gridSize);
+ }
+
+ memset(m_bfsGrid.data(), 0, gridSize * sizeof(ClipChunk*));
+ for (unsigned int i = 0; i < chunks[playerIndex].length; i++) {
+ ClipChunk* cc = &chunks[playerIndex][i];
+ if (cc->globalIdx < 0) continue;
+ int lx = intFloorDiv(cc->chunk->x, CHUNK_XZSIZE) - minCx;
+ int ly = intFloorDiv(cc->chunk->y, CHUNK_SIZE) - minCy;
+ int lz = intFloorDiv(cc->chunk->z, CHUNK_XZSIZE) - minCz;
+ m_bfsGrid[(lx * sizeY + ly) * sizeZ + lz] = cc;
+ }
+
+ auto getChunkAt = [&](int cx, int cy, int cz) -> ClipChunk* {
+ int lx = cx - minCx;
+ int ly = cy - minCy;
+ int lz = cz - minCz;
+ if (lx >= 0 && lx < sizeX && ly >= 0 && ly < sizeY && lz >= 0 &&
+ lz < sizeZ) {
+ return m_bfsGrid[(lx * sizeY + ly) * sizeZ + lz];
+ }
+ return nullptr;
+ };
+
+ int startCx = floatFloorDiv(camX, CHUNK_XZSIZE);
+ int startCy = floatFloorDiv(camY, CHUNK_SIZE);
+ int startCz = floatFloorDiv(camZ, CHUNK_XZSIZE);
+
+ if (startCx < minCx)
+ startCx = minCx;
+ else if (startCx > maxCx)
+ startCx = maxCx;
+ if (startCy < minCy)
+ startCy = minCy;
+ else if (startCy > maxCy)
+ startCy = maxCy;
+ if (startCz < minCz)
+ startCz = minCz;
+ else if (startCz > maxCz)
+ startCz = maxCz;
+
+ ClipChunk* startChunk = getChunkAt(startCx, startCy, startCz);
+
+ if (!startChunk) {
+ float minDist = 1e30f;
+ for (unsigned int i = 0; i < chunks[playerIndex].length; i++) {
+ ClipChunk* cc = &chunks[playerIndex][i];
+ if (cc->globalIdx < 0) continue;
+ float midX = cc->chunk->x + CHUNK_XZSIZE * 0.5f;
+ float midY = cc->chunk->y + CHUNK_SIZE * 0.5f;
+ float midZ = cc->chunk->z + CHUNK_XZSIZE * 0.5f;
+ float dist = (camX - midX) * (camX - midX) +
+ (camY - midY) * (camY - midY) +
+ (camZ - midZ) * (camZ - midZ);
+ if (dist < minDist) {
+ minDist = dist;
+ startChunk = cc;
+ }
+ }
+ }
+
+ if (!startChunk) return;
+
+ struct BFSNode {
+ ClipChunk* cc;
+ int incomingFace;
+ };
+
+ static thread_local std::vector q;
+ q.clear();
+ q.reserve(chunks[playerIndex].length);
+ int qHead = 0;
+
+ int visitedSize = chunks[playerIndex].length;
+ if (m_bfsVisitedFaces[playerIndex].size() < visitedSize) {
+ m_bfsVisitedFaces[playerIndex].resize(visitedSize, 0);
+ }
+ memset(m_bfsVisitedFaces[playerIndex].data(), 0, visitedSize);
+
+ q.push_back({startChunk, -1});
+ m_bfsVisitedFaces[playerIndex][startChunk - chunks[playerIndex].data] =
+ 0x3F;
+
+ static const int OFFSETS[6][3] = {
+ {0, -1, 0}, // 0: -Y
+ {0, 1, 0}, // 1: +Y
+ {0, 0, -1}, // 2: -Z
+ {0, 0, 1}, // 3: +Z
+ {-1, 0, 0}, // 4: -X
+ {1, 0, 0} // 5: +X
+ };
+
+ while (qHead < (int)q.size()) {
+ BFSNode node = q[qHead++];
+ ClipChunk* curr = node.cc;
+ int incFace = node.incomingFace;
+
+ unsigned char flags = globalChunkFlags[curr->globalIdx];
+ bool isCompiled = (flags & CHUNK_FLAG_COMPILED) != 0;
+ bool isEmptyBoth =
+ (flags & CHUNK_FLAG_EMPTYBOTH) == CHUNK_FLAG_EMPTYBOTH;
+
+ if (isCompiled && !isEmptyBoth) {
+ curr->visible = true;
+ }
+
+ int cx = intFloorDiv(curr->chunk->x, CHUNK_XZSIZE);
+ int cy = intFloorDiv(curr->chunk->y, CHUNK_SIZE);
+ int cz = intFloorDiv(curr->chunk->z, CHUNK_XZSIZE);
+
+ uint64_t conn = getGlobalChunkConnectivity(curr->globalIdx);
+
+ for (int i = 0; i < 6; i++) {
+ int outFace = i;
+
+ bool canGo = false;
+ float chkX = curr->chunk->x;
+ float chkY = curr->chunk->y;
+ float chkZ = curr->chunk->z;
+ switch (outFace) {
+ case 0:
+ canGo = camY >= chkY;
+ break;
+ case 1:
+ canGo = camY <= chkY + CHUNK_SIZE;
+ break;
+ case 2:
+ canGo = camZ >= chkZ;
+ break;
+ case 3:
+ canGo = camZ <= chkZ + CHUNK_XZSIZE;
+ break;
+ case 4:
+ canGo = camX >= chkX;
+ break;
+ case 5:
+ canGo = camX <= chkX + CHUNK_XZSIZE;
+ break;
+ }
+ if (!canGo) continue;
+
+ if (incFace != -1) {
+ int shift = (incFace * 6) + outFace;
+ if ((conn & (1ULL << shift)) == 0) continue;
+ }
+
+ int nx = cx + OFFSETS[i][0];
+ int ny = cy + OFFSETS[i][1];
+ int nz = cz + OFFSETS[i][2];
+
+ ClipChunk* neighbor = getChunkAt(nx, ny, nz);
+ if (!neighbor) continue;
+
+ int nIdx = neighbor - chunks[playerIndex].data;
+ int nextIncFace = outFace ^ 1;
+
+ if ((m_bfsVisitedFaces[playerIndex][nIdx] & (1 << nextIncFace)) !=
+ 0)
+ continue;
+
+ float cellBounds[6] = {
+ (float)neighbor->chunk->x - 0.1f,
+ (float)neighbor->chunk->y - 0.1f,
+ (float)neighbor->chunk->z - 0.1f,
+ (float)neighbor->chunk->x + CHUNK_XZSIZE + 0.1f,
+ (float)neighbor->chunk->y + CHUNK_SIZE + 0.1f,
+ (float)neighbor->chunk->z + CHUNK_XZSIZE + 0.1f};
+
+ if (!clip(cellBounds, fdraw)) continue;
+
+ m_bfsVisitedFaces[playerIndex][nIdx] |= (1 << nextIncFace);
+ q.push_back({neighbor, nextIncFace});
+ }
+ }
+
+#else
+#error \
+ "Unknown occlusion mode, this should NEVER happen, check meson.build for misconfiguration"
+#endif
+}
void LevelRenderer::playStreamingMusic(const std::wstring& name, int x, int y,
int z) {
if (name != L"") {
@@ -3336,6 +3727,19 @@ void LevelRenderer::setGlobalChunkFlag(int x, int y, int z, Level* level,
}
}
+void LevelRenderer::setGlobalChunkConnectivity(int index, uint64_t conn) {
+ if (index >= 0 && index < getGlobalChunkCount()) {
+ globalChunkConnectivity[index] = conn;
+ }
+}
+
+uint64_t LevelRenderer::getGlobalChunkConnectivity(int index) {
+ if (index >= 0 && index < getGlobalChunkCount()) {
+ return globalChunkConnectivity[index];
+ }
+ return ~(uint64_t)0; // out of bounds
+}
+
void LevelRenderer::clearGlobalChunkFlag(int x, int y, int z, Level* level,
unsigned char flag,
unsigned char shift) {
@@ -3400,16 +3804,88 @@ unsigned char LevelRenderer::decGlobalChunkRefCount(int x, int y, int z,
}
}
+void LevelRenderer::queueRenderableTileEntityForRemoval_Locked(
+ int key, TileEntity* tileEntity) {
+ m_renderableTileEntitiesPendingRemoval[key].insert(tileEntity);
+}
+
+void LevelRenderer::addRenderableTileEntity_Locked(
+ int key, const std::shared_ptr& tileEntity) {
+ RenderableTileEntityBucket& bucket = renderableTileEntities[key];
+ TileEntity* tileEntityPtr = tileEntity.get();
+ if (bucket.indexByTile.find(tileEntityPtr) != bucket.indexByTile.end()) {
+ return;
+ }
+
+ size_t index = bucket.tiles.size();
+ bucket.tiles.push_back(tileEntity);
+ bucket.indexByTile.insert(std::make_pair(tileEntityPtr, index));
+}
+
+void LevelRenderer::eraseRenderableTileEntity_Locked(
+ RenderableTileEntityBucket& bucket, TileEntity* tileEntity) {
+ auto it = bucket.indexByTile.find(tileEntity);
+ if (it == bucket.indexByTile.end()) {
+ return;
+ }
+
+ size_t index = it->second;
+ size_t lastIndex = bucket.tiles.size() - 1;
+ if (index != lastIndex) {
+ std::shared_ptr moved = bucket.tiles[lastIndex];
+ bucket.tiles[index] = moved;
+ bucket.indexByTile[moved.get()] = index;
+ }
+
+ bucket.tiles.pop_back();
+ bucket.indexByTile.erase(it);
+}
+
+void LevelRenderer::retireRenderableTileEntitiesForChunkKey(int key) {
+ if (key == -1) return;
+
+ EnterCriticalSection(&m_csRenderableTileEntities);
+ renderableTileEntities.erase(key);
+ m_renderableTileEntitiesPendingRemoval.erase(key);
+ LeaveCriticalSection(&m_csRenderableTileEntities);
+}
+
// 4J added
void LevelRenderer::fullyFlagRenderableTileEntitiesToBeRemoved() {
+ FRAME_PROFILE_SCOPE(RenderableTileEntityCleanup);
+
EnterCriticalSection(&m_csRenderableTileEntities);
- AUTO_VAR(itChunkEnd, renderableTileEntities.end());
- for (AUTO_VAR(it, renderableTileEntities.begin()); it != itChunkEnd; it++) {
- AUTO_VAR(itTEEnd, it->second.end());
- for (AUTO_VAR(it2, it->second.begin()); it2 != itTEEnd; it2++) {
- (*it2)->upgradeRenderRemoveStage();
+ if (m_renderableTileEntitiesPendingRemoval.empty()) {
+ LeaveCriticalSection(&m_csRenderableTileEntities);
+ return;
+ }
+
+ auto itKeyEnd = m_renderableTileEntitiesPendingRemoval.end();
+ for (auto itKey = m_renderableTileEntitiesPendingRemoval.begin();
+ itKey != itKeyEnd; itKey++) {
+ auto itChunk = renderableTileEntities.find(itKey->first);
+ if (itChunk == renderableTileEntities.end()) continue;
+
+ RenderableTileEntityBucket& bucket = itChunk->second;
+ for (AUTO_VAR(itPending, itKey->second.begin());
+ itPending != itKey->second.end(); itPending++) {
+ if (bucket.indexByTile.find(*itPending) ==
+ bucket.indexByTile.end()) {
+ continue;
+ }
+
+ if (!(*itPending)->finalizeRenderRemoveStage()) {
+ continue;
+ }
+
+ eraseRenderableTileEntity_Locked(bucket, *itPending);
+ }
+
+ if (bucket.tiles.empty()) {
+ renderableTileEntities.erase(itChunk);
}
}
+ m_renderableTileEntitiesPendingRemoval.clear();
LeaveCriticalSection(&m_csRenderableTileEntities);
}
@@ -3420,12 +3896,6 @@ LevelRenderer::DestroyedTileManager::RecentTile::RecentTile(int x, int y, int z,
rebuilt = false;
}
-LevelRenderer::DestroyedTileManager::RecentTile::~RecentTile() {
- for (AUTO_VAR(it, boxes.begin()); it != boxes.end(); it++) {
- delete *it;
- }
-}
-
LevelRenderer::DestroyedTileManager::DestroyedTileManager() {
InitializeCriticalSection(&m_csDestroyedTiles);
}
@@ -3449,20 +3919,12 @@ void LevelRenderer::DestroyedTileManager::destroyingTileAt(Level* level, int x,
// ones, so make a temporary list and then copy over
RecentTile* recentTile = new RecentTile(x, y, z, level);
- AABB* box = AABB::newTemp((float)x, (float)y, (float)z, (float)(x + 1),
- (float)(y + 1), (float)(z + 1));
+ AABB box((float)x, (float)y, (float)z, (float)(x + 1), (float)(y + 1),
+ (float)(z + 1));
Tile* tile = Tile::tiles[level->getTile(x, y, z)];
if (tile != NULL) {
- tile->addAABBs(level, x, y, z, box, &recentTile->boxes, nullptr);
- }
-
- // Make these temporary AABBs into permanently allocated AABBs
- for (unsigned int i = 0; i < recentTile->boxes.size(); i++) {
- recentTile->boxes[i] = AABB::newPermanent(
- recentTile->boxes[i]->x0, recentTile->boxes[i]->y0,
- recentTile->boxes[i]->z0, recentTile->boxes[i]->x1,
- recentTile->boxes[i]->y1, recentTile->boxes[i]->z1);
+ tile->addAABBs(level, x, y, z, &box, &recentTile->boxes, nullptr);
}
m_destroyedTiles.push_back(recentTile);
@@ -3535,14 +3997,13 @@ void LevelRenderer::DestroyedTileManager::addAABBs(Level* level, AABB* box,
// interested in, add them to the output list, making a temp
// AABB copy so that we can destroy our own copy without
// worrying about the lifespan of the copy we've passed out
- if (m_destroyedTiles[i]->boxes[j]->intersects(box)) {
- boxes->push_back(
- AABB::newTemp(m_destroyedTiles[i]->boxes[j]->x0,
- m_destroyedTiles[i]->boxes[j]->y0,
- m_destroyedTiles[i]->boxes[j]->z0,
- m_destroyedTiles[i]->boxes[j]->x1,
- m_destroyedTiles[i]->boxes[j]->y1,
- m_destroyedTiles[i]->boxes[j]->z1));
+ if (m_destroyedTiles[i]->boxes[j].intersects(*box)) {
+ boxes->push_back({m_destroyedTiles[i]->boxes[j].x0,
+ m_destroyedTiles[i]->boxes[j].y0,
+ m_destroyedTiles[i]->boxes[j].z0,
+ m_destroyedTiles[i]->boxes[j].x1,
+ m_destroyedTiles[i]->boxes[j].y1,
+ m_destroyedTiles[i]->boxes[j].z1});
}
}
}
@@ -3594,8 +4055,6 @@ void LevelRenderer::staticCtor() {
}
int LevelRenderer::rebuildChunkThreadProc(void* lpParam) {
- Vec3::CreateNewThreadStorage();
- AABB::CreateNewThreadStorage();
Tesselator::CreateNewThreadStorage(1024 * 1024);
RenderManager.InitialiseContext();
Chunk::CreateNewThreadStorage();
@@ -3607,7 +4066,10 @@ int LevelRenderer::rebuildChunkThreadProc(void* lpParam) {
s_activationEventA[index]->WaitForSignal(INFINITE);
// app.DebugPrintf("Rebuilding permaChunk %d\n", index + 1);
- permaChunk[index + 1].rebuild();
+ {
+ FRAME_PROFILE_SCOPE(ChunkRebuildBody);
+ permaChunk[index + 1].rebuild();
+ }
// Inform the producer thread that we are done with this chunk
s_rebuildCompleteEvents->Set(index);
diff --git a/Minecraft.Client/Rendering/LevelRenderer.h b/Minecraft.Client/Rendering/LevelRenderer.h
index fbd13451d..006d357f4 100644
--- a/Minecraft.Client/Rendering/LevelRenderer.h
+++ b/Minecraft.Client/Rendering/LevelRenderer.h
@@ -7,6 +7,7 @@
#if !defined(__linux__)
#include
#endif
+#include
class MultiPlayerLevel;
class Textures;
class Chunk;
@@ -141,8 +142,13 @@ public:
void destroyTileProgress(int id, int x, int y, int z, int progress);
void registerTextures(IconRegister* iconRegister);
- typedef std::unordered_map >,
- IntKeyHash, IntKeyEq>
+ struct RenderableTileEntityBucket {
+ std::vector > tiles;
+ std::unordered_map indexByTile;
+ };
+
+ typedef std::unordered_map
rteMap;
private:
@@ -154,6 +160,10 @@ private:
rteMap renderableTileEntities; // 4J - changed - was
// std::vector,
// now hashed by chunk so we can find them
+ typedef std::unordered_set rtePendingRemovalSet;
+ typedef std::unordered_map
+ rtePendingRemovalMap;
+ rtePendingRemovalMap m_renderableTileEntitiesPendingRemoval;
CRITICAL_SECTION m_csRenderableTileEntities;
MultiPlayerLevel* level[4]; // 4J - now one per player
Textures* textures;
@@ -187,10 +197,21 @@ private:
emptyChunks;
static const int RENDERLISTS_LENGTH = 4; // 4J - added
OffsettedRenderList renderLists[RENDERLISTS_LENGTH];
-
+ void setGlobalChunkConnectivity(int index, uint64_t conn);
+ uint64_t getGlobalChunkConnectivity(int index);
+ std::vector m_bfsGrid;
+ std::vector m_bfsVisitedFaces[4];
std::unordered_map destroyingBlocks;
Icon** breakingTextures;
+ void addRenderableTileEntity_Locked(
+ int key, const std::shared_ptr& tileEntity);
+ void eraseRenderableTileEntity_Locked(RenderableTileEntityBucket& bucket,
+ TileEntity* tileEntity);
+ void queueRenderableTileEntityForRemoval_Locked(int key,
+ TileEntity* tileEntity);
+ void retireRenderableTileEntitiesForChunkKey(int key);
+
public:
void fullyFlagRenderableTileEntitiesToBeRemoved(); // 4J added
@@ -212,7 +233,7 @@ public:
int timeout_ticks;
bool rebuilt;
RecentTile(int x, int y, int z, Level* level);
- ~RecentTile();
+ ~RecentTile() = default;
};
CRITICAL_SECTION m_csDestroyedTiles;
std::vector m_destroyedTiles;
@@ -274,6 +295,8 @@ public:
void clearGlobalChunkFlag(int x, int y, int z, Level* level,
unsigned char flag, unsigned char shift = 0);
+ static uint64_t* globalChunkConnectivity;
+
// Get/set whole byte of flags
unsigned char getGlobalChunkFlags(int x, int y, int z, Level* level);
void setGlobalChunkFlags(int x, int y, int z, Level* level,
diff --git a/Minecraft.Client/Rendering/Lighting.cpp b/Minecraft.Client/Rendering/Lighting.cpp
index c0eb8e562..4182a9fe3 100644
--- a/Minecraft.Client/Rendering/Lighting.cpp
+++ b/Minecraft.Client/Rendering/Lighting.cpp
@@ -22,14 +22,16 @@ void Lighting::turnOn() {
float d = 0.6f;
float s = 0.0f;
- Vec3* l = Vec3::newTemp(0.2f, 1.0f, -0.7f)->normalize();
- glLight(GL_LIGHT0, GL_POSITION, getBuffer(l->x, l->y, l->z, 0));
+ Vec3 l(0.2f, 1.0f, -0.7f);
+ l = l.normalize();
+ glLight(GL_LIGHT0, GL_POSITION, getBuffer(l.x, l.y, l.z, 0));
glLight(GL_LIGHT0, GL_DIFFUSE, getBuffer(d, d, d, 1));
glLight(GL_LIGHT0, GL_AMBIENT, getBuffer(0.0f, 0.0f, 0.0f, 1.0f));
glLight(GL_LIGHT0, GL_SPECULAR, getBuffer(s, s, s, 1.0f));
- l = Vec3::newTemp(-0.2f, 1.0f, 0.7f)->normalize();
- glLight(GL_LIGHT1, GL_POSITION, getBuffer(l->x, l->y, l->z, 0));
+ l = Vec3(-0.2f, 1.0f, 0.7f);
+ l = l.normalize();
+ glLight(GL_LIGHT1, GL_POSITION, getBuffer(l.x, l.y, l.z, 0));
glLight(GL_LIGHT1, GL_DIFFUSE, getBuffer(d, d, d, 1));
glLight(GL_LIGHT1, GL_AMBIENT, getBuffer(0.0f, 0.0f, 0.0f, 1.0f));
glLight(GL_LIGHT1, GL_SPECULAR, getBuffer(s, s, s, 1.0f));
@@ -55,4 +57,4 @@ void Lighting::turnOnGui() {
glRotatef(165, 1, 0, 0);
turnOn();
glPopMatrix();
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/Particles/CritParticle.cpp b/Minecraft.Client/Rendering/Particles/CritParticle.cpp
index 11457da37..fba87aca0 100644
--- a/Minecraft.Client/Rendering/Particles/CritParticle.cpp
+++ b/Minecraft.Client/Rendering/Particles/CritParticle.cpp
@@ -16,14 +16,14 @@ void CritParticle::_init(Level* level, std::shared_ptr entity,
}
CritParticle::CritParticle(Level* level, std::shared_ptr entity)
- : Particle(level, entity->x, entity->bb->y0 + entity->bbHeight / 2,
+ : Particle(level, entity->x, entity->bb.y0 + entity->bbHeight / 2,
entity->z, entity->xd, entity->yd, entity->zd) {
_init(level, entity, eParticleType_crit);
}
CritParticle::CritParticle(Level* level, std::shared_ptr entity,
ePARTICLE_TYPE type)
- : Particle(level, entity->x, entity->bb->y0 + entity->bbHeight / 2,
+ : Particle(level, entity->x, entity->bb.y0 + entity->bbHeight / 2,
entity->z, entity->xd, entity->yd, entity->zd) {
_init(level, entity, type);
}
@@ -43,7 +43,7 @@ void CritParticle::tick() {
if (xa * xa + ya * ya + za * za > 1) continue;
double x = entity->x + xa * entity->bbWidth / 4;
double y =
- entity->bb->y0 + entity->bbHeight / 2 + ya * entity->bbHeight / 4;
+ entity->bb.y0 + entity->bbHeight / 2 + ya * entity->bbHeight / 4;
double z = entity->z + za * entity->bbWidth / 4;
level->addParticle(particleName, x, y, z, xa, ya + 0.2, za);
}
@@ -55,4 +55,4 @@ void CritParticle::tick() {
int CritParticle::getParticleTexture() {
return ParticleEngine::ENTITY_PARTICLE_TEXTURE;
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/Particles/PlayerCloudParticle.cpp b/Minecraft.Client/Rendering/Particles/PlayerCloudParticle.cpp
index 145630db1..a38775947 100644
--- a/Minecraft.Client/Rendering/Particles/PlayerCloudParticle.cpp
+++ b/Minecraft.Client/Rendering/Particles/PlayerCloudParticle.cpp
@@ -52,8 +52,8 @@ void PlayerCloudParticle::tick() {
zd *= 0.96f;
std::shared_ptr p = level->getNearestPlayer(shared_from_this(), 2);
if (p != NULL) {
- if (y > p->bb->y0) {
- y += (p->bb->y0 - y) * 0.2;
+ if (y > p->bb.y0) {
+ y += (p->bb.y0 - y) * 0.2;
yd += (p->yd - yd) * 0.2;
setPos(x, y, z);
}
@@ -63,4 +63,4 @@ void PlayerCloudParticle::tick() {
xd *= 0.7f;
zd *= 0.7f;
}
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/Polygon.cpp b/Minecraft.Client/Rendering/Polygon.cpp
index 28c37260e..d0de18504 100644
--- a/Minecraft.Client/Rendering/Polygon.cpp
+++ b/Minecraft.Client/Rendering/Polygon.cpp
@@ -1,70 +1,62 @@
-#include "../Platform/stdafx.h"
+#include "Rendering/Vertex.h"
#include "Polygon.h"
+#include
+#include
+#include
-// 4J added for common init code
-void _Polygon::_init(VertexArray vertices) {
- vertexCount = 0;
- _flipNormal = false;
-
- this->vertices = vertices;
- vertexCount = vertices.length;
-}
-
-_Polygon::_Polygon(VertexArray vertices) { _init(vertices); }
-
-_Polygon::_Polygon(VertexArray vertices, int u0, int v0, int u1, int v1,
- float xTexSize, float yTexSize) {
- _init(vertices);
+_Polygon::_Polygon(const std::span vertices)
+ : vertexCount(vertices.size()),
+ vertices(vertices.begin(), vertices.end()) {}
+_Polygon::_Polygon(const std::span vertices, int u0, int v0,
+ int u1, int v1, float xTexSize, float yTexSize)
+ : vertexCount(vertices.size()) {
// 4J - added - don't assume that u1 > u0, v1 > v0
float us = (u1 > u0) ? (0.1f / xTexSize) : (-0.1f / xTexSize);
float vs = (v1 > v0) ? (0.1f / yTexSize) : (-0.1f / yTexSize);
- vertices[0] = vertices[0]->remap(u1 / xTexSize - us, v0 / yTexSize + vs);
- vertices[1] = vertices[1]->remap(u0 / xTexSize + us, v0 / yTexSize + vs);
- vertices[2] = vertices[2]->remap(u0 / xTexSize + us, v1 / yTexSize - vs);
- vertices[3] = vertices[3]->remap(u1 / xTexSize - us, v1 / yTexSize - vs);
+ this->vertices = {
+ vertices[0].remap(u1 / xTexSize - us, v0 / yTexSize + vs),
+ vertices[1].remap(u0 / xTexSize + us, v0 / yTexSize + vs),
+ vertices[2].remap(u0 / xTexSize + us, v1 / yTexSize - vs),
+ vertices[3].remap(u1 / xTexSize - us, v1 / yTexSize - vs),
+ };
}
-_Polygon::_Polygon(VertexArray vertices, float u0, float v0, float u1,
- float v1) {
- _init(vertices);
+_Polygon::_Polygon(const std::span vertices, float u0,
+ float v0, float u1, float v1)
+ : vertexCount(vertices.size()),
+ vertices({
+ vertices[0].remap(u1, v0),
+ vertices[1].remap(u0, v0),
+ vertices[2].remap(u0, v1),
+ vertices[3].remap(u1, v1),
+ }) {}
- vertices[0] = vertices[0]->remap(u1, v0);
- vertices[1] = vertices[1]->remap(u0, v0);
- vertices[2] = vertices[2]->remap(u0, v1);
- vertices[3] = vertices[3]->remap(u1, v1);
-}
-
-void _Polygon::mirror() {
- VertexArray newVertices = VertexArray(vertices.length);
- for (unsigned int i = 0; i < vertices.length; i++)
- newVertices[i] = vertices[vertices.length - i - 1];
- delete[] vertices.data;
- vertices = newVertices;
-}
+void _Polygon::mirror() { std::reverse(vertices.begin(), vertices.end()); }
void _Polygon::render(Tesselator* t, float scale) {
- Vec3* v0 = vertices[1]->pos->vectorTo(vertices[0]->pos);
- Vec3* v1 = vertices[1]->pos->vectorTo(vertices[2]->pos);
- Vec3* n = v1->cross(v0)->normalize();
+ Vec3 v0 = vertices[1].pos.vectorTo(vertices[0].pos);
+ Vec3 v1 = vertices[1].pos.vectorTo(vertices[2].pos);
+ Vec3 n = v1.cross(v0).normalize();
t->begin();
if (_flipNormal) {
- t->normal(-(float)n->x, -(float)n->y, -(float)n->z);
+ t->normal(-(float)n.x, -(float)n.y, -(float)n.z);
} else {
- t->normal((float)n->x, (float)n->y, (float)n->z);
+ t->normal((float)n.x, (float)n.y, (float)n.z);
}
for (int i = 0; i < 4; i++) {
- Vertex* v = vertices[i];
- t->vertexUV((float)(v->pos->x * scale), (float)(v->pos->y * scale),
- (float)(v->pos->z * scale), (float)(v->u), (float)(v->v));
+ Vertex v = vertices[i];
+ t->vertexUV((float)(v.pos.x * scale), (float)(v.pos.y * scale),
+ (float)(v.pos.z * scale), (float)(v.u), (float)(v.v));
}
+
t->end();
}
_Polygon* _Polygon::flipNormal() {
_flipNormal = true;
return this;
-}
\ No newline at end of file
+}
diff --git a/Minecraft.Client/Rendering/Polygon.h b/Minecraft.Client/Rendering/Polygon.h
index 38c6e9094..c56306533 100644
--- a/Minecraft.Client/Rendering/Polygon.h
+++ b/Minecraft.Client/Rendering/Polygon.h
@@ -1,22 +1,26 @@
#pragma once
+
+#include
+#include
#include "Vertex.h"
#include "Tesselator.h"
#include "../../Minecraft.World/Util/ArrayWithLength.h"
class _Polygon {
public:
- VertexArray vertices;
+ std::vector vertices;
int vertexCount;
private:
bool _flipNormal;
public:
- void _init(VertexArray vertices); // 4J added for common init code
- _Polygon(VertexArray vertices);
- _Polygon(VertexArray vertices, int u0, int v0, int u1, int v1,
- float xTexSize, float yTexSize);
- _Polygon(VertexArray vertices, float u0, float v0, float u1, float v1);
+ _Polygon() = default;
+ _Polygon(std::span vertices);
+ _Polygon(std::span vertices, int u0, int v0, int u1,
+ int v1, float xTexSize, float yTexSize);
+ _Polygon(std::span vertices, float u0, float v0, float u1,
+ float v1);
void mirror();
void render(Tesselator* t, float scale);
_Polygon* flipNormal();
diff --git a/Minecraft.Client/Rendering/Tesselator.cpp b/Minecraft.Client/Rendering/Tesselator.cpp
index 05a6fa05d..e896334d4 100644
--- a/Minecraft.Client/Rendering/Tesselator.cpp
+++ b/Minecraft.Client/Rendering/Tesselator.cpp
@@ -138,10 +138,15 @@ void Tesselator::end() {
}
}
}
- glDisableClientState(GL_VERTEX_ARRAY);
- if (hasTexture) glDisableClientState(GL_TEXTURE_COORD_ARRAY);
- if (hasColor) glDisableClientState(GL_COLOR_ARRAY);
- if (hasNormal) glDisableClientState(GL_NORMAL_ARRAY);
+ // 4jcraft: gldisableclientstate breaks gl compat, commenting those lead
+ // to some weird glitches with input but.. somehow stopped one day so..
+ // just keep an eye on these incase mouse locking stops working outta
+ // nowhere (i blame opengl not me)
+ //
+ // glDisableClientState(GL_VERTEX_ARRAY); if (hasTexture)
+ // glDisableClientState(GL_TEXTURE_COORD_ARRAY); if (hasColor)
+ // glDisableClientState(GL_COLOR_ARRAY); if (hasNormal)
+ // glDisableClientState(GL_NORMAL_ARRAY);
}
clear();
diff --git a/Minecraft.Client/Rendering/Vertex.cpp b/Minecraft.Client/Rendering/Vertex.cpp
index b4c70ae19..b323c0f79 100644
--- a/Minecraft.Client/Rendering/Vertex.cpp
+++ b/Minecraft.Client/Rendering/Vertex.cpp
@@ -1,22 +1,5 @@
-#include "../Platform/stdafx.h"
#include "Vertex.h"
-Vertex::Vertex(float x, float y, float z, float u, float v) {
- this->pos = Vec3::newPermanent(x, y, z);
- this->u = u;
- this->v = v;
+Vertex Vertex::remap(const float u, const float v) const {
+ return Vertex(pos.x, pos.y, pos.z, u, v);
}
-
-Vertex* Vertex::remap(float u, float v) { return new Vertex(this, u, v); }
-
-Vertex::Vertex(Vertex* vertex, float u, float v) {
- this->pos = vertex->pos;
- this->u = u;
- this->v = v;
-}
-
-Vertex::Vertex(Vec3* pos, float u, float v) {
- this->pos = pos;
- this->u = u;
- this->v = v;
-}
\ No newline at end of file
diff --git a/Minecraft.Client/Rendering/Vertex.h b/Minecraft.Client/Rendering/Vertex.h
index 99166d1ee..b0437b9ba 100644
--- a/Minecraft.Client/Rendering/Vertex.h
+++ b/Minecraft.Client/Rendering/Vertex.h
@@ -3,12 +3,17 @@
class Vertex {
public:
- Vec3* pos;
+ Vec3 pos;
float u, v;
public:
- Vertex(float x, float y, float z, float u, float v);
- Vertex* remap(float u, float v);
- Vertex(Vertex* vertex, float u, float v);
- Vertex(Vec3* pos, float u, float v);
-};
\ No newline at end of file
+ constexpr Vertex(float x, float y, float z, float u, float v)
+ : pos({x, y, z}), u(u), v(v) {}
+
+ constexpr Vertex(Vertex* vertex, float u, float v)
+ : pos(vertex->pos), u(u), v(v) {}
+
+ constexpr Vertex(Vec3* pos, float u, float v) : pos(*pos), u(u), v(v) {}
+
+ Vertex remap(float u, float v) const;
+};
diff --git a/Minecraft.Client/Textures/BufferedImage.cpp b/Minecraft.Client/Textures/BufferedImage.cpp
index 37a77ba3f..b99759037 100644
--- a/Minecraft.Client/Textures/BufferedImage.cpp
+++ b/Minecraft.Client/Textures/BufferedImage.cpp
@@ -1,15 +1,21 @@
#include "../Platform/stdafx.h"
#include "../../Minecraft.World/Util/StringHelpers.h"
#include "Textures.h"
+#include "PathHelper.h"
#include "../../Minecraft.World/Util/ArrayWithLength.h"
#include "BufferedImage.h"
+#if defined(__linux__)
+#include
+#endif
+#include
+#include
BufferedImage::BufferedImage(int width, int height, int type) {
data[0] = new int[width * height];
for (int i = 1; i < 10; i++) {
- data[i] = NULL;
+ data[i] = nullptr;
}
this->width = width;
this->height = height;
@@ -24,130 +30,125 @@ void BufferedImage::ByteFlip4(unsigned int& data) {
// the compression method. Compression method 3 is a 32-bit image with only
// 24-bits used (ie no alpha channel) whereas method 0 is a full 32-bit image
// with a valid alpha channel.
+
+// 4jcraft: mostly rewrote this function
BufferedImage::BufferedImage(const std::wstring& File,
- bool filenameHasExtension /*=false*/,
- bool bTitleUpdateTexture /*=false*/,
- const std::wstring& drive /*=L""*/) {
- HRESULT hr;
- std::wstring wDrive;
- std::wstring filePath;
- filePath = File;
+ bool filenameHasExtension,
+ bool bTitleUpdateTexture,
+ const std::wstring& drive) {
+ HRESULT hr = -1;
+ std::wstring filePath = File;
- wDrive = drive;
- if (wDrive.empty()) {
+ for (size_t i = 0; i < filePath.length(); ++i) {
+ if (filePath[i] == L'\\') filePath[i] = L'/';
+ }
+ for (int l = 0; l < 10; l++) data[l] = nullptr;
- if (bTitleUpdateTexture) {
- // Make the content package point to to the UPDATE: drive is needed
- wDrive = L"Common\\res\\TitleUpdate\\";
- } else {
- wDrive = L"Common/";
+ std::wstring baseName = filePath;
+ if (!filenameHasExtension) {
+ if (baseName.size() > 4 &&
+ baseName.substr(baseName.size() - 4) == L".png") {
+ baseName = baseName.substr(0, baseName.size() - 4);
}
-
}
- for (int l = 0; l < 10; l++) {
- data[l] = NULL;
- }
+ while (!baseName.empty() && (baseName[0] == L'/' || baseName[0] == L'\\'))
+ baseName = baseName.substr(1);
+ if (baseName.find(L"res/") == 0) baseName = baseName.substr(4);
+
+ std::wstring exeDir = PathHelper::GetExecutableDirW();
for (int l = 0; l < 10; l++) {
- std::wstring name;
- std::wstring mipMapPath = L"";
- if (l != 0) {
- mipMapPath = L"MipMapLevel" + _toString(l + 1);
- }
- if (filenameHasExtension) {
- name = wDrive + L"res" + filePath.substr(0, filePath.length());
- } else {
- name = wDrive + L"res" + filePath.substr(0, filePath.length() - 4) +
- mipMapPath + L".png";
- }
+ std::wstring mipSuffix =
+ (l != 0) ? L"MipMapLevel" + _toString(l + 1) : L"";
+ std::wstring fileName = baseName + mipSuffix + L".png";
+ std::wstring finalPath;
+ bool foundOnDisk = false;
- const char* pchTextureName = wstringtofilename(name);
+ std::vector searchPaths = {
+ exeDir + L"/Common/res/TitleUpdate/res/" + fileName,
+ exeDir + L"/Common/res/" + fileName,
+ exeDir + L"/Common/Media/Graphics/" + fileName,
+ exeDir + L"/Common/Media/font/" + fileName,
+ exeDir + L"/Common/res/font/" + fileName,
+ exeDir + L"/Common/Media/" + fileName};
-#if !defined(_CONTENT_PACKAGE)
- app.DebugPrintf("\n--- Loading TEXTURE - %s\n\n", pchTextureName);
-#endif
+ for (auto& attempt : searchPaths) {
+ size_t p;
+ while ((p = attempt.find(L"//")) != std::wstring::npos)
+ attempt.replace(p, 2, L"/");
+ if (access(wstringtofilename(attempt), F_OK) != -1) {
+ finalPath = attempt;
+ foundOnDisk = true;
+ break;
+ }
+ }
D3DXIMAGE_INFO ImageInfo;
ZeroMemory(&ImageInfo, sizeof(D3DXIMAGE_INFO));
- hr =
- RenderManager.LoadTextureData(pchTextureName, &ImageInfo, &data[l]);
- if (hr != ERROR_SUCCESS) {
- // 4J - If we haven't loaded the non-mipmap version then exit the
- // game
- if (l == 0) {
- app.FatalLoadError();
+ if (foundOnDisk) {
+ hr = RenderManager.LoadTextureData(wstringtofilename(finalPath),
+ &ImageInfo, &data[l]);
+ } else {
+ std::wstring archiveKey = L"res/" + fileName;
+ if (app.hasArchiveFile(archiveKey)) {
+ byteArray ba = app.getArchiveFile(archiveKey);
+ hr = RenderManager.LoadTextureData(ba.data, ba.length,
+ &ImageInfo, &data[l]);
}
- return;
}
- if (l == 0) {
- width = ImageInfo.Width;
- height = ImageInfo.Height;
+ if (hr == ERROR_SUCCESS) {
+ if (l == 0) {
+ width = ImageInfo.Width;
+ height = ImageInfo.Height;
+ }
+ } else {
+ if (l == 0) {
+ // safety dummy to prevent crash
+ width = 1;
+ height = 1;
+ data[0] = new int[1];
+ data[0][0] = 0xFFFF00FF;
+ }
+ break;
}
}
}
-
BufferedImage::BufferedImage(DLCPack* dlcPack, const std::wstring& File,
- bool filenameHasExtension /*= false*/) {
+ bool filenameHasExtension) {
HRESULT hr;
std::wstring filePath = File;
- std::uint8_t* pbData = NULL;
+ std::uint8_t* pbData = nullptr;
std::uint32_t dataBytes = 0;
-
- for (int l = 0; l < 10; l++) {
- data[l] = NULL;
- }
+ for (int l = 0; l < 10; l++) data[l] = nullptr;
for (int l = 0; l < 10; l++) {
std::wstring name;
- std::wstring mipMapPath = L"";
- if (l != 0) {
- mipMapPath = L"MipMapLevel" + _toString(l + 1);
- }
- if (filenameHasExtension) {
- name = L"res" + filePath.substr(0, filePath.length());
- } else {
- name = L"res" + filePath.substr(0, filePath.length() - 4) +
- mipMapPath + L".png";
- }
+ std::wstring mipMapPath =
+ (l != 0) ? L"MipMapLevel" + _toString(l + 1) : L"";
+ name = L"res" + (filenameHasExtension
+ ? filePath
+ : filePath.substr(0, filePath.length() - 4) +
+ mipMapPath + L".png");
if (!dlcPack->doesPackContainFile(DLCManager::e_DLCType_All, name)) {
- // 4J - If we haven't loaded the non-mipmap version then exit the
- // game
- if (l == 0) {
- app.FatalLoadError();
- }
+ if (l == 0) app.FatalLoadError();
return;
}
DLCFile* dlcFile = dlcPack->getFile(DLCManager::e_DLCType_All, name);
pbData = dlcFile->getData(dataBytes);
- if (pbData == NULL || dataBytes == 0) {
- // 4J - If we haven't loaded the non-mipmap version then exit the
- // game
- if (l == 0) {
- app.FatalLoadError();
- }
+ if (pbData == nullptr || dataBytes == 0) {
+ if (l == 0) app.FatalLoadError();
return;
}
D3DXIMAGE_INFO ImageInfo;
- ZeroMemory(&ImageInfo, sizeof(D3DXIMAGE_INFO));
hr = RenderManager.LoadTextureData(pbData, dataBytes, &ImageInfo,
&data[l]);
-
- if (hr != ERROR_SUCCESS) {
- // 4J - If we haven't loaded the non-mipmap version then exit the
- // game
- if (l == 0) {
- app.FatalLoadError();
- }
- return;
- }
-
- if (l == 0) {
+ if (hr == ERROR_SUCCESS && l == 0) {
width = ImageInfo.Width;
height = ImageInfo.Height;
}
@@ -155,9 +156,8 @@ BufferedImage::BufferedImage(DLCPack* dlcPack, const std::wstring& File,
}
BufferedImage::BufferedImage(std::uint8_t* pbData, std::uint32_t dataBytes) {
- int iCurrentByte = 0;
for (int l = 0; l < 10; l++) {
- data[l] = NULL;
+ data[l] = nullptr;
}
D3DXIMAGE_INFO ImageInfo;
@@ -198,7 +198,7 @@ int* BufferedImage::getData() { return data[0]; }
int* BufferedImage::getData(int level) { return data[level]; }
-Graphics* BufferedImage::getGraphics() { return NULL; }
+Graphics* BufferedImage::getGraphics() { return nullptr; }
// Returns the transparency. Returns either OPAQUE, BITMASK, or TRANSLUCENT.
// Specified by:
@@ -224,14 +224,15 @@ BufferedImage* BufferedImage::getSubimage(int x, int y, int w, int h) {
this->getRGB(x, y, w, h, arrayWrapper, 0, w);
int level = 1;
- while (getData(level) != NULL) {
+ // prevent overflow
+ while (level < 10 && getData(level) != nullptr) {
int ww = w >> level;
int hh = h >> level;
int xx = x >> level;
int yy = y >> level;
img->data[level] = new int[ww * hh];
- intArray arrayWrapper(img->data[level], ww * hh);
- this->getRGB(xx, yy, ww, hh, arrayWrapper, 0, ww, level);
+ intArray levelWrapper(img->data[level], ww * hh);
+ this->getRGB(xx, yy, ww, hh, levelWrapper, 0, ww, level);
++level;
}
@@ -249,7 +250,8 @@ void BufferedImage::preMultiplyAlpha() {
int b = 0;
int total = width * height;
- for (unsigned int i = 0; i < total; ++i) {
+ // why was it unsigned??
+ for (int i = 0; i < total; ++i) {
cur = curData[i];
alpha = (cur >> 24) & 0xff;
r = ((cur >> 16) & 0xff) * (float)alpha / 255;
diff --git a/Minecraft.Client/Textures/Texture.cpp b/Minecraft.Client/Textures/Texture.cpp
index 165990201..9cf70cb5a 100644
--- a/Minecraft.Client/Textures/Texture.cpp
+++ b/Minecraft.Client/Textures/Texture.cpp
@@ -269,10 +269,10 @@ void Texture::blit(int x, int y, Texture* source, bool rotated) {
}
void Texture::transferFromBuffer(intArray buffer) {
- //if (depth == 1) {
- // return;
- //}
- // 4jcraft - move pos out of loops
+ // if (depth == 1) {
+ // return;
+ // }
+ // 4jcraft - move pos out of loops
data[0]->clear();
// #if 0
// int byteRemapRGBA[] = { 3, 0, 1, 2 };
@@ -285,7 +285,7 @@ void Texture::transferFromBuffer(intArray buffer) {
int totalPixels = width * height * depth;
- for (int i = 0; i < totalPixels; i++){
+ for (int i = 0; i < totalPixels; i++) {
int pixel = buffer[i];
int offset = i * 4;
@@ -299,7 +299,7 @@ void Texture::transferFromBuffer(intArray buffer) {
updateOnGPU();
}
-
+
/* for (int z = 0; z < depth; z++) {
int plane = z * height * width * 4;
for (int y = 0; y < height; y++) {
diff --git a/Minecraft.Client/Textures/Textures.cpp b/Minecraft.Client/Textures/Textures.cpp
index 8f2e0c117..ed06047ba 100644
--- a/Minecraft.Client/Textures/Textures.cpp
+++ b/Minecraft.Client/Textures/Textures.cpp
@@ -33,24 +33,12 @@ C4JRender::eTextureFormat Textures::TEXTURE_FORMAT =
int Textures::preLoadedIdx[TN_COUNT];
const wchar_t* Textures::preLoaded[TN_COUNT] = {
L"%blur%misc/pumpkinblur",
- L"%blur%/misc/vignette", // Not currently used
L"%clamp%misc/shadow",
- L"/achievement/bg", // Not currently used
L"art/kz",
L"environment/clouds",
L"environment/rain",
L"environment/snow",
L"gui/gui",
- L"gui/background",
- L"gui/inventory",
- L"gui/container",
- L"gui/crafting",
- L"gui/furnace",
- L"gui/creative_inventory/tabs",
- L"gui/creative_inventory/tab_items",
- L"gui/creative_inventory/tab_inventory",
- L"gui/creative_inventory/tab_item_search",
- L"title/mclogo",
L"gui/icons",
L"item/arrows",
L"item/boat",
@@ -174,6 +162,37 @@ const wchar_t* Textures::preLoaded[TN_COUNT] = {
L"item/trapped",
L"item/trapped_double",
+
+// 4jcraft: java UI specific
+#ifdef ENABLE_JAVA_GUIS
+ L"%blur%/misc/vignette",
+ L"/achievement/bg",
+ L"gui/background",
+ L"gui/inventory",
+ L"gui/container",
+ L"gui/crafting",
+ L"gui/furnace",
+ L"gui/creative_inventory/tabs",
+ L"gui/creative_inventory/tab_items",
+ L"gui/creative_inventory/tab_inventory",
+ L"gui/creative_inventory/tab_item_search",
+ L"title/mclogo",
+ L"gui/horse",
+ L"gui/anvil",
+ L"gui/trap",
+ L"gui/beacon",
+ L"gui/hopper",
+ L"gui/enchant",
+ L"gui/villager",
+ L"gui/brewing_stand",
+ L"title/bg/panorama",
+ L"title/bg/panorama0",
+ L"title/bg/panorama1",
+ L"title/bg/panorama2",
+ L"title/bg/panorama3",
+ L"title/bg/panorama4",
+ L"title/bg/panorama5",
+#endif
// L"item/christmas",
// L"item/christmas_double",
@@ -509,11 +528,16 @@ void Textures::bindTextureLayers(ResourceLocation* resource) {
}
void Textures::bind(int id) {
+ // 4jcraft: Classic GUI code still performs some raw glBindTexture calls, so
+ // this path must always rebind rather than trusting lastBoundId to be in sync.
+ // TODO(4jcraft): Long term, route all texture binds through one synchronized
+ // path or invalidate lastBoundId at every raw glBindTexture call so this can
+ // safely use cached binds again without breaking font/UI rendering.
// if (id != lastBoundId)
{
if (id < 0) return;
glBindTexture(GL_TEXTURE_2D, id);
- // lastBoundId = id;
+ // lastBoundId = id;
}
}
@@ -664,8 +688,8 @@ void Textures::loadTexture(BufferedImage* img, int id, bool blur, bool clamp) {
}
if (clamp) {
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
} else {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
@@ -1341,4 +1365,4 @@ bool Textures::IsOriginalImage(TEXTURE_NAME texId, const std::wstring& name) {
i++;
}
return false;
-}
+}
\ No newline at end of file
diff --git a/Minecraft.Client/Textures/Textures.h b/Minecraft.Client/Textures/Textures.h
index 46a86b603..fd59fc66b 100644
--- a/Minecraft.Client/Textures/Textures.h
+++ b/Minecraft.Client/Textures/Textures.h
@@ -16,24 +16,12 @@ class ResourceLocation;
typedef enum _TEXTURE_NAME {
TN__BLUR__MISC_PUMPKINBLUR,
- TN__BLUR__MISC_VIGNETTE, // Not currently used
TN__CLAMP__MISC_SHADOW,
- TN_ACHIEVEMENT_BG, // Not currently used
TN_ART_KZ,
TN_ENVIRONMENT_CLOUDS,
TN_ENVIRONMENT_RAIN,
TN_ENVIRONMENT_SNOW,
TN_GUI_GUI,
- TN_GUI_BACKGROUND,
- TN_GUI_INVENTORY,
- TN_GUI_CONTAINER,
- TN_GUI_CRAFTING,
- TN_GUI_FURNACE,
- TN_GUI_CREATIVE_TABS,
- TN_GUI_CREATIVE_TAB_ITEMS,
- TN_GUI_CREATIVE_TAB_INVENTORY,
- TN_GUI_CREATIVE_TAB_ITEM_SEARCH,
- TN_TITLE_MCLOGO,
TN_GUI_ICONS,
TN_ITEM_ARROWS,
TN_ITEM_BOAT,
@@ -156,6 +144,37 @@ typedef enum _TEXTURE_NAME {
TN_TILE_TRAP_CHEST,
TN_TILE_LARGE_TRAP_CHEST,
+
+// 4jcraft: java UI specific
+#ifdef ENABLE_JAVA_GUIS
+ TN__BLUR__MISC_VIGNETTE,
+ TN_ACHIEVEMENT_BG,
+ TN_GUI_BACKGROUND,
+ TN_GUI_INVENTORY,
+ TN_GUI_CONTAINER,
+ TN_GUI_CRAFTING,
+ TN_GUI_FURNACE,
+ TN_GUI_CREATIVE_TABS,
+ TN_GUI_CREATIVE_TAB_ITEMS,
+ TN_GUI_CREATIVE_TAB_INVENTORY,
+ TN_GUI_CREATIVE_TAB_ITEM_SEARCH,
+ TN_TITLE_MCLOGO,
+ TN_GUI_HORSE,
+ TN_GUI_ANVIL,
+ TN_GUI_TRAP,
+ TN_GUI_BEACON,
+ TN_GUI_HOPPER,
+ TN_GUI_ENCHANT,
+ TN_GUI_VILLAGER,
+ TN_GUI_BREWING_STAND,
+ TN_TITLE_BG_PANORAMA,
+ TN_TITLE_BG_PANORAMA0,
+ TN_TITLE_BG_PANORAMA1,
+ TN_TITLE_BG_PANORAMA2,
+ TN_TITLE_BG_PANORAMA3,
+ TN_TITLE_BG_PANORAMA4,
+ TN_TITLE_BG_PANORAMA5,
+#endif
// TN_TILE_XMAS_CHEST,
// TN_TILE_LARGE_XMAS_CHEST,
@@ -352,4 +371,4 @@ public:
// drive
static bool IsTUImage(TEXTURE_NAME texId, const std::wstring& name);
static bool IsOriginalImage(TEXTURE_NAME texId, const std::wstring& name);
-};
+};
\ No newline at end of file
diff --git a/Minecraft.Client/UI/AbstractBeaconButton.cpp b/Minecraft.Client/UI/AbstractBeaconButton.cpp
new file mode 100644
index 000000000..92b49e881
--- /dev/null
+++ b/Minecraft.Client/UI/AbstractBeaconButton.cpp
@@ -0,0 +1,46 @@
+#include "../../Platform/stdafx.h"
+#include "AbstractBeaconButton.h"
+#include "../Textures/Textures.h"
+#include "../../../Minecraft.Client/Minecraft.h"
+#include
+
+// 4jcraft: referenced from MCP 8.11 (JE 1.6.4)
+#ifdef ENABLE_JAVA_GUIS
+extern ResourceLocation GUI_BEACON_LOCATION;
+#endif
+
+AbstractBeaconButton::AbstractBeaconButton(int id, int x, int y)
+ : Button(id, x, y, 22, 22, L"") {
+ hovered = false;
+ selected = false;
+ iconRes = nullptr;
+ iconU = iconV = 0;
+}
+
+void AbstractBeaconButton::renderBg(Minecraft* minecraft, int xm, int ym) {
+#ifdef ENABLE_JAVA_GUIS
+ if (!visible) return;
+
+ hovered = (xm >= x && ym >= y && xm < x + w && ym < y + h);
+
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+ minecraft->textures->bindTexture(&GUI_BEACON_LOCATION);
+
+ int texU = 0;
+ if (!active) {
+ texU += w * 2;
+ } else if (selected) {
+ texU += w * 1;
+ } else if (hovered) {
+ texU += w * 3;
+ }
+ int texV = 219;
+
+ blit(x, y, texU, texV, w, h);
+
+ if (iconRes != nullptr && iconRes != &GUI_BEACON_LOCATION) {
+ minecraft->textures->bindTexture(iconRes);
+ }
+ blit(x + 2, y + 2, iconU, iconV, 18, 18);
+#endif
+}
\ No newline at end of file
diff --git a/Minecraft.Client/UI/AbstractBeaconButton.h b/Minecraft.Client/UI/AbstractBeaconButton.h
new file mode 100644
index 000000000..3254f4912
--- /dev/null
+++ b/Minecraft.Client/UI/AbstractBeaconButton.h
@@ -0,0 +1,24 @@
+#pragma once
+#include "Button.h"
+
+class ResourceLocation;
+
+class AbstractBeaconButton : public Button {
+protected:
+ bool hovered;
+ bool selected;
+ ResourceLocation* iconRes;
+ int iconU, iconV;
+
+public:
+ AbstractBeaconButton(int id, int x, int y);
+
+ void setSelected(bool sel) { selected = sel; }
+ bool isSelected() const { return selected; }
+ bool isHovered() const { return hovered; }
+
+ virtual void renderTooltip(int xm, int ym) = 0;
+
+protected:
+ virtual void renderBg(Minecraft* minecraft, int xm, int ym) override;
+};
\ No newline at end of file
diff --git a/Minecraft.Client/UI/BeaconCancelButton.cpp b/Minecraft.Client/UI/BeaconCancelButton.cpp
new file mode 100644
index 000000000..081029e4c
--- /dev/null
+++ b/Minecraft.Client/UI/BeaconCancelButton.cpp
@@ -0,0 +1,25 @@
+#include "../../Platform/stdafx.h"
+#include "BeaconCancelButton.h"
+#include "Screens/BeaconScreen.h"
+#include "../../../Minecraft.World/Headers/net.minecraft.locale.h"
+
+// 4jcraft: referenced from MCP 8.11 (JE 1.6.4)
+#ifdef ENABLE_JAVA_GUIS
+extern ResourceLocation GUI_BEACON_LOCATION;
+#endif
+
+BeaconCancelButton::BeaconCancelButton(BeaconScreen* screen, int id, int x,
+ int y)
+ : AbstractBeaconButton(id, x, y) {
+ this->screen = screen;
+#ifdef ENABLE_JAVA_GUIS
+ this->iconRes = &GUI_BEACON_LOCATION;
+#endif
+ this->iconU = 112;
+ this->iconV = 220;
+}
+
+void BeaconCancelButton::renderTooltip(int xm, int ym) {
+ screen->renderTooltip(Language::getInstance()->getElement(L"gui.cancel"),
+ xm, ym);
+}
\ No newline at end of file
diff --git a/Minecraft.Client/UI/BeaconCancelButton.h b/Minecraft.Client/UI/BeaconCancelButton.h
new file mode 100644
index 000000000..f9d62456e
--- /dev/null
+++ b/Minecraft.Client/UI/BeaconCancelButton.h
@@ -0,0 +1,13 @@
+#pragma once
+#include "AbstractBeaconButton.h"
+
+class BeaconScreen;
+
+class BeaconCancelButton : public AbstractBeaconButton {
+public:
+ BeaconCancelButton(BeaconScreen* screen, int id, int x, int y);
+ void renderTooltip(int xm, int ym) override;
+
+private:
+ BeaconScreen* screen;
+};
\ No newline at end of file
diff --git a/Minecraft.Client/UI/BeaconConfirmButton.cpp b/Minecraft.Client/UI/BeaconConfirmButton.cpp
new file mode 100644
index 000000000..00871f6e1
--- /dev/null
+++ b/Minecraft.Client/UI/BeaconConfirmButton.cpp
@@ -0,0 +1,25 @@
+#include "../../Platform/stdafx.h"
+#include "BeaconConfirmButton.h"
+#include "Screens/BeaconScreen.h"
+#include "../../../Minecraft.World/Headers/net.minecraft.locale.h"
+
+// 4jcraft: referenced from MCP 8.11 (JE 1.6.4)
+#ifdef ENABLE_JAVA_GUIS
+extern ResourceLocation GUI_BEACON_LOCATION;
+#endif
+
+BeaconConfirmButton::BeaconConfirmButton(BeaconScreen* screen, int id, int x,
+ int y)
+ : AbstractBeaconButton(id, x, y) {
+ this->screen = screen;
+#ifdef ENABLE_JAVA_GUIS
+ this->iconRes = &GUI_BEACON_LOCATION;
+#endif
+ this->iconU = 90;
+ this->iconV = 220;
+}
+
+void BeaconConfirmButton::renderTooltip(int xm, int ym) {
+ screen->renderTooltip(Language::getInstance()->getElement(L"gui.done"), xm,
+ ym);
+}
\ No newline at end of file
diff --git a/Minecraft.Client/UI/BeaconConfirmButton.h b/Minecraft.Client/UI/BeaconConfirmButton.h
new file mode 100644
index 000000000..ab1d28177
--- /dev/null
+++ b/Minecraft.Client/UI/BeaconConfirmButton.h
@@ -0,0 +1,13 @@
+#pragma once
+#include "AbstractBeaconButton.h"
+
+class BeaconScreen;
+
+class BeaconConfirmButton : public AbstractBeaconButton {
+public:
+ BeaconConfirmButton(BeaconScreen* screen, int id, int x, int y);
+ void renderTooltip(int xm, int ym) override;
+
+private:
+ BeaconScreen* screen;
+};
\ No newline at end of file
diff --git a/Minecraft.Client/UI/BeaconPowerButton.cpp b/Minecraft.Client/UI/BeaconPowerButton.cpp
new file mode 100644
index 000000000..958badfe7
--- /dev/null
+++ b/Minecraft.Client/UI/BeaconPowerButton.cpp
@@ -0,0 +1,39 @@
+#include "../../Platform/stdafx.h"
+#include "BeaconPowerButton.h"
+#include "Screens/BeaconScreen.h"
+#include "../../../Minecraft.World/Entities/MobEffect.h"
+#include "../../../Minecraft.World/Headers/net.minecraft.locale.h"
+#include "../Textures/Textures.h"
+#include "Textures/ResourceLocation.h"
+
+// 4jcraft: referenced from MCP 8.11 (JE 1.6.4)
+#ifdef ENABLE_JAVA_GUIS
+ResourceLocation GUI_INVENTORY_LOCATION = ResourceLocation(TN_GUI_INVENTORY);
+#endif
+
+BeaconPowerButton::BeaconPowerButton(BeaconScreen* screen, int id, int x, int y,
+ int effectId, int tier)
+ : AbstractBeaconButton(id, x, y) {
+ this->screen = screen;
+ this->effectId = effectId;
+ this->tier = tier;
+
+#ifdef ENABLE_JAVA_GUIS
+ this->iconRes = &GUI_INVENTORY_LOCATION;
+#endif
+
+ int statusIconIndex = MobEffect::javaId(effectId);
+ this->iconU = (statusIconIndex % 8) * 18;
+ this->iconV = 198 + (statusIconIndex / 8) * 18;
+}
+
+void BeaconPowerButton::renderTooltip(int xm, int ym) {
+ MobEffect* effect = MobEffect::effects[effectId];
+ if (!effect) return;
+
+ std::wstring name = app.GetString(effect->getDescriptionId());
+ if (tier >= 3 && effect->id != MobEffect::regeneration->id) {
+ name += L" II";
+ }
+ screen->renderTooltip(name, xm, ym);
+}
\ No newline at end of file
diff --git a/Minecraft.Client/UI/BeaconPowerButton.h b/Minecraft.Client/UI/BeaconPowerButton.h
new file mode 100644
index 000000000..fc6e40266
--- /dev/null
+++ b/Minecraft.Client/UI/BeaconPowerButton.h
@@ -0,0 +1,18 @@
+#pragma once
+#include "AbstractBeaconButton.h"
+#include "../../../Minecraft.World/Headers/net.minecraft.world.effect.h"
+
+class BeaconScreen;
+
+class BeaconPowerButton : public AbstractBeaconButton {
+public:
+ BeaconPowerButton(BeaconScreen* screen, int id, int x, int y, int effectId,
+ int tier);
+ void renderTooltip(int xm, int ym) override;
+ bool isSelected() const { return selected; }
+
+private:
+ BeaconScreen* screen;
+ int effectId;
+ int tier;
+};
\ No newline at end of file
diff --git a/Minecraft.Client/UI/Button.cpp b/Minecraft.Client/UI/Button.cpp
index 09630ed6b..ced455e3b 100644
--- a/Minecraft.Client/UI/Button.cpp
+++ b/Minecraft.Client/UI/Button.cpp
@@ -2,6 +2,10 @@
#include "Button.h"
#include "../Textures/Textures.h"
+#ifdef ENABLE_JAVA_GUIS
+ResourceLocation GUI_GUI_LOCATION = ResourceLocation(TN_GUI_GUI);
+#endif
+
Button::Button(int id, int x, int y, const std::wstring& msg) {
init(id, x, y, 200, 20, msg);
}
@@ -34,12 +38,14 @@ int Button::getYImage(bool hovered) {
}
void Button::render(Minecraft* minecraft, int xm, int ym) {
+#ifdef ENABLE_JAVA_GUIS
if (!visible) return;
Font* font = minecraft->font;
- glBindTexture(GL_TEXTURE_2D, minecraft->textures->loadTexture(
- TN_GUI_GUI)); // 4J was L"/gui/gui.png"
+ // glBindTexture(GL_TEXTURE_2D, minecraft->textures->loadTexture(
+ // TN_GUI_GUI)); // 4J was L"/gui/gui.png"
+ minecraft->textures->bindTexture(&GUI_GUI_LOCATION);
glColor4f(1, 1, 1, 1);
bool hovered = xm >= x && ym >= y && xm < x + w && ym < y + h;
@@ -59,6 +65,7 @@ void Button::render(Minecraft* minecraft, int xm, int ym) {
drawCenteredString(font, msg, x + w / 2, y + (h - 8) / 2, 0xe0e0e0);
}
}
+#endif
}
void Button::renderBg(Minecraft* minecraft, int xm, int ym) {}
diff --git a/Minecraft.Client/UI/EditBox.cpp b/Minecraft.Client/UI/EditBox.cpp
index 2ce3d3224..da48457e7 100644
--- a/Minecraft.Client/UI/EditBox.cpp
+++ b/Minecraft.Client/UI/EditBox.cpp
@@ -7,6 +7,9 @@ EditBox::EditBox(Screen* screen, Font* font, int x, int y, int width,
// 4J - added initialisers
maxLength = 0;
frame = 0;
+ enableBackgroundDrawing =
+ true; // 4jcraft: for toggling the background rendering (from 1.6.4,
+ // mainly for RepairScreen)
this->screen = screen;
this->font = font;
@@ -68,18 +71,36 @@ void EditBox::focus(bool newFocus) {
}
void EditBox::render() {
- fill(x - 1, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0);
- fill(x, y, x + width, y + height, 0xff000000);
+ // 4jcraft: render the background conditionally
+ if (enableBackgroundDrawing) {
+ fill(x - 1, y - 1, x + width + 1, y + height + 1, 0xffa0a0a0);
+ fill(x, y, x + width, y + height, 0xff000000);
+ }
+
+ // 4jcraft: offset conditionally
+ int textX = x;
+ int textY = y;
+ if (enableBackgroundDrawing) {
+ textX += 4;
+ textY += (height - 8) / 2;
+ }
if (active) {
bool renderUnderscore = inFocus && (frame / 6 % 2 == 0);
- drawString(font, value + (renderUnderscore ? L"_" : L""), x + 4,
- y + (height - 8) / 2, 0xe0e0e0);
+ drawString(font, value + (renderUnderscore ? L"_" : L""), textX, textY,
+ (enableBackgroundDrawing ? 0xe0e0e0 : 0xffffff));
} else {
- drawString(font, value, x + 4, y + (height - 8) / 2, 0x707070);
+ drawString(font, value, textX, textY,
+ (enableBackgroundDrawing ? 0xe0e0e0 : 0xffffff));
}
}
void EditBox::setMaxLength(int maxLength) { this->maxLength = maxLength; }
-int EditBox::getMaxLength() { return maxLength; }
\ No newline at end of file
+int EditBox::getMaxLength() { return maxLength; }
+
+// 4jcraft: for toggling the background rendering (from 1.6.4, mainly for
+// RepairScreen)
+void EditBox::setEnableBackgroundDrawing(bool enable) {
+ enableBackgroundDrawing = enable;
+}
\ No newline at end of file
diff --git a/Minecraft.Client/UI/EditBox.h b/Minecraft.Client/UI/EditBox.h
index 1b78d424f..133bfc0f8 100644
--- a/Minecraft.Client/UI/EditBox.h
+++ b/Minecraft.Client/UI/EditBox.h
@@ -18,6 +18,8 @@ private:
public:
bool inFocus;
bool active;
+ bool enableBackgroundDrawing; // 4jcraft: for toggling the background
+ // rendering (mainly for RepairScreen)
private:
Screen* screen;
@@ -34,4 +36,7 @@ public:
void render();
void setMaxLength(int maxLength);
int getMaxLength();
+
+ // 4jcraft: for toggling the background rendering (mainly for RepairScreen)
+ void setEnableBackgroundDrawing(bool enable);
};
\ No newline at end of file
diff --git a/Minecraft.Client/UI/Gui.cpp b/Minecraft.Client/UI/Gui.cpp
index 3dee33ba4..4dd7f056f 100644
--- a/Minecraft.Client/UI/Gui.cpp
+++ b/Minecraft.Client/UI/Gui.cpp
@@ -56,6 +56,10 @@ Gui::Gui(Minecraft* minecraft) {
tbr = 1.0f;
fAlphaIncrementPerCent = 255.0f / 100.0f;
+ // 4jcraft: backported item switch tooltip display from 1.6.4
+ remainingHighlightTicks = 0;
+ highlightingItemStack = nullptr;
+
this->minecraft = minecraft;
lastTickA = 0.0f;
@@ -811,6 +815,31 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) {
}
#if RENDER_HUD
+ // 4jcraft: backported item switch tooltip display from 1.6.4
+ if (remainingHighlightTicks > 0 && highlightingItemStack != nullptr) {
+ std::wstring displayName = highlightingItemStack->getHoverName();
+ int x = (screenWidth - font->width(displayName)) / 2;
+ int y = screenHeight - 89;
+
+ if (!minecraft->gameMode->canHurtPlayer()) {
+ y += 14;
+ }
+
+ int alpha = (int)((float)remainingHighlightTicks * 256.0f / 10.0f);
+ if (alpha > 255) alpha = 255;
+ if (alpha > 0) {
+ glPushMatrix();
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+ int color = 0xFFFFFF | (alpha << 24);
+ font->drawShadow(displayName, x, y, color);
+
+ glDisable(GL_BLEND);
+ glPopMatrix();
+ }
+ }
+
// Moved so the opacity blend is applied to it
if (bDisplayGui && minecraft->gameMode->hasExperience() &&
minecraft->player->experienceLevel > 0) {
@@ -1260,7 +1289,8 @@ void Gui::renderSlot(int slot, int x, int y, float a) {
}
itemRenderer->renderAndDecorateItem(minecraft->font, minecraft->textures,
- item, x, y);
+ item, x, y, 1.0f, 1.0f, 1.0f,
+ item->isFoil(), false);
if (pop > 0) {
glPopMatrix();
@@ -1274,6 +1304,27 @@ void Gui::tick() {
if (overlayMessageTime > 0) overlayMessageTime--;
tickCount++;
+ // 4jcraft: backported item switch tooltip display from 1.6.4
+ if (minecraft->player != nullptr) {
+ std::shared_ptr currentItem =
+ minecraft->player->inventory->getSelected();
+
+ if (currentItem == nullptr) {
+ remainingHighlightTicks = 0;
+ } else if (highlightingItemStack != nullptr &&
+ currentItem->id == highlightingItemStack->id &&
+ currentItem->sameItemWithTags(highlightingItemStack) &&
+ (currentItem->isDamageableItem() ||
+ currentItem->getDamageValue() ==
+ highlightingItemStack->getDamageValue())) {
+ if (remainingHighlightTicks > 0) --remainingHighlightTicks;
+ } else {
+ remainingHighlightTicks = 40;
+ }
+
+ highlightingItemStack = currentItem;
+ }
+
for (int iPad = 0; iPad < XUSER_MAX_COUNT; iPad++) {
// 4J Stu - Fix for #10929 - MP LAB: Network Disconnects: Host does not
// receive an error message stating the client left the game when
diff --git a/Minecraft.Client/UI/Gui.h b/Minecraft.Client/UI/Gui.h
index 81ee2b5f8..4077c9c40 100644
--- a/Minecraft.Client/UI/Gui.h
+++ b/Minecraft.Client/UI/Gui.h
@@ -2,9 +2,9 @@
#include
#include "GuiComponent.h"
#include "GuiMessage.h"
+#include "../../../Minecraft.Client/Rendering/EntityRenderers/ItemRenderer.h"
class Random;
class Minecraft;
-class ItemRenderer;
class Gui : public GuiComponent {
private:
@@ -34,6 +34,10 @@ private:
float lastTickA;
float fAlphaIncrementPerCent;
+ // 4jcraft: backported item switch tooltip display from 1.6.4
+ int remainingHighlightTicks;
+ std::shared_ptr highlightingItemStack;
+
public:
static float currentGuiBlendFactor; // 4J added
static float currentGuiScaleFactor; // 4J added
diff --git a/Minecraft.Client/UI/Screen.cpp b/Minecraft.Client/UI/Screen.cpp
index c3260a893..d0d0a744c 100644
--- a/Minecraft.Client/UI/Screen.cpp
+++ b/Minecraft.Client/UI/Screen.cpp
@@ -174,7 +174,6 @@ void Screen::renderBackground(int vo) {
}
void Screen::renderDirtBackground(int vo) {
- // 4J Unused - Iggy Flash UI renders the background on consoles
#ifdef ENABLE_JAVA_GUIS
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
diff --git a/Minecraft.Client/UI/Screens/AbstractContainerScreen.cpp b/Minecraft.Client/UI/Screens/AbstractContainerScreen.cpp
index a3b16edc5..00a7e81f1 100644
--- a/Minecraft.Client/UI/Screens/AbstractContainerScreen.cpp
+++ b/Minecraft.Client/UI/Screens/AbstractContainerScreen.cpp
@@ -95,138 +95,11 @@ void AbstractContainerScreen::render(int xm, int ym, float a) {
hoveredSlot->hasItem()) {
std::shared_ptr item = hoveredSlot->getItem();
- // std::wstring elementName =
- // trimString(Language::getInstance()->getElementName(hoveredSlot->getItem()->getDescriptionId()));
- std::vector elementName;
- std::vector* tooltipLines =
- item->getHoverText(minecraft->player, false, elementName);
+ int xo = (width - imageWidth) / 2;
+ int yo = (height - imageHeight) / 2;
- if (tooltipLines != NULL && tooltipLines->size() > 0) {
- int tooltipWidth = 0;
- std::vector cleanedLines;
- std::vector lineColors;
-
- for (int lineIndex = 0; lineIndex < (int)tooltipLines->size();
- ++lineIndex) {
- std::wstring rawLine = (*tooltipLines)[lineIndex];
- std::wstring clean = L"";
- int lineColor = 0xffffffff;
-
- // 4jcraft: LCE is using HTML font elements for its tooltip
- // colors, so make sure to parse them for parity w iggy UI
- //
- // examples would be enchantment books, potions and music
- // discs
- size_t fontPos = rawLine.find(L"') {
- inTag = false;
- } else if (!inTag) {
- clean += currentChar;
- }
- }
-
- cleanedLines.push_back(clean);
- lineColors.push_back(lineColor);
-
- int lineWidth = font->width(clean);
- if (lineWidth > tooltipWidth) {
- tooltipWidth = lineWidth;
- }
- }
-
- int tooltipX = xm - xo + 12;
- int tooltipY = ym - yo - 12;
-
- int tooltipHeight = 8;
-
- if (tooltipLines->size() > 1) {
- tooltipHeight += 2 + (tooltipLines->size() - 1) * 10;
- }
-
- int bgColor = 0xf0100010;
- fillGradient(tooltipX - 3, tooltipY - 4,
- tooltipX + tooltipWidth + 3, tooltipY - 3, bgColor,
- bgColor);
- fillGradient(tooltipX - 3, tooltipY + tooltipHeight + 3,
- tooltipX + tooltipWidth + 3,
- tooltipY + tooltipHeight + 4, bgColor, bgColor);
- fillGradient(tooltipX - 3, tooltipY - 3,
- tooltipX + tooltipWidth + 3,
- tooltipY + tooltipHeight + 3, bgColor, bgColor);
- fillGradient(tooltipX - 4, tooltipY - 3, tooltipX - 3,
- tooltipY + tooltipHeight + 3, bgColor, bgColor);
- fillGradient(tooltipX + tooltipWidth + 3, tooltipY - 3,
- tooltipX + tooltipWidth + 4,
- tooltipY + tooltipHeight + 3, bgColor, bgColor);
-
- int borderStart = 0x505000ff;
- int borderFinish =
- (borderStart & 0xfefefe) >> 1 | borderStart & 0xff000000;
- fillGradient(tooltipX - 3, (tooltipY - 3) + 1, (tooltipX - 3) + 1,
- (tooltipY + tooltipHeight + 3) - 1, borderStart,
- borderFinish);
- fillGradient(tooltipX + tooltipWidth + 2, (tooltipY - 3) + 1,
- tooltipX + tooltipWidth + 3,
- (tooltipY + tooltipHeight + 3) - 1, borderStart,
- borderFinish);
- fillGradient(tooltipX - 3, tooltipY - 3,
- tooltipX + tooltipWidth + 3, (tooltipY - 3) + 1,
- borderStart, borderStart);
- fillGradient(tooltipX - 3, tooltipY + tooltipHeight + 2,
- tooltipX + tooltipWidth + 3,
- tooltipY + tooltipHeight + 3, borderFinish,
- borderFinish);
-
- int currentY = tooltipY;
- for (int lineIndex = 0; lineIndex < (int)tooltipLines->size();
- ++lineIndex) {
- std::wstring& currentLine = cleanedLines[lineIndex];
- int textColor;
-
- if (lineIndex == 0) {
- textColor = app.GetHTMLColour(item->getRarity()->color);
- } else {
- textColor = (lineColors[lineIndex] != 0xffffffff)
- ? lineColors[lineIndex]
- : 0xffaaaaaa;
- }
-
- font->drawShadow(currentLine, tooltipX, currentY, textColor);
-
- if (lineIndex == 0) {
- currentY += 2;
- }
-
- currentY += 10;
- }
- }
+ // 4jcraft: abstracted tooltip rendering into a new method
+ renderTooltip(item, xm - xo, ym - yo);
}
glPopMatrix();
@@ -237,10 +110,167 @@ void AbstractContainerScreen::render(int xm, int ym, float a) {
#endif
}
+// 4jcraft: extracted from render() into a standalone method so this can be used
+// in other derived classes
+// update: also added 1.6.x era overloads (for the creative inventory and other
+// places)
+void AbstractContainerScreen::renderTooltipInternal(
+ const std::vector& cleanedLines,
+ const std::vector& lineColors, int xm, int ym) {
+ if (cleanedLines.empty()) return;
+
+ int tooltipWidth = 0;
+ for (const auto& line : cleanedLines) {
+ int lineWidth = font->width(line);
+ if (lineWidth > tooltipWidth) tooltipWidth = lineWidth;
+ }
+
+ int tooltipX = xm + 12;
+ int tooltipY = ym - 12;
+ int tooltipHeight = 8;
+
+ if (cleanedLines.size() > 1) {
+ tooltipHeight += 2 + (cleanedLines.size() - 1) * 10;
+ }
+
+ int bgColor = 0xf0100010;
+ fillGradient(tooltipX - 3, tooltipY - 4, tooltipX + tooltipWidth + 3,
+ tooltipY - 3, bgColor, bgColor);
+ fillGradient(tooltipX - 3, tooltipY + tooltipHeight + 3,
+ tooltipX + tooltipWidth + 3, tooltipY + tooltipHeight + 4,
+ bgColor, bgColor);
+ fillGradient(tooltipX - 3, tooltipY - 3, tooltipX + tooltipWidth + 3,
+ tooltipY + tooltipHeight + 3, bgColor, bgColor);
+ fillGradient(tooltipX - 4, tooltipY - 3, tooltipX - 3,
+ tooltipY + tooltipHeight + 3, bgColor, bgColor);
+ fillGradient(tooltipX + tooltipWidth + 3, tooltipY - 3,
+ tooltipX + tooltipWidth + 4, tooltipY + tooltipHeight + 3,
+ bgColor, bgColor);
+
+ int borderStart = 0x505000ff;
+ int borderFinish = (borderStart & 0xfefefe) >> 1 | borderStart & 0xff000000;
+ fillGradient(tooltipX - 3, (tooltipY - 3) + 1, (tooltipX - 3) + 1,
+ (tooltipY + tooltipHeight + 3) - 1, borderStart, borderFinish);
+ fillGradient(tooltipX + tooltipWidth + 2, (tooltipY - 3) + 1,
+ tooltipX + tooltipWidth + 3,
+ (tooltipY + tooltipHeight + 3) - 1, borderStart, borderFinish);
+ fillGradient(tooltipX - 3, tooltipY - 3, tooltipX + tooltipWidth + 3,
+ (tooltipY - 3) + 1, borderStart, borderStart);
+ fillGradient(tooltipX - 3, tooltipY + tooltipHeight + 2,
+ tooltipX + tooltipWidth + 3, tooltipY + tooltipHeight + 3,
+ borderFinish, borderFinish);
+
+ int currentY = tooltipY;
+ for (size_t lineIndex = 0; lineIndex < cleanedLines.size(); ++lineIndex) {
+ const std::wstring& currentLine = cleanedLines[lineIndex];
+ int textColor = lineColors[lineIndex];
+
+ font->drawShadow(currentLine, tooltipX, currentY, textColor);
+
+ if (lineIndex == 0) {
+ currentY += 2;
+ }
+ currentY += 10;
+ }
+}
+
+void AbstractContainerScreen::renderTooltip(std::shared_ptr item,
+ int xm, int ym) {
+ if (item == nullptr) return;
+
+ std::vector elementName;
+ std::vector* tooltipLines =
+ item->getHoverText(minecraft->player, false, elementName);
+
+ if (tooltipLines != NULL && tooltipLines->size() > 0) {
+ std::vector cleanedLines;
+ std::vector |