mirror of
https://github.com/celisej567/mcpe.git
synced 2025-12-31 17:49:17 +03:00
SDL/WASM Port
This commit is contained in:
committed by
iProgramInCpp
parent
0b16b2843a
commit
0fbe90752d
2
.gitignore
vendored
2
.gitignore
vendored
@@ -379,3 +379,5 @@ FodyWeavers.xsd
|
||||
/windows_vs/games/com.mojang
|
||||
/windows_vs/assets
|
||||
/windows_vs/assetsO
|
||||
|
||||
/wasm
|
||||
|
||||
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
[submodule "thirdparty/coi-serviceworker"]
|
||||
path = thirdparty/coi-serviceworker
|
||||
url = https://github.com/gzuidhof/coi-serviceworker
|
||||
[submodule "thirdparty/gles-compatibility-layer"]
|
||||
path = thirdparty/gles-compatibility-layer
|
||||
url = https://gitea.thebrokenrail.com/minecraft-pi-reborn/gles-compatibility-layer.git
|
||||
42
build-wasm.sh
Executable file
42
build-wasm.sh
Executable file
@@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
# Working Directory
|
||||
mkdir -p wasm
|
||||
cd wasm
|
||||
|
||||
# Clone Emscripten SDK
|
||||
if [ ! -d emsdk ]; then
|
||||
git clone https://github.com/emscripten-core/emsdk.git
|
||||
fi
|
||||
cd emsdk
|
||||
|
||||
# Update Emscripten SDK
|
||||
git pull
|
||||
./emsdk install 3.1.42 # https://github.com/emscripten-core/emscripten/issues/19921
|
||||
./emsdk activate 3.1.42 > /dev/null
|
||||
|
||||
# Use Emscripten SDK
|
||||
export EMSDK_QUIET=1
|
||||
source ./emsdk_env.sh
|
||||
|
||||
# Create Output Directory
|
||||
cd ../
|
||||
rm -rf dist
|
||||
mkdir dist
|
||||
|
||||
# Create Build Directory
|
||||
mkdir -p build
|
||||
cd build
|
||||
|
||||
# Configure Build
|
||||
emcmake cmake -GNinja "$@" ../../platforms/sdl
|
||||
|
||||
# Build
|
||||
cmake --build .
|
||||
|
||||
# Bundle
|
||||
cp reminecraftpe.* ../dist
|
||||
cp ../../platforms/sdl/wasm_shell.html ../dist/reminecraftpe.html
|
||||
cp ../../thirdparty/coi-serviceworker/coi-serviceworker.min.js ../dist
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
@@ -55,6 +55,7 @@ enum
|
||||
AKEYCODE_APOSTROPHE = VK_OEM_7, // ''"'
|
||||
AKEYCODE_SPACE = VK_SPACE,
|
||||
|
||||
AKEYCODE_1 = '1',
|
||||
AKEYCODE_0 = '0',
|
||||
//...
|
||||
AKEYCODE_9 = '9',
|
||||
@@ -73,6 +74,109 @@ enum
|
||||
#define AKEYCODE_ARROW_LEFT VK_LEFT
|
||||
#define AKEYCODE_ARROW_RIGHT VK_RIGHT
|
||||
|
||||
#elif defined(USE_SDL)
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
enum
|
||||
{
|
||||
AKEYCODE_UNKNOWN = 0,
|
||||
AKEYCODE_MENU,
|
||||
AKEYCODE_SEARCH,
|
||||
AKEYCODE_BACK,
|
||||
AKEYCODE_BUTTON_X,
|
||||
AKEYCODE_BUTTON_Y,
|
||||
AKEYCODE_DPAD_UP,
|
||||
AKEYCODE_DPAD_DOWN,
|
||||
AKEYCODE_DPAD_LEFT,
|
||||
AKEYCODE_DPAD_RIGHT,
|
||||
AKEYCODE_DPAD_CENTER,
|
||||
AKEYCODE_BUTTON_L1,
|
||||
AKEYCODE_BUTTON_R1,
|
||||
AKEYCODE_SHIFT_LEFT,
|
||||
AKEYCODE_SHIFT_RIGHT,
|
||||
AKEYCODE_DEL,
|
||||
AKEYCODE_FORWARD_DEL,
|
||||
AKEYCODE_COMMA,
|
||||
AKEYCODE_PERIOD,
|
||||
AKEYCODE_PLUS,
|
||||
AKEYCODE_MINUS,
|
||||
AKEYCODE_SEMICOLON,
|
||||
AKEYCODE_SLASH,
|
||||
AKEYCODE_GRAVE,
|
||||
AKEYCODE_LEFT_BRACKET,
|
||||
AKEYCODE_BACKSLASH,
|
||||
AKEYCODE_RIGHT_BRACKET,
|
||||
AKEYCODE_APOSTROPHE,
|
||||
AKEYCODE_SPACE,
|
||||
AKEYCODE_0,
|
||||
AKEYCODE_1,
|
||||
AKEYCODE_2,
|
||||
AKEYCODE_3,
|
||||
AKEYCODE_4,
|
||||
AKEYCODE_5,
|
||||
AKEYCODE_6,
|
||||
AKEYCODE_7,
|
||||
AKEYCODE_8,
|
||||
AKEYCODE_9,
|
||||
AKEYCODE_A,
|
||||
AKEYCODE_Q,
|
||||
AKEYCODE_T,
|
||||
AKEYCODE_Z,
|
||||
AKEYCODE_F4,
|
||||
AKEYCODE_ARROW_LEFT,
|
||||
AKEYCODE_ARROW_RIGHT
|
||||
};
|
||||
|
||||
static inline int translate_sdl_key_to_mcpe(int key) {
|
||||
switch (key) {
|
||||
case SDLK_ESCAPE: return AKEYCODE_MENU;
|
||||
case SDLK_F5: return AKEYCODE_SEARCH;
|
||||
case SDLK_y: return AKEYCODE_BACK;
|
||||
case SDLK_u: return AKEYCODE_BUTTON_X;
|
||||
case SDLK_e: return AKEYCODE_BUTTON_Y;
|
||||
case SDLK_w: return AKEYCODE_DPAD_UP;
|
||||
case SDLK_s: return AKEYCODE_DPAD_DOWN;
|
||||
case SDLK_a: return AKEYCODE_DPAD_LEFT;
|
||||
case SDLK_d: return AKEYCODE_DPAD_RIGHT;
|
||||
case SDLK_SPACE: return AKEYCODE_DPAD_CENTER;
|
||||
case SDLK_x: return AKEYCODE_BUTTON_L1;
|
||||
case SDLK_c: return AKEYCODE_BUTTON_R1;
|
||||
case SDLK_LSHIFT: return AKEYCODE_SHIFT_LEFT;
|
||||
case SDLK_RSHIFT: return AKEYCODE_SHIFT_RIGHT;
|
||||
case SDLK_BACKSPACE: return AKEYCODE_DEL;
|
||||
case SDLK_DELETE: return AKEYCODE_FORWARD_DEL;
|
||||
case SDLK_COMMA: return AKEYCODE_COMMA;
|
||||
case SDLK_PERIOD: return AKEYCODE_PERIOD;
|
||||
case SDLK_PLUS: return AKEYCODE_PLUS;
|
||||
case SDLK_MINUS: return AKEYCODE_MINUS;
|
||||
case SDLK_SEMICOLON: return AKEYCODE_SEMICOLON;
|
||||
case SDLK_SLASH: return AKEYCODE_SLASH;
|
||||
case SDLK_BACKQUOTE: return AKEYCODE_GRAVE;
|
||||
case SDLK_LEFTBRACKET: return AKEYCODE_LEFT_BRACKET;
|
||||
case SDLK_BACKSLASH: return AKEYCODE_BACKSLASH;
|
||||
case SDLK_RIGHTBRACKET: return AKEYCODE_RIGHT_BRACKET;
|
||||
case SDLK_QUOTE: return AKEYCODE_APOSTROPHE;
|
||||
case SDLK_1: return AKEYCODE_1;
|
||||
case SDLK_2: return AKEYCODE_2;
|
||||
case SDLK_3: return AKEYCODE_3;
|
||||
case SDLK_4: return AKEYCODE_4;
|
||||
case SDLK_5: return AKEYCODE_5;
|
||||
case SDLK_6: return AKEYCODE_6;
|
||||
case SDLK_7: return AKEYCODE_7;
|
||||
case SDLK_8: return AKEYCODE_8;
|
||||
case SDLK_0: return AKEYCODE_0;
|
||||
case SDLK_9: return AKEYCODE_9;
|
||||
case SDLK_q: return AKEYCODE_Q;
|
||||
case SDLK_t: return AKEYCODE_T;
|
||||
case SDLK_z: return AKEYCODE_Z;
|
||||
case SDLK_F4: return AKEYCODE_F4;
|
||||
case SDLK_LEFT: return AKEYCODE_ARROW_LEFT;
|
||||
case SDLK_RIGHT: return AKEYCODE_ARROW_RIGHT;
|
||||
default: return AKEYCODE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
#error "Add AKEYCODEs for your platform!"
|
||||
#endif
|
||||
|
||||
@@ -8,6 +8,65 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef USE_SDL
|
||||
|
||||
#ifdef USE_GLES1_COMPATIBILITY_LAYER
|
||||
#include <GLES/gl.h>
|
||||
#define GL_QUADS 0x7
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// https://cgit.freedesktop.org/mesa/glu/tree/src/libutil/project.c
|
||||
static inline void __gluMakeIdentityf(GLfloat m[16]) {
|
||||
m[0+4*0] = 1; m[0+4*1] = 0; m[0+4*2] = 0; m[0+4*3] = 0;
|
||||
m[1+4*0] = 0; m[1+4*1] = 1; m[1+4*2] = 0; m[1+4*3] = 0;
|
||||
m[2+4*0] = 0; m[2+4*1] = 0; m[2+4*2] = 1; m[2+4*3] = 0;
|
||||
m[3+4*0] = 0; m[3+4*1] = 0; m[3+4*2] = 0; m[3+4*3] = 1;
|
||||
}
|
||||
static inline void gluPerspective(GLfloat fovy, GLfloat aspect, GLfloat zNear, GLfloat zFar) {
|
||||
GLfloat m[4][4];
|
||||
float sine, cotangent, deltaZ;
|
||||
float radians = fovy / 2 * M_PI / 180;
|
||||
|
||||
deltaZ = zFar - zNear;
|
||||
sine = sin(radians);
|
||||
if ((deltaZ == 0) || (sine == 0) || (aspect == 0)) {
|
||||
return;
|
||||
}
|
||||
cotangent = cosf(radians) / sine;
|
||||
|
||||
__gluMakeIdentityf(&m[0][0]);
|
||||
m[0][0] = cotangent / aspect;
|
||||
m[1][1] = cotangent;
|
||||
m[2][2] = -(zFar + zNear) / deltaZ;
|
||||
m[2][3] = -1;
|
||||
m[3][2] = -2 * zNear * zFar / deltaZ;
|
||||
m[3][3] = 0;
|
||||
glMultMatrixf(&m[0][0]);
|
||||
}
|
||||
#else
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <SDL2/SDL_opengl.h>
|
||||
#include <SDL2/SDL_opengl_glext.h>
|
||||
#include <GL/glu.h>
|
||||
#endif
|
||||
|
||||
#define xglBindBuffer glBindBuffer
|
||||
#define xglBufferData glBufferData
|
||||
#define xglGenBuffers glGenBuffers
|
||||
#define xglDeleteBuffers glDeleteBuffers
|
||||
#ifdef USE_GLES1_COMPATIBILITY_LAYER
|
||||
#define xglOrthof glOrthof
|
||||
#else
|
||||
#define xglOrthof(left, right, bottom, top, nearpl, farpl) glOrtho((GLdouble) (left), (GLdouble) (right), (GLdouble) (bottom), (GLdouble) (top), (GLdouble) (nearpl), (GLdouble) (farpl))
|
||||
#endif
|
||||
|
||||
// @TODO: not the right place, but er, it's ok
|
||||
void drawArrayVT(GLuint buffer, int count, int stride);
|
||||
void drawArrayVTC(GLuint buffer, int count, int stride);
|
||||
|
||||
#else
|
||||
|
||||
#ifdef USE_OPENGL_2
|
||||
|
||||
#define xglBindBuffer glBindBuffer
|
||||
@@ -36,3 +95,5 @@ void drawArrayVT(GLuint buffer, int count, int stride);
|
||||
void drawArrayVTC(GLuint buffer, int count, int stride);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
1
platforms/.gitignore
vendored
Normal file
1
platforms/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build*
|
||||
@@ -15,6 +15,12 @@
|
||||
|
||||
// Add sound system overrides here
|
||||
|
||||
#elif defined(USE_SDL)
|
||||
|
||||
// -- OpenAL based sound system for SDL
|
||||
#include "sdl/SoundSystemAL.hpp"
|
||||
#define SOUND_SYSTEM_TYPE SoundSystemAL
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
// -- DirectSound based sound system for Windows
|
||||
|
||||
2
platforms/sdl/.gitignore
vendored
Normal file
2
platforms/sdl/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/build
|
||||
/assets
|
||||
308
platforms/sdl/AppPlatform_sdl.cpp
Normal file
308
platforms/sdl/AppPlatform_sdl.cpp
Normal file
@@ -0,0 +1,308 @@
|
||||
#include "AppPlatform_sdl.hpp"
|
||||
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#include <png.h>
|
||||
|
||||
#include "compat/GL.hpp"
|
||||
#else
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
#include "client/common/Utils.hpp"
|
||||
|
||||
AppPlatform_sdl::AppPlatform_sdl(std::string storageDir, SDL_Window *window) {
|
||||
_storageDir = storageDir;
|
||||
_window = window;
|
||||
}
|
||||
|
||||
int AppPlatform_sdl::checkLicense() {
|
||||
// we own the game!!
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Ensure Screenshots Folder Exists
|
||||
void ensure_screenshots_folder(const char *screenshots) {
|
||||
// Check Screenshots Folder
|
||||
struct stat obj;
|
||||
if (stat(screenshots, &obj) != 0 || !S_ISDIR(obj.st_mode)) {
|
||||
// Create Screenshots Folder
|
||||
#ifdef _WIN32
|
||||
int ret = mkdir(screenshots);
|
||||
#else
|
||||
int ret = mkdir(screenshots, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
#endif
|
||||
if (ret != 0) {
|
||||
// Unable To Create Folder
|
||||
LogMsg("Error Creating Directory: %s: %s", screenshots, strerror(errno));
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
// 4 (Year) + 1 (Hyphen) + 2 (Month) + 1 (Hyphen) + 2 (Day) + 1 (Underscore) + 2 (Hour) + 1 (Period) + 2 (Minute) + 1 (Period) + 2 (Second) + 1 (Null Terminator)
|
||||
#define TIME_SIZE 20
|
||||
// Take Screenshot
|
||||
static int save_png(const char *filename, unsigned char *pixels, int line_size, int width, int height) {
|
||||
// Return value
|
||||
int ret = 0;
|
||||
|
||||
// Variables
|
||||
png_structp png = NULL;
|
||||
png_infop info = NULL;
|
||||
FILE *file = NULL;
|
||||
png_colorp palette = NULL;
|
||||
png_bytep rows[height];
|
||||
for (int i = 0; i < height; ++i) {
|
||||
rows[height - i - 1] = (png_bytep)(&pixels[i * line_size]);
|
||||
}
|
||||
|
||||
// Init
|
||||
png = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
|
||||
if (!png) {
|
||||
ret = 1;
|
||||
goto ret;
|
||||
}
|
||||
info = png_create_info_struct(png);
|
||||
if (!info) {
|
||||
ret = 1;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
// Open File
|
||||
file = fopen(filename, "wb");
|
||||
if (!file) {
|
||||
ret = 1;
|
||||
goto ret;
|
||||
}
|
||||
|
||||
// Prepare To Write
|
||||
png_init_io(png, file);
|
||||
png_set_IHDR(png, info, width, height, 8 /* Depth */, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
|
||||
palette = (png_colorp) png_malloc(png, PNG_MAX_PALETTE_LENGTH * sizeof(png_color));
|
||||
if (!palette) {
|
||||
ret = 1;
|
||||
goto ret;
|
||||
}
|
||||
png_set_PLTE(png, info, palette, PNG_MAX_PALETTE_LENGTH);
|
||||
png_write_info(png, info);
|
||||
png_set_packing(png);
|
||||
|
||||
// Write
|
||||
png_write_image(png, rows);
|
||||
png_write_end(png, info);
|
||||
|
||||
ret:
|
||||
// Free
|
||||
if (palette != NULL) {
|
||||
png_free(png, palette);
|
||||
}
|
||||
if (file != NULL) {
|
||||
fclose(file);
|
||||
}
|
||||
if (png != NULL) {
|
||||
png_destroy_write_struct(&png, &info);
|
||||
}
|
||||
|
||||
// Return
|
||||
return ret;
|
||||
}
|
||||
void AppPlatform_sdl::saveScreenshot(const std::string &filename, int glWidth, int glHeight) {
|
||||
// Get Directory
|
||||
std::string screenshots = _storageDir + "/screenshots";
|
||||
|
||||
// Get Timestamp
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
char time[TIME_SIZE];
|
||||
strftime(time, TIME_SIZE, "%Y-%m-%d_%H.%M.%S", timeinfo);
|
||||
|
||||
// Ensure Screenshots Folder Exists
|
||||
ensure_screenshots_folder(screenshots.c_str());
|
||||
|
||||
// Prevent Overwriting Screenshots
|
||||
int num = 1;
|
||||
std::string file = screenshots + '/' + time + ".png";
|
||||
while (access(file.c_str(), F_OK) != -1) {
|
||||
file = screenshots + '/' + time + '-' + std::to_string(num) + ".png";
|
||||
num++;
|
||||
}
|
||||
|
||||
// Get Image Size
|
||||
GLint viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, viewport);
|
||||
int x = viewport[0];
|
||||
int y = viewport[1];
|
||||
int width = viewport[2];
|
||||
int height = viewport[3];
|
||||
|
||||
// Get Line Size
|
||||
int line_size = width * 4;
|
||||
{
|
||||
// Handle Alignment
|
||||
int alignment;
|
||||
glGetIntegerv(GL_PACK_ALIGNMENT, &alignment);
|
||||
// Round
|
||||
int diff = line_size % alignment;
|
||||
if (diff > 0) {
|
||||
line_size = line_size + (alignment - diff);
|
||||
}
|
||||
}
|
||||
int size = height * line_size;
|
||||
|
||||
// Read Pixels
|
||||
bool fail = false;
|
||||
unsigned char *pixels = (unsigned char *) malloc(size);
|
||||
if (pixels == NULL) {
|
||||
fail = true;
|
||||
} else {
|
||||
glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
|
||||
}
|
||||
|
||||
// Save Image
|
||||
if (fail || save_png(file.c_str(), pixels, line_size, width, height)) {
|
||||
LogMsg("Screenshot Failed: %s", file.c_str());
|
||||
} else {
|
||||
LogMsg("Screenshot Saved: %s", file.c_str());
|
||||
}
|
||||
|
||||
// Free
|
||||
if (pixels != NULL) {
|
||||
free(pixels);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int AppPlatform_sdl::getScreenWidth() const {
|
||||
int width;
|
||||
SDL_GL_GetDrawableSize(_window, &width, nullptr);
|
||||
return width;
|
||||
}
|
||||
|
||||
int AppPlatform_sdl::getScreenHeight() const {
|
||||
int height;
|
||||
SDL_GL_GetDrawableSize(_window, nullptr, &height);
|
||||
return height;
|
||||
}
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
static void png_read_sdl(png_structp png_ptr, png_bytep data, png_size_t length) {
|
||||
SDL_RWread((SDL_RWops *) png_get_io_ptr(png_ptr), (char *) data, length, 1);
|
||||
}
|
||||
static void nop_png_warning(png_structp png_ptr, png_const_charp warning_message) {
|
||||
// Do Nothing
|
||||
}
|
||||
#endif
|
||||
Texture AppPlatform_sdl::loadTexture(const std::string& str, bool b) {
|
||||
Texture out;
|
||||
out.field_C = 0;
|
||||
out.field_D = 0;
|
||||
|
||||
std::string realPath = str;
|
||||
if (realPath.size() && realPath[0] == '/') {
|
||||
// trim it off
|
||||
realPath = realPath.substr(1);
|
||||
}
|
||||
realPath = "assets/" + realPath;
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
SDL_RWops *io = SDL_RWFromFile(realPath.c_str(), "rb");
|
||||
|
||||
if (io != NULL) {
|
||||
png_structp pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, nop_png_warning);
|
||||
if (!pngPtr) {
|
||||
return out;
|
||||
}
|
||||
|
||||
png_infop infoPtr = png_create_info_struct(pngPtr);
|
||||
if (!infoPtr) {
|
||||
png_destroy_read_struct(&pngPtr, NULL, NULL);
|
||||
return out;
|
||||
}
|
||||
|
||||
png_set_read_fn(pngPtr, (png_voidp) io, png_read_sdl);
|
||||
|
||||
png_read_info(pngPtr, infoPtr);
|
||||
|
||||
png_set_expand(pngPtr);
|
||||
png_set_strip_16(pngPtr);
|
||||
png_set_gray_to_rgb(pngPtr);
|
||||
png_read_update_info(pngPtr, infoPtr);
|
||||
|
||||
out.m_width = png_get_image_width(pngPtr, infoPtr);
|
||||
out.m_height = png_get_image_height(pngPtr, infoPtr);
|
||||
|
||||
bool opaque = png_get_color_type(pngPtr, infoPtr) != PNG_COLOR_TYPE_RGBA;
|
||||
if (!opaque) {
|
||||
out.field_C = 1;
|
||||
}
|
||||
int pixelSize = opaque ? 3 : 4;
|
||||
|
||||
png_bytep *rowPtrs = new png_bytep[out.m_height];
|
||||
unsigned char *pixels = new unsigned char[pixelSize * out.m_width * out.m_height];
|
||||
|
||||
int rowStrideBytes = pixelSize * out.m_width;
|
||||
for (int i = 0; i < out.m_height; i++) {
|
||||
rowPtrs[i] = (png_bytep) &pixels[i * rowStrideBytes];
|
||||
}
|
||||
png_read_image(pngPtr, rowPtrs);
|
||||
|
||||
out.m_pixels = (uint32_t *) pixels;
|
||||
|
||||
png_destroy_read_struct(&pngPtr, &infoPtr, (png_infopp) 0);
|
||||
delete[](png_bytep) rowPtrs;
|
||||
SDL_RWclose(io);
|
||||
}
|
||||
#else
|
||||
char *data = emscripten_get_preloaded_image_data(("/" + realPath).c_str(), &out.m_width, &out.m_height);
|
||||
if (data != NULL) {
|
||||
size_t data_size = out.m_width * out.m_height * 4;
|
||||
out.m_pixels = (uint32_t *) new unsigned char[data_size];
|
||||
out.field_C = 1;
|
||||
memcpy(out.m_pixels, data, data_size);
|
||||
free(data);
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
LogMsg("Couldn't find file: %s", str.c_str());
|
||||
return out;
|
||||
}
|
||||
|
||||
void AppPlatform_sdl::setMouseGrabbed(bool b) {
|
||||
SDL_SetWindowGrab(_window, b ? SDL_TRUE : SDL_FALSE);
|
||||
SDL_SetRelativeMouseMode(b ? SDL_TRUE : SDL_FALSE);
|
||||
}
|
||||
|
||||
void AppPlatform_sdl::setMouseDiff(int x, int y) {
|
||||
xrel = x;
|
||||
yrel = y;
|
||||
}
|
||||
|
||||
void AppPlatform_sdl::getMouseDiff(int& x, int& y) {
|
||||
x = xrel;
|
||||
y = yrel;
|
||||
}
|
||||
|
||||
void AppPlatform_sdl::clearDiff() {
|
||||
xrel = 0;
|
||||
yrel = 0;
|
||||
}
|
||||
|
||||
bool AppPlatform_sdl::shiftPressed() {
|
||||
return m_bShiftPressed[0] || m_bShiftPressed[1];
|
||||
}
|
||||
|
||||
void AppPlatform_sdl::setShiftPressed(bool b, bool isLeft) {
|
||||
m_bShiftPressed[isLeft ? 0 : 1] = b;
|
||||
}
|
||||
|
||||
int AppPlatform_sdl::getUserInputStatus() {
|
||||
return -1;
|
||||
}
|
||||
45
platforms/sdl/AppPlatform_sdl.hpp
Normal file
45
platforms/sdl/AppPlatform_sdl.hpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "AppPlatform.hpp"
|
||||
|
||||
#ifdef ORIGINAL_CODE
|
||||
#error "This isn't original code. You probably shouldn't try to compile this"
|
||||
#endif
|
||||
|
||||
void ensure_screenshots_folder(const char *screenshots);
|
||||
|
||||
class AppPlatform_sdl : public AppPlatform {
|
||||
public:
|
||||
AppPlatform_sdl(std::string storageDir, SDL_Window *window);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
void saveScreenshot(const std::string& fileName, int width, int height) override;
|
||||
#endif
|
||||
int checkLicense() override;
|
||||
int getScreenWidth() const override;
|
||||
int getScreenHeight() const override;
|
||||
Texture loadTexture(const std::string& str, bool b) override;
|
||||
int getUserInputStatus() override;
|
||||
|
||||
// Also add these to allow proper turning within the game.
|
||||
void setMouseGrabbed(bool b) override;
|
||||
void setMouseDiff(int x, int y);
|
||||
void getMouseDiff(int& x, int& y) override;
|
||||
void clearDiff() override;
|
||||
|
||||
// Also add these to allow proper text input within the game.
|
||||
bool shiftPressed() override;
|
||||
void setShiftPressed(bool b, bool isLeft);
|
||||
private:
|
||||
std::string _storageDir;
|
||||
SDL_Window *_window;
|
||||
|
||||
bool m_bShiftPressed[2] = {false, false};
|
||||
|
||||
int xrel;
|
||||
int yrel;
|
||||
};
|
||||
64
platforms/sdl/CMakeLists.txt
Normal file
64
platforms/sdl/CMakeLists.txt
Normal file
@@ -0,0 +1,64 @@
|
||||
cmake_minimum_required(VERSION 3.16.0)
|
||||
project(reminecraftpe)
|
||||
|
||||
# SDL Build
|
||||
add_compile_definitions(USE_SDL HANDLE_CHARS_SEPARATELY)
|
||||
|
||||
# WASM
|
||||
if(EMSCRIPTEN)
|
||||
function(add_compile_and_link_options)
|
||||
add_compile_options(${ARGV})
|
||||
add_link_options(${ARGV})
|
||||
endfunction()
|
||||
set(CMAKE_EXECUTABLE_SUFFIX ".js")
|
||||
endif()
|
||||
|
||||
# Clang
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
add_compile_options(-Wno-inconsistent-missing-override -Wno-enum-compare-switch -Wno-register)
|
||||
endif()
|
||||
|
||||
# Threads
|
||||
if(EMSCRIPTEN)
|
||||
add_compile_and_link_options(-pthread)
|
||||
else()
|
||||
find_package(Threads)
|
||||
link_libraries(Threads::Threads)
|
||||
endif()
|
||||
|
||||
# Build
|
||||
add_executable(reminecraftpe
|
||||
main.cpp
|
||||
AppPlatform_sdl.cpp
|
||||
SoundSystemAL.cpp
|
||||
)
|
||||
|
||||
# Core
|
||||
add_subdirectory(../../source source)
|
||||
target_link_libraries(reminecraftpe reminecraftpe-core)
|
||||
|
||||
# LibPNG
|
||||
if(NOT EMSCRIPTEN)
|
||||
find_package(PNG REQUIRED)
|
||||
target_link_libraries(reminecraftpe PNG::PNG)
|
||||
endif()
|
||||
|
||||
# SDL
|
||||
if(TARGET SDL2::SDL2main)
|
||||
target_link_libraries(reminecraftpe SDL2::SDL2main)
|
||||
endif()
|
||||
|
||||
# WASM
|
||||
if(EMSCRIPTEN)
|
||||
target_link_options(reminecraftpe PRIVATE -Wno-pthreads-mem-growth)
|
||||
target_link_options(reminecraftpe PRIVATE -sALLOW_MEMORY_GROWTH=1)
|
||||
# Export Resize Function
|
||||
target_link_options(reminecraftpe PRIVATE -sEXPORTED_FUNCTIONS=_main,_resize_from_js -sEXPORTED_RUNTIME_METHODS=ccall)
|
||||
endif()
|
||||
|
||||
# Assets
|
||||
if(EMSCRIPTEN)
|
||||
target_link_options(reminecraftpe PRIVATE --use-preload-plugins --preload-file "${CMAKE_CURRENT_SOURCE_DIR}/assets@/assets")
|
||||
elseif(NOT EXISTS "${CMAKE_CURRENT_BINARY_DIR}/assets")
|
||||
file(CREATE_LINK "${CMAKE_CURRENT_SOURCE_DIR}/assets" "${CMAKE_CURRENT_BINARY_DIR}/assets" SYMBOLIC)
|
||||
endif()
|
||||
245
platforms/sdl/SoundSystemAL.cpp
Normal file
245
platforms/sdl/SoundSystemAL.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
#include "SoundSystemAL.hpp"
|
||||
|
||||
#include "client/common/Utils.hpp"
|
||||
|
||||
SoundSystemAL::SoundSystemAL() {
|
||||
device = alcOpenDevice(NULL);
|
||||
if (!device) {
|
||||
LogMsg("Unable To Load Audio Engine");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create Context
|
||||
context = alcCreateContext(device, NULL);
|
||||
ALCenum err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
LogMsg("Unable To Open Audio Context: %s", alcGetString(device, err));
|
||||
return;
|
||||
}
|
||||
|
||||
// Select Context
|
||||
alcMakeContextCurrent(context);
|
||||
err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
LogMsg("Unable To Select Audio Context: %s", alcGetString(device, err));
|
||||
return;
|
||||
}
|
||||
|
||||
// Set Distance Model
|
||||
alDistanceModel(AL_LINEAR_DISTANCE_CLAMPED);
|
||||
|
||||
// Mark As Loaded
|
||||
loaded = true;
|
||||
}
|
||||
|
||||
SoundSystemAL::~SoundSystemAL() {
|
||||
if (loaded) {
|
||||
// Delete Audio Sources
|
||||
delete_sources();
|
||||
|
||||
// Delete Audio Buffers
|
||||
delete_buffers();
|
||||
|
||||
// Deselect Context
|
||||
alcMakeContextCurrent(NULL);
|
||||
ALCenum err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
LogMsg("Unable To Deselect Audio Context: %s", alcGetString(device, err));
|
||||
}
|
||||
|
||||
// Destroy Context
|
||||
alcDestroyContext(context);
|
||||
err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
LogMsg("Unable To Destroy Audio Context: %s", alcGetString(device, err));
|
||||
}
|
||||
|
||||
// Close Device
|
||||
alcCloseDevice(device);
|
||||
err = alcGetError(device);
|
||||
if (err != ALC_NO_ERROR) {
|
||||
LogMsg("Unable To Close Audio Device: %s", alcGetString(device, err));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error Checking
|
||||
#define AL_ERROR_CHECK() AL_ERROR_CHECK_MANUAL(alGetError())
|
||||
#define AL_ERROR_CHECK_MANUAL(val) \
|
||||
{ \
|
||||
ALenum __err = val; \
|
||||
if (__err != AL_NO_ERROR) { \
|
||||
LogMsg("(%s:%i) OpenAL Error: %s", __FILE__, __LINE__, alGetString(__err)); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} \
|
||||
}
|
||||
|
||||
// Delete Sources
|
||||
void SoundSystemAL::delete_sources() {
|
||||
if (loaded) {
|
||||
for (ALuint source : idle_sources) {
|
||||
alDeleteSources(1, &source);
|
||||
AL_ERROR_CHECK();
|
||||
}
|
||||
for (ALuint source : sources) {
|
||||
alDeleteSources(1, &source);
|
||||
AL_ERROR_CHECK();
|
||||
}
|
||||
}
|
||||
idle_sources.clear();
|
||||
sources.clear();
|
||||
}
|
||||
|
||||
// Delete Buffers
|
||||
void SoundSystemAL::delete_buffers() {
|
||||
if (loaded) {
|
||||
for (auto &it : buffers) {
|
||||
if (it.second && alIsBuffer(it.second)) {
|
||||
alDeleteBuffers(1, &it.second);
|
||||
AL_ERROR_CHECK();
|
||||
}
|
||||
}
|
||||
}
|
||||
buffers.clear();
|
||||
}
|
||||
|
||||
// Get Buffer
|
||||
ALuint SoundSystemAL::get_buffer(const SoundDesc &sound) {
|
||||
if (buffers.count(sound.m_pData) > 0) {
|
||||
return buffers[sound.m_pData];
|
||||
} else {
|
||||
// Sound Format
|
||||
ALenum format = AL_NONE;
|
||||
if (sound.m_header.m_channels == 1) {
|
||||
format = sound.m_header.m_bytes_per_sample == 2 ? AL_FORMAT_MONO16 : AL_FORMAT_MONO8;
|
||||
} else if (sound.m_header.m_channels == 2) {
|
||||
format = sound.m_header.m_bytes_per_sample == 2 ? AL_FORMAT_STEREO16 : AL_FORMAT_STEREO8;
|
||||
}
|
||||
|
||||
// Sound Data Size
|
||||
int size = sound.m_header.m_length * sound.m_header.m_bytes_per_sample;
|
||||
|
||||
// Create Buffer
|
||||
ALuint buffer;
|
||||
alGenBuffers(1, &buffer);
|
||||
AL_ERROR_CHECK();
|
||||
alBufferData(buffer, format, sound.m_pData, size, sound.m_header.m_sample_rate);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Store
|
||||
buffers[sound.m_pData] = buffer;
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
|
||||
void SoundSystemAL::update(float x, float y, float z, float yaw) {
|
||||
// Check
|
||||
if (loaded) {
|
||||
// Update Listener Volume
|
||||
float volume = 1;
|
||||
alListenerf(AL_GAIN, volume);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Update Listener Position
|
||||
alListener3f(AL_POSITION, x, y, z);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Update Listener Orientation
|
||||
float radian_yaw = yaw * (M_PI / 180);
|
||||
ALfloat orientation[] = {-sinf(radian_yaw), 0.0f, cosf(radian_yaw), 0.0f, 1.0f, 0.0f};
|
||||
alListenerfv(AL_ORIENTATION, orientation);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Clear Finished Sources
|
||||
std::vector<ALuint>::iterator it = sources.begin();
|
||||
while (it != sources.end()) {
|
||||
ALuint source = *it;
|
||||
bool remove = false;
|
||||
// Check
|
||||
if (source && alIsSource(source)) {
|
||||
// Is Valid Source
|
||||
ALint source_state;
|
||||
alGetSourcei(source, AL_SOURCE_STATE, &source_state);
|
||||
AL_ERROR_CHECK();
|
||||
if (source_state != AL_PLAYING) {
|
||||
// Finished Playing
|
||||
remove = true;
|
||||
if (idle_sources.size() < MAX_IDLE_SOURCES) {
|
||||
idle_sources.push_back(source);
|
||||
} else {
|
||||
alDeleteSources(1, &source);
|
||||
AL_ERROR_CHECK();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Not A Source
|
||||
remove = true;
|
||||
}
|
||||
// Remove If Needed
|
||||
if (remove) {
|
||||
it = sources.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SoundSystemAL::play(const SoundDesc &sound, float x, float y, float z, float volume, float pitch, bool is_ui) {
|
||||
if (loaded) {
|
||||
// Load Sound
|
||||
ALuint buffer = get_buffer(sound);
|
||||
if (volume > 0.0f && buffer) {
|
||||
// Get Source
|
||||
ALuint al_source;
|
||||
if (idle_sources.size() > 0) {
|
||||
// Use Idle Source
|
||||
al_source = idle_sources.back();
|
||||
idle_sources.pop_back();
|
||||
} else {
|
||||
// Create Source
|
||||
alGenSources(1, &al_source);
|
||||
// Special Out-Of-Memory Handling
|
||||
{
|
||||
ALenum err = alGetError();
|
||||
if (err == AL_OUT_OF_MEMORY) {
|
||||
return;
|
||||
} else {
|
||||
AL_ERROR_CHECK_MANUAL(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set Properties
|
||||
alSourcef(al_source, AL_PITCH, pitch);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcef(al_source, AL_GAIN, volume);
|
||||
AL_ERROR_CHECK();
|
||||
alSource3f(al_source, AL_POSITION, x, y, z);
|
||||
AL_ERROR_CHECK();
|
||||
alSource3f(al_source, AL_VELOCITY, 0, 0, 0);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcei(al_source, AL_LOOPING, AL_FALSE);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcei(al_source, AL_SOURCE_RELATIVE, is_ui ? AL_TRUE : AL_FALSE);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Set Attenuation
|
||||
alSourcef(al_source, AL_MAX_DISTANCE, 16.0f);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcef(al_source, AL_ROLLOFF_FACTOR, 6.0f);
|
||||
AL_ERROR_CHECK();
|
||||
alSourcef(al_source, AL_REFERENCE_DISTANCE, 5.0f);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Set Buffer
|
||||
alSourcei(al_source, AL_BUFFER, buffer);
|
||||
AL_ERROR_CHECK();
|
||||
|
||||
// Play
|
||||
alSourcePlay(al_source);
|
||||
AL_ERROR_CHECK();
|
||||
sources.push_back(al_source);
|
||||
}
|
||||
}
|
||||
}
|
||||
31
platforms/sdl/SoundSystemAL.hpp
Normal file
31
platforms/sdl/SoundSystemAL.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
|
||||
#include <AL/al.h>
|
||||
#include <AL/alc.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "client/sound/SoundData.hpp"
|
||||
|
||||
#define MAX_IDLE_SOURCES 50
|
||||
|
||||
class SoundSystemAL {
|
||||
public:
|
||||
SoundSystemAL();
|
||||
~SoundSystemAL();
|
||||
void update(float x, float y, float z, float yaw);
|
||||
void play(const SoundDesc &sound, float x, float y, float z, float volume, float pitch, bool is_ui);
|
||||
private:
|
||||
void delete_sources();
|
||||
void delete_buffers();
|
||||
ALuint get_buffer(const SoundDesc &sound);
|
||||
|
||||
ALCdevice *device = NULL;
|
||||
ALCcontext *context = NULL;
|
||||
bool loaded = false;
|
||||
std::vector<ALuint> sources;
|
||||
std::vector<ALuint> idle_sources;
|
||||
std::unordered_map<void *, ALuint> buffers;
|
||||
};
|
||||
258
platforms/sdl/main.cpp
Normal file
258
platforms/sdl/main.cpp
Normal file
@@ -0,0 +1,258 @@
|
||||
#include <cstdarg>
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
#include "compat/GL.hpp"
|
||||
#include "compat/AKeyCodes.hpp"
|
||||
#include "App.hpp"
|
||||
#include "AppPlatform_sdl.hpp"
|
||||
#include "NinecraftApp.hpp"
|
||||
|
||||
#ifdef __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#include <emscripten/html5.h>
|
||||
#endif
|
||||
|
||||
void LogMsg(const char* fmt, ...) {
|
||||
va_list lst;
|
||||
va_start(lst, fmt);
|
||||
|
||||
vprintf(fmt, lst);
|
||||
printf("\n");
|
||||
|
||||
va_end(lst);
|
||||
}
|
||||
// I hate duplicating code, but yeah
|
||||
void LogMsgNoCR(const char* fmt, ...) {
|
||||
va_list lst;
|
||||
va_start(lst, fmt);
|
||||
|
||||
vprintf(fmt, lst);
|
||||
|
||||
va_end(lst);
|
||||
}
|
||||
|
||||
AppPlatform_sdl *g_AppPlatform;
|
||||
NinecraftApp *g_pApp;
|
||||
|
||||
SDL_Window *window = NULL;
|
||||
SDL_GLContext context = NULL;
|
||||
static void teardown() {
|
||||
if (window != NULL) {
|
||||
SDL_GL_DeleteContext(context);
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
window = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// Resize From JS
|
||||
#ifdef __EMSCRIPTEN__
|
||||
extern "C" void resize_from_js(int new_width, int new_height) {
|
||||
SDL_SetWindowSize(window, new_width, new_height);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Handle Events
|
||||
static bool window_resized = false;
|
||||
static void handle_events() {
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP: {
|
||||
Keyboard::feed(event.key.state == SDL_PRESSED ? 1 : 0, translate_sdl_key_to_mcpe(event.key.keysym.sym));
|
||||
if (event.key.keysym.sym == SDLK_LSHIFT || event.key.keysym.sym == SDLK_RSHIFT) {
|
||||
g_AppPlatform->setShiftPressed(event.key.state == SDL_PRESSED, event.key.keysym.sym == SDLK_LSHIFT);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEBUTTONDOWN:
|
||||
case SDL_MOUSEBUTTONUP: {
|
||||
Mouse::feed(event.button.button == SDL_BUTTON_LEFT ? 1 : 2, event.button.state == SDL_PRESSED ? 1 : 0, event.button.x, event.button.y);
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEMOTION: {
|
||||
Mouse::_x = event.motion.x;
|
||||
Mouse::_y = event.motion.y;
|
||||
Mouse::feed(0, 0, event.motion.x, event.motion.y);
|
||||
g_AppPlatform->setMouseDiff(event.motion.xrel, event.motion.yrel);
|
||||
break;
|
||||
}
|
||||
case SDL_MOUSEWHEEL: {
|
||||
Mouse::feed(3, event.wheel.y, Mouse::_x, Mouse::_y);
|
||||
break;
|
||||
}
|
||||
case SDL_TEXTINPUT: {
|
||||
if (g_pApp != nullptr) {
|
||||
char x = event.text.text[0];
|
||||
if (x >= ' ' && x <= '~') {
|
||||
g_pApp->handleCharInput(x);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_WINDOWEVENT: {
|
||||
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
|
||||
window_resized = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SDL_QUIT: {
|
||||
g_pApp->quit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// GUI Scale
|
||||
static void calulate_gui_scale() {
|
||||
int width = Minecraft::width;
|
||||
|
||||
// Modified Version Of https://github.com/MCPI-Revival/Ninecraft/blob/3f71638a10b581f6a50669edb24bc1ef1a92fbea/ninecraft/src/main.c#L243-L255
|
||||
if (width < 1000) {
|
||||
if (width < 400) {
|
||||
Gui::InvGuiScale = 1.0;
|
||||
} else {
|
||||
Gui::InvGuiScale = 0.5;
|
||||
}
|
||||
} else {
|
||||
Gui::InvGuiScale = 0.25;
|
||||
}
|
||||
}
|
||||
|
||||
// Resizing
|
||||
static void resize() {
|
||||
SDL_GL_GetDrawableSize(window, &Minecraft::width, &Minecraft::height);
|
||||
|
||||
calulate_gui_scale();
|
||||
|
||||
if (g_pApp != nullptr && g_pApp->m_pScreen != nullptr) {
|
||||
g_pApp->m_pScreen->setSize(Minecraft::width * Gui::InvGuiScale, Minecraft::height * Gui::InvGuiScale);
|
||||
}
|
||||
}
|
||||
|
||||
// Main Loop
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#define EM_BOOL bool
|
||||
#define EM_TRUE true
|
||||
#define EM_FALSE false
|
||||
#endif
|
||||
static bool is_first_window_resize = true;
|
||||
static EM_BOOL main_loop(double time, void *user_data) {
|
||||
// Handle Events
|
||||
handle_events();
|
||||
|
||||
// Screen Size
|
||||
if (window_resized) {
|
||||
window_resized = false;
|
||||
resize();
|
||||
}
|
||||
|
||||
// Update MCPE
|
||||
g_pApp->update();
|
||||
|
||||
// Swap Buffers
|
||||
SDL_GL_SwapWindow(window);
|
||||
|
||||
if (g_pApp->wantToQuit()) {
|
||||
delete g_pApp;
|
||||
delete g_AppPlatform;
|
||||
teardown();
|
||||
// Stop Looping
|
||||
return EM_FALSE;
|
||||
} else {
|
||||
// Keep Looping
|
||||
return EM_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
// Main
|
||||
int main(int argc, char *argv[]) {
|
||||
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
|
||||
LOGE("Unable To Initialize SDL: %s\n", SDL_GetError());
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Configure OpenGL ES Context
|
||||
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
|
||||
#ifdef USE_GLES1_COMPATIBILITY_LAYER
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
|
||||
#else
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
|
||||
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
|
||||
#endif
|
||||
// Double-Buffering
|
||||
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
|
||||
|
||||
// Window Size
|
||||
#ifdef __EMSCRIPTEN__
|
||||
Minecraft::width = std::stoi(argv[1]);
|
||||
Minecraft::height = std::stoi(argv[2]);
|
||||
#endif
|
||||
|
||||
// Create Window
|
||||
window = SDL_CreateWindow("ReMinecraftPE", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, Minecraft::width, Minecraft::height, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
|
||||
if (!window) {
|
||||
LOGE("Unable To Create SDL Window\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Enable Text Input
|
||||
SDL_StartTextInput();
|
||||
|
||||
// Create OpenGL ES Context
|
||||
context = SDL_GL_CreateContext(window);
|
||||
if (!context) {
|
||||
LOGE("Unable To Create OpenGL Context\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Setup Compatibility Layer If Needed
|
||||
#ifdef USE_GLES1_COMPATIBILITY_LAYER
|
||||
init_gles_compatibility_layer();
|
||||
#endif
|
||||
|
||||
// Setup Teardown
|
||||
#ifndef __EMSCRIPTEN__
|
||||
atexit(teardown);
|
||||
#endif
|
||||
|
||||
// Set Size
|
||||
resize();
|
||||
|
||||
// Storage Directory
|
||||
#ifdef _WIN32
|
||||
std::string storagePath = getenv("APPDATA");
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
std::string storagePath = "";
|
||||
#else
|
||||
std::string storagePath = getenv("HOME");
|
||||
#endif
|
||||
storagePath += "/.reminecraftpe";
|
||||
ensure_screenshots_folder(storagePath.c_str());
|
||||
|
||||
// Start MCPE
|
||||
g_pApp = new NinecraftApp;
|
||||
g_pApp->m_externalStorageDir = storagePath;
|
||||
g_AppPlatform = new AppPlatform_sdl(g_pApp->m_externalStorageDir, window);
|
||||
g_pApp->m_pPlatform = g_AppPlatform;
|
||||
g_pApp->init();
|
||||
|
||||
// Loop
|
||||
#ifndef __EMSCRIPTEN__
|
||||
while (true) {
|
||||
EM_BOOL result = main_loop(0, nullptr);
|
||||
if (result == EM_FALSE) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
emscripten_request_animation_frame_loop(main_loop, nullptr);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
54
platforms/sdl/wasm_shell.html
Normal file
54
platforms/sdl/wasm_shell.html
Normal file
@@ -0,0 +1,54 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<title>ReMinecraftPE</title>
|
||||
<style>
|
||||
html, body {
|
||||
background-color: black;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
}
|
||||
canvas {
|
||||
display: block;
|
||||
border: 0px none;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<canvas id="canvas" oncontextmenu="event.preventDefault()" tabindex=-1></canvas>
|
||||
<script type="text/javascript" src="coi-serviceworker.min.js"></script>
|
||||
<script type='text/javascript'>
|
||||
var Module = {
|
||||
print: function (text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.log(text);
|
||||
},
|
||||
printErr: function (text) {
|
||||
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
|
||||
console.error(text);
|
||||
},
|
||||
canvas: (function () {
|
||||
var canvas = document.getElementById('canvas');
|
||||
|
||||
// As a default initial behavior, pop up an alert when webgl context is lost. To make your
|
||||
// application robust, you may want to override this behavior before shipping!
|
||||
// See http://www.khronos.org/registry/webgl/specs/latest/1.0/#5.15.2
|
||||
canvas.addEventListener("webglcontextlost", function(e) { alert('WebGL context lost. You will need to reload the page.'); e.preventDefault(); }, false);
|
||||
|
||||
// Handle Resize
|
||||
function setCanvasSize() {
|
||||
Module.ccall('resize_from_js', null, ['number', 'number'], [window.innerWidth, window.innerHeight]);
|
||||
}
|
||||
window.addEventListener("resize", setCanvasSize);
|
||||
|
||||
return canvas;
|
||||
})(),
|
||||
arguments: [String(window.innerWidth), String(window.innerHeight)]
|
||||
};
|
||||
</script>
|
||||
<script async type="text/javascript" src="reminecraftpe.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
254
source/CMakeLists.txt
Normal file
254
source/CMakeLists.txt
Normal file
@@ -0,0 +1,254 @@
|
||||
cmake_minimum_required(VERSION 3.16.0)
|
||||
project(reminecraftpe-core)
|
||||
|
||||
# Build
|
||||
add_library(reminecraftpe-core STATIC
|
||||
NinecraftApp.cpp
|
||||
client/renderer/LevelRenderer.cpp
|
||||
client/renderer/Culler.cpp
|
||||
client/renderer/entity/HumanoidMobRenderer.cpp
|
||||
client/renderer/entity/TntRenderer.cpp
|
||||
client/renderer/entity/MobRenderer.cpp
|
||||
client/renderer/entity/FallingTileRenderer.cpp
|
||||
client/renderer/entity/EntityRenderer.cpp
|
||||
client/renderer/entity/ItemRenderer.cpp
|
||||
client/renderer/entity/TripodCameraRenderer.cpp
|
||||
client/renderer/entity/ItemSpriteRenderer.cpp
|
||||
client/renderer/entity/EntityRenderDispatcher.cpp
|
||||
client/renderer/RenderList.cpp
|
||||
client/renderer/Chunk.cpp
|
||||
client/renderer/RenderChunk.cpp
|
||||
client/renderer/Frustum.cpp
|
||||
client/renderer/ItemInHandRenderer.cpp
|
||||
client/renderer/DynamicTexture.cpp
|
||||
client/renderer/GameRenderer.cpp
|
||||
client/renderer/Textures.cpp
|
||||
client/renderer/FrustumCuller.cpp
|
||||
client/renderer/LightUpdate.cpp
|
||||
client/renderer/Font.cpp
|
||||
client/renderer/WaterSideTexture.cpp
|
||||
client/renderer/Tesselator.cpp
|
||||
client/renderer/TileRenderer.cpp
|
||||
client/renderer/LightLayer.cpp
|
||||
client/renderer/WaterTexture.cpp
|
||||
client/network/Packets/UpdateBlockPacket.cpp
|
||||
client/network/Packets/RequestChunkPacket.cpp
|
||||
client/network/Packets/PlayerEquipmentPacket.cpp
|
||||
client/network/Packets/ChunkDataPacket.cpp
|
||||
client/network/Packets/PlaceBlockPacket.cpp
|
||||
client/network/Packets/LoginPacket.cpp
|
||||
client/network/Packets/StartGamePacket.cpp
|
||||
client/network/Packets/RemoveEntityPacket.cpp
|
||||
client/network/Packets/AddPlayerPacket.cpp
|
||||
client/network/Packets/RemoveBlockPacket.cpp
|
||||
client/network/Packets/MovePlayerPacket.cpp
|
||||
client/network/Packets/MessagePacket.cpp
|
||||
client/network/ServerSideNetworkHandler.cpp
|
||||
client/network/RakNetInstance.cpp
|
||||
client/network/ClientSideNetworkHandler.cpp
|
||||
client/network/MinecraftPackets.cpp
|
||||
client/network/NetEventCallback.cpp
|
||||
client/sound/SoundData.cpp
|
||||
client/sound/SoundSystem.cpp
|
||||
client/sound/SoundRepository.cpp
|
||||
client/sound/SoundEngine.cpp
|
||||
client/gui/Screen.cpp
|
||||
client/gui/screens/OptionsScreen.cpp
|
||||
client/gui/screens/StartMenuScreen.cpp
|
||||
client/gui/screens/CreateWorldScreen.cpp
|
||||
client/gui/screens/SelectWorldScreen.cpp
|
||||
client/gui/screens/SavingWorldScreen.cpp
|
||||
client/gui/screens/InvalidLicenseScreen.cpp
|
||||
client/gui/screens/ConfirmScreen.cpp
|
||||
client/gui/screens/DeleteWorldScreen.cpp
|
||||
client/gui/screens/ChatScreen.cpp
|
||||
client/gui/screens/RenameMPLevelScreen.cpp
|
||||
client/gui/screens/ProgressScreen.cpp
|
||||
client/gui/screens/JoinGameScreen.cpp
|
||||
client/gui/screens/IngameBlockSelectionScreen.cpp
|
||||
client/gui/screens/PauseScreen.cpp
|
||||
client/gui/components/ScrolledSelectionList.cpp
|
||||
client/gui/components/AvailableGamesList.cpp
|
||||
client/gui/components/RolledSelectionList.cpp
|
||||
client/gui/components/Button.cpp
|
||||
client/gui/components/TextInputBox.cpp
|
||||
client/gui/components/SmallButton.cpp
|
||||
client/gui/components/WorldSelectionList.cpp
|
||||
client/gui/Gui.cpp
|
||||
client/gui/GuiComponent.cpp
|
||||
client/model/PolygonQuad.cpp
|
||||
client/model/Model.cpp
|
||||
client/model/HumanoidModel.cpp
|
||||
client/model/Cube.cpp
|
||||
client/common/Random.cpp
|
||||
client/common/HitResult.cpp
|
||||
client/common/Utils.cpp
|
||||
client/common/PerlinNoise.cpp
|
||||
client/common/ImprovedNoise.cpp
|
||||
client/common/Matrix.cpp
|
||||
client/common/Mth.cpp
|
||||
client/common/Options.cpp
|
||||
client/common/Timer.cpp
|
||||
client/common/Synth.cpp
|
||||
client/common/CThread.cpp
|
||||
client/common/Util.cpp
|
||||
client/common/Vec3.cpp
|
||||
client/common/AABB.cpp
|
||||
client/player/input/ControllerTurnInput.cpp
|
||||
client/player/input/Controller.cpp
|
||||
client/player/input/Mouse.cpp
|
||||
client/player/input/Keyboard.cpp
|
||||
client/player/input/MouseTurnInput.cpp
|
||||
client/player/input/KeyboardInput.cpp
|
||||
client/player/input/ITurnInput.cpp
|
||||
Minecraft.cpp
|
||||
world/gamemode/SurvivalMode.cpp
|
||||
world/gamemode/GameMode.cpp
|
||||
world/gamemode/CreativeMode.cpp
|
||||
world/entity/Mob.cpp
|
||||
world/entity/LocalPlayer.cpp
|
||||
world/entity/Player.cpp
|
||||
world/entity/PrimedTnt.cpp
|
||||
world/entity/Entity.cpp
|
||||
world/entity/FallingTile.cpp
|
||||
world/entity/TripodCamera.cpp
|
||||
world/entity/ItemEntity.cpp
|
||||
world/level/Dimension.cpp
|
||||
world/level/Material.cpp
|
||||
world/level/LevelListener.cpp
|
||||
world/level/TickNextTickData.cpp
|
||||
world/level/Explosion.cpp
|
||||
world/level/storage/LevelStorageSource.cpp
|
||||
world/level/storage/MemoryLevelStorageSource.cpp
|
||||
world/level/storage/LevelData.cpp
|
||||
world/level/storage/ExternalFileLevelStorage.cpp
|
||||
world/level/storage/RegionFile.cpp
|
||||
world/level/storage/LevelStorage.cpp
|
||||
world/level/storage/MemoryLevelStorage.cpp
|
||||
world/level/storage/ChunkStorage.cpp
|
||||
world/level/storage/LevelSource.cpp
|
||||
world/level/storage/MemoryChunkStorage.cpp
|
||||
world/level/storage/ExternalFileLevelStorageSource.cpp
|
||||
world/level/levelgen/feature/BirchFeature.cpp
|
||||
world/level/levelgen/feature/LargeFeature.cpp
|
||||
world/level/levelgen/feature/Feature.cpp
|
||||
world/level/levelgen/feature/LargeCaveFeature.cpp
|
||||
world/level/levelgen/feature/SpringFeature.cpp
|
||||
world/level/levelgen/feature/TreeFeature.cpp
|
||||
world/level/levelgen/feature/PineFeature.cpp
|
||||
world/level/levelgen/feature/ReedsFeature.cpp
|
||||
world/level/levelgen/feature/OreFeature.cpp
|
||||
world/level/levelgen/feature/ClayFeature.cpp
|
||||
world/level/levelgen/feature/FlowerFeature.cpp
|
||||
world/level/levelgen/feature/SpruceFeature.cpp
|
||||
world/level/levelgen/biome/Biome.cpp
|
||||
world/level/levelgen/biome/BiomeSource.cpp
|
||||
world/level/levelgen/chunk/RandomLevelSource.cpp
|
||||
world/level/levelgen/chunk/LevelChunk.cpp
|
||||
world/level/levelgen/chunk/ChunkCache.cpp
|
||||
world/level/levelgen/chunk/ChunkSource.cpp
|
||||
world/level/levelgen/chunk/PerformanceTestChunkSource.cpp
|
||||
world/level/levelgen/chunk/TestChunkSource.cpp
|
||||
world/level/Level.cpp
|
||||
world/level/Region.cpp
|
||||
world/item/TilePlanterItem.cpp
|
||||
world/item/CameraItem.cpp
|
||||
world/item/TileItem.cpp
|
||||
world/item/Inventory.cpp
|
||||
world/item/DoorItem.cpp
|
||||
world/item/ItemInstance.cpp
|
||||
world/item/Item.cpp
|
||||
world/particle/RedDustParticle.cpp
|
||||
world/particle/TerrainParticle.cpp
|
||||
world/particle/BubbleParticle.cpp
|
||||
world/particle/ExplodeParticle.cpp
|
||||
world/particle/ParticleEngine.cpp
|
||||
world/particle/FlameParticle.cpp
|
||||
world/particle/SmokeParticle.cpp
|
||||
world/particle/Particle.cpp
|
||||
world/particle/LavaParticle.cpp
|
||||
world/tile/InvisibleTile.cpp
|
||||
world/tile/Sapling.cpp
|
||||
world/tile/TreeTile.cpp
|
||||
world/tile/GrassTile.cpp
|
||||
world/tile/HalfTransparentTile.cpp
|
||||
world/tile/ClothTile.cpp
|
||||
world/tile/TorchTile.cpp
|
||||
world/tile/MetalTile.cpp
|
||||
world/tile/SpongeTile.cpp
|
||||
world/tile/GlassTile.cpp
|
||||
world/tile/SandTile.cpp
|
||||
world/tile/Tile.cpp
|
||||
world/tile/ClayTile.cpp
|
||||
world/tile/StoneTile.cpp
|
||||
world/tile/LadderTile.cpp
|
||||
world/tile/IceTile.cpp
|
||||
world/tile/TopSnowTile.cpp
|
||||
world/tile/ReedTile.cpp
|
||||
world/tile/Bush.cpp
|
||||
world/tile/RedStoneOreTile.cpp
|
||||
world/tile/DirtTile.cpp
|
||||
world/tile/LiquidTileStatic.cpp
|
||||
world/tile/BookshelfTile.cpp
|
||||
world/tile/TntTile.cpp
|
||||
world/tile/OreTile.cpp
|
||||
world/tile/StairTile.cpp
|
||||
world/tile/SandStoneTile.cpp
|
||||
world/tile/FireTile.cpp
|
||||
world/tile/StoneSlabTile.cpp
|
||||
world/tile/LiquidTile.cpp
|
||||
world/tile/GravelTile.cpp
|
||||
world/tile/LiquidTileDynamic.cpp
|
||||
world/tile/TransparentTile.cpp
|
||||
world/tile/LeafTile.cpp
|
||||
world/tile/ObsidianTile.cpp
|
||||
world/tile/FarmTile.cpp
|
||||
world/tile/DoorTile.cpp
|
||||
App.cpp
|
||||
AppPlatform.cpp
|
||||
)
|
||||
target_include_directories(reminecraftpe-core PUBLIC . ..)
|
||||
|
||||
# RakNet
|
||||
add_subdirectory(../thirdparty/raknet raknet)
|
||||
target_link_libraries(reminecraftpe-core PUBLIC raknet)
|
||||
|
||||
# SDL
|
||||
add_library(SDL INTERFACE)
|
||||
if(EMSCRIPTEN)
|
||||
set(SDL_FLAG -sUSE_SDL=2)
|
||||
target_compile_options(SDL INTERFACE "${SDL_FLAG}")
|
||||
target_link_options(SDL INTERFACE "${SDL_FLAG}")
|
||||
else()
|
||||
find_package(SDL2 REQUIRED)
|
||||
target_link_libraries(SDL INTERFACE SDL2::SDL2)
|
||||
endif()
|
||||
target_link_libraries(reminecraftpe-core PUBLIC SDL)
|
||||
|
||||
# OpenGL
|
||||
if(NOT EMSCRIPTEN)
|
||||
option(USE_GLES1_COMPATIBILITY_LAYER "Whether To Enable The GLESv1_CM Compatibility Layer" TRUE)
|
||||
else()
|
||||
set(USE_GLES1_COMPATIBILITY_LAYER TRUE)
|
||||
endif()
|
||||
if(USE_GLES1_COMPATIBILITY_LAYER)
|
||||
set(GLES_COMPATIBILITY_LAYER_USE_SDL TRUE CACHE BOOL "" FORCE)
|
||||
set(GLES_COMPATIBILITY_LAYER_DEPENDENCY SDL CACHE STRING "" FORCE)
|
||||
add_subdirectory(../thirdparty/gles-compatibility-layer gles-compatibility-layer)
|
||||
target_link_libraries(reminecraftpe-core PUBLIC gles-compatibility-layer)
|
||||
target_compile_definitions(reminecraftpe-core PUBLIC USE_GLES1_COMPATIBILITY_LAYER)
|
||||
if(EMSCRIPTEN)
|
||||
target_link_options(reminecraftpe-core PUBLIC -sMIN_WEBGL_VERSION=2 -sMAX_WEBGL_VERSION=2)
|
||||
endif()
|
||||
else()
|
||||
find_package(OpenGL REQUIRED)
|
||||
target_link_libraries(reminecraftpe-core PUBLIC OpenGL::OpenGL OpenGL::GLU)
|
||||
endif()
|
||||
|
||||
# OpenAL
|
||||
if(EMSCRIPTEN)
|
||||
target_link_libraries(reminecraftpe-core PUBLIC openal)
|
||||
else()
|
||||
find_library(OPENAL_LIBRARY NAMES openal REQUIRED)
|
||||
target_link_libraries(reminecraftpe-core PUBLIC "${OPENAL_LIBRARY}")
|
||||
endif()
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
@@ -48,7 +48,7 @@ Minecraft::Minecraft() : m_gui(this)
|
||||
#else
|
||||
m_pTurnInput = new ControllerTurnInput;
|
||||
#endif
|
||||
|
||||
|
||||
m_pRakNetInstance = new RakNetInstance;
|
||||
|
||||
m_pSoundEngine = new SoundEngine;
|
||||
@@ -59,7 +59,7 @@ int Minecraft::getLicenseId()
|
||||
{
|
||||
if (m_licenseID < 0)
|
||||
m_licenseID = m_pPlatform->checkLicense();
|
||||
|
||||
|
||||
return m_licenseID;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ void Minecraft::grabMouse()
|
||||
{
|
||||
if (m_bGrabbedMouse)
|
||||
return;
|
||||
|
||||
|
||||
m_bGrabbedMouse = true;
|
||||
field_D20 = 0.0f;
|
||||
field_D24 = 0.0f;
|
||||
@@ -91,6 +91,12 @@ void Minecraft::grabMouse()
|
||||
|
||||
void Minecraft::setScreen(Screen* pScreen)
|
||||
{
|
||||
#ifndef ORIGINAL_CODE
|
||||
if (pScreen == nullptr && !isLevelGenerated()) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (m_bUsingScreen)
|
||||
{
|
||||
m_bHasQueuedScreen = true;
|
||||
@@ -396,7 +402,7 @@ void Minecraft::tickInput()
|
||||
{
|
||||
m_gui.handleKeyPressed(keyCode);
|
||||
|
||||
int index = keyCode - '1';
|
||||
int index = keyCode - AKEYCODE_1;
|
||||
if (index <= 8 && index >= 0)
|
||||
{
|
||||
m_pLocalPlayer->m_pInventory->selectSlot(index);
|
||||
@@ -441,7 +447,7 @@ void Minecraft::tickInput()
|
||||
}
|
||||
}
|
||||
|
||||
// @TODO: fix gotos
|
||||
// @TODO: fix gotos
|
||||
bool v12 = false;
|
||||
|
||||
if (m_options.field_19)
|
||||
@@ -484,7 +490,7 @@ void Minecraft::tickMouse()
|
||||
{
|
||||
if (!m_bGrabbedMouse)
|
||||
return;
|
||||
|
||||
|
||||
platform()->recenterMouse();
|
||||
}
|
||||
|
||||
@@ -506,7 +512,7 @@ void Minecraft::tick()
|
||||
field_DA4--;
|
||||
|
||||
tickInput();
|
||||
|
||||
|
||||
m_gui.tick();
|
||||
|
||||
// if the level has been prepared, delete the prep thread
|
||||
@@ -547,8 +553,12 @@ void Minecraft::tick()
|
||||
#ifndef ORIGINAL_CODE
|
||||
if (m_pMobPersp)
|
||||
{
|
||||
#ifdef USE_SDL
|
||||
m_pSoundEngine->m_soundSystem.update(m_pMobPersp->m_pos.x, m_pMobPersp->m_pos.y, m_pMobPersp->m_pos.z, m_pMobPersp->m_yaw);
|
||||
#else
|
||||
m_pSoundEngine->m_soundSystem.setListenerPos(m_pMobPersp->m_pos.x, m_pMobPersp->m_pos.y, m_pMobPersp->m_pos.z);
|
||||
m_pSoundEngine->m_soundSystem.setListenerAngle(m_pMobPersp->m_yaw, m_pMobPersp->m_pitch);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -653,7 +663,7 @@ void Minecraft::prepareLevel(const std::string& unused)
|
||||
|
||||
float startTime = getTimeS();
|
||||
Level* pLevel = m_pLevel;
|
||||
|
||||
|
||||
if (!pLevel->field_B0C)
|
||||
{
|
||||
pLevel->setUpdateLights(0);
|
||||
@@ -769,7 +779,7 @@ void Minecraft::generateLevel(const std::string& unused, Level* pLevel)
|
||||
|
||||
if (m_pLevelRenderer)
|
||||
m_pLevelRenderer->setLevel(pLevel);
|
||||
|
||||
|
||||
if (m_pParticleEngine)
|
||||
m_pParticleEngine->setLevel(pLevel);
|
||||
|
||||
@@ -925,30 +935,38 @@ void Minecraft::leaveGame(bool bCopyMap)
|
||||
|
||||
void Minecraft::hostMultiplayer()
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
m_pRakNetInstance->host(m_pUser->field_0, C_DEFAULT_PORT, C_MAX_CONNECTIONS);
|
||||
m_pNetEventCallback = new ServerSideNetworkHandler(this, m_pRakNetInstance);
|
||||
#endif
|
||||
}
|
||||
|
||||
void Minecraft::joinMultiplayer(const PingedCompatibleServer& serverInfo)
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
if (field_18 && m_pNetEventCallback)
|
||||
{
|
||||
field_18 = false;
|
||||
m_pRakNetInstance->connect(serverInfo.m_address.ToString(), serverInfo.m_address.GetPort());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Minecraft::cancelLocateMultiplayer()
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
field_18 = false;
|
||||
m_pRakNetInstance->stopPingForHosts();
|
||||
delete m_pNetEventCallback;
|
||||
m_pNetEventCallback = nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
void Minecraft::locateMultiplayer()
|
||||
{
|
||||
#ifndef __EMSCRIPTEN__
|
||||
field_18 = true;
|
||||
m_pRakNetInstance->pingForHosts(C_DEFAULT_PORT);
|
||||
m_pNetEventCallback = new ClientSideNetworkHandler(this, m_pRakNetInstance);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
int g_TimeSecondsOnInit = 0;
|
||||
|
||||
#ifndef USE_SDL
|
||||
|
||||
DIR* opendir(const char* name)
|
||||
{
|
||||
size_t len = strlen(name);
|
||||
@@ -97,6 +99,13 @@ void closedir(DIR* dir)
|
||||
free(dir);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#endif
|
||||
|
||||
bool createFolderIfNotExists(const char* pDir)
|
||||
{
|
||||
if (!XPL_ACCESS(pDir, 0))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
@@ -21,6 +21,6 @@ public:
|
||||
void fillGradient(int left, int top, int right, int bottom, int colorUp, int colorDown);
|
||||
|
||||
public:
|
||||
float field_4;
|
||||
float field_4 = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
@@ -30,7 +30,7 @@ void Screen::init(Minecraft* pMinecraft, int a3, int a4)
|
||||
|
||||
void Screen::init()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Screen::buttonClicked(Button* pButton)
|
||||
@@ -65,7 +65,7 @@ bool Screen::isInGameScreen()
|
||||
|
||||
void Screen::keyPressed(int key)
|
||||
{
|
||||
if (key == '\x1B')//escape
|
||||
if (key == AKEYCODE_MENU)//escape
|
||||
{
|
||||
m_pMinecraft->setScreen(nullptr);
|
||||
}
|
||||
|
||||
@@ -128,6 +128,11 @@ void TextInputBox::keyPressed(Minecraft* minecraft, int key)
|
||||
case AKEYCODE_ARROW_RIGHT:
|
||||
chr = '\003';
|
||||
break;
|
||||
#ifdef USE_SDL
|
||||
case AKEYCODE_DEL:
|
||||
chr = '\b';
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
@@ -93,7 +93,7 @@ void StartMenuScreen::init()
|
||||
m_buyButton.m_yPos = yPos;
|
||||
|
||||
m_startButton.m_xPos = (m_width - m_startButton.m_width) / 2;
|
||||
|
||||
|
||||
int x1 = m_width - m_joinButton.m_width;
|
||||
|
||||
m_joinButton.m_xPos = x1 / 2;
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
#include "Controller.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
bool Controller::isTouchedValues[2];
|
||||
float Controller::stickValuesX[2];
|
||||
float Controller::stickValuesY[2];
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "ControllerTurnInput.hpp"
|
||||
#include "Controller.hpp"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
ITurnInput::Delta ControllerTurnInput::getTurnDelta()
|
||||
{
|
||||
bool isTouched = Controller::isTouched(m_stickNo);
|
||||
|
||||
@@ -1,19 +1,28 @@
|
||||
/********************************************************************
|
||||
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 "Keyboard.hpp"
|
||||
|
||||
#include "GameMods.hpp"
|
||||
|
||||
std::vector<Keyboard::Input> Keyboard::_inputs;
|
||||
int Keyboard::_index = -1;
|
||||
int Keyboard::_states[256];
|
||||
int Keyboard::_states[KEYBOARD_STATES_SIZE];
|
||||
|
||||
void Keyboard::feed(int down, int key)
|
||||
{
|
||||
#ifndef ORIGINAL_CODE
|
||||
// Prevent Crashes
|
||||
if (key >= KEYBOARD_STATES_SIZE || key < 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
Input i;
|
||||
i.field_0 = down;
|
||||
i.field_4 = uint8_t(key);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
@@ -9,6 +9,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#define KEYBOARD_STATES_SIZE 256
|
||||
|
||||
class Keyboard
|
||||
{
|
||||
@@ -21,7 +24,7 @@ public:
|
||||
};
|
||||
|
||||
static std::vector<Input> _inputs;
|
||||
static int _states[256];
|
||||
static int _states[KEYBOARD_STATES_SIZE];
|
||||
static int _index;
|
||||
|
||||
// likely inlined
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
@@ -328,7 +328,7 @@ void GameRenderer::setupFog(int i)
|
||||
float GameRenderer::getFov(float f)
|
||||
{
|
||||
Mob* pMob = m_pMinecraft->m_pMobPersp;
|
||||
|
||||
|
||||
float x1 = 70.0f;
|
||||
|
||||
if (pMob->isUnderLiquid(Material::water))
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
@@ -459,14 +459,14 @@ void LevelRenderer::render(Mob* pMob, int a, float b)
|
||||
|
||||
if (!a)
|
||||
field_54 = field_58 = field_5C = field_60 = field_64 = 0;
|
||||
|
||||
|
||||
float mobX1 = pMob->m_pos.x;
|
||||
float mobX2 = pMob->field_98.x + (pMob->m_pos.x - pMob->field_98.x) * b;
|
||||
float mobY1 = pMob->m_pos.y;
|
||||
float mobY2 = pMob->field_98.y + (pMob->m_pos.y - pMob->field_98.y) * b;
|
||||
float mobZ1 = pMob->m_pos.z;
|
||||
float mobZ2 = pMob->field_98.z + (pMob->m_pos.z - pMob->field_98.z) * b;
|
||||
|
||||
|
||||
float dX = pMob->m_pos.x - field_4, dY = pMob->m_pos.y - field_8, dZ = pMob->m_pos.z - field_C;
|
||||
|
||||
if (dX * dX + dY * dY + dZ * dZ > 16.0f)
|
||||
@@ -567,7 +567,8 @@ void LevelRenderer::render(Mob* pMob, int a, float b)
|
||||
|
||||
y3++;
|
||||
y2++;
|
||||
pChunk->field_4E++;
|
||||
//pChunk->field_4E++;
|
||||
pChunk->field_4E = true;
|
||||
if (y3 == x3)
|
||||
goto label_37;
|
||||
}
|
||||
@@ -576,7 +577,7 @@ void LevelRenderer::render(Mob* pMob, int a, float b)
|
||||
label_26:
|
||||
y3++;
|
||||
y2++;
|
||||
|
||||
|
||||
if (y3 == x3)
|
||||
goto label_37;
|
||||
|
||||
@@ -663,7 +664,7 @@ void LevelRenderer::tick()
|
||||
void LevelRenderer::updateDirtyChunks(Mob* pMob, bool b)
|
||||
{
|
||||
// @TODO This updates 16 chunks per frame. Not good.
|
||||
|
||||
|
||||
int updated = 0;
|
||||
for (int i = 0; i < 16 && i < int(field_88.size()); i++)
|
||||
{
|
||||
@@ -1021,7 +1022,7 @@ void LevelRenderer::takePicture(TripodCamera* pCamera, Entity* pOwner)
|
||||
#ifdef ENH_CAMERA_NO_PARTICLES
|
||||
g_bDisableParticles = false;
|
||||
#endif
|
||||
|
||||
|
||||
t_keepPic = -1;
|
||||
|
||||
static char str[256];
|
||||
@@ -1100,7 +1101,7 @@ void LevelRenderer::renderSky(float f)
|
||||
{
|
||||
if (m_pMinecraft->m_pLevel->m_pDimension->field_C)
|
||||
return;
|
||||
|
||||
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
Vec3 skyColor = m_pLevel->getSkyColor(m_pMinecraft->m_pMobPersp, f);
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "RenderList.hpp"
|
||||
#include "Tesselator.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
constexpr int C_MAX_RENDERS = 3072;
|
||||
|
||||
RenderList::RenderList()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
@@ -9,6 +9,8 @@
|
||||
#include "compat/GL.hpp"
|
||||
#include "Tesselator.hpp"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
int dword_2514A4 = 0;
|
||||
|
||||
Tesselator Tesselator::instance;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/********************************************************************
|
||||
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
|
||||
********************************************************************/
|
||||
@@ -69,7 +69,7 @@ int Textures::assignTexture(const std::string& name, Texture& texture)
|
||||
if (texture.field_C)
|
||||
internalFormat = GL_RGBA;
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, texture.m_width, texture.m_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture.m_pixels);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, texture.m_width, texture.m_height, 0, internalFormat, GL_UNSIGNED_BYTE, texture.m_pixels);
|
||||
|
||||
m_textures[name] = textureID;
|
||||
|
||||
|
||||
@@ -63,8 +63,13 @@ void SoundEngine::play(const std::string& name)
|
||||
|
||||
SoundDesc sd;
|
||||
|
||||
if (m_repository.get(name, sd))
|
||||
if (m_repository.get(name, sd)) {
|
||||
#ifdef USE_SDL
|
||||
m_soundSystem.play(sd, 0, 0, 0, 1, 1, true);
|
||||
#else
|
||||
m_soundSystem.playAt(sd, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void SoundEngine::play(const std::string& name, float a, float b, float c, float d, float e)
|
||||
@@ -74,6 +79,11 @@ void SoundEngine::play(const std::string& name, float a, float b, float c, float
|
||||
|
||||
SoundDesc sd;
|
||||
|
||||
if (m_repository.get(name, sd))
|
||||
if (m_repository.get(name, sd)) {
|
||||
#ifdef USE_SDL
|
||||
m_soundSystem.play(sd, a, b, c, d, e, false);
|
||||
#else
|
||||
m_soundSystem.playAt(sd, a, b, c, d, e);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
1
thirdparty/coi-serviceworker
vendored
Submodule
1
thirdparty/coi-serviceworker
vendored
Submodule
Submodule thirdparty/coi-serviceworker added at 34e0bc7458
1
thirdparty/gles-compatibility-layer
vendored
Submodule
1
thirdparty/gles-compatibility-layer
vendored
Submodule
Submodule thirdparty/gles-compatibility-layer added at c6f1947c1b
118
thirdparty/raknet/CMakeLists.txt
vendored
118
thirdparty/raknet/CMakeLists.txt
vendored
@@ -1 +1,117 @@
|
||||
cmake_minimum_required(VERSION 2.6)
|
||||
cmake_minimum_required(VERSION 3.16.0)
|
||||
project(raknet)
|
||||
|
||||
# Build
|
||||
add_library(raknet STATIC
|
||||
VariadicSQLParser.cpp
|
||||
SuperFastHash.cpp
|
||||
VariableListDeltaTracker.cpp
|
||||
StatisticsHistory.cpp
|
||||
SendToThread.cpp
|
||||
SignaledEvent.cpp
|
||||
ReplicaManager3.cpp
|
||||
IncrementalReadInterface.cpp
|
||||
Getche.cpp
|
||||
RakNetSocket2_Berkley_NativeClient.cpp
|
||||
WSAStartupSingleton.cpp
|
||||
DataCompressor.cpp
|
||||
RakMemoryOverride.cpp
|
||||
CommandParserInterface.cpp
|
||||
GetTime.cpp
|
||||
RakNetSocket2_Berkley.cpp
|
||||
PacketOutputWindowLogger.cpp
|
||||
DynDNS.cpp
|
||||
LocklessTypes.cpp
|
||||
UDPForwarder.cpp
|
||||
RakString.cpp
|
||||
SimpleMutex.cpp
|
||||
Itoa.cpp
|
||||
VitaIncludes.cpp
|
||||
TableSerializer.cpp
|
||||
EpochTimeToString.cpp
|
||||
ConnectionGraph2.cpp
|
||||
EmailSender.cpp
|
||||
UDPProxyCoordinator.cpp
|
||||
UDPProxyClient.cpp
|
||||
CloudClient.cpp
|
||||
ReadyEvent.cpp
|
||||
MessageFilter.cpp
|
||||
TCPInterface.cpp
|
||||
PS4Includes.cpp
|
||||
NatPunchthroughClient.cpp
|
||||
RakNetStatistics.cpp
|
||||
PacketConsoleLogger.cpp
|
||||
RakNetSocket2_NativeClient.cpp
|
||||
PacketLogger.cpp
|
||||
Gets.cpp
|
||||
NatPunchthroughServer.cpp
|
||||
FileOperations.cpp
|
||||
CheckSum.cpp
|
||||
HTTPConnection.cpp
|
||||
NatTypeDetectionServer.cpp
|
||||
RakNetSocket.cpp
|
||||
DS_Table.cpp
|
||||
RakNetSocket2.cpp
|
||||
PacketizedTCP.cpp
|
||||
RelayPlugin.cpp
|
||||
ThreadsafePacketLogger.cpp
|
||||
Rand.cpp
|
||||
GridSectorizer.cpp
|
||||
DS_BytePool.cpp
|
||||
FullyConnectedMesh2.cpp
|
||||
SocketLayer.cpp
|
||||
RakWString.cpp
|
||||
UDPProxyServer.cpp
|
||||
StringTable.cpp
|
||||
DR_SHA1.cpp
|
||||
LinuxStrings.cpp
|
||||
VariableDeltaSerializer.cpp
|
||||
CloudServer.cpp
|
||||
RPC4Plugin.cpp
|
||||
PacketFileLogger.cpp
|
||||
CloudCommon.cpp
|
||||
SecureHandshake.cpp
|
||||
FormatString.cpp
|
||||
RakNetSocket2_PS4.cpp
|
||||
DS_ByteQueue.cpp
|
||||
NetworkIDObject.cpp
|
||||
PluginInterface2.cpp
|
||||
RakNetSocket2_WindowsStore8.cpp
|
||||
RandSync.cpp
|
||||
RakPeer.cpp
|
||||
RakNetTransport2.cpp
|
||||
RakNetSocket2_Windows_Linux_360.cpp
|
||||
NatTypeDetectionClient.cpp
|
||||
ConsoleServer.cpp
|
||||
TelnetTransport.cpp
|
||||
Base64Encoder.cpp
|
||||
TeamManager.cpp
|
||||
RakThread.cpp
|
||||
DirectoryDeltaTransfer.cpp
|
||||
CCRakNetSlidingWindow.cpp
|
||||
Router2.cpp
|
||||
StringCompressor.cpp
|
||||
ReliabilityLayer.cpp
|
||||
RakNetSocket2_Vita.cpp
|
||||
NatTypeDetectionCommon.cpp
|
||||
Rackspace.cpp
|
||||
RakNetCommandParser.cpp
|
||||
LogCommandParser.cpp
|
||||
BitStream.cpp
|
||||
HTTPConnection2.cpp
|
||||
RakNetSocket2_Windows_Linux.cpp
|
||||
RakNetTypes.cpp
|
||||
RakNetSocket2_PS3_PS4.cpp
|
||||
FileListTransfer.cpp
|
||||
FileList.cpp
|
||||
TwoWayAuthentication.cpp
|
||||
_FindFirst.cpp
|
||||
DS_HuffmanEncodingTree.cpp
|
||||
gettimeofday.cpp
|
||||
NetworkIDManager.cpp
|
||||
TeamBalancer.cpp
|
||||
CCRakNetUDT.cpp
|
||||
RakNetSocket2_360_720.cpp
|
||||
RakSleep.cpp
|
||||
)
|
||||
target_include_directories(raknet PUBLIC .)
|
||||
|
||||
2
thirdparty/raknet/FileList.cpp
vendored
2
thirdparty/raknet/FileList.cpp
vendored
@@ -20,7 +20,7 @@
|
||||
#include <io.h>
|
||||
|
||||
|
||||
#elif !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ ) && !defined ( __PPC__ ) && !defined ( __FreeBSD__ ) && !defined ( __S3E__ )
|
||||
#elif !defined ( __APPLE__ ) && !defined ( __APPLE_CC__ ) && !defined ( __PPC__ ) && !defined ( __FreeBSD__ ) && !defined ( __S3E__ ) && !defined( __EMSCRIPTEN__ )
|
||||
#include <sys/io.h>
|
||||
#endif
|
||||
|
||||
|
||||
Reference in New Issue
Block a user