Initial build scripts

This commit is contained in:
paradust7 2022-03-30 03:04:49 +00:00
parent 7e3772891a
commit 76e2800c3c
19 changed files with 829 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
minetest/
build/
sources/
install/
www/

30
README.md Normal file
View File

@ -0,0 +1,30 @@
Minetest-wasm
=============
This is an experimental port of Minetest to the web using emscripten/WebAssembly.
System Requirements
-------------------
This has only been tested on Ubuntu 20.04.
* Ubuntu: apt-get install -y build-essential cmake tclsh
Pre-requisites
--------------
The Emscripten SDK (emsdk) must be installed, activated, and in the PATH.
It is assumed to be installed in $HOME/emsdk (edit `common.sh` to change this).
Building
---------
cd minetest-wasm
./build_all.sh
Installation
------------
If the build completes successfully, the www/ directory will contain the entire application. This
includes an `.htaccess` file which sets headers that are required (by browsers) to load the app.
If your webserver does not recognize `.htaccess` files, you may need to set the headers in
another way.

23
build_all.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash -eux
rm -rf build install www
# Emscripten comes with ports for most of these, but they don't compile
# with pthread support. Wipe the cache and build them ourselves.
emcc --clear-cache --clear-ports
# Dependencies
./build_zlib.sh
./build_libjpeg.sh
./build_libpng.sh # uses zlib
./build_libogg.sh
./build_libvorbis.sh # uses ogg
./build_freetype.sh # uses zlib, libpng
./build_zstd.sh
./build_sqlite3.sh
./build_webshims.sh
# Minetest
./pull_minetest.sh
./build_fsroot.sh
./build_minetest.sh

27
build_freetype.sh Executable file
View File

@ -0,0 +1,27 @@
#!/bin/bash -eux
source common.sh
if [ ! -d src/freetype ]; then
pushd sources
git clone https://gitlab.freedesktop.org/freetype/freetype.git freetype
popd
fi
pushd build
rm -rf freetype
mkdir freetype
pushd freetype
emcmake cmake \
-DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" \
-DZLIB_LIBRARY="$INSTALL_DIR/lib/libz.a" \
-DZLIB_INCLUDE_DIR="$INSTALL_DIR/include" \
-DPNG_LIBRARY="$INSTALL_DIR/lib/libpng.a" \
-DPNG_PNG_INCLUDE_DIR="$INSTALL_DIR/include" \
"$SRC_DIR/freetype"
emmake make
emmake make install
echo "freetype OK"

54
build_fsroot.sh Executable file
View File

