/******************************************************************** Minecraft: Pocket Edition - Decompilation Project Copyright (C) 2023 iProgramInCpp The following code is licensed under the BSD 1 clause license. SPDX-License-Identifier: BSD-1-Clause ********************************************************************/ #include "UnifiedTurnBuild.hpp" #include "Multitouch.hpp" #include "common/Utils.hpp" #include "world/entity/Player.hpp" UnifiedTurnBuild::UnifiedTurnBuild(int a, int width, int height, float d, float e, IInputHolder* pHolder) : field_C(a), field_10(0), m_screenArea(-1, -1, 0, 0), field_40(-1, -1, 0, 0), field_58(-1, -1, 0, 0), m_pInputHolder(pHolder), field_78(0.0f), field_7C(0.0f), m_bWasTouched(false), field_BC(0.0f), field_C0(d), field_C4(e), m_pPlayer(nullptr), field_D8(0) { m_includeExcludeArea.field_4 = false; UnifiedTurnBuild::setScreenSize(width, height); field_B8 = getTimeS(); field_CC = field_B8; field_D0 = 0; field_24 = 0; field_D4 = false; } void UnifiedTurnBuild::setScreenSize(int width, int height) { m_screenArea = RectangleArea(0.0f, 0.0f, float(width), float(height)); field_40.right += 10.0f + 0.05f * (field_40.right - field_40.left); field_40.top -= 10.0f + 0.05f * (field_40.bottom - field_40.top); m_includeExcludeArea.clear(); m_includeExcludeArea.include(&m_screenArea); m_includeExcludeArea.exclude(&field_40); m_includeExcludeArea.exclude(&field_58); m_touchAreaModel.clear(); m_touchAreaModel.addArea(100, &m_includeExcludeArea); } TurnDelta UnifiedTurnBuild::getTurnDelta() { float timeS = getTimeS(); float m1 = 0.0f, m2 = 0.0f; float xd = 0.0f, yd = 0.0f; bool touched = false; const int* activePtrs; int activePtrCount = Multitouch::getActivePointerIds(&activePtrs); for (int i = 0; i < activePtrCount; i++) { int finger = activePtrs[i]; int x = Multitouch::getX(finger); int y = Multitouch::getY(finger); if (m_touchAreaModel.getPointerId(x, y, finger) == 100) { touched = true; m1 = float(x) * 0.5f; m2 = float(y) * -0.5f; break; } } if (touched && !m_bWasTouched) // if this is the first frame we were touched { field_B8 = timeS; field_BC = 0.0f; bool b2 = m_pPlayer && getSpeedSquared(m_pPlayer) > 0.01f; field_D8 = 1; field_D4 = !b2; field_24 = 0; } else if (m_bWasTouched && !touched) // if that was the last frame we were touched { field_24 = 0; field_D8 = 0; } if (field_C == 2 && (m_bWasTouched || touched)) { // note: return value dropped (void) getDeltaTime(); if (!m_bWasTouched) { field_78 = m1; field_7C = m2; } if (touched) { xd = field_C4 * linearTransform(m1 - field_78, 0.0f, 1.0f, false); yd = field_C4 * linearTransform(m2 - field_7C, 0.0f, 1.0f, false); float c3 = abs(xd) * abs(yd); if (field_C0 < c3) c3 = yd = xd = 0.0f; field_BC += c3; if (field_D8 == 1 && field_BC >= 20.0f) field_D8 = 2; if (field_D8 == 1 && timeS - field_B8 >= 0.4f) { bool check = m_pPlayer && getSpeedSquared(m_pPlayer) > 0.01f; if (field_BC > 20.0f || check) field_D8 = 2; else field_D8 = 3; } if (field_D8 == 1) { xd = yd = 0.0f; } field_78 = m1; field_7C = m2; } } if (field_D4) { // Yes, again, this is what IDA gave me. It was either a switch that the compiler // for some reason forgot to optimize into a jump table, or was actually an if chain. // I believe it's the latter though because the build I'm reversing (0.1.1j) is unoptimized) if (field_D8 == 1) m_pInputHolder->m_feedbackAlpha = m_smoothFloat.getNewDeltaValue((timeS - field_B8) / 0.4f, 0.05f); else if (field_D8 == 3) m_pInputHolder->m_feedbackAlpha = m_smoothFloat.getNewDeltaValue(1.0f, 0.25f); else if (field_D8 == 2) m_pInputHolder->m_feedbackAlpha = m_smoothFloat.getNewDeltaValue(-0.05f, 0.5f); else if (field_D8 == 0) m_pInputHolder->m_feedbackAlpha = m_smoothFloat.getNewDeltaValue(-0.05f, 0.5f); } else { m_pInputHolder->m_feedbackAlpha = -0.05f; } m_bWasTouched = touched; return TurnDelta(xd, -yd); } bool UnifiedTurnBuild::smoothTurning() { return true; } bool UnifiedTurnBuild::tickBuild(Player* pPlayer, BuildActionIntention* pIntention) { m_pPlayer = pPlayer; if (field_D8 == 3) { if (field_24 != 1) { *pIntention = BuildActionIntention(INTENT_FIRST_REMOVE); field_24 = 1; } else { *pIntention = BuildActionIntention(INTENT_HELD); } return true; } Multitouch::rewind(); float timeS = getTimeS(); field_10 = 0; bool wroteIntention = false; while (Multitouch::next()) { MouseAction* pEvent = Multitouch::getEvent(); if (pEvent->_buttonType) { int finger = m_touchAreaModel.getPointerId(pEvent->_posX, pEvent->_posY, pEvent->_fingerId); if (finger == 100) { if (field_BC > 20.0f || pEvent->_buttonState || wroteIntention) { if (pEvent->_buttonState) { field_CC = timeS; field_D0 = 0; field_D8 = 1; } } else { float delta = timeS - field_CC; if (field_D8 <= 1 && delta >= 0.0f && delta < 0.25f) { *pIntention = BuildActionIntention(INTENT_CLICKED); wroteIntention = true; } field_D8 = 0; } } } } return wroteIntention; } bool UnifiedTurnBuild::isInsideArea(float x, float y) { return m_includeExcludeArea.isInside(x, y); } float UnifiedTurnBuild::getSpeedSquared(Entity* pEnt) { return (pEnt->m_pos - pEnt->field_3C).lengthSqr(); }