Merge branch 'ci-test-jsapi'
This commit is contained in:
BIN
.github/build/web/dev/favicon.ico
vendored
Normal file
BIN
.github/build/web/dev/favicon.ico
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
112
.github/build/web/dev/index.html
vendored
Normal file
112
.github/build/web/dev/index.html
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
<!doctype html>
|
||||
<html lang="en-us">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, minimum-scale=1, maximum-scale=1">
|
||||
<title>Techmino Development</title>
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="stylesheet" type="text/css" href="theme/love.css">
|
||||
<script src="consolewrapper.js"></script>
|
||||
<script src="webdb.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
<div>
|
||||
<h1>Techmino</h1>
|
||||
<canvas id="loadingCanvas" oncontextmenu="event.preventDefault()" width="800" height="600"></canvas>
|
||||
<canvas id="canvas" oncontextmenu="event.preventDefault()"></canvas>
|
||||
</div>
|
||||
</center>
|
||||
|
||||
<script type='text/javascript'>
|
||||
function goFullScreen(){
|
||||
var canvas = document.getElementById("canvas");
|
||||
if(canvas.requestFullScreen)
|
||||
canvas.requestFullScreen();
|
||||
else if(canvas.webkitRequestFullScreen)
|
||||
canvas.webkitRequestFullScreen();
|
||||
else if(canvas.mozRequestFullScreen)
|
||||
canvas.mozRequestFullScreen();
|
||||
}
|
||||
function FullScreenHook(){
|
||||
var canvas = document.getElementById("canvas");
|
||||
canvas.width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
|
||||
canvas.height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
|
||||
}
|
||||
var loadingContext = document.getElementById('loadingCanvas').getContext('2d');
|
||||
function drawLoadingText(text) {
|
||||
var canvas = loadingContext.canvas;
|
||||
|
||||
loadingContext.fillStyle = "rgb(142, 195, 227)";
|
||||
loadingContext.fillRect(0, 0, canvas.scrollWidth, canvas.scrollHeight);
|
||||
|
||||
loadingContext.font = '2em arial';
|
||||
loadingContext.textAlign = 'center'
|
||||
loadingContext.fillStyle = "rgb( 11, 86, 117 )";
|
||||
loadingContext.fillText(text, canvas.scrollWidth / 2, canvas.scrollHeight / 2);
|
||||
|
||||
loadingContext.fillText("Powered By Emscripten.", canvas.scrollWidth / 2, canvas.scrollHeight / 4);
|
||||
loadingContext.fillText("Powered By LÖVE.", canvas.scrollWidth / 2, canvas.scrollHeight / 4 * 3);
|
||||
}
|
||||
|
||||
window.onload = function () { window.focus(); };
|
||||
window.onclick = function () { window.focus(); };
|
||||
|
||||
window.addEventListener("keydown", function(e) {
|
||||
// space and arrow keys
|
||||
if([32, 37, 38, 39, 40].indexOf(e.keyCode) > -1) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}, false);
|
||||
|
||||
var Module = {
|
||||
arguments: ["./game.love"],
|
||||
INITIAL_MEMORY: 128000000,
|
||||
printErr: console.error.bind(console),
|
||||
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 (text) {
|
||||
drawLoadingText(text);
|
||||
} else if (Module.remainingDependencies === 0) {
|
||||
document.getElementById('loadingCanvas').style.display = 'none';
|
||||
document.getElementById('canvas').style.visibility = 'visible';
|
||||
}
|
||||
},
|
||||
totalDependencies: 0,
|
||||
remainingDependencies: 0,
|
||||
monitorRunDependencies: function(left) {
|
||||
this.remainingDependencies = left;
|
||||
this.totalDependencies = Math.max(this.totalDependencies, left);
|
||||
Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.');
|
||||
}
|
||||
};
|
||||
Module.setStatus('Downloading...');
|
||||
window.onerror = function(event) {
|
||||
// TODO: do not warn on ok events like simulating an infinite loop or exitStatus
|
||||
Module.setStatus('Exception thrown, see JavaScript console');
|
||||
Module.setStatus = function(text) {
|
||||
if (text) Module.printErr('[post-exception status] ' + text);
|
||||
};
|
||||
};
|
||||
|
||||
var applicationLoad = function(e) {
|
||||
Love(Module);
|
||||
}
|
||||
</script>
|
||||
<script type="text/javascript" src="game.js"></script>
|
||||
<script async type="text/javascript" src="love.js" onload="applicationLoad(this)"></script>
|
||||
<footer>
|
||||
<p>Built with <a href="https://github.com/Davidobot/love.js">love.js</a> <button onclick="goFullScreen();">Go Fullscreen</button><br>Hint: Reload the page if screen is blank</p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
288
.github/build/web/game.js
vendored
288
.github/build/web/game.js
vendored
@@ -1,288 +0,0 @@
|
||||
|
||||
var Module;
|
||||
|
||||
if (typeof Module === 'undefined') Module = eval('(function() { try { return Module || {} } catch(e) { return {} } })()');
|
||||
|
||||
if (!Module.expectedDataFileDownloads) {
|
||||
Module.expectedDataFileDownloads = 0;
|
||||
Module.finishedDataFileDownloads = 0;
|
||||
}
|
||||
Module.expectedDataFileDownloads++;
|
||||
(function() {
|
||||
var loadPackage = function(metadata) {
|
||||
|
||||
var PACKAGE_PATH;
|
||||
if (typeof window === 'object') {
|
||||
PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/');
|
||||
} else if (typeof location !== 'undefined') {
|
||||
// worker
|
||||
PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/');
|
||||
} else {
|
||||
throw 'using preloaded data can only be done on a web page or in a web worker';
|
||||
}
|
||||
var PACKAGE_NAME = 'game.data';
|
||||
var REMOTE_PACKAGE_BASE = 'game.data';
|
||||
if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) {
|
||||
Module['locateFile'] = Module['locateFilePackage'];
|
||||
Module.printErr('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)');
|
||||
}
|
||||
var REMOTE_PACKAGE_NAME = typeof Module['locateFile'] === 'function' ?
|
||||
Module['locateFile'](REMOTE_PACKAGE_BASE) :
|
||||
((Module['filePackagePrefixURL'] || '') + REMOTE_PACKAGE_BASE);
|
||||
|
||||
var REMOTE_PACKAGE_SIZE = metadata.remote_package_size;
|
||||
var PACKAGE_UUID = metadata.package_uuid;
|
||||
|
||||
function fetchRemotePackage(packageName, packageSize, callback, errback) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', packageName, true);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onprogress = function(event) {
|
||||
var url = packageName;
|
||||
var size = packageSize;
|
||||
if (event.total) size = event.total;
|
||||
if (event.loaded) {
|
||||
if (!xhr.addedTotal) {
|
||||
xhr.addedTotal = true;
|
||||
if (!Module.dataFileDownloads) Module.dataFileDownloads = {};
|
||||
Module.dataFileDownloads[url] = {
|
||||
loaded: event.loaded,
|
||||
total: size
|
||||
};
|
||||
} else {
|
||||
Module.dataFileDownloads[url].loaded = event.loaded;
|
||||
}
|
||||
var total = 0;
|
||||
var loaded = 0;
|
||||
var num = 0;
|
||||
for (var download in Module.dataFileDownloads) {
|
||||
var data = Module.dataFileDownloads[download];
|
||||
total += data.total;
|
||||
loaded += data.loaded;
|
||||
num++;
|
||||
}
|
||||
total = Math.ceil(total * Module.expectedDataFileDownloads/num);
|
||||
if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')');
|
||||
} else if (!Module.dataFileDownloads) {
|
||||
if (Module['setStatus']) Module['setStatus']('Downloading data...');
|
||||
}
|
||||
};
|
||||
xhr.onerror = function(event) {
|
||||
throw new Error("NetworkError for: " + packageName);
|
||||
}
|
||||
xhr.onload = function(event) {
|
||||
if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
|
||||
var packageData = xhr.response;
|
||||
callback(packageData);
|
||||
} else {
|
||||
throw new Error(xhr.statusText + " : " + xhr.responseURL);
|
||||
}
|
||||
};
|
||||
xhr.send(null);
|
||||
};
|
||||
|
||||
function handleError(error) {
|
||||
console.error('package error:', error);
|
||||
};
|
||||
|
||||
function runWithFS() {
|
||||
|
||||
function assert(check, msg) {
|
||||
if (!check) throw msg + new Error().stack;
|
||||
}
|
||||
|
||||
function DataRequest(start, end, crunched, audio) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.crunched = crunched;
|
||||
this.audio = audio;
|
||||
}
|
||||
DataRequest.prototype = {
|
||||
requests: {},
|
||||
open: function(mode, name) {
|
||||
this.name = name;
|
||||
this.requests[name] = this;
|
||||
Module['addRunDependency']('fp ' + this.name);
|
||||
},
|
||||
send: function() {},
|
||||
onload: function() {
|
||||
var byteArray = this.byteArray.subarray(this.start, this.end);
|
||||
|
||||
this.finish(byteArray);
|
||||
|
||||
},
|
||||
finish: function(byteArray) {
|
||||
var that = this;
|
||||
|
||||
Module['FS_createDataFile'](this.name, null, byteArray, true, true, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change
|
||||
Module['removeRunDependency']('fp ' + that.name);
|
||||
|
||||
this.requests[this.name] = null;
|
||||
}
|
||||
};
|
||||
|
||||
var files = metadata.files;
|
||||
for (i = 0; i < files.length; ++i) {
|
||||
new DataRequest(files[i].start, files[i].end, files[i].crunched, files[i].audio).open('GET', files[i].filename);
|
||||
}
|
||||
|
||||
|
||||
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
|
||||
var IDB_RO = "readonly";
|
||||
var IDB_RW = "readwrite";
|
||||
var DB_NAME = "EM_PRELOAD_CACHE";
|
||||
var DB_VERSION = 1;
|
||||
var METADATA_STORE_NAME = 'METADATA';
|
||||
var PACKAGE_STORE_NAME = 'PACKAGES';
|
||||
function openDatabase(callback, errback) {
|
||||
try {
|
||||
var openRequest = indexedDB.open(DB_NAME, DB_VERSION);
|
||||
} catch (e) {
|
||||
return errback(e);
|
||||
}
|
||||
openRequest.onupgradeneeded = function(event) {
|
||||
var db = event.target.result;
|
||||
|
||||
if(db.objectStoreNames.contains(PACKAGE_STORE_NAME)) {
|
||||
db.deleteObjectStore(PACKAGE_STORE_NAME);
|
||||
}
|
||||
var packages = db.createObjectStore(PACKAGE_STORE_NAME);
|
||||
|
||||
if(db.objectStoreNames.contains(METADATA_STORE_NAME)) {
|
||||
db.deleteObjectStore(METADATA_STORE_NAME);
|
||||
}
|
||||
var metadata = db.createObjectStore(METADATA_STORE_NAME);
|
||||
};
|
||||
openRequest.onsuccess = function(event) {
|
||||
var db = event.target.result;
|
||||
callback(db);
|
||||
};
|
||||
openRequest.onerror = function(error) {
|
||||
errback(error);
|
||||
};
|
||||
};
|
||||
|
||||
/* Check if there's a cached package, and if so whether it's the latest available */
|
||||
function checkCachedPackage(db, packageName, callback, errback) {
|
||||
var transaction = db.transaction([METADATA_STORE_NAME], IDB_RO);
|
||||
var metadata = transaction.objectStore(METADATA_STORE_NAME);
|
||||
|
||||
var getRequest = metadata.get("metadata/" + packageName);
|
||||
getRequest.onsuccess = function(event) {
|
||||
var result = event.target.result;
|
||||
if (!result) {
|
||||
return callback(false);
|
||||
} else {
|
||||
return callback(PACKAGE_UUID === result.uuid);
|
||||
}
|
||||
};
|
||||
getRequest.onerror = function(error) {
|
||||
errback(error);
|
||||
};
|
||||
};
|
||||
|
||||
function fetchCachedPackage(db, packageName, callback, errback) {
|
||||
var transaction = db.transaction([PACKAGE_STORE_NAME], IDB_RO);
|
||||
var packages = transaction.objectStore(PACKAGE_STORE_NAME);
|
||||
|
||||
var getRequest = packages.get("package/" + packageName);
|
||||
getRequest.onsuccess = function(event) {
|
||||
var result = event.target.result;
|
||||
callback(result);
|
||||
};
|
||||
getRequest.onerror = function(error) {
|
||||
errback(error);
|
||||
};
|
||||
};
|
||||
|
||||
function cacheRemotePackage(db, packageName, packageData, packageMeta, callback, errback) {
|
||||
var transaction_packages = db.transaction([PACKAGE_STORE_NAME], IDB_RW);
|
||||
var packages = transaction_packages.objectStore(PACKAGE_STORE_NAME);
|
||||
|
||||
var putPackageRequest = packages.put(packageData, "package/" + packageName);
|
||||
putPackageRequest.onsuccess = function(event) {
|
||||
var transaction_metadata = db.transaction([METADATA_STORE_NAME], IDB_RW);
|
||||
var metadata = transaction_metadata.objectStore(METADATA_STORE_NAME);
|
||||
var putMetadataRequest = metadata.put(packageMeta, "metadata/" + packageName);
|
||||
putMetadataRequest.onsuccess = function(event) {
|
||||
callback(packageData);
|
||||
};
|
||||
putMetadataRequest.onerror = function(error) {
|
||||
errback(error);
|
||||
};
|
||||
};
|
||||
putPackageRequest.onerror = function(error) {
|
||||
errback(error);
|
||||
};
|
||||
};
|
||||
|
||||
function processPackageData(arrayBuffer) {
|
||||
Module.finishedDataFileDownloads++;
|
||||
assert(arrayBuffer, 'Loading data file failed.');
|
||||
assert(arrayBuffer instanceof ArrayBuffer, 'bad input to processPackageData');
|
||||
var byteArray = new Uint8Array(arrayBuffer);
|
||||
var curr;
|
||||
|
||||
// copy the entire loaded file into a spot in the heap. Files will refer to slices in that. They cannot be freed though
|
||||
// (we may be allocating before malloc is ready, during startup).
|
||||
if (Module['SPLIT_MEMORY']) Module.printErr('warning: you should run the file packager with --no-heap-copy when SPLIT_MEMORY is used, otherwise copying into the heap may fail due to the splitting');
|
||||
var ptr = Module['getMemory'](byteArray.length);
|
||||
Module['HEAPU8'].set(byteArray, ptr);
|
||||
DataRequest.prototype.byteArray = Module['HEAPU8'].subarray(ptr, ptr+byteArray.length);
|
||||
|
||||
var files = metadata.files;
|
||||
for (i = 0; i < files.length; ++i) {
|
||||
DataRequest.prototype.requests[files[i].filename].onload();
|
||||
}
|
||||
Module['removeRunDependency']('datafile_game.data');
|
||||
|
||||
};
|
||||
Module['addRunDependency']('datafile_game.data');
|
||||
|
||||
if (!Module.preloadResults) Module.preloadResults = {};
|
||||
|
||||
function preloadFallback(error) {
|
||||
console.error(error);
|
||||
console.error('falling back to default preload behavior');
|
||||
fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, processPackageData, handleError);
|
||||
};
|
||||
|
||||
openDatabase(
|
||||
function(db) {
|
||||
checkCachedPackage(db, PACKAGE_PATH + PACKAGE_NAME,
|
||||
function(useCached) {
|
||||
Module.preloadResults[PACKAGE_NAME] = {fromCache: useCached};
|
||||
if (useCached) {
|
||||
console.info('loading ' + PACKAGE_NAME + ' from cache');
|
||||
fetchCachedPackage(db, PACKAGE_PATH + PACKAGE_NAME, processPackageData, preloadFallback);
|
||||
} else {
|
||||
console.info('loading ' + PACKAGE_NAME + ' from remote');
|
||||
fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE,
|
||||
function(packageData) {
|
||||
cacheRemotePackage(db, PACKAGE_PATH + PACKAGE_NAME, packageData, {uuid:PACKAGE_UUID}, processPackageData,
|
||||
function(error) {
|
||||
console.error(error);
|
||||
processPackageData(packageData);
|
||||
});
|
||||
}
|
||||
, preloadFallback);
|
||||
}
|
||||
}
|
||||
, preloadFallback);
|
||||
}
|
||||
, preloadFallback);
|
||||
|
||||
if (Module['setStatus']) Module['setStatus']('Downloading...');
|
||||
|
||||
}
|
||||
if (Module['calledRun']) {
|
||||
runWithFS();
|
||||
} else {
|
||||
if (!Module['preRun']) Module['preRun'] = [];
|
||||
Module["preRun"].push(runWithFS); // FS is not initialized yet, wait for it
|
||||
}
|
||||
|
||||
}
|
||||
loadPackage({"package_uuid":"80826f15-f924-4428-a8c4-e984743417c6","remote_package_size":62246034,"files":[{"filename":"/game.love","crunched":0,"start":0,"end":62246034,"audio":false}]});
|
||||
|
||||
})();
|
||||
22
.github/build/web/love.js
vendored
22
.github/build/web/love.js
vendored
File diff suppressed because one or more lines are too long
BIN
.github/build/web/love.wasm
vendored
BIN
.github/build/web/love.wasm
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 305 KiB After Width: | Height: | Size: 305 KiB |
@@ -5,9 +5,10 @@
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, minimum-scale=1, maximum-scale=1">
|
||||
<title>Techmino</title>
|
||||
|
||||
<!-- Load custom style sheet -->
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||
<link rel="stylesheet" type="text/css" href="theme/love.css">
|
||||
<script src="consolewrapper.js"></script>
|
||||
<script src="webdb.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<center>
|
||||
@@ -61,7 +62,7 @@
|
||||
|
||||
var Module = {
|
||||
arguments: ["./game.love"],
|
||||
INITIAL_MEMORY: 536870912,
|
||||
INITIAL_MEMORY: 128000000,
|
||||
printErr: console.error.bind(console),
|
||||
canvas: (function() {
|
||||
var canvas = document.getElementById('canvas');
|
||||
BIN
.github/build/web/theme/bg.png
vendored
BIN
.github/build/web/theme/bg.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 7.0 KiB |
49
.github/build/web/theme/love.css
vendored
49
.github/build/web/theme/love.css
vendored
@@ -1,49 +0,0 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-family: arial;
|
||||
color: rgb( 11, 86, 117 );
|
||||
}
|
||||
|
||||
body {
|
||||
background-image: url(bg.png);
|
||||
background-repeat: no-repeat;
|
||||
font-family: arial;
|
||||
margin: 0;
|
||||
padding: none;
|
||||
background-color: rgb( 154, 205, 237 );
|
||||
color: rgb( 28, 78, 104 );
|
||||
}
|
||||
|
||||
footer {
|
||||
font-family: arial;
|
||||
font-size: 12px;
|
||||
padding-left: 10px;
|
||||
position:absolute;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* Links */
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
a:link {
|
||||
color: rgb( 233, 73, 154 );
|
||||
}
|
||||
a:visited {
|
||||
color: rgb( 110, 30, 71 );
|
||||
}
|
||||
a:hover {
|
||||
color: rgb( 252, 207, 230 );
|
||||
}
|
||||
|
||||
/* the canvas *must not* have any border or padding, or mouse coords will be wrong */
|
||||
#canvas {
|
||||
padding-right: 0;
|
||||
display: block;
|
||||
border: 0px none;
|
||||
visibility: hidden;
|
||||
}
|
||||
95
.github/workflows/main.yml
vendored
95
.github/workflows/main.yml
vendored
@@ -136,35 +136,36 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Love actions for testing
|
||||
uses: love-actions/love-actions-test@v1
|
||||
with:
|
||||
font-path: ./parts/fonts/proportional.otf
|
||||
language-folder: ./parts/language
|
||||
- name: Download core love package
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||
- name: Download love
|
||||
shell: bash
|
||||
run: |
|
||||
curl -OL --retry 5 https://github.com/love2d/love/releases/download/11.4/love-11.4-x86_64.AppImage
|
||||
chmod +x love-11.4-x86_64.AppImage
|
||||
- name: Prepare PulseAudio and AppImage
|
||||
shell: bash
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install pulseaudio pulseaudio-utils pavucontrol alsa-oss alsa-utils libfuse2 -y
|
||||
- name: Run automated test
|
||||
uses: coactions/setup-xvfb@v1
|
||||
with:
|
||||
run: |
|
||||
./love-11.4-x86_64.AppImage ${{ env.CORE_LOVE_PACKAGE_PATH }} --test
|
||||
# - name: Love actions for testing
|
||||
# uses: love-actions/love-actions-test@v1
|
||||
# with:
|
||||
# font-path: ./parts/fonts/proportional.otf
|
||||
# language-folder: ./parts/language
|
||||
# - name: Download core love package
|
||||
# uses: actions/download-artifact@v3
|
||||
# with:
|
||||
# name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||
# - name: Download love
|
||||
# shell: bash
|
||||
# run: |
|
||||
# curl -OL --retry 5 https://github.com/love2d/love/releases/download/11.4/love-11.4-x86_64.AppImage
|
||||
# chmod +x love-11.4-x86_64.AppImage
|
||||
# - name: Prepare PulseAudio and AppImage
|
||||
# shell: bash
|
||||
# run: |
|
||||
# sudo apt-get update
|
||||
# sudo apt-get install pulseaudio pulseaudio-utils pavucontrol alsa-oss alsa-utils libfuse2 -y
|
||||
# - name: Run automated test
|
||||
# uses: coactions/setup-xvfb@v1
|
||||
# with:
|
||||
# run: |
|
||||
# ./love-11.4-x86_64.AppImage ${{ env.CORE_LOVE_PACKAGE_PATH }} --test
|
||||
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: github.event_name != 'pull_request'
|
||||
# if: github.event_name != 'pull_request'
|
||||
if: ${{ !always()}}
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
@@ -237,6 +238,7 @@ jobs:
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: ${{ !always()}}
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
@@ -320,7 +322,8 @@ jobs:
|
||||
build-macos-portable:
|
||||
runs-on: macos-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
if: github.event_name != 'pull_request'
|
||||
# if: github.event_name != 'pull_request'
|
||||
if: ${{ !always()}}
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
RELEASE_FOLDER: ./release
|
||||
@@ -423,6 +426,9 @@ jobs:
|
||||
build-web:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [get-info, build-core, auto-test]
|
||||
env:
|
||||
MEMORY_LIMIT: 128000000
|
||||
OUTPUT_FOLDER: ./build
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
@@ -431,25 +437,38 @@ jobs:
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||
- name: Move core love package
|
||||
- name: Build web packages
|
||||
run: |
|
||||
mv ${{ env.CORE_LOVE_PACKAGE_PATH }} ./.github/build/web/game.data
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: crazy-max/ghaction-github-pages@v3
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
build_dir: ./.github/build/web/
|
||||
keep_history: false
|
||||
target_branch: web-dev
|
||||
npx love.js ${{ env.CORE_LOVE_PACKAGE_PATH }} ${{ env.OUTPUT_FOLDER }} -t "${{ needs.get-info.outputs.app-name }}" -m ${{ env.MEMORY_LIMIT }} -c
|
||||
- name: Move assets
|
||||
run: |
|
||||
mv ./.github/build/web/${{ env.BUILD_TYPE }}/* ${{ env.OUTPUT_FOLDER }}
|
||||
- name: Initialize Love.js Api Player
|
||||
run: |
|
||||
pushd ${{ env.OUTPUT_FOLDER }}
|
||||
wget https://raw.githubusercontent.com/MrcSnm/Love.js-Api-Player/refs/heads/master/consolewrapper.js
|
||||
wget https://raw.githubusercontent.com/MrcSnm/Love.js-Api-Player/refs/heads/master/globalizeFS.js
|
||||
wget https://raw.githubusercontent.com/MrcSnm/Love.js-Api-Player/refs/heads/master/webdb.js
|
||||
node globalizeFS.js
|
||||
rm globalizeFS.js
|
||||
popd
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: ${{ needs.get-info.outputs.base-name }}_Web_PWA
|
||||
path: ./.github/build/web/
|
||||
name: ${{ needs.get-info.outputs.base-name }}_Web
|
||||
path: ${{ env.OUTPUT_FOLDER }}
|
||||
- name: Deploy to GitHub Pages
|
||||
uses: crazy-max/ghaction-github-pages@v4
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
build_dir: ${{ env.OUTPUT_FOLDER }}
|
||||
keep_history: false
|
||||
target_branch: gh-pages
|
||||
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
if: ${{ !always()}}
|
||||
needs: [get-info, build-core, auto-test]
|
||||
env:
|
||||
OUTPUT_FOLDER: ./build
|
||||
|
||||
103
Zframework/clipboard.lua
Normal file
103
Zframework/clipboard.lua
Normal file
@@ -0,0 +1,103 @@
|
||||
local function _sanitize(content)
|
||||
if type(content)=='boolean' then
|
||||
content=content and 'true' or 'false'
|
||||
end
|
||||
if type(content)=='nil' then
|
||||
content=''
|
||||
end
|
||||
if type(content)=='number' then
|
||||
content=tostring(content)
|
||||
end
|
||||
if type(content)~='string' then
|
||||
MES.new('error',"Invalid content type!")
|
||||
MES.traceback()
|
||||
return ''
|
||||
end
|
||||
return content
|
||||
end
|
||||
|
||||
if SYSTEM~='Web' then
|
||||
local get=love.system.getClipboardText
|
||||
local set=love.system.setClipboardText
|
||||
return {
|
||||
get=function() return get() or '' end,
|
||||
set=function(content) set(_sanitize(content)) end,
|
||||
setFreshInterval=NULL,
|
||||
_update=NULL,
|
||||
}
|
||||
end
|
||||
|
||||
if WEB_COMPAT_MODE then
|
||||
local _clipboardBuffer=''
|
||||
return {
|
||||
get=function()
|
||||
JS.newPromiseRequest(
|
||||
JS.stringFunc(
|
||||
[[
|
||||
window.navigator.clipboard
|
||||
.readText()
|
||||
.then((text) => _$_(text))
|
||||
.catch((e) => {
|
||||
console.warn(e);
|
||||
_$_('');
|
||||
});
|
||||
]]
|
||||
),
|
||||
function(data) _clipboardBuffer=data end,
|
||||
function() _clipboardBuffer='' end,
|
||||
3,
|
||||
'getClipboardText'
|
||||
)
|
||||
if TASK.lock('clipboard_compat_interval',2.6) then
|
||||
_clipboardBuffer=''
|
||||
MES.new('warn',"Web-Compat mode, paste again to confirm",2.6)
|
||||
end
|
||||
return _clipboardBuffer
|
||||
end,
|
||||
set=function(str)
|
||||
JS.callJS(JS.stringFunc(
|
||||
[[
|
||||
window.navigator.clipboard
|
||||
.writeText('%s')
|
||||
.then(() => console.log('Copied to clipboard'))
|
||||
.catch((e) => console.warn(e));
|
||||
]],
|
||||
_sanitize(str)
|
||||
))
|
||||
end,
|
||||
setFreshInterval=NULL,
|
||||
_update=NULL,
|
||||
}
|
||||
end
|
||||
|
||||
local getCHN=love.thread.getChannel('CLIP_get')
|
||||
local setCHN=love.thread.getChannel('CLIP_set')
|
||||
local trigCHN=love.thread.getChannel('CLIP_trig')
|
||||
|
||||
local clipboard_thread=love.thread.newThread('Zframework/clipboard_thread.lua')
|
||||
local isStarted,errorMessage=clipboard_thread:start()
|
||||
|
||||
if not isStarted then
|
||||
MES.new("error",errorMessage,26)
|
||||
end
|
||||
|
||||
local freshInterval=1
|
||||
local timer=-.626
|
||||
return {
|
||||
get=function() return getCHN:peek() or '' end,
|
||||
set=function(content) setCHN:push(_sanitize(content)) end,
|
||||
setFreshInterval=function(val)
|
||||
freshInterval=val
|
||||
end,
|
||||
_update=function(dt)
|
||||
timer=timer+dt
|
||||
if timer>freshInterval then
|
||||
if isStarted and not clipboard_thread:isRunning() then
|
||||
MES.new("warn",clipboard_thread:getError(),26)
|
||||
isStarted=false
|
||||
end
|
||||
trigCHN:push(timer)
|
||||
timer=0
|
||||
end
|
||||
end,
|
||||
}
|
||||
48
Zframework/clipboard_thread.lua
Normal file
48
Zframework/clipboard_thread.lua
Normal file
@@ -0,0 +1,48 @@
|
||||
local getCHN=love.thread.getChannel('CLIP_get')
|
||||
local setCHN=love.thread.getChannel('CLIP_set')
|
||||
local trigCHN=love.thread.getChannel('CLIP_trig')
|
||||
|
||||
JS=require'Zframework.js'
|
||||
local sleep=require'love.timer'.sleep
|
||||
|
||||
local retrieving=false
|
||||
while true do
|
||||
if trigCHN:getCount()>0 then
|
||||
local dt = trigCHN:pop()
|
||||
if setCHN:getCount()>0 then
|
||||
while setCHN:getCount()>1 do setCHN:pop() end
|
||||
-- Set Clipboard
|
||||
JS.callJS(JS.stringFunc(
|
||||
[[
|
||||
window.navigator.clipboard
|
||||
.writeText('%s')
|
||||
.then(() => console.log('Copied to clipboard'))
|
||||
.catch((e) => console.warn(e));
|
||||
]],
|
||||
setCHN:pop()
|
||||
))
|
||||
end
|
||||
-- Get Clipboard
|
||||
if not retrieving then
|
||||
JS.newPromiseRequest(
|
||||
JS.stringFunc[[
|
||||
window.navigator.clipboard
|
||||
.readText()
|
||||
.then((text) => _$_(text))
|
||||
.catch((e)=>{});
|
||||
]],
|
||||
function(data)
|
||||
while getCHN:getCount()>0 do getCHN:pop() end
|
||||
getCHN:push(data)
|
||||
retrieving=false
|
||||
end,
|
||||
function() retrieving=false end,
|
||||
1,
|
||||
'getClipboardText'
|
||||
)
|
||||
retrieving=true
|
||||
end
|
||||
JS.retrieveData(dt)
|
||||
end
|
||||
sleep(.001)
|
||||
end
|
||||
@@ -1,5 +1,5 @@
|
||||
local sendCHN=love.thread.getChannel('inputChannel')
|
||||
local recvCHN=love.thread.getChannel('outputChannel')
|
||||
local sendCHN=love.thread.getChannel('HTTP_inputChannel')
|
||||
local recvCHN=love.thread.getChannel('HTTP_outputChannel')
|
||||
|
||||
local threads={}
|
||||
local threadCount=0
|
||||
@@ -9,11 +9,15 @@ local threadCode=[[
|
||||
local http=require'socket.http'
|
||||
local ltn12=require'ltn12'
|
||||
|
||||
local sendCHN=love.thread.getChannel('inputChannel')
|
||||
local recvCHN=love.thread.getChannel('outputChannel')
|
||||
local sendCHN=love.thread.getChannel('HTTP_inputChannel')
|
||||
local recvCHN=love.thread.getChannel('HTTP_outputChannel')
|
||||
local sleep=require'love.timer'.sleep
|
||||
|
||||
while true do
|
||||
local arg=sendCHN:demand()
|
||||
-- local arg=sendCHN:demand()
|
||||
-- Warning: workaround for love.js
|
||||
while sendCHN:getCount()==0 do sleep(.0626) end
|
||||
local arg=sendCHN:pop()
|
||||
|
||||
if arg._destroy then
|
||||
recvCHN:push{
|
||||
|
||||
@@ -3,8 +3,24 @@
|
||||
NONE={}function NULL() end PAPER=love.graphics.newCanvas(1,1)
|
||||
EDITING=""
|
||||
LOADED=false
|
||||
|
||||
--[[
|
||||
Available SYSTEM values:
|
||||
Android
|
||||
iOS
|
||||
Linux
|
||||
macOS
|
||||
Web
|
||||
Windows
|
||||
]]--
|
||||
SYSTEM=love.system.getOS()
|
||||
if SYSTEM=='OS X' then SYSTEM='macOS' end
|
||||
WEB_COMPAT_MODE=false
|
||||
if SYSTEM=='OS X' then
|
||||
SYSTEM='macOS'
|
||||
elseif SYSTEM=='Web' then
|
||||
WEB_COMPAT_MODE=not love.thread.newThread('\n'):start()
|
||||
print('Web compatible mode: ', WEB_COMPAT_MODE)
|
||||
end
|
||||
|
||||
-- Bit module
|
||||
local success
|
||||
@@ -72,6 +88,7 @@ do
|
||||
end
|
||||
|
||||
-- Love-based modules (basic)
|
||||
CLIPBOARD= require'Zframework.clipboard'
|
||||
HTTP= require'Zframework.http'
|
||||
WS= require'Zframework.websocket'
|
||||
FILE= require'Zframework.file'
|
||||
@@ -94,6 +111,10 @@ IMG= require'Zframework.image'
|
||||
BGM= require'Zframework.bgm'
|
||||
VOC= require'Zframework.voice'
|
||||
|
||||
if SYSTEM=='Web' then
|
||||
JS=require'Zframework.js'
|
||||
end
|
||||
|
||||
local ms,kb=love.mouse,love.keyboard
|
||||
local KBisDown=kb.isDown
|
||||
|
||||
@@ -174,6 +195,7 @@ local function updatePowerInfo()
|
||||
gc_pop()
|
||||
gc.setCanvas()
|
||||
end
|
||||
|
||||
-------------------------------------------------------------
|
||||
local lastX,lastY=0,0-- Last click pos
|
||||
local function _updateMousePos(x,y,dx,dy)
|
||||
@@ -423,38 +445,38 @@ local dPadToKey={
|
||||
start='return',
|
||||
back='escape',
|
||||
}
|
||||
function love.joystickadded(JS)
|
||||
function love.joystickadded(joystick)
|
||||
table.insert(jsState,{
|
||||
_id=JS:getID(),
|
||||
_jsObj=JS,
|
||||
_id=joystick:getID(),
|
||||
_jsObj=joystick,
|
||||
leftx=0,lefty=0,
|
||||
rightx=0,righty=0,
|
||||
triggerleft=0,triggerright=0
|
||||
})
|
||||
MES.new('info',"Joystick added")
|
||||
end
|
||||
function love.joystickremoved(JS)
|
||||
function love.joystickremoved(joystick)
|
||||
for i=1,#jsState do
|
||||
if jsState[i]._jsObj==JS then
|
||||
if jsState[i]._jsObj==joystick then
|
||||
for j=1,#gamePadKeys do
|
||||
if JS:isGamepadDown(gamePadKeys[j]) then
|
||||
love.gamepadreleased(JS,gamePadKeys[j])
|
||||
if joystick:isGamepadDown(gamePadKeys[j]) then
|
||||
love.gamepadreleased(joystick,gamePadKeys[j])
|
||||
end
|
||||
end
|
||||
love.gamepadaxis(JS,'leftx',0)
|
||||
love.gamepadaxis(JS,'lefty',0)
|
||||
love.gamepadaxis(JS,'rightx',0)
|
||||
love.gamepadaxis(JS,'righty',0)
|
||||
love.gamepadaxis(JS,'triggerleft',-1)
|
||||
love.gamepadaxis(JS,'triggerright',-1)
|
||||
love.gamepadaxis(joystick,'leftx',0)
|
||||
love.gamepadaxis(joystick,'lefty',0)
|
||||
love.gamepadaxis(joystick,'rightx',0)
|
||||
love.gamepadaxis(joystick,'righty',0)
|
||||
love.gamepadaxis(joystick,'triggerleft',-1)
|
||||
love.gamepadaxis(joystick,'triggerright',-1)
|
||||
MES.new('info',"Joystick removed")
|
||||
table.remove(jsState,i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
function love.gamepadaxis(JS,axis,val)
|
||||
if jsState[1] and JS==jsState[1]._jsObj then
|
||||
function love.gamepadaxis(joystick,axis,val)
|
||||
if jsState[1] and joystick==jsState[1]._jsObj then
|
||||
local js=jsState[1]
|
||||
if axis=='leftx' or axis=='lefty' or axis=='rightx' or axis=='righty' then
|
||||
local newVal=-- range: [0,1]
|
||||
@@ -463,14 +485,14 @@ function love.gamepadaxis(JS,axis,val)
|
||||
0
|
||||
if newVal~=js[axis] then
|
||||
if js[axis]==-1 then
|
||||
love.gamepadreleased(JS,jsAxisEventName[axis][1])
|
||||
love.gamepadreleased(joystick,jsAxisEventName[axis][1])
|
||||
elseif js[axis]~=0 then
|
||||
love.gamepadreleased(JS,jsAxisEventName[axis][2])
|
||||
love.gamepadreleased(joystick,jsAxisEventName[axis][2])
|
||||
end
|
||||
if newVal==-1 then
|
||||
love.gamepadpressed(JS,jsAxisEventName[axis][1])
|
||||
love.gamepadpressed(joystick,jsAxisEventName[axis][1])
|
||||
elseif newVal==1 then
|
||||
love.gamepadpressed(JS,jsAxisEventName[axis][2])
|
||||
love.gamepadpressed(joystick,jsAxisEventName[axis][2])
|
||||
end
|
||||
js[axis]=newVal
|
||||
end
|
||||
@@ -478,9 +500,9 @@ function love.gamepadaxis(JS,axis,val)
|
||||
local newVal=val>.3 and 1 or 0-- range: [0,1]
|
||||
if newVal~=js[axis] then
|
||||
if newVal==1 then
|
||||
love.gamepadpressed(JS,jsAxisEventName[axis])
|
||||
love.gamepadpressed(joystick,jsAxisEventName[axis])
|
||||
else
|
||||
love.gamepadreleased(JS,jsAxisEventName[axis])
|
||||
love.gamepadreleased(joystick,jsAxisEventName[axis])
|
||||
end
|
||||
js[axis]=newVal
|
||||
end
|
||||
@@ -720,6 +742,10 @@ function love.run()
|
||||
|
||||
-- UPDATE
|
||||
STEP()
|
||||
if SYSTEM == 'Web' then
|
||||
JS.retrieveData(dt)
|
||||
CLIPBOARD._update(dt)
|
||||
end
|
||||
if mouseShow then mouse_update(dt) end
|
||||
if next(jsState) then gp_update(jsState[1],dt) end
|
||||
VOC.update()
|
||||
|
||||
148
Zframework/js.lua
Normal file
148
Zframework/js.lua
Normal file
@@ -0,0 +1,148 @@
|
||||
local __requestQueue={}
|
||||
local _requestCount=0
|
||||
local _Request=
|
||||
{
|
||||
command="",
|
||||
currentTime=0,
|
||||
timeOut=2,
|
||||
id='0',
|
||||
}
|
||||
local __defaultErrorFunction=nil
|
||||
local isDebugActive=false
|
||||
|
||||
local JS={}
|
||||
|
||||
function JS.callJS(funcToCall)
|
||||
print("callJavascriptFunction "..funcToCall)
|
||||
end
|
||||
|
||||
--You can pass a set of commands here and, it is a syntactic sugar for executing many commands inside callJS, as it only calls a function
|
||||
--If you pass arguments to the func beyond the string, it will perform automatically string.format
|
||||
--Return statement is possible inside this structure
|
||||
--This will return a string containing a function to be called by JS.callJS
|
||||
function JS.stringFunc(str,...)
|
||||
str="(function(){"..str.."})()"
|
||||
if (#arg>0) then
|
||||
str=str:format(unpack(arg))
|
||||
end
|
||||
str=str:gsub("[\n\t]", "")
|
||||
return str
|
||||
end
|
||||
|
||||
--The call will store in the webDB the return value from the function passed
|
||||
--it timeouts
|
||||
local function retrieveJS(funcToCall,filename)
|
||||
--Used for retrieveData function
|
||||
JS.callJS(("FS.writeFile('%s/%s',%s);"):format(love.filesystem.getSaveDirectory(),filename,funcToCall))
|
||||
end
|
||||
|
||||
--Call JS.newRequest instead
|
||||
function _Request:new(isPromise,command,onDataLoaded,onError,timeout,id)
|
||||
local obj={}
|
||||
setmetatable(obj, self)
|
||||
obj.command=command
|
||||
obj.onError=onError or __defaultErrorFunction
|
||||
if not isPromise then
|
||||
retrieveJS(command, self.filename)
|
||||
else
|
||||
JS.callJS(command)
|
||||
end
|
||||
obj.onDataLoaded=onDataLoaded
|
||||
obj.timeOut=(timeout==nil) and obj.timeOut or timeout
|
||||
obj.id=id
|
||||
obj.filename="__temp"..id
|
||||
|
||||
|
||||
function obj:getData()
|
||||
--Try to read from webdb
|
||||
if love.filesystem.getInfo(self.filename) then
|
||||
return love.filesystem.read(self.filename)
|
||||
end
|
||||
end
|
||||
|
||||
function obj:purgeData()
|
||||
--Data must be purged for not allowing old data to be retrieved
|
||||
love.filesystem.remove(self.filename)
|
||||
end
|
||||
|
||||
function obj:update(dt)
|
||||
self.timeOut=self.timeOut-dt
|
||||
local retData=self:getData()
|
||||
|
||||
if ((retData~=nil and retData~="nil") or self.timeOut<=0) then
|
||||
if (retData~=nil and retData:match("ERROR")==nil) then
|
||||
if isDebugActive then
|
||||
print("Data has been retrieved "..retData)
|
||||
end
|
||||
self.onDataLoaded(retData)
|
||||
else
|
||||
self.onError(self.id, retData)
|
||||
end
|
||||
self:purgeData()
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
return obj
|
||||
end
|
||||
|
||||
--Place this function on love.update and set it to return if it returns false (This API is synchronous)
|
||||
function JS.retrieveData(dt)
|
||||
local isRetrieving=#__requestQueue~=0
|
||||
local deadRequests={}
|
||||
for i=1,#__requestQueue do
|
||||
local isUpdating=__requestQueue[i]:update(dt)
|
||||
if not isUpdating then
|
||||
table.insert(deadRequests, i)
|
||||
end
|
||||
end
|
||||
for i=1,#deadRequests do
|
||||
if (isDebugActive) then
|
||||
print("Request died: "..deadRequests[i])
|
||||
end
|
||||
table.remove(__requestQueue, deadRequests[i])
|
||||
end
|
||||
return isRetrieving
|
||||
end
|
||||
|
||||
--May only be used for functions that don't return a promise
|
||||
function JS.newRequest(funcToCall,onDataLoaded,onError,timeout,optionalId)
|
||||
table.insert(__requestQueue, _Request:new(false, funcToCall, onDataLoaded, onError, timeout or 5, optionalId or _requestCount))
|
||||
end
|
||||
|
||||
--This function can be handled manually (in JS code)
|
||||
--How to: add the function call when your events resolve: FS.writeFile("Put love.filesystem.getSaveDirectory here", "Pass a string here (NUMBER DONT WORK"))
|
||||
--Or it can be handled by Lua, it auto sets your data if you write the following command:
|
||||
-- _$_(yourStringOrFunctionHere)
|
||||
function JS.newPromiseRequest(funcToCall,onDataLoaded,onError,timeout,optionalId)
|
||||
optionalId=optionalId or _requestCount
|
||||
funcToCall=funcToCall:gsub("_$_%(", "FS.writeFile('"..love.filesystem.getSaveDirectory().."/__temp"..optionalId.."', ")
|
||||
table.insert(__requestQueue, _Request:new(true, funcToCall, onDataLoaded, onError, timeout or 5, optionalId))
|
||||
end
|
||||
|
||||
|
||||
--It receives the ID from ther request
|
||||
--Don't try printing the request.command, as it will execute the javascript command
|
||||
function JS.setDefaultErrorFunction(func)
|
||||
__defaultErrorFunction=func
|
||||
end
|
||||
|
||||
JS.setDefaultErrorFunction(function(id,error)
|
||||
if (isDebugActive) then
|
||||
local msg="Data could not be loaded for id:'"..id.."'"
|
||||
if (error) then
|
||||
msg=msg.."\nError: "..error
|
||||
end
|
||||
print(msg)
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
JS.callJS(JS.stringFunc(
|
||||
[[
|
||||
__getWebDB("%s");
|
||||
]]
|
||||
, "__LuaJSDB"))
|
||||
|
||||
return JS
|
||||
@@ -140,7 +140,7 @@ function profile.switch()
|
||||
switch=not switch
|
||||
if not switch then
|
||||
profile.stop()
|
||||
love.system.setClipboardText(profile.report())
|
||||
CLIPBOARD.set(profile.report())
|
||||
profile.reset()
|
||||
return false
|
||||
else
|
||||
|
||||
@@ -189,7 +189,7 @@ do-- functions to shorted big numbers
|
||||
function STRING.bigInt(t)
|
||||
if t<1000 then
|
||||
return tostring(t)
|
||||
elseif t~=1e999 then
|
||||
elseif t~=1/0 then
|
||||
local e=floorint(lg(t)/3)
|
||||
return(t/10^(e*3))..units[e+1]
|
||||
else
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
---@type love.Channel,love.Channel,love.Channel
|
||||
local triggerCHN,sendCHN,readCHN=...
|
||||
|
||||
local CHN_demand,CHN_getCount=triggerCHN.demand,triggerCHN.getCount
|
||||
@@ -5,13 +6,16 @@ local CHN_push,CHN_pop=triggerCHN.push,triggerCHN.pop
|
||||
|
||||
local SOCK=require'socket'.tcp()
|
||||
local JSON=require'Zframework.json'
|
||||
local sleep=require'love.timer'.sleep
|
||||
|
||||
do-- Connect
|
||||
local host=CHN_demand(sendCHN)
|
||||
local port=CHN_demand(sendCHN)
|
||||
local path=CHN_demand(sendCHN)
|
||||
local head=CHN_demand(sendCHN)
|
||||
local timeout=CHN_demand(sendCHN)
|
||||
-- Warning: workaround for love.js, used to use CHN_demand instead
|
||||
while CHN_getCount(sendCHN)<5 do sleep(.0626) end
|
||||
local host=CHN_pop(sendCHN)
|
||||
local port=CHN_pop(sendCHN)
|
||||
local path=CHN_pop(sendCHN)
|
||||
local head=CHN_pop(sendCHN)
|
||||
local timeout=CHN_pop(sendCHN)
|
||||
|
||||
SOCK:settimeout(timeout)
|
||||
local res,err=SOCK:connect(host,port)
|
||||
@@ -186,7 +190,8 @@ end)
|
||||
local success,err
|
||||
|
||||
while true do-- Running
|
||||
CHN_demand(triggerCHN)
|
||||
while CHN_getCount(triggerCHN)==0 do sleep(.0626) end
|
||||
CHN_pop(triggerCHN)
|
||||
success,err=pcall(sendThread)
|
||||
if not success or err then break end
|
||||
success,err=pcall(readThread)
|
||||
|
||||
10
conf.lua
10
conf.lua
@@ -1,9 +1,9 @@
|
||||
local OS=love._os
|
||||
if OS=='OS X' then OS='macOS' end
|
||||
MOBILE=OS=='Android' or OS=='iOS'
|
||||
FNNS=OS:find'\79\83' -- What does FNSF stand for? IDK so don't ask me lol
|
||||
local system=love._os
|
||||
if system=='OS X' then system='macOS' end
|
||||
MOBILE=system=='Android' or system=='iOS'
|
||||
FNNS=system:find'\79\83' -- What does FNSF stand for? IDK so don't ask me lol
|
||||
|
||||
if OS=='Web' then
|
||||
if system=='Web' then
|
||||
local oldRead=love.filesystem.read
|
||||
function love.filesystem.read(name,size)
|
||||
if love.filesystem.getInfo(name) then
|
||||
|
||||
4
main.lua
4
main.lua
@@ -49,6 +49,10 @@ SCR.setSize(1280,720) -- Initialize Screen size
|
||||
BGM.setMaxSources(5)
|
||||
VOC.setDiversion(.62)
|
||||
|
||||
if SYSTEM == 'Web' and not WEB_COMPAT_MODE then
|
||||
CLIPBOARD.setFreshInterval(.5)
|
||||
end
|
||||
|
||||
WIDGET.setOnChange(function()
|
||||
if SCN.cur=='net_game' or SCN.cur=='custom_field' then return end
|
||||
local colorList=THEME.getThemeColor()
|
||||
|
||||
@@ -330,20 +330,20 @@ local L={
|
||||
},
|
||||
cards={-- F0300 - F070F
|
||||
cardBack= 0xF0300,
|
||||
clubA= 0xF0301,
|
||||
club2= 0xF0302,
|
||||
club3= 0xF0303,
|
||||
club4= 0xF0304,
|
||||
club5= 0xF0305,
|
||||
club6= 0xF0306,
|
||||
club7= 0xF0307,
|
||||
club8= 0xF0308,
|
||||
club9= 0xF0309,
|
||||
club10= 0xF030A,
|
||||
clubJ= 0xF030B,
|
||||
clubC= 0xF030C,
|
||||
clubQ= 0xF030D,
|
||||
clubK= 0xF030E,
|
||||
spadeA= 0xF0301,
|
||||
spade2= 0xF0302,
|
||||
spade3= 0xF0303,
|
||||
spade4= 0xF0304,
|
||||
spade5= 0xF0305,
|
||||
spade6= 0xF0306,
|
||||
spade7= 0xF0307,
|
||||
spade8= 0xF0308,
|
||||
spade9= 0xF0309,
|
||||
spade10= 0xF030A,
|
||||
spadeJ= 0xF030B,
|
||||
spadeC= 0xF030C,
|
||||
spadeQ= 0xF030D,
|
||||
spadeK= 0xF030E,
|
||||
heartA= 0xF0401,
|
||||
heart2= 0xF0402,
|
||||
heart3= 0xF0403,
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
if SYSTEM=='Web' then
|
||||
return {
|
||||
update=NULL
|
||||
}
|
||||
end
|
||||
|
||||
local appId='1288557386700951554'
|
||||
|
||||
local ffi=require"ffi"
|
||||
|
||||
@@ -949,16 +949,16 @@ end
|
||||
|
||||
local combKey={
|
||||
x=function()
|
||||
love.system.setClipboardText(inputBox:getText())
|
||||
CLIPBOARD.set(inputBox:getText())
|
||||
inputBox:clear()
|
||||
SFX.play('reach')
|
||||
end,
|
||||
c=function()
|
||||
love.system.setClipboardText(inputBox:getText())
|
||||
CLIPBOARD.set(inputBox:getText())
|
||||
SFX.play('reach')
|
||||
end,
|
||||
v=function()
|
||||
inputBox:addText(love.system.getClipboardText())
|
||||
inputBox:addText(CLIPBOARD.get())
|
||||
SFX.play('reach')
|
||||
end,
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ function scene.update(dt)
|
||||
end
|
||||
ct=ct-1
|
||||
if ct==0 then
|
||||
local t=love.system.getClipboardText()
|
||||
local t=CLIPBOARD.get()
|
||||
if type(t)=='string' then
|
||||
t=t:lower():match("^s=(%d+)$")
|
||||
t=t and tonumber(t) and tonumber(t)>0 and tonumber(t)<=8000 and floor(tonumber(t))
|
||||
|
||||
@@ -181,7 +181,7 @@ function reset()
|
||||
time=0
|
||||
score=0
|
||||
|
||||
local t=love.system.getClipboardText()
|
||||
local t=CLIPBOARD.get()
|
||||
if type(t)=='string' then
|
||||
t=t:lower():match("^s=(.+)")
|
||||
t=t and tonumber(t) and tonumber(t)*2
|
||||
|
||||
@@ -188,10 +188,10 @@ function scene.keyDown(key,isRep)
|
||||
if #CUSTOMGAME_LOCAL.bag>0 then str=str..DATA.copySequence(CUSTOMGAME_LOCAL.bag) end
|
||||
str=str.."!"
|
||||
if #CUSTOMGAME_LOCAL.mission>0 then str=str..DATA.copyMission(CUSTOMGAME_LOCAL.mission) end
|
||||
sys.setClipboardText(str.."!"..DATA.copyBoards(CUSTOMGAME_LOCAL.field).."!")
|
||||
CLIPBOARD.set(str.."!"..DATA.copyBoards(CUSTOMGAME_LOCAL.field).."!")
|
||||
MES.new('check',text.exportSuccess)
|
||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
||||
local str=sys.getClipboardText()
|
||||
local str=CLIPBOARD.get()
|
||||
local args=str:sub((str:find(":") or 0)+1):split("!")
|
||||
local hasTooHighField=false
|
||||
repeat
|
||||
|
||||
@@ -226,10 +226,10 @@ function scene.keyDown(key)
|
||||
SFX.play('clear_4',.8)
|
||||
SFX.play('fall',.8)
|
||||
elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then
|
||||
sys.setClipboardText("Techmino Field:"..DATA.copyBoard(FIELD[page]))
|
||||
CLIPBOARD.set("Techmino Field:"..DATA.copyBoard(FIELD[page]))
|
||||
MES.new('check',text.exportSuccess)
|
||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
||||
local str=sys.getClipboardText()
|
||||
local str=CLIPBOARD.get()
|
||||
local p=str:find(":")-- ptr*
|
||||
if p then
|
||||
if not str:sub(1,p-1):find("Field") then
|
||||
|
||||
@@ -68,11 +68,11 @@ function scene.keyDown(key)
|
||||
end
|
||||
elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then
|
||||
if #MISSION>0 then
|
||||
sys.setClipboardText("Techmino Target:"..DATA.copyMission(MISSION))
|
||||
CLIPBOARD.set("Techmino Target:"..DATA.copyMission(MISSION))
|
||||
MES.new('check',text.exportSuccess)
|
||||
end
|
||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
||||
local str=sys.getClipboardText()
|
||||
local str=CLIPBOARD.get()
|
||||
local p=str:find(":")-- ptr*
|
||||
if p then
|
||||
if not str:sub(1,p-1):find("Target") then
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
local sys=love.system
|
||||
local kb=love.keyboard
|
||||
|
||||
local sin=math.sin
|
||||
@@ -76,11 +75,11 @@ function scene.keyDown(key)
|
||||
scene.widgetList.sequence:scroll(kb.isDown('lshift','rshift') and -1 or 1)
|
||||
elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then
|
||||
if #BAG>0 then
|
||||
sys.setClipboardText("Techmino SEQ:"..DATA.copySequence(BAG))
|
||||
CLIPBOARD.set("Techmino SEQ:"..DATA.copySequence(BAG))
|
||||
MES.new('check',text.exportSuccess)
|
||||
end
|
||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
||||
local str=sys.getClipboardText()
|
||||
local str=CLIPBOARD.get()
|
||||
local p=str:find(":")-- ptr*
|
||||
if p then
|
||||
if not str:sub(1,p-1):find("SEQ") then
|
||||
|
||||
@@ -124,7 +124,7 @@ end
|
||||
local function _copy()
|
||||
local t=_getList()[listBox.selected]
|
||||
t=t.title_Org..":\n"..t.content_Org..(t.url and "\n[ "..t.url.." ]\n" or "\n")..text.dictNote
|
||||
love.system.setClipboardText(t)
|
||||
CLIPBOARD.set(t)
|
||||
scene.widgetList.copy.hide=true
|
||||
MES.new('info',text.copyDone)
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@ local function _submit()
|
||||
end
|
||||
end
|
||||
local function _paste()
|
||||
local t=love.system.getClipboardText()
|
||||
local t=CLIPBOARD.get()
|
||||
if t then
|
||||
t=STRING.trim(t)
|
||||
if #t==128 and t:match("[0-9A-Z]+") then
|
||||
|
||||
@@ -97,7 +97,7 @@ function scene.keyDown(key)
|
||||
if rep.available and rep.fileName then
|
||||
local repStr=loadFile(rep.fileName,'-string')
|
||||
if repStr then
|
||||
love.system.setClipboardText(love.data.encode('string','base64',repStr))
|
||||
CLIPBOARD.set(love.data.encode('string','base64',repStr))
|
||||
MES.new('info',text.exportSuccess)
|
||||
else
|
||||
MES.new('error',text.replayBroken)
|
||||
@@ -107,7 +107,7 @@ function scene.keyDown(key)
|
||||
end
|
||||
end
|
||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
||||
local repStr=love.system.getClipboardText()
|
||||
local repStr=CLIPBOARD.get()
|
||||
local res,fileData=pcall(love.data.decode,'string','base64',repStr)
|
||||
if res then
|
||||
local fileName=os.date("replay/%Y_%m_%d_%H%M%S_import.rep")
|
||||
|
||||
@@ -15,7 +15,7 @@ local function _setPW()
|
||||
end
|
||||
end
|
||||
local function _paste()
|
||||
local t=love.system.getClipboardText()
|
||||
local t=CLIPBOARD.get()
|
||||
if t then
|
||||
t=STRING.trim(t)
|
||||
if #t==8 and t:match("[0-9]+") then
|
||||
|
||||
@@ -7,12 +7,12 @@ function scene.enter()
|
||||
end
|
||||
|
||||
local function _dumpCB(T)
|
||||
love.system.setClipboardText(STRING.packText(TABLE.dump(T)))
|
||||
CLIPBOARD.set(STRING.packText(TABLE.dump(T)))
|
||||
MES.new('check',text.exportSuccess)
|
||||
end
|
||||
local function _parseCB()
|
||||
local _
|
||||
local s=love.system.getClipboardText()
|
||||
local s=CLIPBOARD.get()
|
||||
|
||||
-- Decode
|
||||
s=STRING.unpackText(s)
|
||||
|
||||
@@ -136,7 +136,7 @@ scene.widgetList={
|
||||
},
|
||||
WIDGET.newKey{name='bg_custom_base64',x=1010,y=1502.5,w=420,h=135,align='M',
|
||||
code=function()
|
||||
local okay,data=pcall(love.data.decode,"data","base64",love.system.getClipboardText())
|
||||
local okay,data=pcall(love.data.decode,"data","base64",CLIPBOARD.get())
|
||||
if okay and pcall(gc.newImage,data) then
|
||||
love.filesystem.write('conf/customBG',data)
|
||||
SETTING.bg='custom'
|
||||
|
||||
@@ -164,7 +164,7 @@ scene.widgetList={
|
||||
textBox,
|
||||
WIDGET.newButton {name='home',x=1140,y= 90,w=170,h=80,sound='click',font=60,fText=CHAR.key.macHome,code=pressKey('home')},
|
||||
WIDGET.newButton {name='endd',x=1140,y=190,w=170,h=80,sound='click',font=60,fText=CHAR.key.macEnd ,code=pressKey('end')},
|
||||
WIDGET.newButton {name='copy',x=1140,y=290,w=170,h=80,sound='click',font=60,fText=CHAR.icon.copy ,code=function()love.system.setClipboardText(table.concat(textBox.texts,'\n'))end,color='lC'},
|
||||
WIDGET.newButton {name='copy',x=1140,y=290,w=170,h=80,sound='click',font=60,fText=CHAR.icon.copy ,code=function()CLIPBOARD.set(table.concat(textBox.texts,'\n'))end,color='lC'},
|
||||
|
||||
logList,
|
||||
|
||||
|
||||
Reference in New Issue
Block a user