@ -0,0 +1,54 @@
#!/bin/bash -eux
# Build virtual file system
#
# All the files minetest needs to function correctly.
#
# Shaders, fonts, games, etc
#
# The only source for this seems to be the official distribution.
# There must be a script to build it somewhere, but I haven't found it.
source common.sh
UPSTREAM="https://github.com/minetest/minetest/releases/download/5.5.0/minetest-5.5.0-win64.zip"
ZIPFILE="minetest-5.5.0-win64.zip"
ZIPDIR="minetest-5.5.0-win64"
if [ ! -d "$MINETEST_REPO" ] || [ ! -d "$IRRLICHT_REPO" ; then
echo "Minetest source not found"
exit 1
fi
if [ ! -f sources/"$ZIPFILE" ]; then
pushd sources
wget "$UPSTREAM"
popd
fi
pushd build
rm -rf "$ZIPDIR"
unzip "$SRC_DIR"/"$ZIPFILE"
rm -rf fsroot
mkdir fsroot
mv "$ZIPDIR" fsroot/minetest
pushd fsroot/minetest
# Don't need the Windows exe/dlls
rm -rf bin
# Emscripten strips empty directories. But bin/ needs to be present so that
# realpath() works on relative paths starting with bin/../
mkdir bin
echo "This is here to ensure bin exists" > bin/readme.txt
# Replace these directories with the ones from the source directory
for I in client builtin clientmods games/devtest textures; do
rm -rf "$I"
cp -r "$MINETEST_REPO/$I" "$I"
done
# Copy the irrlicht shaders
cp -r "$IRRLICHT_REPO/media/Shaders" client/shaders/Irrlicht

24
build_libjpeg.sh Executable file
View File

@ -0,0 +1,24 @@
#!/bin/bash -eux
source common.sh
if [ ! -d sources/libjpeg ]; then
pushd sources
git clone "https://github.com/libjpeg-turbo/libjpeg-turbo.git" libjpeg
popd
fi
pushd build
rm -rf libjpeg
mkdir -p libjpeg
pushd libjpeg
emcmake cmake \
-DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" \
-DWITH_SIMD=0 \
"$SRC_DIR/libjpeg"
emmake make
emmake make install
echo "libjpeg OK"

30
build_libogg.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/bash -eux
source common.sh
TARNAME="libogg-1.3.5"
TARBALL="libogg-1.3.5.tar.gz"
if [ ! -f sources/"$TARBALL" ]; then
pushd sources
wget "https://downloads.xiph.org/releases/ogg/$TARBALL"
popd
fi
if ! sha256sum sources/"$TARBALL" | grep -q 0eb4b4b9420a0f51db142ba3f9c64b333f826532dc0f48c6410ae51f4799b664; then
echo "Wrong checksum for $TARNAME"
exit 1
fi
pushd build
rm -rf "$TARNAME"
tar -zxvf "$SRC_DIR/$TARBALL"
pushd "$TARNAME"
emconfigure ./configure --disable-shared --prefix="$INSTALL_DIR"
emmake make
emmake make install
echo "libogg OK"

21
build_libpng.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash -eux
source common.sh
if [ ! -d sources/libpng ]; then
pushd sources
git clone https://git.code.sf.net/p/libpng/code libpng
popd
fi
pushd build
rm -rf libpng
cp -a "$SRC_DIR/libpng" libpng
pushd libpng
# For zlib
export CPPFLAGS="-I${INSTALL_DIR}/include"
export LDFLAGS="-L${INSTALL_DIR}/lib"
emconfigure ./configure --disable-shared --prefix="${INSTALL_DIR}"
emmake make
emmake make install

29
build_libvorbis.sh Executable file
View File

@ -0,0 +1,29 @@
#!/bin/bash -eux
source common.sh
TARNAME="libvorbis-1.3.7"
TARBALL="libvorbis-1.3.7.tar.gz"
if [ ! -f "sources/$TARBALL" ]; then
pushd sources
wget "https://downloads.xiph.org/releases/vorbis/$TARBALL"
popd
fi
if ! sha256sum "sources/$TARBALL" | grep -q 0e982409a9c3fc82ee06e08205b1355e5c6aa4c36bca58146ef399621b0ce5ab; then
echo "Wrong checksum"
exit 1
fi
pushd build
rm -rf "$TARNAME"
tar -zxvf "$SRC_DIR/$TARBALL"
pushd "$TARNAME"
emconfigure ./configure --disable-shared --prefix="$INSTALL_DIR" --with-ogg="$INSTALL_DIR"
emmake make
emmake make install
echo "libvorbis OK"

83
build_minetest.sh Executable file
View File

@ -0,0 +1,83 @@
#!/bin/bash -eux
source common.sh
INCREMENTAL=${INCREMENTAL:-false}
pushd build
if ! $INCREMENTAL; then
rm -rf minetest
fi
mkdir -p minetest
pushd minetest
export EMSDK_EXTRA="-sUSE_SDL=2"
export CFLAGS="$CFLAGS $EMSDK_EXTRA"
export CXXFLAGS="$CXXFLAGS $EMSDK_EXTRA"
export LDFLAGS="$LDFLAGS $EMSDK_EXTRA -sALLOW_MEMORY_GROWTH=1 -sPTHREAD_POOL_SIZE=20 -s EXPORTED_RUNTIME_METHODS=ccall,cwrap -L$INSTALL_DIR/lib -lemsocket"
# Used by CMakeFiles.txt in the webport
export FSROOT_DIR="$BUILD_DIR/fsroot"
# Create a dummy .o file to use as a substitute for the OpenGLES2 / EGL libraries,
# since Emscripten doesn't actually provide those. (the symbols are resolved through
# javascript stubs).
echo > dummy.c
emcc -c dummy.c -o dummy.o
DUMMY_OBJECT="$(pwd)/dummy.o"
if ! $INCREMENTAL; then
emcmake cmake \
-DENABLE_SYSTEM_GMP=OFF \
-DRUN_IN_PLACE=TRUE \
-DENABLE_GLES=TRUE \
-DCMAKE_BUILD_TYPE="$BUILD_KIND" \
-DZLIB_INCLUDE_DIR="$INSTALL_DIR/include" \
-DZLIB_LIBRARY="$INSTALL_DIR/lib/libz.a" \
-DJPEG_INCLUDE_DIR="$INSTALL_DIR/include" \
-DJPEG_LIBRARY="$INSTALL_DIR/lib/libjpeg.a" \
-DPNG_PNG_INCLUDE_DIR="$INSTALL_DIR/include" \
-DPNG_LIBRARY="$INSTALL_DIR/lib/libpng.a" \
-DOGG_INCLUDE_DIR="$INSTALL_DIR/include" \
-DVORBIS_INCLUDE_DIR="$INSTALL_DIR/include" \
-DOGG_LIBRARY="$INSTALL_DIR/lib/libogg.a" \
-DVORBIS_LIBRARY="$INSTALL_DIR/lib/libvorbis.a" \
-DVORBISFILE_LIBRARY="$INSTALL_DIR/lib/libvorbisfile.a" \
-DFREETYPE_LIBRARY="$INSTALL_DIR/lib/libfreetype.a" \
-DFREETYPE_INCLUDE_DIRS="$INSTALL_DIR/include/freetype2" \
-DOPENGLES2_INCLUDE_DIR="$EMSDK_SYSINCLUDE" \
-DOPENGLES2_LIBRARY="$DUMMY_OBJECT" \
-DSQLITE3_LIBRARY="$INSTALL_DIR/lib/libsqlite3.a" \
-DSQLITE3_INCLUDE_DIR="$INSTALL_DIR/include" \
-DZSTD_LIBRARY="$INSTALL_DIR/lib/libzstd.a" \
-DZSTD_INCLUDE_DIR="$INSTALL_DIR/include" \
-DEGL_LIBRARY="$DUMMY_OBJECT" \
-DEGL_INCLUDE_DIR="$EMSDK_SYSINCLUDE" \
-G "Unix Makefiles" \
"$BASE_DIR/minetest"
fi
if $INCREMENTAL; then
emmake make -j1
else
emmake make -j4
fi
echo "Installing into www/"
rm -rf "$WWW_DIR"
mkdir "$WWW_DIR"
FILES="minetest.data minetest.js minetest.wasm minetest.worker.js"
for I in $FILES; do
cp src/"$I" "$WWW_DIR"
done
if [ -f src/minetest.wasm.map ]; then
cp src/minetest.wasm.map "$WWW_DIR"
fi
cp "$BASE_DIR/static/index.html" "$WWW_DIR"
cp "$BASE_DIR/static/.htaccess" "$WWW_DIR"
echo "DONE"

21
build_sqlite3.sh Executable file
View File

@ -0,0 +1,21 @@
#!/bin/bash -eux
source common.sh
if [ ! -f sources/sqlite.tar.gz ]; then
pushd sources
wget "https://www.sqlite.org/src/tarball/sqlite.tar.gz?r=release" -O sqlite.tar.gz
popd
fi
pushd build
rm -rf sqlite
tar -zxvf "$SRC_DIR/sqlite.tar.gz"
pushd sqlite
export BUILD_CC="gcc"
emconfigure ./configure --disable-shared --prefix="$INSTALL_DIR" cross_compiling=yes
emmake make
emmake make install
echo "sqlite3 OK"

20
build_webshims.sh Executable file
View File

@ -0,0 +1,20 @@
#!/bin/bash -eux
source common.sh
if [ ! -d sources/webshims ]; then
pushd sources
git clone "https://github.com/paradust7/webshims.git" webshims
popd
fi
pushd build
rm -rf webshims
mkdir webshims
pushd webshims
emcmake cmake -DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" "$SRC_DIR/webshims"
emmake make
emmake make install
echo "webshims OK"

20
build_zlib.sh Executable file
View File

@ -0,0 +1,20 @@
#!/bin/bash -eux
source common.sh
if [ ! -d sources/zlib ]; then
pushd sources
git clone "https://github.com/madler/zlib.git" zlib
popd
fi
pushd build
rm -rf zlib
cp -a "$SRC_DIR/zlib" zlib
pushd zlib
emconfigure ./configure --static --prefix="$INSTALL_DIR"
emmake make
emmake make install
echo "ZLIB OK"

30
build_zstd.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/bash -eux
source common.sh
if [ ! -d sources/zstd ]; then
pushd sources
git clone https://github.com/facebook/zstd.git zstd
pushd zstd
git checkout v1.5.2
popd
popd
fi
pushd build
rm -rf zstd
mkdir zstd
pushd zstd
export CFLAGS="-D_POSIX_SOURCE=1"
export CXXFLAGS="-D_POSIX_SOURCE=1"
emcmake cmake \
-DCMAKE_INSTALL_PREFIX="$INSTALL_DIR" \
"$SRC_DIR/zstd/build/cmake"
emmake make
emmake make install
echo "zstd OK"

34
common.sh Normal file
View File

@ -0,0 +1,34 @@
BASE_DIR="$(dirname -- "$(readlink -f -- "$0")")"
cd "$BASE_DIR"
mkdir -p sources build install
SRC_DIR="$BASE_DIR/sources"
BUILD_DIR="$BASE_DIR/build"
INSTALL_DIR="$BASE_DIR/install"
WWW_DIR="$BASE_DIR/www"
test -d "$SRC_DIR"
test -d "$BUILD_DIR"
test -d "$INSTALL_DIR"
# Debug / Release
export BUILD_KIND=Release
if [ $BUILD_KIND == Debug ]; then
export BUILD_CFLAGS="-g -gsource-map -O0 --source-map-base=/dev/"
export BUILD_LDFLAGS="-sSAFE_HEAP=1 -sASSERTIONS=2 -sDEMANGLE_SUPPORT=1"
else
export BUILD_CFLAGS="-O2"
export BUILD_LDFLAGS=""
fi
export CFLAGS="$BUILD_CFLAGS -pthread -sUSE_PTHREADS=1 -fexceptions"
export CXXFLAGS="$BUILD_CFLAGS -pthread -sUSE_PTHREADS=1 -fexceptions"
export LDFLAGS="$BUILD_LDFLAGS -pthread -sUSE_PTHREADS=1 -fexceptions -sEXIT_RUNTIME"
export EMSDK_ROOT="$HOME/emsdk"
export EMSDK_SYSLIB="${EMSDK_ROOT}/upstream/emscripten/cache/sysroot/lib/wasm32-emscripten"
export EMSDK_SYSINCLUDE="${EMSDK_ROOT}/upstream/emscripten/cache/sysroot/include"
export MINETEST_REPO="$BASE_DIR/minetest"
export IRRLICHT_REPO="$BASE_DIR/minetest/lib/irrlichtmt"

4
incremental.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/bash -eux
export INCREMENTAL=true
./build_minetest.sh

15
pull_minetest.sh Executable file
View File

@ -0,0 +1,15 @@
#!/bin/bash -eux
source common.sh
# If there's an existing source directory, leave it alone
if [ -d minetest ]; then
exit
fi
git clone -b webport "https://github.com/paradust7/minetest.git"
pushd minetest/lib/
git clone -b webport "https://github.com/paradust7/irrlicht.git" irrlichtmt

2
static/.htaccess Normal file
View File

@ -0,0 +1,2 @@
Header set Cross-Origin-Embedder-Policy "require-corp"
Header set Cross-Origin-Opener-Policy "same-origin"

357
static/index.html Normal file
View File

@ -0,0 +1,357 @@
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Minetest 5.6.0</title>
<style>
body {
font-family: arial;
margin: 0;
padding: none;
background-color: black;
}
.emscripten {
padding-right: 0;
margin-left: auto;
margin-right: auto;
display: block;
}
div.emscripten {
text-align: center;
width: 100%;
}
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
canvas.emscripten {
border: 0px none;
background-color: black;
}
#progress {
height: 20px;
width: 300px;
}
#controls {
display: inline-block;
vertical-align: top;
height: 25px;
}
#output {
width: 100%;
height: 200px;
margin: 0 auto;
margin-top: 0px;
border-left: 0px;
border-right: 0px;
padding-left: 0px;
padding-right: 0px;
display: block;
background-color: black;
color: white;
font-family: 'Lucida Console', Monaco, monospace;
outline: none;
}
.playbutton {
position: absolute;
width: 300px;
height: 120px;
z-index: 10;
font-size: 20pt;
}
</style>
</head>
<body>
<div id="header">
<div class="emscripten">
<span id='controls'>
<span>
<select id="resolution" onchange="fixGeometry()">
<option value="high">High</option>
<option value="medium">Medium</option>
<option value="low">Low</option>
</select>
</span>
<span>
<select id="aspectRatio" onchange="fixGeometry()">
<option value="any">Fit Screen</option>
<option value="4:3">4:3</option>
<option value="16:9">16:9</option>
<option value="5:4">5:4</option>
<option value="21:9">21:9</option>
<option value="32:9">32:9</option>
<option value="1:1">1:1</option>
</select>
</span>
<span><input type="button" value="Toggle Fullscreen" onclick="fullscreen_button()"></span>
<span><input type="button" value="Toggle Console" onclick="toggle_console()"></span>
</span>
</div>
<div class="emscripten">
<progress value="0" max="100" id="progress" hidden=1></progress>
</div>
</div>
<div class="emscripten">
<canvas class="emscripten" id="canvas" oncontextmenu="event.preventDefault()" onclick="doPlay()" tabindex=-1 width="1024" height="600">
</canvas>
</div>
<div id="footer">
<textarea id="output" rows="8" style="display: none;"></textarea>
</div>
<script type='text/javascript'>
var progressElement = document.getElementById('progress');
function toggle_console() {
var element = document.getElementById('output');
element.style.display = (element.style.display == 'block') ? 'none' : 'block';
fixGeometry();
}
var consoleElement = document.getElementById('output');
var enableTracing = false;
var consoleText = [];
var consoleLengthMax = 1000;
var consoleTextLast = 0;
var consoleDirty = false;
var playOK = false;
var didPlay = false;
// Called by the MainLoop when it is ready
function mainloop_ready_to_play() {
drawPlayButton();
playOK = true;
}
var thePlayButton;
function drawPlayButton() {
if (thePlayButton) return;
var canvas = document.getElementById('canvas');
var canvasRect = canvas.getBoundingClientRect();
var midX = Math.floor((canvasRect.top + canvasRect.bottom) / 2);
var midY = Math.floor((canvasRect.left + canvasRect.right) / 2);
thePlayButton = document.createElement('button');
thePlayButton.className = 'playbutton';
thePlayButton.innerText = 'Click to Launch';
thePlayButton.style.left = (midY - 300/2) + 'px';
thePlayButton.style.top = (midX - 120/2) + 'px';
thePlayButton.addEventListener('click', doPlay);
document.body.appendChild(thePlayButton);
}
function doPlay() {
if (thePlayButton) {
thePlayButton.remove();
thePlayButton = null;
}
if (playOK && !didPlay) {
setupWrappers();
didPlay = true;
mainloop_play_wrapped();
// irrlicht initialization resets the width/height
fixGeometry();
}
}
function consoleUpdate() {
if (consoleDirty) {
if (consoleText.length > consoleLengthMax) {
consoleText = consoleText.slice(-consoleLengthMax);
}
consoleElement.value = consoleText.join('');
consoleElement.scrollTop = consoleElement.scrollHeight; // focus on bottom
consoleDirty = false;
}
window.requestAnimationFrame(consoleUpdate);
}
consoleUpdate();
var Module = {
preRun: [],
postRun: [],
print: (function() {
return function(text) {
if (enableTracing) {
console.trace(text);
}
consoleText.push(text + "\n");
consoleDirty = true;
};
})(),
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);
return canvas;
})(),
setStatus: function(text) {
if (!Module.setStatus.last) Module.setStatus.last = { time: Date.now(), text: '' };
if (text === Module.setStatus.last.text) return;
if (text) Module.print('[status] ' + text);
var m = text.match(/([^(]+)\((\d+(\.\d+)?)\/(\d+)\)/);
var now = Date.now();
if (m && now - Module.setStatus.last.time < 30) return; // if this is a progress update, skip it if too soon
Module.setStatus.last.time = now;
Module.setStatus.last.text = text;
if (m) {
text = m[1];
progressElement.value = parseInt(m[2])*100;
progressElement.max = parseInt(m[4])*100;
progressElement.hidden = false;
} else {
progressElement.value = null;
progressElement.max = null;
progressElement.hidden = true;
}
},
totalDependencies: 0,
monitorRunDependencies: function(left) {
this.totalDependencies = Math.max(this.totalDependencies, left);
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
}
};
Module['printErr'] = Module['print'];
Module['onFullScreen'] = () => { fixGeometry(); };
Module.setStatus('Downloading...');
window.onerror = function(event) {
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
Module.print('Exception thrown, see JavaScript console');
Module.setStatus = function(text) {
if (text) Module.print('[status] ' + text);
};
};
var pointerlock_pending = false;
var mainloop_play_wrapped;
var irrlicht_want_pointerlock;
var irrlicht_resize;
function setupWrappers() {
if (!mainloop_play_wrapped || !irrlicht_want_pointerlock || !irrlicht_resize) {
mainloop_play_wrapped = cwrap("mainloop_play");
irrlicht_want_pointerlock = cwrap("irrlicht_want_pointerlock", "number");
irrlicht_resize = cwrap("irrlicht_resize", null, ['number', 'number']);
}
}
function fullscreen_button() {
var canvas = document.getElementById('canvas');
if (playOK) {
setupWrappers();
var alsoLockPointer = irrlicht_want_pointerlock();
// This calls Module['onFullScreen'] when finished, which calls fixGeometry.
Module.requestFullscreen(alsoLockPointer, false);
}
}
function resizeCanvas(width, height) {
var canvas = document.getElementById('canvas');
if (canvas.width != width || canvas.height != height) {
canvas.width = width;
canvas.height = height;
canvas.widthNative = width;
canvas.heightNative = height;
}
// Trigger SDL window resize.
// This should happen automatically, it's disappointing that it doesn't.
if (playOK) {
setupWrappers();
irrlicht_resize(width, height);
}
}
var resolutionSelect = document.getElementById('resolution');
var aspectRatioSelect = document.getElementById('aspectRatio');
function fixGeometry() {
var canvas = document.getElementById('canvas');
var resolution = resolutionSelect.value;
var aspectRatio = aspectRatioSelect.value;
var screenX;
var screenY;
var isFullScreen = document.fullscreenElement ? true : false;
if (isFullScreen) {
screenX = screen.width;
screenY = screen.height;
} else {
var headerHeight = document.getElementById('header').offsetHeight;
var footerHeight = document.getElementById('footer').offsetHeight;
screenX = document.documentElement.clientWidth;
screenY = document.documentElement.clientHeight - headerHeight - footerHeight;
}
// Size of the viewport (after scaling)
var realX;
var realY;
if (aspectRatio == 'any') {
realX = screenX;
realY = screenY;
} else {
var ar = aspectRatio.split(':');
var innerRatio = parseInt(ar[0]) / parseInt(ar[1]);
var outerRatio = screenX / screenY;
if (innerRatio <= outerRatio) {
realX = Math.floor(innerRatio * screenY);
realY = screenY;
} else {
realX = screenX;
realY = Math.floor(screenX / innerRatio);
}
}
// Native canvas resolution
var resX;
var resY;
var scale = false;
if (resolution == 'high') {
resX = realX;
resY = realY;
} else if (resolution == 'medium') {
resX = Math.floor(realX / 1.5);
resY = Math.floor(realY / 1.5);
scale = true;
} else {
resX = Math.floor(realX / 2.0);
resY = Math.floor(realY / 2.0);
scale = true;
}
resizeCanvas(resX, resY);
if (scale) {
var styleWidth = realX + "px";
var styleHeight = realY + "px";
canvas.style.setProperty("width", styleWidth, "important");
canvas.style.setProperty("height", styleHeight, "important");
} else {
canvas.style.removeProperty("width");
canvas.style.removeProperty("height");
}
}
window.addEventListener('resize', fixGeometry);
fixGeometry();
</script>
<script async type="text/javascript" src="minetest.js"></script>
</body>
</html>