mirror of
https://github.com/celisej567/mcpe.git
synced 2026-09-11 20:11:18 +03:00
* Visual Studio Project Overhaul + Cleanup * SDL2 project for Windows * Re-added game client icon to SDL2 code * Renamed "AppPlatform_windows" to "AppPlatform_win32" (this is the name of the Windows API and is not representative of the architecture type) * Renamed "LoggerWindows" to "LoggerWin32" * Renamed "SoundSystemWindows to "SoundSystemDS" (DirectSound). This may be used for the 360, so it wouldn't really be Windows-specific then. * Moved "ClientSideNetworkHandler" from "network" to "client/network". We don't need it being compiled for the server if the client's the only thing that needs it. * I wonder if this still works on macOS... * Bugfixes & Fixed for macOS * Options::savePropertiesToFile Logging Bugfix * Silence Winsock Deprecation Warnings in RakNet * VS Project Improvements - Replaced 50 billion relative paths with $(MC_ROOT) - Added $(RAKNET_PATH) variable to override RakNet location - Re-added gitignore for .vcxproj.user files - Added debugging config to Directory.Builds.props - Slimmed down project configurations for SDL2 * VS Project Config Bugfixes - Fixed RakNet header path for additional includes * RakNet Target for XCode * XCode Project Config Fixes * Packet logging * Network VS Project Filter Fix * Fix RakNet Packet ID Length We previously didn't have consistency between old and new C++ regarding PacketType enum length. Now we do. This is required or else it completely breaks networking between the versions. * Additional RakNet Error Handling * Disable packet logging * * Fix CMakeLists.txt This reflects the relocation of ClientSideNetworkHandler.cpp. * * Also add renderer/GL/GL.cpp to the CMakeLists.txt * * Replace libpng with stb_image * * Fix buggy water behavior. * * Put the CMakeLists of the SDL project in debug mode * Visual Studio 2010 Support * * Change the SdlIoCallbacks from an array to a single member. This fixes compilation of the sdl2 target on VS. * * Fix missing _error label. * Revert "* Fix missing _error label." This reverts commit 99a057fc84049a16c864bd840fb439a008af5c74. * Revert "* Replace libpng with stb_image" * info_updateGame Tiles --------- Co-authored-by: Brent Da Mage <BrentDaMage@users.noreply.github.com> Co-authored-by: iProgramInCpp <iprogramincpp@gmail.com>
385 lines
8.3 KiB
C++
385 lines
8.3 KiB
C++
/********************************************************************
|
|
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
|
|
********************************************************************/
|
|
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <shlobj.h>
|
|
|
|
#include "AppPlatform_win32.hpp"
|
|
#include "LoggerWin32.hpp"
|
|
|
|
#include "thirdparty/GL/GL.hpp"
|
|
|
|
#include "thirdparty/stb_image.h"
|
|
#include "thirdparty/stb_image_write.h"
|
|
|
|
AppPlatform_win32::AppPlatform_win32()
|
|
{
|
|
m_WindowTitle = "ReMinecraftPE";
|
|
// just assume an 854x480 window for now:
|
|
m_ScreenWidth = C_DEFAULT_SCREEN_WIDTH;
|
|
m_ScreenHeight = C_DEFAULT_SCREEN_HEIGHT;
|
|
m_UserInputStatus = -1;
|
|
|
|
m_bIsFocused = false;
|
|
m_bGrabbedMouse = false;
|
|
m_bActuallyGrabbedMouse = false;
|
|
m_bWasUnfocused = false;
|
|
m_bShiftPressed = false;
|
|
|
|
m_MouseDiffX = 0, m_MouseDiffY = 0;
|
|
|
|
// This initializes the Logger singleton to use the Windows-specific variant
|
|
// If we didn't initialize it here, the Minecraft class would have our back
|
|
m_pLogger = new LoggerWin32();
|
|
m_pSoundSystem = nullptr;
|
|
}
|
|
|
|
AppPlatform_win32::~AppPlatform_win32()
|
|
{
|
|
SAFE_DELETE(m_pSoundSystem);
|
|
|
|
// DELETE THIS LAST
|
|
SAFE_DELETE(m_pLogger);
|
|
}
|
|
|
|
void AppPlatform_win32::initSoundSystem()
|
|
{
|
|
if (!m_pSoundSystem)
|
|
m_pSoundSystem = new SoundSystemDS();
|
|
else
|
|
LOG_E("Trying to initialize SoundSystem more than once!");
|
|
}
|
|
|
|
int AppPlatform_win32::checkLicense()
|
|
{
|
|
// we own the game!!
|
|
return 1;
|
|
}
|
|
|
|
void AppPlatform_win32::buyGame()
|
|
{
|
|
MessageBoxA(GetHWND(), "Buying the game!", getWindowTitle(), MB_OK | MB_ICONINFORMATION);
|
|
}
|
|
|
|
void AppPlatform_win32::saveScreenshot(const std::string& fileName, int width, int height)
|
|
{
|
|
int npixels = width * height;
|
|
uint32_t* pixels = new uint32_t[npixels];
|
|
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
|
|
|
stbi_flip_vertically_on_write(true);
|
|
|
|
// Verify if the folder exists for saving screenshots and
|
|
// create it if it doesn't
|
|
// Kinda inefficient but I didn't want to be too intrusive
|
|
// -Vruk
|
|
// https://stackoverflow.com/a/22182041
|
|
|
|
// https://stackoverflow.com/a/8901001
|
|
CHAR mypicturespath[MAX_PATH];
|
|
HRESULT result = SHGetFolderPathA(NULL, CSIDL_MYPICTURES, NULL, SHGFP_TYPE_CURRENT, mypicturespath);
|
|
|
|
static char str[MAX_PATH];
|
|
|
|
if (result == S_OK)
|
|
sprintf(str, "%s\\%s", mypicturespath, "MCPE");
|
|
else
|
|
sprintf(str, "%s\\%s", ".", "Screenshots");
|
|
|
|
// https://stackoverflow.com/a/8233867
|
|
DWORD ftyp = GetFileAttributesA(str);
|
|
|
|
DWORD error = GetLastError();
|
|
if (error == ERROR_PATH_NOT_FOUND || error == ERROR_FILE_NOT_FOUND || error == ERROR_INVALID_NAME)
|
|
{
|
|
// https://stackoverflow.com/a/22182041
|
|
CreateDirectoryA(str, NULL);
|
|
}
|
|
|
|
char fullpath[MAX_PATH];
|
|
sprintf(fullpath, "%s\\%s", str, fileName.c_str());
|
|
|
|
stbi_write_png(fullpath, width, height, 4, pixels, width * 4);
|
|
|
|
delete[] pixels;
|
|
}
|
|
|
|
void AppPlatform_win32::createUserInput()
|
|
{
|
|
m_UserInput.clear();
|
|
m_UserInputStatus = -1;
|
|
|
|
switch (m_DialogType)
|
|
{
|
|
case DLG_CREATE_WORLD:
|
|
{
|
|
// some placeholder for now
|
|
m_UserInput.push_back("New World");
|
|
m_UserInput.push_back("123456");
|
|
m_UserInputStatus = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void AppPlatform_win32::showDialog(eDialogType type)
|
|
{
|
|
m_DialogType = type;
|
|
}
|
|
|
|
std::string AppPlatform_win32::getDateString(int time)
|
|
{
|
|
time_t tt = time;
|
|
struct tm t;
|
|
// using the _s variant. For a different platform there's gmtime_r. This is not directly portable however.
|
|
gmtime_s(&t, &tt);
|
|
|
|
//format it with strftime
|
|
char buf[2048];
|
|
strftime(buf, sizeof buf, "%b %d %Y %H:%M:%S", &t);
|
|
//strftime(buf, sizeof buf, "%a %b %d %H:%M:%S %Z %Y", &t);
|
|
|
|
return std::string(buf);
|
|
}
|
|
|
|
Texture AppPlatform_win32::loadTexture(const std::string& str, bool b)
|
|
{
|
|
std::string realPath = str;
|
|
if (realPath.size() && realPath[0] == '/')
|
|
// trim it off
|
|
realPath = realPath.substr(1);
|
|
|
|
realPath = "assets/" + realPath;
|
|
|
|
FILE* f = fopen(realPath.c_str(), "rb");
|
|
if (!f)
|
|
{
|
|
LOG_E("File %s couldn't be opened", realPath.c_str());
|
|
|
|
_error:
|
|
const std::string msg = "Error loading " + realPath + ". Did you unzip the Minecraft assets?";
|
|
MessageBoxA(GetHWND(), msg.c_str(), getWindowTitle(), MB_OK);
|
|
|
|
if (f)
|
|
fclose(f);
|
|
::exit(1);
|
|
}
|
|
|
|
int width = 0, height = 0, channels = 0;
|
|
|
|
stbi_uc* img = stbi_load_from_file(f, &width, &height, &channels, STBI_rgb_alpha);
|
|
if (!img)
|
|
{
|
|
LOG_E("File %s couldn't be loaded via stb_image", realPath.c_str());
|
|
goto _error;
|
|
}
|
|
|
|
uint32_t* img2 = new uint32_t[width * height];
|
|
memcpy(img2, img, width * height * sizeof(uint32_t));
|
|
stbi_image_free(img);
|
|
img = nullptr;
|
|
|
|
fclose(f);
|
|
return Texture(width, height, img2, 1, 0);
|
|
}
|
|
|
|
bool AppPlatform_win32::hasFileSystemAccess()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
std::string AppPlatform_win32::getPatchData()
|
|
{
|
|
std::ifstream ifs("assets/patches/patch_data.txt");
|
|
if (!ifs.is_open())
|
|
return "";
|
|
|
|
std::stringstream ss;
|
|
ss << ifs.rdbuf();
|
|
|
|
return ss.str();
|
|
}
|
|
|
|
void AppPlatform_win32::setScreenSize(int width, int height)
|
|
{
|
|
m_ScreenWidth = width;
|
|
m_ScreenHeight = height;
|
|
}
|
|
|
|
void AppPlatform_win32::recenterMouse()
|
|
{
|
|
// only recenter the mouse if it's grabbed
|
|
if (!m_bGrabbedMouse)
|
|
return;
|
|
|
|
// If we aren't the foreground window, return
|
|
if (GetForegroundWindow() != GetHWND())
|
|
{
|
|
m_bWasUnfocused = true;
|
|
return;
|
|
}
|
|
|
|
POINT oldPos = { 0, 0 };
|
|
GetCursorPos(&oldPos);
|
|
|
|
RECT rect;
|
|
GetClientRect(GetHWND(), &rect);
|
|
|
|
POINT offs = { m_ScreenWidth / 2, m_ScreenHeight / 2 };
|
|
ClientToScreen(GetHWND(), &offs);
|
|
|
|
SetCursorPos(offs.x, offs.y);
|
|
|
|
// Note. The only reason we do it this way instead of
|
|
// using the Mouse class is because, after SetCursorPos,
|
|
// we'll get an event on our window telling us "hey, the
|
|
// user has moved their cursor back to the center! Move
|
|
// the camera back as well", causing a camera that just
|
|
// refuses to move
|
|
|
|
// If we were unfocused last frame, ignore the diff data we have.
|
|
if (!m_bWasUnfocused)
|
|
{
|
|
m_MouseDiffX -= offs.x - oldPos.x;
|
|
m_MouseDiffY -= offs.y - oldPos.y;
|
|
}
|
|
|
|
m_bWasUnfocused = false;
|
|
}
|
|
|
|
void AppPlatform_win32::setMouseGrabbed(bool b)
|
|
{
|
|
m_bGrabbedMouse = b;
|
|
|
|
if (m_bActuallyGrabbedMouse == (b && m_bIsFocused))
|
|
return;
|
|
|
|
if (!b || !m_bIsFocused)
|
|
{
|
|
m_bActuallyGrabbedMouse = false;
|
|
|
|
//show the cursor
|
|
ShowCursor(TRUE);
|
|
|
|
//unconfine it
|
|
ClipCursor(NULL);
|
|
|
|
clearDiff();
|
|
}
|
|
else
|
|
{
|
|
m_bActuallyGrabbedMouse = true;
|
|
|
|
//hide the cursor
|
|
ShowCursor(FALSE);
|
|
|
|
//confine it to our client area
|
|
RECT rect;
|
|
GetClientRect(GetHWND(), &rect);
|
|
|
|
POINT offs = { 0, 0 };
|
|
ClientToScreen(GetHWND(), &offs);
|
|
rect.left += offs.x;
|
|
rect.top += offs.y;
|
|
rect.right += offs.x;
|
|
rect.bottom += offs.y;
|
|
|
|
ClipCursor(&rect);
|
|
|
|
// set the cursor pos to the middle of the screen
|
|
recenterMouse();
|
|
|
|
clearDiff();
|
|
}
|
|
}
|
|
|
|
void AppPlatform_win32::getMouseDiff(int& x, int& y)
|
|
{
|
|
x = m_MouseDiffX;
|
|
y = m_MouseDiffY;
|
|
}
|
|
|
|
void AppPlatform_win32::clearDiff()
|
|
{
|
|
m_MouseDiffX = m_MouseDiffY = 0;
|
|
}
|
|
|
|
void AppPlatform_win32::updateFocused(bool focused)
|
|
{
|
|
m_bIsFocused = focused;
|
|
setMouseGrabbed(m_bGrabbedMouse);
|
|
}
|
|
|
|
Mouse::ButtonType AppPlatform_win32::GetMouseButtonType(UINT iMsg)
|
|
{
|
|
switch (iMsg)
|
|
{
|
|
case WM_LBUTTONUP:
|
|
case WM_LBUTTONDOWN:
|
|
return Mouse::ButtonType::LEFT;
|
|
case WM_RBUTTONUP:
|
|
case WM_RBUTTONDOWN:
|
|
return Mouse::ButtonType::RIGHT;
|
|
case WM_MBUTTONUP:
|
|
case WM_MBUTTONDOWN:
|
|
return Mouse::ButtonType::MIDDLE;
|
|
case WM_MOUSEWHEEL:
|
|
return Mouse::ButtonType::SCROLLWHEEL;
|
|
default:
|
|
return Mouse::ButtonType::NONE;
|
|
}
|
|
}
|
|
|
|
Mouse::ButtonState AppPlatform_win32::GetMouseButtonState(UINT iMsg, WPARAM wParam)
|
|
{
|
|
Mouse::ButtonState result;
|
|
|
|
switch (iMsg)
|
|
{
|
|
case WM_LBUTTONDOWN:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_MBUTTONDOWN:
|
|
result = Mouse::ButtonState::DOWN;
|
|
break;
|
|
case WM_MOUSEWHEEL:
|
|
{
|
|
short wheelDelta = GET_WHEEL_DELTA_WPARAM(wParam);
|
|
if (wheelDelta > 0)
|
|
{
|
|
// "A positive value indicates that the wheel was rotated forward, away from the user."
|
|
result = Mouse::ButtonState::UP;
|
|
}
|
|
else
|
|
{
|
|
// "A negative value indicates that the wheel was rotated backward, toward the user."
|
|
result = Mouse::ButtonState::DOWN;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
result = Mouse::ButtonState::UP;
|
|
break;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
Keyboard::KeyState AppPlatform_win32::GetKeyState(UINT iMsg)
|
|
{
|
|
switch (iMsg)
|
|
{
|
|
case WM_KEYUP:
|
|
return Keyboard::KeyState::UP;
|
|
case WM_KEYDOWN:
|
|
default:
|
|
return Keyboard::KeyState::DOWN;
|
|
}
|
|
}
|