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 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); + } + + if (!cleanedLines.empty()) { + lineColors[0] = app.GetHTMLColour(item->getRarity()->color); + } + + renderTooltipInternal(cleanedLines, lineColors, xm, ym); + } +} + +void AbstractContainerScreen::renderTooltip( + const std::vector& lines, int xm, int ym) { + if (lines.empty()) return; + + std::vector cleanedLines = lines; + std::vector lineColors; + lineColors.reserve(lines.size()); + + for (size_t i = 0; i < lines.size(); ++i) { + if (i == 0) { + lineColors.push_back(0xffffffff); + } else { + lineColors.push_back(0xffaaaaaa); + } + } + + renderTooltipInternal(cleanedLines, lineColors, xm, ym); +} + +void AbstractContainerScreen::renderTooltip(const std::wstring& line, int xm, + int ym) { + renderTooltip(std::vector{line}, xm, ym); +} + void AbstractContainerScreen::renderLabels() {} void AbstractContainerScreen::renderSlot(Slot* slot) { - // 4J Unused #if ENABLE_JAVA_GUIS int x = slot->x; int y = slot->y; @@ -278,14 +308,20 @@ Slot* AbstractContainerScreen::findSlot(int x, int y) { return NULL; } -bool AbstractContainerScreen::isHovering(Slot* slot, int xm, int ym) { +// 4jcraft: equivalent to MCP 8.11 (1.6.x)'s GuiContainer.isPointInRegion() for +// use in other derived classes +bool AbstractContainerScreen::isHoveringOver(int x, int y, int w, int h, int xm, + int ym) { int xo = (width - imageWidth) / 2; int yo = (height - imageHeight) / 2; xm -= xo; ym -= yo; - return xm >= slot->x - 1 && xm < slot->x + 16 + 1 && ym >= slot->y - 1 && - ym < slot->y + 16 + 1; + return xm >= x - 1 && xm < x + w + 1 && ym >= y - 1 && ym < y + h + 1; +} + +bool AbstractContainerScreen::isHovering(Slot* slot, int xm, int ym) { + return isHoveringOver(slot->x, slot->y, 16, 16, xm, ym); } void AbstractContainerScreen::mouseClicked(int x, int y, int buttonNum) { @@ -306,9 +342,10 @@ void AbstractContainerScreen::mouseClicked(int x, int y, int buttonNum) { } if (slotId != -1) { - bool quickKey = slotId != AbstractContainerMenu::SLOT_CLICKED_OUTSIDE && - (Keyboard::isKeyDown(Keyboard::KEY_LSHIFT) || - Keyboard::isKeyDown(Keyboard::KEY_RSHIFT)); + bool quickKey = + slotId != AbstractContainerMenu::SLOT_CLICKED_OUTSIDE && + (Keyboard::isKeyDown(Keyboard::KEY_LSHIFT) || + Keyboard::isKeyDown(Keyboard::KEY_RSHIFT)); minecraft->gameMode->handleInventoryMouseClick( menu->containerId, slotId, buttonNum, quickKey, minecraft->player); @@ -341,4 +378,4 @@ void AbstractContainerScreen::tick() { Screen::tick(); if (!minecraft->player->isAlive() || minecraft->player->removed) minecraft->player->closeContainer(); -} \ No newline at end of file +} diff --git a/Minecraft.Client/UI/Screens/AbstractContainerScreen.h b/Minecraft.Client/UI/Screens/AbstractContainerScreen.h index da3d3e625..462e178d5 100644 --- a/Minecraft.Client/UI/Screens/AbstractContainerScreen.h +++ b/Minecraft.Client/UI/Screens/AbstractContainerScreen.h @@ -6,7 +6,8 @@ class Slot; class Container; class AbstractContainerScreen : public Screen { -private: +protected: + // 4jcraft: made protected to match JE 1.6.4 static ItemRenderer* itemRenderer; protected: @@ -17,8 +18,8 @@ public: AbstractContainerMenu* menu; AbstractContainerScreen(AbstractContainerMenu* menu); - virtual void init(); - virtual void render(int xm, int ym, float a); + virtual void init() override; + virtual void render(int xm, int ym, float a) override; protected: virtual void renderLabels(); @@ -27,19 +28,34 @@ protected: // can call findSlot() and isHovering() directly for its custom click // handling. virtual Slot* findSlot(int x, int y); + // 4jcraft: equivalent to MCP 8.11 (1.6.x)'s GuiContainer.isPointInRegion() + // for use in other derived classes + virtual bool isHoveringOver(int x, int y, int w, int h, int xm, int ym); virtual bool isHovering(Slot* slot, int xm, int ym); + // 4jcraft: extracted from render() into a standalone method so this can be + // used in other places + virtual void renderTooltipInternal( + const std::vector& cleanedLines, + const std::vector& lineColors, int xm, int ym); + virtual void renderTooltip(std::shared_ptr item, int xm, + int ym); private: virtual void renderSlot(Slot* slot); protected: - virtual void mouseClicked(int x, int y, int buttonNum); - virtual void mouseReleased(int x, int y, int buttonNum); - virtual void keyPressed(wchar_t eventCharacter, int eventKey); + virtual void mouseClicked(int x, int y, int buttonNum) override; + virtual void mouseReleased(int x, int y, int buttonNum) override; + virtual void keyPressed(wchar_t eventCharacter, int eventKey) override; public: - virtual void removed(); + virtual void removed() override; virtual void slotsChanged(std::shared_ptr container); - virtual bool isPauseScreen(); - virtual void tick(); -}; \ No newline at end of file + virtual bool isPauseScreen() override; + virtual void tick() override; + + // 4jcraft: 1.6.x era overloads + virtual void renderTooltip(const std::vector& lines, int xm, + int ym); + virtual void renderTooltip(const std::wstring& line, int xm, int ym); +}; diff --git a/Minecraft.Client/UI/Screens/AchievementPopup.cpp b/Minecraft.Client/UI/Screens/AchievementPopup.cpp index de59ec75b..512533c81 100644 --- a/Minecraft.Client/UI/Screens/AchievementPopup.cpp +++ b/Minecraft.Client/UI/Screens/AchievementPopup.cpp @@ -66,16 +66,15 @@ void AchievementPopup::prepareWindow() { } void AchievementPopup::render() { -// 4J Unused #if ENABLE_JAVA_GUIS - if (Minecraft::warezTime > 0) - { + if (Minecraft::warezTime > 0) { glDisable(GL_DEPTH_TEST); glDepthMask(false); Lighting::turnOff(); prepareWindow(); - std::wstring title = L"Minecraft " + SharedConstants::VERSION_STRING + L" Unlicensed Copy :("; + std::wstring title = L"Minecraft " + SharedConstants::VERSION_STRING + + L" Unlicensed Copy :("; std::wstring msg1 = L"(Or logged in from another location)"; std::wstring msg2 = L"Purchase at minecraft.net"; @@ -89,16 +88,12 @@ void AchievementPopup::render() { if (ach == NULL || startTime == 0) return; double time = (System::currentTimeMillis() - startTime) / 3000.0; - if (isHelper) - { - } - else if (!isHelper && (time < 0 || time > 1)) - { + if (isHelper) { + } else if (!isHelper && (time < 0 || time > 1)) { startTime = 0; return; } - prepareWindow(); glDisable(GL_DEPTH_TEST); glDepthMask(false); @@ -112,7 +107,7 @@ void AchievementPopup::render() { yo = yo * yo; int xx = width - 160; - int yy = 0 - (int) (yo * 36); + int yy = 0 - (int)(yo * 36); int tex = mc->textures->loadTexture(TN_ACHIEVEMENT_BG); glColor4f(1, 1, 1, 1); glEnable(GL_TEXTURE_2D); @@ -122,13 +117,13 @@ void AchievementPopup::render() { blit(xx, yy, 96, 202, 160, 32); // if (isHelper) - // { + // { // mc->font->drawWordWrap(desc, xx + 30, yy + 7, 120, 0xffffffff); // } - // else - // { - mc->font->draw(title, xx + 30, yy + 7, 0xffffff00); - mc->font->draw(desc, xx + 30, yy + 18, 0xffffffff); + // else + // { + mc->font->draw(title, xx + 30, yy + 7, 0xffffff00); + mc->font->draw(desc, xx + 30, yy + 18, 0xffffffff); // } glPushMatrix(); diff --git a/Minecraft.Client/UI/Screens/AchievementScreen.h b/Minecraft.Client/UI/Screens/AchievementScreen.h index 398ab950d..9c8a1223d 100644 --- a/Minecraft.Client/UI/Screens/AchievementScreen.h +++ b/Minecraft.Client/UI/Screens/AchievementScreen.h @@ -43,20 +43,20 @@ public: using Screen::keyPressed; AchievementScreen(StatsCounter* statsCounter); - virtual void init(); + virtual void init() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; virtual void keyPressed(char eventCharacter, int eventKey); public: - virtual void render(int mouseX, int mouseY, float a); - virtual void tick(); + virtual void render(int mouseX, int mouseY, float a) override; + virtual void tick() override; protected: virtual void renderLabels(); virtual void renderBg(int xm, int ym, float a); public: - virtual bool isPauseScreen(); + virtual bool isPauseScreen() override; }; diff --git a/Minecraft.Client/UI/Screens/BeaconScreen.cpp b/Minecraft.Client/UI/Screens/BeaconScreen.cpp new file mode 100644 index 000000000..d44378d83 --- /dev/null +++ b/Minecraft.Client/UI/Screens/BeaconScreen.cpp @@ -0,0 +1,229 @@ +#include "../../Platform/stdafx.h" +#include "BeaconScreen.h" +#include "../BeaconConfirmButton.h" +#include "../BeaconCancelButton.h" +#include "../BeaconPowerButton.h" +#include +#include +#include "../../Player/MultiPlayerLocalPlayer.h" +#include "../../Rendering/Lighting.h" +#include "../../Textures/Textures.h" +#include "../../../Minecraft.World/Headers/net.minecraft.locale.h" +#include "../../../Minecraft.World/Containers/Slot.h" +#include "../../../Minecraft.World/Headers/net.minecraft.world.item.h" +#include "../../../Minecraft.Client/Minecraft.h" +#include "../../../Minecraft.Client/Network/ClientConnection.h" +#include "../../../Minecraft.World/IO/Streams/ByteArrayOutputStream.h" +#include "../../../Minecraft.World/IO/Streams/DataOutputStream.h" + +// 4jcraft: referenced from MCP 8.11 (JE 1.6.4) and the existing +// container classes (and iggy too) +#ifdef ENABLE_JAVA_GUIS +ResourceLocation GUI_BEACON_LOCATION = ResourceLocation(TN_GUI_BEACON); +#endif + +BeaconScreen::BeaconScreen(std::shared_ptr inventory, + std::shared_ptr beacon) + : AbstractContainerScreen(new BeaconMenu(inventory, beacon)) { + this->inventory = inventory; + this->beacon = beacon; + this->beaconMenu = static_cast(menu); + this->imageWidth = 230; + this->imageHeight = 219; + this->buttonsNotDrawn = true; + this->beaconConfirmButton = nullptr; +} + +BeaconScreen::~BeaconScreen() = default; + +void BeaconScreen::init() { + AbstractContainerScreen::init(); + + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + + beaconConfirmButton = new BeaconConfirmButton(this, -1, xo + 164, yo + 107); + buttons.push_back(beaconConfirmButton); + buttons.push_back(new BeaconCancelButton(this, -2, xo + 190, yo + 107)); + + buttonsNotDrawn = true; + beaconConfirmButton->active = false; +} + +void BeaconScreen::tick() { + if (buttonsNotDrawn && beacon->getLevels() >= 0) { + buttonsNotDrawn = false; + + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + + for (int tier = 0; tier <= 2; ++tier) { + int effectCount = BeaconTileEntity::BEACON_EFFECTS_EFFECTS; + int actualCount = 0; + for (int e = 0; e < effectCount; ++e) { + if (BeaconTileEntity::BEACON_EFFECTS[tier][e] != nullptr) { + actualCount++; + } else { + break; + } + } + + int totalWidth = actualCount * 22 + (actualCount - 1) * 2; + int startX = xo + 53 + (actualCount * 24 - totalWidth) / 2; + + for (int e = 0; e < actualCount; ++e) { + MobEffect* effect = BeaconTileEntity::BEACON_EFFECTS[tier][e]; + if (effect == nullptr) break; + + int buttonId = (tier << 8) | effect->id; + BeaconPowerButton* button = new BeaconPowerButton( + this, buttonId, startX + e * 24, yo + 22 + tier * 25, + effect->id, tier); + buttons.push_back(button); + + if (tier >= beacon->getLevels()) { + button->active = false; + } else if (effect->id == beacon->getPrimaryPower()) { + button->setSelected(true); + } + } + } + + int tier = 3; + int effectCount = BeaconTileEntity::BEACON_EFFECTS_EFFECTS; + int actualCount = 0; + for (int e = 0; e < effectCount; ++e) { + if (BeaconTileEntity::BEACON_EFFECTS[tier][e] != nullptr) { + actualCount++; + } else { + break; + } + } + + int totalWidth = (actualCount + 1) * 22 + actualCount * 2; + int startX = xo + 143 + ((actualCount + 1) * 24 - totalWidth) / 2; + + for (int e = 0; e < actualCount; ++e) { + MobEffect* effect = BeaconTileEntity::BEACON_EFFECTS[tier][e]; + if (effect == nullptr) break; + + int buttonId = (tier << 8) | effect->id; + BeaconPowerButton* button = new BeaconPowerButton( + this, buttonId, startX + e * 24, yo + 47, effect->id, tier); + buttons.push_back(button); + + if (tier >= beacon->getLevels()) { + button->active = false; + } else if (effect->id == beacon->getSecondaryPower()) { + button->setSelected(true); + } + } + + if (beacon->getPrimaryPower() > 0) { + int buttonId = (tier << 8) | beacon->getPrimaryPower(); + BeaconPowerButton* button = + new BeaconPowerButton(this, buttonId, startX + actualCount * 24, + yo + 47, beacon->getPrimaryPower(), tier); + buttons.push_back(button); + + if (tier >= beacon->getLevels()) { + button->active = false; + } else if (beacon->getPrimaryPower() == + beacon->getSecondaryPower()) { + button->setSelected(true); + } + } + } + + beaconConfirmButton->active = + (beacon->getItem(0) != nullptr && beacon->getPrimaryPower() > 0); +} + +void BeaconScreen::removed() { AbstractContainerScreen::removed(); } + +void BeaconScreen::renderLabels() { + std::wstring primaryLabel = + Language::getInstance()->getElement(L"tile.beacon.primary"); + font->drawShadow(primaryLabel, 25, 10, 0xE1E1E1); + + std::wstring secondaryLabel = + Language::getInstance()->getElement(L"tile.beacon.secondary"); + font->drawShadow(secondaryLabel, 125, 10, 0xE1E1E1); +} + +void BeaconScreen::renderBg(float a) { +#ifdef ENABLE_JAVA_GUIS + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + minecraft->textures->bindTexture(&GUI_BEACON_LOCATION); + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + blit(xo, yo, 0, 0, imageWidth, imageHeight); + + // Render payment item icons + itemRenderer->renderGuiItem( + font, minecraft->textures, + std::shared_ptr(new ItemInstance(Item::emerald_Id, 1, 0)), + xo + 42, yo + 109); + itemRenderer->renderGuiItem( + font, minecraft->textures, + std::shared_ptr(new ItemInstance(Item::diamond_Id, 1, 0)), + xo + 42 + 22, yo + 109); + itemRenderer->renderGuiItem(font, minecraft->textures, + std::shared_ptr( + new ItemInstance(Item::goldIngot_Id, 1, 0)), + xo + 42 + 44, yo + 109); + itemRenderer->renderGuiItem(font, minecraft->textures, + std::shared_ptr( + new ItemInstance(Item::ironIngot_Id, 1, 0)), + xo + 42 + 66, yo + 109); +#endif +} + +void BeaconScreen::render(int xm, int ym, float a) { + AbstractContainerScreen::render(xm, ym, a); + for (Button* button : buttons) { + AbstractBeaconButton* beaconButton = + dynamic_cast(button); + if (beaconButton && beaconButton->isHovered()) { + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + beaconButton->renderTooltip(xm, ym); + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + break; + } + } +} + +void BeaconScreen::buttonClicked(Button* button) { + if (button->id == -2) { + minecraft->player->closeContainer(); + } else if (button->id == -1) { + // 4jcraft: copied from IUIScene_BeaconMenu + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + dos.writeInt(beacon->getPrimaryPower()); + dos.writeInt(beacon->getSecondaryPower()); + + minecraft->player->connection->send( + std::shared_ptr(new CustomPayloadPacket( + CustomPayloadPacket::SET_BEACON_PACKET, baos.toByteArray()))); + minecraft->player->closeContainer(); + } else if (dynamic_cast(button)) { + int effectId = button->id & 255; + int tier = button->id >> 8; + + if (tier < 3) { + beacon->setPrimaryPower(effectId); + } else { + beacon->setSecondaryPower(effectId); + } + + for (Button* btn : buttons) { + delete btn; + } + buttons.clear(); + init(); + tick(); + } +} \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/BeaconScreen.h b/Minecraft.Client/UI/Screens/BeaconScreen.h new file mode 100644 index 000000000..03a9db927 --- /dev/null +++ b/Minecraft.Client/UI/Screens/BeaconScreen.h @@ -0,0 +1,32 @@ +#pragma once + +#include "AbstractContainerScreen.h" +#include "../../../Minecraft.World/Containers/BeaconMenu.h" +#include "../../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h" + +class BeaconConfirmButton; +class BeaconCancelButton; + +class BeaconScreen : public AbstractContainerScreen { +public: + BeaconScreen(std::shared_ptr inventory, + std::shared_ptr beacon); + virtual ~BeaconScreen(); + + void init() override; + void removed() override; + void tick() override; + void renderLabels() override; + void renderBg(float a) override; + void render(int xm, int ym, float a) override; + void buttonClicked(Button* button) override; + + std::shared_ptr getBeacon() { return beacon; } + +private: + std::shared_ptr inventory; + std::shared_ptr beacon; + BeaconMenu* beaconMenu; + BeaconConfirmButton* beaconConfirmButton; + bool buttonsNotDrawn; +}; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/BrewingStandScreen.cpp b/Minecraft.Client/UI/Screens/BrewingStandScreen.cpp new file mode 100644 index 000000000..1d1239c2a --- /dev/null +++ b/Minecraft.Client/UI/Screens/BrewingStandScreen.cpp @@ -0,0 +1,99 @@ +#include "../../Platform/stdafx.h" +#include "BrewingStandScreen.h" +#include +#include +#include +#include "../../Player/MultiPlayerLocalPlayer.h" +#include "../../Rendering/Lighting.h" +#include "../../Textures/Textures.h" +#include "../../../Minecraft.World/Headers/net.minecraft.locale.h" +#include "../../../Minecraft.World/Containers/BrewingStandMenu.h" +#include "../../../Minecraft.World/Containers/Slot.h" +#include "../../../Minecraft.Client/Minecraft.h" + +// 4jcraft: referenced from MCP 8.11 (JE 1.6.4) and the existing +// container classes +#ifdef ENABLE_JAVA_GUIS +ResourceLocation GUI_BREWING_STAND_LOCATION = + ResourceLocation(TN_GUI_BREWING_STAND); +#endif + +BrewingStandScreen::BrewingStandScreen( + std::shared_ptr inventory, + std::shared_ptr brewingStand) + : AbstractContainerScreen(new BrewingStandMenu(inventory, brewingStand)) { + this->inventory = inventory; + this->brewingStand = brewingStand; + this->brewMenu = static_cast(menu); +} + +BrewingStandScreen::~BrewingStandScreen() = default; + +void BrewingStandScreen::init() { AbstractContainerScreen::init(); } + +void BrewingStandScreen::removed() { AbstractContainerScreen::removed(); } + +void BrewingStandScreen::renderLabels() { + font->draw(brewingStand->getName(), + (imageWidth / 2) - (font->width(brewingStand->getName()) / 2), 6, + 0x404040); + font->draw(inventory->getName(), 8, imageHeight - 96 + 2, 0x404040); +} + +void BrewingStandScreen::renderBg(float a) { +#ifdef ENABLE_JAVA_GUIS + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + Minecraft::GetInstance()->textures->bindTexture( + &GUI_BREWING_STAND_LOCATION); + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + blit(xo, yo, 0, 0, imageWidth, imageHeight); + + int brewTime = brewingStand->getBrewTime(); + + if (brewTime > 0) { + int arrowHeight = (int)(28.0f * (1.0f - (float)brewTime / 400.0f)); + + if (arrowHeight > 0) { + blit(xo + 97, yo + 16 + (28 - arrowHeight), 176, 28 - arrowHeight, + 9, arrowHeight); + } + + int bubbleStep = (brewTime / 2) % 7; + int bubbleHeight = 0; + + switch (bubbleStep) { + case 0: + bubbleHeight = 29; + break; + case 1: + bubbleHeight = 24; + break; + case 2: + bubbleHeight = 20; + break; + case 3: + bubbleHeight = 16; + break; + case 4: + bubbleHeight = 11; + break; + case 5: + bubbleHeight = 6; + break; + case 6: + bubbleHeight = 0; + break; + } + + if (bubbleHeight > 0) { + blit(xo + 65, yo + 14 + (29 - bubbleHeight), 185, 29 - bubbleHeight, + 12, bubbleHeight); + } + } +#endif +} + +void BrewingStandScreen::render(int xm, int ym, float a) { + AbstractContainerScreen::render(xm, ym, a); +} \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/BrewingStandScreen.h b/Minecraft.Client/UI/Screens/BrewingStandScreen.h new file mode 100644 index 000000000..12f834ed7 --- /dev/null +++ b/Minecraft.Client/UI/Screens/BrewingStandScreen.h @@ -0,0 +1,23 @@ +#pragma once + +#include "AbstractContainerScreen.h" +#include "../../../Minecraft.World/Containers/BrewingStandMenu.h" +#include "../../../Minecraft.World/Headers/net.minecraft.world.level.tile.entity.h" + +class BrewingStandScreen : public AbstractContainerScreen { +public: + BrewingStandScreen(std::shared_ptr inventory, + std::shared_ptr brewingStand); + virtual ~BrewingStandScreen(); + + void init() override; + void removed() override; + void renderLabels() override; + void renderBg(float a) override; + void render(int xm, int ym, float a) override; + +private: + std::shared_ptr inventory; + std::shared_ptr brewingStand; + BrewingStandMenu* brewMenu; +}; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/ChatScreen.h b/Minecraft.Client/UI/Screens/ChatScreen.h index a1d508fab..ce20f5a62 100644 --- a/Minecraft.Client/UI/Screens/ChatScreen.h +++ b/Minecraft.Client/UI/Screens/ChatScreen.h @@ -10,19 +10,19 @@ private: public: ChatScreen(); // 4J added - virtual void init(); - virtual void removed(); - virtual void tick(); + virtual void init() override; + virtual void removed() override; + virtual void tick() override; private: static const std::wstring allowedChars; protected: - void keyPressed(wchar_t ch, int eventKey); + void keyPressed(wchar_t ch, int eventKey) override; public: - void render(int xm, int ym, float a); + void render(int xm, int ym, float a) override; protected: - void mouseClicked(int x, int y, int buttonNum); + void mouseClicked(int x, int y, int buttonNum) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/ConfirmScreen.cpp b/Minecraft.Client/UI/Screens/ConfirmScreen.cpp index 16f4ffe9d..17133b288 100644 --- a/Minecraft.Client/UI/Screens/ConfirmScreen.cpp +++ b/Minecraft.Client/UI/Screens/ConfirmScreen.cpp @@ -47,9 +47,9 @@ void ConfirmScreen::render(int xm, int ym, float a) { Screen::render(xm, ym, a); // 4J - debug code - remove - static int count = 0; - if (count++ == 100) { - count = 0; - buttonClicked(buttons[0]); - } + // static int count = 0; + // if (count++ == 100) { + // count = 0; + // buttonClicked(buttons[0]); + // } } \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/ConfirmScreen.h b/Minecraft.Client/UI/Screens/ConfirmScreen.h index d0e337129..d400c70cd 100644 --- a/Minecraft.Client/UI/Screens/ConfirmScreen.h +++ b/Minecraft.Client/UI/Screens/ConfirmScreen.h @@ -16,11 +16,11 @@ public: ConfirmScreen(Screen* parent, const std::wstring& title1, const std::wstring& title2, const std::wstring& yesButton, const std::wstring& noButton, int id); - virtual void init(); + virtual void init() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/ConnectScreen.h b/Minecraft.Client/UI/Screens/ConnectScreen.h index bb817198c..f99add276 100644 --- a/Minecraft.Client/UI/Screens/ConnectScreen.h +++ b/Minecraft.Client/UI/Screens/ConnectScreen.h @@ -10,17 +10,17 @@ private: public: ConnectScreen(Minecraft* minecraft, const std::wstring& ip, int port); - virtual void tick(); + virtual void tick() override; protected: virtual void keyPressed(char eventCharacter, int eventKey); public: - virtual void init(); + virtual void init() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/ContainerScreen.h b/Minecraft.Client/UI/Screens/ContainerScreen.h index 2e37eafa7..fca18c2f3 100644 --- a/Minecraft.Client/UI/Screens/ContainerScreen.h +++ b/Minecraft.Client/UI/Screens/ContainerScreen.h @@ -14,6 +14,6 @@ public: std::shared_ptr container); protected: - virtual void renderLabels(); - virtual void renderBg(float a); + virtual void renderLabels() override; + virtual void renderBg(float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/ControlsScreen.h b/Minecraft.Client/UI/Screens/ControlsScreen.h index c5079aba1..3132fb451 100644 --- a/Minecraft.Client/UI/Screens/ControlsScreen.h +++ b/Minecraft.Client/UI/Screens/ControlsScreen.h @@ -25,12 +25,12 @@ private: int getLeftScreenPosition(); public: - void init(); + void init() override; protected: - void buttonClicked(Button* button); - void keyPressed(wchar_t eventCharacter, int eventKey); + void buttonClicked(Button* button) override; + void keyPressed(wchar_t eventCharacter, int eventKey) override; public: - void render(int xm, int ym, float a); + void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/CraftingScreen.cpp b/Minecraft.Client/UI/Screens/CraftingScreen.cpp index d9c3f4759..666c66878 100644 --- a/Minecraft.Client/UI/Screens/CraftingScreen.cpp +++ b/Minecraft.Client/UI/Screens/CraftingScreen.cpp @@ -2,11 +2,18 @@ #include "CraftingScreen.h" #include "../../Textures/Textures.h" #include "../../Player/MultiPlayerLocalPlayer.h" +#include "../../../Minecraft.World/Headers/net.minecraft.locale.h" #include "../../../Minecraft.World/Headers/net.minecraft.world.inventory.h" +#ifdef ENABLE_JAVA_GUIS +ResourceLocation GUI_CRAFTING_LOCATION = ResourceLocation(TN_GUI_CRAFTING); +#endif + CraftingScreen::CraftingScreen(std::shared_ptr inventory, Level* level, int x, int y, int z) - : AbstractContainerScreen(new CraftingMenu(inventory, level, x, y, z)) {} + : AbstractContainerScreen(new CraftingMenu(inventory, level, x, y, z)) { + this->inventory = inventory; +} void CraftingScreen::removed() { AbstractContainerScreen::removed(); @@ -14,16 +21,15 @@ void CraftingScreen::removed() { } void CraftingScreen::renderLabels() { - font->draw(L"Crafting", 8 + 16 + 4, 2 + 2 + 2, 0x404040); - font->draw(L"Inventory", 8, imageHeight - 96 + 2, 0x404040); + font->draw(Language::getInstance()->getElement(L"container.crafting"), + 8 + 16 + 4, 2 + 2 + 2, 0x404040); + font->draw(inventory->getName(), 8, imageHeight - 96 + 2, 0x404040); } void CraftingScreen::renderBg(float a) { - // 4J Unused #ifdef ENABLE_JAVA_GUIS - int tex = minecraft->textures->loadTexture(TN_GUI_CRAFTING); glColor4f(1, 1, 1, 1); - minecraft->textures->bind(tex); + minecraft->textures->bindTexture(&GUI_CRAFTING_LOCATION); int xo = (width - imageWidth) / 2; int yo = (height - imageHeight) / 2; this->blit(xo, yo, 0, 0, imageWidth, imageHeight); diff --git a/Minecraft.Client/UI/Screens/CraftingScreen.h b/Minecraft.Client/UI/Screens/CraftingScreen.h index ba59f871d..77eb664c7 100644 --- a/Minecraft.Client/UI/Screens/CraftingScreen.h +++ b/Minecraft.Client/UI/Screens/CraftingScreen.h @@ -4,12 +4,15 @@ class Inventory; class Level; class CraftingScreen : public AbstractContainerScreen { +private: + std::shared_ptr inventory; + public: CraftingScreen(std::shared_ptr inventory, Level* level, int x, int y, int z); - virtual void removed(); + virtual void removed() override; protected: - virtual void renderLabels(); - virtual void renderBg(float a); + virtual void renderLabels() override; + virtual void renderBg(float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/CreateWorldScreen.cpp b/Minecraft.Client/UI/Screens/CreateWorldScreen.cpp index c3395ec25..9de1625fb 100644 --- a/Minecraft.Client/UI/Screens/CreateWorldScreen.cpp +++ b/Minecraft.Client/UI/Screens/CreateWorldScreen.cpp @@ -30,8 +30,8 @@ void CreateWorldScreen::tick() { if (moreOptions) seedEdit->tick(); // 4J - debug code - to be removed - static int count = 0; - if (count++ == 100) buttonClicked(buttons[0]); + // static int count = 0; + // if (count++ == 100) buttonClicked(buttons[0]); } void CreateWorldScreen::init() { @@ -149,7 +149,9 @@ void CreateWorldScreen::buttonClicked(Button* button) { app.DebugPrintf("CreateWorldScreen::buttonClicked START\n"); if (!button->active) return; if (button->id == 1) { - app.DebugPrintf("CreateWorldScreen::buttonClicked 'Cancel' minecraft->setScreen(lastScreen)\n"); + app.DebugPrintf( + "CreateWorldScreen::buttonClicked 'Cancel' " + "minecraft->setScreen(lastScreen)\n"); minecraft->setScreen(lastScreen); } else if (button->id == 0) { minecraft->setScreen( diff --git a/Minecraft.Client/UI/Screens/CreateWorldScreen.h b/Minecraft.Client/UI/Screens/CreateWorldScreen.h index 71a18e4d5..ba38b2ec3 100644 --- a/Minecraft.Client/UI/Screens/CreateWorldScreen.h +++ b/Minecraft.Client/UI/Screens/CreateWorldScreen.h @@ -31,8 +31,8 @@ private: public: CreateWorldScreen(Screen* lastScreen); - virtual void tick(); - virtual void init(); + virtual void tick() override; + virtual void init() override; private: void updateResultFolder(); @@ -41,16 +41,16 @@ private: public: static std::wstring findAvailableFolderName(LevelStorageSource* levelSource, const std::wstring& folder); - virtual void removed(); + virtual void removed() override; protected: - virtual void buttonClicked(Button* button); - virtual void keyPressed(wchar_t ch, int eventKey); - virtual void mouseClicked(int x, int y, int buttonNum); + virtual void buttonClicked(Button* button) override; + virtual void keyPressed(wchar_t ch, int eventKey) override; + virtual void mouseClicked(int x, int y, int buttonNum) override; public: - virtual void render(int xm, int ym, float a); - virtual void tabPressed(); + virtual void render(int xm, int ym, float a) override; + virtual void tabPressed() override; private: int m_iGameModeId; diff --git a/Minecraft.Client/UI/Screens/CreativeInventoryScreen.cpp b/Minecraft.Client/UI/Screens/CreativeInventoryScreen.cpp index aea796309..ac8481673 100644 --- a/Minecraft.Client/UI/Screens/CreativeInventoryScreen.cpp +++ b/Minecraft.Client/UI/Screens/CreativeInventoryScreen.cpp @@ -15,513 +15,569 @@ #include // Static member initialization -int CreativeInventoryScreen::selectedTabIndex = IUIScene_CreativeMenu::eCreativeInventoryTab_BuildingBlocks; -std::shared_ptr CreativeInventoryScreen::basicInventory = std::make_shared(0, L"", false, ITEMS_PER_PAGE); +int CreativeInventoryScreen::selectedTabIndex = + IUIScene_CreativeMenu::eCreativeInventoryTab_BuildingBlocks; +const int CreativeInventoryScreen::tabIconIds + [IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT] = { + // Building Blocks + Tile::redBrick_Id, + + // Decorations + Tile::rose_Id, + + // Redstone & Transportation + Item::redStone_Id, + + // Materials + Item::stick_Id, + + // Food + Item::apple_Id, + +// Fix for it not compiling with shiggy +#ifdef ENABLE_JAVA_GUIS + // Search Items + Item::compass_Id, +#endif + + // Tools, Weapons & Armor + Item::hatchet_iron_Id, + + // Brewing + Item::potion_Id, + + // Materials + Item::bucket_lava_Id}; + +std::shared_ptr CreativeInventoryScreen::basicInventory = + std::make_shared(0, L"", false, ITEMS_PER_PAGE); +ItemRenderer* CreativeInventoryScreen::itemRenderer = new ItemRenderer(); +std::shared_ptr CreativeInventoryScreen::tabIcons + [IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT]; // ContainerCreative implementation -CreativeInventoryScreen::ContainerCreative::ContainerCreative(std::shared_ptr player) : AbstractContainerMenu() -{ - std::shared_ptr inventoryplayer = player->inventory; - - // Add creative inventory slots (5 rows x 9 columns = 45 slots) - for (int i = 0; i < ROWS; ++i) - { - for (int j = 0; j < COLUMNS; ++j) - { - addSlot(new Slot(basicInventory, i * COLUMNS + j, 9 + j * 18, 18 + i * 18)); - } - } - - // Add hotbar slots (9 slots at bottom) - for (int k = 0; k < 9; ++k) - { - addSlot(new Slot(inventoryplayer, k, 9 + k * 18, 112)); - } - - scrollTo(0.0f); +CreativeInventoryScreen::ContainerCreative::ContainerCreative( + std::shared_ptr player) + : AbstractContainerMenu() { + std::shared_ptr inventoryplayer = player->inventory; + + // Add creative inventory slots (5 rows x 9 columns = 45 slots) + for (int i = 0; i < ROWS; i++) { + for (int j = 0; j < COLUMNS; j++) { + addSlot(new Slot(basicInventory, i * COLUMNS + j, 9 + j * 18, + 18 + i * 18)); + } + } + + // Add hotbar slots (9 slots at bottom) + for (int k = 0; k < 9; ++k) { + addSlot(new Slot(inventoryplayer, k, 9 + k * 18, 112)); + } + + scrollTo(0.0f); + + for (int i = 0; i < IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT; + i++) { + tabIcons[i] = std::shared_ptr( + new ItemInstance(tabIconIds[i], 1, 0)); + } } -bool CreativeInventoryScreen::ContainerCreative::stillValid(std::shared_ptr player) -{ - return true; +bool CreativeInventoryScreen::ContainerCreative::stillValid( + std::shared_ptr player) { + return true; } -std::shared_ptr CreativeInventoryScreen::ContainerCreative::clicked(int slotIndex, int buttonNum, int clickType, std::shared_ptr player) -{ - std::shared_ptr inventory = player->inventory; - std::shared_ptr carried = inventory->getCarried(); - - // Handle clicks outside the GUI - if (slotIndex == SLOT_CLICKED_OUTSIDE) - { - // Drop the carried item - if (carried != NULL) - { - if (buttonNum == 0) - { - player->drop(carried, true); - inventory->setCarried(std::shared_ptr()); - } - else if (buttonNum == 1) - { - std::shared_ptr single = carried->copy(); - single->count = 1; - player->drop(single, true); - carried->count--; - if (carried->count <= 0) - { - inventory->setCarried(std::shared_ptr()); - } - } - } - return std::shared_ptr(); - } - - // Validate slot index - if (slotIndex < 0 || slotIndex >= (int)slots.size()) - { - return std::shared_ptr(); - } - - Slot* slot = slots.at(slotIndex); - - // Handle creative inventory slots (0-44) - if (slotIndex >= 0 && slotIndex < ITEMS_PER_PAGE) - { - std::shared_ptr slotItem = slot->getItem(); - - // Handle SWAP (number key) - copy item to hotbar - if (clickType == CLICK_SWAP) - { - if (slotItem != NULL && buttonNum >= 0 && buttonNum < 9) - { - std::shared_ptr copy = slotItem->copy(); - copy->count = copy->getMaxStackSize(); - inventory->setItem(buttonNum, copy); - } - return std::shared_ptr(); - } - - // Handle CLONE (middle click) - if (clickType == CLICK_CLONE) - { - if (slotItem != NULL) - { - std::shared_ptr copy = slotItem->copy(); - copy->count = copy->getMaxStackSize(); - inventory->setCarried(copy); - } - return std::shared_ptr(); - } - - // Handle normal clicks - if (slotItem != NULL) - { - if (buttonNum == 0) // Left click - { - std::shared_ptr copy = slotItem->copy(); - copy->count = copy->getMaxStackSize(); - inventory->setCarried(copy); - } - else if (buttonNum == 1) // Right click - { - std::shared_ptr copy = slotItem->copy(); - copy->count = 1; - inventory->setCarried(copy); - } - } - else if (carried != NULL) - { - // Clicking on empty creative slot with item - clear the carried item - inventory->setCarried(std::shared_ptr()); - } - - return std::shared_ptr(); - } - - // For hotbar slots (45-53), use normal container behavior - return AbstractContainerMenu::clicked(slotIndex, buttonNum, clickType, player); +std::shared_ptr +CreativeInventoryScreen::ContainerCreative::clicked( + int slotIndex, int buttonNum, int clickType, std::shared_ptr player, + bool looped) { + std::shared_ptr inventory = player->inventory; + std::shared_ptr carried = inventory->getCarried(); + + // Handle clicks outside the GUI + if (slotIndex == SLOT_CLICKED_OUTSIDE) { + // Drop the carried item + if (carried != NULL) { + if (buttonNum == 0) { + player->drop(carried, true); + inventory->setCarried(std::shared_ptr()); + } else if (buttonNum == 1) { + std::shared_ptr single = carried->copy(); + single->count = 1; + player->drop(single, true); + carried->count--; + if (carried->count <= 0) { + inventory->setCarried(std::shared_ptr()); + } + } + } + return std::shared_ptr(); + } + + // Validate slot index + if (slotIndex < 0 || slotIndex >= (int)slots.size()) { + return std::shared_ptr(); + } + + Slot* slot = slots.at(slotIndex); + + // Handle creative inventory slots (0-44) + if (slotIndex >= 0 && slotIndex < ITEMS_PER_PAGE) { + std::shared_ptr slotItem = slot->getItem(); + + // Handle SWAP (number key) - copy item to hotbar + if (clickType == CLICK_SWAP) { + if (slotItem != NULL && buttonNum >= 0 && buttonNum < 9) { + std::shared_ptr copy = slotItem->copy(); + copy->count = copy->getMaxStackSize(); + inventory->setItem(buttonNum, copy); + } + return std::shared_ptr(); + } + + // Handle CLONE (middle click) + if (clickType == CLICK_CLONE) { + if (slotItem != NULL) { + std::shared_ptr copy = slotItem->copy(); + copy->count = copy->getMaxStackSize(); + inventory->setCarried(copy); + } + return std::shared_ptr(); + } + + // Handle normal clicks + if (slotItem != NULL) { + if (buttonNum == 0) // Left click + { + std::shared_ptr copy = slotItem->copy(); + copy->count = copy->getMaxStackSize(); + inventory->setCarried(copy); + } else if (buttonNum == 1) // Right click + { + std::shared_ptr copy = slotItem->copy(); + copy->count = 1; + inventory->setCarried(copy); + } + } else if (carried != NULL) { + // Clicking on empty creative slot with item - clear the carried + // item + inventory->setCarried(std::shared_ptr()); + } + + return std::shared_ptr(); + } + + // For hotbar slots (45-53), use normal container behavior + return AbstractContainerMenu::clicked(slotIndex, buttonNum, clickType, + player); } -void CreativeInventoryScreen::ContainerCreative::scrollTo(float pos) -{ - int i = (itemList.size() + COLUMNS - 1) / COLUMNS - ROWS; - int j = (int)((double)(pos * (float)i) + 0.5); - - if (j < 0) - { - j = 0; - } - - for (int k = 0; k < ROWS; ++k) - { - for (int l = 0; l < COLUMNS; ++l) - { - int i1 = l + (k + j) * COLUMNS; - - if (i1 >= 0 && i1 < (int)itemList.size()) - { - basicInventory->setItem(l + k * COLUMNS, itemList[i1]); - } - else - { - basicInventory->setItem(l + k * COLUMNS, std::shared_ptr()); - } - } - } +void CreativeInventoryScreen::ContainerCreative::scrollTo(float pos) { + int i = (itemList.size() + COLUMNS - 1) / COLUMNS - ROWS; + int j = (int)((double)(pos * (float)i) + 0.5); + + if (j < 0) { + j = 0; + } + + for (int k = 0; k < ROWS; ++k) { + for (int l = 0; l < COLUMNS; ++l) { + int i1 = l + (k + j) * COLUMNS; + + if (i1 >= 0 && i1 < (int)itemList.size()) { + basicInventory->setItem(l + k * COLUMNS, itemList[i1]); + } else { + basicInventory->setItem(l + k * COLUMNS, + std::shared_ptr()); + } + } + } } -bool CreativeInventoryScreen::ContainerCreative::canScroll() -{ - return itemList.size() > ITEMS_PER_PAGE; +bool CreativeInventoryScreen::ContainerCreative::canScroll() { + return itemList.size() > ITEMS_PER_PAGE; } -CreativeInventoryScreen::CreativeInventoryScreen(std::shared_ptr player) - : AbstractContainerScreen(new ContainerCreative(player)) -{ - this->player = player; - player->containerMenu = menu; - - currentScroll = 0.0f; - isScrolling = false; - wasClicking = false; - isLeftMouseDown = false; - - imageHeight = 136; - imageWidth = 195; +CreativeInventoryScreen::CreativeInventoryScreen(std::shared_ptr player) + : AbstractContainerScreen(new ContainerCreative(player)) { + this->player = player; + player->containerMenu = menu; + + currentScroll = 0.0f; + isScrolling = false; + wasClicking = false; + isLeftMouseDown = false; + + imageHeight = 136; + imageWidth = 195; } -void CreativeInventoryScreen::removed() -{ - AbstractContainerScreen::removed(); +void CreativeInventoryScreen::removed() { AbstractContainerScreen::removed(); } + +void CreativeInventoryScreen::init() { + buttons.clear(); + + int i = selectedTabIndex; + selectedTabIndex = -1; + setCurrentCreativeTab(i); } -void CreativeInventoryScreen::init() -{ - buttons.clear(); - - int i = selectedTabIndex; - selectedTabIndex = -1; - setCurrentCreativeTab(i); -} - -void CreativeInventoryScreen::updateEvents() -{ +void CreativeInventoryScreen::updateEvents() { #ifdef ENABLE_JAVA_GUIS - // Handle mouse wheel scrolling. - // We use ButtonDown with the scroll actions rather than GetScrollDelta() because - // both share s_scrollTicksForButtonPressed; whichever is called first in a tick - // zeroes it, so GetScrollDelta() would return 0 if hotbar scroll ran first. - // ButtonDown/ScrollSnap() snapshots once per tick so all callers see the same value. - if (needsScrollBars()) - { - ContainerCreative* container = (ContainerCreative*)menu; - int totalRows = ((int)container->itemList.size() + COLUMNS - 1) / COLUMNS; - int scrollableRows = totalRows - ROWS; - if (scrollableRows > 0) - { - float step = 1.0f / (float)scrollableRows; - if (InputManager.ButtonDown(0, MINECRAFT_ACTION_LEFT_SCROLL)) - { - currentScroll -= step; - currentScroll = std::max(0.0f, std::min(1.0f, currentScroll)); - container->scrollTo(currentScroll); - } - else if (InputManager.ButtonDown(0, MINECRAFT_ACTION_RIGHT_SCROLL)) - { - currentScroll += step; - currentScroll = std::max(0.0f, std::min(1.0f, currentScroll)); - container->scrollTo(currentScroll); - } - } - } + // Handle mouse wheel scrolling. + // We use ButtonDown with the scroll actions rather than GetScrollDelta() + // because both share s_scrollTicksForButtonPressed; whichever is called + // first in a tick zeroes it, so GetScrollDelta() would return 0 if hotbar + // scroll ran first. ButtonDown/ScrollSnap() snapshots once per tick so all + // callers see the same value. + if (needsScrollBars()) { + ContainerCreative* container = (ContainerCreative*)menu; + int totalRows = + ((int)container->itemList.size() + COLUMNS - 1) / COLUMNS; + int scrollableRows = totalRows - ROWS; + if (scrollableRows > 0) { + float step = 1.0f / (float)scrollableRows; + if (InputManager.ButtonDown(0, MINECRAFT_ACTION_LEFT_SCROLL)) { + currentScroll -= step; + currentScroll = std::max(0.0f, std::min(1.0f, currentScroll)); + container->scrollTo(currentScroll); + } else if (InputManager.ButtonDown(0, + MINECRAFT_ACTION_RIGHT_SCROLL)) { + currentScroll += step; + currentScroll = std::max(0.0f, std::min(1.0f, currentScroll)); + container->scrollTo(currentScroll); + } + } + } #endif - Screen::updateEvents(); + Screen::updateEvents(); } -void CreativeInventoryScreen::containerTick() -{ +void CreativeInventoryScreen::containerTick() {} + +void CreativeInventoryScreen::tick() { Screen::tick(); } + +void CreativeInventoryScreen::keyPressed(wchar_t eventCharacter, int eventKey) { + AbstractContainerScreen::keyPressed(eventCharacter, eventKey); } -void CreativeInventoryScreen::tick() -{ - Screen::tick(); +void CreativeInventoryScreen::mouseClicked(int x, int y, int buttonNum) { + if (buttonNum == 0) isLeftMouseDown = true; + + Screen::mouseClicked(x, y, buttonNum); + + if (buttonNum == 0 || buttonNum == 1) { + int mouseX = x - (width - imageWidth) / 2; + int mouseY = y - (height - imageHeight) / 2; + + // Check for tab clicks first; let mouseReleased handle the actual tab + // switch + for (int tab = 0; + tab < IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT; tab++) { + if (isMouseOverTab(tab, mouseX, mouseY)) { + return; + } + } + + // Determine which slot (if any) was clicked + Slot* slot = findSlot(x, y); + + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + bool clickedOutside = + (x < xo || y < yo || x >= xo + imageWidth || y >= yo + imageHeight); + + int slotId = -1; + if (slot != NULL) slotId = slot->index; + if (clickedOutside) + slotId = AbstractContainerMenu::SLOT_CLICKED_OUTSIDE; + + if (slotId == -1) return; + + bool quickKey = slotId != AbstractContainerMenu::SLOT_CLICKED_OUTSIDE && + (Keyboard::isKeyDown(Keyboard::KEY_LSHIFT) || + Keyboard::isKeyDown(Keyboard::KEY_RSHIFT)); + int clickType = quickKey ? AbstractContainerMenu::CLICK_QUICK_MOVE + : AbstractContainerMenu::CLICK_PICKUP; + + // 4jcraft: bypass AbstractContainerScreen::mouseClicked / + // handleInventoryMouseClick here intentionally. The normal path sends a + // ContainerClickPacket to the server, where player->containerMenu is + // still the InventoryMenu (45 slots). Creative slot indices 0-44 are + // valid in ContainerCreative but not in InventoryMenu, and hotbar + // indices 45-53 exceed InventoryMenu's slot count entirely, causing an + // out-of-range crash in AbstractContainerMenu::clicked on the server + // side. Instead we apply the click locally and sync hotbar changes via + // SetCreativeModeSlotPacket. + menu->clicked(slotId, buttonNum, clickType, minecraft->player); + + // 4jcraft: sync hotbar slot changes to the server using + // SetCreativeModeSlotPacket. The packet handler + // (PlayerConnection::handleSetCreativeModeSlot) validates slots against + // InventoryMenu coordinates where the hotbar starts at + // USE_ROW_SLOT_START (36), so we must offset the local hotbar index + // (0-8) accordingly. + if (slotId >= ITEMS_PER_PAGE && slotId < ITEMS_PER_PAGE + 9) { + int hotbarSlot = slotId - ITEMS_PER_PAGE; + std::shared_ptr hotbarItem = + minecraft->player->inventory->getItem(hotbarSlot); + minecraft->gameMode->handleCreativeModeItemAdd( + hotbarItem, hotbarSlot + InventoryMenu::USE_ROW_SLOT_START); + } + } } -void CreativeInventoryScreen::keyPressed(wchar_t eventCharacter, int eventKey) -{ - AbstractContainerScreen::keyPressed(eventCharacter, eventKey); +void CreativeInventoryScreen::mouseReleased(int x, int y, int buttonNum) { + if (buttonNum == 0) isLeftMouseDown = false; + + if (buttonNum == 0) { + int mouseX = x - (width - imageWidth) / 2; + int mouseY = y - (height - imageHeight) / 2; + + // Check for tab clicks + for (int tab = 0; + tab < IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT; tab++) { + if (isMouseOverTab(tab, mouseX, mouseY)) { + setCurrentCreativeTab(tab); + return; + } + } + } + + AbstractContainerScreen::mouseReleased(x, y, buttonNum); } -void CreativeInventoryScreen::mouseClicked(int x, int y, int buttonNum) -{ - if (buttonNum == 0) isLeftMouseDown = true; +void CreativeInventoryScreen::render(int xm, int ym, float a) { + // Java: drawDefaultBackground() + renderBackground(); - Screen::mouseClicked(x, y, buttonNum); + // Handle scrollbar dragging + bool mouseDown = isLeftMouseDown; + int left = (width - imageWidth) / 2; + int top = (height - imageHeight) / 2; + int x1 = left + 175; + int y1 = top + 18; + int x2 = x1 + 14; + int y2 = y1 + 112; - if (buttonNum == 0 || buttonNum == 1) - { - int i = x - (width - imageWidth) / 2; - int j = y - (height - imageHeight) / 2; + if (!wasClicking && mouseDown && xm >= x1 && ym >= y1 && xm < x2 && + ym < y2) { + isScrolling = needsScrollBars(); + } - // Check for tab clicks first; let mouseReleased handle the actual tab switch - for (int tab = 0; tab < IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT; ++tab) - { - if (isMouseOverTab(tab, i, j)) - { - return; - } - } + if (!mouseDown) { + isScrolling = false; + } - // Determine which slot (if any) was clicked - Slot *slot = findSlot(x, y); + wasClicking = mouseDown; - int xo = (width - imageWidth) / 2; - int yo = (height - imageHeight) / 2; - bool clickedOutside = (x < xo || y < yo || x >= xo + imageWidth || y >= yo + imageHeight); + if (isScrolling) { + currentScroll = ((float)(ym - y1) - 7.5f) / ((float)(y2 - y1) - 15.0f); + currentScroll = std::max(0.0f, std::min(1.0f, currentScroll)); + ((ContainerCreative*)menu)->scrollTo(currentScroll); + } - int slotId = -1; - if (slot != NULL) slotId = slot->index; - if (clickedOutside) slotId = AbstractContainerMenu::SLOT_CLICKED_OUTSIDE; + AbstractContainerScreen::render(xm, ym, a); - if (slotId == -1) return; - - bool quickKey = slotId != AbstractContainerMenu::SLOT_CLICKED_OUTSIDE && - (Keyboard::isKeyDown(Keyboard::KEY_LSHIFT) || Keyboard::isKeyDown(Keyboard::KEY_RSHIFT)); - int clickType = quickKey ? AbstractContainerMenu::CLICK_QUICK_MOVE : AbstractContainerMenu::CLICK_PICKUP; - - // 4jcraft: bypass AbstractContainerScreen::mouseClicked / handleInventoryMouseClick - // here intentionally. The normal path sends a ContainerClickPacket to the server, - // where player->containerMenu is still the InventoryMenu (45 slots). Creative slot - // indices 0-44 are valid in ContainerCreative but not in InventoryMenu, and hotbar - // indices 45-53 exceed InventoryMenu's slot count entirely, causing an out-of-range - // crash in AbstractContainerMenu::clicked on the server side. - // Instead we apply the click locally and sync hotbar changes via SetCreativeModeSlotPacket. - menu->clicked(slotId, buttonNum, clickType, minecraft->player); - - // 4jcraft: sync hotbar slot changes to the server using SetCreativeModeSlotPacket. - // The packet handler (PlayerConnection::handleSetCreativeModeSlot) validates slots - // against InventoryMenu coordinates where the hotbar starts at USE_ROW_SLOT_START (36), - // so we must offset the local hotbar index (0-8) accordingly. - if (slotId >= ITEMS_PER_PAGE && slotId < ITEMS_PER_PAGE + 9) - { - int hotbarSlot = slotId - ITEMS_PER_PAGE; - std::shared_ptr hotbarItem = minecraft->player->inventory->getItem(hotbarSlot); - minecraft->gameMode->handleCreativeModeItemAdd(hotbarItem, hotbarSlot + InventoryMenu::USE_ROW_SLOT_START); - } - } + for (int i = 0; i < IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT; + i++) { + if (renderIconTooltip(i, xm, ym)) { + break; + } + } } -void CreativeInventoryScreen::mouseReleased(int x, int y, int buttonNum) -{ - if (buttonNum == 0) isLeftMouseDown = false; - - if (buttonNum == 0) - { - int i = x - (width - imageWidth) / 2; - int j = y - (height - imageHeight) / 2; - - // Check for tab clicks - for (int tab = 0; tab < IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT; ++tab) - { - if (isMouseOverTab(tab, i, j)) - { - setCurrentCreativeTab(tab); - return; - } - } - } - - AbstractContainerScreen::mouseReleased(x, y, buttonNum); -} - -void CreativeInventoryScreen::render(int xm, int ym, float a) -{ - // Java: drawDefaultBackground() - renderBackground(); - - // Handle scrollbar dragging - bool mouseDown = isLeftMouseDown; - int i = (width - imageWidth) / 2; - int j = (height - imageHeight) / 2; - int k = i + 175; - int l = j + 18; - int i1 = k + 14; - int j1 = l + 112; - - if (!wasClicking && mouseDown && xm >= k && ym >= l && xm < i1 && ym < j1) - { - isScrolling = needsScrollBars(); - } - - if (!mouseDown) - { - isScrolling = false; - } - - wasClicking = mouseDown; - - if (isScrolling) - { - currentScroll = ((float)(ym - l) - 7.5f) / ((float)(j1 - l) - 15.0f); - currentScroll = std::max(0.0f, std::min(1.0f, currentScroll)); - ((ContainerCreative*)menu)->scrollTo(currentScroll); - } - - AbstractContainerScreen::render(xm, ym, a); -} - -void CreativeInventoryScreen::renderLabels() -{ +void CreativeInventoryScreen::renderLabels() { #ifdef ENABLE_JAVA_GUIS - if (IUIScene_CreativeMenu::specs && selectedTabIndex >= 0 && selectedTabIndex < IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT) - { - IUIScene_CreativeMenu::TabSpec* spec = IUIScene_CreativeMenu::specs[selectedTabIndex]; - if (spec) - { - std::wstring tabName = app.GetString(spec->m_descriptionId); - font->draw(tabName, 8, 6, 0x404040); - } - } + if (IUIScene_CreativeMenu::specs && selectedTabIndex >= 0 && + selectedTabIndex < IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT) { + IUIScene_CreativeMenu::TabSpec* spec = + IUIScene_CreativeMenu::specs[selectedTabIndex]; + if (spec) { + std::wstring tabName = app.GetString(spec->m_descriptionId); + font->draw(tabName, 8, 6, 0x404040); + } + } #endif } -void CreativeInventoryScreen::renderBg(float a) -{ - int x = (width - imageWidth) / 2; - int y = (height - imageHeight) / 2; +void CreativeInventoryScreen::renderBg(float a) { + int x = (width - imageWidth) / 2; + int y = (height - imageHeight) / 2; #ifdef ENABLE_JAVA_GUIS - // Render all non-selected tabs first - for (int tab = 0; tab < IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT; ++tab) - { - if (tab != selectedTabIndex) - { - drawTab(tab); - } - } - - // Load and render main creative inventory background - int tex = minecraft->textures->loadTexture(TN_GUI_CREATIVE_TAB_ITEMS); - glColor4f(1, 1, 1, 1); - minecraft->textures->bind(tex); - blit(x, y, 0, 0, imageWidth, imageHeight); - - // Render scrollbar - tex = minecraft->textures->loadTexture(TN_GUI_CREATIVE_TABS); - minecraft->textures->bind(tex); - - int scrollX = x + 175; - int scrollY = y + 18; - int scrollHeight = 112; - - if (needsScrollBars()) - { - int scrollPos = (int)((float)(scrollHeight - 17) * currentScroll); - blit(scrollX, scrollY + scrollPos, 232, 0, 12, 15); - } - else - { - blit(scrollX, scrollY + (scrollHeight - 17) / 2, 244, 0, 12, 15); - } - - // Render selected tab last (on top) - drawTab(selectedTabIndex); + static int itemsTex = + minecraft->textures->loadTexture(TN_GUI_CREATIVE_TAB_ITEMS); + static int searchTex = + minecraft->textures->loadTexture(TN_GUI_CREATIVE_TAB_ITEM_SEARCH); + static int scrollTex = + minecraft->textures->loadTexture(TN_GUI_CREATIVE_TABS); + // Render all non-selected tabs first + for (int tab = 0; tab < IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT; + tab++) { + if (tab != selectedTabIndex) { + renderTab(tab); + } + } + + // Load and render main creative inventory background + glColor4f(1, 1, 1, 1); + minecraft->textures->bind((selectedTabIndex == 5) ? searchTex : itemsTex); + blit(x, y, 0, 0, imageWidth, imageHeight); + + // Render scrollbar + minecraft->textures->bind(scrollTex); + + int scrollX = x + 175; + int scrollY = y + 18; + int scrollHeight = 112; + + if (needsScrollBars()) { + int scrollPos = (int)((float)(scrollHeight - 17) * currentScroll); + blit(scrollX, scrollY + scrollPos, 232, 0, 12, 15); + } else { + blit(scrollX, scrollY, 244, 0, 12, 15); + } + + // Render selected tab last (on top) + renderTab(selectedTabIndex); #endif } -void CreativeInventoryScreen::setCurrentCreativeTab(int tab) -{ - if (tab < 0 || tab >= IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT) - return; - - int oldTab = selectedTabIndex; - selectedTabIndex = tab; - - ContainerCreative* container = (ContainerCreative*)menu; - container->itemList.clear(); - - // Populate itemList from the tab's category groups - if (IUIScene_CreativeMenu::specs && IUIScene_CreativeMenu::specs[tab]) - { - IUIScene_CreativeMenu::TabSpec* spec = IUIScene_CreativeMenu::specs[tab]; - - // Add items from static groups - for (int i = 0; i < spec->m_staticGroupsCount; ++i) - { - int groupIdx = spec->m_staticGroupsA[i]; - if (groupIdx >= 0 && groupIdx < IUIScene_CreativeMenu::eCreativeInventoryGroupsCount) - { - auto& group = IUIScene_CreativeMenu::categoryGroups[groupIdx]; - for (auto& item : group) - { - container->itemList.push_back(item); - } - } - } - } - - currentScroll = 0.0f; - container->scrollTo(0.0f); +bool CreativeInventoryScreen::isMouseOverInternal(int tab, int mouseX, + int mouseY, int xo, int yo, + int w, int h) { + int tabColumn = tab % 6; + int x = (tabColumn * 28) + xo; + int y = yo; + + if (tabColumn == 5) { + x = imageWidth - 28 + 2; + } else if (tabColumn > 0) { + x += tabColumn; + } + + if (tab < 6) { + y -= 32; + } else { + y = imageHeight; + } + + return ((mouseX >= x && mouseX <= x + w) && + (mouseY >= y && mouseY <= y + h)); } -void CreativeInventoryScreen::selectTab(int tab) -{ - setCurrentCreativeTab(tab); +void CreativeInventoryScreen::setCurrentCreativeTab(int tab) { + if (tab < 0 || tab >= IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT) + return; + + int oldTab = selectedTabIndex; + selectedTabIndex = tab; + + ContainerCreative* container = (ContainerCreative*)menu; + container->itemList.clear(); + + // Populate itemList from the tab's category groups + if (IUIScene_CreativeMenu::specs && IUIScene_CreativeMenu::specs[tab]) { + IUIScene_CreativeMenu::TabSpec* spec = + IUIScene_CreativeMenu::specs[tab]; + + // Add items from static groups + for (int i = 0; i < spec->m_staticGroupsCount; ++i) { + int groupIdx = spec->m_staticGroupsA[i]; + if (groupIdx >= 0 && + groupIdx < + IUIScene_CreativeMenu::eCreativeInventoryGroupsCount) { + auto& group = IUIScene_CreativeMenu::categoryGroups[groupIdx]; + for (auto& item : group) { + container->itemList.push_back(item); + } + } + } + } + + currentScroll = 0.0f; + container->scrollTo(0.0f); } -bool CreativeInventoryScreen::needsScrollBars() -{ - return ((ContainerCreative*)menu)->canScroll(); +void CreativeInventoryScreen::selectTab(int tab) { setCurrentCreativeTab(tab); } + +bool CreativeInventoryScreen::needsScrollBars() { + return ((ContainerCreative*)menu)->canScroll(); } -bool CreativeInventoryScreen::isMouseOverTab(int tab, int mouseX, int mouseY) -{ - int i = tab; - int j = 28 * i; - int k = 0; - - if (i > 0) - { - j += i; - } - - // Tabs are in the top row - k = k - 32; - - return mouseX >= j && mouseX <= j + 28 && mouseY >= k && mouseY <= k + 32; +bool CreativeInventoryScreen::isMouseOverTab(int tab, int mouseX, int mouseY) { + return isMouseOverInternal(tab, mouseX, mouseY, 0, 0, 28, 32); } -void CreativeInventoryScreen::drawTab(int tab) -{ +bool CreativeInventoryScreen::isMouseOverIcon(int tab, int mouseX, int mouseY) { + return isMouseOverInternal(tab, mouseX, mouseY, 7, 12, 14, 16); +} + +void CreativeInventoryScreen::renderTab(int tab) { #ifdef ENABLE_JAVA_GUIS - bool isSelected = (tab == selectedTabIndex); - int i = tab; - int j = i * 28; - int k = 0; - int l = (width - imageWidth) / 2 + 28 * i; - int i1 = (height - imageHeight) / 2; - int j1 = 32; - - if (isSelected) - { - k += 32; - } - - if (i > 0) - { - l += i; - } - - // Tabs are in the top row - i1 = i1 - 28; - - // Render tab background - int tex = minecraft->textures->loadTexture(TN_GUI_CREATIVE_TABS); - minecraft->textures->bind(tex); - glColor4f(1, 1, 1, 1); - blit(l, i1, j, k, 28, 32); - - // TODO: Render tab icon (would need item icons) + bool isSelected = (selectedTabIndex == tab); + bool tabFirstRow = (tab < 6); + int left = (width - imageWidth) / 2; + int top = (height - imageHeight) / 2; + int tabColumn = tab % 6; + int sy = 0; + int x = left + 28 * tabColumn; + int y = top; + static int tex = minecraft->textures->loadTexture(TN_GUI_CREATIVE_TABS); + + if (isSelected) { + sy += 32; + } + + if (tabColumn == 5) { + x = left + imageWidth - 28; + } else if (tabColumn > 0) { + x += tabColumn; + } + + // Tabs are in the top row + if (tabFirstRow) { + y -= 28; + } else { + sy += 64; + y += imageHeight - 4; + } + + // Render tab background + glDisable(GL_LIGHTING); + minecraft->textures->bind(tex); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + blit(x, y, tabColumn * 28, sy, 28, 32); + + // Render tab icon + x += 6; + y += 8 + (tabFirstRow ? 1 : -1); + glEnable(GL_LIGHTING); + glEnable(GL_RESCALE_NORMAL); + Lighting::turnOnGui(); + itemRenderer->renderGuiItem(font, minecraft->textures, tabIcons[tab], x, y); + itemRenderer->renderGuiItemDecorations(font, minecraft->textures, + tabIcons[tab], x, y); + glDisable(GL_LIGHTING); #endif } + +bool CreativeInventoryScreen::renderIconTooltip(int tab, int mouseX, + int mouseY) { + int x = mouseX - (width - imageWidth) / 2; + int y = mouseY - (height - imageHeight) / 2; + + if (isMouseOverIcon(tab, x, y)) { + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + renderTooltip( + app.GetString(IUIScene_CreativeMenu::specs[tab]->m_descriptionId), + mouseX, mouseY); + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + return true; + } + return false; +} \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/CreativeInventoryScreen.h b/Minecraft.Client/UI/Screens/CreativeInventoryScreen.h index 4ce1659f4..e8fd36877 100644 --- a/Minecraft.Client/UI/Screens/CreativeInventoryScreen.h +++ b/Minecraft.Client/UI/Screens/CreativeInventoryScreen.h @@ -9,63 +9,81 @@ class SimpleContainer; class Inventory; class Slot; -class CreativeInventoryScreen : public AbstractContainerScreen -{ +class CreativeInventoryScreen : public AbstractContainerScreen { private: - static constexpr int ROWS = 5; - static constexpr int COLUMNS = 9; - static constexpr int ITEMS_PER_PAGE = ROWS * COLUMNS; // 45 items (9x5 grid) - - // Currently selected creative tab index - static int selectedTabIndex; - - // Temporary inventory for creative mode items - static std::shared_ptr basicInventory; - - // Amount scrolled in Creative mode inventory (0 = top, 1 = bottom) - float currentScroll; - - bool isScrolling; - - // True if the left mouse button is currently being held - bool isLeftMouseDown; + static constexpr int ROWS = 5; + static constexpr int COLUMNS = 9; + static constexpr int ITEMS_PER_PAGE = + ROWS * COLUMNS; // 45 items (9x5 grid) - // True if the left mouse button was held down last time render was called - bool wasClicking; + // Currently selected creative tab index + static int selectedTabIndex; + + // Array of item ids for the tab icons + static const int + tabIconIds[IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT]; + + // Temporary inventory for creative mode items + static std::shared_ptr basicInventory; + + // Item renderer for the tab icons + static ItemRenderer* itemRenderer; + + // Array of tab icons + static std::shared_ptr + tabIcons[IUIScene_CreativeMenu::eCreativeInventoryTab_COUNT]; + + // Amount scrolled in Creative mode inventory (0 = top, 1 = bottom) + float currentScroll; + + bool isScrolling; + + // True if the left mouse button is currently being held + bool isLeftMouseDown; + + // True if the left mouse button was held down last time render was called + bool wasClicking; + + std::shared_ptr player; - std::shared_ptr player; - public: - class ContainerCreative : public AbstractContainerMenu - { - public: - std::vector> itemList; - - ContainerCreative(std::shared_ptr player); - virtual bool stillValid(std::shared_ptr player); - virtual std::shared_ptr clicked(int slotIndex, int buttonNum, int clickType, std::shared_ptr player); - void scrollTo(float pos); - bool canScroll(); - }; - + class ContainerCreative : public AbstractContainerMenu { + public: + std::vector> itemList; + + ContainerCreative(std::shared_ptr player); + virtual bool stillValid(std::shared_ptr player) override; + virtual std::shared_ptr clicked( + int slotIndex, int buttonNum, int clickType, + std::shared_ptr player, bool looped = false) override; + void scrollTo(float pos); + bool canScroll(); + }; + public: - CreativeInventoryScreen(std::shared_ptr player); - virtual void removed(); - virtual void init(); - virtual void containerTick(); - virtual void tick(); - virtual void updateEvents(); - virtual void keyPressed(wchar_t eventCharacter, int eventKey); - virtual void mouseClicked(int x, int y, int buttonNum); - virtual void mouseReleased(int x, int y, int buttonNum); - virtual void render(int xm, int ym, float a); + CreativeInventoryScreen(std::shared_ptr player); + virtual void removed() override; + virtual void init() override; + virtual void containerTick(); + virtual void tick() override; + virtual void updateEvents() override; + virtual void keyPressed(wchar_t eventCharacter, int eventKey) override; + virtual void mouseClicked(int x, int y, int buttonNum) override; + virtual void mouseReleased(int x, int y, int buttonNum) override; + virtual void render(int xm, int ym, float a) override; + protected: - virtual void renderLabels(); - virtual void renderBg(float a); + virtual void renderLabels() override; + virtual void renderBg(float a) override; + virtual bool isMouseOverInternal(int tab, int mouseX, int mouseY, int xo, + int yo, int w, int h); + private: - void setCurrentCreativeTab(int tab); - void selectTab(int tab); - bool needsScrollBars(); - bool isMouseOverTab(int tab, int mouseX, int mouseY); - void drawTab(int tab); -}; + void setCurrentCreativeTab(int tab); + void selectTab(int tab); + bool needsScrollBars(); + bool isMouseOverTab(int tab, int mouseX, int mouseY); + bool isMouseOverIcon(int tab, int mouseX, int mouseY); + void renderTab(int tab); + bool renderIconTooltip(int tab, int mouseX, int mouseY); +}; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/DeathScreen.h b/Minecraft.Client/UI/Screens/DeathScreen.h index 976832afb..382f0e5b6 100644 --- a/Minecraft.Client/UI/Screens/DeathScreen.h +++ b/Minecraft.Client/UI/Screens/DeathScreen.h @@ -3,13 +3,13 @@ class DeathScreen : public Screen { public: - virtual void init(); + virtual void init() override; protected: virtual void keyPressed(char eventCharacter, int eventKey); - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void render(int xm, int ym, float a); - virtual bool isPauseScreen(); + virtual void render(int xm, int ym, float a) override; + virtual bool isPauseScreen() override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/DisconnectedScreen.h b/Minecraft.Client/UI/Screens/DisconnectedScreen.h index 4e49685d7..1dcc1151d 100644 --- a/Minecraft.Client/UI/Screens/DisconnectedScreen.h +++ b/Minecraft.Client/UI/Screens/DisconnectedScreen.h @@ -8,7 +8,7 @@ private: public: DisconnectedScreen(const std::wstring& title, const std::wstring reason, void* reasonObjects, ...); - virtual void tick(); + virtual void tick() override; protected: using Screen::keyPressed; @@ -16,11 +16,11 @@ protected: virtual void keyPressed(char eventCharacter, int eventKey); public: - virtual void init(); + virtual void init() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; diff --git a/Minecraft.Client/UI/Screens/EnchantmentScreen.cpp b/Minecraft.Client/UI/Screens/EnchantmentScreen.cpp new file mode 100644 index 000000000..24d239382 --- /dev/null +++ b/Minecraft.Client/UI/Screens/EnchantmentScreen.cpp @@ -0,0 +1,322 @@ +#include "../../Platform/stdafx.h" +#include "EnchantmentScreen.h" +#include +#include +#include +#include +#include "../../Player/MultiPlayerLocalPlayer.h" +#include "../../Rendering/Lighting.h" +#include "../../Textures/Textures.h" +#include "../../../Minecraft.World/Headers/net.minecraft.locale.h" +#include "../../../Minecraft.World/Containers/EnchantmentMenu.h" +#include "../../../Minecraft.World/Containers/Slot.h" +#include "../../Rendering/Models/BookModel.h" +#include "../../../Minecraft.Client/Minecraft.h" + +// 4jcraft: referenced from MCP 8.11 (JE 1.6.4) and the existing +// container classes (and iggy too) +#ifdef ENABLE_JAVA_GUIS +ResourceLocation GUI_ENCHANT_LOCATION = ResourceLocation(TN_GUI_ENCHANT); +ResourceLocation ITEM_BOOK_LOCATION = ResourceLocation(TN_ITEM_BOOK); +#endif + +EnchantmentScreen::EnchantmentScreen(std::shared_ptr inventory, + Level* level, int x, int y, int z) + : AbstractContainerScreen(new EnchantmentMenu(inventory, level, x, y, z)) { + xMouse = yMouse = 0.0f; + + this->inventory = inventory; + this->enchantMenu = static_cast(menu); + bookTick = 0; + flip = oFlip = flipT = flipA = 0.0f; + open = oOpen = 0.0f; + last = nullptr; +} + +EnchantmentScreen::~EnchantmentScreen() = default; + +void EnchantmentScreen::init() { AbstractContainerScreen::init(); } + +void EnchantmentScreen::removed() { AbstractContainerScreen::removed(); } + +void EnchantmentScreen::renderLabels() { + font->draw(Language::getInstance()->getElement(L"container.enchant"), 12, 5, + 0x404040); + font->draw(inventory->getName(), 8, imageHeight - 96 + 2, 0x404040); + + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + + // 4jcraft: our own refactor, text rendering has been moved to the + // foreground here from renderBg() (which is where it was in the JE 1.6.4 + // code) + bool needsUpdate = false; + for (int i = 0; i < 3; ++i) { + if (enchantMenu->costs[i] != lastCosts[i]) { + needsUpdate = true; + lastCosts[i] = enchantMenu->costs[i]; + } + } + if (needsUpdate) { + for (int i = 0; i < 3; ++i) { + if (enchantMenu->costs[i] > 0) { + enchantNames[i] = EnchantmentNames::instance.getRandomName(); + } else { + enchantNames[i] = L""; + } + } + } + + for (int i = 0; i < 3; ++i) { + int cost = enchantMenu->costs[i]; + + int buttonX = 60; + int buttonY = 14 + 19 * i; + + bool isHovering = + (xMouse >= xo + buttonX && xMouse < xo + buttonX + 108 && + yMouse >= yo + buttonY && yMouse < yo + buttonY + 19); + + bool hasEnoughLevels = (minecraft->player->experienceLevel >= cost) || + minecraft->player->abilities.instabuild; + + if (cost > 0) { + std::wstring enchantName = enchantNames[i]; + + Font* weirdEnchantTableFont = minecraft->altFont; + if (weirdEnchantTableFont) { + int nameColor; + + if (!hasEnoughLevels) { + nameColor = 0x342F25; + } else if (isHovering) { + nameColor = 0xFFFF80; + } else { + nameColor = 0x685E4A; + } + + int textX = xo + buttonX + 2; + int textY = yo + buttonY + 2; + + weirdEnchantTableFont->drawWordWrap( + enchantName, buttonX + 2, buttonY + 2, 104, nameColor, 64); + } + + std::wstring costStr = std::to_wstring(cost); + int costX = buttonX + 108 - font->width(costStr) - 2; + int costY = buttonY + 8; + + int costColor; + if (!hasEnoughLevels) { + costColor = 0x407F10; + } else { + costColor = 0x80FF20; + } + + font->drawShadow(costStr, costX, costY, costColor); + } + } +} + +void EnchantmentScreen::render(int xm, int ym, float a) { + AbstractContainerScreen::render(xm, ym, a); + this->xMouse = (float)xm; + this->yMouse = (float)ym; +} + +void EnchantmentScreen::renderBg(float a) { +#ifdef ENABLE_JAVA_GUIS + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + Minecraft::GetInstance()->textures->bindTexture(&GUI_ENCHANT_LOCATION); + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + blit(xo, yo, 0, 0, imageWidth, imageHeight); + + glPushMatrix(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + ScreenSizeCalculator screenSize(minecraft->options, minecraft->width, + minecraft->height); + int scaledWidth = screenSize.getWidth(); + int scaledHeight = screenSize.getHeight(); + int scaleFactor = screenSize.scale; + + glViewport(((scaledWidth - 320) / 2) * scaleFactor, + ((scaledHeight - 240) / 2) * scaleFactor, 320 * scaleFactor, + 240 * scaleFactor); + + glTranslatef(-0.34f, 0.23f, 0.0f); + gluPerspective(90.0f, 1.3333334f, 9.0f, 80.0f); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + Lighting::turnOn(); + + glTranslatef(0.0f, 3.3f, -16.0f); + glScalef(5.0f, 5.0f, 5.0f); + glRotatef(180.0f, 0.0f, 0.0f, 1.0f); + + Minecraft::GetInstance()->textures->bindTexture(&ITEM_BOOK_LOCATION); + glRotatef(20.0f, 1.0f, 0.0f, 0.0f); + + // 4jcraft: brought over from UIControl_EnchantmentBook + float o = oOpen + (open - oOpen) * a; + glTranslatef((1 - o) * 0.2f, (1 - o) * 0.1f, (1 - o) * 0.25f); + glRotatef(-(1 - o) * 90 - 90, 0, 1, 0); + glRotatef(180, 1, 0, 0); + + float ff1 = oFlip + (flip - oFlip) * a + 0.25f; + float ff2 = oFlip + (flip - oFlip) * a + 0.75f; + ff1 = (ff1 - floor(ff1)) * 1.6f - 0.3f; + ff2 = (ff2 - floor(ff2)) * 1.6f - 0.3f; + + if (ff1 < 0.0f) ff1 = 0.0f; + if (ff2 < 0.0f) ff2 = 0.0f; + if (ff1 > 1.0f) ff1 = 1.0f; + if (ff2 > 1.0f) ff2 = 1.0f; + + glEnable(GL_RESCALE_NORMAL); + + static BookModel bookModel; + bookModel.render(nullptr, 0.0f, ff1, ff2, o, 0.0f, 0.0625f, true); + + glDisable(GL_RESCALE_NORMAL); + Lighting::turnOff(); + + glMatrixMode(GL_PROJECTION); + glViewport(0, 0, minecraft->width, minecraft->height); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + Minecraft::GetInstance()->textures->bindTexture(&GUI_ENCHANT_LOCATION); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + for (int i = 0; i < 3; ++i) { + int cost = enchantMenu->costs[i]; + int buttonX = 60; + int buttonY = 14 + 19 * i; + + bool isHovering = + (xMouse >= xo + buttonX && xMouse < xo + buttonX + 108 && + yMouse >= yo + buttonY && yMouse < yo + buttonY + 19); + + if (cost == 0) { + blit(xo + buttonX, yo + buttonY, 0, 185, 108, 19); + } else { + bool hasEnoughLevels = + (minecraft->player->experienceLevel >= cost) || + minecraft->player->abilities.instabuild; + + int texV; + if (!hasEnoughLevels) { + texV = 185; + } else if (isHovering) { + texV = 204; + } else { + texV = 166; + } + + blit(xo + buttonX, yo + buttonY, 0, texV, 108, 19); + } + } +#endif +} + +void EnchantmentScreen::mouseClicked(int x, int y, int buttonNum) { + AbstractContainerScreen::mouseClicked(x, y, buttonNum); + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + + for (int i = 0; i < 3; ++i) { + int buttonX = xo + 60; + int buttonY = yo + 14 + 19 * i; + + if (x >= buttonX && x < buttonX + 108 && y >= buttonY && + y < buttonY + 19) { + if (enchantMenu->clickMenuButton(minecraft->player, i)) { + minecraft->gameMode->handleInventoryButtonClick( + enchantMenu->containerId, i); + } + break; + } + } +} + +void EnchantmentScreen::tick() { + AbstractContainerScreen::tick(); + + // 4jcraft: brought over from UIControl_EnchantmentBook + oFlip = flip; + oOpen = open; + + std::shared_ptr current = + enchantMenu->getSlot(EnchantmentMenu::INGREDIENT_SLOT)->getItem(); + if (!ItemInstance::matches(current, last)) { + last = current; + + if (current) { + do { + flipT += random.nextInt(4) - random.nextInt(4); + } while (flip <= flipT + 1 && flip >= flipT - 1); + } else { + flipT = 0.0f; + } + } + + bool shouldBeOpen = false; + for (int i = 0; i < 3; ++i) { + if (enchantMenu->costs[i] != 0) { + shouldBeOpen = true; + break; + } + } + + if (shouldBeOpen) + open += 0.2f; + else + open -= 0.2f; + + if (open < 0.0f) open = 0.0f; + if (open > 1.0f) open = 1.0f; + + float diff = (flipT - flip) * 0.4f; + float max = 0.2f; + if (diff < -max) diff = -max; + if (diff > max) diff = max; + flipA += (diff - flipA) * 0.9f; + flip = flip + flipA; +} + +// 4jcraft: brought over from UIControl_EnchantmentButton +EnchantmentScreen::EnchantmentNames + EnchantmentScreen::EnchantmentNames::instance; + +EnchantmentScreen::EnchantmentNames::EnchantmentNames() { + std::wstring allWords = + L"the elder scrolls klaatu berata niktu xyzzy bless curse light " + L"darkness fire air earth water hot dry cold wet ignite snuff embiggen " + L"twist shorten stretch fiddle destroy imbue galvanize enchant free " + L"limited range of towards inside sphere cube self other ball mental " + L"physical grow shrink demon elemental spirit animal creature beast " + L"humanoid undead fresh stale "; + std::wistringstream iss(allWords); + std::copy(std::istream_iterator >(iss), + std::istream_iterator >(), + std::back_inserter(words)); +} + +std::wstring EnchantmentScreen::EnchantmentNames::getRandomName() { + int wordCount = random.nextInt(2) + 3; + std::wstring word = L""; + for (int i = 0; i < wordCount; i++) { + if (i > 0) word += L" "; + word += words[random.nextInt(words.size())]; + } + return word; +} \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/EnchantmentScreen.h b/Minecraft.Client/UI/Screens/EnchantmentScreen.h new file mode 100644 index 000000000..96a7a6af6 --- /dev/null +++ b/Minecraft.Client/UI/Screens/EnchantmentScreen.h @@ -0,0 +1,50 @@ +#pragma once + +#include "AbstractContainerScreen.h" +#include "../../../Minecraft.World/Containers/EnchantmentMenu.h" + +class EnchantmentScreen : public AbstractContainerScreen { +public: + EnchantmentScreen(std::shared_ptr inventory, Level* level, int x, + int y, int z); + virtual ~EnchantmentScreen(); + + void init() override; + void removed() override; + void tick() override; + void mouseClicked(int mouseX, int mouseY, int buttonNum) override; + void renderLabels() override; + void renderBg(float a) override; + void render(int xm, int ym, float a) override; + +private: + std::shared_ptr inventory; + EnchantmentMenu* enchantMenu; + float xMouse, yMouse; + + Random random; + + // 4jcraft: brought over from UIControl_EnchantmentBook + int bookTick; + float flip, oFlip, flipT, flipA; + float open, oOpen; + std::shared_ptr last; + + // 4jcraft: brought over from UIControl_EnchantmentButton + class EnchantmentNames { + public: + static EnchantmentNames instance; + + private: + Random random; + std::vector words; + + EnchantmentNames(); + + public: + std::wstring getRandomName(); + }; + + std::wstring enchantNames[3]; + int lastCosts[3]; +}; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/ErrorScreen.h b/Minecraft.Client/UI/Screens/ErrorScreen.h index b89b64e5d..4c46d36ff 100644 --- a/Minecraft.Client/UI/Screens/ErrorScreen.h +++ b/Minecraft.Client/UI/Screens/ErrorScreen.h @@ -7,9 +7,9 @@ private: public: ErrorScreen(const std::wstring& title, const std::wstring& message); - virtual void init(); - virtual void render(int xm, int ym, float a); + virtual void init() override; + virtual void render(int xm, int ym, float a) override; protected: - virtual void keyPressed(wchar_t eventCharacter, int eventKey); + virtual void keyPressed(wchar_t eventCharacter, int eventKey) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/FurnaceScreen.cpp b/Minecraft.Client/UI/Screens/FurnaceScreen.cpp index c12ca82dc..170aedb61 100644 --- a/Minecraft.Client/UI/Screens/FurnaceScreen.cpp +++ b/Minecraft.Client/UI/Screens/FurnaceScreen.cpp @@ -6,23 +6,26 @@ #include "../../../Minecraft.World/Headers/net.minecraft.world.inventory.h" #include "../../../Minecraft.World/Blocks/TileEntities/FurnaceTileEntity.h" +#ifdef ENABLE_JAVA_GUIS +ResourceLocation GUI_FURNACE_LOCATION = ResourceLocation(TN_GUI_FURNACE); +#endif + FurnaceScreen::FurnaceScreen(std::shared_ptr inventory, std::shared_ptr furnace) : AbstractContainerScreen(new FurnaceMenu(inventory, furnace)) { + this->inventory = inventory; this->furnace = furnace; } void FurnaceScreen::renderLabels() { - font->draw(L"Furnace", 16 + 4 + 40, 2 + 2 + 2, 0x404040); - font->draw(L"Inventory", 8, imageHeight - 96 + 2, 0x404040); + font->draw(furnace->getName(), 16 + 4 + 40, 2 + 2 + 2, 0x404040); + font->draw(inventory->getName(), 8, imageHeight - 96 + 2, 0x404040); } void FurnaceScreen::renderBg(float a) { - // 4J Unused #ifdef ENABLE_JAVA_GUIS - int tex = minecraft->textures->loadTexture(TN_GUI_FURNACE); glColor4f(1, 1, 1, 1); - minecraft->textures->bind(tex); + minecraft->textures->bindTexture(&GUI_FURNACE_LOCATION); int xo = (width - imageWidth) / 2; int yo = (height - imageHeight) / 2; this->blit(xo, yo, 0, 0, imageWidth, imageHeight); diff --git a/Minecraft.Client/UI/Screens/FurnaceScreen.h b/Minecraft.Client/UI/Screens/FurnaceScreen.h index 6908524ec..cdaab078e 100644 --- a/Minecraft.Client/UI/Screens/FurnaceScreen.h +++ b/Minecraft.Client/UI/Screens/FurnaceScreen.h @@ -6,6 +6,7 @@ class Inventory; class FurnaceScreen : public AbstractContainerScreen { private: + std::shared_ptr inventory; std::shared_ptr furnace; public: @@ -13,6 +14,6 @@ public: std::shared_ptr furnace); protected: - virtual void renderLabels(); - virtual void renderBg(float a); + virtual void renderLabels() override; + virtual void renderBg(float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/HopperScreen.cpp b/Minecraft.Client/UI/Screens/HopperScreen.cpp new file mode 100644 index 000000000..df3b3af9a --- /dev/null +++ b/Minecraft.Client/UI/Screens/HopperScreen.cpp @@ -0,0 +1,36 @@ +#include "../../Platform/stdafx.h" +#include "HopperScreen.h" +#include "../../Textures/Textures.h" +#include "../../Player/LocalPlayer.h" +#include "../Font.h" +#include "../../../Minecraft.World/Headers/net.minecraft.world.inventory.h" +#include "../../../Minecraft.World/Containers/HopperMenu.h" + +// 4jcraft: referenced from MCP 8.11 (JE 1.6.4) and the existing +// container classes +#ifdef ENABLE_JAVA_GUIS +ResourceLocation GUI_HOPPER_LOCATION = ResourceLocation(TN_GUI_HOPPER); +#endif + +HopperScreen::HopperScreen(std::shared_ptr inventory, + std::shared_ptr hopper) + : AbstractContainerScreen(new HopperMenu(inventory, hopper)) { + this->hopper = hopper; + this->inventory = inventory; + imageHeight = 133; +} + +void HopperScreen::renderLabels() { + font->draw(hopper->getName(), 8, 6, 0x404040); + font->draw(inventory->getName(), 8, imageHeight - 96 + 2, 0x404040); +} + +void HopperScreen::renderBg(float a) { +#ifdef ENABLE_JAVA_GUIS + glColor4f(1, 1, 1, 1); + minecraft->textures->bindTexture(&GUI_HOPPER_LOCATION); + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + this->blit(xo, yo, 0, 0, imageWidth, imageHeight); +#endif +} \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/HopperScreen.h b/Minecraft.Client/UI/Screens/HopperScreen.h new file mode 100644 index 000000000..e3e3d1eb4 --- /dev/null +++ b/Minecraft.Client/UI/Screens/HopperScreen.h @@ -0,0 +1,21 @@ +#pragma once +#include +#include "AbstractContainerScreen.h" + +class HopperTileEntity; +class MinecartHopper; +class Inventory; + +class HopperScreen : public AbstractContainerScreen { +public: + HopperScreen(std::shared_ptr inventory, + std::shared_ptr hopper); + +protected: + virtual void renderLabels() override; + virtual void renderBg(float a) override; + +private: + std::shared_ptr inventory; + std::shared_ptr hopper; +}; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/HorseInventoryScreen.cpp b/Minecraft.Client/UI/Screens/HorseInventoryScreen.cpp new file mode 100644 index 000000000..f6de569c9 --- /dev/null +++ b/Minecraft.Client/UI/Screens/HorseInventoryScreen.cpp @@ -0,0 +1,100 @@ +#include "../../Platform/stdafx.h" +#include "HorseInventoryScreen.h" +#include "../../Player/MultiPlayerLocalPlayer.h" +#include "../../Rendering/EntityRenderers/EntityRenderDispatcher.h" +#include "../../Rendering/Lighting.h" +#include "../../Textures/Textures.h" +#include "../../../Minecraft.World/Headers/net.minecraft.locale.h" +#include "../../../Minecraft.World/Containers/HorseInventoryMenu.h" + +// 4jcraft: referenced from MCP 8.11 (JE 1.6.4) and the existing InventoryScreen +#ifdef ENABLE_JAVA_GUIS +ResourceLocation GUI_HORSE_LOCATION = ResourceLocation(TN_GUI_HORSE); +#endif + +HorseInventoryScreen::HorseInventoryScreen( + std::shared_ptr inventory, + std::shared_ptr horseContainer, + std::shared_ptr horse) + : AbstractContainerScreen( + new HorseInventoryMenu(inventory, horseContainer, horse)) { + xMouse = yMouse = 0.0f; // 4J added + + this->inventory = inventory; + this->horseContainer = horseContainer; + this->horse = horse; + this->passEvents = false; +} + +void HorseInventoryScreen::init() { AbstractContainerScreen::init(); } + +void HorseInventoryScreen::renderLabels() { + font->draw(horseContainer->getName(), 8, 6, 0x404040); + font->draw(inventory->getName(), 8, imageHeight - 96 + 2, 0x404040); +} + +void HorseInventoryScreen::render(int xm, int ym, float a) { + AbstractContainerScreen::render(xm, ym, a); + this->xMouse = (float)xm; + this->yMouse = (float)ym; +} + +void HorseInventoryScreen::renderBg(float a) { +#ifdef ENABLE_JAVA_GUIS + glColor4f(1, 1, 1, 1); + minecraft->textures->bindTexture(&GUI_HORSE_LOCATION); + + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + blit(xo, yo, 0, 0, imageWidth, imageHeight); + + if (horse->isChestedHorse()) { + blit(xo + 79, yo + 17, 0, imageHeight, 90, 54); + } + + if (horse->canWearArmor()) { + blit(xo + 7, yo + 35, 0, imageHeight + 54, 18, 18); + } + + glEnable(GL_RESCALE_NORMAL); + glEnable(GL_COLOR_MATERIAL); + + glPushMatrix(); + glTranslatef((float)xo + 51, (float)yo + 60, 50); + float ss = 30; + glScalef(-ss, ss, ss); + glRotatef(180, 0, 0, 1); + + float oybr = horse->yBodyRot; + float oyr = horse->yRot; + float oxr = horse->xRot; + float oyh = horse->yHeadRot; + float oyhp = horse->yHeadRotO; + + float xd = (xo + 51) - xMouse; + float yd = (yo + 75 - 50) - yMouse; + + glRotatef(45 + 90, 0, 1, 0); + Lighting::turnOn(); + glRotatef(-45 - 90, 0, 1, 0); + + glRotatef(-(float)atan(yd / 40.0f) * 20, 1, 0, 0); + + horse->yBodyRot = (float)atan(xd / 40.0f) * 20; + horse->yRot = (float)atan(xd / 40.0f) * 40; + horse->xRot = -(float)atan(yd / 40.0f) * 20; + horse->yHeadRot = (float)atan(xd / 40.0f) * 40; + horse->yHeadRotO = (float)atan(xd / 40.0f) * 40; + glTranslatef(0, horse->heightOffset, 0); + EntityRenderDispatcher::instance->playerRotY = 180; + EntityRenderDispatcher::instance->render(horse, 0, 0, 0, 0, 1); + horse->yBodyRot = oybr; + horse->yRot = oyr; + horse->xRot = oxr; + horse->yHeadRot = oyh; + horse->yHeadRotO = oyhp; + glPopMatrix(); + Lighting::turnOff(); + glDisable(GL_RESCALE_NORMAL); +#endif +} \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/HorseInventoryScreen.h b/Minecraft.Client/UI/Screens/HorseInventoryScreen.h new file mode 100644 index 000000000..12b0e68a2 --- /dev/null +++ b/Minecraft.Client/UI/Screens/HorseInventoryScreen.h @@ -0,0 +1,22 @@ +#pragma once +#include +#include "AbstractContainerScreen.h" +#include "../../../Minecraft.World/Headers/net.minecraft.world.entity.animal.h" + +class HorseInventoryScreen : public AbstractContainerScreen { +public: + HorseInventoryScreen(std::shared_ptr inventory, + std::shared_ptr horseContainer, + std::shared_ptr horse); + + virtual void init() override; + virtual void renderLabels() override; + virtual void renderBg(float a) override; + virtual void render(int xm, int ym, float a) override; + +private: + std::shared_ptr inventory; + std::shared_ptr horseContainer; + std::shared_ptr horse; + float xMouse, yMouse; +}; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/InBedChatScreen.h b/Minecraft.Client/UI/Screens/InBedChatScreen.h index 3f8625eba..e068f5ce4 100644 --- a/Minecraft.Client/UI/Screens/InBedChatScreen.h +++ b/Minecraft.Client/UI/Screens/InBedChatScreen.h @@ -7,17 +7,17 @@ private: static const int WAKE_UP_BUTTON = 1; public: - virtual void init(); - virtual void removed(); + virtual void init() override; + virtual void removed() override; protected: - virtual void keyPressed(wchar_t ch, int eventKey); + virtual void keyPressed(wchar_t ch, int eventKey) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; private: void sendWakeUp(); diff --git a/Minecraft.Client/UI/Screens/InventoryScreen.cpp b/Minecraft.Client/UI/Screens/InventoryScreen.cpp index 67348db84..f4dccf4f6 100644 --- a/Minecraft.Client/UI/Screens/InventoryScreen.cpp +++ b/Minecraft.Client/UI/Screens/InventoryScreen.cpp @@ -32,7 +32,6 @@ void InventoryScreen::render(int xm, int ym, float a) { } void InventoryScreen::renderBg(float a) { - // 4J Unused #ifdef ENABLE_JAVA_GUIS int tex = minecraft->textures->loadTexture(TN_GUI_INVENTORY); glColor4f(1, 1, 1, 1); diff --git a/Minecraft.Client/UI/Screens/InventoryScreen.h b/Minecraft.Client/UI/Screens/InventoryScreen.h index 0c7080014..d2a5307c7 100644 --- a/Minecraft.Client/UI/Screens/InventoryScreen.h +++ b/Minecraft.Client/UI/Screens/InventoryScreen.h @@ -6,18 +6,18 @@ class Button; class InventoryScreen : public AbstractContainerScreen { public: InventoryScreen(std::shared_ptr player); - virtual void init(); + virtual void init() override; protected: - virtual void renderLabels(); + virtual void renderLabels() override; private: float xMouse, yMouse; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; protected: - virtual void renderBg(float a); - virtual void buttonClicked(Button* button); + virtual void renderBg(float a) override; + virtual void buttonClicked(Button* button) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/JoinMultiplayerScreen.h b/Minecraft.Client/UI/Screens/JoinMultiplayerScreen.h index c04c0d41f..78bce6115 100644 --- a/Minecraft.Client/UI/Screens/JoinMultiplayerScreen.h +++ b/Minecraft.Client/UI/Screens/JoinMultiplayerScreen.h @@ -10,20 +10,20 @@ private: public: JoinMultiplayerScreen(Screen* lastScreen); - virtual void tick(); - virtual void init(); - virtual void removed(); + virtual void tick() override; + virtual void init() override; + virtual void removed() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; private: virtual int parseInt(const std::wstring& str, int def); protected: - virtual void keyPressed(wchar_t ch, int eventKey); - virtual void mouseClicked(int x, int y, int buttonNum); + virtual void keyPressed(wchar_t ch, int eventKey) override; + virtual void mouseClicked(int x, int y, int buttonNum) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/MerchantScreen.cpp b/Minecraft.Client/UI/Screens/MerchantScreen.cpp new file mode 100644 index 000000000..f7e5a51e5 --- /dev/null +++ b/Minecraft.Client/UI/Screens/MerchantScreen.cpp @@ -0,0 +1,207 @@ +#include "../../Platform/stdafx.h" +#include "MerchantScreen.h" +#include +#include +#include "../TradeSwitchButton.h" +#include "../../Player/MultiPlayerLocalPlayer.h" +#include "../../Rendering/Lighting.h" +#include "../../Textures/Textures.h" +#include "../../Rendering/EntityRenderers/ItemRenderer.h" +#include "../../../Minecraft.World/Headers/net.minecraft.locale.h" +#include "../../../Minecraft.World/Containers/MerchantMenu.h" +#include "../../../Minecraft.World/Containers/Slot.h" +#include "../../../Minecraft.World/Containers/MerchantContainer.h" +#include "../../../Minecraft.World/Headers/net.minecraft.world.item.trading.h" +#include "../../../Minecraft.Client/Minecraft.h" +#include "../../../Minecraft.Client/Network/ClientConnection.h" +#include "../../../Minecraft.World/IO/Streams/ByteArrayOutputStream.h" +#include "../../../Minecraft.World/IO/Streams/DataOutputStream.h" +#include "../../../Minecraft.World/Util/Rarity.h" + +// 4jcraft: referenced from MCP 8.11 (JE 1.6.4) and the existing +// container classes (and iggy too) +#ifdef ENABLE_JAVA_GUIS +ResourceLocation GUI_VILLAGER_LOCATION = ResourceLocation(TN_GUI_VILLAGER); +#endif + +MerchantScreen::MerchantScreen(std::shared_ptr inventory, + std::shared_ptr merchant, Level* level) + : AbstractContainerScreen(new MerchantMenu(inventory, merchant, level)) { + this->inventory = inventory; + this->merchantMenu = static_cast(menu); + this->merchant = merchant; + this->currentRecipeIndex = 0; + this->nextRecipeButton = nullptr; + this->prevRecipeButton = nullptr; +} + +MerchantScreen::~MerchantScreen() = default; + +void MerchantScreen::init() { + AbstractContainerScreen::init(); + + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + + nextRecipeButton = + new TradeSwitchButton(1, xo + 120 + 27, yo + 24 - 1, true); + prevRecipeButton = + new TradeSwitchButton(2, xo + 36 - 19, yo + 24 - 1, false); + + nextRecipeButton->active = false; + prevRecipeButton->active = false; + + buttons.push_back(nextRecipeButton); + buttons.push_back(prevRecipeButton); +} + +void MerchantScreen::removed() { AbstractContainerScreen::removed(); } + +void MerchantScreen::renderLabels() { + font->draw(merchant->getDisplayName(), + (imageWidth / 2) - (font->width(merchant->getDisplayName()) / 2), + 6, 0x404040); + + font->draw(inventory->getName(), 8, imageHeight - 96 + 2, 0x404040); +} + +void MerchantScreen::renderBg(float a) { +#ifdef ENABLE_JAVA_GUIS + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + minecraft->textures->bindTexture(&GUI_VILLAGER_LOCATION); + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + blit(xo, yo, 0, 0, imageWidth, imageHeight); + + MerchantRecipe* activeRecipe = + merchantMenu->getTradeContainer()->getActiveRecipe(); + if (activeRecipe != nullptr && activeRecipe->isDeprecated()) { + blit(xo + 83, yo + 21, 212, 0, 28, 21); + blit(xo + 83, yo + 51, 212, 0, 28, 21); + } +#endif +} + +void MerchantScreen::render(int xm, int ym, float a) { + AbstractContainerScreen::render(xm, ym, a); + +#ifdef ENABLE_JAVA_GUIS + std::shared_ptr player = std::dynamic_pointer_cast( + inventory->player->shared_from_this()); + MerchantRecipeList* offers = merchant->getOffers(player); + + if (offers != nullptr && !offers->empty()) { + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + + MerchantRecipe* recipe = offers->at(currentRecipeIndex); + if (recipe != nullptr && !recipe->isDeprecated()) { + std::shared_ptr buyItem1 = recipe->getBuyAItem(); + std::shared_ptr buyItem2 = recipe->getBuyBItem(); + std::shared_ptr sellItem = recipe->getSellItem(); + + glPushMatrix(); + glTranslatef((float)xo, (float)yo, 0.0f); + + Lighting::turnOnGui(); + glEnable(GL_RESCALE_NORMAL); + glEnable(GL_LIGHTING); + + if (buyItem1 != nullptr) { + itemRenderer->renderGuiItem(font, minecraft->textures, buyItem1, + 36, 24); + itemRenderer->renderGuiItemDecorations( + font, minecraft->textures, buyItem1, 36, 24); + } + + if (buyItem2 != nullptr) { + itemRenderer->renderGuiItem(font, minecraft->textures, buyItem2, + 62, 24); + itemRenderer->renderGuiItemDecorations( + font, minecraft->textures, buyItem2, 62, 24); + } + + if (sellItem != nullptr) { + itemRenderer->renderGuiItem(font, minecraft->textures, sellItem, + 120, 24); + itemRenderer->renderGuiItemDecorations( + font, minecraft->textures, sellItem, 120, 24); + } + + glDisable(GL_LIGHTING); + glDisable(GL_RESCALE_NORMAL); + Lighting::turnOff(); + + glPopMatrix(); + + if (buyItem1 != nullptr && isHoveringOver(36, 24, 16, 16, xm, ym)) { + renderTooltip(buyItem1, xm, ym); + } else if (buyItem2 != nullptr && + isHoveringOver(62, 24, 16, 16, xm, ym)) { + renderTooltip(buyItem2, xm, ym); + } else if (sellItem != nullptr && + isHoveringOver(120, 24, 16, 16, xm, ym)) { + renderTooltip(sellItem, xm, ym); + } + } + } +#endif +} + +void MerchantScreen::tick() { + AbstractContainerScreen::tick(); + + std::shared_ptr player = std::dynamic_pointer_cast( + inventory->player->shared_from_this()); + + MerchantRecipeList* offers = merchant->getOffers(player); + + if (offers != nullptr) { + int offerCount = (int)offers->size(); + + nextRecipeButton->active = (currentRecipeIndex < offerCount - 1); + prevRecipeButton->active = (currentRecipeIndex > 0); + + if (currentRecipeIndex >= offerCount && offerCount > 0) { + currentRecipeIndex = offerCount - 1; + merchantMenu->setSelectionHint(currentRecipeIndex); + + // 4jcraft: taken from IUIScene_TradingMenu + ByteArrayOutputStream rawOutput; + DataOutputStream output(&rawOutput); + output.writeInt(currentRecipeIndex); + minecraft->player->connection->send( + std::shared_ptr(new CustomPayloadPacket( + CustomPayloadPacket::TRADER_SELECTION_PACKET, + rawOutput.toByteArray()))); + } + } else { + nextRecipeButton->active = false; + prevRecipeButton->active = false; + } +} + +void MerchantScreen::buttonClicked(Button* button) { + bool changed = false; + + if (button == nextRecipeButton) { + ++currentRecipeIndex; + changed = true; + } else if (button == prevRecipeButton) { + --currentRecipeIndex; + changed = true; + } + + if (changed) { + merchantMenu->setSelectionHint(currentRecipeIndex); + + // 4jcraft: taken from IUIScene_TradingMenu + ByteArrayOutputStream rawOutput; + DataOutputStream output(&rawOutput); + output.writeInt(currentRecipeIndex); + minecraft->player->connection->send( + std::shared_ptr(new CustomPayloadPacket( + CustomPayloadPacket::TRADER_SELECTION_PACKET, + rawOutput.toByteArray()))); + } +} \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/MerchantScreen.h b/Minecraft.Client/UI/Screens/MerchantScreen.h new file mode 100644 index 000000000..4a40bbb72 --- /dev/null +++ b/Minecraft.Client/UI/Screens/MerchantScreen.h @@ -0,0 +1,32 @@ +#pragma once + +#include "AbstractContainerScreen.h" +#include "../../../Minecraft.World/Containers/MerchantMenu.h" +#include "../../../Minecraft.World/Headers/net.minecraft.world.item.trading.h" + +class TradeSwitchButton; + +class MerchantScreen : public AbstractContainerScreen { +public: + MerchantScreen(std::shared_ptr inventory, + std::shared_ptr merchant, Level* level); + virtual ~MerchantScreen(); + + void init() override; + void removed() override; + void renderLabels() override; + void renderBg(float a) override; + void render(int xm, int ym, float a) override; + void tick() override; + void buttonClicked(Button* button) override; + + std::shared_ptr getMerchant() { return merchant; } + +private: + std::shared_ptr inventory; + std::shared_ptr merchant; + MerchantMenu* merchantMenu; + TradeSwitchButton* nextRecipeButton; + TradeSwitchButton* prevRecipeButton; + int currentRecipeIndex; +}; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/MessageScreen.h b/Minecraft.Client/UI/Screens/MessageScreen.h index 42a75aa78..62b4ee280 100644 --- a/Minecraft.Client/UI/Screens/MessageScreen.h +++ b/Minecraft.Client/UI/Screens/MessageScreen.h @@ -14,11 +14,11 @@ protected: virtual void keyPressed(char eventCharacter, int eventKey); public: - virtual void init(); + virtual void init() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/NameEntryScreen.h b/Minecraft.Client/UI/Screens/NameEntryScreen.h index e01c0b428..2f0babddd 100644 --- a/Minecraft.Client/UI/Screens/NameEntryScreen.h +++ b/Minecraft.Client/UI/Screens/NameEntryScreen.h @@ -15,9 +15,9 @@ private: public: NameEntryScreen(Screen* lastScreen, const std::wstring& oldName, int slot); - virtual void init(); - virtual void removed(); - virtual void tick(); + virtual void init() override; + virtual void removed() override; + virtual void tick() override; protected: virtual void buttonClicked(Button button); @@ -26,8 +26,8 @@ private: static const std::wstring allowedChars; protected: - virtual void keyPressed(wchar_t ch, int eventKey); + virtual void keyPressed(wchar_t ch, int eventKey) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/OptionsScreen.h b/Minecraft.Client/UI/Screens/OptionsScreen.h index 9e33e3dfe..509162eff 100644 --- a/Minecraft.Client/UI/Screens/OptionsScreen.h +++ b/Minecraft.Client/UI/Screens/OptionsScreen.h @@ -16,11 +16,11 @@ private: public: OptionsScreen(Screen* lastScreen, Options* options); - virtual void init(); + virtual void init() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/PauseScreen.h b/Minecraft.Client/UI/Screens/PauseScreen.h index 375d03eb6..ef67c9f14 100644 --- a/Minecraft.Client/UI/Screens/PauseScreen.h +++ b/Minecraft.Client/UI/Screens/PauseScreen.h @@ -8,15 +8,15 @@ private: public: PauseScreen(); // 4J added - virtual void init(); + virtual void init() override; static void exitWorld(Minecraft* minecraft, bool save); protected: using Screen::buttonClicked; - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void tick(); - virtual void render(int xm, int ym, float a); + virtual void tick() override; + virtual void render(int xm, int ym, float a) override; }; diff --git a/Minecraft.Client/UI/Screens/ReceivingLevelScreen.h b/Minecraft.Client/UI/Screens/ReceivingLevelScreen.h index ede53e3a2..fb54bec4d 100644 --- a/Minecraft.Client/UI/Screens/ReceivingLevelScreen.h +++ b/Minecraft.Client/UI/Screens/ReceivingLevelScreen.h @@ -16,12 +16,12 @@ protected: virtual void keyPressed(char eventCharacter, int eventKey); public: - virtual void init(); - virtual void tick(); + virtual void init() override; + virtual void tick() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; diff --git a/Minecraft.Client/UI/Screens/RenameWorldScreen.h b/Minecraft.Client/UI/Screens/RenameWorldScreen.h index 1bf433dd3..11f5ed41d 100644 --- a/Minecraft.Client/UI/Screens/RenameWorldScreen.h +++ b/Minecraft.Client/UI/Screens/RenameWorldScreen.h @@ -11,15 +11,15 @@ private: public: RenameWorldScreen(Screen* lastScreen, const std::wstring& levelId); - virtual void tick(); - virtual void init(); - virtual void removed(); + virtual void tick() override; + virtual void init() override; + virtual void removed() override; protected: - virtual void buttonClicked(Button* button); - virtual void keyPressed(wchar_t ch, int eventKey); - virtual void mouseClicked(int x, int y, int buttonNum); + virtual void buttonClicked(Button* button) override; + virtual void keyPressed(wchar_t ch, int eventKey) override; + virtual void mouseClicked(int x, int y, int buttonNum) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/RepairScreen.cpp b/Minecraft.Client/UI/Screens/RepairScreen.cpp new file mode 100644 index 000000000..6fc1e8697 --- /dev/null +++ b/Minecraft.Client/UI/Screens/RepairScreen.cpp @@ -0,0 +1,191 @@ +#include "../../Platform/stdafx.h" +#include "RepairScreen.h" +#include +#include +#include +#include "../EditBox.h" +#include "../../Player/MultiPlayerLocalPlayer.h" +#include "../../Rendering/Lighting.h" +#include "../../Textures/Textures.h" +#include "../../../Minecraft.World/Headers/net.minecraft.locale.h" +#include "../../../Minecraft.World/Containers/AnvilMenu.h" +#include "../../../Minecraft.World/Containers/Slot.h" +#include "../../../Minecraft.Client/Network/ClientConnection.h" +#include "../../../Minecraft.Client/Minecraft.h" + +// 4jcraft: referenced from MCP 8.11 (JE 1.6.4) and the existing +// IUIScene_AnvilMenu (from iggy UI) +#ifdef ENABLE_JAVA_GUIS +ResourceLocation GUI_ANVIL_LOCATION = ResourceLocation(TN_GUI_ANVIL); +#endif + +RepairScreen::RepairScreen(std::shared_ptr inventory, Level* level, + int x, int y, int z) + : AbstractContainerScreen( + new AnvilMenu(inventory, level, x, y, z, + Minecraft::GetInstance()->localplayers[0])) { + this->inventory = inventory; + this->level = level; + this->repairMenu = static_cast(menu); + this->passEvents = false; +} + +RepairScreen::~RepairScreen() = default; + +void RepairScreen::init() { + AbstractContainerScreen::init(); + + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + editName = new EditBox(this, font, xo + 62, yo + 24, 103, 12, L""); + editName->setMaxLength(40); + editName->setEnableBackgroundDrawing(false); + editName->inFocus = true; + + repairMenu->removeSlotListener(this); + repairMenu->addSlotListener(this); +} + +void RepairScreen::removed() { + AbstractContainerScreen::removed(); + repairMenu->removeSlotListener(this); +} + +void RepairScreen::render(int xm, int ym, float a) { + AbstractContainerScreen::render(xm, ym, a); + glDisable(GL_LIGHTING); + if (editName) { + editName->render(); + } +} + +void RepairScreen::renderLabels() { + std::wstring title = + Language::getInstance()->getElement(L"container.repair"); + font->draw(title, 60, 6, 0x404040); + + if (repairMenu->cost > 0) { + int textColor = 0x80ff20; + bool showCost = true; + std::wstring costString; + + if (repairMenu->cost >= 40 && + !Minecraft::GetInstance()->localplayers[0]->abilities.instabuild) { + costString = Language::getInstance()->getElement( + L"container.repair.expensive"); + textColor = 0xff6060; + } else if (!repairMenu->getSlot(AnvilMenu::RESULT_SLOT)->hasItem()) { + showCost = false; + } else if (!repairMenu->getSlot(AnvilMenu::RESULT_SLOT) + ->mayPickup( + Minecraft::GetInstance()->localplayers[0])) { + textColor = 0xff6060; + } + + if (showCost) { + if (costString.empty()) { + costString = Language::getInstance()->getElement( + L"container.repair.cost", repairMenu->cost); + } + + int shadowColor = -0x00ffffff | ((textColor & 0xfcfcfc) >> 2) | + (textColor & -0x00ffffff); + int costX = imageWidth - 8 - font->width(costString); + int costY = 67; + + // if (this.fontRenderer.getUnicodeFlag()) + // { + // drawRect(i1 - 3, b0 - 2, this.xSize - 7, b0 + 10, -16777216); + // drawRect(i1 - 2, b0 - 1, this.xSize - 8, b0 + 9, -12895429); + // } + // else + // { + font->draw(costString, costX, costY + 1, shadowColor); + font->draw(costString, costX + 1, costY, shadowColor); + font->draw(costString, costX + 1, costY + 1, shadowColor); + font->draw(costString, costX, costY, textColor); + // } + } + } +} + +void RepairScreen::renderBg(float a) { +#ifdef ENABLE_JAVA_GUIS + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + Minecraft::GetInstance()->textures->bindTexture(&GUI_ANVIL_LOCATION); + int xo = (width - imageWidth) / 2; + int yo = (height - imageHeight) / 2; + blit(xo, yo, 0, 0, imageWidth, imageHeight); + + int texV = imageHeight + (repairMenu->getSlot(0)->hasItem() ? 0 : 16); + blit(xo + 59, yo + 20, 0, texV, 110, 16); + + if ((repairMenu->getSlot(AnvilMenu::INPUT_SLOT)->hasItem() || + repairMenu->getSlot(AnvilMenu::ADDITIONAL_SLOT)->hasItem()) && + !repairMenu->getSlot(AnvilMenu::RESULT_SLOT)->hasItem()) { + blit(xo + 99, yo + 45, imageWidth, 0, 28, 21); + } +#endif +} + +void RepairScreen::keyPressed(char ch, int eventKey) { + if (editName) { + editName->keyPressed(ch, eventKey); + updateItemName(); + } else { + AbstractContainerScreen::keyPressed(ch, eventKey); + } +} + +void RepairScreen::mouseClicked(int mouseX, int mouseY, int buttonNum) { + AbstractContainerScreen::mouseClicked(mouseX, mouseY, buttonNum); + if (editName) { + editName->mouseClicked(mouseX, mouseY, buttonNum); + } +} + +void RepairScreen::updateItemName() { + std::wstring itemName; + Slot* slot = repairMenu->getSlot(0); + if (slot != NULL && slot->hasItem()) { + if (!slot->getItem()->hasCustomHoverName() && + itemName == slot->getItem()->getHoverName()) { + itemName = L""; + } + } + + repairMenu->setItemName(itemName); + + ByteArrayOutputStream baos; + DataOutputStream dos(&baos); + dos.writeUTF(itemName); + Minecraft::GetInstance()->player->connection->send( + std::shared_ptr(new CustomPayloadPacket( + CustomPayloadPacket::SET_ITEM_NAME_PACKET, baos.toByteArray()))); +} + +// 4jcraft: these 3 are to implement Containerlistener (see IUIScene_AnvilMenu +// and net.minecraft.world.inventory.ContainerListener) +void RepairScreen::refreshContainer( + AbstractContainerMenu* container, + std::vector >* items) { + slotChanged(container, AnvilMenu::INPUT_SLOT, + container->getSlot(0)->getItem()); +} + +void RepairScreen::slotChanged(AbstractContainerMenu* container, int slotIndex, + std::shared_ptr item) { + if (slotIndex == AnvilMenu::INPUT_SLOT) { + std::wstring itemName = item == NULL ? L"" : item->getHoverName(); + editName->setValue(itemName); + if (item != NULL) { + editName->focus(true); + updateItemName(); + } else { + editName->focus(false); + } + } +} + +void RepairScreen::setContainerData(AbstractContainerMenu* container, int id, + int value) {} \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/RepairScreen.h b/Minecraft.Client/UI/Screens/RepairScreen.h new file mode 100644 index 000000000..b5352a939 --- /dev/null +++ b/Minecraft.Client/UI/Screens/RepairScreen.h @@ -0,0 +1,39 @@ +#pragma once + +#include "../../Platform/stdafx.h" +#include "AbstractContainerScreen.h" +#include "../../../Minecraft.World/Containers/AnvilMenu.h" +#include "../../../Minecraft.World/Headers/net.minecraft.world.inventory.ContainerListener.h" + +class EditBox; + +class RepairScreen : public AbstractContainerScreen, public ContainerListener { +public: + RepairScreen(std::shared_ptr inventory, Level* level, int x, + int y, int z); + virtual ~RepairScreen(); + + void init(); + void removed(); + void render(int xm, int ym, float a); + void renderLabels(); + void renderBg(float a); + void keyPressed(char ch, int eventKey); + void mouseClicked(int mouseX, int mouseY, int buttonNum); + + // 4jcraft: these 3 are to implement Containerlistener (see + // IUIScene_AnvilMenu and net.minecraft.world.inventory.ContainerListener) + void refreshContainer(AbstractContainerMenu* container, + std::vector >* items); + void slotChanged(AbstractContainerMenu* container, int slotIndex, + std::shared_ptr item); + void setContainerData(AbstractContainerMenu* container, int id, int value); + +private: + void updateItemName(); + + std::shared_ptr inventory; + Level* level; + AnvilMenu* repairMenu; + EditBox* editName; +}; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/SelectWorldScreen.cpp b/Minecraft.Client/UI/Screens/SelectWorldScreen.cpp index af51786a4..0557435a5 100644 --- a/Minecraft.Client/UI/Screens/SelectWorldScreen.cpp +++ b/Minecraft.Client/UI/Screens/SelectWorldScreen.cpp @@ -122,7 +122,9 @@ void SelectWorldScreen::buttonClicked(Button* button) { minecraft->setScreen( new RenameWorldScreen(this, getWorldId(selectedWorld))); } else if (button->id == BUTTON_CANCEL_ID) { - app.DebugPrintf("SelectWorldScreen::buttonClicked 'Cancel' minecraft->setScreen(lastScreen)\n"); + app.DebugPrintf( + "SelectWorldScreen::buttonClicked 'Cancel' " + "minecraft->setScreen(lastScreen)\n"); minecraft->setScreen(lastScreen); } else { worldSelectionList->buttonClicked(button); @@ -172,9 +174,9 @@ void SelectWorldScreen::render(int xm, int ym, float a) { static bool forceCreateLevel = false; if (count++ >= 100) { if (!forceCreateLevel && levelList->size() > 0) { - // 4J Stu - For some obscures reason the "delete" button is called - // "renameButton" and vice versa. - // if( levelList->size() > 2 && deleteButton->active ) + // 4J Stu - For some obscures reason the "delete" button is + // called "renameButton" and vice versa. if( levelList->size() > + // 2 && deleteButton->active ) //{ // this->selectedWorld = 2; // count = 0; @@ -196,7 +198,9 @@ void SelectWorldScreen::render(int xm, int ym, float a) { count = 0; } } else { - app.DebugPrintf("SelectWorldScreen::render minecraft->setScreen(new CreateWorldScreen(this))\n"); + app.DebugPrintf( + "SelectWorldScreen::render minecraft->setScreen(new " + "CreateWorldScreen(this))\n"); minecraft->setScreen(new CreateWorldScreen(this)); } } diff --git a/Minecraft.Client/UI/Screens/SelectWorldScreen.h b/Minecraft.Client/UI/Screens/SelectWorldScreen.h index 5531d08e7..39b56c32f 100644 --- a/Minecraft.Client/UI/Screens/SelectWorldScreen.h +++ b/Minecraft.Client/UI/Screens/SelectWorldScreen.h @@ -20,7 +20,7 @@ protected: private: // final DateFormat DATE_FORMAT = new SimpleDateFormat(); // 4J - - //removed + // removed protected: Screen* lastScreen; @@ -41,7 +41,7 @@ private: public: SelectWorldScreen(Screen* lastScreen); - virtual void init(); + virtual void init() override; private: void loadLevelList(); @@ -54,12 +54,12 @@ public: virtual void postInit(); protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: void worldSelected(int id); - void confirmResult(bool result, int id); - virtual void render(int xm, int ym, float a); + void confirmResult(bool result, int id) override; + virtual void render(int xm, int ym, float a) override; class WorldSelectionList : public ScrolledSelectionList { public: diff --git a/Minecraft.Client/UI/Screens/StatsScreen.h b/Minecraft.Client/UI/Screens/StatsScreen.h index 91b0f5c40..dc567006d 100644 --- a/Minecraft.Client/UI/Screens/StatsScreen.h +++ b/Minecraft.Client/UI/Screens/StatsScreen.h @@ -31,14 +31,14 @@ private: public: StatsScreen(Screen* lastScreen, StatsCounter* stats); - virtual void init(); + virtual void init() override; virtual void postInit(); protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; class GeneralStatisticsList : public ScrolledSelectionList { protected: diff --git a/Minecraft.Client/UI/Screens/TextEditScreen.h b/Minecraft.Client/UI/Screens/TextEditScreen.h index 4373bd9c9..0c0af219b 100644 --- a/Minecraft.Client/UI/Screens/TextEditScreen.h +++ b/Minecraft.Client/UI/Screens/TextEditScreen.h @@ -13,19 +13,19 @@ private: public: TextEditScreen(std::shared_ptr sign); - virtual void init(); - virtual void removed(); - virtual void tick(); + virtual void init() override; + virtual void removed() override; + virtual void tick() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; private: static const std::wstring allowedChars; protected: - virtual void keyPressed(wchar_t ch, int eventKey); + virtual void keyPressed(wchar_t ch, int eventKey) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/TitleScreen.cpp b/Minecraft.Client/UI/Screens/TitleScreen.cpp index 27559f215..8aac613d5 100644 --- a/Minecraft.Client/UI/Screens/TitleScreen.cpp +++ b/Minecraft.Client/UI/Screens/TitleScreen.cpp @@ -5,6 +5,7 @@ #include "JoinMultiplayerScreen.h" #include "../../Rendering/Tesselator.h" #include "../../Textures/Textures.h" +#include "../../GameState/Options.h" #include "../../../Minecraft.World/Util/StringHelpers.h" #include "../../../Minecraft.World/IO/Streams/InputOutputStream.h" #include "../../../Minecraft.World/Headers/net.minecraft.locale.h" @@ -24,32 +25,52 @@ TitleScreen::TitleScreen() { // try { // 4J - removed try/catch std::vector splashes; - /* -BufferedReader *br = new BufferedReader(new -InputStreamReader(InputStream::getResourceAsStream(L"res\\title\\splashes.txt"))); -//, Charset.forName("UTF-8") + // 4jcraft: copied over from UIScene_MainMenu + int splashIndex; -std::wstring line = L""; -while ( !(line = br->readLine()).empty() ) - { - line = trimString( line ); - if (line.length() > 0) - { - splashes.push_back(line); + std::wstring filename = L"splashes.txt"; + if (app.hasArchiveFile(filename)) { + byteArray splashesArray = app.getArchiveFile(filename); + ByteArrayInputStream bais(splashesArray); + InputStreamReader isr(&bais); + BufferedReader br(&isr); + + std::wstring line = L""; + while (!(line = br.readLine()).empty()) { + line = trimString(line); + if (line.length() > 0) { + splashes.push_back(line); + } + } + + br.close(); } - br->close(); - delete br; - */ + splashIndex = + eSplashRandomStart + 1 + + random->nextInt((int)splashes.size() - (eSplashRandomStart + 1)); - // splash = L""; //splashes.at(random->nextInt(splashes.size())); + // Override splash text on certain dates + SYSTEMTIME LocalSysTime; + GetLocalTime(&LocalSysTime); + if (LocalSysTime.wMonth == 11 && LocalSysTime.wDay == 9) { + splashIndex = eSplashHappyBirthdayEx; + } else if (LocalSysTime.wMonth == 6 && LocalSysTime.wDay == 1) { + splashIndex = eSplashHappyBirthdayNotch; + } else if (LocalSysTime.wMonth == 12 && + LocalSysTime.wDay == 24) // the Java game shows this on + // Christmas Eve, so we will too + { + splashIndex = eSplashMerryXmas; + } else if (LocalSysTime.wMonth == 1 && LocalSysTime.wDay == 1) { + splashIndex = eSplashHappyNewYear; + } - // } catch (Exception e) { - // } + splash = splashes.at(splashIndex); } void TitleScreen::tick() { - // vo += 1.0f; + vo += 1.0f; // if( vo > 100.0f ) minecraft->setScreen(new SelectWorldScreen(this)); // // 4J - temp testing } @@ -58,6 +79,10 @@ void TitleScreen::keyPressed(wchar_t eventCharacter, int eventKey) {} void TitleScreen::init() { app.DebugPrintf("TitleScreen::init() START\n"); + + // 4jcraft: this is for the blured panorama background + viewportTexture = + minecraft->textures->getTexture(new BufferedImage(256, 256, 2)); /* 4J - removed Calendar c = Calendar.getInstance(); c.setTime(new Date()); @@ -104,38 +129,258 @@ if (c.get(Calendar.MONTH) + 1 == 11 && c.get(Calendar.DAY_OF_MONTH) == 9) { void TitleScreen::buttonClicked(Button* button) { if (button->id == 0) { - app.DebugPrintf("TitleScreen::buttonClicked() 'Options...' if (button->id == 0)\n"); + app.DebugPrintf( + "TitleScreen::buttonClicked() 'Options...' if (button->id == 0)\n"); minecraft->setScreen(new OptionsScreen(this, minecraft->options)); } if (button->id == 1) { - app.DebugPrintf("TitleScreen::buttonClicked() 'Singleplayer' if (button->id == 1)\n"); + app.DebugPrintf( + "TitleScreen::buttonClicked() 'Singleplayer' if (button->id == " + "1)\n"); minecraft->setScreen(new SelectWorldScreen(this)); } if (button->id == 2) { - app.DebugPrintf("TitleScreen::buttonClicked() 'Multiplayer' if (button->id == 2)\n"); + app.DebugPrintf( + "TitleScreen::buttonClicked() 'Multiplayer' if (button->id == " + "2)\n"); minecraft->setScreen(new JoinMultiplayerScreen(this)); } if (button->id == 3) { - app.DebugPrintf("TitleScreen::buttonClicked() 'Texture Pack' if (button->id == 3)\n"); + app.DebugPrintf( + "TitleScreen::buttonClicked() 'Texture Pack' if (button->id == " + "3)\n"); // minecraft->setScreen(new TexturePackSelectScreen(this)); // // 4J - TODO put back in } if (button->id == 4) { - app.DebugPrintf("TitleScreen::buttonClicked() Exit Game if (button->id == 4)\n"); - RenderManager.Close(); //minecraft->stop(); + app.DebugPrintf( + "TitleScreen::buttonClicked() Exit Game if (button->id == 4)\n"); + RenderManager.Close(); // minecraft->stop(); } } -void TitleScreen::render(int xm, int ym, float a) { - // 4J Unused - Iggy Flash UI renders the title screen on consoles +// 4jcraft: render our panorama +// uses the TU panorama instead of JE panorama and as such a different rendering +// method +void TitleScreen::renderPanorama(float a) { #ifdef ENABLE_JAVA_GUIS - renderBackground(); + + Tesselator* t = Tesselator::getInstance(); +#ifdef CLASSIC_PANORAMA + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + gluPerspective(120.0f, 1.0f, 0.05f, 10.0f); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + glRotatef(180.0f, 1.0f, 0.0f, 0.0f); + glEnable(GL_BLEND); + glDisable(GL_ALPHA_TEST); + glDisable(GL_CULL_FACE); + glDepthMask(false); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + char offsetPasses = 8; + + for (int i = 0; i < (offsetPasses * offsetPasses); i++) { + glPushMatrix(); + float x = + ((float)(i % offsetPasses) / (float)offsetPasses - 0.5f) / 64.0f; + float y = + ((float)(i / offsetPasses) / (float)offsetPasses - 0.5f) / 64.0f; + float z = 0.0f; + glTranslatef(x, y, z); + glRotatef(sin((vo + a) / 400.0f) * 25.0f + 20.0f, 1.0f, 0.0f, 0.0f); + glRotatef(-(vo + a) * 0.1f, 0.0f, 1.0f, 0.0f); + + for (int j = 0; j < 6; j++) { + glPushMatrix(); + + switch (j) { + case 1: + glRotatef(90.0f, 0.0f, 1.0f, 0.0f); + break; + case 2: + glRotatef(180.0f, 0.0f, 1.0f, 0.0f); + break; + case 3: + glRotatef(-90.0f, 0.0f, 1.0f, 0.0f); + break; + case 4: + glRotatef(90.0f, 1.0f, 0.0f, 0.0f); + break; + case 5: + glRotatef(-90.0f, 1.0f, 0.0f, 0.0f); + break; + default: + break; + } + + glBindTexture(GL_TEXTURE_2D, minecraft->textures->loadTexture( + TN_TITLE_BG_PANORAMA0 + j)); + t->begin(); + t->color(16777215, 255 / (i + 1)); + t->vertexUV(-1.0f, -1.0f, 1.0f, 0.0f, 0.0f); + t->vertexUV(1.0f, -1.0f, 1.0f, 1.0f, 0.0f); + t->vertexUV(1.0f, 1.0f, 1.0f, 1.0f, 1.0f); + t->vertexUV(-1.0f, 1.0f, 1.0f, 0.0f, 1.0f); + t->end(); + glPopMatrix(); + } + glPopMatrix(); + glColorMask(true, true, true, false); + } + + t->offset(0.0f, 0.0f, 0.0f); + glColorMask(true, true, true, true); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glDepthMask(true); + glEnable(GL_CULL_FACE); + glEnable(GL_ALPHA_TEST); + glEnable(GL_DEPTH_TEST); +#else + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, width, height, 0, 1000, 3000); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + glTranslatef(0, 0, -2000); + + glDisable(GL_LIGHTING); + glDisable(GL_FOG); + glEnable(GL_TEXTURE_2D); + glDisable(GL_ALPHA_TEST); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDepthMask(false); + + glBindTexture(GL_TEXTURE_2D, + minecraft->textures->loadTexture(TN_TITLE_BG_PANORAMA)); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + float off = vo * 0.0004f; + + float screenAspect = (float)width / (float)height; + float texAspect = 1748.0f / 144.0f; + float scale; + if (screenAspect > texAspect) { + scale = (float)width / 1748.0f; + } else { + scale = (float)height / 144.0f; + } + + float texWidth = 1748.0f * scale; + float texHeight = 144.0f * scale; + float yOff = (height - texHeight) / 2.0f; + + float uMax = off + (texWidth / 1748.0f); + + t->begin(GL_QUADS); + t->color(0xffffff, 255); + t->vertexUV(0, yOff + texHeight, 0, off, 1.0f); + t->vertexUV(texWidth, yOff + texHeight, 0, uMax, 1.0f); + t->vertexUV(texWidth, yOff, 0, uMax, 0.0f); + t->vertexUV(0, yOff, 0, off, 0.0f); + t->end(); + + glDepthMask(true); + glDisable(GL_BLEND); + glEnable(GL_ALPHA_TEST); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); +#endif +#endif +} + +// 4jcraft +void TitleScreen::renderSkybox(float a) { +#ifdef ENABLE_JAVA_GUIS +#ifdef CLASSIC_PANORAMA + glViewport(0, 0, 256, 256); +#endif + renderPanorama(a); +#ifdef CLASSIC_PANORAMA + glDisable(GL_TEXTURE_2D); + glEnable(GL_TEXTURE_2D); + + for (int i = 0; i < 8; i++) { + rotateAndBlur(a); + } + + glViewport(0, 0, minecraft->width, minecraft->height); + + Tesselator* t = Tesselator::getInstance(); + t->begin(); + float aspect = + width > height ? 120.0f / (float)width : 120.0f / (float)height; + float sWidth = (float)height * aspect / 256.0f; + float sHeight = (float)width * aspect / 256.0f; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + t->color(1.0f, 1.0f, 1.0f, 1.0f); + t->vertexUV(0.0f, height, 0.0f, (0.5f - sWidth), (0.5f + sHeight)); + t->vertexUV(width, height, 0.0f, (0.5f - sWidth), (0.5f - sHeight)); + t->vertexUV(width, 0.0f, 0.0f, (0.5f + sWidth), (0.5f - sHeight)); + t->vertexUV(0.0f, 0.0f, 0.0f, (0.5f + sWidth), (0.5f + sHeight)); + t->end(); +#endif +#endif +} + +// 4jcraft +void TitleScreen::rotateAndBlur(float a) { +#if defined(ENABLE_JAVA_GUIS) && defined(CLASSIC_PANORAMA) + glBindTexture(GL_TEXTURE_2D, viewportTexture); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 256, 256); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColorMask(true, true, true, false); + Tesselator* t = Tesselator::getInstance(); + t->begin(); + char blurPasses = 3; + + for (int i = 0; i < blurPasses; i++) { + t->color(1.0f, 1.0f, 1.0f, 1.0f / (float)(i + 1)); + float offset = (float)(i - blurPasses / 2) / 256.0f; + t->vertexUV(width, height, 0.0f, (0.0f + offset), 0.0f); + t->vertexUV(width, 0.0f, 0.0f, (1.0f + offset), 0.0f); + t->vertexUV(0.0f, 0.0f, 0.0f, (1.0f + offset), 1.0f); + t->vertexUV(0.0f, height, 0.0f, (0.0f + offset), 1.0f); + } + + t->end(); + glColorMask(true, true, true, true); +#endif +} + +void TitleScreen::render(int xm, int ym, float a) { +#ifdef ENABLE_JAVA_GUIS + // 4jcraft: panorama + renderSkybox(a); + Tesselator* t = Tesselator::getInstance(); int logoWidth = 155 + 119; int logoX = width / 2 - logoWidth / 2; int logoY = 30; + // 4jcraft: gradient for classic panorama +#ifdef CLASSIC_PANORAMA + fillGradient(0, 0, width, height, -2130706433, 16777215); + fillGradient(0, 0, width, height, 0, INT_MIN); +#endif + glBindTexture(GL_TEXTURE_2D, minecraft->textures->loadTexture(TN_TITLE_MCLOGO)); glColor4f(1, 1, 1, 1); @@ -155,7 +400,9 @@ void TitleScreen::render(int xm, int ym, float a) { drawCenteredString(font, splash, 0, -8, 0xffff00); glPopMatrix(); - drawString(font, ClientConstants::VERSION_STRING, 2, 2, 0x505050); + drawString( + font, ClientConstants::VERSION_STRING, 2, height - 10, + 0xffffff); // 4jcraft: use the same height as the copyright message wstring msg = L"Copyright Mojang AB. Do not distribute."; drawString(font, msg, width - font->width(msg) - 2, height - 10, 0xffffff); diff --git a/Minecraft.Client/UI/Screens/TitleScreen.h b/Minecraft.Client/UI/Screens/TitleScreen.h index 6a27ae427..5df5d4984 100644 --- a/Minecraft.Client/UI/Screens/TitleScreen.h +++ b/Minecraft.Client/UI/Screens/TitleScreen.h @@ -12,19 +12,38 @@ private: std::wstring splash; Button* multiplayerButton; + // 4jcraft: panorama + void renderPanorama(float a); + void renderSkybox(float a); + void rotateAndBlur(float a); + int viewportTexture; + + // 4jcraft: taken from UIScene_MainMenu + // 4J Added + enum eSplashIndexes { + eSplashHappyBirthdayEx = 0, + eSplashHappyBirthdayNotch, + eSplashMerryXmas, + eSplashHappyNewYear, + + // The start index in the splashes vector from which we can select a + // random splash + eSplashRandomStart, + }; + public: TitleScreen(); - virtual void tick(); + virtual void tick() override; protected: - virtual void keyPressed(wchar_t eventCharacter, int eventKey); + virtual void keyPressed(wchar_t eventCharacter, int eventKey) override; public: - virtual void init(); + virtual void init() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/TrapScreen.cpp b/Minecraft.Client/UI/Screens/TrapScreen.cpp index b754f7447..bcad68240 100644 --- a/Minecraft.Client/UI/Screens/TrapScreen.cpp +++ b/Minecraft.Client/UI/Screens/TrapScreen.cpp @@ -6,13 +6,20 @@ #include "../../../Minecraft.World/Blocks/TileEntities/DispenserTileEntity.h" #include "../../../Minecraft.World/Headers/net.minecraft.world.h" +#ifdef ENABLE_JAVA_GUIS +ResourceLocation GUI_TRAP_LOCATION = ResourceLocation(TN_GUI_TRAP); +#endif + TrapScreen::TrapScreen(std::shared_ptr inventory, std::shared_ptr trap) - : AbstractContainerScreen(new TrapMenu(inventory, trap)) {} + : AbstractContainerScreen(new TrapMenu(inventory, trap)) { + this->trap = trap; + this->inventory = inventory; +} void TrapScreen::renderLabels() { - font->draw(L"Dispenser", 16 + 4 + 40, 2 + 2 + 2, 0x404040); - font->draw(L"Inventory", 8, imageHeight - 96 + 2, 0x404040); + font->draw(trap->getName(), 16 + 4 + 40, 2 + 2 + 2, 0x404040); + font->draw(inventory->getName(), 8, imageHeight - 96 + 2, 0x404040); } void TrapScreen::renderBg(float a) { diff --git a/Minecraft.Client/UI/Screens/TrapScreen.h b/Minecraft.Client/UI/Screens/TrapScreen.h index fcf8a33fa..ae2b02c89 100644 --- a/Minecraft.Client/UI/Screens/TrapScreen.h +++ b/Minecraft.Client/UI/Screens/TrapScreen.h @@ -1,4 +1,5 @@ #pragma once +#include #include "AbstractContainerScreen.h" class DispenserTileEntity; class Inventory; @@ -11,4 +12,8 @@ public: protected: virtual void renderLabels(); virtual void renderBg(float a); + +private: + std::shared_ptr inventory; + std::shared_ptr trap; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/Screens/VideoSettingsScreen.cpp b/Minecraft.Client/UI/Screens/VideoSettingsScreen.cpp index 5daf8fdcc..e97aa1f54 100644 --- a/Minecraft.Client/UI/Screens/VideoSettingsScreen.cpp +++ b/Minecraft.Client/UI/Screens/VideoSettingsScreen.cpp @@ -6,6 +6,9 @@ #include "ControlsScreen.h" #include "../../../Minecraft.World/Headers/net.minecraft.locale.h" +// 4jcraft +#define ITEM_COUNT 10 + VideoSettingsScreen::VideoSettingsScreen(Screen* lastScreen, Options* options) { this->title = L"Video Settings"; // 4J - added this->lastScreen = lastScreen; @@ -16,18 +19,19 @@ void VideoSettingsScreen::init() { Language* language = Language::getInstance(); this->title = language->getElement(L"options.videoTitle"); - const Options::Option* items[10] = {Options::Option::GRAPHICS, - Options::Option::RENDER_DISTANCE, - Options::Option::AMBIENT_OCCLUSION, - Options::Option::FRAMERATE_LIMIT, - Options::Option::ANAGLYPH, - Options::Option::VIEW_BOBBING, - Options::Option::GUI_SCALE, - Options::Option::ADVANCED_OPENGL, - Options::Option::GAMMA, - Options::Option::FOV}; + const Options::Option* items[ITEM_COUNT] = { + Options::Option::GRAPHICS, + Options::Option::RENDER_DISTANCE, + Options::Option::AMBIENT_OCCLUSION, + Options::Option::FRAMERATE_LIMIT, + Options::Option::ANAGLYPH, + Options::Option::VIEW_BOBBING, + Options::Option::GUI_SCALE, + Options::Option::ADVANCED_OPENGL, + Options::Option::GAMMA, + Options::Option::FOV}; - for (int i = 0; i < 10; i++) { + for (int i = 0; i < ITEM_COUNT; i++) { const Options::Option* item = items[i]; int xPos = width / 2 - 155 + (i % 2 * 160); int yPos = height / 6 + 24 * (i / 2); diff --git a/Minecraft.Client/UI/Screens/VideoSettingsScreen.h b/Minecraft.Client/UI/Screens/VideoSettingsScreen.h index 7075523b2..bbeb74698 100644 --- a/Minecraft.Client/UI/Screens/VideoSettingsScreen.h +++ b/Minecraft.Client/UI/Screens/VideoSettingsScreen.h @@ -14,11 +14,11 @@ private: public: VideoSettingsScreen(Screen* lastScreen, Options* options); - virtual void init(); + virtual void init() override; protected: - virtual void buttonClicked(Button* button); + virtual void buttonClicked(Button* button) override; public: - virtual void render(int xm, int ym, float a); + virtual void render(int xm, int ym, float a) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/SlideButton.h b/Minecraft.Client/UI/SlideButton.h index 28e7726ef..f2db25366 100644 --- a/Minecraft.Client/UI/SlideButton.h +++ b/Minecraft.Client/UI/SlideButton.h @@ -16,10 +16,10 @@ public: const std::wstring& msg, float value); protected: - virtual int getYImage(bool hovered); - virtual void renderBg(Minecraft* minecraft, int xm, int ym); + virtual int getYImage(bool hovered) override; + virtual void renderBg(Minecraft* minecraft, int xm, int ym) override; public: - virtual bool clicked(Minecraft* minecraft, int mx, int my); - virtual void released(int mx, int my); + virtual bool clicked(Minecraft* minecraft, int mx, int my) override; + virtual void released(int mx, int my) override; }; \ No newline at end of file diff --git a/Minecraft.Client/UI/TradeSwitchButton.cpp b/Minecraft.Client/UI/TradeSwitchButton.cpp new file mode 100644 index 000000000..860a2c43f --- /dev/null +++ b/Minecraft.Client/UI/TradeSwitchButton.cpp @@ -0,0 +1,46 @@ +#include "../../Platform/stdafx.h" +#include "TradeSwitchButton.h" +#include "../Textures/Textures.h" +#include "../Rendering/Tesselator.h" +#include "../../../Minecraft.Client/Minecraft.h" +#include "../../../Minecraft.World/Headers/net.minecraft.locale.h" +#include "../../../Minecraft.World/Containers/MerchantMenu.h" + +// 4jcraft: referenced from MCP 8.11 (JE 1.6.4) +#ifdef ENABLE_JAVA_GUIS +// ResourceLocation GUI_VILLAGER_LOCATION = ResourceLocation(TN_GUI_VILLAGER); +extern ResourceLocation GUI_VILLAGER_LOCATION; +#endif + +TradeSwitchButton::TradeSwitchButton(int id, int x, int y, bool mirrored) + : Button(id, x, y, 12, 19, L"") { + this->mirrored = mirrored; +} + +int TradeSwitchButton::getYImage(bool hovered) { return 0; } + +void TradeSwitchButton::renderBg(Minecraft* minecraft, int xm, int ym) { +#ifdef ENABLE_JAVA_GUIS + if (!visible) return; + + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + minecraft->textures->bindTexture(&GUI_VILLAGER_LOCATION); + + bool hovered = (xm >= x && ym >= y && xm < x + w && ym < y + h); + + int textureX = 176; + int textureY = 0; + + if (!active) { + textureX += w * 2; + } else if (hovered) { + textureX += w; + } + + if (!mirrored) { + textureY += h; + } + + blit(x, y, textureX, textureY, w, h); +#endif +} \ No newline at end of file diff --git a/Minecraft.Client/UI/TradeSwitchButton.h b/Minecraft.Client/UI/TradeSwitchButton.h new file mode 100644 index 000000000..f5e8e0f0b --- /dev/null +++ b/Minecraft.Client/UI/TradeSwitchButton.h @@ -0,0 +1,14 @@ +#pragma once +#include "Button.h" + +class TradeSwitchButton : public Button { +private: + bool mirrored; + +public: + TradeSwitchButton(int id, int x, int y, bool mirrored); + +protected: + int getYImage(bool hovered) override; + void renderBg(Minecraft* minecraft, int xm, int ym) override; +}; \ No newline at end of file diff --git a/Minecraft.Client/Utils/FrameProfiler.cpp b/Minecraft.Client/Utils/FrameProfiler.cpp new file mode 100644 index 000000000..53ddaa42f --- /dev/null +++ b/Minecraft.Client/Utils/FrameProfiler.cpp @@ -0,0 +1,266 @@ +#include "../Platform/stdafx.h" +#include "FrameProfiler.h" + +#ifdef ENABLE_FRAME_PROFILER + +#include +#include +#include +#include +#include +#include + +#if defined(_MSC_VER) +#define FRAME_PROFILER_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) || defined(__clang__) +#define FRAME_PROFILER_NOINLINE __attribute__((noinline)) +#else +#define FRAME_PROFILER_NOINLINE +#endif + +namespace { + +using FrameProfilerClock = std::chrono::steady_clock; +using Bucket = FrameProfiler::Bucket; +constexpr std::uint64_t kNsPerMs = 1000ULL * 1000ULL; +constexpr std::uint64_t kReportIntervalNs = 1000ULL * 1000ULL * 1000ULL; +constexpr std::size_t kBucketCount = FrameProfiler::BucketCount(); +constexpr auto kFalseTokens = std::to_array({ + "0", "false", "False", "FALSE", "no", "No", "NO", "off", "Off", "OFF", +}); +constexpr std::array + kBucketDescriptors = {{ + {Bucket::Frame, "frame"}, + {Bucket::World, "world"}, + {Bucket::Terrain, "terrain"}, + {Bucket::ChunkCull, "chunkCull"}, + {Bucket::ChunkCollect, "chunkCollect"}, + {Bucket::ChunkPlayback, "chunkPlayback"}, + {Bucket::ChunkDirtyScan, "chunkDirtyScan"}, + {Bucket::ChunkRebuildSchedule, "chunkRebuildSchedule"}, + {Bucket::ChunkRebuildBody, "chunkRebuildBody"}, + {Bucket::ChunkPrepass, "chunkPrepass"}, + {Bucket::ChunkBlockShape, "chunkBlockShape"}, + {Bucket::ChunkBlockFaceCull, "chunkBlockFaceCull"}, + {Bucket::ChunkBlockLighting, "chunkBlockLighting"}, + {Bucket::ChunkBlockEmit, "chunkBlockEmit"}, + {Bucket::RenderableTileEntityCleanup, "renderableTileEntityCleanup"}, + {Bucket::TileEntityUnloadCleanup, "tileEntityUnloadCleanup"}, + {Bucket::Entity, "entities"}, + {Bucket::Particle, "particles"}, + {Bucket::WeatherSky, "weather"}, + {Bucket::UIHud, "ui"}, + {Bucket::Lightmap, "lightmap"}, + }}; + +struct BucketTotals { + std::uint64_t totalNs{}; + std::uint64_t maxNs{}; + std::uint64_t calls{}; + + void Record(std::uint64_t elapsedNs) noexcept { + totalNs += elapsedNs; + ++calls; + if (elapsedNs > maxNs) maxNs = elapsedNs; + } + + void Merge(const BucketTotals& other) noexcept { + totalNs += other.totalNs; + calls += other.calls; + if (other.maxNs > maxNs) maxNs = other.maxNs; + } +}; + +struct AtomicBucketTotals { + std::atomic totalNs{0}; + std::atomic maxNs{0}; + std::atomic calls{0}; +}; + +struct ProfilerState { + std::array workerBuckets{}; +}; + +struct ThreadState { + std::uint32_t frameScopeDepth{}; + std::uint64_t windowStartNs{}; + std::array localBuckets{}; +}; + +constinit ProfilerState g_profilerState{}; +constinit thread_local ThreadState t_threadState{}; + +static_assert(kBucketDescriptors.size() == kBucketCount); + +[[nodiscard]] inline std::uint64_t nowNs() noexcept { + return static_cast( + std::chrono::duration_cast( + FrameProfilerClock::now().time_since_epoch()) + .count()); +} + +[[nodiscard]] constexpr double nsToMs(std::uint64_t ns) noexcept { + return static_cast(ns) / static_cast(kNsPerMs); +} + +[[nodiscard]] constexpr bool envSaysDisabled( + std::string_view value) noexcept { + if (value.empty()) return false; + + for (std::string_view falseToken : kFalseTokens) { + if (value == falseToken) return true; + } + return false; +} + +inline void updateAtomicMax(std::atomic& value, + std::uint64_t candidate) noexcept { + std::uint64_t current = value.load(std::memory_order_relaxed); + while (current < candidate && + !value.compare_exchange_weak(current, candidate, + std::memory_order_relaxed, + std::memory_order_relaxed)) { + } +} + +inline void recordWorkerBucket(Bucket bucket, std::uint64_t elapsedNs) noexcept { + AtomicBucketTotals& state = + g_profilerState.workerBuckets[FrameProfiler::BucketIndex(bucket)]; + state.totalNs.fetch_add(elapsedNs, std::memory_order_relaxed); + state.calls.fetch_add(1, std::memory_order_relaxed); + updateAtomicMax(state.maxNs, elapsedNs); +} + +[[nodiscard]] inline bool isFrameThread() noexcept { + return t_threadState.frameScopeDepth != 0; +} + +FRAME_PROFILER_NOINLINE bool computeEnabled() noexcept { + const char* const envValue = std::getenv("C4J_FRAME_PROFILER"); + if (envValue == nullptr) return true; + return !envSaysDisabled(envValue); +} + +FRAME_PROFILER_NOINLINE void emitWindowReport( + const std::array& buckets) noexcept { + const std::uint64_t frames = + buckets[FrameProfiler::BucketIndex(Bucket::Frame)].calls; + if (frames == 0) return; + + std::fprintf(stderr, + "[frame-prof] avg/frame(ms) frames=%llu", + static_cast(frames)); + for (const auto& descriptor : kBucketDescriptors) { + const BucketTotals& bucket = + buckets[FrameProfiler::BucketIndex(descriptor.bucket)]; + const std::string_view label = descriptor.label; + std::fprintf(stderr, " %.*s=%.2f", static_cast(label.size()), + label.data(), nsToMs(bucket.totalNs) / frames); + } + std::fputc('\n', stderr); + + std::fputs("[frame-prof] max(ms)/calls", stderr); + for (const auto& descriptor : kBucketDescriptors) { + const BucketTotals& bucket = + buckets[FrameProfiler::BucketIndex(descriptor.bucket)]; + const std::string_view label = descriptor.label; + std::fprintf(stderr, " %.*s=%.2f/%llu", + static_cast(label.size()), label.data(), + nsToMs(bucket.maxNs), + static_cast(bucket.calls)); + } + std::fputc('\n', stderr); + std::fflush(stderr); +} + +[[nodiscard]] std::array snapshotAndResetWorkerBuckets() + noexcept { + std::array snapshot = {}; + for (std::size_t i = 0; i < kBucketCount; ++i) { + AtomicBucketTotals& workerBucket = g_profilerState.workerBuckets[i]; + snapshot[i].totalNs = + workerBucket.totalNs.exchange(0, std::memory_order_relaxed); + snapshot[i].maxNs = + workerBucket.maxNs.exchange(0, std::memory_order_relaxed); + snapshot[i].calls = + workerBucket.calls.exchange(0, std::memory_order_relaxed); + } + return snapshot; +} + +} // namespace + +bool FrameProfiler::IsEnabled() noexcept { + static const bool enabled = computeEnabled(); + return enabled; +} + +void FrameProfiler::Record(Bucket bucket, std::uint64_t elapsedNs) noexcept { + if (isFrameThread()) { + t_threadState.localBuckets[BucketIndex(bucket)].Record(elapsedNs); + return; + } + + recordWorkerBucket(bucket, elapsedNs); +} + +void FrameProfiler::EndFrame(std::uint64_t elapsedNs) noexcept { + Record(Bucket::Frame, elapsedNs); + + ThreadState& threadState = t_threadState; + const std::uint64_t now = nowNs(); + + if (threadState.windowStartNs == 0) { + threadState.windowStartNs = now; + return; + } + + if ((now - threadState.windowStartNs) < kReportIntervalNs) return; + + std::array combined = threadState.localBuckets; + const auto workerSnapshot = snapshotAndResetWorkerBuckets(); + + for (std::size_t i = 0; i < kBucketCount; ++i) { + combined[i].Merge(workerSnapshot[i]); + } + + emitWindowReport(combined); + + threadState.windowStartNs = now; + threadState.localBuckets = {}; +} + +FrameProfiler::Scope::Scope(Bucket bucket) noexcept + : m_startNs(0), m_bucket(bucket), m_enabled(FrameProfiler::IsEnabled()) { + if (m_enabled) m_startNs = nowNs(); +} + +FrameProfiler::Scope::~Scope() noexcept { + if (!m_enabled) return; + FrameProfiler::Record(m_bucket, nowNs() - m_startNs); +} + +FrameProfiler::FrameScope::FrameScope() noexcept + : m_startNs(0), m_enabled(false) { + if (!FrameProfiler::IsEnabled()) return; + + m_enabled = (t_threadState.frameScopeDepth++ == 0); + if (m_enabled) m_startNs = nowNs(); +} + +FrameProfiler::FrameScope::~FrameScope() noexcept { + if (!m_enabled) { + if (t_threadState.frameScopeDepth > 0) { + --t_threadState.frameScopeDepth; + } + return; + } + + FrameProfiler::EndFrame(nowNs() - m_startNs); + + if (t_threadState.frameScopeDepth > 0) { + --t_threadState.frameScopeDepth; + } +} + +#endif diff --git a/Minecraft.Client/Utils/FrameProfiler.h b/Minecraft.Client/Utils/FrameProfiler.h new file mode 100644 index 000000000..c22351f69 --- /dev/null +++ b/Minecraft.Client/Utils/FrameProfiler.h @@ -0,0 +1,100 @@ +#pragma once + +#ifdef ENABLE_FRAME_PROFILER + +#include +#include +#include + +class FrameProfiler { +public: + enum class Bucket : std::uint8_t { + Frame, + World, + Terrain, + ChunkCull, + ChunkCollect, + ChunkPlayback, + ChunkDirtyScan, + ChunkRebuildSchedule, + ChunkRebuildBody, + ChunkPrepass, + ChunkBlockShape, + ChunkBlockFaceCull, + ChunkBlockLighting, + ChunkBlockEmit, + RenderableTileEntityCleanup, + TileEntityUnloadCleanup, + Entity, + Particle, + WeatherSky, + UIHud, + Lightmap, + Count, + }; + + struct BucketDescriptor { + Bucket bucket; + const char* label; + }; + + [[nodiscard]] static constexpr std::size_t BucketIndex( + Bucket bucket) noexcept { + return static_cast(std::to_underlying(bucket)); + } + + [[nodiscard]] static constexpr std::size_t BucketCount() noexcept { + return BucketIndex(Bucket::Count); + } + + [[nodiscard]] static bool IsEnabled() noexcept; + + class Scope { + public: + explicit Scope(Bucket bucket) noexcept; + Scope(const Scope&) = delete; + Scope& operator=(const Scope&) = delete; + Scope(Scope&&) = delete; + Scope& operator=(Scope&&) = delete; + ~Scope() noexcept; + + private: + std::uint64_t m_startNs; + Bucket m_bucket; + bool m_enabled; + }; + + class FrameScope { + public: + FrameScope() noexcept; + FrameScope(const FrameScope&) = delete; + FrameScope& operator=(const FrameScope&) = delete; + FrameScope(FrameScope&&) = delete; + FrameScope& operator=(FrameScope&&) = delete; + ~FrameScope() noexcept; + + private: + std::uint64_t m_startNs; + bool m_enabled; + }; + +private: + static void Record(Bucket bucket, std::uint64_t elapsedNs) noexcept; + static void EndFrame(std::uint64_t elapsedNs) noexcept; +}; + +#define FRAME_PROFILE_CONCAT_INNER(a, b) a##b +#define FRAME_PROFILE_CONCAT(a, b) FRAME_PROFILE_CONCAT_INNER(a, b) +#define FRAME_PROFILE_SCOPE(bucket_name) \ + FrameProfiler::Scope FRAME_PROFILE_CONCAT(frameProfileScope_, __LINE__)( \ + FrameProfiler::Bucket::bucket_name) +#define FRAME_PROFILE_FRAME_SCOPE() \ + FrameProfiler::FrameScope FRAME_PROFILE_CONCAT(frameProfileFrameScope_, \ + __LINE__) + +#else + +#define FRAME_PROFILE_SCOPE(bucket_name) ((void)0) +#define FRAME_PROFILE_FRAME_SCOPE() ((void)0) + +#endif diff --git a/Minecraft.Client/meson.build b/Minecraft.Client/meson.build index f81dddddd..123320903 100644 --- a/Minecraft.Client/meson.build +++ b/Minecraft.Client/meson.build @@ -8,21 +8,21 @@ exclude_sources = [ # all sources except ./Platform/* client_sources = run_command( - 'sh', '-c', - 'find "' - + meson.current_source_dir() - + '" \\( -name "*.cpp" -o -name "*.c" \\)' - + ' '.join(exclude_sources), - check : true, + 'sh', + '-c', 'find "' + + meson.current_source_dir() + + '" \\( -name "*.cpp" -o -name "*.c" \\)' + + ' '.join(exclude_sources), + check: true, ).stdout().strip().split('\n') # all sources in ./Platform (top-level files only) platform_sources = run_command( - 'sh', '-c', - 'find "' - + meson.current_source_dir() / 'Platform' - + '" -maxdepth 1 \\( -name "*.cpp" -o -name "*.c" \\)', - check : true, + 'sh', + '-c', 'find "' + + meson.current_source_dir() / 'Platform' + + '" -maxdepth 1 \\( -name "*.cpp" -o -name "*.c" \\)', + check: true, ).stdout().strip().split('\n') # some platform-specific sources that are for some stupid reason in Common @@ -32,88 +32,109 @@ exclude_platform_common_sources = [ # we use system zlib instead, since this one is old as hell and isn't configured for linux correctly ' ! -path "*/zlib/*"', ' ! -name "SonyLeaderboardManager.cpp"', - ' ! -name "UIScene_InGameSaveManagementMenu.cpp"' + ' ! -name "UIScene_InGameSaveManagementMenu.cpp"', ] # all sources in in ./Platform/Common platform_sources += run_command( - 'sh', '-c', - 'find "' - + meson.current_source_dir() / 'Platform/Common' - + '" \\( -name "*.cpp" -o -name "*.c" \\)' - + ' '.join(exclude_platform_common_sources), - check : true, + 'sh', + '-c', 'find "' + + meson.current_source_dir() / 'Platform/Common' + + '" \\( -name "*.cpp" -o -name "*.c" \\)' + + ' '.join(exclude_platform_common_sources), + check: true, ).stdout().strip().split('\n') # linux-specific files (everything in Platform/Linux) if host_machine.system() == 'linux' platform_sources += run_command( - 'sh', '-c', - 'find "' - + meson.current_source_dir() / 'Platform/Linux' - + '" \\( -name "*.cpp" -o -name "*.c" \\) ', - check : true, + 'sh', + '-c', 'find "' + + meson.current_source_dir() / 'Platform/Linux' + + '" \\( -name "*.cpp" -o -name "*.c" \\) ', + check: true, ).stdout().strip().split('\n') endif client_dependencies = [ - render_dep, - input_dep, - profile_dep, - storage_dep, - assets_localisation_dep, - world_dep, - gl_dep, - glu_dep, - thread_dep, - thread_dep, - dependency('zlib'), - miniaudio_dep + render_dep, + input_dep, + profile_dep, + storage_dep, + assets_localisation_dep, + world_dep, + gl_dep, + glu_dep, + thread_dep, + dl_dep, + dependency('zlib'), + miniaudio_dep, + stb_dep, ] if get_option('enable_vsync') - global_cpp_defs += '-DENABLE_VSYNC' + global_cpp_defs += ['-DENABLE_VSYNC'] endif -if get_option('enable_shiggy') - shiggy_dep = dependency( - 'shiggy', - fallback : ['shiggy', 'shiggy_dep'], - ) - - global_cpp_defs += '-D_ENABLEIGGY' - client_dependencies += shiggy_dep +if get_option('classic_panorama') + global_cpp_defs += '-DCLASSIC_PANORAMA' endif -if get_option('enable_java_guis') +if get_option('enable_frame_profiler') + global_cpp_defs += ['-DENABLE_FRAME_PROFILER'] +endif + +if get_option('ui_backend') == 'shiggy' + shiggy_dep = dependency( + 'shiggy', + fallback: ['shiggy', 'shiggy_dep'], + ) + + global_cpp_defs += ['-D_ENABLEIGGY'] + client_dependencies += shiggy_dep +endif + +if get_option('ui_backend') == 'java' global_cpp_defs += '-DENABLE_JAVA_GUIS' endif -if get_option('enable_shiggy') and get_option('enable_java_guis') - error('You cannot use the Iggy and Java UI at the same time, please choose one.') +occlusion_mode = get_option('occlusion_culling') +if occlusion_mode == 'off' + global_cpp_defs += ['-DOCCLUSION_MODE_NONE'] +elif occlusion_mode == 'frustum' + global_cpp_defs += ['-DOCCLUSION_MODE_FRUSTUM'] +elif occlusion_mode == 'bfs' + global_cpp_defs += ['-DOCCLUSION_MODE_BFS', '-DUSE_OCCLUSION_CULLING'] +elif occlusion_mode == 'hardware' + global_cpp_defs += ['-DOCCLUSION_MODE_HARDWARE', '-DUSE_OCCLUSION_CULLING'] endif - -client = executable('Minecraft.Client', +client = executable( + 'Minecraft.Client', client_sources + platform_sources + localisation[1], - include_directories : [include_directories('Platform', 'Platform/Linux/Iggy/include'),stb], - dependencies : client_dependencies, - cpp_args : global_cpp_args + global_cpp_defs + [ - '-DUNICODE', '-D_UNICODE', + include_directories: include_directories('Platform', 'Platform/Linux/Iggy/include'), + dependencies: client_dependencies, + cpp_args: global_cpp_args + + global_cpp_defs + + [ + '-DUNICODE', + '-D_UNICODE', '-include', meson.current_source_dir() / 'Platform/stdafx.h', ], - c_args : global_cpp_defs + ['-DUNICODE', '-D_UNICODE'], - install : true, - install_dir : '' + c_args: global_cpp_defs + ['-DUNICODE', '-D_UNICODE'], + install: true, + install_dir: '', ) # To support actually running the client from the build folder, we need to # copy the generated assets from Minecraft.Assets into the working directory # of the client. -custom_target('copy_assets_to_client', +custom_target( + 'copy_assets_to_client', input: [client, media_archive], output: 'assets.stamp', # using a stamp file to avoid copying assets every time - command : [ - python, meson.project_source_root() / 'scripts/copy_assets_to_client.py', + command: [ + python, + meson.project_source_root() / 'scripts/copy_assets_to_client.py', meson.project_source_root(), meson.project_build_root(), meson.current_build_dir(), diff --git a/Minecraft.World/AI/Control/LookControl.cpp b/Minecraft.World/AI/Control/LookControl.cpp index f5b7519b1..c956da61d 100644 --- a/Minecraft.World/AI/Control/LookControl.cpp +++ b/Minecraft.World/AI/Control/LookControl.cpp @@ -20,7 +20,7 @@ void LookControl::setLookAt(std::shared_ptr target, float yMax, target->y + std::dynamic_pointer_cast(target)->getHeadHeight(); else - wantedY = (target->bb->y0 + target->bb->y1) / 2; + wantedY = (target->bb.y0 + target->bb.y1) / 2; wantedZ = target->z; this->yMax = yMax; this->xMax = xMax; @@ -88,4 +88,4 @@ double LookControl::getWantedX() { return wantedX; } double LookControl::getWantedY() { return wantedY; } -double LookControl::getWantedZ() { return wantedZ; } \ No newline at end of file +double LookControl::getWantedZ() { return wantedZ; } diff --git a/Minecraft.World/AI/Control/MoveControl.cpp b/Minecraft.World/AI/Control/MoveControl.cpp index 3834ed6a4..684ccd498 100644 --- a/Minecraft.World/AI/Control/MoveControl.cpp +++ b/Minecraft.World/AI/Control/MoveControl.cpp @@ -38,7 +38,7 @@ void MoveControl::tick() { if (!_hasWanted) return; _hasWanted = false; - int yFloor = floor(mob->bb->y0 + .5f); + int yFloor = floor(mob->bb.y0 + .5f); double xd = wantedX - mob->x; double zd = wantedZ - mob->z; @@ -66,4 +66,4 @@ float MoveControl::rotlerp(float a, float b, float max) { diff = -max; } return a + diff; -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/AvoidPlayerGoal.cpp b/Minecraft.World/AI/Goals/AvoidPlayerGoal.cpp index 1e2d3cb1d..af58f48ec 100644 --- a/Minecraft.World/AI/Goals/AvoidPlayerGoal.cpp +++ b/Minecraft.World/AI/Goals/AvoidPlayerGoal.cpp @@ -53,9 +53,10 @@ bool AvoidPlayerGoal::canUse() { mob->level->getNearestPlayer(mob->shared_from_this(), maxDist)); if (toAvoid.lock() == NULL) return false; } else { + AABB grown_bb = mob->bb.grow(maxDist, 3, maxDist); std::vector >* entities = mob->level->getEntitiesOfClass( - avoidType, mob->bb->grow(maxDist, 3, maxDist), entitySelector); + avoidType, &grown_bb, entitySelector); if (entities->empty()) { delete entities; return false; @@ -64,18 +65,18 @@ bool AvoidPlayerGoal::canUse() { delete entities; } - Vec3* pos = RandomPos::getPosAvoid( + Vec3 avoid_pos(toAvoid.lock()->x, toAvoid.lock()->y, toAvoid.lock()->z); + auto pos = RandomPos::getPosAvoid( std::dynamic_pointer_cast(mob->shared_from_this()), 16, - 7, - Vec3::newTemp(toAvoid.lock()->x, toAvoid.lock()->y, toAvoid.lock()->z)); - if (pos == NULL) return false; + 7, &avoid_pos); + if (!pos.has_value()) return false; if (toAvoid.lock()->distanceToSqr(pos->x, pos->y, pos->z) < toAvoid.lock()->distanceToSqr(mob->shared_from_this())) return false; delete path; path = pathNav->createPath(pos->x, pos->y, pos->z); if (path == NULL) return false; - if (!path->endsInXZ(pos)) return false; + if (!path->endsInXZ(&*pos)) return false; return true; } @@ -95,4 +96,4 @@ void AvoidPlayerGoal::tick() { mob->getNavigation()->setSpeedModifier(sprintSpeedModifier); else mob->getNavigation()->setSpeedModifier(walkSpeedModifier); -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/BegGoal.cpp b/Minecraft.World/AI/Goals/BegGoal.cpp index de7992e6a..4c8c2bd28 100644 --- a/Minecraft.World/AI/Goals/BegGoal.cpp +++ b/Minecraft.World/AI/Goals/BegGoal.cpp @@ -54,4 +54,4 @@ bool BegGoal::playerHoldingInteresting(std::shared_ptr player) { if (item == NULL) return false; if (!wolf->isTame() && item->id == Item::bone_Id) return true; return wolf->isFood(item); -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/BreedGoal.cpp b/Minecraft.World/AI/Goals/BreedGoal.cpp index 25281c61d..7c9fc4ce7 100644 --- a/Minecraft.World/AI/Goals/BreedGoal.cpp +++ b/Minecraft.World/AI/Goals/BreedGoal.cpp @@ -48,8 +48,9 @@ void BreedGoal::tick() { std::shared_ptr BreedGoal::getFreePartner() { float r = 8; + AABB grown_bb = animal->bb.grow(r, r, r); std::vector >* others = - level->getEntitiesOfClass(typeid(*animal), animal->bb->grow(r, r, r)); + level->getEntitiesOfClass(typeid(*animal), &grown_bb); double dist = std::numeric_limits::max(); std::shared_ptr partner = nullptr; for (AUTO_VAR(it, others->begin()); it != others->end(); ++it) { diff --git a/Minecraft.World/AI/Goals/FleeSunGoal.cpp b/Minecraft.World/AI/Goals/FleeSunGoal.cpp index 70a77fe77..4f35fb567 100644 --- a/Minecraft.World/AI/Goals/FleeSunGoal.cpp +++ b/Minecraft.World/AI/Goals/FleeSunGoal.cpp @@ -5,6 +5,7 @@ #include "../../Headers/net.minecraft.world.level.h" #include "../../Headers/net.minecraft.world.phys.h" #include "FleeSunGoal.h" +#include FleeSunGoal::FleeSunGoal(PathfinderMob* mob, double speedModifier) { this->mob = mob; @@ -16,12 +17,12 @@ FleeSunGoal::FleeSunGoal(PathfinderMob* mob, double speedModifier) { bool FleeSunGoal::canUse() { if (!level->isDay()) return false; if (!mob->isOnFire()) return false; - if (!level->canSeeSky(Mth::floor(mob->x), (int)mob->bb->y0, + if (!level->canSeeSky(Mth::floor(mob->x), (int)mob->bb.y0, Mth::floor(mob->z))) return false; - Vec3* pos = getHidePos(); - if (pos == NULL) return false; + auto pos = getHidePos(); + if (!pos.has_value()) return false; wantedX = pos->x; wantedY = pos->y; wantedZ = pos->z; @@ -34,15 +35,15 @@ void FleeSunGoal::start() { mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier); } -Vec3* FleeSunGoal::getHidePos() { +std::optional FleeSunGoal::getHidePos() { Random* random = mob->getRandom(); for (int i = 0; i < 10; i++) { int xt = Mth::floor(mob->x + random->nextInt(20) - 10); - int yt = Mth::floor(mob->bb->y0 + random->nextInt(6) - 3); + int yt = Mth::floor(mob->bb.y0 + random->nextInt(6) - 3); int zt = Mth::floor(mob->z + random->nextInt(20) - 10); if (!level->canSeeSky(xt, yt, zt) && mob->getWalkTargetValue(xt, yt, zt) < 0) - return Vec3::newTemp(xt, yt, zt); + return Vec3(xt, yt, zt); } - return NULL; -} \ No newline at end of file + return std::nullopt; +} diff --git a/Minecraft.World/AI/Goals/FleeSunGoal.h b/Minecraft.World/AI/Goals/FleeSunGoal.h index cdd6f8612..e9cce5983 100644 --- a/Minecraft.World/AI/Goals/FleeSunGoal.h +++ b/Minecraft.World/AI/Goals/FleeSunGoal.h @@ -1,5 +1,8 @@ #pragma once +#include + +#include "../../Util/Vec3.h" #include "Goal.h" class FleeSunGoal : public Goal { @@ -17,10 +20,10 @@ public: virtual void start(); private: - Vec3* getHidePos(); + std::optional getHidePos(); public: // 4J Added override to update ai elements when loading entity from // schematics virtual void setLevel(Level* level) { this->level = level; } -}; \ No newline at end of file +}; diff --git a/Minecraft.World/AI/Goals/FollowOwnerGoal.cpp b/Minecraft.World/AI/Goals/FollowOwnerGoal.cpp index 928f7e8ef..62c0431ab 100644 --- a/Minecraft.World/AI/Goals/FollowOwnerGoal.cpp +++ b/Minecraft.World/AI/Goals/FollowOwnerGoal.cpp @@ -69,7 +69,7 @@ void FollowOwnerGoal::tick() { // find a good spawn position nearby the owner int sx = Mth::floor(owner.lock()->x) - 2; int sz = Mth::floor(owner.lock()->z) - 2; - int y = Mth::floor(owner.lock()->bb->y0); + int y = Mth::floor(owner.lock()->bb.y0); for (int x = 0; x <= 4; x++) { for (int z = 0; z <= 4; z++) { if (x >= 1 && z >= 1 && x <= 3 && z <= 3) { @@ -85,4 +85,4 @@ void FollowOwnerGoal::tick() { } } } -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/FollowParentGoal.cpp b/Minecraft.World/AI/Goals/FollowParentGoal.cpp index d60dd34a9..bcdc860ae 100644 --- a/Minecraft.World/AI/Goals/FollowParentGoal.cpp +++ b/Minecraft.World/AI/Goals/FollowParentGoal.cpp @@ -16,9 +16,9 @@ FollowParentGoal::FollowParentGoal(Animal* animal, double speedModifier) { bool FollowParentGoal::canUse() { if (animal->getAge() >= 0) return false; + AABB grown_bb = animal->bb.grow(8, 4, 8); std::vector >* parents = - animal->level->getEntitiesOfClass(typeid(*animal), - animal->bb->grow(8, 4, 8)); + animal->level->getEntitiesOfClass(typeid(*animal), &grown_bb); std::shared_ptr closest = nullptr; double closestDistSqr = std::numeric_limits::max(); diff --git a/Minecraft.World/AI/Goals/HurtByTargetGoal.cpp b/Minecraft.World/AI/Goals/HurtByTargetGoal.cpp index 7bee32298..00a3e838d 100644 --- a/Minecraft.World/AI/Goals/HurtByTargetGoal.cpp +++ b/Minecraft.World/AI/Goals/HurtByTargetGoal.cpp @@ -22,11 +22,10 @@ void HurtByTargetGoal::start() { if (alertSameType) { double within = getFollowDistance(); + AABB mob_bb = AABB(mob->x, mob->y, mob->z, mob->x + 1, mob->y + 1, mob->z + 1).grow(within, 4, within); std::vector >* nearby = mob->level->getEntitiesOfClass( - typeid(*mob), AABB::newTemp(mob->x, mob->y, mob->z, mob->x + 1, - mob->y + 1, mob->z + 1) - ->grow(within, 4, within)); + typeid(*mob), &mob_bb); for (AUTO_VAR(it, nearby->begin()); it != nearby->end(); ++it) { std::shared_ptr other = std::dynamic_pointer_cast(*it); @@ -40,4 +39,4 @@ void HurtByTargetGoal::start() { } TargetGoal::start(); -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/LeapAtTargetGoal.cpp b/Minecraft.World/AI/Goals/LeapAtTargetGoal.cpp index 9779984dd..fc59fda1f 100644 --- a/Minecraft.World/AI/Goals/LeapAtTargetGoal.cpp +++ b/Minecraft.World/AI/Goals/LeapAtTargetGoal.cpp @@ -34,4 +34,4 @@ void LeapAtTargetGoal::start() { mob->xd += (xdd / dd * 0.5f) * 0.8f + mob->xd * 0.2f; mob->zd += (zdd / dd * 0.5f) * 0.8f + mob->zd * 0.2f; mob->yd = yd; -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/LookAtPlayerGoal.cpp b/Minecraft.World/AI/Goals/LookAtPlayerGoal.cpp index 631362809..8ab999411 100644 --- a/Minecraft.World/AI/Goals/LookAtPlayerGoal.cpp +++ b/Minecraft.World/AI/Goals/LookAtPlayerGoal.cpp @@ -37,9 +37,9 @@ bool LookAtPlayerGoal::canUse() { lookAt = mob->level->getNearestPlayer(mob->shared_from_this(), lookDistance); } else { + AABB mob_bb = mob->bb.grow(lookDistance, 3, lookDistance); lookAt = std::weak_ptr(mob->level->getClosestEntityOfClass( - lookAtType, mob->bb->grow(lookDistance, 3, lookDistance), - mob->shared_from_this())); + lookAtType, &mob_bb, mob->shared_from_this())); } return lookAt.lock() != NULL; } @@ -62,4 +62,4 @@ void LookAtPlayerGoal::tick() { lookAt.lock()->x, lookAt.lock()->y + lookAt.lock()->getHeadHeight(), lookAt.lock()->z, 10, mob->getMaxHeadXRot()); --lookTime; -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/MakeLoveGoal.cpp b/Minecraft.World/AI/Goals/MakeLoveGoal.cpp index 733036801..af3dd10e3 100644 --- a/Minecraft.World/AI/Goals/MakeLoveGoal.cpp +++ b/Minecraft.World/AI/Goals/MakeLoveGoal.cpp @@ -29,9 +29,9 @@ bool MakeLoveGoal::canUse() { if (village.lock() == NULL) return false; if (!villageNeedsMoreVillagers()) return false; + AABB villager_bb = villager->bb.grow(8, 3, 8); std::shared_ptr mate = level->getClosestEntityOfClass( - typeid(Villager), villager->bb->grow(8, 3, 8), - villager->shared_from_this()); + typeid(Villager), &villager_bb, villager->shared_from_this()); if (mate == NULL) return false; partner = diff --git a/Minecraft.World/AI/Goals/MeleeAttackGoal.cpp b/Minecraft.World/AI/Goals/MeleeAttackGoal.cpp index b3f059d8e..3c9b28244 100644 --- a/Minecraft.World/AI/Goals/MeleeAttackGoal.cpp +++ b/Minecraft.World/AI/Goals/MeleeAttackGoal.cpp @@ -41,7 +41,7 @@ bool MeleeAttackGoal::canUse() { std::shared_ptr target = mob->getTarget(); if (target == NULL) return false; if (!target->isAlive()) return false; - if (attackType != eTYPE_NOTSET && !target->instanceof (attackType)) + if (attackType != eTYPE_NOTSET && !target->instanceof(attackType)) return false; path.reset(mob->getNavigation()->createPath(target)); return path != nullptr; @@ -79,7 +79,7 @@ void MeleeAttackGoal::tick() { double meleeRadiusSqr = (mob->bbWidth * 2) * (mob->bbWidth * 2) + target->bbWidth; - if (mob->distanceToSqr(target->x, target->bb->y0, target->z) > + if (mob->distanceToSqr(target->x, target->bb.y0, target->z) > meleeRadiusSqr) return; if (attackTime > 0) return; diff --git a/Minecraft.World/AI/Goals/MoveIndoorsGoal.cpp b/Minecraft.World/AI/Goals/MoveIndoorsGoal.cpp index db570665d..6451e21e4 100644 --- a/Minecraft.World/AI/Goals/MoveIndoorsGoal.cpp +++ b/Minecraft.World/AI/Goals/MoveIndoorsGoal.cpp @@ -44,13 +44,12 @@ void MoveIndoorsGoal::start() { } if (mob->distanceToSqr(_doorInfo->getIndoorX(), _doorInfo->y, _doorInfo->getIndoorZ()) > 16 * 16) { - Vec3* pos = RandomPos::getPosTowards( + Vec3 towards(_doorInfo->getIndoorX() + 0.5, _doorInfo->getIndoorY(), + _doorInfo->getIndoorZ() + 0.5); + auto pos = RandomPos::getPosTowards( std::dynamic_pointer_cast(mob->shared_from_this()), - 14, 3, - Vec3::newTemp(_doorInfo->getIndoorX() + 0.5, - _doorInfo->getIndoorY(), - _doorInfo->getIndoorZ() + 0.5)); - if (pos != NULL) + 14, 3, &towards); + if (pos.has_value()) mob->getNavigation()->moveTo(pos->x, pos->y, pos->z, 1.0f); } else mob->getNavigation()->moveTo(_doorInfo->getIndoorX() + 0.5, @@ -68,4 +67,4 @@ void MoveIndoorsGoal::stop() { insideX = _doorInfo->getIndoorX(); insideZ = _doorInfo->getIndoorZ(); doorInfo = std::weak_ptr(); -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/MoveThroughVillageGoal.cpp b/Minecraft.World/AI/Goals/MoveThroughVillageGoal.cpp index a5c511525..03fe6795a 100644 --- a/Minecraft.World/AI/Goals/MoveThroughVillageGoal.cpp +++ b/Minecraft.World/AI/Goals/MoveThroughVillageGoal.cpp @@ -47,10 +47,11 @@ bool MoveThroughVillageGoal::canUse() { mob->getNavigation()->setCanOpenDoors(oldCanOpenDoors); if (path != NULL) return true; - Vec3* pos = RandomPos::getPosTowards( + Vec3 towards(_doorInfo->x, _doorInfo->y, _doorInfo->z); + auto pos = RandomPos::getPosTowards( std::dynamic_pointer_cast(mob->shared_from_this()), 10, - 7, Vec3::newTemp(_doorInfo->x, _doorInfo->y, _doorInfo->z)); - if (pos == NULL) return false; + 7, &towards); + if (!pos.has_value()) return false; mob->getNavigation()->setCanOpenDoors(false); delete path; path = mob->getNavigation()->createPath(pos->x, pos->y, pos->z); diff --git a/Minecraft.World/AI/Goals/MoveTowardsRestrictionGoal.cpp b/Minecraft.World/AI/Goals/MoveTowardsRestrictionGoal.cpp index b8c2f9de6..cb52d4c3b 100644 --- a/Minecraft.World/AI/Goals/MoveTowardsRestrictionGoal.cpp +++ b/Minecraft.World/AI/Goals/MoveTowardsRestrictionGoal.cpp @@ -17,11 +17,12 @@ MoveTowardsRestrictionGoal::MoveTowardsRestrictionGoal(PathfinderMob* mob, bool MoveTowardsRestrictionGoal::canUse() { if (mob->isWithinRestriction()) return false; - Pos* towards = mob->getRestrictCenter(); - Vec3* pos = RandomPos::getPosTowards( + Pos* toward = mob->getRestrictCenter(); + Vec3 towards(toward->x, toward->y, toward->z); + auto pos = RandomPos::getPosTowards( std::dynamic_pointer_cast(mob->shared_from_this()), 16, - 7, Vec3::newTemp(towards->x, towards->y, towards->z)); - if (pos == NULL) return false; + 7, &towards); + if (!pos.has_value()) return false; wantedX = pos->x; wantedY = pos->y; wantedZ = pos->z; @@ -34,4 +35,4 @@ bool MoveTowardsRestrictionGoal::canContinueToUse() { void MoveTowardsRestrictionGoal::start() { mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier); -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/MoveTowardsTargetGoal.cpp b/Minecraft.World/AI/Goals/MoveTowardsTargetGoal.cpp index d00147b38..22babe6ca 100644 --- a/Minecraft.World/AI/Goals/MoveTowardsTargetGoal.cpp +++ b/Minecraft.World/AI/Goals/MoveTowardsTargetGoal.cpp @@ -20,10 +20,11 @@ bool MoveTowardsTargetGoal::canUse() { if (target.lock() == NULL) return false; if (target.lock()->distanceToSqr(mob->shared_from_this()) > within * within) return false; - Vec3* pos = RandomPos::getPosTowards( + Vec3 towards(target.lock()->x, target.lock()->y, target.lock()->z); + auto pos = RandomPos::getPosTowards( std::dynamic_pointer_cast(mob->shared_from_this()), 16, - 7, Vec3::newTemp(target.lock()->x, target.lock()->y, target.lock()->z)); - if (pos == NULL) return false; + 7, &towards); + if (!pos.has_value()) return false; wantedX = pos->x; wantedY = pos->y; wantedZ = pos->z; @@ -41,4 +42,4 @@ void MoveTowardsTargetGoal::stop() { target = std::weak_ptr(); } void MoveTowardsTargetGoal::start() { mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier); -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/NearestAttackableTargetGoal.cpp b/Minecraft.World/AI/Goals/NearestAttackableTargetGoal.cpp index bdb2d72e2..a1126b45e 100644 --- a/Minecraft.World/AI/Goals/NearestAttackableTargetGoal.cpp +++ b/Minecraft.World/AI/Goals/NearestAttackableTargetGoal.cpp @@ -55,9 +55,9 @@ bool NearestAttackableTargetGoal::canUse() { return false; double within = getFollowDistance(); + AABB mob_bb = mob->bb.grow(within, 4, within); std::vector >* entities = - mob->level->getEntitiesOfClass( - targetType, mob->bb->grow(within, 4, within), selector); + mob->level->getEntitiesOfClass(targetType, &mob_bb, selector); bool result = false; if (entities != NULL && !entities->empty()) { @@ -74,4 +74,4 @@ bool NearestAttackableTargetGoal::canUse() { void NearestAttackableTargetGoal::start() { mob->setTarget(target.lock()); TargetGoal::start(); -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/OcelotAttackGoal.cpp b/Minecraft.World/AI/Goals/OcelotAttackGoal.cpp index 5f56a3712..6753e64e3 100644 --- a/Minecraft.World/AI/Goals/OcelotAttackGoal.cpp +++ b/Minecraft.World/AI/Goals/OcelotAttackGoal.cpp @@ -40,7 +40,7 @@ void OcelotAttackGoal::tick() { mob->getLookControl()->setLookAt(target.lock(), 30, 30); double meleeRadiusSqr = (mob->bbWidth * 2) * (mob->bbWidth * 2); - double distSqr = mob->distanceToSqr(target.lock()->x, target.lock()->bb->y0, + double distSqr = mob->distanceToSqr(target.lock()->x, target.lock()->bb.y0, target.lock()->z); double speedModifier = Ocelot::WALK_SPEED_MOD; @@ -57,4 +57,4 @@ void OcelotAttackGoal::tick() { if (attackTime > 0) return; attackTime = 20; mob->doHurtTarget(target.lock()); -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/OfferFlowerGoal.cpp b/Minecraft.World/AI/Goals/OfferFlowerGoal.cpp index 01c1b3dbf..f78623fec 100644 --- a/Minecraft.World/AI/Goals/OfferFlowerGoal.cpp +++ b/Minecraft.World/AI/Goals/OfferFlowerGoal.cpp @@ -15,9 +15,9 @@ OfferFlowerGoal::OfferFlowerGoal(VillagerGolem* golem) { bool OfferFlowerGoal::canUse() { if (!golem->level->isDay()) return false; if (golem->getRandom()->nextInt(8000) != 0) return false; + AABB golem_bb = golem->bb.grow(6, 2, 6); villager = std::weak_ptr(std::dynamic_pointer_cast( - golem->level->getClosestEntityOfClass(typeid(Villager), - golem->bb->grow(6, 2, 6), + golem->level->getClosestEntityOfClass(typeid(Villager), &golem_bb, golem->shared_from_this()))); return villager.lock() != NULL; } @@ -39,4 +39,4 @@ void OfferFlowerGoal::stop() { void OfferFlowerGoal::tick() { golem->getLookControl()->setLookAt(villager.lock(), 30, 30); --_tick; -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/PanicGoal.cpp b/Minecraft.World/AI/Goals/PanicGoal.cpp index 9c32c1c6e..ec47e765f 100644 --- a/Minecraft.World/AI/Goals/PanicGoal.cpp +++ b/Minecraft.World/AI/Goals/PanicGoal.cpp @@ -14,10 +14,18 @@ PanicGoal::PanicGoal(PathfinderMob* mob, double speedModifier) { bool PanicGoal::canUse() { if (mob->getLastHurtByMob() == NULL && !mob->isOnFire()) return false; - Vec3* pos = RandomPos::getPos( + + // 4jcraft: stop entities from being eternally scared (referenced from + // smartcmd/MinecraftConsoles #519) + const int hurtTimeout = mob->getLastHurtByMobTimestamp(); + static thread_local Random random; + const int panicDuration = random.nextInt(41) + 60; + if (mob->tickCount - hurtTimeout > panicDuration) return false; + + auto pos = RandomPos::getPos( std::dynamic_pointer_cast(mob->shared_from_this()), 5, 4); - if (pos == NULL) return false; + if (!pos.has_value()) return false; posX = pos->x; posY = pos->y; posZ = pos->z; @@ -28,4 +36,4 @@ void PanicGoal::start() { mob->getNavigation()->moveTo(posX, posY, posZ, speedModifier); } -bool PanicGoal::canContinueToUse() { return !mob->getNavigation()->isDone(); } \ No newline at end of file +bool PanicGoal::canContinueToUse() { return !mob->getNavigation()->isDone(); } diff --git a/Minecraft.World/AI/Goals/PlayGoal.cpp b/Minecraft.World/AI/Goals/PlayGoal.cpp index 4c933d513..b748d7519 100644 --- a/Minecraft.World/AI/Goals/PlayGoal.cpp +++ b/Minecraft.World/AI/Goals/PlayGoal.cpp @@ -23,9 +23,9 @@ bool PlayGoal::canUse() { if (mob->getAge() >= 0) return false; if (mob->getRandom()->nextInt(400) != 0) return false; + AABB mob_bb = mob->bb.grow(6, 3, 6); std::vector >* children = - mob->level->getEntitiesOfClass(typeid(Villager), - mob->bb->grow(6, 3, 6)); + mob->level->getEntitiesOfClass(typeid(Villager), &mob_bb); double closestDistSqr = std::numeric_limits::max(); // for (Entity c : children) for (AUTO_VAR(it, children->begin()); it != children->end(); ++it) { @@ -43,10 +43,10 @@ bool PlayGoal::canUse() { delete children; if (followFriend.lock() == NULL) { - Vec3* pos = RandomPos::getPos( + auto pos = RandomPos::getPos( std::dynamic_pointer_cast(mob->shared_from_this()), 16, 3); - if (pos == NULL) return false; + if (!pos.has_value()) return false; } return true; } @@ -72,11 +72,11 @@ void PlayGoal::tick() { mob->getNavigation()->moveTo(followFriend.lock(), speedModifier); } else { if (mob->getNavigation()->isDone()) { - Vec3* pos = + auto pos = RandomPos::getPos(std::dynamic_pointer_cast( mob->shared_from_this()), 16, 3); - if (pos == NULL) return; + if (!pos.has_value()) return; mob->getNavigation()->moveTo(pos->x, pos->y, pos->z, speedModifier); } } diff --git a/Minecraft.World/AI/Goals/RandomStrollGoal.cpp b/Minecraft.World/AI/Goals/RandomStrollGoal.cpp index ba81c5442..2e95918bd 100644 --- a/Minecraft.World/AI/Goals/RandomStrollGoal.cpp +++ b/Minecraft.World/AI/Goals/RandomStrollGoal.cpp @@ -20,11 +20,11 @@ bool RandomStrollGoal::canUse() { // fenced-off region far enough to determine we can despawn them if (mob->getNoActionTime() < SharedConstants::TICKS_PER_SECOND * 5) { if (mob->getRandom()->nextInt(120) == 0) { - Vec3* pos = + auto pos = RandomPos::getPos(std::dynamic_pointer_cast( mob->shared_from_this()), 10, 7); - if (pos == NULL) return false; + if (!pos.has_value()) return false; wantedX = pos->x; wantedY = pos->y; wantedZ = pos->z; @@ -38,11 +38,11 @@ bool RandomStrollGoal::canUse() { // a given area and so waiting around is just wasting time if (mob->isExtraWanderingEnabled()) { - Vec3* pos = + auto pos = RandomPos::getPos(std::dynamic_pointer_cast( mob->shared_from_this()), 10, 7, mob->getWanderingQuadrant()); - if (pos == NULL) return false; + if (!pos.has_value()) return false; wantedX = pos->x; wantedY = pos->y; wantedZ = pos->z; @@ -58,4 +58,4 @@ bool RandomStrollGoal::canContinueToUse() { void RandomStrollGoal::start() { mob->getNavigation()->moveTo(wantedX, wantedY, wantedZ, speedModifier); -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/RangedAttackGoal.cpp b/Minecraft.World/AI/Goals/RangedAttackGoal.cpp index e58c59d1c..2c7f22d9e 100644 --- a/Minecraft.World/AI/Goals/RangedAttackGoal.cpp +++ b/Minecraft.World/AI/Goals/RangedAttackGoal.cpp @@ -67,7 +67,7 @@ void RangedAttackGoal::tick() { if (target.lock() == NULL) return; double targetDistSqr = mob->distanceToSqr( - target.lock()->x, target.lock()->bb->y0, target.lock()->z); + target.lock()->x, target.lock()->bb.y0, target.lock()->z); bool canSee = mob->getSensing()->canSee(target.lock()); if (canSee) { @@ -100,4 +100,4 @@ void RangedAttackGoal::tick() { attackTime = Mth::floor(dist * (attackIntervalMax - attackIntervalMin) + attackIntervalMin); } -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/RunAroundLikeCrazyGoal.cpp b/Minecraft.World/AI/Goals/RunAroundLikeCrazyGoal.cpp index 84c35dd41..c24d376cd 100644 --- a/Minecraft.World/AI/Goals/RunAroundLikeCrazyGoal.cpp +++ b/Minecraft.World/AI/Goals/RunAroundLikeCrazyGoal.cpp @@ -17,10 +17,10 @@ RunAroundLikeCrazyGoal::RunAroundLikeCrazyGoal(EntityHorse* mob, bool RunAroundLikeCrazyGoal::canUse() { if (horse->isTamed() || horse->rider.lock() == NULL) return false; - Vec3* pos = RandomPos::getPos( + auto pos = RandomPos::getPos( std::dynamic_pointer_cast(horse->shared_from_this()), 5, 4); - if (pos == NULL) return false; + if (!pos.has_value()) return false; posX = pos->x; posY = pos->y; posZ = pos->z; @@ -57,4 +57,4 @@ void RunAroundLikeCrazyGoal::tick() { horse->level->broadcastEntityEvent(horse->shared_from_this(), EntityEvent::TAMING_FAILED); } -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/SitGoal.cpp b/Minecraft.World/AI/Goals/SitGoal.cpp index 6a7a3fa14..2ec85aff7 100644 --- a/Minecraft.World/AI/Goals/SitGoal.cpp +++ b/Minecraft.World/AI/Goals/SitGoal.cpp @@ -38,4 +38,4 @@ void SitGoal::start() { void SitGoal::stop() { mob->setSitting(false); } -void SitGoal::wantToSit(bool _wantToSit) { this->_wantToSit = _wantToSit; } \ No newline at end of file +void SitGoal::wantToSit(bool _wantToSit) { this->_wantToSit = _wantToSit; } diff --git a/Minecraft.World/AI/Goals/TakeFlowerGoal.cpp b/Minecraft.World/AI/Goals/TakeFlowerGoal.cpp index 455c84c8b..7c3a49f44 100644 --- a/Minecraft.World/AI/Goals/TakeFlowerGoal.cpp +++ b/Minecraft.World/AI/Goals/TakeFlowerGoal.cpp @@ -22,9 +22,10 @@ bool TakeFlowerGoal::canUse() { if (villager->getAge() >= 0) return false; if (!villager->level->isDay()) return false; + AABB villager_bb = villager->bb.grow(6, 2, 6); std::vector >* golems = villager->level->getEntitiesOfClass(typeid(VillagerGolem), - villager->bb->grow(6, 2, 6)); + &villager_bb); if (golems->size() == 0) { delete golems; return false; @@ -72,4 +73,4 @@ void TakeFlowerGoal::tick() { villager->getNavigation()->stop(); } } -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/TargetGoal.cpp b/Minecraft.World/AI/Goals/TargetGoal.cpp index 4c424e03e..5d7751ee7 100644 --- a/Minecraft.World/AI/Goals/TargetGoal.cpp +++ b/Minecraft.World/AI/Goals/TargetGoal.cpp @@ -115,4 +115,4 @@ bool TargetGoal::canReach(std::shared_ptr target) { int zz = last->z - Mth::floor(target->z); delete path; return xx * xx + zz * zz <= 1.5 * 1.5; -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Goals/TemptGoal.cpp b/Minecraft.World/AI/Goals/TemptGoal.cpp index 82738d257..c0b06eb93 100644 --- a/Minecraft.World/AI/Goals/TemptGoal.cpp +++ b/Minecraft.World/AI/Goals/TemptGoal.cpp @@ -84,4 +84,4 @@ void TemptGoal::tick() { mob->getNavigation()->moveTo(player.lock(), speedModifier); } -bool TemptGoal::isRunning() { return _isRunning; } \ No newline at end of file +bool TemptGoal::isRunning() { return _isRunning; } diff --git a/Minecraft.World/AI/Goals/TradeWithPlayerGoal.cpp b/Minecraft.World/AI/Goals/TradeWithPlayerGoal.cpp index cfb14d6e0..61219b4d5 100644 --- a/Minecraft.World/AI/Goals/TradeWithPlayerGoal.cpp +++ b/Minecraft.World/AI/Goals/TradeWithPlayerGoal.cpp @@ -38,4 +38,4 @@ bool TradeWithPlayerGoal::canUse() { void TradeWithPlayerGoal::start() { mob->getNavigation()->stop(); } -void TradeWithPlayerGoal::stop() { mob->setTradingPlayer(nullptr); } \ No newline at end of file +void TradeWithPlayerGoal::stop() { mob->setTradingPlayer(nullptr); } diff --git a/Minecraft.World/AI/Navigation/Path.cpp b/Minecraft.World/AI/Navigation/Path.cpp index eaef6b8a9..672839665 100644 --- a/Minecraft.World/AI/Navigation/Path.cpp +++ b/Minecraft.World/AI/Navigation/Path.cpp @@ -48,17 +48,17 @@ int Path::getIndex() { return index; } void Path::setIndex(int index) { this->index = index; } -Vec3* Path::getPos(std::shared_ptr e, int index) { +Vec3 Path::getPos(std::shared_ptr e, int index) { double x = nodes[index]->x + (int)(e->bbWidth + 1) * 0.5; double y = nodes[index]->y; double z = nodes[index]->z + (int)(e->bbWidth + 1) * 0.5; - return Vec3::newTemp(x, y, z); + return Vec3(x, y, z); } -Vec3* Path::currentPos(std::shared_ptr e) { return getPos(e, index); } +Vec3 Path::currentPos(std::shared_ptr e) { return getPos(e, index); } -Vec3* Path::currentPos() { - return Vec3::newTemp(nodes[index]->x, nodes[index]->y, nodes[index]->z); +Vec3 Path::currentPos() { + return Vec3(nodes[index]->x, nodes[index]->y, nodes[index]->z); } bool Path::sameAs(Path* path) { @@ -83,4 +83,4 @@ bool Path::endsInXZ(Vec3* pos) { Node* lastNode = last(); if (lastNode == NULL) return false; return lastNode->x == (int)pos->x && lastNode->z == (int)pos->z; -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Navigation/Path.h b/Minecraft.World/AI/Navigation/Path.h index 0e5697959..ab0a013be 100644 --- a/Minecraft.World/AI/Navigation/Path.h +++ b/Minecraft.World/AI/Navigation/Path.h @@ -20,10 +20,10 @@ public: void setSize(int length); int getIndex(); void setIndex(int index); - Vec3* getPos(std::shared_ptr e, int index); + Vec3 getPos(std::shared_ptr e, int index); NodeArray Getarray(); - Vec3* currentPos(std::shared_ptr e); - Vec3* currentPos(); + Vec3 currentPos(std::shared_ptr e); + Vec3 currentPos(); bool sameAs(Path* path); bool endsIn(Vec3* pos); bool endsInXZ(Vec3* pos); diff --git a/Minecraft.World/AI/Navigation/PathFinder.cpp b/Minecraft.World/AI/Navigation/PathFinder.cpp index 0fe650e3b..429b99302 100644 --- a/Minecraft.World/AI/Navigation/PathFinder.cpp +++ b/Minecraft.World/AI/Navigation/PathFinder.cpp @@ -33,7 +33,7 @@ PathFinder::~PathFinder() { } Path* PathFinder::findPath(Entity* from, Entity* to, float maxDist) { - return findPath(from, to->x, to->bb->y0, to->z, maxDist); + return findPath(from, to->x, to->bb.y0, to->z, maxDist); } Path* PathFinder::findPath(Entity* from, int x, int y, int z, float maxDist) { @@ -46,9 +46,9 @@ Path* PathFinder::findPath(Entity* e, double xt, double yt, double zt, nodes.clear(); bool resetAvoidWater = avoidWater; - int startY = Mth::floor(e->bb->y0 + 0.5f); + int startY = Mth::floor(e->bb.y0 + 0.5f); if (canFloat && e->isInWater()) { - startY = (int)(e->bb->y0); + startY = (int)(e->bb.y0); int tileId = level->getTile((int)Mth::floor(e->x), startY, (int)Mth::floor(e->z)); while (tileId == Tile::water_Id || tileId == Tile::calmWater_Id) { @@ -59,9 +59,9 @@ Path* PathFinder::findPath(Entity* e, double xt, double yt, double zt, resetAvoidWater = avoidWater; avoidWater = false; } else - startY = Mth::floor(e->bb->y0 + 0.5f); + startY = Mth::floor(e->bb.y0 + 0.5f); - Node* from = getNode((int)floor(e->bb->x0), startY, (int)floor(e->bb->z0)); + Node* from = getNode((int)floor(e->bb.x0), startY, (int)floor(e->bb.z0)); Node* to = getNode((int)floor(xt - e->bbWidth / 2), (int)floor(yt), (int)floor(zt - e->bbWidth / 2)); @@ -283,4 +283,4 @@ Path* PathFinder::reconstruct_path(Node* from, Node* to) { Path* ret = new Path(nodes); delete[] nodes.data; return ret; -} \ No newline at end of file +} diff --git a/Minecraft.World/AI/Navigation/PathNavigation.cpp b/Minecraft.World/AI/Navigation/PathNavigation.cpp index a80e4d4ef..fc03d1948 100644 --- a/Minecraft.World/AI/Navigation/PathNavigation.cpp +++ b/Minecraft.World/AI/Navigation/PathNavigation.cpp @@ -20,7 +20,7 @@ PathNavigation::PathNavigation(Mob* mob, Level* level) { avoidSun = false; _tick = 0; lastStuckCheck = 0; - lastStuckCheckPos = Vec3::newPermanent(0, 0, 0); + lastStuckCheckPos = Vec3(0, 0, 0); _canPassDoors = true; _canOpenDoors = false; avoidWater = false; @@ -29,7 +29,6 @@ PathNavigation::PathNavigation(Mob* mob, Level* level) { PathNavigation::~PathNavigation() { if (path != NULL) delete path; - delete lastStuckCheckPos; } void PathNavigation::setAvoidWater(bool avoidWater) { @@ -110,11 +109,11 @@ bool PathNavigation::moveTo(Path* newPath, double speedModifier) { if (path->getSize() == 0) return false; this->speedModifier = speedModifier; - Vec3* mobPos = getTempMobPos(); + Vec3 mobPos = getTempMobPos(); lastStuckCheck = _tick; - lastStuckCheckPos->x = mobPos->x; - lastStuckCheckPos->y = mobPos->y; - lastStuckCheckPos->z = mobPos->z; + lastStuckCheckPos.x = mobPos.x; + lastStuckCheckPos.y = mobPos.y; + lastStuckCheckPos.z = mobPos.z; return true; } @@ -127,20 +126,19 @@ void PathNavigation::tick() { if (canUpdatePath()) updatePath(); if (isDone()) return; - Vec3* target = path->currentPos(mob->shared_from_this()); - if (target == NULL) return; + Vec3 target = path->currentPos(mob->shared_from_this()); - mob->getMoveControl()->setWantedPosition(target->x, target->y, target->z, + mob->getMoveControl()->setWantedPosition(target.x, target.y, target.z, speedModifier); } void PathNavigation::updatePath() { - Vec3* mobPos = getTempMobPos(); + Vec3 mobPos = getTempMobPos(); // find first elevations in path int firstElevation = path->getSize(); for (int i = path->getIndex(); path != NULL && i < path->getSize(); ++i) { - if ((int)path->get(i)->y != (int)mobPos->y) { + if ((int)path->get(i)->y != (int)mobPos.y) { firstElevation = i; break; } @@ -150,8 +148,8 @@ void PathNavigation::updatePath() { // check canWalkDirectly also) possibly only check next as well float waypointRadiusSqr = mob->bbWidth * mob->bbWidth; for (int i = path->getIndex(); i < firstElevation; ++i) { - Vec3* pathPos = path->getPos(mob->shared_from_this(), i); - if (mobPos->distanceToSqr(pathPos) < waypointRadiusSqr) { + Vec3 pathPos = path->getPos(mob->shared_from_this(), i); + if (mobPos.distanceToSqr(pathPos) < waypointRadiusSqr) { path->setIndex(i + 1); } } @@ -161,8 +159,8 @@ void PathNavigation::updatePath() { int sy = (int)mob->bbHeight + 1; int sz = sx; for (int i = firstElevation - 1; i >= path->getIndex(); --i) { - if (canMoveDirectly(mobPos, path->getPos(mob->shared_from_this(), i), - sx, sy, sz)) { + Vec3 mob_pos = path->getPos(mob->shared_from_this(), i); + if (canMoveDirectly(&mobPos, &mob_pos, sx, sy, sz)) { path->setIndex(i); break; } @@ -170,11 +168,11 @@ void PathNavigation::updatePath() { // stuck detection (probably pushed off path) if (_tick - lastStuckCheck > 100) { - if (mobPos->distanceToSqr(lastStuckCheckPos) < 1.5 * 1.5) stop(); + if (mobPos.distanceToSqr(lastStuckCheckPos) < 1.5 * 1.5) stop(); lastStuckCheck = _tick; - lastStuckCheckPos->x = mobPos->x; - lastStuckCheckPos->y = mobPos->y; - lastStuckCheckPos->z = mobPos->z; + lastStuckCheckPos.x = mobPos.x; + lastStuckCheckPos.y = mobPos.y; + lastStuckCheckPos.z = mobPos.z; } } @@ -185,14 +183,14 @@ void PathNavigation::stop() { path = NULL; } -Vec3* PathNavigation::getTempMobPos() { - return Vec3::newTemp(mob->x, getSurfaceY(), mob->z); +Vec3 PathNavigation::getTempMobPos() { + return Vec3(mob->x, getSurfaceY(), mob->z); } int PathNavigation::getSurfaceY() { - if (!mob->isInWater() || !canFloat) return (int)(mob->bb->y0 + 0.5); + if (!mob->isInWater() || !canFloat) return (int)(mob->bb.y0 + 0.5); - int surface = (int)(mob->bb->y0); + int surface = (int)(mob->bb.y0); int tileId = level->getTile(Mth::floor(mob->x), surface, Mth::floor(mob->z)); int steps = 0; @@ -200,7 +198,7 @@ int PathNavigation::getSurfaceY() { ++surface; tileId = level->getTile(Mth::floor(mob->x), surface, Mth::floor(mob->z)); - if (++steps > 16) return (int)(mob->bb->y0); + if (++steps > 16) return (int)(mob->bb.y0); } return surface; } @@ -214,7 +212,7 @@ bool PathNavigation::isInLiquid() { } void PathNavigation::trimPathFromSun() { - if (level->canSeeSky(Mth::floor(mob->x), (int)(mob->bb->y0 + 0.5), + if (level->canSeeSky(Mth::floor(mob->x), (int)(mob->bb.y0 + 0.5), Mth::floor(mob->z))) return; @@ -329,4 +327,4 @@ bool PathNavigation::canWalkAbove(int startX, int startY, int startZ, int sx, return true; } -void PathNavigation::setLevel(Level* level) { this->level = level; } \ No newline at end of file +void PathNavigation::setLevel(Level* level) { this->level = level; } diff --git a/Minecraft.World/AI/Navigation/PathNavigation.h b/Minecraft.World/AI/Navigation/PathNavigation.h index d9d731532..0d5843281 100644 --- a/Minecraft.World/AI/Navigation/PathNavigation.h +++ b/Minecraft.World/AI/Navigation/PathNavigation.h @@ -14,7 +14,7 @@ private: bool avoidSun; int _tick; int lastStuckCheck; - Vec3* lastStuckCheckPos; + Vec3 lastStuckCheckPos; bool _canPassDoors; bool _canOpenDoors; @@ -52,7 +52,7 @@ public: void stop(); private: - Vec3* getTempMobPos(); + Vec3 getTempMobPos(); int getSurfaceY(); bool canUpdatePath(); bool isInLiquid(); @@ -67,4 +67,4 @@ public: // 4J Added override to update ai elements when loading entity from // schematics void setLevel(Level* level); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/AI/Navigation/RandomPos.cpp b/Minecraft.World/AI/Navigation/RandomPos.cpp index d092d0e82..4025cc9f3 100644 --- a/Minecraft.World/AI/Navigation/RandomPos.cpp +++ b/Minecraft.World/AI/Navigation/RandomPos.cpp @@ -2,34 +2,38 @@ #include "../../Headers/net.minecraft.world.entity.h" #include "../../Headers/net.minecraft.world.phys.h" #include "RandomPos.h" +#include -Vec3* RandomPos::tempDir = Vec3::newPermanent(0, 0, 0); +Vec3 RandomPos::tempDir = Vec3(0, 0, 0); -Vec3* RandomPos::getPos(std::shared_ptr mob, int xzDist, - int yDist, int quadrant /*=-1*/) // 4J - added quadrant +std::optional RandomPos::getPos( + std::shared_ptr mob, int xzDist, int yDist, + int quadrant /*=-1*/) // 4J - added quadrant { return generateRandomPos(mob, xzDist, yDist, NULL, quadrant); } -Vec3* RandomPos::getPosTowards(std::shared_ptr mob, int xzDist, - int yDist, Vec3* towardsPos) { - tempDir->x = towardsPos->x - mob->x; - tempDir->y = towardsPos->y - mob->y; - tempDir->z = towardsPos->z - mob->z; - return generateRandomPos(mob, xzDist, yDist, tempDir); +std::optional RandomPos::getPosTowards(std::shared_ptr mob, + int xzDist, int yDist, + Vec3* towardsPos) { + tempDir.x = towardsPos->x - mob->x; + tempDir.y = towardsPos->y - mob->y; + tempDir.z = towardsPos->z - mob->z; + return generateRandomPos(mob, xzDist, yDist, &tempDir); } -Vec3* RandomPos::getPosAvoid(std::shared_ptr mob, int xzDist, - int yDist, Vec3* avoidPos) { - tempDir->x = mob->x - avoidPos->x; - tempDir->y = mob->y - avoidPos->y; - tempDir->z = mob->z - avoidPos->z; - return generateRandomPos(mob, xzDist, yDist, tempDir); +std::optional RandomPos::getPosAvoid(std::shared_ptr mob, + int xzDist, int yDist, + Vec3* avoidPos) { + tempDir.x = mob->x - avoidPos->x; + tempDir.y = mob->y - avoidPos->y; + tempDir.z = mob->z - avoidPos->z; + return generateRandomPos(mob, xzDist, yDist, &tempDir); } -Vec3* RandomPos::generateRandomPos(std::shared_ptr mob, - int xzDist, int yDist, Vec3* dir, - int quadrant /*=-1*/) // 4J - added quadrant +std::optional RandomPos::generateRandomPos( + std::shared_ptr mob, int xzDist, int yDist, Vec3* dir, + int quadrant /*=-1*/) // 4J - added quadrant { Random* random = mob->getRandom(); bool hasBest = false; @@ -81,8 +85,8 @@ Vec3* RandomPos::generateRandomPos(std::shared_ptr mob, } } if (hasBest) { - return Vec3::newTemp(xBest, yBest, zBest); + return Vec3(xBest, yBest, zBest); } - return NULL; -} \ No newline at end of file + return std::nullopt; +} diff --git a/Minecraft.World/AI/Navigation/RandomPos.h b/Minecraft.World/AI/Navigation/RandomPos.h index 8baa8e50f..b7bd8f394 100644 --- a/Minecraft.World/AI/Navigation/RandomPos.h +++ b/Minecraft.World/AI/Navigation/RandomPos.h @@ -1,21 +1,25 @@ #pragma once +#include class PathfinderMob; class RandomPos { private: - static Vec3* tempDir; + static Vec3 tempDir; public: - static Vec3* getPos(std::shared_ptr mob, int xzDist, - int yDist, int quadrant = -1); // 4J added quadrant - static Vec3* getPosTowards(std::shared_ptr mob, int xzDist, - int yDist, Vec3* towardsPos); - static Vec3* getPosAvoid(std::shared_ptr mob, int xzDist, - int yDist, Vec3* avoidPos); + static std::optional getPos(std::shared_ptr mob, + int xzDist, int yDist, + int quadrant = -1); // 4J added quadrant + static std::optional getPosTowards(std::shared_ptr mob, + int xzDist, int yDist, + Vec3* towardsPos); + static std::optional getPosAvoid(std::shared_ptr mob, + int xzDist, int yDist, + Vec3* avoidPos); private: - static Vec3* generateRandomPos(std::shared_ptr mob, - int xzDist, int yDist, Vec3* dir, - int quadrant = -1); // 4J added quadrant -}; \ No newline at end of file + static std::optional generateRandomPos( + std::shared_ptr mob, int xzDist, int yDist, Vec3* dir, + int quadrant = -1); // 4J added quadrant +}; diff --git a/Minecraft.World/Blocks/BasePressurePlateTile.cpp b/Minecraft.World/Blocks/BasePressurePlateTile.cpp index 740e0a871..212fbb914 100644 --- a/Minecraft.World/Blocks/BasePressurePlateTile.cpp +++ b/Minecraft.World/Blocks/BasePressurePlateTile.cpp @@ -6,6 +6,8 @@ #include "../Headers/net.minecraft.h" #include "../Headers/net.minecraft.world.h" #include "BasePressurePlateTile.h" +#include +#include "Util/AABB.h" BasePressurePlateTile::BasePressurePlateTile(int id, const std::wstring& tex, Material* material) @@ -38,8 +40,9 @@ int BasePressurePlateTile::getTickDelay(Level* level) { return SharedConstants::TICKS_PER_SECOND; } -AABB* BasePressurePlateTile::getAABB(Level* level, int x, int y, int z) { - return NULL; +std::optional BasePressurePlateTile::getAABB(Level* level, int x, int y, + int z) { + return std::nullopt; } bool BasePressurePlateTile::isSolidRender(bool isServerLevel) { return false; } @@ -111,9 +114,9 @@ void BasePressurePlateTile::checkPressed(Level* level, int x, int y, int z, } } -AABB* BasePressurePlateTile::getSensitiveAABB(int x, int y, int z) { +AABB BasePressurePlateTile::getSensitiveAABB(int x, int y, int z) { float b = 2 / 16.0f; - return AABB::newTemp(x + b, y, z + b, x + 1 - b, y + 0.25, z + 1 - b); + return AABB(x + b, y, z + b, x + 1 - b, y + 0.25, z + 1 - b); } void BasePressurePlateTile::onRemove(Level* level, int x, int y, int z, int id, @@ -160,4 +163,4 @@ int BasePressurePlateTile::getPistonPushReaction() { void BasePressurePlateTile::registerIcons(IconRegister* iconRegister) { icon = iconRegister->registerIcon(texture); -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/BasePressurePlateTile.h b/Minecraft.World/Blocks/BasePressurePlateTile.h index 62d8de583..254f72e1d 100644 --- a/Minecraft.World/Blocks/BasePressurePlateTile.h +++ b/Minecraft.World/Blocks/BasePressurePlateTile.h @@ -20,7 +20,7 @@ protected: public: virtual int getTickDelay(Level* level); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual bool isSolidRender(bool isServerLevel = false); virtual bool blocksLight(); virtual bool isCubeShaped(); @@ -33,7 +33,7 @@ public: protected: virtual void checkPressed(Level* level, int x, int y, int z, int oldSignal); - virtual AABB* getSensitiveAABB(int x, int y, int z); + virtual AABB getSensitiveAABB(int x, int y, int z); public: virtual void onRemove(Level* level, int x, int y, int z, int id, int data); @@ -56,4 +56,4 @@ protected: public: virtual void registerIcons(IconRegister* iconRegister); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/BaseRailTile.cpp b/Minecraft.World/Blocks/BaseRailTile.cpp index 6478c61bb..31332510e 100644 --- a/Minecraft.World/Blocks/BaseRailTile.cpp +++ b/Minecraft.World/Blocks/BaseRailTile.cpp @@ -3,6 +3,7 @@ #include "../Headers/net.minecraft.world.level.h" #include "../Headers/net.minecraft.world.h" #include "BaseRailTile.h" +#include BaseRailTile::Rail::Rail(Level* level, int x, int y, int z) { this->level = level; @@ -311,7 +312,7 @@ BaseRailTile::BaseRailTile(int id, bool usesDataBit) bool BaseRailTile::isUsesDataBit() { return usesDataBit; } -AABB* BaseRailTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional BaseRailTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } bool BaseRailTile::blocksLight() { return false; } @@ -415,4 +416,4 @@ void BaseRailTile::onRemove(Level* level, int x, int y, int z, int id, level->updateNeighborsAt(x, y, z, id); level->updateNeighborsAt(x, y - 1, z, id); } -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/BaseRailTile.h b/Minecraft.World/Blocks/BaseRailTile.h index e352bd3ca..23a7b45af 100644 --- a/Minecraft.World/Blocks/BaseRailTile.h +++ b/Minecraft.World/Blocks/BaseRailTile.h @@ -70,7 +70,7 @@ public: using Tile::getResourceCount; bool isUsesDataBit(); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual bool blocksLight(); virtual bool isSolidRender(bool isServerLevel = false); virtual HitResult* clip(Level* level, int xt, int yt, int zt, Vec3* a, diff --git a/Minecraft.World/Blocks/ButtonTile.cpp b/Minecraft.World/Blocks/ButtonTile.cpp index 73ac3122a..bf0cb742e 100644 --- a/Minecraft.World/Blocks/ButtonTile.cpp +++ b/Minecraft.World/Blocks/ButtonTile.cpp @@ -5,6 +5,7 @@ #include "../Headers/net.minecraft.world.phys.h" #include "../Headers/net.minecraft.h" #include "ButtonTile.h" +#include #include "../Util/SoundTypes.h" ButtonTile::ButtonTile(int id, bool sensitive) @@ -20,7 +21,7 @@ Icon* ButtonTile::getTexture(int face, int data) { return Tile::stone->getTexture(Facing::UP); } -AABB* ButtonTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional ButtonTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } int ButtonTile::getTickDelay(Level* level) { return sensitive ? 30 : 20; } @@ -261,9 +262,12 @@ void ButtonTile::checkPressed(Level* level, int x, int y, int z) { updateShape(data); Tile::ThreadStorage* tls = m_tlsShape; - std::vector >* entities = level->getEntitiesOfClass( - typeid(Arrow), AABB::newTemp(x + tls->xx0, y + tls->yy0, z + tls->zz0, - x + tls->xx1, y + tls->yy1, z + tls->zz1)); + AABB arrow_aabb{ + x + tls->xx0, y + tls->yy0, z + tls->zz0, + x + tls->xx1, y + tls->yy1, z + tls->zz1, + }; + std::vector >* entities = + level->getEntitiesOfClass(typeid(Arrow), &arrow_aabb); shouldBePressed = !entities->empty(); delete entities; diff --git a/Minecraft.World/Blocks/ButtonTile.h b/Minecraft.World/Blocks/ButtonTile.h index da0f6f757..570dc1be0 100644 --- a/Minecraft.World/Blocks/ButtonTile.h +++ b/Minecraft.World/Blocks/ButtonTile.h @@ -17,7 +17,7 @@ protected: public: Icon* getTexture(int face, int data); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual int getTickDelay(Level* level); virtual bool blocksLight(); virtual bool isSolidRender(bool isServerLevel = false); @@ -74,4 +74,4 @@ public: // 4J Added so we can check before we try to add a tile to the tick list if // it's actually going to do seomthing virtual bool shouldTileTick(Level* level, int x, int y, int z); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/CactusTile.cpp b/Minecraft.World/Blocks/CactusTile.cpp index 34469f773..229c52e6a 100644 --- a/Minecraft.World/Blocks/CactusTile.cpp +++ b/Minecraft.World/Blocks/CactusTile.cpp @@ -33,14 +33,14 @@ void CactusTile::tick(Level* level, int x, int y, int z, Random* random) { } } -AABB* CactusTile::getAABB(Level* level, int x, int y, int z) { +std::optional CactusTile::getAABB(Level* level, int x, int y, int z) { float r = 1 / 16.0f; - return AABB::newTemp(x + r, y, z + r, x + 1 - r, y + 1 - r, z + 1 - r); + return AABB{x + r, static_cast(y), z + r, x + 1 - r, y + 1 - r, z + 1 - r}; } -AABB* CactusTile::getTileAABB(Level* level, int x, int y, int z) { +AABB CactusTile::getTileAABB(Level* level, int x, int y, int z) { float r = 1 / 16.0f; - return AABB::newTemp(x + r, y, z + r, x + 1 - r, y + 1, z + 1 - r); + return AABB(x + r, y, z + r, x + 1 - r, y + 1, z + 1 - r); } Icon* CactusTile::getTexture(int face, int data) { diff --git a/Minecraft.World/Blocks/CactusTile.h b/Minecraft.World/Blocks/CactusTile.h index a34b596d0..c35dc18a2 100644 --- a/Minecraft.World/Blocks/CactusTile.h +++ b/Minecraft.World/Blocks/CactusTile.h @@ -20,8 +20,8 @@ protected: public: virtual void tick(Level* level, int x, int y, int z, Random* random); - virtual AABB* getAABB(Level* level, int x, int y, int z); - virtual AABB* getTileAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); + virtual AABB getTileAABB(Level* level, int x, int y, int z); virtual Icon* getTexture(int face, int data); virtual bool isCubeShaped(); virtual bool isSolidRender(bool isServerLevel = false); @@ -37,4 +37,4 @@ public: // 4J Added so we can check before we try to add a tile to the tick list if // it's actually going to do seomthing virtual bool shouldTileTick(Level* level, int x, int y, int z); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/CakeTile.cpp b/Minecraft.World/Blocks/CakeTile.cpp index b0d8d8ee9..53e2e41e3 100644 --- a/Minecraft.World/Blocks/CakeTile.cpp +++ b/Minecraft.World/Blocks/CakeTile.cpp @@ -34,20 +34,20 @@ void CakeTile::updateDefaultShape() { this->setShape(r, 0, r, 1 - r, h, 1 - r); } -AABB* CakeTile::getAABB(Level* level, int x, int y, int z) { +std::optional CakeTile::getAABB(Level* level, int x, int y, int z) { int d = level->getData(x, y, z); float r = 1 / 16.0f; float r2 = (1 + d * 2) / 16.0f; float h = 8 / 16.0f; - return AABB::newTemp(x + r2, y, z + r, x + 1 - r, y + h - r, z + 1 - r); + return AABB{x + r2, static_cast(y), z + r, x + 1 - r, y + h - r, z + 1 - r}; } -AABB* CakeTile::getTileAABB(Level* level, int x, int y, int z) { +AABB CakeTile::getTileAABB(Level* level, int x, int y, int z) { int d = level->getData(x, y, z); float r = 1 / 16.0f; float r2 = (1 + d * 2) / 16.0f; float h = 8 / 16.0f; - return AABB::newTemp(x + r2, y, z + r, x + 1 - r, y + h, z + 1 - r); + return AABB(x + r2, y, z + r, x + 1 - r, y + h, z + 1 - r); } Icon* CakeTile::getTexture(int face, int data) { @@ -124,4 +124,4 @@ int CakeTile::getResource(int data, Random* random, int playerBonusLevel) { int CakeTile::cloneTileId(Level* level, int x, int y, int z) { return Item::cake_Id; -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/CakeTile.h b/Minecraft.World/Blocks/CakeTile.h index 4f201e0a0..b2f2a3655 100644 --- a/Minecraft.World/Blocks/CakeTile.h +++ b/Minecraft.World/Blocks/CakeTile.h @@ -24,8 +24,8 @@ protected: std::shared_ptr forceEntity = std::shared_ptr< TileEntity>()); // 4J added forceData, forceEntity param virtual void updateDefaultShape(); - virtual AABB* getAABB(Level* level, int x, int y, int z); - virtual AABB* getTileAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); + virtual AABB getTileAABB(Level* level, int x, int y, int z); virtual Icon* getTexture(int face, int data); //@Override void registerIcons(IconRegister* iconRegister); @@ -49,4 +49,4 @@ public: virtual int getResourceCount(Random* random); virtual int getResource(int data, Random* random, int playerBonusLevel); int cloneTileId(Level* level, int x, int y, int z); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/ChestTile.cpp b/Minecraft.World/Blocks/ChestTile.cpp index 9ac3c5364..4a866151c 100644 --- a/Minecraft.World/Blocks/ChestTile.cpp +++ b/Minecraft.World/Blocks/ChestTile.cpp @@ -345,8 +345,9 @@ int ChestTile::getDirectSignal(LevelSource* level, int x, int y, int z, } bool ChestTile::isCatSittingOnChest(Level* level, int x, int y, int z) { - std::vector >* entities = level->getEntitiesOfClass( - typeid(Ocelot), AABB::newTemp(x, y + 1, z, x + 1, y + 2, z + 1)); + AABB ocelot_aabb(x, y + 1, z, x + 1, y + 2, z + 1); + std::vector >* entities = + level->getEntitiesOfClass(typeid(Ocelot), &ocelot_aabb); for (AUTO_VAR(it, entities->begin()); it != entities->end(); ++it) { std::shared_ptr ocelot = std::dynamic_pointer_cast(*it); if (ocelot->isSitting()) { diff --git a/Minecraft.World/Blocks/CocoaTile.cpp b/Minecraft.World/Blocks/CocoaTile.cpp index c0a066699..73449170d 100644 --- a/Minecraft.World/Blocks/CocoaTile.cpp +++ b/Minecraft.World/Blocks/CocoaTile.cpp @@ -5,6 +5,7 @@ #include "../Headers/net.minecraft.world.h" #include "../Headers/net.minecraft.h" #include "CocoaTile.h" +#include "Util/AABB.h" const std::wstring CocoaTile::TEXTURE_AGES[] = {L"cocoa_0", L"cocoa_1", L"cocoa_2"}; @@ -56,12 +57,12 @@ bool CocoaTile::isCubeShaped() { return false; } bool CocoaTile::isSolidRender(bool isServerLevel) { return false; } -AABB* CocoaTile::getAABB(Level* level, int x, int y, int z) { +std::optional CocoaTile::getAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); return DirectionalTile::getAABB(level, x, y, z); } -AABB* CocoaTile::getTileAABB(Level* level, int x, int y, int z) { +AABB CocoaTile::getTileAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); return DirectionalTile::getTileAABB(level, x, y, z); } @@ -157,4 +158,4 @@ void CocoaTile::registerIcons(IconRegister* iconRegister) { for (int i = 0; i < COCOA_TEXTURES_LENGTH; i++) { icons[i] = iconRegister->registerIcon(TEXTURE_AGES[i]); } -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/CocoaTile.h b/Minecraft.World/Blocks/CocoaTile.h index 9726e232b..ff8c02c6f 100644 --- a/Minecraft.World/Blocks/CocoaTile.h +++ b/Minecraft.World/Blocks/CocoaTile.h @@ -22,8 +22,8 @@ public: virtual int getRenderShape(); virtual bool isCubeShaped(); virtual bool isSolidRender(bool isServerLevel = false); - virtual AABB* getAABB(Level* level, int x, int y, int z); - virtual AABB* getTileAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); + virtual AABB getTileAABB(Level* level, int x, int y, int z); virtual void updateShape(LevelSource* level, int x, int y, int z, int forceData = -1, std::shared_ptr forceEntity = diff --git a/Minecraft.World/Blocks/DetectorRailTile.cpp b/Minecraft.World/Blocks/DetectorRailTile.cpp index dacc5f51b..b7bd2d4e5 100644 --- a/Minecraft.World/Blocks/DetectorRailTile.cpp +++ b/Minecraft.World/Blocks/DetectorRailTile.cpp @@ -64,9 +64,9 @@ void DetectorRailTile::checkPressed(Level* level, int x, int y, int z, bool shouldBePressed = false; float b = 2 / 16.0f; - std::vector >* entities = level->getEntitiesOfClass( - typeid(Minecart), - AABB::newTemp(x + b, y, z + b, x + 1 - b, y + 1 - b, z + 1 - b)); + AABB minecart_aabb(x + b, y, z + b, x + b - b, y + b - b, z + 1 - b); + std::vector >* entities = + level->getEntitiesOfClass(typeid(Minecart), &minecart_aabb); if (!entities->empty()) { shouldBePressed = true; } @@ -105,10 +105,10 @@ int DetectorRailTile::getAnalogOutputSignal(Level* level, int x, int y, int z, int dir) { if ((level->getData(x, y, z) & RAIL_DATA_BIT) > 0) { float b = 2 / 16.0f; + AABB minecart_bb(x + b, y, z + b, x + 1 - b, y + 1 - b, z + 1 - b); std::vector >* entities = level->getEntitiesOfClass( - typeid(Minecart), - AABB::newTemp(x + b, y, z + b, x + 1 - b, y + 1 - b, z + 1 - b), + typeid(Minecart), &minecart_bb, EntitySelector::CONTAINER_ENTITY_SELECTOR); if (entities->size() > 0) { @@ -133,4 +133,4 @@ Icon* DetectorRailTile::getTexture(int face, int data) { return icons[1]; } return icons[0]; -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/DoorTile.cpp b/Minecraft.World/Blocks/DoorTile.cpp index 11378ce8a..1c2692370 100644 --- a/Minecraft.World/Blocks/DoorTile.cpp +++ b/Minecraft.World/Blocks/DoorTile.cpp @@ -85,16 +85,14 @@ bool DoorTile::isCubeShaped() { return false; } int DoorTile::getRenderShape() { return Tile::SHAPE_DOOR; } -AABB* DoorTile::getTileAABB(Level* level, int x, int y, int z) { +AABB DoorTile::getTileAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); - AABB* retval = Tile::getTileAABB(level, x, y, z); - return retval; + return Tile::getTileAABB(level, x, y, z); } -AABB* DoorTile::getAABB(Level* level, int x, int y, int z) { +std::optional DoorTile::getAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); - AABB* retval = Tile::getAABB(level, x, y, z); - return retval; + return Tile::getAABB(level, x, y, z); } void DoorTile::updateShape( @@ -307,4 +305,4 @@ void DoorTile::playerWillDestroy(Level* level, int x, int y, int z, int data, } } } -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/DoorTile.h b/Minecraft.World/Blocks/DoorTile.h index 1c9abde7b..3f844a27d 100644 --- a/Minecraft.World/Blocks/DoorTile.h +++ b/Minecraft.World/Blocks/DoorTile.h @@ -40,8 +40,8 @@ public: virtual bool isSolidRender(bool isServerLevel = false); virtual bool isCubeShaped(); virtual int getRenderShape(); - virtual AABB* getTileAABB(Level* level, int x, int y, int z); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual AABB getTileAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual void updateShape( LevelSource* level, int x, int y, int z, int forceData = -1, std::shared_ptr forceEntity = std::shared_ptr< diff --git a/Minecraft.World/Blocks/FallingTile.cpp b/Minecraft.World/Blocks/FallingTile.cpp index a57aa58d2..eb7adda42 100644 --- a/Minecraft.World/Blocks/FallingTile.cpp +++ b/Minecraft.World/Blocks/FallingTile.cpp @@ -168,7 +168,7 @@ void FallingTile::causeFallDamage(float distance) { // entities (invalidating our iterator) std::vector >* entities = new std::vector >( - *level->getEntities(shared_from_this(), bb)); + *level->getEntities(shared_from_this(), &bb)); DamageSource* source = tile == Tile::anvil_Id ? DamageSource::anvil : DamageSource::fallingBlock; @@ -242,4 +242,4 @@ Level* FallingTile::getLevel() { return level; } void FallingTile::setHurtsEntities(bool value) { this->hurtEntities = value; } -bool FallingTile::displayFireAnimation() { return false; } \ No newline at end of file +bool FallingTile::displayFireAnimation() { return false; } diff --git a/Minecraft.World/Blocks/FarmTile.cpp b/Minecraft.World/Blocks/FarmTile.cpp index dce769962..191f0963c 100644 --- a/Minecraft.World/Blocks/FarmTile.cpp +++ b/Minecraft.World/Blocks/FarmTile.cpp @@ -17,8 +17,8 @@ FarmTile::FarmTile(int id) : Tile(id, Material::dirt, false) { // 4J Added override void FarmTile::updateDefaultShape() { setShape(0, 0, 0, 1, 15 / 16.0f, 1); } -AABB* FarmTile::getAABB(Level* level, int x, int y, int z) { - return AABB::newTemp(x + 0, y + 0, z + 0, x + 1, y + 1, z + 1); +std::optional FarmTile::getAABB(Level* level, int x, int y, int z) { + return AABB(x + 0, y + 0, z + 0, x + 1, y + 1, z + 1); } bool FarmTile::isSolidRender(bool isServerLevel) { return false; } diff --git a/Minecraft.World/Blocks/FarmTile.h b/Minecraft.World/Blocks/FarmTile.h index 15be34ebd..ee7a7e3df 100644 --- a/Minecraft.World/Blocks/FarmTile.h +++ b/Minecraft.World/Blocks/FarmTile.h @@ -18,7 +18,7 @@ protected: public: virtual void updateDefaultShape(); // 4J Added override - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual bool isSolidRender(bool isServerLevel = false); virtual bool isCubeShaped(); virtual Icon* getTexture(int face, int data); diff --git a/Minecraft.World/Blocks/FenceGateTile.cpp b/Minecraft.World/Blocks/FenceGateTile.cpp index 4a9a11268..2b947b0e8 100644 --- a/Minecraft.World/Blocks/FenceGateTile.cpp +++ b/Minecraft.World/Blocks/FenceGateTile.cpp @@ -4,6 +4,7 @@ #include "../Headers/net.minecraft.world.level.h" #include "../Headers/net.minecraft.h" #include "../Level/Events/LevelEvent.h" +#include "Util/Direction.h" FenceGateTile::FenceGateTile(int id) : DirectionalTile(id, Material::wood, false) {} @@ -17,19 +18,29 @@ bool FenceGateTile::mayPlace(Level* level, int x, int y, int z) { return Tile::mayPlace(level, x, y, z); } -AABB* FenceGateTile::getAABB(Level* level, int x, int y, int z) { +std::optional FenceGateTile::getAABB(Level* level, int x, int y, int z) { int data = level->getData(x, y, z); if (isOpen(data)) { - return NULL; + return std::nullopt; } - // 4J Brought forward change from 1.2.3 to fix hit box rotation - if (data == Direction::NORTH || data == Direction::SOUTH) { - return AABB::newTemp(x, y, z + 6.0f / 16.0f, x + 1, y + 1.5f, - z + 10.0f / 16.0f); + + switch (data) { + case Direction::NORTH: + case Direction::SOUTH: + return AABB{static_cast(x), + static_cast(y), + z + 6.0 / 16.0, + x + 1.0, + y + 1.5, + z + 10.0 / 16.0}; + default: + return AABB{x + 6.0 / 16.0, + static_cast(y), + static_cast(z), + x + 10.0 / 16.0, + y + 1.5, + z + 1.0}; } - return AABB::newTemp(x + 6.0f / 16.0f, y, z, x + 10.0f / 16.0f, y + 1.5f, - z + 1); - // return AABB::newTemp(x, y, z, x + 1, y + 1.5f, z + 1); } // 4J - Brought forward from 1.2.3 to fix hit box rotation @@ -123,4 +134,4 @@ void FenceGateTile::registerIcons(IconRegister* iconRegister) { bool FenceGateTile::shouldRenderFace(LevelSource* level, int x, int y, int z, int face) { return true; -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/FenceGateTile.h b/Minecraft.World/Blocks/FenceGateTile.h index 85767bf37..c43b41416 100644 --- a/Minecraft.World/Blocks/FenceGateTile.h +++ b/Minecraft.World/Blocks/FenceGateTile.h @@ -9,7 +9,7 @@ public: FenceGateTile(int id); Icon* getTexture(int face, int data); virtual bool mayPlace(Level* level, int x, int y, int z); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual void updateShape( LevelSource* level, int x, int y, int z, int forceData = -1, std::shared_ptr forceEntity = std::shared_ptr< diff --git a/Minecraft.World/Blocks/FireTile.cpp b/Minecraft.World/Blocks/FireTile.cpp index b9b1d460f..bfa27e540 100644 --- a/Minecraft.World/Blocks/FireTile.cpp +++ b/Minecraft.World/Blocks/FireTile.cpp @@ -7,6 +7,7 @@ #include "../Util/SoundTypes.h" #include "../../Minecraft.Client/MinecraftServer.h" #include "../../Minecraft.Client/Network/PlayerList.h" +#include "Util/AABB.h" // AP - added for Vita to set Alpha Cut out #include "../IO/Streams/IntBuffer.h" @@ -57,7 +58,7 @@ void FireTile::setFlammable(int id, int flame, int burn) { burnOdds[id] = burn; } -AABB* FireTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional FireTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } bool FireTile::blocksLight() { return false; } diff --git a/Minecraft.World/Blocks/FireTile.h b/Minecraft.World/Blocks/FireTile.h index 260e98d97..c93e7e94f 100644 --- a/Minecraft.World/Blocks/FireTile.h +++ b/Minecraft.World/Blocks/FireTile.h @@ -39,7 +39,7 @@ private: void setFlammable(int id, int flame, int burn); public: - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual bool blocksLight(); virtual bool isSolidRender(bool isServerLevel = false); virtual bool isCubeShaped(); @@ -69,4 +69,4 @@ public: void registerIcons(IconRegister* iconRegister); Icon* getTextureLayer(int layer); Icon* getTexture(int face, int data); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/LadderTile.cpp b/Minecraft.World/Blocks/LadderTile.cpp index ac0595ea5..06b016284 100644 --- a/Minecraft.World/Blocks/LadderTile.cpp +++ b/Minecraft.World/Blocks/LadderTile.cpp @@ -1,16 +1,17 @@ #include "../Platform/stdafx.h" #include "../Headers/net.minecraft.world.level.h" #include "LadderTile.h" +#include "Util/AABB.h" LadderTile::LadderTile(int id) : Tile(id, Material::decoration, false) {} -AABB* LadderTile::getAABB(Level* level, int x, int y, int z) { +std::optional LadderTile::getAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); return Tile::getAABB(level, x, y, z); } -AABB* LadderTile::getTileAABB(Level* level, int x, int y, int z) { +AABB LadderTile::getTileAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); return Tile::getTileAABB(level, x, y, z); } @@ -87,4 +88,4 @@ void LadderTile::neighborChanged(Level* level, int x, int y, int z, int type) { Tile::neighborChanged(level, x, y, z, type); } -int LadderTile::getResourceCount(Random* random) { return 1; } \ No newline at end of file +int LadderTile::getResourceCount(Random* random) { return 1; } diff --git a/Minecraft.World/Blocks/LadderTile.h b/Minecraft.World/Blocks/LadderTile.h index d91eeda1f..9bde7712d 100644 --- a/Minecraft.World/Blocks/LadderTile.h +++ b/Minecraft.World/Blocks/LadderTile.h @@ -11,8 +11,8 @@ protected: LadderTile(int id); public: - virtual AABB* getAABB(Level* level, int x, int y, int z); - virtual AABB* getTileAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); + virtual AABB getTileAABB(Level* level, int x, int y, int z); virtual void updateShape( LevelSource* level, int x, int y, int z, int forceData = -1, std::shared_ptr forceEntity = std::shared_ptr< @@ -29,4 +29,4 @@ public: float clickZ, int itemValue); virtual void neighborChanged(Level* level, int x, int y, int z, int type); virtual int getResourceCount(Random* random); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/LeverTile.cpp b/Minecraft.World/Blocks/LeverTile.cpp index e44a69ac3..ffb8deead 100644 --- a/Minecraft.World/Blocks/LeverTile.cpp +++ b/Minecraft.World/Blocks/LeverTile.cpp @@ -3,11 +3,12 @@ #include "../Headers/net.minecraft.world.level.redstone.h" #include "../Headers/net.minecraft.h" #include "LeverTile.h" +#include "Util/AABB.h" LeverTile::LeverTile(int id) : Tile(id, Material::decoration, false) {} -AABB* LeverTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional LeverTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } bool LeverTile::blocksLight() { return false; } diff --git a/Minecraft.World/Blocks/LeverTile.h b/Minecraft.World/Blocks/LeverTile.h index 47a6b21cf..7f27ba4a4 100644 --- a/Minecraft.World/Blocks/LeverTile.h +++ b/Minecraft.World/Blocks/LeverTile.h @@ -8,7 +8,7 @@ protected: LeverTile(int id); public: - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual bool blocksLight(); virtual bool isSolidRender(bool isServerLevel = false); virtual bool isCubeShaped(); diff --git a/Minecraft.World/Blocks/LiquidTile.cpp b/Minecraft.World/Blocks/LiquidTile.cpp index e307e2125..1c94595f9 100644 --- a/Minecraft.World/Blocks/LiquidTile.cpp +++ b/Minecraft.World/Blocks/LiquidTile.cpp @@ -5,8 +5,11 @@ #include "../Headers/net.minecraft.world.level.biome.h" #include "../Headers/net.minecraft.world.h" #include "LiquidTile.h" +#include #include "../Util/Facing.h" #include "../Util/SoundTypes.h" +#include "Blocks/Material.h" +#include "Util/AABB.h" const std::wstring LiquidTile::TEXTURE_LAVA_STILL = L"lava"; const std::wstring LiquidTile::TEXTURE_WATER_STILL = L"water"; @@ -106,7 +109,9 @@ bool LiquidTile::shouldRenderFace(LevelSource* level, int x, int y, int z, return Tile::shouldRenderFace(level, x, y, z, face); } -AABB* LiquidTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional LiquidTile::getAABB(Level* level, int x, int y, int z) { + return std::nullopt; +} int LiquidTile::getRenderShape() { return Tile::SHAPE_WATER; } @@ -116,8 +121,8 @@ int LiquidTile::getResource(int data, Random* random, int playerBonusLevel) { int LiquidTile::getResourceCount(Random* random) { return 0; } -Vec3* LiquidTile::getFlow(LevelSource* level, int x, int y, int z) { - Vec3* flow = Vec3::newTemp(0, 0, 0); +Vec3 LiquidTile::getFlow(LevelSource* level, int x, int y, int z) { + Vec3 flow(0, 0, 0); int mid = getRenderedDepth(level, x, y, z); for (int d = 0; d < 4; d++) { int xt = x; @@ -135,15 +140,14 @@ Vec3* LiquidTile::getFlow(LevelSource* level, int x, int y, int z) { t = getRenderedDepth(level, xt, yt - 1, zt); if (t >= 0) { int dir = t - (mid - 8); - flow = flow->add((xt - x) * dir, (yt - y) * dir, - (zt - z) * dir); + flow = flow.add((xt - x) * dir, (yt - y) * dir, + (zt - z) * dir); } } } else { if (t >= 0) { int dir = t - mid; - flow = - flow->add((xt - x) * dir, (yt - y) * dir, (zt - z) * dir); + flow = flow.add((xt - x) * dir, (yt - y) * dir, (zt - z) * dir); } } } @@ -157,18 +161,19 @@ Vec3* LiquidTile::getFlow(LevelSource* level, int x, int y, int z) { if (ok || isSolidFace(level, x, y + 1, z + 1, 3)) ok = true; if (ok || isSolidFace(level, x - 1, y + 1, z, 4)) ok = true; if (ok || isSolidFace(level, x + 1, y + 1, z, 5)) ok = true; - if (ok) flow = flow->normalize()->add(0, -6, 0); + if (ok) flow = flow.normalize().add(0, -6, 0); } - flow = flow->normalize(); + flow = flow.normalize(); + return flow; } void LiquidTile::handleEntityInside(Level* level, int x, int y, int z, std::shared_ptr e, Vec3* current) { - Vec3* flow = getFlow(level, x, y, z); - current->x += flow->x; - current->y += flow->y; - current->z += flow->z; + Vec3 flow = getFlow(level, x, y, z); + current->x += flow.x; + current->y += flow.y; + current->z += flow.z; } int LiquidTile::getTickDelay(Level* level) { @@ -305,13 +310,11 @@ void LiquidTile::animateTick(Level* level, int x, int y, int z, double LiquidTile::getSlopeAngle(LevelSource* level, int x, int y, int z, Material* m) { - Vec3* flow = NULL; - if (m == Material::water) - flow = ((LiquidTile*)Tile::water)->getFlow(level, x, y, z); - if (m == Material::lava) - flow = ((LiquidTile*)Tile::lava)->getFlow(level, x, y, z); - if (flow->x == 0 && flow->z == 0) return -1000; - return atan2(flow->z, flow->x) - PI / 2; + Vec3 flow; + if (m == Material::water) flow = Tile::water->getFlow(level, x, y, z); + if (m == Material::lava) flow = Tile::lava->getFlow(level, x, y, z); + if (flow.x == 0 && flow.z == 0) return -1000; + return atan2(flow.z, flow.x) - PI / 2; } void LiquidTile::onPlace(Level* level, int x, int y, int z) { diff --git a/Minecraft.World/Blocks/LiquidTile.h b/Minecraft.World/Blocks/LiquidTile.h index 24c3d8f17..7ffed063a 100644 --- a/Minecraft.World/Blocks/LiquidTile.h +++ b/Minecraft.World/Blocks/LiquidTile.h @@ -1,4 +1,5 @@ #pragma once +#include #include "Tile.h" #include "../Util/Definitions.h" @@ -40,13 +41,13 @@ public: virtual bool isSolidFace(LevelSource* level, int x, int y, int z, int face); virtual bool shouldRenderFace(LevelSource* level, int x, int y, int z, int face); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual int getRenderShape(); virtual int getResource(int data, Random* random, int playerBonusLevel); virtual int getResourceCount(Random* random); private: - virtual Vec3* getFlow(LevelSource* level, int x, int y, int z); + virtual Vec3 getFlow(LevelSource* level, int x, int y, int z); public: virtual void handleEntityInside(Level* level, int x, int y, int z, @@ -72,4 +73,4 @@ protected: public: void registerIcons(IconRegister* iconRegister); static Icon* getTexture(const std::wstring& name); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/PistonBaseTile.cpp b/Minecraft.World/Blocks/PistonBaseTile.cpp index de8c30b23..8a85152cc 100644 --- a/Minecraft.World/Blocks/PistonBaseTile.cpp +++ b/Minecraft.World/Blocks/PistonBaseTile.cpp @@ -1,5 +1,6 @@ #include "../Platform/stdafx.h" #include +#include #include "PistonBaseTile.h" #include "PistonMovingTileEntity.h" #include "TileEntities/PistonPieceTileEntity.h" @@ -12,6 +13,8 @@ #include "../Level/LevelChunk.h" #include "../Level/Dimensions/Dimension.h" +#include "Util/AABB.h" + const std::wstring PistonBaseTile::EDGE_TEX = L"piston_side"; const std::wstring PistonBaseTile::PLATFORM_TEX = L"piston_top"; const std::wstring PistonBaseTile::PLATFORM_STICKY_TEX = L"piston_top_sticky"; @@ -398,7 +401,7 @@ void PistonBaseTile::addAABBs(Level* level, int x, int y, int z, AABB* box, Tile::addAABBs(level, x, y, z, box, boxes, source); } -AABB* PistonBaseTile::getAABB(Level* level, int x, int y, int z) { +std::optional PistonBaseTile::getAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); return Tile::getAABB(level, x, y, z); } diff --git a/Minecraft.World/Blocks/PistonBaseTile.h b/Minecraft.World/Blocks/PistonBaseTile.h index 272b44e81..36097aacf 100644 --- a/Minecraft.World/Blocks/PistonBaseTile.h +++ b/Minecraft.World/Blocks/PistonBaseTile.h @@ -1,6 +1,7 @@ #pragma once #include "Tile.h" #include +#include class PistonBaseTile : public Tile { public: @@ -68,7 +69,7 @@ public: virtual void updateDefaultShape(); virtual void addAABBs(Level* level, int x, int y, int z, AABB* box, AABBList* boxes, std::shared_ptr source); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual bool isCubeShaped(); static int getFacing(int data); @@ -84,4 +85,4 @@ private: int z); // 4J added bool createPush(Level* level, int sx, int sy, int sz, int facing); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/PistonMovingTileEntity.cpp b/Minecraft.World/Blocks/PistonMovingTileEntity.cpp index b12d0dd7d..f4109695d 100644 --- a/Minecraft.World/Blocks/PistonMovingTileEntity.cpp +++ b/Minecraft.World/Blocks/PistonMovingTileEntity.cpp @@ -1,5 +1,6 @@ #include "../Platform/stdafx.h" #include "PistonMovingTileEntity.h" +#include #include "TileEntities/PistonPieceTileEntity.h" #include "../Headers/net.minecraft.world.level.h" #include "../Headers/net.minecraft.world.h" @@ -91,10 +92,11 @@ std::shared_ptr PistonMovingPiece::newMovingPieceEntity( new PistonPieceEntity(block, data, facing, extending, isSourcePiston)); } -AABB* PistonMovingPiece::getAABB(Level* level, int x, int y, int z) { +std::optional PistonMovingPiece::getAABB(Level* level, int x, int y, + int z) { std::shared_ptr entity = getEntity(level, x, y, z); if (entity == NULL) { - return NULL; + return std::nullopt; } // move the aabb depending on the animation @@ -136,15 +138,16 @@ void PistonMovingPiece::updateShape( } } -AABB* PistonMovingPiece::getAABB(Level* level, int x, int y, int z, int tile, - float progress, int facing) { +std::optional PistonMovingPiece::getAABB(Level* level, int x, int y, + int z, int tile, float progress, + int facing) { if (tile == 0 || tile == id) { - return NULL; + return std::nullopt; } - AABB* aabb = Tile::tiles[tile]->getAABB(level, x, y, z); + auto aabb = Tile::tiles[tile]->getAABB(level, x, y, z); - if (aabb == NULL) { - return NULL; + if (!aabb.has_value()) { + return std::nullopt; } // move the aabb depending on the animation @@ -153,16 +156,19 @@ AABB* PistonMovingPiece::getAABB(Level* level, int x, int y, int z, int tile, } else { aabb->x1 -= Facing::STEP_X[facing] * progress; } + if (Facing::STEP_Y[facing] < 0) { aabb->y0 -= Facing::STEP_Y[facing] * progress; } else { aabb->y1 -= Facing::STEP_Y[facing] * progress; } + if (Facing::STEP_Z[facing] < 0) { aabb->z0 -= Facing::STEP_Z[facing] * progress; } else { aabb->z1 -= Facing::STEP_Z[facing] * progress; } + return aabb; } diff --git a/Minecraft.World/Blocks/PistonMovingTileEntity.h b/Minecraft.World/Blocks/PistonMovingTileEntity.h index 530c6e87d..ec3a5aa7f 100644 --- a/Minecraft.World/Blocks/PistonMovingTileEntity.h +++ b/Minecraft.World/Blocks/PistonMovingTileEntity.h @@ -28,13 +28,13 @@ public: virtual void neighborChanged(Level* level, int x, int y, int z, int type); static std::shared_ptr newMovingPieceEntity( int block, int data, int facing, bool extending, bool isSourcePiston); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual void updateShape( LevelSource* level, int x, int y, int z, int forceData = -1, std::shared_ptr forceEntity = std::shared_ptr< TileEntity>()); // 4J added forceData, forceEntity param - AABB* getAABB(Level* level, int x, int y, int z, int tile, float progress, + std::optional getAABB(Level* level, int x, int y, int z, int tile, float progress, int facing); private: @@ -44,4 +44,4 @@ private: public: virtual int cloneTileId(Level* level, int x, int y, int z); void registerIcons(IconRegister* iconRegister); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/PlantTile.cpp b/Minecraft.World/Blocks/PlantTile.cpp index ee3f09669..543008466 100644 --- a/Minecraft.World/Blocks/PlantTile.cpp +++ b/Minecraft.World/Blocks/PlantTile.cpp @@ -2,6 +2,7 @@ #include "../Headers/net.minecraft.world.level.h" #include "GrassTile.h" #include "PlantTile.h" +#include "Util/AABB.h" void Bush::_init() { setTicking(true); @@ -52,7 +53,7 @@ bool Bush::canSurvive(Level* level, int x, int y, int z) { mayPlaceOn(level->getTile(x, y - 1, z)); } -AABB* Bush::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional Bush::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } bool Bush::blocksLight() { return false; } diff --git a/Minecraft.World/Blocks/PlantTile.h b/Minecraft.World/Blocks/PlantTile.h index 53ebbcb46..72c134196 100644 --- a/Minecraft.World/Blocks/PlantTile.h +++ b/Minecraft.World/Blocks/PlantTile.h @@ -32,7 +32,7 @@ protected: public: virtual bool canSurvive(Level* level, int x, int y, int z); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual bool blocksLight(); virtual bool isSolidRender(bool isServerLevel = false); diff --git a/Minecraft.World/Blocks/PortalTile.cpp b/Minecraft.World/Blocks/PortalTile.cpp index 994e79a24..bd4f199b3 100644 --- a/Minecraft.World/Blocks/PortalTile.cpp +++ b/Minecraft.World/Blocks/PortalTile.cpp @@ -4,6 +4,9 @@ #include "../Headers/net.minecraft.world.level.dimension.h" #include "../Headers/net.minecraft.world.item.h" #include "PortalTile.h" +#include + +#include "Util/AABB.h" #include "FireTile.h" PortalTile::PortalTile(int id) @@ -34,7 +37,7 @@ void PortalTile::tick(Level* level, int x, int y, int z, Random* random) { } } -AABB* PortalTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional PortalTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } void PortalTile::updateShape( LevelSource* level, int x, int y, int z, int forceData, diff --git a/Minecraft.World/Blocks/PortalTile.h b/Minecraft.World/Blocks/PortalTile.h index b498fb1ac..c62fb1033 100644 --- a/Minecraft.World/Blocks/PortalTile.h +++ b/Minecraft.World/Blocks/PortalTile.h @@ -1,4 +1,5 @@ #pragma once +#include #include "HalfTransparentTile.h" #include "../Util/Definitions.h" @@ -8,7 +9,7 @@ class PortalTile : public HalfTransparentTile { public: PortalTile(int id); virtual void tick(Level* level, int x, int y, int z, Random* random); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual void updateShape( LevelSource* level, int x, int y, int z, int forceData = -1, std::shared_ptr forceEntity = std::shared_ptr< diff --git a/Minecraft.World/Blocks/PressurePlateTile.cpp b/Minecraft.World/Blocks/PressurePlateTile.cpp index ef1223bb3..48a273f0d 100644 --- a/Minecraft.World/Blocks/PressurePlateTile.cpp +++ b/Minecraft.World/Blocks/PressurePlateTile.cpp @@ -2,6 +2,7 @@ #include "../Headers/net.minecraft.world.level.h" #include "../Headers/net.minecraft.world.level.redstone.h" #include "PressurePlateTile.h" +#include "Util/AABB.h" PressurePlateTile::PressurePlateTile(int id, const std::wstring& tex, Material* material, @@ -23,15 +24,13 @@ int PressurePlateTile::getSignalForData(int data) { int PressurePlateTile::getSignalStrength(Level* level, int x, int y, int z) { std::vector >* entities = NULL; - + AABB at_bb = getSensitiveAABB(x, y, z); if (sensitivity == everything) - entities = level->getEntities(nullptr, getSensitiveAABB(x, y, z)); + entities = level->getEntities(nullptr, &at_bb); else if (sensitivity == mobs) - entities = level->getEntitiesOfClass(typeid(LivingEntity), - getSensitiveAABB(x, y, z)); + entities = level->getEntitiesOfClass(typeid(LivingEntity), &at_bb); else if (sensitivity == players) - entities = level->getEntitiesOfClass(typeid(Player), - getSensitiveAABB(x, y, z)); + entities = level->getEntitiesOfClass(typeid(Player), &at_bb); else __debugbreak(); // 4J-JEV: We're going to delete something at a random // location. @@ -48,4 +47,4 @@ int PressurePlateTile::getSignalStrength(Level* level, int x, int y, int z) { if (sensitivity != everything) delete entities; return Redstone::SIGNAL_NONE; -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/RedStoneDustTile.cpp b/Minecraft.World/Blocks/RedStoneDustTile.cpp index 5127acb71..02aceb79b 100644 --- a/Minecraft.World/Blocks/RedStoneDustTile.cpp +++ b/Minecraft.World/Blocks/RedStoneDustTile.cpp @@ -1,6 +1,8 @@ #include "../Platform/stdafx.h" #include "../../Minecraft.Client/Minecraft.h" #include "RedStoneDustTile.h" +#include +#include #include "../Headers/net.minecraft.world.item.h" #include "../Headers/net.minecraft.world.level.h" #include "../Headers/net.minecraft.world.level.redstone.h" @@ -9,6 +11,7 @@ #include "../Headers/net.minecraft.h" #include "../Util/Direction.h" #include "DiodeTile.h" +#include "Util/AABB.h" // AP - added for Vita to set Alpha Cut out #include "../IO/Streams/IntBuffer.h" @@ -36,8 +39,9 @@ void RedStoneDustTile::updateDefaultShape() { setShape(0, 0, 0, 1, 1 / 16.0f, 1); } -AABB* RedStoneDustTile::getAABB(Level* level, int x, int y, int z) { - return NULL; +std::optional RedStoneDustTile::getAABB(Level* level, int x, int y, + int z) { + return std::nullopt; } bool RedStoneDustTile::isSolidRender(bool isServerLevel) { return false; } diff --git a/Minecraft.World/Blocks/RedStoneDustTile.h b/Minecraft.World/Blocks/RedStoneDustTile.h index 872f9ea58..e9656d395 100644 --- a/Minecraft.World/Blocks/RedStoneDustTile.h +++ b/Minecraft.World/Blocks/RedStoneDustTile.h @@ -1,4 +1,5 @@ #pragma once +#include #include "Tile.h" #include "../Util/Definitions.h" @@ -26,7 +27,7 @@ private: public: RedStoneDustTile(int id); virtual void updateDefaultShape(); // 4J Added override - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual bool isSolidRender(bool isServerLevel = false); virtual bool isCubeShaped(); virtual int getRenderShape(); diff --git a/Minecraft.World/Blocks/ReedTile.cpp b/Minecraft.World/Blocks/ReedTile.cpp index c9297caf4..7961dbaeb 100644 --- a/Minecraft.World/Blocks/ReedTile.cpp +++ b/Minecraft.World/Blocks/ReedTile.cpp @@ -5,6 +5,7 @@ #include "../Headers/net.minecraft.world.level.material.h" #include "../Headers/net.minecraft.world.phys.h" #include "ReedTile.h" +#include ReedTile::ReedTile(int id) : Tile(id, Material::plant, false) { this->updateDefaultShape(); @@ -64,7 +65,7 @@ bool ReedTile::canSurvive(Level* level, int x, int y, int z) { return mayPlace(level, x, y, z); } -AABB* ReedTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional ReedTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } int ReedTile::getResource(int data, Random* random, int playerBonusLevel) { return Item::reeds->id; diff --git a/Minecraft.World/Blocks/ReedTile.h b/Minecraft.World/Blocks/ReedTile.h index dd3a3bab4..4fbe21aa3 100644 --- a/Minecraft.World/Blocks/ReedTile.h +++ b/Minecraft.World/Blocks/ReedTile.h @@ -1,5 +1,6 @@ #pragma once +#include #include "Tile.h" #include "../Util/Definitions.h" @@ -28,7 +29,7 @@ public: bool canSurvive(Level* level, int x, int y, int z); public: - AABB* getAABB(Level* level, int x, int y, int z); + std::optional getAABB(Level* level, int x, int y, int z); public: int getResource(int data, Random* random, int playerBonusLevel); diff --git a/Minecraft.World/Blocks/SignTile.cpp b/Minecraft.World/Blocks/SignTile.cpp index 0ffd3e7b9..7a62f9248 100644 --- a/Minecraft.World/Blocks/SignTile.cpp +++ b/Minecraft.World/Blocks/SignTile.cpp @@ -4,6 +4,9 @@ #include "Material.h" #include "TileEntities/SignTileEntity.h" #include "SignTile.h" +#include "Util/AABB.h" + +#include SignTile::SignTile(int id, eINSTANCEOF clas, bool onGround) : BaseEntityTile(id, Material::wood, false) { @@ -22,9 +25,9 @@ void SignTile::updateDefaultShape() { this->setShape(0.5f - r, 0, 0.5f - r, 0.5f + r, h, 0.5f + r); } -AABB* SignTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional SignTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } -AABB* SignTile::getTileAABB(Level* level, int x, int y, int z) { +AABB SignTile::getTileAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); return BaseEntityTile::getTileAABB(level, x, y, z); } @@ -109,4 +112,4 @@ int SignTile::cloneTileId(Level* level, int x, int y, int z) { void SignTile::registerIcons(IconRegister* iconRegister) { // None -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/SignTile.h b/Minecraft.World/Blocks/SignTile.h index b3e5ec372..952b5e1cc 100644 --- a/Minecraft.World/Blocks/SignTile.h +++ b/Minecraft.World/Blocks/SignTile.h @@ -1,5 +1,6 @@ #pragma once +#include #include "BaseEntityTile.h" #include "TileEntities/TileEntity.h" @@ -19,8 +20,8 @@ protected: public: Icon* getTexture(int face, int data); virtual void updateDefaultShape(); - AABB* getAABB(Level* level, int x, int y, int z); - AABB* getTileAABB(Level* level, int x, int y, int z); + std::optional getAABB(Level* level, int x, int y, int z); + AABB getTileAABB(Level* level, int x, int y, int z); void updateShape(LevelSource* level, int x, int y, int z, int forceData = -1, std::shared_ptr forceEntity = @@ -39,4 +40,4 @@ public: void neighborChanged(Level* level, int x, int y, int z, int type); int cloneTileId(Level* level, int x, int y, int z); void registerIcons(IconRegister* iconRegister); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/SkullTile.cpp b/Minecraft.World/Blocks/SkullTile.cpp index 251cb7833..1a0340b7d 100644 --- a/Minecraft.World/Blocks/SkullTile.cpp +++ b/Minecraft.World/Blocks/SkullTile.cpp @@ -49,7 +49,7 @@ void SkullTile::updateShape(LevelSource* level, int x, int y, int z, } } -AABB* SkullTile::getAABB(Level* level, int x, int y, int z) { +std::optional SkullTile::getAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); return BaseEntityTile::getAABB(level, x, y, z); } @@ -316,4 +316,4 @@ Icon* SkullTile::getTexture(int face, int data) { std::wstring SkullTile::getTileItemIconName() { return getIconName() + L"_" + SkullItem::ICON_NAMES[0]; -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/SkullTile.h b/Minecraft.World/Blocks/SkullTile.h index 5c2642b01..f8fea1299 100644 --- a/Minecraft.World/Blocks/SkullTile.h +++ b/Minecraft.World/Blocks/SkullTile.h @@ -26,7 +26,7 @@ public: int forceData = -1, std::shared_ptr forceEntity = std::shared_ptr()); - AABB* getAABB(Level* level, int x, int y, int z); + std::optional getAABB(Level* level, int x, int y, int z); void setPlacedBy(Level* level, int x, int y, int z, std::shared_ptr by); std::shared_ptr newTileEntity(Level* level); diff --git a/Minecraft.World/Blocks/SoulSandTile.cpp b/Minecraft.World/Blocks/SoulSandTile.cpp index fe240022f..b9f7b48df 100644 --- a/Minecraft.World/Blocks/SoulSandTile.cpp +++ b/Minecraft.World/Blocks/SoulSandTile.cpp @@ -5,13 +5,13 @@ SoulSandTile::SoulSandTile(int id) : Tile(id, Material::sand) {} -AABB* SoulSandTile::getAABB(Level* level, int x, int y, int z) { +std::optional SoulSandTile::getAABB(Level* level, int x, int y, int z) { float r = 2 / 16.0f; - return AABB::newTemp(x, y, z, x + 1, y + 1 - r, z + 1); + return AABB(x, y, z, x + 1, y + 1 - r, z + 1); } void SoulSandTile::entityInside(Level* level, int x, int y, int z, std::shared_ptr entity) { entity->xd *= 0.4; entity->zd *= 0.4; -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/SoulSandTile.h b/Minecraft.World/Blocks/SoulSandTile.h index 62d6b1e45..b45c8dc53 100644 --- a/Minecraft.World/Blocks/SoulSandTile.h +++ b/Minecraft.World/Blocks/SoulSandTile.h @@ -5,7 +5,7 @@ class SoulSandTile : public Tile { public: SoulSandTile(int id); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual void entityInside(Level* level, int x, int y, int z, std::shared_ptr entity); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/StairTile.cpp b/Minecraft.World/Blocks/StairTile.cpp index f03aa9a08..244c58895 100644 --- a/Minecraft.World/Blocks/StairTile.cpp +++ b/Minecraft.World/Blocks/StairTile.cpp @@ -326,7 +326,7 @@ Icon* StairTile::getTexture(int face, int data) { int StairTile::getTickDelay(Level* level) { return base->getTickDelay(level); } -AABB* StairTile::getTileAABB(Level* level, int x, int y, int z) { +AABB StairTile::getTileAABB(Level* level, int x, int y, int z) { return base->getTileAABB(level, x, y, z); } @@ -443,7 +443,7 @@ HitResult* StairTile::clip(Level* level, int xt, int yt, int zt, Vec3* a, for (unsigned int i = 0; i < 8; ++i) { HitResult* result = results[i]; if (result != NULL) { - double dist = result->pos->distanceToSqr(b); + double dist = result->pos.distanceToSqr(*b); if (dist > closestDist) { closest = result; diff --git a/Minecraft.World/Blocks/StairTile.h b/Minecraft.World/Blocks/StairTile.h index 23d906835..690b52bd2 100644 --- a/Minecraft.World/Blocks/StairTile.h +++ b/Minecraft.World/Blocks/StairTile.h @@ -65,7 +65,7 @@ public: virtual int getRenderLayer(); virtual Icon* getTexture(int face, int data); virtual int getTickDelay(Level* level); - virtual AABB* getTileAABB(Level* level, int x, int y, int z); + virtual AABB getTileAABB(Level* level, int x, int y, int z); virtual void handleEntityInside(Level* level, int x, int y, int z, std::shared_ptr e, Vec3* current); virtual bool mayPick(); diff --git a/Minecraft.World/Blocks/Tile.cpp b/Minecraft.World/Blocks/Tile.cpp index 71fe2db82..f29a77a6f 100644 --- a/Minecraft.World/Blocks/Tile.cpp +++ b/Minecraft.World/Blocks/Tile.cpp @@ -15,7 +15,9 @@ #include "../Headers/net.minecraft.world.food.h" #include "../Headers/net.minecraft.world.h" #include "../Headers/net.minecraft.h" +#include "Util/Vec3.h" #include "Tile.h" +#include std::wstring Tile::TILE_DESCRIPTION_PREFIX = L"Tile."; @@ -2003,26 +2005,26 @@ Icon* Tile::getTexture(int face, int data) { return icon; } Icon* Tile::getTexture(int face) { return getTexture(face, 0); } -AABB* Tile::getTileAABB(Level* level, int x, int y, int z) { +AABB Tile::getTileAABB(Level* level, int x, int y, int z) { ThreadStorage* tls = m_tlsShape; // 4J Stu - Added this so that the TLS shape is correct for this tile if (tls->tileId != this->id) updateDefaultShape(); - return AABB::newTemp(x + tls->xx0, y + tls->yy0, z + tls->zz0, x + tls->xx1, - y + tls->yy1, z + tls->zz1); + return AABB(x + tls->xx0, y + tls->yy0, z + tls->zz0, x + tls->xx1, + y + tls->yy1, z + tls->zz1); } void Tile::addAABBs(Level* level, int x, int y, int z, AABB* box, AABBList* boxes, std::shared_ptr source) { - AABB* aabb = getAABB(level, x, y, z); - if (aabb != NULL && box->intersects(aabb)) boxes->push_back(aabb); + auto aabb = getAABB(level, x, y, z); + if (aabb.has_value() && box->intersects(*aabb)) boxes->push_back(*aabb); } -AABB* Tile::getAABB(Level* level, int x, int y, int z) { +std::optional Tile::getAABB(Level* level, int x, int y, int z) { ThreadStorage* tls = m_tlsShape; // 4J Stu - Added this so that the TLS shape is correct for this tile if (tls->tileId != this->id) updateDefaultShape(); - return AABB::newTemp(x + tls->xx0, y + tls->yy0, z + tls->zz0, x + tls->xx1, - y + tls->yy1, z + tls->zz1); + return AABB{x + tls->xx0, y + tls->yy0, z + tls->zz0, + x + tls->xx1, y + tls->yy1, z + tls->zz1}; } bool Tile::isSolidRender(bool isServerLevel) { return true; } @@ -2117,44 +2119,54 @@ float Tile::getExplosionResistance(std::shared_ptr source) { return explosionResistance / 5.0f; } -HitResult* Tile::clip(Level* level, int xt, int yt, int zt, Vec3* a, Vec3* b) { +HitResult* Tile::clip(Level* level, int xt, int yt, int zt, Vec3* a_, + Vec3* b_) { updateShape(level, xt, yt, zt); - a = a->add(-xt, -yt, -zt); - b = b->add(-xt, -yt, -zt); + Vec3 a = a_->add(-xt, -yt, -zt); + Vec3 b = b_->add(-xt, -yt, -zt); ThreadStorage* tls = m_tlsShape; - Vec3* xh0 = a->clipX(b, tls->xx0); - Vec3* xh1 = a->clipX(b, tls->xx1); - Vec3* yh0 = a->clipY(b, tls->yy0); - Vec3* yh1 = a->clipY(b, tls->yy1); + auto xh0 = a.clipX(b, tls->xx0); + auto xh1 = a.clipX(b, tls->xx1); - Vec3* zh0 = a->clipZ(b, tls->zz0); - Vec3* zh1 = a->clipZ(b, tls->zz1); + auto yh0 = a.clipY(b, tls->yy0); + auto yh1 = a.clipY(b, tls->yy1); - Vec3* closest = NULL; + auto zh0 = a.clipZ(b, tls->zz0); + auto zh1 = a.clipZ(b, tls->zz1); - if (containsX(xh0) && - (closest == NULL || a->distanceToSqr(xh0) < a->distanceToSqr(closest))) + std::optional closest = std::nullopt; + + // 4jcraft NOTE: containsX does a nullopt check and will short circuit so + // dereffing in distanceToSqr is fine. + + if (containsX(xh0) && (!closest.has_value() || + a.distanceToSqr(*xh0) < a.distanceToSqr(*closest))) closest = xh0; - if (containsX(xh1) && - (closest == NULL || a->distanceToSqr(xh1) < a->distanceToSqr(closest))) + + if (containsX(xh1) && (!closest.has_value() || + a.distanceToSqr(*xh1) < a.distanceToSqr(*closest))) closest = xh1; - if (containsY(yh0) && - (closest == NULL || a->distanceToSqr(yh0) < a->distanceToSqr(closest))) + + if (containsY(yh0) && (!closest.has_value() || + a.distanceToSqr(*yh0) < a.distanceToSqr(*closest))) closest = yh0; - if (containsY(yh1) && - (closest == NULL || a->distanceToSqr(yh1) < a->distanceToSqr(closest))) + + if (containsY(yh1) && (!closest.has_value() || + a.distanceToSqr(*yh1) < a.distanceToSqr(*closest))) closest = yh1; - if (containsZ(zh0) && - (closest == NULL || a->distanceToSqr(zh0) < a->distanceToSqr(closest))) + + if (containsZ(zh0) && (!closest.has_value() || + a.distanceToSqr(*zh0) < a.distanceToSqr(*closest))) closest = zh0; - if (containsZ(zh1) && - (closest == NULL || a->distanceToSqr(zh1) < a->distanceToSqr(closest))) + + if (containsZ(zh1) && (!closest.has_value() || + a.distanceToSqr(*zh1) < a.distanceToSqr(*closest))) closest = zh1; - if (closest == NULL) return NULL; + if (!closest.has_value()) return nullptr; int face = -1; @@ -2168,8 +2180,8 @@ HitResult* Tile::clip(Level* level, int xt, int yt, int zt, Vec3* a, Vec3* b) { return new HitResult(xt, yt, zt, face, closest->add(xt, yt, zt)); } -bool Tile::containsX(Vec3* v) { - if (v == NULL) return false; +bool Tile::containsX(const std::optional& v) { + if (!v.has_value()) return false; ThreadStorage* tls = m_tlsShape; // 4J Stu - Added this so that the TLS shape is correct for this tile @@ -2178,8 +2190,8 @@ bool Tile::containsX(Vec3* v) { v->z <= tls->zz1; } -bool Tile::containsY(Vec3* v) { - if (v == NULL) return false; +bool Tile::containsY(const std::optional& v) { + if (!v.has_value()) return false; ThreadStorage* tls = m_tlsShape; // 4J Stu - Added this so that the TLS shape is correct for this tile @@ -2188,8 +2200,8 @@ bool Tile::containsY(Vec3* v) { v->z <= tls->zz1; } -bool Tile::containsZ(Vec3* v) { - if (v == NULL) return false; +bool Tile::containsZ(const std::optional& v) { + if (!v.has_value()) return false; ThreadStorage* tls = m_tlsShape; // 4J Stu - Added this so that the TLS shape is correct for this tile diff --git a/Minecraft.World/Blocks/Tile.h b/Minecraft.World/Blocks/Tile.h index b46748ff5..8c9d33566 100644 --- a/Minecraft.World/Blocks/Tile.h +++ b/Minecraft.World/Blocks/Tile.h @@ -4,6 +4,7 @@ #include "../Util/Definitions.h" #include "../Util/SoundTypes.h" #include +#include class GrassTile; class LeafTile; @@ -630,10 +631,10 @@ public: virtual Icon* getTexture(LevelSource* level, int x, int y, int z, int face); virtual Icon* getTexture(int face, int data); virtual Icon* getTexture(int face); - virtual AABB* getTileAABB(Level* level, int x, int y, int z); + virtual AABB getTileAABB(Level* level, int x, int y, int z); virtual void addAABBs(Level* level, int x, int y, int z, AABB* box, AABBList* boxes, std::shared_ptr source); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual bool isSolidRender( bool isServerLevel = false); // 4J - Added isServerLevel param virtual bool mayPick(int data, bool liquid); @@ -667,9 +668,9 @@ public: Vec3* b); private: - virtual bool containsX(Vec3* v); - virtual bool containsY(Vec3* v); - virtual bool containsZ(Vec3* v); + virtual bool containsX(const std::optional& v); + virtual bool containsY(const std::optional& v); + virtual bool containsZ(const std::optional& v); public: virtual void wasExploded(Level* level, int x, int y, int z, diff --git a/Minecraft.World/Blocks/TileEntities/BeaconTileEntity.cpp b/Minecraft.World/Blocks/TileEntities/BeaconTileEntity.cpp index 5b160f153..738303f3c 100644 --- a/Minecraft.World/Blocks/TileEntities/BeaconTileEntity.cpp +++ b/Minecraft.World/Blocks/TileEntities/BeaconTileEntity.cpp @@ -70,11 +70,10 @@ void BeaconTileEntity::applyEffects() { baseAmp = 1; } - AABB* bb = AABB::newTemp(x, y, z, x + 1, y + 1, z + 1) - ->grow(range, range, range); - bb->y1 = level->getMaxBuildHeight(); + AABB bb = AABB(x, y, z, x + 1, y + 1, z + 1).grow(range, range, range); + bb.y1 = level->getMaxBuildHeight(); std::vector >* players = - level->getEntitiesOfClass(typeid(Player), bb); + level->getEntitiesOfClass(typeid(Player), &bb); for (AUTO_VAR(it, players->begin()); it != players->end(); ++it) { std::shared_ptr player = std::dynamic_pointer_cast(*it); @@ -299,4 +298,4 @@ bool BeaconTileEntity::canPlaceItem(int slot, std::shared_ptr item) { return (item->id == Item::emerald_Id || item->id == Item::diamond_Id || item->id == Item::goldIngot_Id || item->id == Item::ironIngot_Id); -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/TileEntities/ChestTileEntity.cpp b/Minecraft.World/Blocks/TileEntities/ChestTileEntity.cpp index d1cbd500b..d66c15c24 100644 --- a/Minecraft.World/Blocks/TileEntities/ChestTileEntity.cpp +++ b/Minecraft.World/Blocks/TileEntities/ChestTileEntity.cpp @@ -242,11 +242,10 @@ void ChestTileEntity::tick() { openCount = 0; float range = 5; + AABB player_aabb(x - range, y - range, z - range, x + 1 + range, + y + 1 + range, z + 1 + range); std::vector >* players = - level->getEntitiesOfClass( - typeid(Player), - AABB::newTemp(x - range, y - range, z - range, x + 1 + range, - y + 1 + range, z + 1 + range)); + level->getEntitiesOfClass(typeid(Player), &player_aabb); for (AUTO_VAR(it, players->begin()); it != players->end(); ++it) { std::shared_ptr player = std::dynamic_pointer_cast(*it); @@ -383,4 +382,4 @@ std::shared_ptr ChestTileEntity::clone() { } } return result; -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/TileEntities/HopperTileEntity.cpp b/Minecraft.World/Blocks/TileEntities/HopperTileEntity.cpp index 36da69010..26ed8f516 100644 --- a/Minecraft.World/Blocks/TileEntities/HopperTileEntity.cpp +++ b/Minecraft.World/Blocks/TileEntities/HopperTileEntity.cpp @@ -345,9 +345,10 @@ std::shared_ptr HopperTileEntity::getSourceContainer( std::shared_ptr HopperTileEntity::getItemAt(Level* level, double xt, double yt, double zt) { - std::vector >* entities = level->getEntitiesOfClass( - typeid(ItemEntity), AABB::newTemp(xt, yt, zt, xt + 1, yt + 1, zt + 1), - EntitySelector::ENTITY_STILL_ALIVE); + AABB item_entity_aabb{xt, yt, zt, xt + 1, yt + 1, zt + 1}; + std::vector >* entities = + level->getEntitiesOfClass(typeid(ItemEntity), &item_entity_aabb, + EntitySelector::ENTITY_STILL_ALIVE); if (entities->size() > 0) { std::shared_ptr out = @@ -384,9 +385,9 @@ std::shared_ptr HopperTileEntity::getContainerAt(Level* level, } if (result == NULL) { + AABB block_above{x, y, z, x + 1, y + 1, z + 1}; std::vector >* entities = level->getEntities( - nullptr, AABB::newTemp(x, y, z, x + 1, y + 1, z + 1), - EntitySelector::CONTAINER_ENTITY_SELECTOR); + nullptr, &block_above, EntitySelector::CONTAINER_ENTITY_SELECTOR); if ((entities != NULL) && (entities->size() > 0)) { result = std::dynamic_pointer_cast( @@ -432,4 +433,4 @@ std::shared_ptr HopperTileEntity::clone() { } } return result; -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/TileEntities/PistonPieceTileEntity.cpp b/Minecraft.World/Blocks/TileEntities/PistonPieceTileEntity.cpp index fb49032ca..84d73b9c7 100644 --- a/Minecraft.World/Blocks/TileEntities/PistonPieceTileEntity.cpp +++ b/Minecraft.World/Blocks/TileEntities/PistonPieceTileEntity.cpp @@ -5,6 +5,7 @@ #include "../../Headers/net.minecraft.world.level.h" #include "../../Util/Facing.h" #include "../Tile.h" +#include "../../Util/AABB.h" PistonPieceEntity::PistonPieceEntity() { // for the tile entity loader @@ -81,11 +82,11 @@ void PistonPieceEntity::moveCollidedEntities(float progress, float amount) { progress = progress - 1.0f; } - AABB* aabb = + auto aabb = Tile::pistonMovingPiece->getAABB(level, x, y, z, id, progress, facing); - if (aabb != NULL) { + if (aabb.has_value()) { std::vector >* entities = - level->getEntities(nullptr, aabb); + level->getEntities(nullptr, &*aabb); if (!entities->empty()) { std::vector > collisionHolder; for (AUTO_VAR(it, entities->begin()); it != entities->end(); it++) { diff --git a/Minecraft.World/Blocks/TileEntities/TileEntity.cpp b/Minecraft.World/Blocks/TileEntities/TileEntity.cpp index 24986046f..66ae1afac 100644 --- a/Minecraft.World/Blocks/TileEntities/TileEntity.cpp +++ b/Minecraft.World/Blocks/TileEntities/TileEntity.cpp @@ -187,6 +187,15 @@ void TileEntity::upgradeRenderRemoveStage() { } } +bool TileEntity::finalizeRenderRemoveStage() { + if (renderRemoveStage == e_RenderRemoveStageFlaggedAtChunk) { + renderRemoveStage = e_RenderRemoveStageRemove; + return true; + } + + return renderRemoveStage == e_RenderRemoveStageRemove; +} + // 4J Added void TileEntity::clone(std::shared_ptr tileEntity) { tileEntity->level = this->level; @@ -195,4 +204,4 @@ void TileEntity::clone(std::shared_ptr tileEntity) { tileEntity->z = this->z; tileEntity->data = this->data; tileEntity->tile = this->tile; -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/TileEntities/TileEntity.h b/Minecraft.World/Blocks/TileEntities/TileEntity.h index e640ae2e4..fc382b673 100644 --- a/Minecraft.World/Blocks/TileEntities/TileEntity.h +++ b/Minecraft.World/Blocks/TileEntities/TileEntity.h @@ -49,6 +49,7 @@ public: void setRenderRemoveStage(unsigned char stage); // 4J added void upgradeRenderRemoveStage(); // 4J added + bool finalizeRenderRemoveStage(); // 4J added bool shouldRemoveForRender(); // 4J added virtual Level* getLevel(); @@ -77,4 +78,4 @@ public: protected: void clone(std::shared_ptr tileEntity); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/TopSnowTile.cpp b/Minecraft.World/Blocks/TopSnowTile.cpp index 8ba44c61b..cd5182116 100644 --- a/Minecraft.World/Blocks/TopSnowTile.cpp +++ b/Minecraft.World/Blocks/TopSnowTile.cpp @@ -21,11 +21,11 @@ void TopSnowTile::registerIcons(IconRegister* iconRegister) { icon = iconRegister->registerIcon(L"snow"); } -AABB* TopSnowTile::getAABB(Level* level, int x, int y, int z) { +std::optional TopSnowTile::getAABB(Level* level, int x, int y, int z) { int height = level->getData(x, y, z) & HEIGHT_MASK; float offset = 2.0f / SharedConstants::WORLD_RESOLUTION; ThreadStorage* tls = m_tlsShape; - return AABB::newTemp(x + tls->xx0, y + tls->yy0, z + tls->zz0, x + tls->xx1, + return AABB(x + tls->xx0, y + tls->yy0, z + tls->zz0, x + tls->xx1, y + (height * offset), z + tls->zz1); } diff --git a/Minecraft.World/Blocks/TopSnowTile.h b/Minecraft.World/Blocks/TopSnowTile.h index 710aab8b8..bfa529d76 100644 --- a/Minecraft.World/Blocks/TopSnowTile.h +++ b/Minecraft.World/Blocks/TopSnowTile.h @@ -16,7 +16,7 @@ protected: public: void registerIcons(IconRegister* iconRegister); - AABB* getAABB(Level* level, int x, int y, int z); + std::optional getAABB(Level* level, int x, int y, int z); public: static float getHeight(Level* level, int x, int y, int z); diff --git a/Minecraft.World/Blocks/TorchTile.cpp b/Minecraft.World/Blocks/TorchTile.cpp index bca94562f..4932ff4fc 100644 --- a/Minecraft.World/Blocks/TorchTile.cpp +++ b/Minecraft.World/Blocks/TorchTile.cpp @@ -3,14 +3,16 @@ #include "../Headers/net.minecraft.world.level.h" #include "../Headers/net.minecraft.world.level.tile.h" #include "TorchTile.h" +#include +#include "Util/AABB.h" TorchTile::TorchTile(int id) : Tile(id, Material::decoration, false) { this->setTicking(true); } -AABB* TorchTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional TorchTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } -AABB* TorchTile::getTileAABB(Level* level, int x, int y, int z) { +AABB TorchTile::getTileAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); return Tile::getTileAABB(level, x, y, z); } diff --git a/Minecraft.World/Blocks/TorchTile.h b/Minecraft.World/Blocks/TorchTile.h index 0369a3584..525f851cc 100644 --- a/Minecraft.World/Blocks/TorchTile.h +++ b/Minecraft.World/Blocks/TorchTile.h @@ -12,8 +12,8 @@ protected: TorchTile(int id); public: - virtual AABB* getAABB(Level* level, int x, int y, int z); - virtual AABB* getTileAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); + virtual AABB getTileAABB(Level* level, int x, int y, int z); virtual void updateShape( LevelSource* level, int x, int y, int z, int forceData = -1, std::shared_ptr forceEntity = std::shared_ptr< diff --git a/Minecraft.World/Blocks/TrapDoorTile.cpp b/Minecraft.World/Blocks/TrapDoorTile.cpp index eb685504d..7a6e46e5a 100644 --- a/Minecraft.World/Blocks/TrapDoorTile.cpp +++ b/Minecraft.World/Blocks/TrapDoorTile.cpp @@ -4,6 +4,7 @@ #include "../Headers/net.minecraft.world.level.tile.h" #include "../Headers/net.minecraft.h" #include "TrapDoorTile.h" +#include "Util/AABB.h" TrapDoorTile::TrapDoorTile(int id, Material* material) : Tile(id, material, false) { @@ -24,12 +25,12 @@ bool TrapDoorTile::isPathfindable(LevelSource* level, int x, int y, int z) { int TrapDoorTile::getRenderShape() { return Tile::SHAPE_BLOCK; } -AABB* TrapDoorTile::getTileAABB(Level* level, int x, int y, int z) { +AABB TrapDoorTile::getTileAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); return Tile::getTileAABB(level, x, y, z); } -AABB* TrapDoorTile::getAABB(Level* level, int x, int y, int z) { +std::optional TrapDoorTile::getAABB(Level* level, int x, int y, int z) { updateShape(level, x, y, z); return Tile::getAABB(level, x, y, z); } @@ -175,4 +176,4 @@ bool TrapDoorTile::attachesTo(int id) { tile == Tile::glowstone || (dynamic_cast(tile) != NULL) || (dynamic_cast(tile) != NULL); -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/TrapDoorTile.h b/Minecraft.World/Blocks/TrapDoorTile.h index f2e978759..8ef150568 100644 --- a/Minecraft.World/Blocks/TrapDoorTile.h +++ b/Minecraft.World/Blocks/TrapDoorTile.h @@ -37,10 +37,10 @@ public: int getRenderShape(); public: - AABB* getTileAABB(Level* level, int x, int y, int z); + AABB getTileAABB(Level* level, int x, int y, int z); public: - AABB* getAABB(Level* level, int x, int y, int z); + std::optional getAABB(Level* level, int x, int y, int z); public: void updateShape(LevelSource* level, int x, int y, int z, @@ -91,4 +91,4 @@ public: private: static bool attachesTo(int id); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/TripWireSourceTile.cpp b/Minecraft.World/Blocks/TripWireSourceTile.cpp index 14fc620b9..c9115901e 100644 --- a/Minecraft.World/Blocks/TripWireSourceTile.cpp +++ b/Minecraft.World/Blocks/TripWireSourceTile.cpp @@ -4,14 +4,16 @@ #include "../Headers/net.minecraft.world.level.tile.h" #include "../Headers/net.minecraft.world.level.redstone.h" #include "TripWireSourceTile.h" +#include "optional" +#include "Util/AABB.h" TripWireSourceTile::TripWireSourceTile(int id) : Tile(id, Material::decoration, false) { this->setTicking(true); } -AABB* TripWireSourceTile::getAABB(Level* level, int x, int y, int z) { - return NULL; +std::optional TripWireSourceTile::getAABB(Level* level, int x, int y, int z) { + return std::nullopt; } bool TripWireSourceTile::blocksLight() { return false; } diff --git a/Minecraft.World/Blocks/TripWireSourceTile.h b/Minecraft.World/Blocks/TripWireSourceTile.h index 9cce09eb6..e23c61feb 100644 --- a/Minecraft.World/Blocks/TripWireSourceTile.h +++ b/Minecraft.World/Blocks/TripWireSourceTile.h @@ -14,7 +14,7 @@ public: TripWireSourceTile(int id); - AABB* getAABB(Level* level, int x, int y, int z); + std::optional getAABB(Level* level, int x, int y, int z); bool blocksLight(); bool isSolidRender(bool isServerLevel = false); bool isCubeShaped(); diff --git a/Minecraft.World/Blocks/TripWireTile.cpp b/Minecraft.World/Blocks/TripWireTile.cpp index 0118aa0a1..e72ea5cdd 100644 --- a/Minecraft.World/Blocks/TripWireTile.cpp +++ b/Minecraft.World/Blocks/TripWireTile.cpp @@ -4,6 +4,7 @@ #include "../Headers/net.minecraft.world.level.tile.h" #include "../Headers/net.minecraft.world.phys.h" #include "TripWireTile.h" +#include TripWireTile::TripWireTile(int id) : Tile(id, Material::decoration, false) { setShape(0, 0, 0, 1, 2.5f / 16.0f, 1); @@ -16,7 +17,7 @@ int TripWireTile::getTickDelay(Level* level) { return 20; // 10; } -AABB* TripWireTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional TripWireTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } bool TripWireTile::blocksLight() { return false; } @@ -132,9 +133,10 @@ void TripWireTile::checkPressed(Level* level, int x, int y, int z) { bool shouldBePressed = false; ThreadStorage* tls = m_tlsShape; - std::vector >* entities = level->getEntities( - nullptr, AABB::newTemp(x + tls->xx0, y + tls->yy0, z + tls->zz0, - x + tls->xx1, y + tls->yy1, z + tls->zz1)); + AABB offs_aabb(x + tls->xx0, y + tls->yy0, z + tls->zz0, x + tls->xx1, + y + tls->yy1, z + tls->zz1); + std::vector >* entities = + level->getEntities(nullptr, &offs_aabb); if (!entities->empty()) { for (AUTO_VAR(it, entities->begin()); it != entities->end(); ++it) { std::shared_ptr e = *it; diff --git a/Minecraft.World/Blocks/TripWireTile.h b/Minecraft.World/Blocks/TripWireTile.h index f6c7becef..6963d0305 100644 --- a/Minecraft.World/Blocks/TripWireTile.h +++ b/Minecraft.World/Blocks/TripWireTile.h @@ -14,7 +14,7 @@ public: TripWireTile(int id); int getTickDelay(Level* level); - AABB* getAABB(Level* level, int x, int y, int z); + std::optional getAABB(Level* level, int x, int y, int z); bool blocksLight(); bool isSolidRender(bool isServerLevel = false); bool isCubeShaped(); diff --git a/Minecraft.World/Blocks/VineTile.cpp b/Minecraft.World/Blocks/VineTile.cpp index d2febbaa9..787fb4588 100644 --- a/Minecraft.World/Blocks/VineTile.cpp +++ b/Minecraft.World/Blocks/VineTile.cpp @@ -7,6 +7,7 @@ #include "../Headers/net.minecraft.world.item.h" #include "../Headers/net.minecraft.stats.h" #include "../Headers/net.minecraft.world.level.biome.h" +#include "Util/AABB.h" VineTile::VineTile(int id) : Tile(id, Material::replaceable_plant, false) { @@ -85,7 +86,7 @@ void VineTile::updateShape( setShape(minX, minY, minZ, maxX, maxY, maxZ); } -AABB* VineTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional VineTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } bool VineTile::mayPlace(Level* level, int x, int y, int z, int face) { switch (face) { diff --git a/Minecraft.World/Blocks/VineTile.h b/Minecraft.World/Blocks/VineTile.h index 965eba70f..dc123a38c 100644 --- a/Minecraft.World/Blocks/VineTile.h +++ b/Minecraft.World/Blocks/VineTile.h @@ -21,7 +21,7 @@ public: LevelSource* level, int x, int y, int z, int forceData = -1, std::shared_ptr forceEntity = std::shared_ptr< TileEntity>()); // 4J added forceData, forceEntity param - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual bool mayPlace(Level* level, int x, int y, int z, int face); private: @@ -43,4 +43,4 @@ public: virtual int getResourceCount(Random* random); virtual void playerDestroy(Level* level, std::shared_ptr player, int x, int y, int z, int data); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/WallTile.cpp b/Minecraft.World/Blocks/WallTile.cpp index 67d3c0bae..a072b82c8 100644 --- a/Minecraft.World/Blocks/WallTile.cpp +++ b/Minecraft.World/Blocks/WallTile.cpp @@ -80,7 +80,7 @@ void WallTile::updateShape(LevelSource* level, int x, int y, int z, setShape(west, 0, north, east, up, south); } -AABB* WallTile::getAABB(Level* level, int x, int y, int z) { +std::optional WallTile::getAABB(Level* level, int x, int y, int z) { // 4J-JEV: Changed to avoid race conditions associated with calling update // shape. @@ -125,7 +125,7 @@ AABB* WallTile::getAABB(Level* level, int x, int y, int z) { // south = .5f + WALL_WIDTH; } - return AABB::newTemp(x + west, y, z + north, x + east, y + 1.5f, z + south); + return AABB(x + west, y, z + north, x + east, y + 1.5f, z + south); } bool WallTile::connectsTo(LevelSource* level, int x, int y, int z) { diff --git a/Minecraft.World/Blocks/WallTile.h b/Minecraft.World/Blocks/WallTile.h index 634253966..7f5a963c6 100644 --- a/Minecraft.World/Blocks/WallTile.h +++ b/Minecraft.World/Blocks/WallTile.h @@ -25,9 +25,9 @@ public: int forceData = -1, std::shared_ptr forceEntity = std::shared_ptr()); - AABB* getAABB(Level* level, int x, int y, int z); + std::optional getAABB(Level* level, int x, int y, int z); bool connectsTo(LevelSource* level, int x, int y, int z); int getSpawnResourcesAuxValue(int data); bool shouldRenderFace(LevelSource* level, int x, int y, int z, int face); void registerIcons(IconRegister* iconRegister); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/WaterLilyTile.cpp b/Minecraft.World/Blocks/WaterLilyTile.cpp index 3ea6660a4..ce0a7d2be 100644 --- a/Minecraft.World/Blocks/WaterLilyTile.cpp +++ b/Minecraft.World/Blocks/WaterLilyTile.cpp @@ -23,11 +23,11 @@ void WaterlilyTile::addAABBs(Level* level, int x, int y, int z, AABB* box, } } -AABB* WaterlilyTile::getAABB(Level* level, int x, int y, int z) { +std::optional WaterlilyTile::getAABB(Level* level, int x, int y, int z) { ThreadStorage* tls = m_tlsShape; // 4J Stu - Added this so that the TLS shape is correct for this tile if (tls->tileId != this->id) updateDefaultShape(); - return AABB::newTemp(x + tls->xx0, y + tls->yy0, z + tls->zz0, x + tls->xx1, + return AABB(x + tls->xx0, y + tls->yy0, z + tls->zz0, x + tls->xx1, y + tls->yy1, z + tls->zz1); } diff --git a/Minecraft.World/Blocks/WaterLilyTile.h b/Minecraft.World/Blocks/WaterLilyTile.h index 81143ddfd..23b39fdc0 100644 --- a/Minecraft.World/Blocks/WaterLilyTile.h +++ b/Minecraft.World/Blocks/WaterLilyTile.h @@ -12,7 +12,7 @@ public: virtual int getRenderShape(); virtual void addAABBs(Level* level, int x, int y, int z, AABB* box, AABBList* boxes, std::shared_ptr source); - virtual AABB* getAABB(Level* level, int x, int y, int z); + virtual std::optional getAABB(Level* level, int x, int y, int z); virtual int getColor() const; virtual int getColor(int auxData); virtual int getColor(LevelSource* level, int x, int y, int z); diff --git a/Minecraft.World/Blocks/WebTile.cpp b/Minecraft.World/Blocks/WebTile.cpp index ffc4137d5..26e8e909a 100644 --- a/Minecraft.World/Blocks/WebTile.cpp +++ b/Minecraft.World/Blocks/WebTile.cpp @@ -2,6 +2,7 @@ #include "../Headers/net.minecraft.world.entity.h" #include "../Headers/net.minecraft.world.item.h" #include "WebTile.h" +#include "Util/AABB.h" WebTile::WebTile(int id) : Tile(id, Material::web) {} @@ -12,7 +13,7 @@ void WebTile::entityInside(Level* level, int x, int y, int z, bool WebTile::isSolidRender(bool isServerLevel) { return false; } -AABB* WebTile::getAABB(Level* level, int x, int y, int z) { return NULL; } +std::optional WebTile::getAABB(Level* level, int x, int y, int z) { return std::nullopt; } int WebTile::getRenderShape() { return Tile::SHAPE_CROSS_TEXTURE; } @@ -25,4 +26,4 @@ int WebTile::getResource(int data, Random* random, int playerBonusLevel) { return Item::string->id; } -bool WebTile::isSilkTouchable() { return true; } \ No newline at end of file +bool WebTile::isSilkTouchable() { return true; } diff --git a/Minecraft.World/Blocks/WebTile.h b/Minecraft.World/Blocks/WebTile.h index 1512cd92d..5b8049d6b 100644 --- a/Minecraft.World/Blocks/WebTile.h +++ b/Minecraft.World/Blocks/WebTile.h @@ -14,7 +14,7 @@ public: bool isSolidRender(bool isServerLevel = false); public: - AABB* getAABB(Level* level, int x, int y, int z); + std::optional getAABB(Level* level, int x, int y, int z); public: int getRenderShape(); @@ -25,4 +25,4 @@ public: protected: bool isSilkTouchable(); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Blocks/WeightedPressurePlateTile.cpp b/Minecraft.World/Blocks/WeightedPressurePlateTile.cpp index 55e1b5a15..e31a7c451 100644 --- a/Minecraft.World/Blocks/WeightedPressurePlateTile.cpp +++ b/Minecraft.World/Blocks/WeightedPressurePlateTile.cpp @@ -5,6 +5,7 @@ #include "../Headers/net.minecraft.world.item.h" #include "../Entities/Entity.h" #include "WeightedPressurePlateTile.h" +#include "Util/AABB.h" WeightedPressurePlateTile::WeightedPressurePlateTile(int id, const std::wstring& tex, @@ -19,8 +20,9 @@ WeightedPressurePlateTile::WeightedPressurePlateTile(int id, int WeightedPressurePlateTile::getSignalStrength(Level* level, int x, int y, int z) { + AABB at_bb = getSensitiveAABB(x, y, z); int weightOfEntities = - level->getEntitiesOfClass(typeid(Entity), getSensitiveAABB(x, y, z)) + level->getEntitiesOfClass(typeid(Entity), &at_bb) ->size(); int count = std::min(weightOfEntities, maxWeight); @@ -38,4 +40,4 @@ int WeightedPressurePlateTile::getDataForSignal(int signal) { return signal; } int WeightedPressurePlateTile::getTickDelay(Level* level) { return SharedConstants::TICKS_PER_SECOND / 2; -} \ No newline at end of file +} diff --git a/Minecraft.World/Blocks/WoolCarpetTile.cpp b/Minecraft.World/Blocks/WoolCarpetTile.cpp index 2800a94c0..030285d7f 100644 --- a/Minecraft.World/Blocks/WoolCarpetTile.cpp +++ b/Minecraft.World/Blocks/WoolCarpetTile.cpp @@ -15,13 +15,13 @@ Icon* WoolCarpetTile::getTexture(int face, int data) { return Tile::wool->getTexture(face, data); } -AABB* WoolCarpetTile::getAABB(Level* level, int x, int y, int z) { +std::optional WoolCarpetTile::getAABB(Level* level, int x, int y, int z) { int height = 0; float offset = 1.0f / SharedConstants::WORLD_RESOLUTION; ThreadStorage* tls = m_tlsShape; // 4J Stu - Added this so that the TLS shape is correct for this tile if (tls->tileId != this->id) updateDefaultShape(); - return AABB::newTemp(x + tls->xx0, y + tls->yy0, z + tls->zz0, x + tls->xx1, + return AABB(x + tls->xx0, y + tls->yy0, z + tls->zz0, x + tls->xx1, y + (height * offset), z + tls->zz1); } diff --git a/Minecraft.World/Blocks/WoolCarpetTile.h b/Minecraft.World/Blocks/WoolCarpetTile.h index 7ad28797c..cb473c2f1 100644 --- a/Minecraft.World/Blocks/WoolCarpetTile.h +++ b/Minecraft.World/Blocks/WoolCarpetTile.h @@ -1,5 +1,6 @@ #pragma once +#include #include "Tile.h" class WoolCarpetTile : public Tile { @@ -10,7 +11,7 @@ protected: public: Icon* getTexture(int face, int data); - AABB* getAABB(Level* level, int x, int y, int z); + std::optional getAABB(Level* level, int x, int y, int z); bool blocksLight(); bool isSolidRender(bool isServerLevel = false); bool isCubeShaped(); @@ -37,4 +38,4 @@ public: static int getTileDataForItemAuxValue(int auxValue); static int getItemAuxValueForTileData(int data); void registerIcons(IconRegister* iconRegister); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Containers/HorseInventoryMenu.cpp b/Minecraft.World/Containers/HorseInventoryMenu.cpp index e4766aaef..a492bb442 100644 --- a/Minecraft.World/Containers/HorseInventoryMenu.cpp +++ b/Minecraft.World/Containers/HorseInventoryMenu.cpp @@ -113,4 +113,4 @@ void HorseInventoryMenu::removed(std::shared_ptr player) { std::shared_ptr HorseInventoryMenu::getContainer() { return horseContainer; -} \ No newline at end of file +} diff --git a/Minecraft.World/Containers/RepairContainer.h b/Minecraft.World/Containers/RepairContainer.h index edb7a6756..1494a1099 100644 --- a/Minecraft.World/Containers/RepairContainer.h +++ b/Minecraft.World/Containers/RepairContainer.h @@ -11,6 +11,6 @@ private: public: RepairContainer(AnvilMenu* menu, int name, bool customName, int size); - void setChanged(); - bool canPlaceItem(int slot, std::shared_ptr item); + void setChanged() override; + bool canPlaceItem(int slot, std::shared_ptr item) override; }; \ No newline at end of file diff --git a/Minecraft.World/Containers/RepairResultSlot.h b/Minecraft.World/Containers/RepairResultSlot.h index 1f8f0f4ea..2dc6b5c17 100644 --- a/Minecraft.World/Containers/RepairResultSlot.h +++ b/Minecraft.World/Containers/RepairResultSlot.h @@ -14,9 +14,10 @@ public: std::shared_ptr container, int slot, int x, int y); - bool mayPlace(std::shared_ptr item); - bool mayPickup(std::shared_ptr player); + bool mayPlace(std::shared_ptr item) override; + bool mayPickup(std::shared_ptr player) override; void onTake(std::shared_ptr player, - std::shared_ptr carried); - virtual bool mayCombine(std::shared_ptr item); // 4J Added + std::shared_ptr carried) override; + virtual bool mayCombine( + std::shared_ptr item) override; // 4J Added }; \ No newline at end of file diff --git a/Minecraft.World/Containers/ResultContainer.h b/Minecraft.World/Containers/ResultContainer.h index 69ed8ed1e..dc4ff7a9e 100644 --- a/Minecraft.World/Containers/ResultContainer.h +++ b/Minecraft.World/Containers/ResultContainer.h @@ -10,19 +10,21 @@ public: // 4J Stu Added a ctor to init items ResultContainer(); - virtual unsigned int getContainerSize(); - virtual std::shared_ptr getItem(unsigned int slot); - virtual std::wstring getName(); - virtual std::wstring getCustomName(); - virtual bool hasCustomName(); + virtual unsigned int getContainerSize() override; + virtual std::shared_ptr getItem(unsigned int slot) override; + virtual std::wstring getName() override; + virtual std::wstring getCustomName() override; + virtual bool hasCustomName() override; virtual std::shared_ptr removeItem(unsigned int slot, - int count); - virtual std::shared_ptr removeItemNoUpdate(int slot); - virtual void setItem(unsigned int slot, std::shared_ptr item); - virtual int getMaxStackSize(); - virtual void setChanged(); - virtual bool stillValid(std::shared_ptr player); - virtual void startOpen() {} // TODO Auto-generated method stub - virtual void stopOpen() {} // TODO Auto-generated method stub - virtual bool canPlaceItem(int slot, std::shared_ptr item); + int count) override; + virtual std::shared_ptr removeItemNoUpdate(int slot) override; + virtual void setItem(unsigned int slot, + std::shared_ptr item) override; + virtual int getMaxStackSize() override; + virtual void setChanged() override; + virtual bool stillValid(std::shared_ptr player) override; + virtual void startOpen() override {} // TODO Auto-generated method stub + virtual void stopOpen() override {} // TODO Auto-generated method stub + virtual bool canPlaceItem(int slot, + std::shared_ptr item) override; }; \ No newline at end of file diff --git a/Minecraft.World/Containers/ResultSlot.h b/Minecraft.World/Containers/ResultSlot.h index b2a0347f4..46fecd0b2 100644 --- a/Minecraft.World/Containers/ResultSlot.h +++ b/Minecraft.World/Containers/ResultSlot.h @@ -14,15 +14,18 @@ public: std::shared_ptr container, int id, int x, int y); virtual ~ResultSlot() {} - virtual bool mayPlace(std::shared_ptr item); - virtual std::shared_ptr remove(int c); + virtual bool mayPlace(std::shared_ptr item) override; + virtual std::shared_ptr remove(int c) override; protected: - virtual void onQuickCraft(std::shared_ptr picked, int count); - virtual void checkTakeAchievements(std::shared_ptr carried); + virtual void onQuickCraft(std::shared_ptr picked, + int count) override; + virtual void checkTakeAchievements( + std::shared_ptr carried) override; public: virtual void onTake(std::shared_ptr player, - std::shared_ptr carried); - virtual bool mayCombine(std::shared_ptr item); // 4J Added + std::shared_ptr carried) override; + virtual bool mayCombine( + std::shared_ptr item) override; // 4J Added }; \ No newline at end of file diff --git a/Minecraft.World/Containers/SimpleContainer.h b/Minecraft.World/Containers/SimpleContainer.h index 74392b3f3..e9164c1eb 100644 --- a/Minecraft.World/Containers/SimpleContainer.h +++ b/Minecraft.World/Containers/SimpleContainer.h @@ -19,20 +19,22 @@ public: virtual void addListener(net_minecraft_world::ContainerListener* listener); virtual void removeListener( net_minecraft_world::ContainerListener* listener); - virtual std::shared_ptr getItem(unsigned int slot); + virtual std::shared_ptr getItem(unsigned int slot) override; virtual std::shared_ptr removeItem(unsigned int slot, - int count); - virtual std::shared_ptr removeItemNoUpdate(int slot); - virtual void setItem(unsigned int slot, std::shared_ptr item); - virtual unsigned int getContainerSize(); - virtual std::wstring getName(); - virtual std::wstring getCustomName(); - virtual bool hasCustomName(); + int count) override; + virtual std::shared_ptr removeItemNoUpdate(int slot) override; + virtual void setItem(unsigned int slot, + std::shared_ptr item) override; + virtual unsigned int getContainerSize() override; + virtual std::wstring getName() override; + virtual std::wstring getCustomName() override; + virtual bool hasCustomName() override; virtual void setCustomName(const std::wstring& name); - virtual int getMaxStackSize(); - virtual void setChanged(); - virtual bool stillValid(std::shared_ptr player); - virtual void startOpen() {} // TODO Auto-generated method stub - virtual void stopOpen() {} // TODO Auto-generated method stub - virtual bool canPlaceItem(int slot, std::shared_ptr item); + virtual int getMaxStackSize() override; + virtual void setChanged() override; + virtual bool stillValid(std::shared_ptr player) override; + virtual void startOpen() override {} // TODO Auto-generated method stub + virtual void stopOpen() override {} // TODO Auto-generated method stub + virtual bool canPlaceItem(int slot, + std::shared_ptr item) override; }; \ No newline at end of file diff --git a/Minecraft.World/Containers/TrapMenu.h b/Minecraft.World/Containers/TrapMenu.h index 03b818380..c4f38b626 100644 --- a/Minecraft.World/Containers/TrapMenu.h +++ b/Minecraft.World/Containers/TrapMenu.h @@ -18,7 +18,7 @@ public: TrapMenu(std::shared_ptr inventory, std::shared_ptr trap); - virtual bool stillValid(std::shared_ptr player); + virtual bool stillValid(std::shared_ptr player) override; virtual std::shared_ptr quickMoveStack( - std::shared_ptr player, int slotIndex); + std::shared_ptr player, int slotIndex) override; }; \ No newline at end of file diff --git a/Minecraft.World/Entities/Entity.cpp b/Minecraft.World/Entities/Entity.cpp index 1c4170040..64e5a0bb4 100644 --- a/Minecraft.World/Entities/Entity.cpp +++ b/Minecraft.World/Entities/Entity.cpp @@ -23,6 +23,7 @@ #include "../../Minecraft.Client/Level/MultiPlayerLevel.h" #include "../../Minecraft.Client/Player/MultiPlayerLocalPlayer.h" #include +#include #include "../../Minecraft.Client/Level/ServerLevel.h" #include "../../Minecraft.Client/Network/PlayerList.h" @@ -267,7 +268,7 @@ void Entity::_init(bool useSmallId, Level* level) { xd = yd = zd = 0.0; yRot = xRot = 0.0f; yRotO = xRotO = 0.0f; - bb = AABB::newPermanent(0, 0, 0, 0, 0, 0); // 4J Was final + bb = AABB(0, 0, 0, 0, 0, 0); // 4J Was final onGround = false; horizontalCollision = verticalCollision = false; collision = false; @@ -375,7 +376,6 @@ Entity::Entity(Level* level, Entity::~Entity() { freeSmallId(entityId); delete random; - delete bb; } std::shared_ptr Entity::getEntityData() { @@ -401,7 +401,7 @@ void Entity::resetPos() { std::shared_ptr sharedThis = shared_from_this(); while (true && y > 0) { setPos(x, y, z); - if (level->getCubes(sharedThis, bb)->empty()) break; + if (level->getCubes(sharedThis, &bb)->empty()) break; y += 1; } @@ -418,9 +418,9 @@ void Entity::setSize(float w, float h) { bbWidth = w; bbHeight = h; - bb->x1 = bb->x0 + bbWidth; - bb->z1 = bb->z0 + bbWidth; - bb->y1 = bb->y0 + bbHeight; + bb.x1 = bb.x0 + bbWidth; + bb.z1 = bb.z0 + bbWidth; + bb.y1 = bb.y0 + bbHeight; if (bbWidth > oldW && !firstTick && !level->isClientSide) { move(oldW - bbWidth, 0, oldW - bbWidth); @@ -462,8 +462,8 @@ void Entity::setPos(double x, double y, double z) { this->z = z; float w = bbWidth / 2; float h = bbHeight; - bb->set(x - w, y - heightOffset + ySlideOffset, z - w, x + w, - y - heightOffset + ySlideOffset + h, z + w); + bb = {x - w, y - heightOffset + ySlideOffset, z - w, + x + w, y - heightOffset + ySlideOffset + h, z + w}; } void Entity::turn(float xo, float yo) { @@ -550,7 +550,7 @@ void Entity::baseTick() { if (t > 0) { level->addParticle(PARTICLE_TILECRACK(t, d), x + (random->nextFloat() - 0.5) * bbWidth, - bb->y0 + 0.1, + bb.y0 + 0.1, z + (random->nextFloat() - 0.5) * bbWidth, -xd * 4, 1.5, -zd * 4); } @@ -617,18 +617,18 @@ void Entity::clearFire() { onFire = 0; } void Entity::outOfWorld() { remove(); } bool Entity::isFree(float xa, float ya, float za, float grow) { - AABB* box = bb->grow(grow, grow, grow)->cloneMove(xa, ya, za); - AABBList* aABBs = level->getCubes(shared_from_this(), box); + AABB box = bb.grow(grow, grow, grow).move(xa, ya, za); + AABBList* aABBs = level->getCubes(shared_from_this(), &box); if (!aABBs->empty()) return false; - if (level->containsAnyLiquid(box)) return false; + if (level->containsAnyLiquid(&box)) return false; return true; } bool Entity::isFree(double xa, double ya, double za) { - AABB* box = bb->cloneMove(xa, ya, za); - AABBList* aABBs = level->getCubes(shared_from_this(), box); + AABB box = bb.move(xa, ya, za); + AABBList* aABBs = level->getCubes(shared_from_this(), &box); if (!aABBs->empty()) return false; - if (level->containsAnyLiquid(box)) return false; + if (level->containsAnyLiquid(&box)) return false; return true; } @@ -636,10 +636,10 @@ void Entity::move(double xa, double ya, double za, bool noEntityCubes) // 4J - added noEntityCubes parameter { if (noPhysics) { - bb->move(xa, ya, za); - x = (bb->x0 + bb->x1) / 2.0f; - y = bb->y0 + heightOffset - ySlideOffset; - z = (bb->z0 + bb->z1) / 2.0f; + bb = bb.move(xa, ya, za); + x = (bb.x0 + bb.x1) / 2.0f; + y = bb.y0 + heightOffset - ySlideOffset; + z = (bb.z0 + bb.z1) / 2.0f; return; } @@ -664,16 +664,17 @@ void Entity::move(double xa, double ya, double za, double yaOrg = ya; double zaOrg = za; - AABB* bbOrg = bb->copy(); + AABB bbOrg = bb; bool isPlayerSneaking = onGround && isSneaking() && instanceof(eTYPE_PLAYER); if (isPlayerSneaking) { double d = 0.05; + + AABB translated_bb = bb.move(xa, -1.0, 0.0); while (xa != 0 && - level->getCubes(shared_from_this(), bb->cloneMove(xa, -1.0, 0)) - ->empty()) { + level->getCubes(shared_from_this(), &translated_bb)->empty()) { if (xa < d && xa >= -d) xa = 0; else if (xa > 0) @@ -682,9 +683,10 @@ void Entity::move(double xa, double ya, double za, xa += d; xaOrg = xa; } + + translated_bb = bb.move(0, -1.0, za); while (za != 0 && - level->getCubes(shared_from_this(), bb->cloneMove(0, -1.0, za)) - ->empty()) { + level->getCubes(shared_from_this(), &translated_bb)->empty()) { if (za < d && za >= -d) za = 0; else if (za > 0) @@ -693,9 +695,10 @@ void Entity::move(double xa, double ya, double za, za += d; zaOrg = za; } + + translated_bb = bb.move(xa, -1.0, za); while (xa != 0 && za != 0 && - level->getCubes(shared_from_this(), bb->cloneMove(xa, -1.0, za)) - ->empty()) { + level->getCubes(shared_from_this(), &translated_bb)->empty()) { if (xa < d && xa >= -d) xa = 0; else if (xa > 0) @@ -713,8 +716,9 @@ void Entity::move(double xa, double ya, double za, } } - AABBList* aABBs = level->getCubes( - shared_from_this(), bb->expand(xa, ya, za), noEntityCubes, true); + AABB expanded = bb.expand(xa, ya, za); + AABBList* aABBs = + level->getCubes(shared_from_this(), &expanded, noEntityCubes, true); // LAND FIRST, then x and z AUTO_VAR(itEndAABB, aABBs->end()); @@ -728,8 +732,8 @@ void Entity::move(double xa, double ya, double za, // But if we don't have the chunk data then all the collision info will // be incorrect as well for (AUTO_VAR(it, aABBs->begin()); it != itEndAABB; it++) - ya = (*it)->clipYCollide(bb, ya); - bb->move(0, ya, 0); + ya = it->clipYCollide(bb, ya); + bb = bb.move(0, ya, 0); } if (!slide && yaOrg != ya) { @@ -740,9 +744,9 @@ void Entity::move(double xa, double ya, double za, itEndAABB = aABBs->end(); for (AUTO_VAR(it, aABBs->begin()); it != itEndAABB; it++) - xa = (*it)->clipXCollide(bb, xa); + xa = it->clipXCollide(bb, xa); - bb->move(xa, 0, 0); + bb = bb.move(xa, 0, 0); if (!slide && xaOrg != xa) { xa = ya = za = 0; @@ -750,8 +754,8 @@ void Entity::move(double xa, double ya, double za, itEndAABB = aABBs->end(); for (AUTO_VAR(it, aABBs->begin()); it != itEndAABB; it++) - za = (*it)->clipZCollide(bb, za); - bb->move(0, 0, za); + za = it->clipZCollide(bb, za); + bb = bb.move(0, 0, za); if (!slide && zaOrg != za) { xa = ya = za = 0; @@ -767,15 +771,15 @@ void Entity::move(double xa, double ya, double za, ya = footSize; za = zaOrg; - AABB* normal = bb->copy(); - bb->set(bbOrg); + AABB normal = bb; + bb = bbOrg; + // 4J - added extra expand, as if we don't move up by footSize by // hitting a block above us, then overall we could be trying to move as // much as footSize downwards, so we'd better include cubes under our // feet in this list of things we might possibly collide with - aABBs = level->getCubes(shared_from_this(), - bb->expand(xa, ya, za)->expand(0, -ya, 0), - false, true); + AABB expanded = bb.expand(xa, ya, za).expand(0, -ya, 0); + aABBs = level->getCubes(shared_from_this(), &expanded, false, true); // LAND FIRST, then x and z itEndAABB = aABBs->end(); @@ -785,8 +789,8 @@ void Entity::move(double xa, double ya, double za, // all! But if we don't have the chunk data then all the collision // info will be incorrect as well for (AUTO_VAR(it, aABBs->begin()); it != itEndAABB; it++) - ya = (*it)->clipYCollide(bb, ya); - bb->move(0, ya, 0); + ya = it->clipYCollide(bb, ya); + bb = bb.move(0, ya, 0); } if (!slide && yaOrg != ya) { @@ -795,8 +799,8 @@ void Entity::move(double xa, double ya, double za, itEndAABB = aABBs->end(); for (AUTO_VAR(it, aABBs->begin()); it != itEndAABB; it++) - xa = (*it)->clipXCollide(bb, xa); - bb->move(xa, 0, 0); + xa = it->clipXCollide(bb, xa); + bb = bb.move(xa, 0, 0); if (!slide && xaOrg != xa) { xa = ya = za = 0; @@ -804,8 +808,8 @@ void Entity::move(double xa, double ya, double za, itEndAABB = aABBs->end(); for (AUTO_VAR(it, aABBs->begin()); it != itEndAABB; it++) - za = (*it)->clipZCollide(bb, za); - bb->move(0, 0, za); + za = it->clipZCollide(bb, za); + bb = bb.move(0, 0, za); if (!slide && zaOrg != za) { xa = ya = za = 0; @@ -818,21 +822,21 @@ void Entity::move(double xa, double ya, double za, // LAND FIRST, then x and z itEndAABB = aABBs->end(); for (AUTO_VAR(it, aABBs->begin()); it != itEndAABB; it++) - ya = (*it)->clipYCollide(bb, ya); - bb->move(0, ya, 0); + ya = it->clipYCollide(bb, ya); + bb = bb.move(0, ya, 0); } if (xaN * xaN + zaN * zaN >= xa * xa + za * za) { xa = xaN; ya = yaN; za = zaN; - bb->set(normal); + bb = normal; } } - x = (bb->x0 + bb->x1) / 2.0f; - y = bb->y0 + heightOffset - ySlideOffset; - z = (bb->z0 + bb->z1) / 2.0f; + x = (bb.x0 + bb.x1) / 2.0f; + y = bb.y0 + heightOffset - ySlideOffset; + z = (bb.z0 + bb.z1) / 2.0f; horizontalCollision = (xaOrg != xa) || (zaOrg != za); verticalCollision = !m_ignoreVerticalCollisions && (yaOrg != ya); @@ -887,7 +891,8 @@ void Entity::move(double xa, double ya, double za, checkInsideTiles(); bool water = isInWaterOrRain(); - if (level->containsFireTile(bb->shrink(0.001, 0.001, 0.001))) { + AABB shrunk = bb.shrink(0.001, 0.001, 0.001); + if (level->containsFireTile(&shrunk)) { burn(1); if (!water) { onFire++; @@ -907,12 +912,12 @@ void Entity::move(double xa, double ya, double za, } void Entity::checkInsideTiles() { - int x0 = Mth::floor(bb->x0 + 0.001); - int y0 = Mth::floor(bb->y0 + 0.001); - int z0 = Mth::floor(bb->z0 + 0.001); - int x1 = Mth::floor(bb->x1 - 0.001); - int y1 = Mth::floor(bb->y1 - 0.001); - int z1 = Mth::floor(bb->z1 - 0.001); + int x0 = Mth::floor(bb.x0 + 0.001); + int y0 = Mth::floor(bb.y0 + 0.001); + int z0 = Mth::floor(bb.z0 + 0.001); + int x1 = Mth::floor(bb.x1 - 0.001); + int y1 = Mth::floor(bb.y1 - 0.001); + int z1 = Mth::floor(bb.z1 - 0.001); if (level->hasChunksAt(x0, y0, z0, x1, y1, z1)) { for (int x = x0; x <= x1; x++) @@ -995,9 +1000,9 @@ bool Entity::isInWaterOrRain() { bool Entity::isInWater() { return wasInWater; } bool Entity::updateInWaterState() { - if (level->checkAndHandleWater( - bb->grow(0, -0.4f, 0)->shrink(0.001, 0.001, 0.001), Material::water, - shared_from_this())) { + AABB shrunk = bb.grow(0, -0.4, 0).shrink(0.001, 0.001, 0.001); + if (level->checkAndHandleWater(&shrunk, Material::water, + shared_from_this())) { if (!wasInWater && !firstTick && canCreateParticles()) { float speed = Mth::sqrt(xd * xd * 0.2f + yd * yd + zd * zd * 0.2f) * 0.2f; @@ -1006,7 +1011,7 @@ bool Entity::updateInWaterState() { playSound(eSoundType_RANDOM_SPLASH, speed, 1 + (random->nextFloat() - random->nextFloat()) * 0.4f); MemSect(0); - float yt = (float)Mth::floor(bb->y0); + float yt = (float)Mth::floor(bb.y0); for (int i = 0; i < 1 + bbWidth * 20; i++) { float xo = (random->nextFloat() * 2 - 1) * bbWidth; float zo = (random->nextFloat() * 2 - 1) * bbWidth; @@ -1047,8 +1052,8 @@ bool Entity::isUnderLiquid(Material* material) { float Entity::getHeadHeight() { return 0; } bool Entity::isInLava() { - return level->containsMaterial(bb->grow(-0.1f, -0.4f, -0.1f), - Material::lava); + AABB mat_bounds = bb.grow(-0.1, -0.4, -0.1); + return level->containsMaterial(&mat_bounds, Material::lava); } void Entity::moveRelative(float xa, float za, float speed) { @@ -1074,7 +1079,7 @@ int Entity::getLightColor(float a) { int zTile = Mth::floor(z); if (level->hasChunkAt(xTile, 0, zTile)) { - double hh = (bb->y1 - bb->y0) * 0.66; + double hh = (bb.y1 - bb.y0) * 0.66; int yTile = Mth::floor(y - heightOffset + hh); return level->getLightColor(xTile, yTile, zTile, 0); } @@ -1086,7 +1091,7 @@ float Entity::getBrightness(float a) { int xTile = Mth::floor(x); int zTile = Mth::floor(z); if (level->hasChunkAt(xTile, 0, zTile)) { - double hh = (bb->y1 - bb->y0) * 0.66; + double hh = (bb.y1 - bb.y0) * 0.66; int yTile = Mth::floor(y - heightOffset + hh); return level->getBrightness(xTile, yTile, zTile); } @@ -1195,7 +1200,7 @@ bool Entity::hurt(DamageSource* source, float damage) { bool Entity::intersects(double x0, double y0, double z0, double x1, double y1, double z1) { - return bb->intersects(x0, y0, z0, x1, y1, z1); + return bb.intersects(x0, y0, z0, x1, y1, z1); } bool Entity::isPickable() { return false; } @@ -1215,7 +1220,7 @@ bool Entity::shouldRender(Vec3* c) { } bool Entity::shouldRenderAtSqrDistance(double distance) { - double size = bb->getSize(); + double size = bb.getSize(); size *= 64.0f * viewScale; return distance < size * size; } @@ -1492,7 +1497,7 @@ void Entity::ride(std::shared_ptr e) { // 4J Stu - Position should already be updated before the // SetEntityLinkPacket comes in if (!level->isClientSide) - moveTo(riding->x, riding->bb->y0 + riding->bbHeight, riding->z, + moveTo(riding->x, riding->bb.y0 + riding->bbHeight, riding->z, yRot, xRot); riding->rider = std::weak_ptr(); } @@ -1515,17 +1520,16 @@ void Entity::lerpTo(double x, double y, double z, float yRot, float xRot, // its definitely bad news for arrows as they are actually Meant to // intersect the geometry they land in slightly. if (GetType() != eTYPE_ARROW) { - AABBList* collisions = level->getCubes( - shared_from_this(), bb->shrink(1 / 32.0, 0, 1 / 32.0)); + AABB shrunk = bb.shrink(1 / 32.0, 0.0, 1 / 32.0); + AABBList* collisions = level->getCubes(shared_from_this(), &shrunk); if (!collisions->empty()) { double yTop = 0; AUTO_VAR(itEnd, collisions->end()); for (AUTO_VAR(it, collisions->begin()); it != itEnd; it++) { - AABB* ab = *it; // collisions->at(i); - if (ab->y1 > yTop) yTop = ab->y1; + if (it->y1 > yTop) yTop = it->y1; } - y += yTop - bb->y0; + y += yTop - bb.y0; setPos(x, y, z); } } @@ -1533,7 +1537,7 @@ void Entity::lerpTo(double x, double y, double z, float yRot, float xRot, float Entity::getPickRadius() { return 0.1f; } -Vec3* Entity::getLookAngle() { return NULL; } +std::optional Entity::getLookAngle() { return std::nullopt; } void Entity::handleInsidePortal() { if (changingDimensionDelay > 0) { @@ -1663,7 +1667,7 @@ bool Entity::checkInTile(double x, double y, double z) { double yd = y - (yTile); double zd = z - (zTile); - std::vector* cubes = level->getTileCubes(bb); + auto* cubes = level->getTileCubes(&bb); if ((cubes && !cubes->empty()) || level->isFullAABBTile(xTile, yTile, zTile)) { bool west = !level->isFullAABBTile(xTile - 1, yTile, zTile); @@ -1874,4 +1878,4 @@ unsigned int Entity::getAnimOverrideBitmask() { } return m_uiAnimOverrideBitmask; -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Entity.h b/Minecraft.World/Entities/Entity.h index ea827e28f..485a2ae57 100644 --- a/Minecraft.World/Entities/Entity.h +++ b/Minecraft.World/Entities/Entity.h @@ -5,7 +5,9 @@ #include "../IO/NBT/FloatTag.h" #include "../Util/Vec3.h" #include "../Util/Definitions.h" +#include "../Util/AABB.h" #include +#include class LivingEntity; class LightningBolt; @@ -71,7 +73,7 @@ public: double xd, yd, zd; float yRot, xRot; float yRotO, xRotO; - /*const*/ AABB* bb; // 4J Was final + /*const*/ AABB bb; // 4J Was final bool onGround; bool horizontalCollision, verticalCollision; bool collision; @@ -342,7 +344,7 @@ public: virtual void lerpTo(double x, double y, double z, float yRot, float xRot, int steps); virtual float getPickRadius(); - virtual Vec3* getLookAngle(); + virtual std::optional getLookAngle(); virtual void handleInsidePortal(); virtual int getDimensionChangingDelay(); virtual void lerpMotion(double xd, double yd, double zd); @@ -424,6 +426,7 @@ private: static int extraWanderTicks; static thread_local bool m_tlsUseSmallIds; + public: static void tickExtraWandering(); static void countFlagsForPIX(); diff --git a/Minecraft.World/Entities/FlyingMob.cpp b/Minecraft.World/Entities/FlyingMob.cpp index 752c68047..6a38c457d 100644 --- a/Minecraft.World/Entities/FlyingMob.cpp +++ b/Minecraft.World/Entities/FlyingMob.cpp @@ -34,7 +34,7 @@ void FlyingMob::travel(float xa, float ya) { float friction = 0.91f; if (onGround) { friction = 0.6f * 0.91f; - int t = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, + int t = level->getTile(Mth::floor(x), Mth::floor(bb.y0) - 1, Mth::floor(z)); if (t > 0) { friction = Tile::tiles[t]->friction * 0.91f; @@ -48,7 +48,7 @@ void FlyingMob::travel(float xa, float ya) { friction = 0.91f; if (onGround) { friction = 0.6f * 0.91f; - int t = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, + int t = level->getTile(Mth::floor(x), Mth::floor(bb.y0) - 1, Mth::floor(z)); if (t > 0) { friction = Tile::tiles[t]->friction * 0.91f; @@ -70,4 +70,4 @@ void FlyingMob::travel(float xa, float ya) { walkAnimPos += walkAnimSpeed; } -bool FlyingMob::onLadder() { return false; } \ No newline at end of file +bool FlyingMob::onLadder() { return false; } diff --git a/Minecraft.World/Entities/HangingEntity.cpp b/Minecraft.World/Entities/HangingEntity.cpp index d67329209..aa693de88 100644 --- a/Minecraft.World/Entities/HangingEntity.cpp +++ b/Minecraft.World/Entities/HangingEntity.cpp @@ -74,8 +74,8 @@ void HangingEntity::setDir(int dir) { float y1 = y + h + ss; float z0 = z - d - ss; float z1 = z + d + ss; - bb->set(std::min(x0, x1), std::min(y0, y1), std::min(z0, z1), - std::max(x0, x1), std::max(y0, y1), std::max(z0, z1)); + bb = {std::min(x0, x1), std::min(y0, y1), std::min(z0, z1), + std::max(x0, x1), std::max(y0, y1), std::max(z0, z1)}; } float HangingEntity::offs(int w) { @@ -98,7 +98,7 @@ void HangingEntity::tick() { } bool HangingEntity::survives() { - if (level->getCubes(shared_from_this(), bb)->size() != 0) // isEmpty()) + if (level->getCubes(shared_from_this(), &bb)->size() != 0) // isEmpty()) { return false; } else { @@ -128,7 +128,7 @@ bool HangingEntity::survives() { } std::vector >* entities = - level->getEntities(shared_from_this(), bb); + level->getEntities(shared_from_this(), &bb); if (entities != NULL && entities->size() > 0) { AUTO_VAR(itEnd, entities->end()); @@ -253,4 +253,4 @@ void HangingEntity::readAdditionalSaveData(CompoundTag* tag) { setDir(dir); } -bool HangingEntity::repositionEntityAfterLoad() { return false; } \ No newline at end of file +bool HangingEntity::repositionEntityAfterLoad() { return false; } diff --git a/Minecraft.World/Entities/ItemEntity.cpp b/Minecraft.World/Entities/ItemEntity.cpp index 8725cbe5f..8d4706e39 100644 --- a/Minecraft.World/Entities/ItemEntity.cpp +++ b/Minecraft.World/Entities/ItemEntity.cpp @@ -68,7 +68,7 @@ void ItemEntity::tick() { zo = z; yd -= 0.04f; - noPhysics = checkInTile(x, (bb->y0 + bb->y1) / 2, z); + noPhysics = checkInTile(x, (bb.y0 + bb.y1) / 2, z); // 4J - added parameter here so that these don't care about colliding with // other entities @@ -96,7 +96,7 @@ void ItemEntity::tick() { float friction = 0.98f; if (onGround) { friction = 0.6f * 0.98f; - int t = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, + int t = level->getTile(Mth::floor(x), Mth::floor(bb.y0) - 1, Mth::floor(z)); if (t > 0) { friction = Tile::tiles[t]->friction * 0.98f; @@ -119,8 +119,9 @@ void ItemEntity::tick() { } void ItemEntity::mergeWithNeighbours() { + AABB grown = bb.grow(0.5, 0, 0.5); std::vector >* neighbours = - level->getEntitiesOfClass(typeid(*this), bb->grow(0.5, 0, 0.5)); + level->getEntitiesOfClass(typeid(*this), &grown); for (AUTO_VAR(it, neighbours->begin()); it != neighbours->end(); ++it) { std::shared_ptr entity = std::dynamic_pointer_cast(*it); @@ -163,7 +164,7 @@ void ItemEntity::setShortLifeTime() { } bool ItemEntity::updateInWaterState() { - return level->checkAndHandleWater(bb, Material::water, shared_from_this()); + return level->checkAndHandleWater(&bb, Material::water, shared_from_this()); } void ItemEntity::burn(int dmg) { hurt(DamageSource::inFire, dmg); } diff --git a/Minecraft.World/Entities/LargeFireball.cpp b/Minecraft.World/Entities/LargeFireball.cpp index 81677498d..5c2eb50a6 100644 --- a/Minecraft.World/Entities/LargeFireball.cpp +++ b/Minecraft.World/Entities/LargeFireball.cpp @@ -44,4 +44,4 @@ void LargeFireball::readAdditionalSaveData(CompoundTag* tag) { Fireball::readAdditionalSaveData(tag); if (tag->contains(L"ExplosionPower")) explosionPower = tag->getInt(L"ExplosionPower"); -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/LeashFenceKnotEntity.cpp b/Minecraft.World/Entities/LeashFenceKnotEntity.cpp index 5a4ccd45f..d86972cad 100644 --- a/Minecraft.World/Entities/LeashFenceKnotEntity.cpp +++ b/Minecraft.World/Entities/LeashFenceKnotEntity.cpp @@ -54,11 +54,10 @@ bool LeashFenceKnotEntity::interact(std::shared_ptr player) { if (!level->isClientSide) { // look for entities that can be attached to the fence double range = 7; + AABB mob_aabb{x - range, y - range, z - range, + x + range, y + range, z + range}; std::vector >* mobs = - level->getEntitiesOfClass( - typeid(Mob), - AABB::newTemp(x - range, y - range, z - range, x + range, - y + range, z + range)); + level->getEntitiesOfClass(typeid(Mob), &mob_aabb); if (mobs != NULL) { for (AUTO_VAR(it, mobs->begin()); it != mobs->end(); ++it) { std::shared_ptr mob = @@ -79,11 +78,10 @@ bool LeashFenceKnotEntity::interact(std::shared_ptr player) { // if the player is in creative mode, attempt to remove all leashed // mobs without dropping additional items double range = 7; + AABB mob_aabb{x - range, y - range, z - range, + x + range, y + range, z + range}; std::vector >* mobs = - level->getEntitiesOfClass( - typeid(Mob), - AABB::newTemp(x - range, y - range, z - range, x + range, - y + range, z + range)); + level->getEntitiesOfClass(typeid(Mob), &mob_aabb); if (mobs != NULL) { for (AUTO_VAR(it, mobs->begin()); it != mobs->end(); ++it) { std::shared_ptr mob = @@ -122,9 +120,10 @@ std::shared_ptr LeashFenceKnotEntity::createAndAddKnot( std::shared_ptr LeashFenceKnotEntity::findKnotAt( Level* level, int x, int y, int z) { + AABB leash_fence_knot_entity_aabb{x - 1.0, y - 1.0, z - 1.0, + x + 1.0, y + 1.0, z + 1.0}; std::vector >* knots = level->getEntitiesOfClass( - typeid(LeashFenceKnotEntity), - AABB::newTemp(x - 1.0, y - 1.0, z - 1.0, x + 1.0, y + 1.0, z + 1.0)); + typeid(LeashFenceKnotEntity), &leash_fence_knot_entity_aabb); if (knots != NULL) { for (AUTO_VAR(it, knots->begin()); it != knots->end(); ++it) { std::shared_ptr knot = @@ -137,4 +136,4 @@ std::shared_ptr LeashFenceKnotEntity::findKnotAt( delete knots; } return nullptr; -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/LivingEntity.cpp b/Minecraft.World/Entities/LivingEntity.cpp index 286c5d6bc..4013c2cc3 100644 --- a/Minecraft.World/Entities/LivingEntity.cpp +++ b/Minecraft.World/Entities/LivingEntity.cpp @@ -24,6 +24,7 @@ #include "../Headers/net.minecraft.world.scores.h" #include "../Headers/com.mojang.nbt.h" #include "LivingEntity.h" +#include #include "../../Minecraft.Client/Textures/Textures.h" #include "../../Minecraft.Client/Level/ServerLevel.h" #include "../../Minecraft.Client/Player/EntityTracker.h" @@ -31,6 +32,7 @@ #include "../Util/ParticleTypes.h" #include "../Stats/GenericStats.h" #include "ItemEntity.h" +#include "Util/Vec3.h" const double LivingEntity::MIN_MOVEMENT_DISTANCE = 0.005; @@ -791,18 +793,18 @@ void LivingEntity::breakItem(std::shared_ptr itemInstance) { 0.8f + level->random->nextFloat() * 0.4f); for (int i = 0; i < 5; i++) { - Vec3* d = Vec3::newTemp((random->nextFloat() - 0.5) * 0.1, - Math::random() * 0.1 + 0.1, 0); - d->xRot(-xRot * PI / 180); - d->yRot(-yRot * PI / 180); + Vec3 d = Vec3((random->nextFloat() - 0.5) * 0.1, + Math::random() * 0.1 + 0.1, 0); + d.xRot(-xRot * PI / 180); + d.yRot(-yRot * PI / 180); - Vec3* p = Vec3::newTemp((random->nextFloat() - 0.5) * 0.3, - -random->nextFloat() * 0.6 - 0.3, 0.6); - p->xRot(-xRot * PI / 180); - p->yRot(-yRot * PI / 180); - p = p->add(x, y + getHeadHeight(), z); + Vec3 p = Vec3((random->nextFloat() - 0.5) * 0.3, + -random->nextFloat() * 0.6 - 0.3, 0.6); + p.xRot(-xRot * PI / 180); + p.yRot(-yRot * PI / 180); + p = p.add(x, y + getHeadHeight(), z); level->addParticle(PARTICLE_ICONCRACK(itemInstance->getItem()->id, 0), - p->x, p->y, p->z, d->x, d->y + 0.05, d->z); + p.x, p.y, p.z, d.x, d.y + 0.05, d.z); } } @@ -895,7 +897,7 @@ void LivingEntity::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) { bool LivingEntity::onLadder() { int xt = Mth::floor(x); - int yt = Mth::floor(bb->y0); + int yt = Mth::floor(bb.y0); int zt = Mth::floor(z); // 4J-PB - TU9 - add climbable vines @@ -1162,9 +1164,9 @@ void LivingEntity::teleportTo(double x, double y, double z) { } void LivingEntity::findStandUpPosition(std::shared_ptr vehicle) { - AABB* boundingBox; + AABB boundingBox; double fallbackX = vehicle->x; - double fallbackY = vehicle->bb->y0 + vehicle->bbHeight; + double fallbackY = vehicle->bb.y0 + vehicle->bbHeight; double fallbackZ = vehicle->z; for (double xDiff = -1.5; xDiff < 2; xDiff += 1.5) { @@ -1175,9 +1177,9 @@ void LivingEntity::findStandUpPosition(std::shared_ptr vehicle) { int xToInt = (int)(x + xDiff); int zToInt = (int)(z + zDiff); - boundingBox = bb->cloneMove(xDiff, 1, zDiff); + boundingBox = bb.move(xDiff, 1, zDiff); - if (level->getTileCubes(boundingBox, true)->empty()) { + if (level->getTileCubes(&boundingBox, true)->empty()) { if (level->isTopSolidBlocking(xToInt, (int)y, zToInt)) { teleportTo(x + xDiff, y + 1, z + zDiff); return; @@ -1249,7 +1251,7 @@ void LivingEntity::travel(float xa, float ya) { float friction = 0.91f; if (onGround) { friction = 0.6f * 0.91f; - int t = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, + int t = level->getTile(Mth::floor(x), Mth::floor(bb.y0) - 1, Mth::floor(z)); if (t > 0) { friction = Tile::tiles[t]->friction * 0.91f; @@ -1271,7 +1273,7 @@ void LivingEntity::travel(float xa, float ya) { friction = 0.91f; if (onGround) { friction = 0.6f * 0.91f; - int t = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, + int t = level->getTile(Mth::floor(x), Mth::floor(bb.y0) - 1, Mth::floor(z)); if (t > 0) { friction = Tile::tiles[t]->friction * 0.91f; @@ -1327,13 +1329,13 @@ void LivingEntity::travel(float xa, float ya) { // and out of lit areas, for example when bobbing in the water. int LivingEntity::getLightColor(float a) { float accum[2] = {0, 0}; - float totVol = (bb->x1 - bb->x0) * (bb->y1 - bb->y0) * (bb->z1 - bb->z0); - int xmin = Mth::floor(bb->x0); - int xmax = Mth::floor(bb->x1); - int ymin = Mth::floor(bb->y0); - int ymax = Mth::floor(bb->y1); - int zmin = Mth::floor(bb->z0); - int zmax = Mth::floor(bb->z1); + float totVol = (bb.x1 - bb.x0) * (bb.y1 - bb.y0) * (bb.z1 - bb.z0); + int xmin = Mth::floor(bb.x0); + int xmax = Mth::floor(bb.x1); + int ymin = Mth::floor(bb.y0); + int ymax = Mth::floor(bb.y1); + int zmin = Mth::floor(bb.z0); + int zmax = Mth::floor(bb.z1); for (int xt = xmin; xt <= xmax; xt++) for (int yt = ymin; yt <= ymax; yt++) for (int zt = zmin; zt <= zmax; zt++) { @@ -1343,12 +1345,12 @@ int LivingEntity::getLightColor(float a) { float tileymax = (float)(yt + 1); float tilezmin = (float)zt; float tilezmax = (float)(zt + 1); - if (tilexmin < bb->x0) tilexmin = bb->x0; - if (tilexmax > bb->x1) tilexmax = bb->x1; - if (tileymin < bb->y0) tileymin = bb->y0; - if (tileymax > bb->y1) tileymax = bb->y1; - if (tilezmin < bb->z0) tilezmin = bb->z0; - if (tilezmax > bb->z1) tilezmax = bb->z1; + if (tilexmin < bb.x0) tilexmin = bb.x0; + if (tilexmax > bb.x1) tilexmax = bb.x1; + if (tileymin < bb.y0) tileymin = bb.y0; + if (tileymax > bb.y1) tileymax = bb.y1; + if (tilezmin < bb.z0) tilezmin = bb.z0; + if (tilezmax > bb.z1) tilezmax = bb.z1; float tileVol = (tilexmax - tilexmin) * (tileymax - tileymin) * (tilezmax - tilezmin); float frac = tileVol / totVol; @@ -1498,21 +1500,20 @@ void LivingEntity::aiStep() { // 4J - this collision is carried out to try and stop the lerping push // the mob through the floor, in which case gravity can then carry on // moving the mob because the collision just won't work anymore. BB for - // collision used to be calculated as: bb->shrink(1 / 32.0, 0, 1 / 32.0) + // collision used to be calculated as: bb.shrink(1 / 32.0, 0, 1 / 32.0) // now using a reduced BB to try and get rid of some issues where mobs // pop up the sides of walls, undersides of trees etc. - AABB* shrinkbb = bb->shrink(0.1, 0, 0.1); - shrinkbb->y1 = shrinkbb->y0 + 0.1; - AABBList* collisions = level->getCubes(shared_from_this(), shrinkbb); + AABB shrinkbb = bb.shrink(0.1, 0, 0.1); + shrinkbb.y1 = shrinkbb.y0 + 0.1; + AABBList* collisions = level->getCubes(shared_from_this(), &shrinkbb); if (collisions->size() > 0) { double yTop = 0; AUTO_VAR(itEnd, collisions->end()); for (AUTO_VAR(it, collisions->begin()); it != itEnd; it++) { - AABB* ab = *it; // collisions->at(i); - if (ab->y1 > yTop) yTop = ab->y1; + if (it->y1 > yTop) yTop = it->y1; } - yt += yTop - bb->y0; + yt += yTop - bb.y0; setPos(xt, yt, zt); } } else if (!isEffectiveAi()) { @@ -1572,8 +1573,9 @@ void LivingEntity::aiStep() { void LivingEntity::newServerAiStep() {} void LivingEntity::pushEntities() { + AABB grown = bb.grow(0.2, 0, 0.2); std::vector >* entities = - level->getEntities(shared_from_this(), this->bb->grow(0.2f, 0, 0.2f)); + level->getEntities(shared_from_this(), &grown); if (entities != NULL && !entities->empty()) { AUTO_VAR(itEnd, entities->end()); for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) { @@ -1632,25 +1634,25 @@ void LivingEntity::take(std::shared_ptr e, int orgCount) { } bool LivingEntity::canSee(std::shared_ptr target) { - HitResult* hres = level->clip( - Vec3::newTemp(x, y + getHeadHeight(), z), - Vec3::newTemp(target->x, target->y + target->getHeadHeight(), - target->z)); + Vec3 a{x, y + getHeadHeight(), z}; + Vec3 b{target->x, target->y + target->getHeadHeight(), target->z}; + + HitResult* hres = level->clip(&a, &b); bool retVal = (hres == NULL); delete hres; return retVal; } -Vec3* LivingEntity::getLookAngle() { return getViewVector(1); } +std::optional LivingEntity::getLookAngle() { return getViewVector(1); } -Vec3* LivingEntity::getViewVector(float a) { +Vec3 LivingEntity::getViewVector(float a) { if (a == 1) { float yCos = Mth::cos(-yRot * Mth::RAD_TO_GRAD - PI); float ySin = Mth::sin(-yRot * Mth::RAD_TO_GRAD - PI); float xCos = -Mth::cos(-xRot * Mth::RAD_TO_GRAD); float xSin = Mth::sin(-xRot * Mth::RAD_TO_GRAD); - return Vec3::newTemp(ySin * xCos, xSin, yCos * xCos); + return Vec3(ySin * xCos, xSin, yCos * xCos); } float xRot = xRotO + (this->xRot - xRotO) * a; float yRot = yRotO + (this->yRot - yRotO) * a; @@ -1660,7 +1662,7 @@ Vec3* LivingEntity::getViewVector(float a) { float xCos = -Mth::cos(-xRot * Mth::RAD_TO_GRAD); float xSin = Mth::sin(-xRot * Mth::RAD_TO_GRAD); - return Vec3::newTemp(ySin * xCos, xSin, yCos * xCos); + return Vec3(ySin * xCos, xSin, yCos * xCos); } float LivingEntity::getAttackAnim(float a) { @@ -1669,22 +1671,23 @@ float LivingEntity::getAttackAnim(float a) { return oAttackAnim + diff * a; } -Vec3* LivingEntity::getPos(float a) { +Vec3 LivingEntity::getPos(float a) { if (a == 1) { - return Vec3::newTemp(x, y, z); + return Vec3(x, y, z); } double x = xo + (this->x - xo) * a; double y = yo + (this->y - yo) * a; double z = zo + (this->z - zo) * a; - return Vec3::newTemp(x, y, z); + return Vec3(x, y, z); } HitResult* LivingEntity::pick(double range, float a) { - Vec3* from = getPos(a); - Vec3* b = getViewVector(a); - Vec3* to = from->add(b->x * range, b->y * range, b->z * range); - return level->clip(from, to); + Vec3 from = getPos(a); + Vec3 b = getViewVector(a); + Vec3 to{b.x * range, b.y * range, b.z * range}; + to = to.add(from.x, from.y, from.z); + return level->clip(&from, &to); } bool LivingEntity::isEffectiveAi() { return !level->isClientSide; } diff --git a/Minecraft.World/Entities/LivingEntity.h b/Minecraft.World/Entities/LivingEntity.h index ead873ce3..30ad389b3 100644 --- a/Minecraft.World/Entities/LivingEntity.h +++ b/Minecraft.World/Entities/LivingEntity.h @@ -1,5 +1,6 @@ #pragma once +#include #include "Entity.h" #include "MobType.h" #include "../AI/Goals/GoalSelector.h" @@ -304,10 +305,10 @@ public: virtual bool canSee(std::shared_ptr target); public: - virtual Vec3* getLookAngle(); - virtual Vec3* getViewVector(float a); + virtual std::optional getLookAngle(); + virtual Vec3 getViewVector(float a); virtual float getAttackAnim(float a); - virtual Vec3* getPos(float a); + virtual Vec3 getPos(float a); virtual HitResult* pick(double range, float a); virtual bool isEffectiveAi(); diff --git a/Minecraft.World/Entities/MinecartContainer.cpp b/Minecraft.World/Entities/MinecartContainer.cpp index 63364c434..ca25f81df 100644 --- a/Minecraft.World/Entities/MinecartContainer.cpp +++ b/Minecraft.World/Entities/MinecartContainer.cpp @@ -210,4 +210,4 @@ void MinecartContainer::applyNaturalSlowdown() { xd *= keep; yd *= 0; zd *= keep; -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/MinecartHopper.cpp b/Minecraft.World/Entities/MinecartHopper.cpp index 55b7ed3aa..ef70622c7 100644 --- a/Minecraft.World/Entities/MinecartHopper.cpp +++ b/Minecraft.World/Entities/MinecartHopper.cpp @@ -85,8 +85,9 @@ void MinecartHopper::tick() { bool MinecartHopper::suckInItems() { if (HopperTileEntity::suckInItems(this)) return true; + AABB grown = bb.grow(0.25, 0, 0.25); std::vector >* items = - level->getEntitiesOfClass(typeid(ItemEntity), bb->grow(0.25f, 0, 0.25f), + level->getEntitiesOfClass(typeid(ItemEntity), &grown, EntitySelector::ENTITY_STILL_ALIVE); if (items->size() > 0) { @@ -116,4 +117,4 @@ void MinecartHopper::readAdditionalSaveData(CompoundTag* base) { void MinecartHopper::setCooldown(int time) { cooldownTime = time; } -bool MinecartHopper::isOnCooldown() { return cooldownTime > 0; } \ No newline at end of file +bool MinecartHopper::isOnCooldown() { return cooldownTime > 0; } diff --git a/Minecraft.World/Entities/Mob.cpp b/Minecraft.World/Entities/Mob.cpp index 6b744faf8..4ebcf21ac 100644 --- a/Minecraft.World/Entities/Mob.cpp +++ b/Minecraft.World/Entities/Mob.cpp @@ -301,8 +301,9 @@ void Mob::aiStep() { if (!level->isClientSide && canPickUpLoot() && !dead && level->getGameRules()->getBoolean(GameRules::RULE_MOBGRIEFING)) { + AABB grown = bb.grow(1, 0, 1); std::vector >* entities = - level->getEntitiesOfClass(typeid(ItemEntity), bb->grow(1, 0, 1)); + level->getEntitiesOfClass(typeid(ItemEntity), &grown); for (AUTO_VAR(it, entities->begin()); it != entities->end(); ++it) { std::shared_ptr entity = std::dynamic_pointer_cast(*it); @@ -498,7 +499,7 @@ void Mob::lookAt(std::shared_ptr e, float yMax, float xMax) { std::dynamic_pointer_cast(e); yd = (mob->y + mob->getHeadHeight()) - (y + getHeadHeight()); } else { - yd = (e->bb->y0 + e->bb->y1) / 2 - (y + getHeadHeight()); + yd = (e->bb.y0 + e->bb.y1) / 2 - (y + getHeadHeight()); } double sd = Mth::sqrt(xd * xd + zd * zd); @@ -526,9 +527,9 @@ float Mob::rotlerp(float a, float b, float max) { bool Mob::canSpawn() { // 4J - altered to use special containsAnyLiquid variant - return level->isUnobstructed(bb) && - level->getCubes(shared_from_this(), bb)->empty() && - !level->containsAnyLiquid_NoLoad(bb); + return level->isUnobstructed(&bb) && + level->getCubes(shared_from_this(), &bb)->empty() && + !level->containsAnyLiquid_NoLoad(&bb); } float Mob::getSizeScale() { return 1.0f; } @@ -847,9 +848,10 @@ void Mob::restoreLeashFromSave() { if (_isLeashed && leashInfoTag != NULL) { if (leashInfoTag->contains(L"UUID")) { std::wstring leashUuid = leashInfoTag->getString(L"UUID"); + AABB grown = bb.grow(10, 10, 10); std::vector >* livingEnts = level->getEntitiesOfClass(typeid(LivingEntity), - bb->grow(10, 10, 10)); + &grown); for (AUTO_VAR(it, livingEnts->begin()); it != livingEnts->end(); ++it) { std::shared_ptr le = @@ -887,9 +889,9 @@ void Mob::restoreLeashFromSave() { // resolve bug 10327 :Gameplay: NPCs can spawn over chunks that have not yet // been streamed and display jitter. bool Mob::shouldRender(Vec3* c) { - if (!level->reallyHasChunksAt(Mth::floor(bb->x0), Mth::floor(bb->y0), - Mth::floor(bb->z0), Mth::floor(bb->x1), - Mth::floor(bb->y1), Mth::floor(bb->z1))) { + if (!level->reallyHasChunksAt(Mth::floor(bb.x0), Mth::floor(bb.y0), + Mth::floor(bb.z0), Mth::floor(bb.x1), + Mth::floor(bb.y1), Mth::floor(bb.z1))) { return false; } return Entity::shouldRender(c); diff --git a/Minecraft.World/Entities/MobEffect.cpp b/Minecraft.World/Entities/MobEffect.cpp index a0822934f..828b5a4e3 100644 --- a/Minecraft.World/Entities/MobEffect.cpp +++ b/Minecraft.World/Entities/MobEffect.cpp @@ -443,4 +443,53 @@ void MobEffect::addAttributeModifiers(std::shared_ptr entity, double MobEffect::getAttributeModifierValue(int amplifier, AttributeModifier* original) { return original->getAmount() * (amplifier + 1); +} + +// 4jcraft: helper for inventoryscreen and beaconscreen +int MobEffect::javaId(int id) { + // mapped to java based on the inventory texture (see gui/inventory.png) + switch (id) { + case 1: + return 0; + case 2: + return 1; + case 3: + return 2; + case 4: + return 3; + case 5: + return 4; + case 18: + return 5; + case 19: + return 6; + case 10: + return 7; + case 14: + return 8; + case 17: + return 9; + case 8: + return 10; + case 9: + return 11; + case 16: + return 12; + case 15: + return 13; + case 11: + return 14; + case 12: + return 15; + case 13: + return 16; + case 20: + return 17; + case 21: + return 18; + case 22: + return 18; + default: + return 0; + } } \ No newline at end of file diff --git a/Minecraft.World/Entities/MobEffect.h b/Minecraft.World/Entities/MobEffect.h index 8e7ccce17..5576a2b4b 100644 --- a/Minecraft.World/Entities/MobEffect.h +++ b/Minecraft.World/Entities/MobEffect.h @@ -134,4 +134,6 @@ public: int amplifier); virtual double getAttributeModifierValue(int amplifier, AttributeModifier* original); + static int javaId( + int id); // 4jcraft: helper for inventoryscreen and beaconscreen }; \ No newline at end of file diff --git a/Minecraft.World/Entities/Mobs/Animal.cpp b/Minecraft.World/Entities/Mobs/Animal.cpp index b404a0102..a2ce25b5b 100644 --- a/Minecraft.World/Entities/Mobs/Animal.cpp +++ b/Minecraft.World/Entities/Mobs/Animal.cpp @@ -61,7 +61,7 @@ void Animal::aiStep() { void Animal::checkHurtTarget(std::shared_ptr target, float d) { // 4J-JEV: Changed from dynamic cast to use eINSTANCEOF - if (target->instanceof (eTYPE_PLAYER)) { + if (target->instanceof(eTYPE_PLAYER)) { if (d < 3) { double xd = target->x - x; double zd = target->z - z; @@ -77,7 +77,7 @@ void Animal::checkHurtTarget(std::shared_ptr target, float d) { } // 4J-JEV: Changed from dynamic cast to use eINSTANCEOF - else if (target->instanceof (eTYPE_ANIMAL)) { + else if (target->instanceof(eTYPE_ANIMAL)) { std::shared_ptr a = std::dynamic_pointer_cast(target); if (getAge() > 0 && a->getAge() < 0) { if (d < 2.5) { @@ -162,22 +162,22 @@ bool Animal::hurt(DamageSource* dmgSource, float dmg) { std::shared_ptr source = dmgSource->getDirectEntity(); // 4J-JEV: Changed from dynamic cast to use eINSTANCEOF - if (source->instanceof - (eTYPE_PLAYER) && !std::dynamic_pointer_cast(source) - ->isAllowedToAttackAnimals()) { + if (source->instanceof(eTYPE_PLAYER) && + !std::dynamic_pointer_cast(source) + ->isAllowedToAttackAnimals()) { return false; } - if ((source != NULL) && source->instanceof (eTYPE_ARROW)) { + if ((source != NULL) && source->instanceof(eTYPE_ARROW)) { std::shared_ptr arrow = std::dynamic_pointer_cast(source); // 4J: Check that the arrow's owner can attack animals (dispenser // arrows are not owned) - if (arrow->owner != NULL && arrow->owner->instanceof - (eTYPE_PLAYER) && - !std::dynamic_pointer_cast(arrow->owner) - ->isAllowedToAttackAnimals()) { + if (arrow->owner != NULL && + arrow->owner->instanceof(eTYPE_PLAYER) && + !std::dynamic_pointer_cast(arrow->owner) + ->isAllowedToAttackAnimals()) { return false; } } @@ -216,8 +216,9 @@ std::shared_ptr Animal::findAttackTarget() { float r = 8; if (getInLoveValue() > 0) { + AABB grown = bb.grow(r, r, r); std::vector >* others = - level->getEntitiesOfClass(typeid(*this), bb->grow(r, r, r)); + level->getEntitiesOfClass(typeid(*this), &grown); // for (int i = 0; i < others->size(); i++) for (AUTO_VAR(it, others->begin()); it != others->end(); ++it) { std::shared_ptr p = std::dynamic_pointer_cast(*it); @@ -229,8 +230,9 @@ std::shared_ptr Animal::findAttackTarget() { delete others; } else { if (getAge() == 0) { + AABB grown = bb.grow(r, r, r); std::vector >* players = - level->getEntitiesOfClass(typeid(Player), bb->grow(r, r, r)); + level->getEntitiesOfClass(typeid(Player), &grown); // for (int i = 0; i < players.size(); i++) for (AUTO_VAR(it, players->begin()); it != players->end(); ++it) { setDespawnProtected(); @@ -245,8 +247,9 @@ std::shared_ptr Animal::findAttackTarget() { } delete players; } else if (getAge() > 0) { + AABB grown = bb.grow(r, r, r); std::vector >* others = - level->getEntitiesOfClass(typeid(*this), bb->grow(r, r, r)); + level->getEntitiesOfClass(typeid(*this), &grown); // for (int i = 0; i < others.size(); i++) for (AUTO_VAR(it, others->begin()); it != others->end(); ++it) { std::shared_ptr p = @@ -264,7 +267,7 @@ std::shared_ptr Animal::findAttackTarget() { bool Animal::canSpawn() { int xt = Mth::floor(x); - int yt = Mth::floor(bb->y0); + int yt = Mth::floor(bb.y0); int zt = Mth::floor(z); return level->getTile(xt, yt - 1, zt) == Tile::grass_Id && level->getDaytimeRawBrightness(xt, yt, zt) > 8 && @@ -332,7 +335,7 @@ bool Animal::mobInteract(std::shared_ptr player) { return false; } - } else if (instanceof (eTYPE_MONSTER)) { + } else if (instanceof(eTYPE_MONSTER)) { } break; } diff --git a/Minecraft.World/Entities/Mobs/Arrow.cpp b/Minecraft.World/Entities/Mobs/Arrow.cpp index fc6562f26..4c8977b66 100644 --- a/Minecraft.World/Entities/Mobs/Arrow.cpp +++ b/Minecraft.World/Entities/Mobs/Arrow.cpp @@ -183,8 +183,9 @@ void Arrow::tick() { int t = level->getTile(xTile, yTile, zTile); if (t > 0) { Tile::tiles[t]->updateShape(level, xTile, yTile, zTile); - AABB* aabb = Tile::tiles[t]->getAABB(level, xTile, yTile, zTile); - if (aabb != NULL && aabb->contains(Vec3::newTemp(x, y, z))) { + auto aabb = Tile::tiles[t]->getAABB(level, xTile, yTile, zTile); + Vec3 pos{x, y, z}; + if (aabb.has_value() && aabb->contains(pos)) { inGround = true; } } @@ -217,18 +218,21 @@ void Arrow::tick() { flightTime++; } - Vec3* from = Vec3::newTemp(x, y, z); - Vec3* to = Vec3::newTemp(x + xd, y + yd, z + zd); - HitResult* res = level->clip(from, to, false, true); + Vec3 from{x, y, z}; + Vec3 to{x + xd, y + yd, z + zd}; + HitResult* res = level->clip(&from, &to, false, true); + + from = Vec3{x, y, z}; + to = Vec3{x + xd, y + yd, z + zd}; - from = Vec3::newTemp(x, y, z); - to = Vec3::newTemp(x + xd, y + yd, z + zd); if (res != NULL) { - to = Vec3::newTemp(res->pos->x, res->pos->y, res->pos->z); + to = Vec3{res->pos.x, res->pos.y, res->pos.z}; } + std::shared_ptr hitEntity = nullptr; - std::vector >* objects = level->getEntities( - shared_from_this(), this->bb->expand(xd, yd, zd)->grow(1, 1, 1)); + AABB grown = bb.expand(xd, yd, zd).grow(1, 1, 1); + std::vector >* objects = + level->getEntities(shared_from_this(), &grown); double nearest = 0; AUTO_VAR(itEnd, objects->end()); for (AUTO_VAR(it, objects->begin()); it != itEnd; it++) { @@ -236,10 +240,10 @@ void Arrow::tick() { if (!e->isPickable() || (e == owner && flightTime < 5)) continue; float rr = 0.3f; - AABB* bb = e->bb->grow(rr, rr, rr); - HitResult* p = bb->clip(from, to); + AABB bb = e->bb.grow(rr, rr, rr); + HitResult* p = bb.clip(from, to); if (p != NULL) { - double dd = from->distanceTo(p->pos); + double dd = from.distanceTo(p->pos); if (dd < nearest || nearest == 0) { hitEntity = e; nearest = dd; @@ -359,9 +363,9 @@ void Arrow::tick() { zTile = res->z; lastTile = level->getTile(xTile, yTile, zTile); lastData = level->getData(xTile, yTile, zTile); - xd = (float)(res->pos->x - x); - yd = (float)(res->pos->y - y); - zd = (float)(res->pos->z - z); + xd = (float)(res->pos.x - x); + yd = (float)(res->pos.y - y); + zd = (float)(res->pos.z - z); float dd = (float)sqrt(xd * xd + yd * yd + zd * zd); // 4J added check - zero dd here was creating NaNs if (dd > 0.0001f) { diff --git a/Minecraft.World/Entities/Mobs/Bat.cpp b/Minecraft.World/Entities/Mobs/Bat.cpp index 43c180678..5835875af 100644 --- a/Minecraft.World/Entities/Mobs/Bat.cpp +++ b/Minecraft.World/Entities/Mobs/Bat.cpp @@ -185,7 +185,7 @@ void Bat::addAdditonalSaveData(CompoundTag* entityTag) { } bool Bat::canSpawn() { - int yt = Mth::floor(bb->y0); + int yt = Mth::floor(bb.y0); if (yt >= level->seaLevel) return false; int xt = Mth::floor(x); @@ -205,4 +205,4 @@ bool Bat::canSpawn() { if (br > random->nextInt(maxLight)) return false; return AmbientCreature::canSpawn(); -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/Blaze.cpp b/Minecraft.World/Entities/Mobs/Blaze.cpp index 2ac264dbd..ce7fec922 100644 --- a/Minecraft.World/Entities/Mobs/Blaze.cpp +++ b/Minecraft.World/Entities/Mobs/Blaze.cpp @@ -93,14 +93,14 @@ void Blaze::aiStep() { } void Blaze::checkHurtTarget(std::shared_ptr target, float d) { - if (attackTime <= 0 && d < 2.0f && target->bb->y1 > bb->y0 && - target->bb->y0 < bb->y1) { + if (attackTime <= 0 && d < 2.0f && target->bb.y1 > bb.y0 && + target->bb.y0 < bb.y1) { attackTime = 20; doHurtTarget(target); } else if (d < 30) { double xd = target->x - x; double yd = - (target->bb->y0 + target->bbHeight / 2) - (y + bbHeight / 2); + (target->bb.y0 + target->bbHeight / 2) - (y + bbHeight / 2); double zd = target->z - z; if (attackTime == 0) { @@ -181,4 +181,4 @@ void Blaze::setCharged(bool value) { entityData->set(DATA_FLAGS_ID, flags); } -bool Blaze::isDarkEnoughToSpawn() { return true; } \ No newline at end of file +bool Blaze::isDarkEnoughToSpawn() { return true; } diff --git a/Minecraft.World/Entities/Mobs/Boat.cpp b/Minecraft.World/Entities/Mobs/Boat.cpp index 31ab96364..aafb09124 100644 --- a/Minecraft.World/Entities/Mobs/Boat.cpp +++ b/Minecraft.World/Entities/Mobs/Boat.cpp @@ -44,10 +44,10 @@ void Boat::defineSynchedData() { } AABB* Boat::getCollideAgainstBox(std::shared_ptr entity) { - return entity->bb; + return &entity->bb; } -AABB* Boat::getCollideBox() { return bb; } +AABB* Boat::getCollideBox() { return &bb; } bool Boat::isPushable() { return true; } @@ -165,10 +165,10 @@ void Boat::tick() { int steps = 5; double waterPercentage = 0; for (int i = 0; i < steps; i++) { - double y0 = bb->y0 + (bb->y1 - bb->y0) * (i + 0) / steps - 2 / 16.0f; - double y1 = bb->y0 + (bb->y1 - bb->y0) * (i + 1) / steps - 2 / 16.0f; - AABB* bb2 = AABB::newTemp(bb->x0, y0, bb->z0, bb->x1, y1, bb->z1); - if (level->containsLiquid(bb2, Material::water)) { + double y0 = bb.y0 + (bb.y1 - bb.y0) * (i + 0) / steps - 2 / 16.0f; + double y1 = bb.y0 + (bb.y1 - bb.y0) * (i + 1) / steps - 2 / 16.0f; + AABB bb2(bb.x0, y0, bb.z0, bb.x1, y1, bb.z1); + if (level->containsLiquid(&bb2, Material::water)) { waterPercentage += 1.0 / steps; } } @@ -313,8 +313,9 @@ void Boat::tick() { if (level->isClientSide) return; + AABB grown = bb.grow(0.2, 0, 0.2); std::vector >* entities = - level->getEntities(shared_from_this(), bb->grow(0.2f, 0, 0.2f)); + level->getEntities(shared_from_this(), &grown); if (entities != NULL && !entities->empty()) { AUTO_VAR(itEnd, entities->end()); for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) { diff --git a/Minecraft.World/Entities/Mobs/DragonFireball.cpp b/Minecraft.World/Entities/Mobs/DragonFireball.cpp index 29fa582d0..19486ffbe 100644 --- a/Minecraft.World/Entities/Mobs/DragonFireball.cpp +++ b/Minecraft.World/Entities/Mobs/DragonFireball.cpp @@ -29,9 +29,9 @@ DragonFireball::DragonFireball(Level* level, double x, double y, double z, void DragonFireball::onHit(HitResult* res) { if (!level->isClientSide) { - AABB* aoe = bb->grow(SPLASH_RANGE, SPLASH_RANGE / 2, SPLASH_RANGE); + AABB aoe = bb.grow(SPLASH_RANGE, SPLASH_RANGE / 2, SPLASH_RANGE); std::vector >* entitiesOfClass = - level->getEntitiesOfClass(typeid(LivingEntity), aoe); + level->getEntitiesOfClass(typeid(LivingEntity), &aoe); if (entitiesOfClass != NULL && !entitiesOfClass->empty()) { // for (Entity e : entitiesOfClass) @@ -67,4 +67,4 @@ ePARTICLE_TYPE DragonFireball::getTrailParticleType() { return eParticleType_dragonbreath; } -bool DragonFireball::shouldBurn() { return false; } \ No newline at end of file +bool DragonFireball::shouldBurn() { return false; } diff --git a/Minecraft.World/Entities/Mobs/EnderDragon.cpp b/Minecraft.World/Entities/Mobs/EnderDragon.cpp index 582bda987..7aa192c13 100644 --- a/Minecraft.World/Entities/Mobs/EnderDragon.cpp +++ b/Minecraft.World/Entities/Mobs/EnderDragon.cpp @@ -14,6 +14,7 @@ #include "../../Util/SharedConstants.h" #include "EnderDragon.h" #include +#include #define PRINT_DRAGON_STATE_CHANGE_MESSAGES 1 @@ -72,7 +73,7 @@ void EnderDragon::_init() { m_actionTicks = 0; m_sittingDamageReceived = 0; m_headYRot = 0.0; - m_acidArea = AABB::newPermanent(-4, -10, -3, 6, 3, 3); + m_acidArea = AABB(-4, -10, -3, 6, 3, 3); m_flameAttacks = 0; for (int i = 0; i < positionsLength; i++) { @@ -309,20 +310,21 @@ void EnderDragon::aiStep() { double xP = 0.0; double yP = 0.0; double zP = 0.0; - Vec3* v = getHeadLookVector(1); // getViewVector(1); + Vec3 v = getHeadLookVector(1); // getViewVector(1); // app.DebugPrintf("View vector is (%f,%f,%f) - lsteps %d\n", v->x, // v->y, v->z, lSteps); unsigned int d = 0; for(unsigned int d = 1; // d < 3; ++d) { - Vec3* vN = v->normalize(); - vN->yRot(-PI / 4); + Vec3 vN = Vec3{v.x, v.y, v.z}.normalize(); + vN.yRot(-PI / 4); + for (unsigned int i = 0; i < 8; ++i) { if (getSynchedAction() == e_EnderdragonAction_Landing) { // for(unsigned int j = 0; j < 6; ++j) { xP = head->x; // - vN->x * d; yP = - head->bb->y0 + + head->bb.y0 + head->bbHeight / 2; // - vN->y * d; //head->y + // head->bbHeight / 2 + 0.5f - v->y * d; @@ -334,9 +336,9 @@ void EnderDragon::aiStep() { zP += (level->random->nextBoolean() ? 1 : -1) * level->random->nextFloat() / 2; level->addParticle(eParticleType_dragonbreath, xP, - yP, zP, (-vN->x * 0.08) + xd, - (-vN->y * 0.3) + yd, - (-vN->z * 0.08) + zd); + yP, zP, (-vN.x * 0.08) + xd, + (-vN.y * 0.3) + yd, + (-vN.z * 0.08) + zd); } } else { double yVelocity = 0.6; @@ -344,7 +346,7 @@ void EnderDragon::aiStep() { for (unsigned int j = 0; j < 6; ++j) { xP = head->x; // - vN->x * d; yP = - head->bb->y0 + + head->bb.y0 + head->bbHeight / 2; // - vN->y * d; //head->y + // head->bbHeight / 2 + 0.5f - v->y * d; @@ -356,12 +358,12 @@ void EnderDragon::aiStep() { zP += (level->random->nextBoolean() ? 1 : -1) * level->random->nextFloat() / 2; level->addParticle(eParticleType_dragonbreath, xP, - yP, zP, -vN->x * xzVelocity * j, - -vN->y * yVelocity, - -vN->z * xzVelocity * j); + yP, zP, -vN.x * xzVelocity * j, + -vN.y * yVelocity, + -vN.z * xzVelocity * j); } } - vN->yRot(PI / (2 * 8)); + vN.yRot(PI / (2 * 8)); } } } else if (getSynchedAction() == @@ -460,7 +462,7 @@ void EnderDragon::aiStep() { getSynchedAction() == e_EnderdragonAction_Landing) { if (m_actionTicks < (FLAME_TICKS - 10)) { std::vector >* targets = - level->getEntities(shared_from_this(), m_acidArea); + level->getEntities(shared_from_this(), &m_acidArea); for (AUTO_VAR(it, targets->begin()); it != targets->end(); ++it) { @@ -477,19 +479,19 @@ void EnderDragon::aiStep() { // No movement } else if (getSynchedAction() == e_EnderdragonAction_Sitting_Scanning) { if (attackTarget != NULL) { - Vec3* aim = Vec3::newTemp((attackTarget->x - x), 0, - (attackTarget->z - z)) - ->normalize(); - Vec3* dir = Vec3::newTemp(sin(yRot * PI / 180), 0, - -cos(yRot * PI / 180)) - ->normalize(); - float dot = (float)dir->dot(aim); + Vec3 aim = Vec3((attackTarget->x - x), 0, (attackTarget->z - z)) + .normalize(); + + Vec3 dir = Vec3(sin(yRot * PI / 180), 0, -cos(yRot * PI / 180)) + .normalize(); + + float dot = (float)dir.dot(aim); float angleDegs = acos(dot) * 180 / PI; angleDegs = angleDegs + 0.5f; if (angleDegs < 0 || angleDegs > 10) { double xdd = attackTarget->x - head->x; - // double ydd = (attackTarget->bb->y0 + + // double ydd = (attackTarget->bb.y0 + // attackTarget->bbHeight / 2) - (head->y + head->bbHeight / // 2); double zdd = attackTarget->z - head->z; @@ -539,7 +541,7 @@ void EnderDragon::aiStep() { double sd = sqrt(xd * xd + zd * zd); double ho = 0.4f + sd / 80.0f - 1; if (ho > 10) ho = 10; - yTarget = attackTarget->bb->y0 + ho; + yTarget = attackTarget->bb.y0 + ho; } else { // xTarget += random->nextGaussian() * 2; // zTarget += random->nextGaussian() * 2; @@ -561,13 +563,12 @@ void EnderDragon::aiStep() { if (yRotD > 50) yRotD = 50; if (yRotD < -50) yRotD = -50; - Vec3* aim = - Vec3::newTemp((xTarget - x), (yTarget - y), (zTarget - z)) - ->normalize(); - Vec3* dir = - Vec3::newTemp(sin(yRot * PI / 180), yd, -cos(yRot * PI / 180)) - ->normalize(); - float dot = (float)(dir->dot(aim) + 0.5f) / 1.5f; + Vec3 aim = + Vec3((xTarget - x), (yTarget - y), (zTarget - z)).normalize(); + + Vec3 dir = Vec3(sin(yRot * PI / 180), yd, -cos(yRot * PI / 180)) + .normalize(); + float dot = (float)(dir.dot(aim) + 0.5f) / 1.5f; if (dot < 0) dot = 0; yRotA *= 0.80f; @@ -591,8 +592,8 @@ void EnderDragon::aiStep() { move(xd, yd, zd); } - Vec3* actual = Vec3::newTemp(xd, yd, zd)->normalize(); - float slide = (float)(actual->dot(dir) + 1) / 2.0f; + Vec3 actual = Vec3(xd, yd, zd).normalize(); + float slide = (float)(actual.dot(dir) + 1) / 2.0f; slide = 0.8f + 0.15f * slide; xd *= slide; @@ -645,12 +646,15 @@ void EnderDragon::aiStep() { if (!level->isClientSide) checkAttack(); if (!level->isClientSide && hurtDuration == 0) { - knockBack(level->getEntities(shared_from_this(), - wing1->bb->grow(4, 2, 4)->move(0, -2, 0))); - knockBack(level->getEntities(shared_from_this(), - wing2->bb->grow(4, 2, 4)->move(0, -2, 0))); - hurt(level->getEntities(shared_from_this(), neck->bb->grow(1, 1, 1))); - hurt(level->getEntities(shared_from_this(), head->bb->grow(1, 1, 1))); + AABB wing_mov = wing1->bb.grow(4, 2, 4).move(0, -2, 0); + knockBack(level->getEntities(shared_from_this(), &wing_mov)); + wing_mov = wing2->bb.grow(4, 2, 4).move(0, -2, 0); + knockBack(level->getEntities(shared_from_this(), &wing_mov)); + + AABB neck_bb = neck->bb.grow(1, 1, 1); + AABB head_bb = head->bb.grow(1, 1, 1); + hurt(level->getEntities(shared_from_this(), &neck_bb)); + hurt(level->getEntities(shared_from_this(), &head_bb)); } double p1components[3]; @@ -683,19 +687,19 @@ void EnderDragon::aiStep() { double acidX = x + ss * 9.5f * ccTilt; double acidY = y + yOffset + ssTilt * 10.5f; double acidZ = z - cc * 9.5f * ccTilt; - m_acidArea->set(acidX - 5, acidY - 17, acidZ - 5, acidX + 5, acidY + 4, - acidZ + 5); + m_acidArea = {acidX - 5, acidY - 17, acidZ - 5, + acidX + 5, acidY + 4, acidZ + 5}; // app.DebugPrintf("\nDragon is %s, yRot = %f, yRotA = %f, ss = %f, cc = // %f, ccTilt = %f\n",level->isClientSide?"client":"server", yRot, // yRotA, ss, cc, ccTilt); app.DebugPrintf("Body (%f,%f,%f) to - // (%f,%f,%f)\n", body->bb->x0, body->bb->y0, body->bb->z0, - // body->bb->x1, body->bb->y1, body->bb->z1); app.DebugPrintf("Neck - // (%f,%f,%f) to (%f,%f,%f)\n", neck->bb->x0, neck->bb->y0, - // neck->bb->z0, neck->bb->x1, neck->bb->y1, neck->bb->z1); - // app.DebugPrintf("Head (%f,%f,%f) to (%f,%f,%f)\n", head->bb->x0, - // head->bb->y0, head->bb->z0, head->bb->x1, head->bb->y1, - // head->bb->z1); app.DebugPrintf("Acid (%f,%f,%f) to (%f,%f,%f)\n\n", + // (%f,%f,%f)\n", body->bb.x0, body->bb.y0, body->bb.z0, + // body->bb.x1, body->bb.y1, body->bb.z1); app.DebugPrintf("Neck + // (%f,%f,%f) to (%f,%f,%f)\n", neck->bb.x0, neck->bb.y0, + // neck->bb.z0, neck->bb.x1, neck->bb.y1, neck->bb.z1); + // app.DebugPrintf("Head (%f,%f,%f) to (%f,%f,%f)\n", head->bb.x0, + // head->bb.y0, head->bb.z0, head->bb.x1, head->bb.y1, + // head->bb.z1); app.DebugPrintf("Acid (%f,%f,%f) to (%f,%f,%f)\n\n", // m_acidArea->x0, m_acidArea->y0, m_acidArea->z0, m_acidArea->x1, // m_acidArea->y1, m_acidArea->z1); } @@ -733,27 +737,27 @@ void EnderDragon::aiStep() { maxDist * maxDist) { if (this->canSee(attackTarget)) { m_fireballCharge++; - Vec3* aim = Vec3::newTemp((attackTarget->x - x), 0, - (attackTarget->z - z)) - ->normalize(); - Vec3* dir = Vec3::newTemp(sin(yRot * PI / 180), 0, - -cos(yRot * PI / 180)) - ->normalize(); - float dot = (float)dir->dot(aim); + Vec3 aim = Vec3((attackTarget->x - x), 0, (attackTarget->z - z)) + .normalize(); + + Vec3 dir = Vec3(sin(yRot * PI / 180), 0, -cos(yRot * PI / 180)) + .normalize(); + + float dot = (float)dir.dot(aim); float angleDegs = acos(dot) * 180 / PI; angleDegs = angleDegs + 0.5f; if (m_fireballCharge >= 20 && (angleDegs >= 0 && angleDegs < 10)) { double d = 1; - Vec3* v = getViewVector(1); - float startingX = head->x - v->x * d; + Vec3 v = getViewVector(1); + float startingX = head->x - v.x * d; float startingY = head->y + head->bbHeight / 2 + 0.5f; - float startingZ = head->z - v->z * d; + float startingZ = head->z - v.z * d; double xdd = attackTarget->x - startingX; double ydd = - (attackTarget->bb->y0 + attackTarget->bbHeight / 2) - + (attackTarget->bb.y0 + attackTarget->bbHeight / 2) - (startingY + head->bbHeight / 2); double zdd = attackTarget->z - startingZ; @@ -791,7 +795,7 @@ void EnderDragon::aiStep() { if (!level->isClientSide) { inWall = - checkWalls(head->bb) | checkWalls(neck->bb) | checkWalls(body->bb); + checkWalls(&head->bb) | checkWalls(&neck->bb) | checkWalls(&body->bb); } } @@ -810,9 +814,9 @@ void EnderDragon::checkCrystals() { if (random->nextInt(10) == 0) { float maxDist = 32; + AABB grown = bb.grow(maxDist, maxDist, maxDist); std::vector >* crystals = - level->getEntitiesOfClass(typeid(EnderCrystal), - bb->grow(maxDist, maxDist, maxDist)); + level->getEntitiesOfClass(typeid(EnderCrystal), &grown); std::shared_ptr crystal = nullptr; double nearest = std::numeric_limits::max(); @@ -847,9 +851,9 @@ void EnderDragon::checkAttack() { } void EnderDragon::knockBack(std::vector >* entities) { - double xm = (body->bb->x0 + body->bb->x1) / 2; + double xm = (body->bb.x0 + body->bb.x1) / 2; // double ym = (body.bb.y0 + body.bb.y1) / 2; - double zm = (body->bb->z0 + body->bb->z1) / 2; + double zm = (body->bb.z0 + body->bb.z1) / 2; // for (Entity e : entities) for (AUTO_VAR(it, entities->begin()); it != entities->end(); ++it) { @@ -978,13 +982,13 @@ void EnderDragon::findNewTarget() { int targetNodeIndex = 0; if (playerNearestToEgg != NULL) { - Vec3* aim = Vec3::newTemp(playerNearestToEgg->x, 0, - playerNearestToEgg->z) - ->normalize(); + Vec3 aim = Vec3(playerNearestToEgg->x, 0, playerNearestToEgg->z) + .normalize(); + // app.DebugPrintf("Final marker node near (%f,%d,%f)\n", // -aim->x*40,105,-aim->z*40 ); targetNodeIndex = - findClosestNode(-aim->x * 40, 105.0, -aim->z * 40); + findClosestNode(-aim.x * 40, 105.0, -aim.z * 40); } else { targetNodeIndex = findClosestNode(40.0, eggHeight, 0.0); } @@ -1022,9 +1026,8 @@ void EnderDragon::findNewTarget() { // !m_holdingPatternClockwise; if (getSynchedAction() == e_EnderdragonAction_Takeoff) { - Vec3* v = getHeadLookVector(1); - targetNodeIndex = - findClosestNode(-v->x * 40, 105.0, -v->z * 40); + Vec3 v = getHeadLookVector(1); + targetNodeIndex = findClosestNode(-v.x * 40, 105.0, -v.z * 40); } else { if (random->nextInt(8) == 0) { m_holdingPatternClockwise = !m_holdingPatternClockwise; @@ -1420,10 +1423,11 @@ EnderDragon::EEnderdragonAction EnderDragon::getSynchedAction() { } void EnderDragon::handleCrystalDestroyed(DamageSource* source) { - AABB* tempBB = AABB::newTemp(PODIUM_X_POS, 84.0, PODIUM_Z_POS, - PODIUM_X_POS + 1.0, 85.0, PODIUM_Z_POS + 1.0); - std::vector >* crystals = level->getEntitiesOfClass( - typeid(EnderCrystal), tempBB->grow(48, 40, 48)); + AABB tempBB(PODIUM_X_POS, 84.0, PODIUM_Z_POS, PODIUM_X_POS + 1.0, 85.0, + PODIUM_Z_POS + 1.0); + AABB grown = tempBB.grow(48, 40, 48); + std::vector >* crystals = + level->getEntitiesOfClass(typeid(EnderCrystal), &grown); m_remainingCrystalsCount = (int)crystals->size() - 1; if (m_remainingCrystalsCount < 0) m_remainingCrystalsCount = 0; delete crystals; @@ -1471,7 +1475,7 @@ void EnderDragon::strafeAttackTarget() { double sd = sqrt(xd * xd + zd * zd); double ho = 0.4f + sd / 80.0f - 1; if (ho > 10) ho = 10; - int finalYTarget = attackTarget->bb->y0 + ho; + int finalYTarget = attackTarget->bb.y0 + ho; Node finalNode(finalXTarget, finalYTarget, finalZTarget); @@ -1488,24 +1492,24 @@ void EnderDragon::strafeAttackTarget() { void EnderDragon::navigateToNextPathNode() { if (m_currentPath != NULL && !m_currentPath->isDone()) { - Vec3* curr = m_currentPath->currentPos(); + Vec3 curr = m_currentPath->currentPos(); m_currentPath->next(); - xTarget = curr->x; + xTarget = curr.x; if (getSynchedAction() == e_EnderdragonAction_LandingApproach && m_currentPath->isDone()) { // When heading to the last node on the landing approach, we want // the yCoord to be exact - yTarget = curr->y; + yTarget = curr.y; } else { do { - yTarget = curr->y + random->nextFloat() * 20; - } while (yTarget < (curr->y)); + yTarget = curr.y + random->nextFloat() * 20; + } while (yTarget < (curr.y)); } - zTarget = curr->z; - app.DebugPrintf("Path node pos is (%f,%f,%f)\n", curr->x, curr->y, - curr->z); + zTarget = curr.z; + app.DebugPrintf("Path node pos is (%f,%f,%f)\n", curr.x, curr.y, + curr.z); app.DebugPrintf("Setting new target to (%f,%f,%f)\n", xTarget, yTarget, zTarget); } @@ -1846,8 +1850,8 @@ double EnderDragon::getHeadPartYRotDiff(int partIndex, doubleArray bodyPos, return result; } -Vec3* EnderDragon::getHeadLookVector(float a) { - Vec3* result = NULL; +Vec3 EnderDragon::getHeadLookVector(float a) { + Vec3 result; if (getSynchedAction() == e_EnderdragonAction_Landing || getSynchedAction() == e_EnderdragonAction_Takeoff) { @@ -1888,5 +1892,6 @@ Vec3* EnderDragon::getHeadLookVector(float a) { } else { result = getViewVector(a); } + return result; } diff --git a/Minecraft.World/Entities/Mobs/EnderDragon.h b/Minecraft.World/Entities/Mobs/EnderDragon.h index 90056ce63..1e8479407 100644 --- a/Minecraft.World/Entities/Mobs/EnderDragon.h +++ b/Minecraft.World/Entities/Mobs/EnderDragon.h @@ -59,7 +59,7 @@ private: int m_iGrowlTimer; double m_headYRot; - AABB* m_acidArea; + AABB m_acidArea; NodeArray* m_nodes; int m_nodeAdjacency[24]; @@ -188,7 +188,7 @@ public: doubleArray partPos); double getHeadPartYRotDiff(int partIndex, doubleArray bodyPos, doubleArray partPos); - Vec3* getHeadLookVector(float a); + Vec3 getHeadLookVector(float a); virtual std::wstring getAName() { return app.GetString(IDS_ENDERDRAGON); }; virtual float getHealth() { return LivingEntity::getHealth(); }; diff --git a/Minecraft.World/Entities/Mobs/EnderMan.cpp b/Minecraft.World/Entities/Mobs/EnderMan.cpp index 986143ab9..c83c478f5 100644 --- a/Minecraft.World/Entities/Mobs/EnderMan.cpp +++ b/Minecraft.World/Entities/Mobs/EnderMan.cpp @@ -114,14 +114,15 @@ bool EnderMan::isLookingAtMe(std::shared_ptr player) { std::shared_ptr helmet = player->inventory->armor[3]; if (helmet != NULL && helmet->id == Tile::pumpkin_Id) return false; - Vec3* look = player->getViewVector(1)->normalize(); - Vec3* dir = Vec3::newTemp( - x - player->x, - (bb->y0 + bbHeight / 2) - (player->y + player->getHeadHeight()), - z - player->z); - double dist = dir->length(); - dir = dir->normalize(); - double dot = look->dot(dir); + Vec3 look = player->getViewVector(1).normalize(); + + Vec3 dir{x - player->x, + (bb.y0 + bbHeight / 2) - (player->y + player->getHeadHeight()), + z - player->z}; + + double dist = dir.length(); + dir = dir.normalize(); + double dot = look.dot(dir); if (dot > 1 - 0.025 / dist) { return player->canSee(shared_from_this()); } @@ -249,13 +250,13 @@ bool EnderMan::teleport() { } bool EnderMan::teleportTowards(std::shared_ptr e) { - Vec3* dir = Vec3::newTemp( - x - e->x, bb->y0 + bbHeight / 2 - e->y + e->getHeadHeight(), z - e->z); - dir = dir->normalize(); + Vec3 dir{x - e->x, bb.y0 + bbHeight / 2 - e->y + e->getHeadHeight(), + z - e->z}; + dir = dir.normalize(); double d = 16; - double xx = x + (random->nextDouble() - 0.5) * 8 - dir->x * d; - double yy = y + (random->nextInt(16) - 8) - dir->y * d; - double zz = z + (random->nextDouble() - 0.5) * 8 - dir->z * d; + double xx = x + (random->nextDouble() - 0.5) * 8 - dir.x * d; + double yy = y + (random->nextInt(16) - 8) - dir.y * d; + double zz = z + (random->nextDouble() - 0.5) * 8 - dir.z * d; return teleport(xx, yy, zz); } @@ -285,8 +286,8 @@ bool EnderMan::teleport(double xx, double yy, double zz) { } if (landed) { setPos(x, y, z); - if (level->getCubes(shared_from_this(), bb)->empty() && - !level->containsAnyLiquid(bb)) { + if (level->getCubes(shared_from_this(), &bb)->empty() && + !level->containsAnyLiquid(&bb)) { ok = true; } } @@ -378,4 +379,4 @@ bool EnderMan::isCreepy() { return entityData->getByte(DATA_CREEPY) > 0; } void EnderMan::setCreepy(bool creepy) { entityData->set(DATA_CREEPY, (uint8_t)(creepy ? 1 : 0)); -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/EntityHorse.cpp b/Minecraft.World/Entities/Mobs/EntityHorse.cpp index 65502c329..2692045da 100644 --- a/Minecraft.World/Entities/Mobs/EntityHorse.cpp +++ b/Minecraft.World/Entities/Mobs/EntityHorse.cpp @@ -420,9 +420,9 @@ std::shared_ptr EntityHorse::getClosestMommy( double closestDistance = std::numeric_limits::max(); std::shared_ptr mommy = nullptr; - std::vector >* list = level->getEntities( - baby, baby->bb->expand(searchRadius, searchRadius, searchRadius), - PARENT_HORSE_SELECTOR); + AABB expanded = baby->bb.expand(searchRadius, searchRadius, searchRadius); + std::vector >* list = + level->getEntities(baby, &expanded, PARENT_HORSE_SELECTOR); for (AUTO_VAR(it, list->begin()); it != list->end(); ++it) { std::shared_ptr horse = *it; diff --git a/Minecraft.World/Entities/Mobs/ExperienceOrb.cpp b/Minecraft.World/Entities/Mobs/ExperienceOrb.cpp index 83aa925af..fb7755f52 100644 --- a/Minecraft.World/Entities/Mobs/ExperienceOrb.cpp +++ b/Minecraft.World/Entities/Mobs/ExperienceOrb.cpp @@ -84,7 +84,7 @@ void ExperienceOrb::tick() { playSound(eSoundType_RANDOM_FIZZ, 0.4f, 2.0f + random->nextFloat() * 0.4f); } - checkInTile(x, (bb->y0 + bb->y1) / 2, z); + checkInTile(x, (bb.y0 + bb.y1) / 2, z); double maxDist = 8; // 4J - PC Comment @@ -121,7 +121,7 @@ void ExperienceOrb::tick() { float friction = 0.98f; if (onGround) { friction = 0.6f * 0.98f; - int t = level->getTile(Mth::floor(x), Mth::floor(bb->y0) - 1, + int t = level->getTile(Mth::floor(x), Mth::floor(bb.y0) - 1, Mth::floor(z)); if (t > 0) { friction = Tile::tiles[t]->friction * 0.98f; @@ -145,7 +145,7 @@ void ExperienceOrb::tick() { } bool ExperienceOrb::updateInWaterState() { - return level->checkAndHandleWater(bb, Material::water, shared_from_this()); + return level->checkAndHandleWater(&bb, Material::water, shared_from_this()); } void ExperienceOrb::burn(int dmg) { hurt(DamageSource::inFire, dmg); } @@ -265,4 +265,4 @@ bool ExperienceOrb::shouldRender(Vec3* c) { if (distance < 4) return false; return Entity::shouldRender(c); -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/EyeOfEnderSignal.cpp b/Minecraft.World/Entities/Mobs/EyeOfEnderSignal.cpp index 71981b9b9..ed3311a2c 100644 --- a/Minecraft.World/Entities/Mobs/EyeOfEnderSignal.cpp +++ b/Minecraft.World/Entities/Mobs/EyeOfEnderSignal.cpp @@ -28,7 +28,7 @@ EyeOfEnderSignal::EyeOfEnderSignal(Level* level) : Entity(level) { void EyeOfEnderSignal::defineSynchedData() {} bool EyeOfEnderSignal::shouldRenderAtSqrDistance(double distance) { - double size = bb->getSize() * 4; + double size = bb.getSize() * 4; size *= 64.0f; return distance < size * size; } @@ -159,4 +159,4 @@ float EyeOfEnderSignal::getBrightness(float a) { return 1.0f; } int EyeOfEnderSignal::getLightColor(float a) { return 15 << 20 | 15 << 4; } -bool EyeOfEnderSignal::isAttackable() { return false; } \ No newline at end of file +bool EyeOfEnderSignal::isAttackable() { return false; } diff --git a/Minecraft.World/Entities/Mobs/Fireball.cpp b/Minecraft.World/Entities/Mobs/Fireball.cpp index 1bf7bf6df..86ebfd150 100644 --- a/Minecraft.World/Entities/Mobs/Fireball.cpp +++ b/Minecraft.World/Entities/Mobs/Fireball.cpp @@ -39,7 +39,7 @@ Fireball::Fireball(Level* level) : Entity(level) { void Fireball::defineSynchedData() {} bool Fireball::shouldRenderAtSqrDistance(double distance) { - double size = bb->getSize() * 4; + double size = bb.getSize() * 4; size *= 64.0f; return distance < size * size; } @@ -166,18 +166,19 @@ void Fireball::tick() { } MemSect(41); - Vec3* from = Vec3::newTemp(x, y, z); - Vec3* to = Vec3::newTemp(x + xd, y + yd, z + zd); - HitResult* res = level->clip(from, to); + Vec3 from(x, y, z); + Vec3 to(x + xd, y + yd, z + zd); + HitResult* res = level->clip(&from, &to); - from = Vec3::newTemp(x, y, z); - to = Vec3::newTemp(x + xd, y + yd, z + zd); + from = Vec3(x, y, z); + to = Vec3(x + xd, y + yd, z + zd); if (res != NULL) { - to = Vec3::newTemp(res->pos->x, res->pos->y, res->pos->z); + to = Vec3{res->pos.x, res->pos.y, res->pos.z}; } std::shared_ptr hitEntity = nullptr; - std::vector >* objects = level->getEntities( - shared_from_this(), bb->expand(xd, yd, zd)->grow(1, 1, 1)); + AABB grown = bb.expand(xd, yd, zd).grow(1, 1, 1); + std::vector >* objects = + level->getEntities(shared_from_this(), &grown); double nearest = 0; AUTO_VAR(itEnd, objects->end()); for (AUTO_VAR(it, objects->begin()); it != itEnd; it++) { @@ -187,10 +188,10 @@ void Fireball::tick() { // && flightTime < 25)) continue; float rr = 0.3f; - AABB* bb = e->bb->grow(rr, rr, rr); - HitResult* p = bb->clip(from, to); + AABB bb = e->bb.grow(rr, rr, rr); + HitResult* p = bb.clip(from, to); if (p != NULL) { - double dd = from->distanceTo(p->pos); + double dd = from.distanceTo(p->pos); if (dd < nearest || nearest == 0) { hitEntity = e; nearest = dd; @@ -300,8 +301,8 @@ bool Fireball::hurt(DamageSource* source, float damage) { markHurt(); if (source->getEntity() != NULL) { - Vec3* lookAngle = source->getEntity()->getLookAngle(); - if (lookAngle != NULL) { + auto lookAngle = source->getEntity()->getLookAngle(); + if (lookAngle.has_value()) { xd = lookAngle->x; yd = lookAngle->y; zd = lookAngle->z; @@ -309,6 +310,7 @@ bool Fireball::hurt(DamageSource* source, float damage) { yPower = yd * 0.1; zPower = zd * 0.1; } + if (source->getEntity()->instanceof(eTYPE_LIVINGENTITY)) { owner = std::dynamic_pointer_cast(source->getEntity()); @@ -326,4 +328,4 @@ int Fireball::getLightColor(float a) { return 15 << 20 | 15 << 4; } ePARTICLE_TYPE Fireball::getTrailParticleType() { return eParticleType_smoke; } -bool Fireball::shouldBurn() { return true; } \ No newline at end of file +bool Fireball::shouldBurn() { return true; } diff --git a/Minecraft.World/Entities/Mobs/FishingHook.cpp b/Minecraft.World/Entities/Mobs/FishingHook.cpp index f5bbb74d7..617f363e8 100644 --- a/Minecraft.World/Entities/Mobs/FishingHook.cpp +++ b/Minecraft.World/Entities/Mobs/FishingHook.cpp @@ -88,7 +88,7 @@ FishingHook::FishingHook(Level* level, std::shared_ptr mob) void FishingHook::defineSynchedData() {} bool FishingHook::shouldRenderAtSqrDistance(double distance) { - double size = bb->getSize() * 4; + double size = bb.getSize() * 4; size *= 64.0f; return distance < size * size; } @@ -175,7 +175,7 @@ void FishingHook::tick() { hookedIn = nullptr; else { x = hookedIn->x; - y = hookedIn->bb->y0 + hookedIn->bbHeight * 0.8; + y = hookedIn->bb.y0 + hookedIn->bbHeight * 0.8; z = hookedIn->z; return; } @@ -203,18 +203,19 @@ void FishingHook::tick() { flightTime++; } - Vec3* from = Vec3::newTemp(x, y, z); - Vec3* to = Vec3::newTemp(x + xd, y + yd, z + zd); - HitResult* res = level->clip(from, to); + Vec3 from(x, y, z); + Vec3 to(x + xd, y + yd, z + zd); + HitResult* res = level->clip(&from, &to); - from = Vec3::newTemp(x, y, z); - to = Vec3::newTemp(x + xd, y + yd, z + zd); + from = Vec3(x, y, z); + to = Vec3(x + xd, y + yd, z + zd); if (res != NULL) { - to = Vec3::newTemp(res->pos->x, res->pos->y, res->pos->z); + to = Vec3(res->pos.x, res->pos.y, res->pos.z); } std::shared_ptr hitEntity = nullptr; - std::vector >* objects = level->getEntities( - shared_from_this(), bb->expand(xd, yd, zd)->grow(1, 1, 1)); + AABB grown = bb.expand(xd, yd, zd).grow(1, 1, 1); + std::vector >* objects = + level->getEntities(shared_from_this(), &grown); double nearest = 0; AUTO_VAR(itEnd, objects->end()); for (AUTO_VAR(it, objects->begin()); it != itEnd; it++) { @@ -222,10 +223,10 @@ void FishingHook::tick() { if (!e->isPickable() || (e == owner && flightTime < 5)) continue; float rr = 0.3f; - AABB* bb = e->bb->grow(rr, rr, rr); - HitResult* p = bb->clip(from, to); + AABB bb = e->bb.grow(rr, rr, rr); + HitResult* p = bb.clip(from, to); if (p != NULL) { - double dd = from->distanceTo(p->pos); + double dd = from.distanceTo(p->pos); if (dd < nearest || nearest == 0) { hitEntity = e; nearest = dd; @@ -283,12 +284,12 @@ void FishingHook::tick() { int steps = 5; double waterPercentage = 0; for (int i = 0; i < steps; i++) { - double y0 = bb->y0 + (bb->y1 - bb->y0) * (i + 0) / steps - 2 / 16.0f + + double y0 = bb.y0 + (bb.y1 - bb.y0) * (i + 0) / steps - 2 / 16.0f + 2 / 16.0f; - double y1 = bb->y0 + (bb->y1 - bb->y0) * (i + 1) / steps - 2 / 16.0f + + double y1 = bb.y0 + (bb.y1 - bb.y0) * (i + 1) / steps - 2 / 16.0f + 2 / 16.0f; - AABB* bb2 = AABB::newTemp(bb->x0, y0, bb->z0, bb->x1, y1, bb->z1); - if (level->containsLiquid(bb2, Material::water)) { + AABB bb2(bb.x0, y0, bb.z0, bb.x1, y1, bb.z1); + if (level->containsLiquid(&bb2, Material::water)) { waterPercentage += 1.0 / steps; } } @@ -308,7 +309,7 @@ void FishingHook::tick() { playSound( eSoundType_RANDOM_SPLASH, 0.25f, 1 + (random->nextFloat() - random->nextFloat()) * 0.4f); - float yt = (float)Mth::floor(bb->y0); + float yt = (float)Mth::floor(bb.y0); for (int i = 0; i < 1 + bbWidth * 20; i++) { float xo = (random->nextFloat() * 2 - 1) * bbWidth; float zo = (random->nextFloat() * 2 - 1) * bbWidth; @@ -412,4 +413,4 @@ int FishingHook::retrieve() { void FishingHook::remove() { Entity::remove(); if (owner != NULL) owner->fishing = nullptr; -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/Ghast.cpp b/Minecraft.World/Entities/Mobs/Ghast.cpp index c170a0f66..7808df292 100644 --- a/Minecraft.World/Entities/Mobs/Ghast.cpp +++ b/Minecraft.World/Entities/Mobs/Ghast.cpp @@ -119,7 +119,7 @@ void Ghast::serverAiStep() { target->distanceToSqr(shared_from_this()) < maxDist * maxDist) { double xdd = target->x - x; double ydd = - (target->bb->y0 + target->bbHeight / 2) - (y + bbHeight / 2); + (target->bb.y0 + target->bbHeight / 2) - (y + bbHeight / 2); double zdd = target->z - z; yBodyRot = yRot = -(float)atan2(xdd, zdd) * 180 / PI; @@ -141,10 +141,10 @@ void Ghast::serverAiStep() { ydd, zdd)); ie->explosionPower = explosionPower; double d = 4; - Vec3* v = getViewVector(1); - ie->x = x + v->x * d; + Vec3 v = getViewVector(1); + ie->x = x + v.x * d; ie->y = y + bbHeight / 2 + 0.5f; - ie->z = z + v->z * d; + ie->z = z + v.z * d; level->addEntity(ie); charge = -40; } @@ -169,11 +169,11 @@ bool Ghast::canReach(double xt, double yt, double zt, double dist) { double xd = (xTarget - x) / dist; double yd = (yTarget - y) / dist; double zd = (zTarget - z) / dist; + AABB probe = bb; - AABB* bb = this->bb->copy(); for (int d = 1; d < dist; d++) { - bb->move(xd, yd, zd); - if (!level->getCubes(shared_from_this(), bb)->empty()) return false; + probe = probe.move(xd, yd, zd); + if (!level->getCubes(shared_from_this(), &probe)->empty()) return false; } return true; @@ -217,4 +217,4 @@ void Ghast::readAdditionalSaveData(CompoundTag* tag) { FlyingMob::readAdditionalSaveData(tag); if (tag->contains(L"ExplosionPower")) explosionPower = tag->getInt(L"ExplosionPower"); -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/LavaSlime.cpp b/Minecraft.World/Entities/Mobs/LavaSlime.cpp index a84116c43..bcf420571 100644 --- a/Minecraft.World/Entities/Mobs/LavaSlime.cpp +++ b/Minecraft.World/Entities/Mobs/LavaSlime.cpp @@ -27,9 +27,9 @@ void LavaSlime::registerAttributes() { bool LavaSlime::canSpawn() { return level->difficulty > Difficulty::PEACEFUL && - level->isUnobstructed(bb) && - level->getCubes(shared_from_this(), bb)->empty() && - !level->containsAnyLiquid(bb); + level->isUnobstructed(&bb) && + level->getCubes(shared_from_this(), &bb)->empty() && + !level->containsAnyLiquid(&bb); } int LavaSlime::getArmorValue() { return getSize() * 3; } @@ -102,4 +102,4 @@ bool LavaSlime::isInLava() { return false; } -bool LavaSlime::doPlayLandSound() { return true; } \ No newline at end of file +bool LavaSlime::doPlayLandSound() { return true; } diff --git a/Minecraft.World/Entities/Mobs/LightningBolt.cpp b/Minecraft.World/Entities/Mobs/LightningBolt.cpp index fe864cb07..24bd495dd 100644 --- a/Minecraft.World/Entities/Mobs/LightningBolt.cpp +++ b/Minecraft.World/Entities/Mobs/LightningBolt.cpp @@ -105,10 +105,9 @@ void LightningBolt::tick() { level->skyFlashTime = 2; } else { double r = 3; + AABB aoe_bb = AABB(x, y, z, x, y + 6, z).grow(r, r, r); std::vector >* entities = - level->getEntities(shared_from_this(), - AABB::newTemp(x - r, y - r, z - r, x + r, - y + 6 + r, z + r)); + level->getEntities(shared_from_this(), &aoe_bb); AUTO_VAR(itEnd, entities->end()); for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) { std::shared_ptr e = (*it); // entities->at(i); diff --git a/Minecraft.World/Entities/Mobs/Minecart.cpp b/Minecraft.World/Entities/Mobs/Minecart.cpp index 4351c4ad8..7c6b1e24c 100644 --- a/Minecraft.World/Entities/Mobs/Minecart.cpp +++ b/Minecraft.World/Entities/Mobs/Minecart.cpp @@ -13,6 +13,8 @@ #include "../../../Minecraft.Client/Level/ServerLevel.h" #include "../../Headers/com.mojang.nbt.h" #include "Minecart.h" +#include +#include #include "../../Util/SharedConstants.h" const int Minecart::EXITS[][2][3] = { @@ -96,7 +98,7 @@ void Minecart::defineSynchedData() { AABB* Minecart::getCollideAgainstBox(std::shared_ptr entity) { if (entity->isPushable()) { - return entity->bb; + return &entity->bb; } return NULL; } @@ -129,10 +131,9 @@ bool Minecart::hurt(DamageSource* source, float hurtDamage) { if (dynamic_cast(source) != NULL) { std::shared_ptr attacker = source->getDirectEntity(); - if (attacker->instanceof - (eTYPE_PLAYER) && - !std::dynamic_pointer_cast(attacker) - ->isAllowedToHurtEntity(shared_from_this())) { + if (attacker->instanceof(eTYPE_PLAYER) && + !std::dynamic_pointer_cast(attacker)->isAllowedToHurtEntity( + shared_from_this())) { return false; } } @@ -149,9 +150,9 @@ bool Minecart::hurt(DamageSource* source, float hurtDamage) { if (rider.lock() != NULL && rider.lock() == source->getEntity()) hurtDamage += 1; - bool creativePlayer = - source->getEntity() != NULL && source->getEntity()->instanceof - (eTYPE_PLAYER) && std::dynamic_pointer_cast(source->getEntity()) + bool creativePlayer = source->getEntity() != NULL && + source->getEntity()->instanceof(eTYPE_PLAYER) && + std::dynamic_pointer_cast(source->getEntity()) ->abilities.instabuild; if (creativePlayer || getDamage() > 20 * 2) { @@ -304,14 +305,15 @@ void Minecart::tick() { } setRot(yRot, xRot); + AABB grown = bb.grow(0.2, 0, 0.2); std::vector >* entities = - level->getEntities(shared_from_this(), bb->grow(0.2f, 0, 0.2f)); + level->getEntities(shared_from_this(), &grown); if (entities != NULL && !entities->empty()) { AUTO_VAR(itEnd, entities->end()); for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) { std::shared_ptr e = (*it); // entities->at(i); - if (e != rider.lock() && e->isPushable() && e->instanceof - (eTYPE_MINECART)) { + if (e != rider.lock() && e->isPushable() && + e->instanceof(eTYPE_MINECART)) { std::shared_ptr cart = std::dynamic_pointer_cast(e); cart->m_bHasPushedCartThisTick = false; @@ -362,7 +364,7 @@ void Minecart::moveAlongTrack(int xt, int yt, int zt, double maxSpeed, double slideSpeed, int tile, int data) { fallDistance = 0; - Vec3* oldPos = getPos(x, y, z); + auto oldPos = getPos(x, y, z); y = yt; bool powerTrack = false; @@ -405,7 +407,7 @@ void Minecart::moveAlongTrack(int xt, int yt, int zt, double maxSpeed, xd = pow * xD / dd; zd = pow * zD / dd; - if (rider.lock() != NULL && rider.lock()->instanceof (eTYPE_LIVINGENTITY)) { + if (rider.lock() != NULL && rider.lock()->instanceof(eTYPE_LIVINGENTITY)) { std::shared_ptr living = std::dynamic_pointer_cast(rider.lock()); @@ -490,8 +492,8 @@ void Minecart::moveAlongTrack(int xt, int yt, int zt, double maxSpeed, applyNaturalSlowdown(); - Vec3* newPos = getPos(x, y, z); - if (newPos != NULL && oldPos != NULL) { + auto newPos = getPos(x, y, z); + if (newPos.has_value() && oldPos.has_value()) { double speed = (oldPos->y - newPos->y) * 0.05; pow = sqrt(xd * xd + zd * zd); @@ -550,7 +552,8 @@ void Minecart::applyNaturalSlowdown() { } } -Vec3* Minecart::getPosOffs(double x, double y, double z, double offs) { +std::optional Minecart::getPosOffs(double x, double y, double z, + double offs) { int xt = Mth::floor(x); int yt = Mth::floor(y); int zt = Mth::floor(z); @@ -595,10 +598,11 @@ Vec3* Minecart::getPosOffs(double x, double y, double z, double offs) { return getPos(x, y, z); } - return NULL; + + return std::nullopt; } -Vec3* Minecart::getPos(double x, double y, double z) { +std::optional Minecart::getPos(double x, double y, double z) { int xt = Mth::floor(x); int yt = Mth::floor(y); int zt = Mth::floor(z); @@ -654,9 +658,10 @@ Vec3* Minecart::getPos(double x, double y, double z) { z = z0 + zD * progress; if (yD < 0) y += 1; if (yD > 0) y += 0.5; - return Vec3::newTemp(x, y, z); + return Vec3(x, y, z); } - return NULL; + + return std::nullopt; } void Minecart::readAdditionalSaveData(CompoundTag* tag) { @@ -689,10 +694,9 @@ void Minecart::push(std::shared_ptr e) { if (level->isClientSide) return; if (e == rider.lock()) return; - if (e->instanceof (eTYPE_LIVINGENTITY) && !e->instanceof - (eTYPE_PLAYER) && !e->instanceof - (eTYPE_VILLAGERGOLEM) && (getType() == TYPE_RIDEABLE) && - (xd * xd + zd * zd > 0.01)) { + if (e->instanceof(eTYPE_LIVINGENTITY) && !e->instanceof(eTYPE_PLAYER) && + !e->instanceof(eTYPE_VILLAGERGOLEM) && (getType() == TYPE_RIDEABLE) && + (xd * xd + zd * zd > 0.01)) { if ((rider.lock() == NULL) && (e->riding == NULL)) { e->ride(shared_from_this()); } @@ -718,7 +722,7 @@ void Minecart::push(std::shared_ptr e) { xa *= 0.5; za *= 0.5; - if (e->instanceof (eTYPE_MINECART)) { + if (e->instanceof(eTYPE_MINECART)) { double xo = e->x - x; double zo = e->z - z; @@ -726,12 +730,13 @@ void Minecart::push(std::shared_ptr e) { // other // Fix for #38882 - TU5: Gameplay: Minecart with furnace is not // able to move another minecart on the rail. - Vec3* dir = Vec3::newTemp(xo, 0, zo)->normalize(); - Vec3* facing = - Vec3::newTemp(cos(yRot * PI / 180), 0, sin(yRot * PI / 180)) - ->normalize(); + Vec3 dir(xo, 0, zo); + dir = dir.normalize(); - double dot = abs(dir->dot(facing)); + Vec3 facing(cos(yRot * PI / 180), 0, sin(yRot * PI / 180)); + facing = facing.normalize(); + + double dot = abs(dir.dot(facing)); if (dot < 0.8f) { return; diff --git a/Minecraft.World/Entities/Mobs/Minecart.h b/Minecraft.World/Entities/Mobs/Minecart.h index 353df82dc..1fc6e2919 100644 --- a/Minecraft.World/Entities/Mobs/Minecart.h +++ b/Minecraft.World/Entities/Mobs/Minecart.h @@ -1,4 +1,5 @@ #pragma once +#include #include "../Entity.h" class DamageSource; @@ -77,8 +78,9 @@ protected: virtual void moveAlongTrack(int xt, int yt, int zt, double maxSpeed, double slideSpeed, int tile, int data); virtual void applyNaturalSlowdown(); - virtual Vec3* getPosOffs(double x, double y, double z, double offs); - virtual Vec3* getPos(double x, double y, double z); + virtual std::optional getPosOffs(double x, double y, double z, + double offs); + virtual std::optional getPos(double x, double y, double z); protected: virtual void addAdditonalSaveData(CompoundTag* base); diff --git a/Minecraft.World/Entities/Mobs/MushroomCow.cpp b/Minecraft.World/Entities/Mobs/MushroomCow.cpp index fe8bed57b..5ab441782 100644 --- a/Minecraft.World/Entities/Mobs/MushroomCow.cpp +++ b/Minecraft.World/Entities/Mobs/MushroomCow.cpp @@ -67,7 +67,7 @@ bool MushroomCow::mobInteract(std::shared_ptr player) { // already really bool MushroomCow::canSpawn() { int xt = Mth::floor(x); - int yt = Mth::floor(bb->y0); + int yt = Mth::floor(bb.y0); int zt = Mth::floor(z); return (level->getTile(xt, yt - 1, zt) == Tile::grass_Id || level->getTile(xt, yt - 1, zt) == Tile::mycel_Id) && diff --git a/Minecraft.World/Entities/Mobs/Ocelot.cpp b/Minecraft.World/Entities/Mobs/Ocelot.cpp index f9a0e1bdc..ea104f5e5 100644 --- a/Minecraft.World/Entities/Mobs/Ocelot.cpp +++ b/Minecraft.World/Entities/Mobs/Ocelot.cpp @@ -240,11 +240,11 @@ bool Ocelot::canSpawn() { if (level->random->nextInt(3) == 0) { return false; } - if (level->isUnobstructed(bb) && - level->getCubes(shared_from_this(), bb)->empty() && - !level->containsAnyLiquid(bb)) { + if (level->isUnobstructed(&bb) && + level->getCubes(shared_from_this(), &bb)->empty() && + !level->containsAnyLiquid(&bb)) { int xt = Mth::floor(x); - int yt = Mth::floor(bb->y0); + int yt = Mth::floor(bb.y0); int zt = Mth::floor(z); if (yt < level->seaLevel) { return false; @@ -305,4 +305,4 @@ void Ocelot::setSittingOnTile(bool val) { bool Ocelot::isSittingOnTile() { uint8_t current = entityData->getByte(DATA_FLAGS_ID); return (current & 0x02) > 0; -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/PigZombie.cpp b/Minecraft.World/Entities/Mobs/PigZombie.cpp index e619286cb..f88d30044 100644 --- a/Minecraft.World/Entities/Mobs/PigZombie.cpp +++ b/Minecraft.World/Entities/Mobs/PigZombie.cpp @@ -69,9 +69,9 @@ void PigZombie::tick() { bool PigZombie::canSpawn() { return level->difficulty > Difficulty::PEACEFUL && - level->isUnobstructed(bb) && - level->getCubes(shared_from_this(), bb)->empty() && - !level->containsAnyLiquid(bb); + level->isUnobstructed(&bb) && + level->getCubes(shared_from_this(), &bb)->empty() && + !level->containsAnyLiquid(&bb); } void PigZombie::addAdditonalSaveData(CompoundTag* tag) { @@ -100,8 +100,9 @@ std::shared_ptr PigZombie::findAttackTarget() { bool PigZombie::hurt(DamageSource* source, float dmg) { std::shared_ptr sourceEntity = source->getEntity(); if (sourceEntity != NULL && sourceEntity->instanceof(eTYPE_PLAYER)) { + AABB grown = bb.grow(32, 32, 32); std::vector >* nearby = - level->getEntities(shared_from_this(), bb->grow(32, 32, 32)); + level->getEntities(shared_from_this(), &grown); AUTO_VAR(itEnd, nearby->end()); for (AUTO_VAR(it, nearby->begin()); it != itEnd; it++) { std::shared_ptr e = *it; // nearby->at(i); @@ -158,4 +159,4 @@ MobGroupData* PigZombie::finalizeMobSpawn( Zombie::finalizeMobSpawn(groupData); setVillager(false); return groupData; -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/Silverfish.cpp b/Minecraft.World/Entities/Mobs/Silverfish.cpp index 2ced041aa..ec0e014da 100644 --- a/Minecraft.World/Entities/Mobs/Silverfish.cpp +++ b/Minecraft.World/Entities/Mobs/Silverfish.cpp @@ -69,8 +69,8 @@ bool Silverfish::hurt(DamageSource* source, float dmg) { void Silverfish::checkHurtTarget(std::shared_ptr target, float d) { // super.checkHurtTarget(target, d); - if (attackTime <= 0 && d < 1.2f && target->bb->y1 > bb->y0 && - target->bb->y0 < bb->y1) { + if (attackTime <= 0 && d < 1.2f && target->bb.y1 > bb.y0 && + target->bb.y0 < bb.y1) { attackTime = 20; doHurtTarget(target); } @@ -192,4 +192,4 @@ bool Silverfish::canSpawn() { return false; } -MobType Silverfish::getMobType() { return ARTHROPOD; } \ No newline at end of file +MobType Silverfish::getMobType() { return ARTHROPOD; } diff --git a/Minecraft.World/Entities/Mobs/Slime.cpp b/Minecraft.World/Entities/Mobs/Slime.cpp index a504db841..de4816ea7 100644 --- a/Minecraft.World/Entities/Mobs/Slime.cpp +++ b/Minecraft.World/Entities/Mobs/Slime.cpp @@ -91,7 +91,7 @@ void Slime::tick() { float d = random->nextFloat() * 0.5f + 0.5f; float xd = Mth::sin(dir) * size * 0.5f * d; float zd = Mth::cos(dir) * size * 0.5f * d; - level->addParticle(getParticleName(), x + xd, bb->y0, z + zd, 0, 0, + level->addParticle(getParticleName(), x + xd, bb.y0, z + zd, 0, 0, 0); } @@ -248,4 +248,4 @@ int Slime::getMaxHeadXRot() { return 0; } bool Slime::doPlayJumpSound() { return getSize() > 0; } -bool Slime::doPlayLandSound() { return getSize() > 2; } \ No newline at end of file +bool Slime::doPlayLandSound() { return getSize() > 2; } diff --git a/Minecraft.World/Entities/Mobs/Squid.cpp b/Minecraft.World/Entities/Mobs/Squid.cpp index 951d7b511..c04bba6eb 100644 --- a/Minecraft.World/Entities/Mobs/Squid.cpp +++ b/Minecraft.World/Entities/Mobs/Squid.cpp @@ -65,7 +65,8 @@ void Squid::dropDeathLoot(bool wasKilledByPlayer, int playerBonusLevel) { } bool Squid::isInWater() { - return level->checkAndHandleWater(bb->grow(0, -0.6f, 0), Material::water, + AABB grown = bb.grow(0, -0.6, 0); + return level->checkAndHandleWater(&grown, Material::water, shared_from_this()); } diff --git a/Minecraft.World/Entities/Mobs/ThrownPotion.cpp b/Minecraft.World/Entities/Mobs/ThrownPotion.cpp index 3ed57fa98..71020e479 100644 --- a/Minecraft.World/Entities/Mobs/ThrownPotion.cpp +++ b/Minecraft.World/Entities/Mobs/ThrownPotion.cpp @@ -82,9 +82,9 @@ void ThrownPotion::onHit(HitResult* res) { Item::potion->getMobEffects(potionItem); if (mobEffects != NULL && !mobEffects->empty()) { - AABB* aoe = bb->grow(SPLASH_RANGE, SPLASH_RANGE / 2, SPLASH_RANGE); + AABB aoe = bb.grow(SPLASH_RANGE, SPLASH_RANGE / 2, SPLASH_RANGE); std::vector >* entitiesOfClass = - level->getEntitiesOfClass(typeid(LivingEntity), aoe); + level->getEntitiesOfClass(typeid(LivingEntity), &aoe); if (entitiesOfClass != NULL && !entitiesOfClass->empty()) { // for (Entity e : entitiesOfClass) @@ -151,4 +151,4 @@ void ThrownPotion::addAdditonalSaveData(CompoundTag* tag) { if (potionItem != NULL) tag->putCompound(L"Potion", potionItem->save(new CompoundTag())); -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/VillagerGolem.cpp b/Minecraft.World/Entities/Mobs/VillagerGolem.cpp index 6f1880259..a9811005d 100644 --- a/Minecraft.World/Entities/Mobs/VillagerGolem.cpp +++ b/Minecraft.World/Entities/Mobs/VillagerGolem.cpp @@ -113,7 +113,7 @@ void VillagerGolem::aiStep() { if (t > 0) { level->addParticle(PARTICLE_TILECRACK(t, d), x + (random->nextFloat() - 0.5) * bbWidth, - bb->y0 + 0.1, + bb.y0 + 0.1, z + (random->nextFloat() - 0.5) * bbWidth, 4 * (random->nextFloat() - 0.5), .5, (random->nextFloat() - 0.5) * 4); @@ -226,4 +226,4 @@ bool VillagerGolem::hurt(DamageSource* source, float dmg) { } return Golem::hurt(source, dmg); -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/Witch.cpp b/Minecraft.World/Entities/Mobs/Witch.cpp index 4099d1f95..f8e970389 100644 --- a/Minecraft.World/Entities/Mobs/Witch.cpp +++ b/Minecraft.World/Entities/Mobs/Witch.cpp @@ -153,7 +153,7 @@ void Witch::handleEntityEvent(uint8_t id) { for (int i = 0; i < random->nextInt(35) + 10; i++) { level->addParticle(eParticleType_witchMagic, x + random->nextGaussian() * .13f, - bb->y1 + 0.5f + random->nextGaussian() * .13f, + bb.y1 + 0.5f + random->nextGaussian() * .13f, z + random->nextGaussian() * .13f, 0, 0, 0); } } else { @@ -212,4 +212,4 @@ void Witch::performRangedAttack(std::shared_ptr target, potion->shoot(xd, yd + dist * 0.2f, zd, 0.75f, 8); level->addEntity(potion); -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/WitherBoss.cpp b/Minecraft.World/Entities/Mobs/WitherBoss.cpp index 2c6a0d849..1263662d9 100644 --- a/Minecraft.World/Entities/Mobs/WitherBoss.cpp +++ b/Minecraft.World/Entities/Mobs/WitherBoss.cpp @@ -252,9 +252,9 @@ void WitherBoss::newServerAiStep() { idleHeadUpdates[i - 1] = 0; } } else { + AABB grown = bb.grow(20, 8, 20); std::vector >* entities = - level->getEntitiesOfClass(typeid(LivingEntity), - bb->grow(20, 8, 20), + level->getEntitiesOfClass(typeid(LivingEntity), &grown, livingEntitySelector); // randomly try to find a target 10 times for (int attempt = 0; attempt < 10 && !entities->empty(); @@ -506,4 +506,4 @@ bool WitherBoss::isPowered() { return getHealth() <= getMaxHealth() / 2; } MobType WitherBoss::getMobType() { return UNDEAD; } -void WitherBoss::ride(std::shared_ptr e) { riding = nullptr; } \ No newline at end of file +void WitherBoss::ride(std::shared_ptr e) { riding = nullptr; } diff --git a/Minecraft.World/Entities/Mobs/Wolf.cpp b/Minecraft.World/Entities/Mobs/Wolf.cpp index e5ce60cd5..bccbe462e 100644 --- a/Minecraft.World/Entities/Mobs/Wolf.cpp +++ b/Minecraft.World/Entities/Mobs/Wolf.cpp @@ -182,7 +182,7 @@ void Wolf::tick() { } if (shakeAnim > 0.4f) { - float yt = (float)bb->y0; + float yt = (float)bb.y0; int shakeCount = (int)(Mth::sin((shakeAnim - 0.4f) * PI) * 7.0f); for (int i = 0; i < shakeCount; i++) { @@ -503,4 +503,4 @@ bool Wolf::wantsToAttack(std::shared_ptr target, return false; } return true; -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Mobs/Zombie.cpp b/Minecraft.World/Entities/Mobs/Zombie.cpp index d6d15644d..c67e1ccfd 100644 --- a/Minecraft.World/Entities/Mobs/Zombie.cpp +++ b/Minecraft.World/Entities/Mobs/Zombie.cpp @@ -176,10 +176,10 @@ bool Zombie::hurt(DamageSource* source, float dmg) { level->getRawBrightness(xt, yt, zt) < 10) { reinforcement->setPos(xt, yt, zt); - if (level->isUnobstructed(reinforcement->bb) && - level->getCubes(reinforcement, reinforcement->bb) + if (level->isUnobstructed(&reinforcement->bb) && + level->getCubes(reinforcement, &reinforcement->bb) ->empty() && - !level->containsAnyLiquid(reinforcement->bb)) { + !level->containsAnyLiquid(&reinforcement->bb)) { level->addEntity(reinforcement); reinforcement->setTarget(target); reinforcement->finalizeMobSpawn(NULL); @@ -492,4 +492,4 @@ int Zombie::getConversionProgress() { Zombie::ZombieGroupData::ZombieGroupData(bool baby, bool villager) { isBaby = baby; isVillager = villager; -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Monster.cpp b/Minecraft.World/Entities/Monster.cpp index 2b89198e5..a0e98c5d5 100644 --- a/Minecraft.World/Entities/Monster.cpp +++ b/Minecraft.World/Entities/Monster.cpp @@ -113,8 +113,8 @@ bool Monster::doHurtTarget(std::shared_ptr target) { } void Monster::checkHurtTarget(std::shared_ptr target, float distance) { - if (attackTime <= 0 && distance < 2.0f && target->bb->y1 > bb->y0 && - target->bb->y0 < bb->y1) { + if (attackTime <= 0 && distance < 2.0f && target->bb.y1 > bb.y0 && + target->bb.y0 < bb.y1) { attackTime = 20; doHurtTarget(target); } @@ -126,7 +126,7 @@ float Monster::getWalkTargetValue(int x, int y, int z) { bool Monster::isDarkEnoughToSpawn() { int xt = Mth::floor(x); - int yt = Mth::floor(bb->y0); + int yt = Mth::floor(bb.y0); int zt = Mth::floor(z); if (level->getBrightness(LightLayer::Sky, xt, yt, zt) > random->nextInt(32)) return false; @@ -152,4 +152,4 @@ void Monster::registerAttributes() { PathfinderMob::registerAttributes(); getAttributes()->registerAttribute(SharedMonsterAttributes::ATTACK_DAMAGE); -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/PathfinderMob.cpp b/Minecraft.World/Entities/PathfinderMob.cpp index 8b30f6fb8..b2dbbdca6 100644 --- a/Minecraft.World/Entities/PathfinderMob.cpp +++ b/Minecraft.World/Entities/PathfinderMob.cpp @@ -109,7 +109,7 @@ void PathfinderMob::serverAiStep() { // protected. considerForExtraWandering(isDespawnProtected()); - int yFloor = Mth::floor(bb->y0 + 0.5f); + int yFloor = Mth::floor(bb.y0 + 0.5f); bool inWater = isInWater(); bool inLava = isInLava(); @@ -120,18 +120,20 @@ void PathfinderMob::serverAiStep() { return; } - Vec3* target = path->currentPos(shared_from_this()); + Vec3 target = path->currentPos(shared_from_this()); double r = bbWidth * 2; - while (target != NULL && target->distanceToSqr(x, target->y, z) < r * r) { + while (target.distanceToSqr(x, target.y, z) < r * r) { path->next(); if (path->isDone()) { - target = NULL; setPath(NULL); // 4J - changed to setPath from path = + break; } else target = path->currentPos(shared_from_this()); } jumping = false; + // 4jcraft - refactoring Vec3 shows this branch never hits + /* if (target != NULL) { double xd = target->x - x; double zd = target->z - z; @@ -165,6 +167,7 @@ void PathfinderMob::serverAiStep() { jumping = true; } } + */ if (attackTarget != NULL) { lookAt(attackTarget, 30, 30); @@ -223,7 +226,7 @@ std::shared_ptr PathfinderMob::findAttackTarget() { bool PathfinderMob::canSpawn() { int xt = Mth::floor(x); - int yt = Mth::floor(bb->y0); + int yt = Mth::floor(bb.y0); int zt = Mth::floor(z); return this->Mob::canSpawn() && getWalkTargetValue(xt, yt, zt) >= 0; } @@ -328,4 +331,4 @@ void PathfinderMob::onLeashDistance(float distanceToLeashHolder) {} bool PathfinderMob::couldWander() { return (noActionTime < SharedConstants::TICKS_PER_SECOND * 5) || (isExtraWanderingEnabled()); -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/Throwable.cpp b/Minecraft.World/Entities/Throwable.cpp index 5e0165b8e..973c7d8d7 100644 --- a/Minecraft.World/Entities/Throwable.cpp +++ b/Minecraft.World/Entities/Throwable.cpp @@ -27,7 +27,7 @@ Throwable::Throwable(Level* level) : Entity(level) { void Throwable::defineSynchedData() {} bool Throwable::shouldRenderAtSqrDistance(double distance) { - double size = bb->getSize() * 4; + double size = bb.getSize() * 4; size *= 64.0f; return distance < size * size; } @@ -135,20 +135,21 @@ void Throwable::tick() { flightTime++; } - Vec3* from = Vec3::newTemp(x, y, z); - Vec3* to = Vec3::newTemp(x + xd, y + yd, z + zd); - HitResult* res = level->clip(from, to); + Vec3 from(x, y, z); + Vec3 to(x + xd, y + yd, z + zd); + HitResult* res = level->clip(&from, &to); - from = Vec3::newTemp(x, y, z); - to = Vec3::newTemp(x + xd, y + yd, z + zd); + from = Vec3(x, y, z); + to = Vec3(x + xd, y + yd, z + zd); if (res != NULL) { - to = Vec3::newTemp(res->pos->x, res->pos->y, res->pos->z); + to = Vec3(res->pos.x, res->pos.y, res->pos.z); } if (!level->isClientSide) { std::shared_ptr hitEntity = nullptr; - std::vector >* objects = level->getEntities( - shared_from_this(), bb->expand(xd, yd, zd)->grow(1, 1, 1)); + AABB grown = bb.expand(xd, yd, zd).grow(1, 1, 1); + std::vector >* objects = + level->getEntities(shared_from_this(), &grown); double nearest = 0; std::shared_ptr owner = getOwner(); for (int i = 0; i < objects->size(); i++) { @@ -156,10 +157,10 @@ void Throwable::tick() { if (!e->isPickable() || (e == owner && flightTime < 5)) continue; float rr = 0.3f; - AABB* bb = e->bb->grow(rr, rr, rr); - HitResult* p = bb->clip(from, to); + AABB bb = e->bb.grow(rr, rr, rr); + HitResult* p = bb.clip(from, to); if (p != NULL) { - double dd = from->distanceTo(p->pos); + double dd = from.distanceTo(p->pos); delete p; if (dd < nearest || nearest == 0) { hitEntity = e; @@ -256,4 +257,4 @@ std::shared_ptr Throwable::getOwner() { owner = level->getPlayerByName(ownerName); } return owner; -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/WaterAnimal.cpp b/Minecraft.World/Entities/WaterAnimal.cpp index 7cdd2ed31..71470f35b 100644 --- a/Minecraft.World/Entities/WaterAnimal.cpp +++ b/Minecraft.World/Entities/WaterAnimal.cpp @@ -18,7 +18,7 @@ bool WaterAnimal::isWaterMob() { return true; // prevent drowning } -bool WaterAnimal::canSpawn() { return level->isUnobstructed(bb); } +bool WaterAnimal::canSpawn() { return level->isUnobstructed(&bb); } int WaterAnimal::getAmbientSoundInterval() { return 20 * 6; } @@ -42,4 +42,4 @@ void WaterAnimal::baseTick() { } else { setAirSupply(TOTAL_AIR_SUPPLY); } -} \ No newline at end of file +} diff --git a/Minecraft.World/Entities/WitherSkull.cpp b/Minecraft.World/Entities/WitherSkull.cpp index 81a6a4cca..049309c04 100644 --- a/Minecraft.World/Entities/WitherSkull.cpp +++ b/Minecraft.World/Entities/WitherSkull.cpp @@ -105,4 +105,4 @@ void WitherSkull::setDangerous(bool value) { entityData->set(DATA_DANGEROUS, value ? (uint8_t)1 : (uint8_t)0); } -bool WitherSkull::shouldBurn() { return false; } \ No newline at end of file +bool WitherSkull::shouldBurn() { return false; } diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp index 9f4378f02..8ae4310f0 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp +++ b/Minecraft.World/IO/Files/ConsoleSaveFileOriginal.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "../../Platform/stdafx.h" #include "../../Util/StringHelpers.h" #include "../../Util/PortableFileIO.h" diff --git a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp index 5c719be0b..0c3641815 100644 --- a/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp +++ b/Minecraft.World/IO/Files/ConsoleSaveFileSplit.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "../../Platform/stdafx.h" #include "../../Util/StringHelpers.h" #include "../../Util/PortableFileIO.h" @@ -1256,7 +1259,7 @@ void ConsoleSaveFileSplit::Flush(bool autosave, bool updateThumbnail) { while (StorageManager.GetSaveState() != C4JStorage::ESaveGame_Idle) { app.DebugPrintf("Flush wait\n"); - Sleep(10); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); } finalizeWrite(); diff --git a/Minecraft.World/IO/Files/File.cpp b/Minecraft.World/IO/Files/File.cpp index 2b8f95c8d..40fe65724 100644 --- a/Minecraft.World/IO/Files/File.cpp +++ b/Minecraft.World/IO/Files/File.cpp @@ -2,6 +2,7 @@ #include "FileFilter.h" #include "../../Level/Storage/McRegionLevelStorageSource.h" #include "File.h" +#include "PathHelper.h" #include #include @@ -41,17 +42,54 @@ File::File(const File& parent, const std::wstring& child) { // Creates a new File instance by converting the given pathname string into an // abstract pathname. -File::File(const std::wstring& pathname) //: parent( NULL ) -{ - // #ifndef _CONTENT_PACKAGE - // char buf[256]; - // wcstombs(buf, pathname.c_str(), 256); - // printf("File::File - %s\n",buf); - // #endif - if (pathname.empty()) - m_abstractPathName = std::wstring(L""); - else - m_abstractPathName = pathname; + +File::File(const std::wstring& pathname) { + if (pathname.empty()) { + m_abstractPathName = L""; + return; + } + + std::wstring fixedPath = pathname; + for (size_t i = 0; i < fixedPath.length(); ++i) { + if (fixedPath[i] == L'\\') fixedPath[i] = L'/'; + } + size_t dpos; + while ((dpos = fixedPath.find(L"//")) != std::wstring::npos) + fixedPath.erase(dpos, 1); + if (fixedPath.find(L"GAME:/") == 0) fixedPath = fixedPath.substr(6); + m_abstractPathName = fixedPath; + +#if defined(__linux__) + std::string request = wstringtofilename(m_abstractPathName); + while (!request.empty() && request[0] == '/') request.erase(0, 1); + if (request.find("res/") == 0) request.erase(0, 4); + + std::string exeDir = PathHelper::GetExecutableDirA(); + std::string fileName = request; + size_t lastSlash = fileName.find_last_of('/'); + if (lastSlash != std::string::npos) + fileName = fileName.substr(lastSlash + 1); + + const char* bases[] = {"/", + "/Common/res/TitleUpdate/res/", + "/Common/Media/", + "/Common/res/", + "/Common/", + "/Minecraft.Assets/"}; + + for (const char* base : bases) { + std::string tryFull = exeDir + base + request; + std::string tryFile = exeDir + base + fileName; + if (access(tryFull.c_str(), F_OK) != -1) { + m_abstractPathName = convStringToWstring(tryFull); + return; + } + if (access(tryFile.c_str(), F_OK) != -1) { + m_abstractPathName = convStringToWstring(tryFile); + return; + } + } +#endif #ifdef _WINDOWS64 std::string path = wstringtofilename(m_abstractPathName); diff --git a/Minecraft.World/Items/ArmorItem.cpp b/Minecraft.World/Items/ArmorItem.cpp index 3feb87e07..2f4173530 100644 --- a/Minecraft.World/Items/ArmorItem.cpp +++ b/Minecraft.World/Items/ArmorItem.cpp @@ -26,10 +26,10 @@ std::shared_ptr ArmorItem::ArmorDispenseItemBehavior::execute( int x = source->getBlockX() + facing->getStepX(); int y = source->getBlockY() + facing->getStepY(); int z = source->getBlockZ() + facing->getStepZ(); - AABB* bb = AABB::newTemp(x, y, z, x + 1, y + 1, z + 1); + AABB bb = AABB(x, y, z, x + 1, y + 1, z + 1); EntitySelector* selector = new MobCanWearArmourEntitySelector(dispensed); std::vector >* entities = - source->getWorld()->getEntitiesOfClass(typeid(LivingEntity), bb, + source->getWorld()->getEntitiesOfClass(typeid(LivingEntity), &bb, selector); delete selector; @@ -237,4 +237,4 @@ Icon* ArmorItem::getEmptyIcon(int slot) { } return NULL; -} \ No newline at end of file +} diff --git a/Minecraft.World/Items/BoatItem.cpp b/Minecraft.World/Items/BoatItem.cpp index 90f9b7f32..313b658e1 100644 --- a/Minecraft.World/Items/BoatItem.cpp +++ b/Minecraft.World/Items/BoatItem.cpp @@ -5,6 +5,7 @@ #include "../Headers/net.minecraft.world.level.tile.h" #include "../Headers/net.minecraft.world.phys.h" #include "ItemInstance.h" +#include "Util/Vec3.h" #include "BoatItem.h" BoatItem::BoatItem(int id) : Item(id) { maxStackSize = 1; } @@ -24,7 +25,7 @@ bool BoatItem::TestUse(std::shared_ptr itemInstance, Level* level, player->yo + (player->y - player->yo) + 1.62 - player->heightOffset; double z = player->zo + (player->z - player->zo); - Vec3* from = Vec3::newTemp(x, y, z); + Vec3 from(x, y, z); float yCos = Mth::cos(-yRot * Mth::RAD_TO_GRAD - PI); float ySin = Mth::sin(-yRot * Mth::RAD_TO_GRAD - PI); @@ -36,8 +37,9 @@ bool BoatItem::TestUse(std::shared_ptr itemInstance, Level* level, float za = yCos * xCos; double range = 5; - Vec3* to = from->add(xa * range, ya * range, za * range); - HitResult* hr = level->clip(from, to, true); + Vec3 to(xa * range, ya * range, za * range); + to = to.add(from.x, from.y, from.z); + HitResult* hr = level->clip(&from, &to, true); if (hr == NULL) return false; if (hr->type == HitResult::TILE) { @@ -60,7 +62,7 @@ std::shared_ptr BoatItem::use( player->yo + (player->y - player->yo) * a + 1.62 - player->heightOffset; double z = player->zo + (player->z - player->zo) * a; - Vec3* from = Vec3::newTemp(x, y, z); + Vec3 from(x, y, z); float yCos = Mth::cos(-yRot * Mth::RAD_TO_GRAD - PI); float ySin = Mth::sin(-yRot * Mth::RAD_TO_GRAD - PI); @@ -72,26 +74,27 @@ std::shared_ptr BoatItem::use( float za = yCos * xCos; double range = 5; - Vec3* to = from->add(xa * range, ya * range, za * range); - HitResult* hr = level->clip(from, to, true); + Vec3 to(xa * range, ya * range, za * range); + to = to.add(from.x, from.y, from.z); + HitResult* hr = level->clip(&from, &to, true); if (hr == NULL) return itemInstance; // check entity collision - Vec3* b = player->getViewVector(a); + Vec3 b = player->getViewVector(a); bool hitEntity = false; float overlap = 1; - std::vector >* objects = level->getEntities( - player, - player->bb->expand(b->x * (range), b->y * (range), b->z * (range)) - ->grow(overlap, overlap, overlap)); + AABB grown = player->bb.expand(b.x * (range), b.y * (range), b.z * (range)) + .grow(overlap, overlap, overlap); + std::vector >* objects = + level->getEntities(player, &grown); // for (int i = 0; i < objects.size(); i++) { for (AUTO_VAR(it, objects->begin()); it != objects->end(); ++it) { std::shared_ptr e = *it; // objects.get(i); if (!e->isPickable()) continue; float rr = e->getPickRadius(); - AABB* bb = e->bb->grow(rr, rr, rr); - if (bb->contains(from)) { + AABB bb = e->bb.grow(rr, rr, rr); + if (bb.contains(from)) { hitEntity = true; } } @@ -113,8 +116,8 @@ std::shared_ptr BoatItem::use( boat->yRot = ((Mth::floor(player->yRot * 4.0F / 360.0F + 0.5) & 0x3) - 1) * 90; - if (!level->getCubes(boat, boat->bb->grow(-.1, -.1, -.1)) - ->empty()) { + AABB grown = boat->bb.grow(-0.1, -0.1, -0.1); + if (!level->getCubes(boat, &grown)->empty()) { return itemInstance; } if (!level->isClientSide) { @@ -131,4 +134,4 @@ std::shared_ptr BoatItem::use( delete hr; return itemInstance; -} \ No newline at end of file +} diff --git a/Minecraft.World/Items/Item.cpp b/Minecraft.World/Items/Item.cpp index c1bf2666c..0cc1a2e5d 100644 --- a/Minecraft.World/Items/Item.cpp +++ b/Minecraft.World/Items/Item.cpp @@ -15,6 +15,7 @@ #include "Item.h" #include "HangingEntityItem.h" #include "../Util/HtmlString.h" +#include "Util/Vec3.h" typedef Item::Tier _Tier; @@ -1602,7 +1603,7 @@ HitResult* Item::getPlayerPOVHitResult(Level* level, player->yo + (player->y - player->yo) * a + 1.62 - player->heightOffset; double z = player->zo + (player->z - player->zo) * a; - Vec3* from = Vec3::newTemp(x, y, z); + Vec3 from(x, y, z); float yCos = (float)cos(-yRot * Mth::RAD_TO_GRAD - PI); float ySin = (float)sin(-yRot * Mth::RAD_TO_GRAD - PI); @@ -1614,8 +1615,9 @@ HitResult* Item::getPlayerPOVHitResult(Level* level, float za = yCos * xCos; double range = 5; - Vec3* to = from->add(xa * range, ya * range, za * range); - return level->clip(from, to, alsoPickLiquid, !alsoPickLiquid); + Vec3 to(xa * range, ya * range, za * range); + to = to.add(from.x, from.y, from.z); + return level->clip(&from, &to, alsoPickLiquid, !alsoPickLiquid); } int Item::getEnchantmentValue() { return 0; } diff --git a/Minecraft.World/Items/LeashItem.cpp b/Minecraft.World/Items/LeashItem.cpp index a00d296a1..1139a5d86 100644 --- a/Minecraft.World/Items/LeashItem.cpp +++ b/Minecraft.World/Items/LeashItem.cpp @@ -3,6 +3,7 @@ #include "../Headers/net.minecraft.world.level.h" #include "../Headers/net.minecraft.world.entity.h" #include "../Headers/net.minecraft.world.phys.h" +#include "Util/AABB.h" #include "LeashItem.h" LeashItem::LeashItem(int id) : Item(id) {} @@ -35,9 +36,9 @@ bool LeashItem::bindPlayerMobs(std::shared_ptr player, Level* level, // look for entities that can be attached to the fence bool foundMobs = false; double range = 7; - std::vector >* mobs = level->getEntitiesOfClass( - typeid(Mob), AABB::newTemp(x - range, y - range, z - range, x + range, - y + range, z + range)); + AABB mob_bb = AABB(x, y, z, x, y, z).grow(range, range, range); + std::vector >* mobs = + level->getEntitiesOfClass(typeid(Mob), &mob_bb); if (mobs != NULL) { for (AUTO_VAR(it, mobs->begin()); it != mobs->end(); ++it) { std::shared_ptr mob = std::dynamic_pointer_cast(*it); @@ -59,9 +60,9 @@ bool LeashItem::bindPlayerMobsTest(std::shared_ptr player, Level* level, int x, int y, int z) { // look for entities that can be attached to the fence double range = 7; - std::vector >* mobs = level->getEntitiesOfClass( - typeid(Mob), AABB::newTemp(x - range, y - range, z - range, x + range, - y + range, z + range)); + AABB mob_bb = AABB(x, y, z, x, y, z).grow(range, range, range); + std::vector >* mobs = + level->getEntitiesOfClass(typeid(Mob), &mob_bb); if (mobs != NULL) { for (AUTO_VAR(it, mobs->begin()); it != mobs->end(); ++it) { @@ -71,4 +72,4 @@ bool LeashItem::bindPlayerMobsTest(std::shared_ptr player, Level* level, } } return false; -} \ No newline at end of file +} diff --git a/Minecraft.World/Items/SnowItem.cpp b/Minecraft.World/Items/SnowItem.cpp index b6196253e..66524f9b4 100644 --- a/Minecraft.World/Items/SnowItem.cpp +++ b/Minecraft.World/Items/SnowItem.cpp @@ -3,6 +3,7 @@ #include "../Headers/net.minecraft.world.level.tile.h" #include "../Headers/net.minecraft.world.level.h" #include "SnowItem.h" +#include "Util/AABB.h" SnowItem::SnowItem(int id, Tile* parentTile) : AuxDataTileItem(id, parentTile) {} @@ -22,8 +23,9 @@ bool SnowItem::useOn(std::shared_ptr instance, int currentData = level->getData(x, y, z); int currentHeight = currentData & TopSnowTile::HEIGHT_MASK; + auto snow_bb = snowTile->getAABB(level, x, y, z); if (currentHeight <= TopSnowTile::MAX_HEIGHT && - level->isUnobstructed(snowTile->getAABB(level, x, y, z))) { + level->isUnobstructed(snow_bb.has_value() ? &*snow_bb : nullptr)) { if (!bTestUseOnOnly) { // Increase snow tile height if (level->setData( @@ -46,4 +48,4 @@ bool SnowItem::useOn(std::shared_ptr instance, return AuxDataTileItem::useOn(instance, player, level, x, y, z, face, clickX, clickY, clickZ, bTestUseOnOnly); -} \ No newline at end of file +} diff --git a/Minecraft.World/Items/TileItems/StoneSlabTileItem.cpp b/Minecraft.World/Items/TileItems/StoneSlabTileItem.cpp index 86940cbff..e7e83fa93 100644 --- a/Minecraft.World/Items/TileItems/StoneSlabTileItem.cpp +++ b/Minecraft.World/Items/TileItems/StoneSlabTileItem.cpp @@ -6,6 +6,7 @@ #include "../../Headers/net.minecraft.world.level.tile.h" #include "../../Headers/net.minecraft.h" #include "StoneSlabTileItem.h" +#include "../../Util/AABB.h" StoneSlabTileItem::StoneSlabTileItem(int id, HalfSlabTile* halfTile, HalfSlabTile* fullTile, bool full) @@ -55,7 +56,8 @@ bool StoneSlabTileItem::useOn(std::shared_ptr instance, return true; } - if (level->isUnobstructed(fullTile->getAABB(level, x, y, z)) && + auto tile_bb = fullTile->getAABB(level, x, y, z); + if (level->isUnobstructed(tile_bb.has_value() ? &*tile_bb : nullptr) && level->setTileAndData(x, y, z, fullTile->id, slabType, Tile::UPDATE_ALL)) { level->playSound(x + 0.5f, y + 0.5f, z + 0.5f, @@ -127,7 +129,8 @@ bool StoneSlabTileItem::tryConvertTargetTile( if (bTestUseOnOnly) { return true; } - if (level->isUnobstructed(fullTile->getAABB(level, x, y, z)) && + auto tile_bb = fullTile->getAABB(level, x, y, z); + if (level->isUnobstructed(tile_bb.has_value() ? &*tile_bb : nullptr) && level->setTileAndData(x, y, z, fullTile->id, slabType, Tile::UPDATE_ALL)) { level->playSound(x + 0.5f, y + 0.5f, z + 0.5f, @@ -140,4 +143,4 @@ bool StoneSlabTileItem::tryConvertTargetTile( } return false; -} \ No newline at end of file +} diff --git a/Minecraft.World/Level/BaseMobSpawner.cpp b/Minecraft.World/Level/BaseMobSpawner.cpp index 522290eec..bf6fcb51c 100644 --- a/Minecraft.World/Level/BaseMobSpawner.cpp +++ b/Minecraft.World/Level/BaseMobSpawner.cpp @@ -83,14 +83,13 @@ void BaseMobSpawner::tick() { EntityIO::newEntity(getEntityId(), getLevel()); if (entity == NULL) return; - int nearBy = - getLevel() - ->getEntitiesOfClass( - typeid(entity.get()), - AABB::newTemp(getX(), getY(), getZ(), getX() + 1, - getY() + 1, getZ() + 1) - ->grow(spawnRange * 2, 4, spawnRange * 2)) - ->size(); + AABB grown = + AABB(getX(), getY(), getZ(), getX() + 1, getY() + 1, getZ() + 1) + .grow(spawnRange * 2, 4, spawnRange * 2); + + int nearBy = getLevel() + ->getEntitiesOfClass(typeid(entity.get()), &grown) + ->size(); if (nearBy >= maxNearbyEntities) { delay(); return; @@ -359,4 +358,4 @@ CompoundTag* BaseMobSpawner::SpawnData::save() { result->putInt(L"Weight", randomWeight); return result; -} \ No newline at end of file +} diff --git a/Minecraft.World/Level/ChunkPos.h b/Minecraft.World/Level/ChunkPos.h index 9a2eabca4..e38a551a5 100644 --- a/Minecraft.World/Level/ChunkPos.h +++ b/Minecraft.World/Level/ChunkPos.h @@ -44,4 +44,4 @@ struct ChunkPosKeyEq { bool operator()(const ChunkPos& x, const ChunkPos& y) const { return ChunkPos::eq_test(x, y); } -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Level/Dimensions/Dimension.cpp b/Minecraft.World/Level/Dimensions/Dimension.cpp index a4447878c..0af723d87 100644 --- a/Minecraft.World/Level/Dimensions/Dimension.cpp +++ b/Minecraft.World/Level/Dimensions/Dimension.cpp @@ -157,7 +157,7 @@ float* Dimension::getSunriseColor(float td, float a) { return NULL; } -Vec3* Dimension::getFogColor(float td, float a) const { +Vec3 Dimension::getFogColor(float td, float a) const { float br = Mth::cos(td * PI * 2) * 2 + 0.5f; if (br < 0.0f) br = 0.0f; if (br > 1.0f) br = 1.0f; @@ -172,7 +172,7 @@ Vec3* Dimension::getFogColor(float td, float a) const { g *= br * 0.94f + 0.06f; b *= br * 0.91f + 0.09f; - return Vec3::newTemp(r, g, b); + return Vec3(r, g, b); } bool Dimension::mayRespawn() const { return true; } diff --git a/Minecraft.World/Level/Dimensions/Dimension.h b/Minecraft.World/Level/Dimensions/Dimension.h index b5d1f4674..0aea9e38c 100644 --- a/Minecraft.World/Level/Dimensions/Dimension.h +++ b/Minecraft.World/Level/Dimensions/Dimension.h @@ -48,7 +48,7 @@ private: public: virtual float* getSunriseColor(float td, float a); - virtual Vec3* getFogColor(float td, float a) const; + virtual Vec3 getFogColor(float td, float a) const; virtual bool mayRespawn() const; static Dimension* getNew(int id); virtual float getCloudHeight(); diff --git a/Minecraft.World/Level/Dimensions/HellDimension.cpp b/Minecraft.World/Level/Dimensions/HellDimension.cpp index f2869a58b..87d8ae155 100644 --- a/Minecraft.World/Level/Dimensions/HellDimension.cpp +++ b/Minecraft.World/Level/Dimensions/HellDimension.cpp @@ -15,7 +15,7 @@ void HellDimension::init() { id = -1; } -Vec3* HellDimension::getFogColor(float td, float a) const { +Vec3 HellDimension::getFogColor(float td, float a) const { int colour = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Nether_Fog_Colour); uint8_t redComponent = ((colour >> 16) & 0xFF); @@ -25,7 +25,7 @@ Vec3* HellDimension::getFogColor(float td, float a) const { float rr = (float)redComponent / 256; // 0.2f; float gg = (float)greenComponent / 256; // 0.03f; float bb = (float)blueComponent / 256; // 0.03f; - return Vec3::newTemp(rr, gg, bb); + return Vec3(rr, gg, bb); } void HellDimension::updateLightRamp() { diff --git a/Minecraft.World/Level/Dimensions/HellDimension.h b/Minecraft.World/Level/Dimensions/HellDimension.h index 93f374687..caa6ff55f 100644 --- a/Minecraft.World/Level/Dimensions/HellDimension.h +++ b/Minecraft.World/Level/Dimensions/HellDimension.h @@ -4,7 +4,7 @@ class HellDimension : public Dimension { public: virtual void init(); - virtual Vec3* getFogColor(float td, float a) const; + virtual Vec3 getFogColor(float td, float a) const; protected: virtual void updateLightRamp(); diff --git a/Minecraft.World/Level/Dimensions/SkyIslandDimension.cpp b/Minecraft.World/Level/Dimensions/SkyIslandDimension.cpp index 74ebb817a..07cb4fe4b 100644 --- a/Minecraft.World/Level/Dimensions/SkyIslandDimension.cpp +++ b/Minecraft.World/Level/Dimensions/SkyIslandDimension.cpp @@ -20,7 +20,7 @@ float SkyIslandDimension::getTimeOfDay(int64_t time, float a) const { float* SkyIslandDimension::getSunriseColor(float td, float a) { return NULL; } -Vec3* SkyIslandDimension::getFogColor(float td, float a) const { +Vec3 SkyIslandDimension::getFogColor(float td, float a) const { int fogColor = 0x8080a0; float br = Mth::cos(td * PI * 2) * 2 + 0.5f; if (br < 0.0f) br = 0.0f; @@ -33,7 +33,7 @@ Vec3* SkyIslandDimension::getFogColor(float td, float a) const { g *= br * 0.94f + 0.06f; b *= br * 0.91f + 0.09f; - return Vec3::newTemp(r, g, b); + return Vec3(r, g, b); } bool SkyIslandDimension::hasGround() { return false; } @@ -46,4 +46,4 @@ bool SkyIslandDimension::isValidSpawn(int x, int z) const { if (topTile == 0) return false; return Tile::tiles[topTile]->material->blocksMotion(); -} \ No newline at end of file +} diff --git a/Minecraft.World/Level/Dimensions/TheEndDimension.cpp b/Minecraft.World/Level/Dimensions/TheEndDimension.cpp index 9ffba3f97..d1b40addb 100644 --- a/Minecraft.World/Level/Dimensions/TheEndDimension.cpp +++ b/Minecraft.World/Level/Dimensions/TheEndDimension.cpp @@ -23,7 +23,7 @@ float TheEndDimension::getTimeOfDay(int64_t time, float a) const { float* TheEndDimension::getSunriseColor(float td, float a) { return NULL; } -Vec3* TheEndDimension::getFogColor(float td, float a) const { +Vec3 TheEndDimension::getFogColor(float td, float a) const { int fogColor = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_End_Fog_Colour); // 0xa080a0; float br = Mth::cos(td * PI * 2) * 2 + 0.5f; @@ -37,7 +37,7 @@ Vec3* TheEndDimension::getFogColor(float td, float a) const { g *= br * 0.0f + 0.15f; b *= br * 0.0f + 0.15f; - return Vec3::newTemp(r, g, b); + return Vec3(r, g, b); } bool TheEndDimension::hasGround() { return false; } @@ -60,4 +60,4 @@ Pos* TheEndDimension::getSpawnPos() { return new Pos(100, 50, 0); } bool TheEndDimension::isFoggyAt(int x, int z) { return true; } -int TheEndDimension::getSpawnYPosition() { return 50; } \ No newline at end of file +int TheEndDimension::getSpawnYPosition() { return 50; } diff --git a/Minecraft.World/Level/Dimensions/TheEndDimension.h b/Minecraft.World/Level/Dimensions/TheEndDimension.h index c6c601e99..304974106 100644 --- a/Minecraft.World/Level/Dimensions/TheEndDimension.h +++ b/Minecraft.World/Level/Dimensions/TheEndDimension.h @@ -7,7 +7,7 @@ public: virtual ChunkSource* createRandomLevelSource() const; virtual float getTimeOfDay(int64_t time, float a) const; virtual float* getSunriseColor(float td, float a); - virtual Vec3* getFogColor(float td, float a) const; + virtual Vec3 getFogColor(float td, float a) const; virtual bool hasGround(); virtual bool mayRespawn() const; virtual bool isNaturalDimension(); diff --git a/Minecraft.World/Level/Events/VillageSiege.cpp b/Minecraft.World/Level/Events/VillageSiege.cpp index 3b623da8c..abf2dc517 100644 --- a/Minecraft.World/Level/Events/VillageSiege.cpp +++ b/Minecraft.World/Level/Events/VillageSiege.cpp @@ -4,6 +4,7 @@ #include "../../Headers/net.minecraft.world.entity.monster.h" #include "../../Headers/net.minecraft.world.level.h" #include "VillageSiege.h" +#include VillageSiege::VillageSiege(Level* level) { hasSetupSiege = false; @@ -108,8 +109,8 @@ bool VillageSiege::tryToSetupSiege() { } if (overlaps) return false; - Vec3* spawnPos = findRandomSpawnPos(spawnX, spawnY, spawnZ); - if (spawnPos == NULL) continue; + auto spawnPos = findRandomSpawnPos(spawnX, spawnY, spawnZ); + if (!spawnPos.has_value()) continue; nextSpawnTime = 0; siegeCount = 20; @@ -119,8 +120,8 @@ bool VillageSiege::tryToSetupSiege() { } bool VillageSiege::trySpawn() { - Vec3* spawnPos = findRandomSpawnPos(spawnX, spawnY, spawnZ); - if (spawnPos == NULL) return false; + auto spawnPos = findRandomSpawnPos(spawnX, spawnY, spawnZ); + if (!spawnPos.has_value()) return false; std::shared_ptr mob; // try { @@ -143,9 +144,9 @@ bool VillageSiege::trySpawn() { return true; } -Vec3* VillageSiege::findRandomSpawnPos(int x, int y, int z) { +std::optional VillageSiege::findRandomSpawnPos(int x, int y, int z) { std::shared_ptr _village = village.lock(); - if (_village == NULL) return NULL; + if (_village == NULL) return std::nullopt; for (int i = 0; i < 10; ++i) { int xx = x + level->random->nextInt(16) - 8; @@ -154,7 +155,8 @@ Vec3* VillageSiege::findRandomSpawnPos(int x, int y, int z) { if (!_village->isInside(xx, yy, zz)) continue; if (MobSpawner::isSpawnPositionOk(MobCategory::monster, level, xx, yy, zz)) - return Vec3::newTemp(xx, yy, zz); + return Vec3(xx, yy, zz); } - return NULL; -} \ No newline at end of file + + return std::nullopt; +} diff --git a/Minecraft.World/Level/Events/VillageSiege.h b/Minecraft.World/Level/Events/VillageSiege.h index f6a978824..35456c3aa 100644 --- a/Minecraft.World/Level/Events/VillageSiege.h +++ b/Minecraft.World/Level/Events/VillageSiege.h @@ -1,5 +1,7 @@ #pragma once +#include + class VillageSiege { private: Level* level; @@ -23,5 +25,5 @@ public: private: bool tryToSetupSiege(); bool trySpawn(); - Vec3* findRandomSpawnPos(int x, int y, int z); -}; \ No newline at end of file + std::optional findRandomSpawnPos(int x, int y, int z); +}; diff --git a/Minecraft.World/Level/Explosion.cpp b/Minecraft.World/Level/Explosion.cpp index e3718a552..9be40d49b 100644 --- a/Minecraft.World/Level/Explosion.cpp +++ b/Minecraft.World/Level/Explosion.cpp @@ -9,6 +9,7 @@ #include "TilePos.h" #include "Explosion.h" #include "../Util/SoundTypes.h" +#include "Util/AABB.h" Explosion::Explosion(Level* level, std::shared_ptr source, double x, double y, double z, float r) { @@ -26,12 +27,7 @@ Explosion::Explosion(Level* level, std::shared_ptr source, double x, size = 16; } -Explosion::~Explosion() { - delete random; - for (AUTO_VAR(it, hitPlayers.begin()); it != hitPlayers.end(); ++it) { - delete it->second; - } -} +Explosion::~Explosion() { delete random; } void Explosion::explode() { float oR = r; @@ -104,11 +100,13 @@ void Explosion::explode() { // time. If we explode something next to an EnderCrystal then it creates a // new explosion that overwrites the shared vector in the level So copy it // here instead of directly using the shared one + + AABB source_bb(x0, y0, z0, x1, y1, z1); std::vector >* levelEntities = - level->getEntities(source, AABB::newTemp(x0, y0, z0, x1, y1, z1)); + level->getEntities(source, &source_bb); std::vector > entities(levelEntities->begin(), levelEntities->end()); - Vec3* center = Vec3::newTemp(x, y, z); + Vec3 center(x, y, z); AUTO_VAR(itEnd, entities.end()); for (AUTO_VAR(it, entities.begin()); it != itEnd; it++) { @@ -120,7 +118,7 @@ void Explosion::explode() { // walls bool canDamage = false; for (AUTO_VAR(it2, toBlow.begin()); it2 != toBlow.end(); ++it2) { - if (e->bb->intersects(it2->x, it2->y, it2->z, it2->x + 1, + if (e->bb.intersects(it2->x, it2->y, it2->z, it2->x + 1, it2->y + 1, it2->z + 1)) { canDamage = true; break; @@ -146,7 +144,7 @@ void Explosion::explode() { za /= da; } - double sp = level->getSeenPercent(center, e->bb); + double sp = level->getSeenPercent(¢er, &e->bb); double pow = (1 - dist) * sp; if (canDamage) e->hurt(DamageSource::explosion(this), @@ -165,7 +163,7 @@ void Explosion::explode() { // app.DebugPrintf("Adding player knockback (%f,%f,%f)\n", xa * // pow, ya * pow, za * pow); hitPlayers.insert(playerVec3Map::value_type( - player, Vec3::newPermanent(xa * pow, ya * pow, za * pow))); + player, Vec3(xa * pow, ya * pow, za * pow))); } } } @@ -283,10 +281,10 @@ void Explosion::finalizeExplosion( Explosion::playerVec3Map* Explosion::getHitPlayers() { return &hitPlayers; } -Vec3* Explosion::getHitPlayerKnockback(std::shared_ptr player) { +Vec3 Explosion::getHitPlayerKnockback(std::shared_ptr player) { AUTO_VAR(it, hitPlayers.find(player)); - if (it == hitPlayers.end()) return Vec3::newTemp(0.0, 0.0, 0.0); + if (it == hitPlayers.end()) return Vec3(0.0, 0.0, 0.0); return it->second; } @@ -298,4 +296,4 @@ std::shared_ptr Explosion::getSourceMob() { if (source->instanceof(eTYPE_LIVINGENTITY)) return std::dynamic_pointer_cast(source); return nullptr; -} \ No newline at end of file +} diff --git a/Minecraft.World/Level/Explosion.h b/Minecraft.World/Level/Explosion.h index 46c67f272..1c250e6b3 100644 --- a/Minecraft.World/Level/Explosion.h +++ b/Minecraft.World/Level/Explosion.h @@ -24,7 +24,7 @@ public: std::unordered_set toBlow; private: - typedef std::unordered_map, Vec3*, PlayerKeyHash, + typedef std::unordered_map, Vec3, PlayerKeyHash, PlayerKeyEq> playerVec3Map; playerVec3Map hitPlayers; @@ -42,6 +42,6 @@ public: std::vector* toBlowDirect = NULL); // 4J - added toBlow parameter playerVec3Map* getHitPlayers(); - Vec3* getHitPlayerKnockback(std::shared_ptr player); + Vec3 getHitPlayerKnockback(std::shared_ptr player); std::shared_ptr getSourceMob(); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Level/Level.cpp b/Minecraft.World/Level/Level.cpp index 5ba25ca56..567eb8e2d 100644 --- a/Minecraft.World/Level/Level.cpp +++ b/Minecraft.World/Level/Level.cpp @@ -38,9 +38,11 @@ #include "../../Minecraft.Client/Platform/Common/DLC/DLCPack.h" #include "../../Minecraft.Client/Platform/Common/ShutdownManager.h" #include "../../Minecraft.Client/MinecraftServer.h" +#include "../../Minecraft.Client/Utils/FrameProfiler.h" #include #include #include +#include // 4J : WESTY : Added for time played stats. #include "../Headers/net.minecraft.stats.h" @@ -1391,7 +1393,7 @@ HitResult* Level::clip(Vec3* a, Vec3* b, bool liquid, bool solidOnly) { int data = getData(xTile0, yTile0, zTile0); Tile* tile = Tile::tiles[t]; if (solidOnly && tile != NULL && - tile->getAABB(this, xTile0, yTile0, zTile0) == NULL) { + !tile->getAABB(this, xTile0, yTile0, zTile0).has_value()) { // No collision } else if (t > 0 && tile->mayPick(data, liquid)) { @@ -1478,28 +1480,28 @@ HitResult* Level::clip(Vec3* a, Vec3* b, bool liquid, bool solidOnly) { a->z = zClip; } - Vec3* tPos = Vec3::newTemp(a->x, a->y, a->z); - xTile0 = (int)(tPos->x = floor(a->x)); + Vec3 tPos(a->x, a->y, a->z); + xTile0 = (int)(tPos.x = floor(a->x)); if (face == 5) { xTile0--; - tPos->x++; + tPos.x++; } - yTile0 = (int)(tPos->y = floor(a->y)); + yTile0 = (int)(tPos.y = floor(a->y)); if (face == 1) { yTile0--; - tPos->y++; + tPos.y++; } - zTile0 = (int)(tPos->z = floor(a->z)); + zTile0 = (int)(tPos.z = floor(a->z)); if (face == 3) { zTile0--; - tPos->z++; + tPos.z++; } int t = getTile(xTile0, yTile0, zTile0); int data = getData(xTile0, yTile0, zTile0); Tile* tile = Tile::tiles[t]; if (solidOnly && tile != NULL && - tile->getAABB(this, xTile0, yTile0, zTile0) == NULL) { + !tile->getAABB(this, xTile0, yTile0, zTile0).has_value()) { // No collision } else if (t > 0 && tile->mayPick(data, liquid)) { @@ -1798,18 +1800,19 @@ AABBList* Level::getCubes(std::shared_ptr source, AABB* box, if (noEntities) return &boxes; double r = 0.25; + AABB grown = box->grow(r, r, r); std::vector >* ee = - getEntities(source, box->grow(r, r, r)); + getEntities(source, &grown); std::vector >::iterator itEnd = ee->end(); for (AUTO_VAR(it, ee->begin()); it != itEnd; it++) { AABB* collideBox = (*it)->getCollideBox(); - if (collideBox != NULL && collideBox->intersects(box)) { - boxes.push_back(collideBox); + if (collideBox != NULL && collideBox->intersects(*box)) { + boxes.push_back(*collideBox); } collideBox = source->getCollideAgainstBox(*it); - if (collideBox != NULL && collideBox->intersects(box)) { - boxes.push_back(collideBox); + if (collideBox != NULL && collideBox->intersects(*box)) { + boxes.push_back(*collideBox); } } @@ -1884,7 +1887,7 @@ float Level::getSkyDarken(float a) { return br * 0.8f + 0.2f; } -Vec3* Level::getSkyColor(std::shared_ptr source, float a) { +Vec3 Level::getSkyColor(std::shared_ptr source, float a) { float td = getTimeOfDay(a); float br = Mth::cos(td * PI * 2) * 2 + 0.5f; @@ -1932,7 +1935,7 @@ Vec3* Level::getSkyColor(std::shared_ptr source, float a) { b = b * (1 - f) + 1 * f; } - return Vec3::newTemp(r, g, b); + return Vec3(r, g, b); } float Level::getTimeOfDay(float a) { @@ -1963,7 +1966,7 @@ float Level::getSunAngle(float a) { return td * PI * 2; } -Vec3* Level::getCloudColor(float a) { +Vec3 Level::getCloudColor(float a) { float td = getTimeOfDay(a); float br = Mth::cos(td * PI * 2) * 2.0f + 0.5f; @@ -2001,10 +2004,10 @@ Vec3* Level::getCloudColor(float a) { b = b * ba + mid * (1 - ba); } - return Vec3::newTemp(r, g, b); + return Vec3(r, g, b); } -Vec3* Level::getFogColor(float a) { +Vec3 Level::getFogColor(float a) { float td = getTimeOfDay(a); return dimension->getFogColor(td, a); } @@ -2204,19 +2207,11 @@ void Level::tickEntities() { // 4J-PB - Stuart - check this is correct here if (!tileEntitiesToUnload.empty()) { - // tileEntityList.removeAll(tileEntitiesToUnload); + FRAME_PROFILE_SCOPE(TileEntityUnloadCleanup); for (AUTO_VAR(it, tileEntityList.begin()); it != tileEntityList.end();) { - bool found = false; - for (AUTO_VAR(it2, tileEntitiesToUnload.begin()); - it2 != tileEntitiesToUnload.end(); it2++) { - if ((*it) == (*it2)) { - found = true; - break; - } - } - if (found) { + if (tileEntitiesToUnload.find(*it) != tileEntitiesToUnload.end()) { if (isClientSide) { __debugbreak(); } @@ -2460,7 +2455,7 @@ bool Level::checkAndHandleWater(AABB* box, Material* material, } bool ok = false; - Vec3* current = Vec3::newTemp(0, 0, 0); + Vec3 current(0, 0, 0); for (int x = x0; x < x1; x++) { for (int y = y0; y < y1; y++) { for (int z = z0; z < z1; z++) { @@ -2470,18 +2465,18 @@ bool Level::checkAndHandleWater(AABB* box, Material* material, y + 1 - LiquidTile::getHeight(getData(x, y, z)); if (y1 >= yt0) { ok = true; - tile->handleEntityInside(this, x, y, z, e, current); + tile->handleEntityInside(this, x, y, z, e, ¤t); } } } } } - if (current->length() > 0 && e->isPushedByWater()) { - current = current->normalize(); + if (current.length() > 0 && e->isPushedByWater()) { + current = current.normalize(); double pow = 0.014; - e->xd += current->x * pow; - e->yd += current->y * pow; - e->zd += current->z * pow; + e->xd += current.x * pow; + e->yd += current.y * pow; + e->zd += current.z * pow; } return ok; } @@ -2567,7 +2562,8 @@ float Level::getSeenPercent(Vec3* center, AABB* bb) { double x = bb->x0 + (bb->x1 - bb->x0) * xx; double y = bb->y0 + (bb->y1 - bb->y0) * yy; double z = bb->z0 + (bb->z1 - bb->z0) * zz; - HitResult* res = clip(Vec3::newTemp(x, y, z), center); + Vec3 a(x, y, z); + HitResult* res = clip(&a, center); if (res == NULL) hits++; delete res; count++; @@ -2715,7 +2711,9 @@ void Level::removeTileEntity(int x, int y, int z) { } void Level::markForRemoval(std::shared_ptr entity) { - tileEntitiesToUnload.push_back(entity); + EnterCriticalSection(&m_tileEntityListCS); + tileEntitiesToUnload.insert(entity); + LeaveCriticalSection(&m_tileEntityListCS); } bool Level::isSolidRenderTile(int x, int y, int z) { @@ -2781,8 +2779,8 @@ bool Level::isFullAABBTile(int x, int y, int z) { if (tile == 0 || Tile::tiles[tile] == NULL) { return false; } - AABB* aabb = Tile::tiles[tile]->getAABB(this, x, y, z); - return aabb != NULL && aabb->getSize() >= 1; + auto aabb = Tile::tiles[tile]->getAABB(this, x, y, z); + return aabb.has_value() && aabb->getSize() >= 1; } bool Level::isTopSolidBlocking(int x, int y, int z) { @@ -3546,9 +3544,9 @@ bool Level::mayPlace(int tileId, int x, int y, int z, bool ignoreEntities, Tile* tile = Tile::tiles[tileId]; - AABB* aabb = tile->getAABB(this, x, y, z); - if (ignoreEntities) aabb = NULL; - if (aabb != NULL && !isUnobstructed(aabb, ignoreEntity)) return false; + auto aabb = tile->getAABB(this, x, y, z); + if (ignoreEntities) aabb = std::nullopt; + if (aabb.has_value() && !isUnobstructed(&*aabb, ignoreEntity)) return false; if (targetTile != NULL && (targetTile == Tile::water || targetTile == Tile::calmWater || targetTile == Tile::lava || targetTile == Tile::calmLava || diff --git a/Minecraft.World/Level/Level.h b/Minecraft.World/Level/Level.h index 49ff45f89..567d9aff4 100644 --- a/Minecraft.World/Level/Level.h +++ b/Minecraft.World/Level/Level.h @@ -10,6 +10,7 @@ #include "../WorldGen/Biomes/Biome.h" #include "../Util/C4JThread.h" #include +#include // 4J Stu - This value should be big enough that we don't get any crashes causes // by memory overwrites, however it does seem way too large for what is actually @@ -114,7 +115,7 @@ public: private: std::vector > pendingTileEntities; - std::vector > tileEntitiesToUnload; + std::unordered_set > tileEntitiesToUnload; bool updatingTileEntities; public: @@ -361,13 +362,13 @@ public: false); // 4J: Added noEntities & blockAtEdge parameters int getOldSkyDarken(float a); // 4J - change brought forward from 1.8.2 float getSkyDarken(float a); // 4J - change brought forward from 1.8.2 - Vec3* getSkyColor(std::shared_ptr source, float a); + Vec3 getSkyColor(std::shared_ptr source, float a); float getTimeOfDay(float a); int getMoonPhase(); float getMoonBrightness(); float getSunAngle(float a); - Vec3* getCloudColor(float a); - Vec3* getFogColor(float a); + Vec3 getCloudColor(float a); + Vec3 getFogColor(float a); int getTopRainBlock(int x, int z); int getTopSolidBlock(int x, int z); bool biomeHasRain(int x, int z); // 4J added @@ -656,3 +657,4 @@ public: bool canCreateMore(eINSTANCEOF type, ESPAWN_TYPE spawnType); }; +#include diff --git a/Minecraft.World/Level/LevelChunk.cpp b/Minecraft.World/Level/LevelChunk.cpp index 2e36fa6bf..ce4fc5acf 100644 --- a/Minecraft.World/Level/LevelChunk.cpp +++ b/Minecraft.World/Level/LevelChunk.cpp @@ -1449,13 +1449,19 @@ void LevelChunk::unload(bool unloadTileEntities) // 4J - added parameter { loaded = false; if (unloadTileEntities) { + std::vector > tileEntitiesToRemove; EnterCriticalSection(&m_csTileEntities); for (AUTO_VAR(it, tileEntities.begin()); it != tileEntities.end(); it++) { - // 4J-PB -m 1.7.3 was it->second->setRemoved(); - level->markForRemoval(it->second); + tileEntitiesToRemove.push_back(it->second); } LeaveCriticalSection(&m_csTileEntities); + + AUTO_VAR(itEnd, tileEntitiesToRemove.end()); + for (AUTO_VAR(it, tileEntitiesToRemove.begin()); it != itEnd; it++) { + // 4J-PB -m 1.7.3 was it->second->setRemoved(); + level->markForRemoval(*it); + } } #if defined(_ENTITIES_RW_SECTION) @@ -1580,7 +1586,7 @@ void LevelChunk::getEntities(std::shared_ptr except, AABB* bb, AUTO_VAR(itEnd, entities->end()); for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) { std::shared_ptr e = *it; // entities->at(i); - if (e != except && e->bb->intersects(bb) && + if (e != except && e->bb.intersects(*bb) && (selector == NULL || selector->matches(e))) { es.push_back(e); std::vector >* subs = @@ -1588,7 +1594,7 @@ void LevelChunk::getEntities(std::shared_ptr except, AABB* bb, if (subs != NULL) { for (int j = 0; j < subs->size(); j++) { e = subs->at(j); - if (e != except && e->bb->intersects(bb) && + if (e != except && e->bb.intersects(*bb) && (selector == NULL || selector->matches(e))) { es.push_back(e); } @@ -1650,7 +1656,7 @@ void LevelChunk::getEntitiesOfClass(const std::type_info& ec, AABB* bb, else if (Entity* entity = e.get(); entity != NULL && ec == typeid(*entity)) isAssignableFrom = true; - if (isAssignableFrom && e->bb->intersects(bb)) { + if (isAssignableFrom && e->bb.intersects(*bb)) { if (selector == NULL || selector->matches(e)) { es.push_back(e); } diff --git a/Minecraft.World/Level/RandomLevelSource.cpp b/Minecraft.World/Level/RandomLevelSource.cpp index 9af8d91b8..d3a9574d7 100644 --- a/Minecraft.World/Level/RandomLevelSource.cpp +++ b/Minecraft.World/Level/RandomLevelSource.cpp @@ -98,32 +98,34 @@ int RandomLevelSource::getMinDistanceToEdge(int xxx, int zzz, int worldSize, // // only check if either x or z values are within the falloff // if(xxx > (min - falloffStart) - Vec3* topLeft = Vec3::newTemp(min, 0, min); - Vec3* topRight = Vec3::newTemp(max, 0, min); - Vec3* bottomLeft = Vec3::newTemp(min, 0, max); - Vec3* bottomRight = Vec3::newTemp(max, 0, max); + Vec3 topLeft(min, 0, min); + Vec3 topRight(max, 0, min); + Vec3 bottomLeft(min, 0, max); + Vec3 bottomRight(max, 0, max); float closest = falloffStart; float dist; // make sure we're in range of the edges before we do a full distance check if ((xxx > (min - falloffStart) && xxx < (min + falloffStart)) || (xxx > (max - falloffStart) && xxx < (max + falloffStart))) { - Vec3* point = Vec3::newTemp(xxx, 0, zzz); + Vec3 point(xxx, 0, zzz); + if (xxx > 0) - dist = point->distanceFromLine(topRight, bottomRight); + dist = point.distanceFromLine(topRight, bottomRight); else - dist = point->distanceFromLine(topLeft, bottomLeft); + dist = point.distanceFromLine(topLeft, bottomLeft); closest = dist; } // make sure we're in range of the edges before we do a full distance check if ((zzz > (min - falloffStart) && zzz < (min + falloffStart)) || (zzz > (max - falloffStart) && zzz < (max + falloffStart))) { - Vec3* point = Vec3::newTemp(xxx, 0, zzz); + Vec3 point(xxx, 0, zzz); + if (zzz > 0) - dist = point->distanceFromLine(bottomLeft, bottomRight); + dist = point.distanceFromLine(bottomLeft, bottomRight); else - dist = point->distanceFromLine(topLeft, topRight); + dist = point.distanceFromLine(topLeft, topRight); if (dist < closest) closest = dist; } diff --git a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp index 3426803b6..c8ddae142 100644 --- a/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp +++ b/Minecraft.World/Level/Storage/McRegionChunkStorage.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "../../Platform/stdafx.h" #include "../../Headers/net.minecraft.world.level.h" #include "../../IO/Files/ConsoleSaveFileIO.h" @@ -380,9 +383,10 @@ int McRegionChunkStorage::runSaveThreadProc(void* lpParam) { // If there was more than one thing in the queue last time we checked, // then we want to spin round again soon Otherwise wait a bit longer if ((lastQueueSize - 1) > 0) - Sleep(1); // Sleep 1 to yield + std::this_thread::sleep_for( + std::chrono::milliseconds(1)); // Sleep 1 to yield else - Sleep(100); + std::this_thread::sleep_for(std::chrono::milliseconds(100)); } Compression::ReleaseThreadStorage(); @@ -402,7 +406,7 @@ void McRegionChunkStorage::WaitForAllSaves() { LeaveCriticalSection(&cs_memory); while (queueSize > 0) { - Sleep(10); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); EnterCriticalSection(&cs_memory); queueSize = s_chunkDataQueue.size(); @@ -416,7 +420,7 @@ void McRegionChunkStorage::WaitForAllSaves() { LeaveCriticalSection(&cs_memory); while (runningThreadCount > 0) { - Sleep(10); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); EnterCriticalSection(&cs_memory); runningThreadCount = s_runningThreadCount; @@ -436,7 +440,7 @@ void McRegionChunkStorage::WaitForSaves() { if (queueSize > MAX_QUEUE_SIZE) { while (queueSize > DESIRED_QUEUE_SIZE) { - Sleep(10); + std::this_thread::sleep_for(std::chrono::milliseconds(10)); EnterCriticalSection(&cs_memory); queueSize = s_chunkDataQueue.size(); diff --git a/Minecraft.World/Network/Connection.cpp b/Minecraft.World/Network/Connection.cpp index 8d807f9fd..709c53e2f 100644 --- a/Minecraft.World/Network/Connection.cpp +++ b/Minecraft.World/Network/Connection.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "../Platform/stdafx.h" #include "../IO/Streams/InputOutputStream.h" #include "Socket.h" @@ -552,7 +555,7 @@ int Connection::runRead(void* lpParam) { while (con->readTick()); // try { - // Sleep(100L); + // std::this_thread::sleep_for(std::chrono::milliseconds(100L)); // TODO - 4J Stu - 1.8.2 changes these sleeps to 2L, but not sure // whether we should do that as well con->m_hWakeReadThread->WaitForSignal(100L); @@ -601,7 +604,7 @@ int Connection::runWrite(void* lpParam) { ShutdownManager::ShouldRun(ShutdownManager::eConnectionWriteThreads)) { while (con->writeTick()); - // Sleep(100L); + // std::this_thread::sleep_for(std::chrono::milliseconds(100L)); // TODO - 4J Stu - 1.8.2 changes these sleeps to 2L, but not sure // whether we should do that as well waitResult = con->m_hWakeWriteThread->WaitForSignal(100L); diff --git a/Minecraft.World/Network/Socket.cpp b/Minecraft.World/Network/Socket.cpp index 750c14543..cc10e4882 100644 --- a/Minecraft.World/Network/Socket.cpp +++ b/Minecraft.World/Network/Socket.cpp @@ -1,3 +1,6 @@ +#include +#include + #include "../Platform/stdafx.h" #include "../IO/Streams/InputOutputStream.h" #include "SocketAddress.h" @@ -250,7 +253,7 @@ int Socket::SocketInputStreamLocal::read() { } LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); } - Sleep(1); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } return -1; } @@ -277,7 +280,7 @@ int Socket::SocketInputStreamLocal::read(byteArray b, unsigned int offset, } LeaveCriticalSection(&s_hostQueueLock[m_queueIdx]); } - Sleep(1); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } return -1; } @@ -356,7 +359,7 @@ int Socket::SocketInputStreamNetwork::read() { } LeaveCriticalSection(&m_socket->m_queueLockNetwork[m_queueIdx]); } - Sleep(1); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } return -1; } @@ -385,7 +388,7 @@ int Socket::SocketInputStreamNetwork::read(byteArray b, unsigned int offset, } LeaveCriticalSection(&m_socket->m_queueLockNetwork[m_queueIdx]); } - Sleep(1); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); } return -1; } diff --git a/Minecraft.World/Platform/PathHelper.h b/Minecraft.World/Platform/PathHelper.h new file mode 100644 index 000000000..e02b755cd --- /dev/null +++ b/Minecraft.World/Platform/PathHelper.h @@ -0,0 +1,37 @@ +#pragma once +#include +#if defined(__linux__) +#include +#include +#endif + +namespace PathHelper { +inline std::wstring GetExecutableDirW() { +#if defined(__linux__) + char buffer[4096]; + ssize_t len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1); + if (len != -1) { + buffer[len] = '\0'; + std::string path(buffer); + size_t lastSlash = path.find_last_of('/'); + if (lastSlash != std::string::npos) + return std::wstring(path.begin(), path.begin() + lastSlash); + } +#endif + return L"."; +} + +inline std::string GetExecutableDirA() { +#if defined(__linux__) + char buffer[4096]; + ssize_t len = readlink("/proc/self/exe", buffer, sizeof(buffer) - 1); + if (len != -1) { + buffer[len] = '\0'; + std::string path(buffer); + size_t lastSlash = path.find_last_of('/'); + if (lastSlash != std::string::npos) return path.substr(0, lastSlash); + } +#endif + return "."; +} +} // namespace PathHelper \ No newline at end of file diff --git a/Minecraft.World/Player/Player.cpp b/Minecraft.World/Player/Player.cpp index 94578c4ea..131db939e 100644 --- a/Minecraft.World/Player/Player.cpp +++ b/Minecraft.World/Player/Player.cpp @@ -422,20 +422,20 @@ void Player::spawnEatParticles(std::shared_ptr useItem, } if (useItem->getUseAnimation() == UseAnim_eat) { for (int i = 0; i < count; i++) { - Vec3* d = Vec3::newTemp((random->nextFloat() - 0.5) * 0.1, - Math::random() * 0.1 + 0.1, 0); + Vec3 d{(random->nextFloat() - 0.5) * 0.1, + Math::random() * 0.1 + 0.1, 0}; - d->xRot(-xRot * PI / 180); - d->yRot(-yRot * PI / 180); + d.xRot(-xRot * PI / 180); + d.yRot(-yRot * PI / 180); - Vec3* p = Vec3::newTemp((random->nextFloat() - 0.5) * 0.3, - -random->nextFloat() * 0.6 - 0.3, 0.6); - p->xRot(-xRot * PI / 180); - p->yRot(-yRot * PI / 180); - p = p->add(x, y + getHeadHeight(), z); + Vec3 p{(random->nextFloat() - 0.5) * 0.3, + -random->nextFloat() * 0.6 - 0.3, 0.6}; + p.xRot(-xRot * PI / 180); + p.yRot(-yRot * PI / 180); + p = p.add(x, y + getHeadHeight(), z); level->addParticle(PARTICLE_ICONCRACK(useItem->getItem()->id, 0), - p->x, p->y, p->z, d->x, d->y + 0.05, d->z); + p.x, p.y, p.z, d.x, d.y + 0.05, d.z); } // 4J Stu - Was L"mob.eat" which doesnt exist @@ -849,17 +849,17 @@ void Player::aiStep() { tilt += (tTilt - tilt) * 0.8f; if (getHealth() > 0) { - AABB* pickupArea = NULL; + AABB pickupArea; if (riding != NULL && !riding->removed) { // if the player is riding, also touch entities under the // pig/horse - pickupArea = bb->minmax(riding->bb)->grow(1, 0, 1); + pickupArea = bb.minmax(riding->bb).grow(1, 0, 1); } else { - pickupArea = bb->grow(1, .5, 1); + pickupArea = bb.grow(1, .5, 1); } std::vector >* entities = - level->getEntities(shared_from_this(), pickupArea); + level->getEntities(shared_from_this(), &pickupArea); if (entities != NULL) { AUTO_VAR(itEnd, entities->end()); for (AUTO_VAR(it, entities->begin()); it != itEnd; it++) { @@ -1484,11 +1484,10 @@ Player::BedSleepingResult Player::startSleepInBed(int x, int y, int z, double hRange = 8; double vRange = 5; + AABB monster_bb = + AABB(x, y, z, x, y, z).grow(hRange, vRange, hRange); std::vector >* monsters = - level->getEntitiesOfClass( - typeid(Monster), - AABB::newTemp(x - hRange, y - vRange, z - hRange, - x + hRange, y + vRange, z + hRange)); + level->getEntitiesOfClass(typeid(Monster), &monster_bb); if (!monsters->empty()) { delete monsters; return NOT_SAFE; diff --git a/Minecraft.World/Util/AABB.cpp b/Minecraft.World/Util/AABB.cpp index c4a8bff2e..c9a58d1bb 100644 --- a/Minecraft.World/Util/AABB.cpp +++ b/Minecraft.World/Util/AABB.cpp @@ -3,58 +3,14 @@ // import java->util.ArrayList; // import java->util.List; +// TODO: use brace initialization everywhere + #include "../Platform/stdafx.h" #include "AABB.h" +#include +#include #include "HitResult.h" - -unsigned int AABB::tlsIdx = 0; -AABB::ThreadStorage* AABB::tlsDefault = NULL; - -AABB::ThreadStorage::ThreadStorage() { - pool = new AABB[POOL_SIZE]; // 4jcraft, needs to be deleted with delete[] - poolPointer = 0; -} - -AABB::ThreadStorage::~ThreadStorage() { - delete[] pool; // 4jcraft, changed to [] -} - -void AABB::CreateNewThreadStorage() { - ThreadStorage* tls = new ThreadStorage(); - if (tlsDefault == NULL) { - tlsIdx = TlsAlloc(); - tlsDefault = tls; - } - - TlsSetValue(tlsIdx, tls); -} - -void AABB::UseDefaultThreadStorage() { TlsSetValue(tlsIdx, tlsDefault); } - -void AABB::ReleaseThreadStorage() { - ThreadStorage* tls = (ThreadStorage*)TlsGetValue(tlsIdx); - if (tls == tlsDefault) return; - - delete tls; -} - -AABB* AABB::newPermanent(double x0, double y0, double z0, double x1, double y1, - double z1) { - return new AABB(x0, y0, z0, x1, y1, z1); -} - -void AABB::clearPool() {} - -void AABB::resetPool() {} - -AABB* AABB::newTemp(double x0, double y0, double z0, double x1, double y1, - double z1) { - ThreadStorage* tls = (ThreadStorage*)TlsGetValue(tlsIdx); - AABB* thisAABB = &tls->pool[tls->poolPointer]; - thisAABB->set(x0, y0, z0, x1, y1, z1); - tls->poolPointer = (tls->poolPointer + 1) % ThreadStorage::POOL_SIZE; - return thisAABB; -} +#include "Util/Vec3.h" AABB::AABB(double x0, double y0, double z0, double x1, double y1, double z1) { this->x0 = x0; @@ -65,18 +21,7 @@ AABB::AABB(double x0, double y0, double z0, double x1, double y1, double z1) { this->z1 = z1; } -AABB* AABB::set(double x0, double y0, double z0, double x1, double y1, - double z1) { - this->x0 = x0; - this->y0 = y0; - this->z0 = z0; - this->x1 = x1; - this->y1 = y1; - this->z1 = z1; - return this; -} - -AABB* AABB::expand(double xa, double ya, double za) { +AABB AABB::expand(double xa, double ya, double za) const { double _x0 = x0; double _y0 = y0; double _z0 = z0; @@ -93,10 +38,10 @@ AABB* AABB::expand(double xa, double ya, double za) { if (za < 0) _z0 += za; if (za > 0) _z1 += za; - return AABB::newTemp(_x0, _y0, _z0, _x1, _y1, _z1); + return {_x0, _y0, _z0, _x1, _y1, _z1}; } -AABB* AABB::grow(double xa, double ya, double za) { +AABB AABB::grow(const double xa, const double ya, const double za) const { double _x0 = x0 - xa; double _y0 = y0 - ya; double _z0 = z0 - za; @@ -104,127 +49,121 @@ AABB* AABB::grow(double xa, double ya, double za) { double _y1 = y1 + ya; double _z1 = z1 + za; - return AABB::newTemp(_x0, _y0, _z0, _x1, _y1, _z1); + return {_x0, _y0, _z0, _x1, _y1, _z1}; } -AABB* AABB::minmax(AABB* other) { - double _x0 = std::min(x0, other->x0); - double _y0 = std::min(y0, other->y0); - double _z0 = std::min(z0, other->z0); - double _x1 = std::max(x1, other->x1); - double _y1 = std::max(y1, other->y1); - double _z1 = std::max(z1, other->z1); +AABB AABB::minmax(const AABB& other) const { + double _x0 = std::min(x0, other.x0); + double _y0 = std::min(y0, other.y0); + double _z0 = std::min(z0, other.z0); + double _x1 = std::max(x1, other.x1); + double _y1 = std::max(y1, other.y1); + double _z1 = std::max(z1, other.z1); - return newTemp(_x0, _y0, _z0, _x1, _y1, _z1); + return {_x0, _y0, _z0, _x1, _y1, _z1}; } -AABB* AABB::cloneMove(double xa, double ya, double za) { - return AABB::newTemp(x0 + xa, y0 + ya, z0 + za, x1 + xa, y1 + ya, z1 + za); -} +double AABB::clipXCollide(const AABB& c, double xa) const { + if (c.y1 <= y0 || c.y0 >= y1) return xa; + if (c.z1 <= z0 || c.z0 >= z1) return xa; -double AABB::clipXCollide(AABB* c, double xa) { - if (c->y1 <= y0 || c->y0 >= y1) return xa; - if (c->z1 <= z0 || c->z0 >= z1) return xa; - - if (xa > 0 && c->x1 <= x0) { - double max = x0 - c->x1; + if (xa > 0 && c.x1 <= x0) { + double max = x0 - c.x1; if (max < xa) xa = max; } - if (xa < 0 && c->x0 >= x1) { - double max = x1 - c->x0; + + if (xa < 0 && c.x0 >= x1) { + double max = x1 - c.x0; if (max > xa) xa = max; } return xa; } -double AABB::clipYCollide(AABB* c, double ya) { - if (c->x1 <= x0 || c->x0 >= x1) return ya; - if (c->z1 <= z0 || c->z0 >= z1) return ya; +double AABB::clipYCollide(const AABB& c, double ya) const { + if (c.x1 <= x0 || c.x0 >= x1) return ya; + if (c.z1 <= z0 || c.z0 >= z1) return ya; - if (ya > 0 && c->y1 <= y0) { - double max = y0 - c->y1; + if (ya > 0 && c.y1 <= y0) { + double max = y0 - c.y1; if (max < ya) ya = max; } - if (ya < 0 && c->y0 >= y1) { - double max = y1 - c->y0; + + if (ya < 0 && c.y0 >= y1) { + double max = y1 - c.y0; if (max > ya) ya = max; } return ya; } -double AABB::clipZCollide(AABB* c, double za) { - if (c->x1 <= x0 || c->x0 >= x1) return za; - if (c->y1 <= y0 || c->y0 >= y1) return za; +double AABB::clipZCollide(const AABB& c, double za) const { + if (c.x1 <= x0 || c.x0 >= x1) return za; + if (c.y1 <= y0 || c.y0 >= y1) return za; - if (za > 0 && c->z1 <= z0) { - double max = z0 - c->z1; + if (za > 0 && c.z1 <= z0) { + double max = z0 - c.z1; if (max < za) za = max; } - if (za < 0 && c->z0 >= z1) { - double max = z1 - c->z0; + + if (za < 0 && c.z0 >= z1) { + double max = z1 - c.z0; if (max > za) za = max; } return za; } -bool AABB::intersects(AABB* c) { - if (c->x1 <= x0 || c->x0 >= x1) return false; - if (c->y1 <= y0 || c->y0 >= y1) return false; - if (c->z1 <= z0 || c->z0 >= z1) return false; +bool AABB::intersects(const AABB& c) const { + if (c.x1 <= x0 || c.x0 >= x1) return false; + if (c.y1 <= y0 || c.y0 >= y1) return false; + if (c.z1 <= z0 || c.z0 >= z1) return false; return true; } -bool AABB::intersectsInner(AABB* c) { - if (c->x1 < x0 || c->x0 > x1) return false; - if (c->y1 < y0 || c->y0 > y1) return false; - if (c->z1 < z0 || c->z0 > z1) return false; - return true; +AABB AABB::move(const double xa, const double ya, const double za) const { + return { + x0 + xa, y0 + ya, z0 + za, + + x1 + xa, y1 + ya, z1 + za, + }; } -AABB* AABB::move(double xa, double ya, double za) { - x0 += xa; - y0 += ya; - z0 += za; - x1 += xa; - y1 += ya; - z1 += za; - return this; -} - -bool AABB::intersects(double x02, double y02, double z02, double x12, - double y12, double z12) { +bool AABB::intersects(const double x02, const double y02, const double z02, + const double x12, const double y12, + const double z12) const { if (x12 <= x0 || x02 >= x1) return false; if (y12 <= y0 || y02 >= y1) return false; if (z12 <= z0 || z02 >= z1) return false; + return true; } -bool AABB::contains(Vec3* p) { - if (p->x <= x0 || p->x >= x1) return false; - if (p->y <= y0 || p->y >= y1) return false; - if (p->z <= z0 || p->z >= z1) return false; +bool AABB::contains(const Vec3& p) const { + if (p.x <= x0 || p.x >= x1) return false; + if (p.y <= y0 || p.y >= y1) return false; + if (p.z <= z0 || p.z >= z1) return false; + return true; } // 4J Added -bool AABB::containsIncludingLowerBound(Vec3* p) { - if (p->x < x0 || p->x >= x1) return false; - if (p->y < y0 || p->y >= y1) return false; - if (p->z < z0 || p->z >= z1) return false; +bool AABB::containsIncludingLowerBound(const Vec3& p) const { + if (p.x < x0 || p.x >= x1) return false; + if (p.y < y0 || p.y >= y1) return false; + if (p.z < z0 || p.z >= z1) return false; return true; } -double AABB::getSize() { - double xs = x1 - x0; - double ys = y1 - y0; - double zs = z1 - z0; +double AABB::getSize() const { + const double xs = x1 - x0; + const double ys = y1 - y0; + const double zs = z1 - z0; + return (xs + ys + zs) / 3.0f; } -AABB* AABB::shrink(double xa, double ya, double za) { +AABB AABB::shrink(const double xa, const double ya, const double za) const { double _x0 = x0 + xa; double _y0 = y0 + ya; double _z0 = z0 + za; @@ -232,50 +171,53 @@ AABB* AABB::shrink(double xa, double ya, double za) { double _y1 = y1 - ya; double _z1 = z1 - za; - return AABB::newTemp(_x0, _y0, _z0, _x1, _y1, _z1); + return {_x0, _y0, _z0, _x1, _y1, _z1}; } -AABB* AABB::copy() { return AABB::newTemp(x0, y0, z0, x1, y1, z1); } +HitResult* AABB::clip(const Vec3& a, const Vec3& b) const { + auto xh0 = a.clipX(b, x0); + auto xh1 = a.clipX(b, x1); -HitResult* AABB::clip(Vec3* a, Vec3* b) { - Vec3* xh0 = a->clipX(b, x0); - Vec3* xh1 = a->clipX(b, x1); + auto yh0 = a.clipY(b, y0); + auto yh1 = a.clipY(b, y1); - Vec3* yh0 = a->clipY(b, y0); - Vec3* yh1 = a->clipY(b, y1); + auto zh0 = a.clipZ(b, z0); + auto zh1 = a.clipZ(b, z1); - Vec3* zh0 = a->clipZ(b, z0); - Vec3* zh1 = a->clipZ(b, z1); + if (!containsX(xh0)) xh0 = std::nullopt; + if (!containsX(xh1)) xh1 = std::nullopt; + if (!containsY(yh0)) yh0 = std::nullopt; + if (!containsY(yh1)) yh1 = std::nullopt; + if (!containsZ(zh0)) zh0 = std::nullopt; + if (!containsZ(zh1)) zh1 = std::nullopt; - if (!containsX(xh0)) xh0 = NULL; - if (!containsX(xh1)) xh1 = NULL; - if (!containsY(yh0)) yh0 = NULL; - if (!containsY(yh1)) yh1 = NULL; - if (!containsZ(zh0)) zh0 = NULL; - if (!containsZ(zh1)) zh1 = NULL; + std::optional closest = std::nullopt; - Vec3* closest = NULL; - - if (xh0 != NULL && - (closest == NULL || a->distanceToSqr(xh0) < a->distanceToSqr(closest))) + if (xh0.has_value() && (!closest.has_value() || + a.distanceToSqr(*xh0) < a.distanceToSqr(*closest))) closest = xh0; - if (xh1 != NULL && - (closest == NULL || a->distanceToSqr(xh1) < a->distanceToSqr(closest))) + + if (xh1.has_value() && (!closest.has_value() || + a.distanceToSqr(*xh1) < a.distanceToSqr(*closest))) closest = xh1; - if (yh0 != NULL && - (closest == NULL || a->distanceToSqr(yh0) < a->distanceToSqr(closest))) + + if (yh0.has_value() && (!closest.has_value() || + a.distanceToSqr(*yh0) < a.distanceToSqr(*closest))) closest = yh0; - if (yh1 != NULL && - (closest == NULL || a->distanceToSqr(yh1) < a->distanceToSqr(closest))) + + if (yh1.has_value() && (!closest.has_value() || + a.distanceToSqr(*yh1) < a.distanceToSqr(*closest))) closest = yh1; - if (zh0 != NULL && - (closest == NULL || a->distanceToSqr(zh0) < a->distanceToSqr(closest))) + + if (zh0.has_value() && (!closest.has_value() || + a.distanceToSqr(*zh0) < a.distanceToSqr(*closest))) closest = zh0; - if (zh1 != NULL && - (closest == NULL || a->distanceToSqr(zh1) < a->distanceToSqr(closest))) + + if (zh1.has_value() && (!closest.has_value() || + a.distanceToSqr(*zh1) < a.distanceToSqr(*closest))) closest = zh1; - if (closest == NULL) return NULL; + if (!closest.has_value()) return nullptr; int face = -1; @@ -286,35 +228,24 @@ HitResult* AABB::clip(Vec3* a, Vec3* b) { if (closest == zh0) face = 2; if (closest == zh1) face = 3; - return new HitResult(0, 0, 0, face, closest); + return new HitResult(0, 0, 0, face, *closest); } -bool AABB::containsX(Vec3* v) { - if (v == NULL) return false; +bool AABB::containsX(const std::optional& v) const { + if (!v.has_value()) return false; return v->y >= y0 && v->y <= y1 && v->z >= z0 && v->z <= z1; } -bool AABB::containsY(Vec3* v) { - if (v == NULL) return false; +bool AABB::containsY(const std::optional& v) const { + if (!v.has_value()) return false; return v->x >= x0 && v->x <= x1 && v->z >= z0 && v->z <= z1; } -bool AABB::containsZ(Vec3* v) { - if (v == NULL) return false; +bool AABB::containsZ(const std::optional& v) const { + if (!v.has_value()) return false; return v->x >= x0 && v->x <= x1 && v->y >= y0 && v->y <= y1; } -void AABB::set(AABB* b) { - x0 = b->x0; - y0 = b->y0; - z0 = b->z0; - x1 = b->x1; - y1 = b->y1; - z1 = b->z1; -} - -std::wstring AABB::toString() { - return L"box[" + _toString(x0) + L", " + _toString(y0) + - L", " + _toString(z0) + L" -> " + _toString(x1) + - L", " + _toString(y1) + L", " + _toString(z1) + L"]"; +std::wstring AABB::toString() const { + return std::format(L"box[{}, {}, {}, {}, {}, {}]", x0, y0, z0, x1, y1, z1); } diff --git a/Minecraft.World/Util/AABB.h b/Minecraft.World/Util/AABB.h index bcd941f39..83c32519a 100644 --- a/Minecraft.World/Util/AABB.h +++ b/Minecraft.World/Util/AABB.h @@ -6,63 +6,30 @@ class HitResult; class AABB { - // 4J added so we can have separate pools for different threads - class ThreadStorage { - public: - static const int POOL_SIZE = 1024; - AABB* pool; - unsigned int poolPointer; - ThreadStorage(); - ~ThreadStorage(); - }; - static unsigned int tlsIdx; - static ThreadStorage* tlsDefault; - public: - // Each new thread that needs to use Vec3 pools will need to call one of the - // following 2 functions, to either create its own local storage, or share - // the default storage already allocated by the main thread - static void CreateNewThreadStorage(); - static void UseDefaultThreadStorage(); - static void ReleaseThreadStorage(); - - static AABB* newPermanent(double x0, double y0, double z0, double x1, - double y1, double z1); - static void clearPool(); - static void resetPool(); - static AABB* newTemp(double x0, double y0, double z0, double x1, double y1, - double z1); - double x0, y0, z0; double x1, y1, z1; -private: - AABB(double x0, double y0, double z0, double x1, double y1, double z1); AABB() {} + AABB(double x0, double y0, double z0, double x1, double y1, double z1); -public: - AABB* set(double x0, double y0, double z0, double x1, double y1, double z1); - AABB* expand(double xa, double ya, double za); - AABB* grow(double xa, double ya, double za); - AABB* minmax(AABB* other); - AABB* cloneMove(double xa, double ya, double za); - double clipXCollide(AABB* c, double xa); - double clipYCollide(AABB* c, double ya); - double clipZCollide(AABB* c, double za); - bool intersects(AABB* c); - bool intersectsInner(AABB* c); - AABB* move(double xa, double ya, double za); + AABB expand(double xa, double ya, double za) const; + AABB grow(double xa, double ya, double za) const; + AABB minmax(const AABB& other) const; + double clipXCollide(const AABB& c, double xa) const; + double clipYCollide(const AABB& c, double ya) const; + double clipZCollide(const AABB& c, double za) const; + bool intersects(const AABB& c) const; + AABB move(double xa, double ya, double za) const; bool intersects(double x02, double y02, double z02, double x12, double y12, - double z12); - bool contains(Vec3* p); - bool containsIncludingLowerBound(Vec3* p); // 4J Added - double getSize(); - AABB* shrink(double xa, double ya, double za); - AABB* copy(); - HitResult* clip(Vec3* a, Vec3* b); - bool containsX(Vec3* v); - bool containsY(Vec3* v); - bool containsZ(Vec3* v); - void set(AABB* b); - std::wstring toString(); + double z12) const; + bool contains(const Vec3& p) const; + bool containsIncludingLowerBound(const Vec3& p) const; // 4J Added + double getSize() const; + AABB shrink(double xa, double ya, double za) const; + HitResult* clip(const Vec3& a, const Vec3& b) const; + bool containsX(const std::optional& v) const; + bool containsY(const std::optional& v) const; + bool containsZ(const std::optional& v) const; + std::wstring toString() const; }; diff --git a/Minecraft.World/Util/ArrayWithLength.h b/Minecraft.World/Util/ArrayWithLength.h index d433329f1..c476a372f 100644 --- a/Minecraft.World/Util/ArrayWithLength.h +++ b/Minecraft.World/Util/ArrayWithLength.h @@ -114,8 +114,6 @@ typedef arrayWithLength TileArray; typedef arrayWithLength StatArray; typedef arrayWithLength MobCategoryArray; typedef arrayWithLength FileArray; -typedef arrayWithLength VertexArray; -typedef arrayWithLength<_Polygon*> PolygonArray; typedef arrayWithLength ServerLevelArray; typedef arrayWithLength MultiPlayerLevelArray; typedef arrayWithLength LevelArray; diff --git a/Minecraft.World/Util/CombatTracker.cpp b/Minecraft.World/Util/CombatTracker.cpp index 0dbc0a2d3..80b0a3072 100644 --- a/Minecraft.World/Util/CombatTracker.cpp +++ b/Minecraft.World/Util/CombatTracker.cpp @@ -19,7 +19,7 @@ void CombatTracker::prepareForDamage() { if (mob->onLadder()) { int type = mob->level->getTile( - Mth::floor(mob->x), Mth::floor(mob->bb->y0), Mth::floor(mob->z)); + Mth::floor(mob->x), Mth::floor(mob->bb.y0), Mth::floor(mob->z)); if (type == Tile::ladder->id) { nextLocation = eLocation_LADDER; diff --git a/Minecraft.World/Util/Definitions.h b/Minecraft.World/Util/Definitions.h index ecc05e73f..c21df2527 100644 --- a/Minecraft.World/Util/Definitions.h +++ b/Minecraft.World/Util/Definitions.h @@ -4,7 +4,7 @@ class AABB; class Recipy; class Object; -typedef std::vector AABBList; +typedef std::vector AABBList; typedef std::vector RecipyList; typedef std::vector ObjectList; @@ -30,4 +30,4 @@ enum EDefaultSkins { eDefaultSkins_Skin7, eDefaultSkins_Count, -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Util/HitResult.cpp b/Minecraft.World/Util/HitResult.cpp index dfa52bf72..e6f49dbac 100644 --- a/Minecraft.World/Util/HitResult.cpp +++ b/Minecraft.World/Util/HitResult.cpp @@ -3,13 +3,13 @@ #include "../Headers/net.minecraft.world.entity.h" #include "HitResult.h" -HitResult::HitResult(int x, int y, int z, int f, Vec3* pos) { +HitResult::HitResult(int x, int y, int z, int f, const Vec3& pos) { type = TILE; this->x = x; this->y = y; this->z = z; this->f = f; - this->pos = Vec3::newTemp(pos->x, pos->y, pos->z); + this->pos = pos; this->entity = nullptr; } @@ -17,14 +17,14 @@ HitResult::HitResult(int x, int y, int z, int f, Vec3* pos) { HitResult::HitResult(std::shared_ptr entity) { type = ENTITY; this->entity = entity; - pos = Vec3::newTemp(entity->x, entity->y, entity->z); + pos = {entity->x, entity->y, entity->z}; x = y = z = f = 0; } double HitResult::distanceTo(std::shared_ptr e) { - double xd = pos->x - e->x; - double yd = pos->y - e->y; - double zd = pos->z - e->z; + double xd = pos.x - e->x; + double yd = pos.y - e->y; + double zd = pos.z - e->z; return xd * xd + yd * yd + zd * zd; -} \ No newline at end of file +} diff --git a/Minecraft.World/Util/HitResult.h b/Minecraft.World/Util/HitResult.h index ee4121d52..83934fc6f 100644 --- a/Minecraft.World/Util/HitResult.h +++ b/Minecraft.World/Util/HitResult.h @@ -7,12 +7,12 @@ public: Type type; int x, y, z, f; - Vec3* pos; + Vec3 pos; std::shared_ptr entity; - HitResult(int x, int y, int z, int f, Vec3* pos); + HitResult(int x, int y, int z, int f, const Vec3& pos); HitResult(std::shared_ptr entity); double distanceTo(std::shared_ptr e); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/Util/Vec3.cpp b/Minecraft.World/Util/Vec3.cpp index 4e42b99a3..8119ae772 100644 --- a/Minecraft.World/Util/Vec3.cpp +++ b/Minecraft.World/Util/Vec3.cpp @@ -1,169 +1,103 @@ -#include "../Platform/stdafx.h" #include "Vec3.h" + +#include +#include + #include "AABB.h" -unsigned int Vec3::tlsIdx = 0; -Vec3::ThreadStorage* Vec3::tlsDefault = NULL; +Vec3 Vec3::vectorTo(const Vec3& p) const { return {p.x - x, p.y - y, p.z - z}; } -Vec3::ThreadStorage::ThreadStorage() { - pool = new Vec3[POOL_SIZE]; - poolPointer = 0; +Vec3 Vec3::normalize() const { + double dist = std::sqrt(x * x + y * y + z * z); + if (dist < 0.0001) return {0, 0, 0}; + + return {x / dist, y / dist, z / dist}; } -Vec3::ThreadStorage::~ThreadStorage() { delete[] pool; } +double Vec3::dot(const Vec3& p) const { return x * p.x + y * p.y + z * p.z; } -void Vec3::CreateNewThreadStorage() { - ThreadStorage* tls = new ThreadStorage(); - if (tlsDefault == NULL) { - tlsIdx = TlsAlloc(); - tlsDefault = tls; - } - TlsSetValue(tlsIdx, tls); +Vec3 Vec3::cross(const Vec3& p) const { + return {y * p.z - z * p.y, z * p.x - x * p.z, x * p.y - y * p.x}; } -void Vec3::UseDefaultThreadStorage() { TlsSetValue(tlsIdx, tlsDefault); } - -void Vec3::ReleaseThreadStorage() { - ThreadStorage* tls = (ThreadStorage*)TlsGetValue(tlsIdx); - if (tls == tlsDefault) return; - - delete tls; +Vec3 Vec3::add(double x, double y, double z) const { + return {this->x + x, this->y + y, this->z + z}; } -Vec3* Vec3::newPermanent(double x, double y, double z) { - return new Vec3(x, y, z); -}; - -void Vec3::clearPool() {} - -void Vec3::resetPool() {} - -Vec3* Vec3::newTemp(double x, double y, double z) { - ThreadStorage* tls = (ThreadStorage*)TlsGetValue(tlsIdx); - Vec3* thisVec = &tls->pool[tls->poolPointer]; - thisVec->set(x, y, z); - tls->poolPointer = (tls->poolPointer + 1) % ThreadStorage::POOL_SIZE; - return thisVec; +double Vec3::distanceTo(const Vec3& p) const { + double xd = p.x - x; + double yd = p.y - y; + double zd = p.z - z; + return std::sqrt(xd * xd + yd * yd + zd * zd); } -Vec3::Vec3(double x, double y, double z) { - if (x == -0.0) x = 0.0; - if (y == -0.0) y = 0.0; - if (z == -0.0) z = 0.0; - this->x = x; - this->y = y; - this->z = z; -} - -Vec3* Vec3::set(double x, double y, double z) { - this->x = x; - this->y = y; - this->z = z; - return this; -} - -Vec3* Vec3::interpolateTo(Vec3* t, double p) { - double xt = x + (t->x - x) * p; - double yt = y + (t->y - y) * p; - double zt = z + (t->z - z) * p; - - return Vec3::newTemp(xt, yt, zt); -} - -Vec3* Vec3::vectorTo(Vec3* p) { - return Vec3::newTemp(p->x - x, p->y - y, p->z - z); -} - -Vec3* Vec3::normalize() { - double dist = (double)(sqrt(x * x + y * y + z * z)); - if (dist < 0.0001) return Vec3::newTemp(0, 0, 0); - return Vec3::newTemp(x / dist, y / dist, z / dist); -} - -double Vec3::dot(Vec3* p) { return x * p->x + y * p->y + z * p->z; } - -Vec3* Vec3::cross(Vec3* p) { - return Vec3::newTemp(y * p->z - z * p->y, z * p->x - x * p->z, - x * p->y - y * p->x); -} - -Vec3* Vec3::add(double x, double y, double z) { - return Vec3::newTemp(this->x + x, this->y + y, this->z + z); -} - -double Vec3::distanceTo(Vec3* p) { - double xd = p->x - x; - double yd = p->y - y; - double zd = p->z - z; - return (double)sqrt(xd * xd + yd * yd + zd * zd); -} - -double Vec3::distanceToSqr(Vec3* p) { - double xd = p->x - x; - double yd = p->y - y; - double zd = p->z - z; +double Vec3::distanceToSqr(const Vec3& p) const { + double xd = p.x - x; + double yd = p.y - y; + double zd = p.z - z; return xd * xd + yd * yd + zd * zd; } -double Vec3::distanceToSqr(double x2, double y2, double z2) { +double Vec3::distanceToSqr(const double x2, const double y2, + const double z2) const { double xd = x2 - x; double yd = y2 - y; double zd = z2 - z; return xd * xd + yd * yd + zd * zd; } -Vec3* Vec3::scale(double l) { return Vec3::newTemp(x * l, y * l, z * l); } +Vec3 Vec3::scale(const double l) const { return {x * l, y * l, z * l}; } -double Vec3::length() { return sqrt(x * x + y * y + z * z); } +double Vec3::length() const { return sqrt(x * x + y * y + z * z); } -Vec3* Vec3::clipX(Vec3* b, double xt) { - double xd = b->x - x; - double yd = b->y - y; - double zd = b->z - z; +std::optional Vec3::clipX(const Vec3& b, const double xt) const { + double xd = b.x - x; + double yd = b.y - y; + double zd = b.z - z; - if (xd * xd < 0.0000001f) return NULL; + if (xd * xd < 0.0000001f) return std::nullopt; double d = (xt - x) / xd; - if (d < 0 || d > 1) return NULL; - return Vec3::newTemp(x + xd * d, y + yd * d, z + zd * d); + if (d < 0 || d > 1) return std::nullopt; + + return Vec3{x + xd * d, y + yd * d, z + zd * d}; } -Vec3* Vec3::clipY(Vec3* b, double yt) { - double xd = b->x - x; - double yd = b->y - y; - double zd = b->z - z; +std::optional Vec3::clipY(const Vec3& b, const double yt) const { + double xd = b.x - x; + double yd = b.y - y; + double zd = b.z - z; - if (yd * yd < 0.0000001f) return NULL; + if (yd * yd < 0.0000001f) return std::nullopt; double d = (yt - y) / yd; - if (d < 0 || d > 1) return NULL; - return Vec3::newTemp(x + xd * d, y + yd * d, z + zd * d); + if (d < 0 || d > 1) return std::nullopt; + + return Vec3{x + xd * d, y + yd * d, z + zd * d}; } -Vec3* Vec3::clipZ(Vec3* b, double zt) { - double xd = b->x - x; - double yd = b->y - y; - double zd = b->z - z; +std::optional Vec3::clipZ(const Vec3& b, const double zt) const { + double xd = b.x - x; + double yd = b.y - y; + double zd = b.z - z; - if (zd * zd < 0.0000001f) return NULL; + if (zd * zd < 0.0000001f) return std::nullopt; double d = (zt - z) / zd; - if (d < 0 || d > 1) return NULL; - return Vec3::newTemp(x + xd * d, y + yd * d, z + zd * d); + if (d < 0 || d > 1) return std::nullopt; + + return Vec3{x + xd * d, y + yd * d, z + zd * d}; } -std::wstring Vec3::toString() { - static wchar_t buf[128]; - swprintf(buf, 128, L"(%f,%f,%f)", x, y, z); - return std::wstring(buf); +std::wstring Vec3::toString() const { + return std::format(L"({},{},{})", x, y, z); } -Vec3* Vec3::lerp(Vec3* v, double a) { - return Vec3::newTemp(x + (v->x - x) * a, y + (v->y - y) * a, - z + (v->z - z) * a); +Vec3 Vec3::lerp(const Vec3& v, const double a) const { + return {x + (v.x - x) * a, y + (v.y - y) * a, z + (v.z - z) * a}; } -void Vec3::xRot(float degs) { +void Vec3::xRot(const float degs) { double _cos = cos(degs); // 4J - cos/sin were floats but seems pointless // wasting precision here double _sin = sin(degs); @@ -177,7 +111,7 @@ void Vec3::xRot(float degs) { z = zz; } -void Vec3::yRot(float degs) { +void Vec3::yRot(const float degs) { double _cos = cos(degs); // 4J - cos/sin were floats but seems pointless // wasting precision here double _sin = sin(degs); @@ -191,7 +125,7 @@ void Vec3::yRot(float degs) { z = zz; } -void Vec3::zRot(float degs) { +void Vec3::zRot(const float degs) { double _cos = cos(degs); // 4J - cos/sin were floats but seems pointless // wasting precision here double _sin = sin(degs); @@ -207,8 +141,9 @@ void Vec3::zRot(float degs) { // Returns 0 if this point is within the box // Otherwise returns the distance to the box +// TODO: rewrite this function double Vec3::distanceTo(AABB* box) { - if (box->contains(this)) return 0; + if (box->contains(*this)) return 0; double xd = 0, yd = 0, zd = 0; @@ -230,23 +165,24 @@ double Vec3::distanceTo(AABB* box) { return sqrt(xd * xd + yd * yd + zd * zd); } -Vec3* Vec3::closestPointOnLine(Vec3* p1, Vec3* p2) { - Vec3* diff = newTemp(x - p1->x, y - p1->y, z - p1->z); - Vec3* dir = newTemp(p2->x - p1->x, p2->y - p1->y, p2->z - p1->z); - float dot1 = diff->dot(dir); +Vec3 Vec3::closestPointOnLine(const Vec3& p1, const Vec3& p2) const { + Vec3 diff = {x - p1.x, y - p1.y, z - p1.z}; + Vec3 dir = {p2.x - p1.x, p2.y - p1.y, p2.z - p1.z}; + float dot1 = diff.dot(dir); + if (dot1 <= 0.0f) return p1; - float dot2 = dir->dot(dir); + float dot2 = dir.dot(dir); if (dot2 <= dot1) return p2; float t = dot1 / dot2; - return newTemp(p1->x + t * dir->x, p1->y + t * dir->y, p1->z + t * dir->z); + + return {p1.x + t * dir.x, p1.y + t * dir.y, p1.z + t * dir.z}; } -double Vec3::distanceFromLine(Vec3* p1, Vec3* p2) { - Vec3* closestPoint = closestPointOnLine(p1, p2); - Vec3* diff = - newTemp(x - closestPoint->x, y - closestPoint->y, z - closestPoint->z); - return diff->length(); +double Vec3::distanceFromLine(const Vec3& p1, const Vec3& p2) const { + Vec3 closestPoint = closestPointOnLine(p1, p2); + Vec3 diff{x - closestPoint.x, y - closestPoint.y, z - closestPoint.z}; + return diff.length(); } diff --git a/Minecraft.World/Util/Vec3.h b/Minecraft.World/Util/Vec3.h index bc1239d81..a45cbebec 100644 --- a/Minecraft.World/Util/Vec3.h +++ b/Minecraft.World/Util/Vec3.h @@ -1,56 +1,33 @@ #pragma once +#include +#include + class AABB; class Vec3 { - // 4J added so we can have separate pools for different threads - class ThreadStorage { - public: - static const int POOL_SIZE = 1024; - Vec3* pool; - unsigned int poolPointer; - ThreadStorage(); - ~ThreadStorage(); - }; - static unsigned int tlsIdx; - static ThreadStorage* tlsDefault; - public: - // Each new thread that needs to use Vec3 pools will need to call one of the - // following 2 functions, to either create its own local storage, or share - // the default storage already allocated by the main thread - static void CreateNewThreadStorage(); - static void UseDefaultThreadStorage(); - static void ReleaseThreadStorage(); - - static Vec3* newPermanent(double x, double y, double z); - static void clearPool(); - static void resetPool(); - static Vec3* newTemp(double x, double y, double z); double x, y, z; -private: - Vec3() {} - Vec3(double x, double y, double z); - Vec3* set(double x, double y, double z); + constexpr Vec3() = default; + constexpr Vec3(const double x, const double y, const double z) + : x(x), y(y), z(z) {} -public: - Vec3* interpolateTo(Vec3* t, double p); - Vec3* vectorTo(Vec3* p); - Vec3* normalize(); - double dot(Vec3* p); - Vec3* cross(Vec3* p); - Vec3* add(double x, double y, double z); - double distanceTo(Vec3* p); - double distanceToSqr(Vec3* p); - double distanceToSqr(double x2, double y2, double z2); - Vec3* scale(double l); - double length(); - Vec3* clipX(Vec3* b, double xt); - Vec3* clipY(Vec3* b, double yt); - Vec3* clipZ(Vec3* b, double zt); - std::wstring toString(); - Vec3* lerp(Vec3* v, double a); + Vec3 vectorTo(const Vec3& p) const; + Vec3 normalize() const; + double dot(const Vec3& p) const; + Vec3 cross(const Vec3& p) const; + Vec3 add(double x, double y, double z) const; + double distanceTo(const Vec3& p) const; + double distanceToSqr(const Vec3& p) const; + double distanceToSqr(double x2, double y2, double z2) const; + Vec3 scale(double l) const; + double length() const; + std::optional clipX(const Vec3& b, double xt) const; + std::optional clipY(const Vec3& b, double yt) const; + std::optional clipZ(const Vec3& b, double zt) const; + std::wstring toString() const; + Vec3 lerp(const Vec3& v, double a) const; void xRot(float degs); void yRot(float degs); void zRot(float degs); @@ -58,6 +35,10 @@ public: // 4J Added double distanceTo(AABB* box); - Vec3* closestPointOnLine(Vec3* p1, Vec3* p2); - double distanceFromLine(Vec3* p1, Vec3* p2); -}; \ No newline at end of file + Vec3 closestPointOnLine(const Vec3& p1, const Vec3& p2) const; + double distanceFromLine(const Vec3& p1, const Vec3& p2) const; + + constexpr bool operator==(const Vec3& rhs) const { + return x == rhs.x and y == rhs.y and z == rhs.z; + } +}; diff --git a/Minecraft.World/WorldGen/Structures/StructureStart.cpp b/Minecraft.World/WorldGen/Structures/StructureStart.cpp index 9bcb12777..d378e9c33 100644 --- a/Minecraft.World/WorldGen/Structures/StructureStart.cpp +++ b/Minecraft.World/WorldGen/Structures/StructureStart.cpp @@ -138,4 +138,4 @@ bool StructureStart::isValid() { return true; } int StructureStart::getChunkX() { return chunkX; } -int StructureStart::getChunkZ() { return chunkZ; } \ No newline at end of file +int StructureStart::getChunkZ() { return chunkZ; } diff --git a/Minecraft.World/WorldGen/Structures/Village.cpp b/Minecraft.World/WorldGen/Structures/Village.cpp index 07e505908..03a079387 100644 --- a/Minecraft.World/WorldGen/Structures/Village.cpp +++ b/Minecraft.World/WorldGen/Structures/Village.cpp @@ -7,6 +7,7 @@ #include "../../Headers/net.minecraft.world.phys.h" #include "Village.h" #include +#include Village::Aggressor::Aggressor(std::shared_ptr mob, int timeStamp) { @@ -60,9 +61,9 @@ void Village::tick(int tick) { int idealGolemCount = populationSize / 10; if (golemCount < idealGolemCount && doorInfos.size() > 20 && level->random->nextInt(7000) == 0) { - Vec3* spawnPos = + auto spawnPos = findRandomSpawnPos(center->x, center->y, center->z, 2, 4, 2); - if (spawnPos != NULL) { + if (spawnPos.has_value()) { std::shared_ptr vg = std::shared_ptr(new VillagerGolem(level)); vg->setPos(spawnPos->x, spawnPos->y, spawnPos->z); @@ -88,16 +89,17 @@ void Village::tick(int tick) { // } } -Vec3* Village::findRandomSpawnPos(int x, int y, int z, int sx, int sy, int sz) { +std::optional Village::findRandomSpawnPos(int x, int y, int z, int sx, + int sy, int sz) { for (int i = 0; i < 10; ++i) { int xx = x + level->random->nextInt(16) - 8; int yy = y + level->random->nextInt(6) - 3; int zz = z + level->random->nextInt(16) - 8; if (!isInside(xx, yy, zz)) continue; - if (canSpawnAt(xx, yy, zz, sx, sy, sz)) - return Vec3::newTemp(xx, yy, zz); + if (canSpawnAt(xx, yy, zz, sx, sy, sz)) return Vec3(xx, yy, zz); } - return NULL; + + return std::nullopt; } bool Village::canSpawnAt(int x, int y, int z, int sx, int sy, int sz) { @@ -115,21 +117,22 @@ bool Village::canSpawnAt(int x, int y, int z, int sx, int sy, int sz) { void Village::countGolem() { // Fix - let bots report themselves? + AABB village_golem_bb = + AABB(center->x, center->y, center->z, center->x, center->y, center->z) + .grow(radius, 4, radius); std::vector >* golems = level->getEntitiesOfClass( typeid(VillagerGolem), - AABB::newTemp(center->x - radius, center->y - 4, center->z - radius, - center->x + radius, center->y + 4, center->z + radius)); + &village_golem_bb); golemCount = golems->size(); delete golems; } void Village::countPopulation() { + AABB villager_bb = AABB(center->x, center->y, center->z, center->x, center->y, center->z).grow(radius, 4, radius); std::vector >* villagers = level->getEntitiesOfClass( typeid(Villager), - AABB::newTemp(center->x - radius, center->y - 4, center->z - radius, - center->x + radius, center->y + 4, - center->z + radius)); + &villager_bb); populationSize = villagers->size(); delete villagers; diff --git a/Minecraft.World/WorldGen/Structures/Village.h b/Minecraft.World/WorldGen/Structures/Village.h index fb35335f7..b63f3e8e9 100644 --- a/Minecraft.World/WorldGen/Structures/Village.h +++ b/Minecraft.World/WorldGen/Structures/Village.h @@ -1,5 +1,6 @@ #pragma once +#include class Village { private: Level* level; @@ -36,7 +37,7 @@ public: void tick(int tick); private: - Vec3* findRandomSpawnPos(int x, int y, int z, int sx, int sy, int sz); + std::optional findRandomSpawnPos(int x, int y, int z, int sx, int sy, int sz); bool canSpawnAt(int x, int y, int z, int sx, int sy, int sz); void countGolem(); void countPopulation(); @@ -78,4 +79,4 @@ public: void resetNoBreedTimer(); bool isBreedTimerOk(); void rewardAllPlayers(int amount); -}; \ No newline at end of file +}; diff --git a/Minecraft.World/WorldGen/Structures/Villages.h b/Minecraft.World/WorldGen/Structures/Villages.h index 9ab55837f..9c8cd5590 100644 --- a/Minecraft.World/WorldGen/Structures/Villages.h +++ b/Minecraft.World/WorldGen/Structures/Villages.h @@ -44,4 +44,4 @@ private: public: void load(CompoundTag* tag); void save(CompoundTag* tag); -}; \ No newline at end of file +}; diff --git a/flake.lock b/flake.lock index 0f6e9ef3b..f2128808e 100644 --- a/flake.lock +++ b/flake.lock @@ -3,11 +3,11 @@ "4jlibs": { "flake": false, "locked": { - "lastModified": 1774012501, - "narHash": "sha256-NoM5LtKcU+3LFPVZUtep1L+hfZS6YSQ4P/xkJU/2NY4=", + "lastModified": 1774836469, + "narHash": "sha256-ukp6tLThQugPlREYFDDB6IaunjGte08f0Ler/c8cvaY=", "owner": "4jcraft", "repo": "4jlibs", - "rev": "df5f4a1fc3288fdc021b3d8ee2abaed3083de460", + "rev": "ab37891dabba90cf1e568660f750cebf46ba83f6", "type": "github" }, "original": { @@ -17,6 +17,24 @@ "type": "github" } }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, "miniaudio": { "flake": false, "locked": { @@ -44,15 +62,15 @@ }, "nixpkgs": { "locked": { - "lastModified": 1774106199, - "narHash": "sha256-US5Tda2sKmjrg2lNHQL3jRQ6p96cgfWh3J1QBliQ8Ws=", - "owner": "nixos", + "lastModified": 1774386573, + "narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=", + "owner": "NixOS", "repo": "nixpkgs", - "rev": "6c9a78c09ff4d6c21d0319114873508a6ec01655", + "rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9", "type": "github" }, "original": { - "owner": "nixos", + "owner": "NixOS", "ref": "nixos-unstable", "repo": "nixpkgs", "type": "github" @@ -61,6 +79,7 @@ "root": { "inputs": { "4jlibs": "4jlibs", + "flake-utils": "flake-utils", "miniaudio": "miniaudio", "miniaudio-patch": "miniaudio-patch", "nixpkgs": "nixpkgs", @@ -118,6 +137,21 @@ "repo": "stb", "type": "github" } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index 04fa60509..05ceb4fef 100644 --- a/flake.nix +++ b/flake.nix @@ -1,121 +1,147 @@ { - description = "4jcraft-nix package and dev shell"; + description = "4jcraft nix-package and dev-shell"; inputs = { - nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable"; + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; shiggy = { - url = "github:4jcraft/shiggy/main"; - flake = false; - }; - miniaudio = { - url = "https://github.com/mackron/miniaudio/archive/refs/tags/0.11.22.tar.gz"; - flake = false; - }; - miniaudio-patch = { - url = "https://wrapdb.mesonbuild.com/v2/miniaudio_0.11.22-2/get_patch"; + url = "github:4jcraft/shiggy/main"; flake = false; }; + "4jlibs" = { - url = "github:4jcraft/4jlibs/main"; + url = "github:4jcraft/4jlibs/main"; flake = false; }; + + miniaudio = { + url = "https://github.com/mackron/miniaudio/archive/refs/tags/0.11.22.tar.gz"; + flake = false; + }; + + miniaudio-patch = { + url = "https://wrapdb.mesonbuild.com/v2/miniaudio_0.11.22-2/get_patch"; + flake = false; + }; + stb = { - url = "github:nothings/stb/master"; + url = "github:nothings/stb/master"; flake = false; }; + simdutf = { - url = "github:simdutf/simdutf"; + url = "github:simdutf/simdutf"; flake = false; }; }; - outputs = { self, nixpkgs, ... } @ inputs: - let - allSystems = [ - "x86_64-linux" - "aarch64-linux" - "x86_64-darwin" - "aarch64-darwin" - ]; - forAllSystems = f: nixpkgs.lib.genAttrs allSystems (system: f { - pkgs = import nixpkgs { inherit system; }; - }); - in - { - packages = forAllSystems ({ pkgs }: { - default = pkgs.clangStdenv.mkDerivation { - pname = "4jcraft"; - version = "0.1.0"; - src = ./.; + outputs = + { + self, + nixpkgs, + flake-utils, + ... + }@inputs: + flake-utils.lib.eachDefaultSystem ( + system: + let + pkgs = import nixpkgs { inherit system; }; + in + { + packages.default = pkgs.clangStdenv.mkDerivation { + pname = "4jcraft"; + version = "0.1.0"; + src = ./.; - dontUseCmakeConfigure = true; + dontFixup = true; + dontUseCmakeConfigure = true; - preConfigure = '' - # shiggy - cp -r ${inputs.shiggy} subprojects/shiggy + # 4jcraft - Meson expects this subprojects structure + postUnpack = '' + mkdir -p $sourceRoot/subprojects - # miniaudio - cp -r ${inputs.miniaudio} subprojects/miniaudio - chmod -R u+w subprojects/miniaudio - unzip ${inputs."miniaudio-patch"} -d /tmp/miniaudio-patch/ - cp -r /tmp/miniaudio-patch/*/. subprojects/miniaudio/ - cat > subprojects/miniaudio.wrap <<'EOF' - [wrap-file] - directory = miniaudio + cp -r ${inputs.shiggy} $sourceRoot/subprojects/shiggy + cp -r ${inputs."4jlibs"} $sourceRoot/subprojects/4jlibs + cp -r ${inputs.stb} $sourceRoot/subprojects/stb + cp -r ${inputs.simdutf} $sourceRoot/subprojects/simdutf + cp -r ${inputs.miniaudio} $sourceRoot/subprojects/miniaudio - [provide] - dependency_names = miniaudio - EOF + chmod -R u+w $sourceRoot/subprojects + ''; - # 4jlibs - cp -r ${inputs."4jlibs"} subprojects/4jlibs + # 4jcraft - `stb` and `simdutf` patches + postPatch = '' + cp subprojects/packagefiles/stb/meson.build subprojects/stb/meson.build + cp subprojects/packagefiles/simdutf/meson.build subprojects/simdutf/meson.build + cp subprojects/packagefiles/simdutf/meson.options subprojects/simdutf/meson.options - # stb - cp -r ${inputs.stb} subprojects/stb - chmod -R u+w subprojects/ - cp subprojects/packagefiles/stb/meson.build subprojects/stb/meson.build + unzip ${inputs.miniaudio-patch} -d miniaudio-patch-tmp + cp -r miniaudio-patch-tmp/*/. subprojects/miniaudio/ - # simdutf - cp -r ${inputs.simdutf} subprojects/simdutf - chmod -R u+w subprojects/simdutf - cp subprojects/packagefiles/simdutf/meson.build subprojects/simdutf/meson.build - cp subprojects/packagefiles/simdutf/meson.options subprojects/simdutf/meson.options - ''; + cat > subprojects/miniaudio.wrap <= 1.7', - default_options : [ + default_options: [ 'cpp_std=c++23', 'warning_level=0', 'buildtype=debug', # for now @@ -16,22 +18,8 @@ python = pymod.find_installation('python3', required: true) cc = meson.get_compiler('cpp') -# system deps -gl_dep = dependency('gl') -glu_dep = dependency('glu') -sdl2_dep = dependency('sdl2') # Yes.. i know sdl3 is out, but there's not point upgrading right now except when - # someone is gonna ask me "Hey juicey can you make it SDL3?" and i'd be like fuck you and still do it. -thread_dep = dependency('threads') -miniaudio_dep = dependency('miniaudio') -stb = subproject('stb').get_variable('stb_inc') -# compile flags (chagne ts juicey) -global_cpp_args = [ - '-fpermissive', - '-Wshift-count-overflow', - '-pipe', # use pipes instead of temp files between compiler stages -] +use_gles = get_option('renderer') == 'gles' -# global ccp defs type shi global_cpp_defs = [ '-DSPLIT_SAVES', '-D_LARGE_WORLDS', @@ -42,18 +30,61 @@ global_cpp_defs = [ ] if host_machine.system() == 'linux' - global_cpp_defs += [ - '-Dlinux', - '-D__linux', - '-D__linux__', - ] + global_cpp_defs += ['-Dlinux', '-D__linux', '-D__linux__'] endif -render_dep = dependency('4j-render', fallback: ['4jlibs', 'render_dep']) -input_dep = dependency('4j-input', fallback: ['4jlibs', 'input_dep']) -profile_dep = dependency('4j-profile', fallback: ['4jlibs', 'profile_dep']) -storage_dep = dependency('4j-storage', fallback: ['4jlibs', 'storage_dep']) +if use_gles + global_cpp_defs += ['-DGLES'] +endif + +add_project_arguments(global_cpp_defs, language: ['cpp', 'c']) + +global_cpp_args = [ + '-fpermissive', + '-Wshift-count-overflow', + '-pipe', +] +add_project_arguments(global_cpp_args, language: 'cpp') + +sdl2_dep = dependency('sdl2') +thread_dep = dependency('threads') +dl_dep = cc.find_library('dl', required: true) + +# GLES vs Desktop GL +if use_gles + gl_dep = dependency('glesv2', required: true) + glu_dep = dependency('', required: false) +else + gl_dep = dependency('gl', required: true) + glu_dep = dependency('glu', required: true) +endif + +stb = subproject('stb').get_variable('stb_inc') +stb_dep = declare_dependency(include_directories: stb) + +miniaudio_dep = dependency('miniaudio') + +sub_opts = ['gles=' + use_gles.to_string()] + +render_dep = dependency('4j-render', fallback: ['4jlibs', 'render_dep'], default_options: sub_opts) +input_dep = dependency('4j-input', fallback: ['4jlibs', 'input_dep'], default_options: sub_opts) +profile_dep = dependency('4j-profile', fallback: ['4jlibs', 'profile_dep'], default_options: sub_opts) +storage_dep = dependency('4j-storage', fallback: ['4jlibs', 'storage_dep'], default_options: sub_opts) + +all_deps = [ + gl_dep, + glu_dep, + sdl2_dep, + thread_dep, + dl_dep, + stb_dep, + miniaudio_dep, + render_dep, + input_dep, + profile_dep, + storage_dep, +] subdir('Minecraft.Assets') subdir('Minecraft.World') -subdir('Minecraft.Client') +subdir('Minecraft.Client') \ No newline at end of file diff --git a/meson.options b/meson.options index 74de97f98..4dc73f322 100644 --- a/meson.options +++ b/meson.options @@ -1,14 +1,42 @@ -option('enable_java_guis', +option( + 'ui_backend', + type: 'combo', + choices: ['shiggy', 'java'], + value: 'shiggy', + description: 'Specifies a backend implementation for the game UI.', +) + +option('classic_panorama', type : 'boolean', value : false, - description : 'Re-enable the Java UI remnants in the code (for testing only)') + description : 'Enable classic java edition panorama (ui_backend=java ONLY).') -option('enable_vsync', - type : 'boolean', - value : true, - description : 'Toggles V-Sync and adds options to unlock maximum in-game framerate.') +option( + 'renderer', + type: 'combo', + choices: ['gl3', 'gles'], + value: 'gl3', + description: 'Specifies a rendering implementation for the game.', +) -option('enable_shiggy', - type : 'boolean', - value : true, - description : 'Toggles shimmed PS4 Iggy binaries and UI for x86_64 Linux.') +option( + 'enable_vsync', + type: 'boolean', + value: true, + description: 'Toggles V-Sync and adds options to unlock maximum in-game framerate.', +) + +option( + 'enable_frame_profiler', + type: 'boolean', + value: false, + description: 'Enable the in-engine frame profiler for render hotspot discovery.', +) + +option( + 'occlusion_culling', + type: 'combo', + choices: ['off', 'frustum', 'bfs', 'hardware'], + value: 'frustum', + description: 'Occlusion culling mode. Off disables ALL CULLING (debug only!), Frustum disables offscreen rendering (default), BFS is experimental connectivity culling, hardware uses GPU queries.', +) diff --git a/subprojects/4jlibs.wrap b/subprojects/4jlibs.wrap index e9e21334c..ab584a950 100644 --- a/subprojects/4jlibs.wrap +++ b/subprojects/4jlibs.wrap @@ -1,6 +1,6 @@ [wrap-git] url = https://github.com/4jcraft/4jlibs.git -revision = main +revision = immediategone-v2 [provide] dependency_names = 4j-render, 4j-input, 4j-profile, 4j-storage