Compare commits
108 Commits
Vietnamese
...
mod-patch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6903c89d9 | ||
|
|
2226aa2e6b | ||
|
|
12ae789239 | ||
|
|
2d7d02d5c9 | ||
|
|
64ddb09060 | ||
|
|
0203bfa805 | ||
|
|
c974db8c1c | ||
|
|
8559b5e565 | ||
|
|
201ec079d6 | ||
|
|
f6e7e993f5 | ||
|
|
ff6a99999b | ||
|
|
35aacc1a3e | ||
|
|
59903397a7 | ||
|
|
ca39c0ddf3 | ||
|
|
6e6e1034b4 | ||
|
|
01efc218bf | ||
|
|
b4b602ae9d | ||
|
|
bd395b2775 | ||
|
|
bf36bfb02b | ||
|
|
4bbf77b217 | ||
|
|
486e88e7bc | ||
|
|
46396efd09 | ||
|
|
57d42a84a4 | ||
|
|
eb7e20d157 | ||
|
|
725e8b35bd | ||
|
|
17a8181822 | ||
|
|
6c40fb098f | ||
|
|
785935d26f | ||
|
|
f2e064e900 | ||
|
|
2e537807a7 | ||
|
|
f4e04b32dd | ||
|
|
e1255e6124 | ||
|
|
37993c1669 | ||
|
|
2fa653fffe | ||
|
|
77fd519b43 | ||
|
|
017f874f38 | ||
|
|
c642bd3857 | ||
|
|
bc831220b4 | ||
|
|
b50147cace | ||
|
|
eb3b8c9e9d | ||
|
|
9ddab37232 | ||
|
|
cec7914c8f | ||
|
|
b19a83ac23 | ||
|
|
1905960b51 | ||
|
|
68a806aa3e | ||
|
|
b555c44b8b | ||
|
|
d0c503e096 | ||
|
|
9ec2182252 | ||
|
|
881d43c56d | ||
|
|
8a663e29a6 | ||
|
|
7ae19b6431 | ||
|
|
081b77f0e1 | ||
|
|
b4a9766d14 | ||
|
|
c33614a9cc | ||
|
|
ae37fde4b9 | ||
|
|
64a86b260a | ||
|
|
59cd9347c2 | ||
|
|
0281d28a72 | ||
|
|
e517e6c65b | ||
|
|
95283b6fc7 | ||
|
|
1ed2cd468e | ||
|
|
eaba1cd0ab | ||
|
|
421e74e357 | ||
|
|
6eba788236 | ||
|
|
d041461f0a | ||
|
|
13b277b35a | ||
|
|
fc703f241c | ||
|
|
271769c502 | ||
|
|
387bbfaf69 | ||
|
|
44ff5e8ee1 | ||
|
|
378d88cff0 | ||
|
|
58648f7cdb | ||
|
|
c143e8eee5 | ||
|
|
519687a718 | ||
|
|
d399f3c9d3 | ||
|
|
97b1abb5b5 | ||
|
|
4928f1964c | ||
|
|
9c47e95d19 | ||
|
|
c20e4ac845 | ||
|
|
f2686fb5bd | ||
|
|
888f2f6074 | ||
|
|
536174220d | ||
|
|
dc8488ff61 | ||
|
|
3cda61b48d | ||
|
|
d61372c041 | ||
|
|
2816a76f5a | ||
|
|
65c050f6df | ||
|
|
898539cab9 | ||
|
|
d09f5b0176 | ||
|
|
6594b4a238 | ||
|
|
70558e82db | ||
|
|
766b32b1b4 | ||
|
|
869135a10c | ||
|
|
3825b7ccbf | ||
|
|
68733170a3 | ||
|
|
2cd330ffa6 | ||
|
|
f0a45b8b32 | ||
|
|
4c3abc454a | ||
|
|
72d5e46056 | ||
|
|
c47ddf2900 | ||
|
|
1117b5390c | ||
|
|
b8ec5df9dc | ||
|
|
47fc75bae8 | ||
|
|
e6f416eee3 | ||
|
|
8252f85720 | ||
|
|
77232885b6 | ||
|
|
b3ca43fa69 | ||
|
|
478eb0774f |
32
.github/actions/get-cc/action.yml
vendored
32
.github/actions/get-cc/action.yml
vendored
@@ -1,32 +0,0 @@
|
|||||||
name: 'get cc'
|
|
||||||
description: 'download cc into specific dir'
|
|
||||||
inputs:
|
|
||||||
tag:
|
|
||||||
required: false
|
|
||||||
default: "11.4.2"
|
|
||||||
platform:
|
|
||||||
required: true
|
|
||||||
dir:
|
|
||||||
required: false
|
|
||||||
default: '.'
|
|
||||||
repo:
|
|
||||||
required: false
|
|
||||||
default: 26F-Studio/cold_clear_ai_love2d_wrapper
|
|
||||||
temp-file:
|
|
||||||
required: false
|
|
||||||
default: temp.zip
|
|
||||||
runs:
|
|
||||||
using: "composite"
|
|
||||||
steps:
|
|
||||||
- run: |
|
|
||||||
echo "tag="$(if [ -z "${{ inputs.tag }}" ]
|
|
||||||
then curl -w '%{url_effective}' -I -L -s -S https://github.com/${{ inputs.repo }}/releases/latest -o /dev/null | grep -o '\<[^/]*$'
|
|
||||||
else echo ${{ inputs.tag }}
|
|
||||||
fi) >> $GITHUB_OUTPUT
|
|
||||||
id: get-tag
|
|
||||||
shell: bash
|
|
||||||
- uses: ./.github/actions/get-unzip
|
|
||||||
with:
|
|
||||||
url: https://github.com/${{ inputs.repo }}/releases/download/${{ steps.get-tag.outputs.tag }}/${{ inputs.platform }}.zip
|
|
||||||
dir: ${{ inputs.dir }}
|
|
||||||
temp-file: ${{ inputs.temp-file }}
|
|
||||||
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 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">
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, minimum-scale=1, maximum-scale=1">
|
||||||
<title>Techmino</title>
|
<title>Techmino</title>
|
||||||
|
<link rel="icon" type="image/x-icon" href="favicon.ico">
|
||||||
<!-- Load custom style sheet -->
|
|
||||||
<link rel="stylesheet" type="text/css" href="theme/love.css">
|
<link rel="stylesheet" type="text/css" href="theme/love.css">
|
||||||
|
<script src="consolewrapper.js"></script>
|
||||||
|
<script src="webdb.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<center>
|
<center>
|
||||||
@@ -61,7 +62,7 @@
|
|||||||
|
|
||||||
var Module = {
|
var Module = {
|
||||||
arguments: ["./game.love"],
|
arguments: ["./game.love"],
|
||||||
INITIAL_MEMORY: 536870912,
|
INITIAL_MEMORY: 128000000,
|
||||||
printErr: console.error.bind(console),
|
printErr: console.error.bind(console),
|
||||||
canvas: (function() {
|
canvas: (function() {
|
||||||
var canvas = document.getElementById('canvas');
|
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;
|
|
||||||
}
|
|
||||||
323
.github/workflows/main.yml
vendored
323
.github/workflows/main.yml
vendored
@@ -8,9 +8,11 @@ on:
|
|||||||
branches: [main]
|
branches: [main]
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
BUILD_ASSETS_FOLDER: ./.github/build
|
||||||
BUILD_TYPE: ${{ fromJSON('["dev", "release"]')[startsWith(github.ref, 'refs/tags/v')] }}
|
BUILD_TYPE: ${{ fromJSON('["dev", "release"]')[startsWith(github.ref, 'refs/tags/v')] }}
|
||||||
CORE_LOVE_PACKAGE_PATH: ./core.love
|
COLD_CLEAR_DOWNLOAD_URL: https://github.com/26F-Studio/cold_clear_ai_love2d_wrapper/releases/download/11.5
|
||||||
CORE_LOVE_ARTIFACT_NAME: core_love_package
|
CORE_LOVE_ARTIFACT_NAME: core_love_package
|
||||||
|
CORE_LOVE_PACKAGE_PATH: ./core.love
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
get-info:
|
get-info:
|
||||||
@@ -25,7 +27,7 @@ jobs:
|
|||||||
commit-hash: ${{ steps.git-info.outputs.commit-hash }}
|
commit-hash: ${{ steps.git-info.outputs.commit-hash }}
|
||||||
base-name: ${{ steps.assemble-base-name.outputs.base-name }}
|
base-name: ${{ steps.assemble-base-name.outputs.base-name }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- name: Install lua
|
- name: Install lua
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get install lua5.3 -y
|
sudo apt-get install lua5.3 -y
|
||||||
@@ -73,7 +75,7 @@ jobs:
|
|||||||
OUTPUT_FOLDER: ./build
|
OUTPUT_FOLDER: ./build
|
||||||
RELEASE_FOLDER: ./release
|
RELEASE_FOLDER: ./release
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Process app name
|
- name: Process app name
|
||||||
@@ -95,13 +97,13 @@ jobs:
|
|||||||
build-list: ./media/ ./parts/ ./Zframework/ ./conf.lua ./main.lua ./version.lua ./legals.md ./license.txt
|
build-list: ./media/ ./parts/ ./Zframework/ ./conf.lua ./main.lua ./version.lua ./legals.md ./license.txt
|
||||||
package-path: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
package-path: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
||||||
- name: Upload core love package
|
- name: Upload core love package
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||||
path: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
path: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
||||||
- name: Add icon to love package
|
- name: Add icon to love package
|
||||||
run: |
|
run: |
|
||||||
cp ./.github/build/linux/${{ env.BUILD_TYPE }}/icon.png media/image/icon.png
|
cp ${{ env.BUILD_ASSETS_FOLDER }}/linux/${{ env.BUILD_TYPE }}/icon.png media/image/icon.png
|
||||||
zip -u ${{ env.CORE_LOVE_PACKAGE_PATH }} media/image/icon.png
|
zip -u ${{ env.CORE_LOVE_PACKAGE_PATH }} media/image/icon.png
|
||||||
rm media/image/icon.png
|
rm media/image/icon.png
|
||||||
- name: Rename love package
|
- name: Rename love package
|
||||||
@@ -109,7 +111,7 @@ jobs:
|
|||||||
mkdir -p ${{ env.OUTPUT_FOLDER }}
|
mkdir -p ${{ env.OUTPUT_FOLDER }}
|
||||||
mv ${{ env.CORE_LOVE_PACKAGE_PATH }} ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.love
|
mv ${{ env.CORE_LOVE_PACKAGE_PATH }} ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.love
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_Core_love
|
name: ${{ needs.get-info.outputs.base-name }}_Core_love
|
||||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.love
|
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.love
|
||||||
@@ -132,8 +134,10 @@ jobs:
|
|||||||
auto-test:
|
auto-test:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
needs: build-core
|
needs: build-core
|
||||||
|
env:
|
||||||
|
APPIMAGE_PATH: ./love.AppImage
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Love actions for testing
|
- name: Love actions for testing
|
||||||
@@ -142,34 +146,34 @@ jobs:
|
|||||||
font-path: ./parts/fonts/proportional.otf
|
font-path: ./parts/fonts/proportional.otf
|
||||||
language-folder: ./parts/language
|
language-folder: ./parts/language
|
||||||
- name: Download core love package
|
- name: Download core love package
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||||
- name: Download love
|
- name: Download love
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
curl -OL --retry 5 https://github.com/love2d/love/releases/download/11.4/love-11.4-x86_64.AppImage
|
curl --retry 5 https://github.com/love2d/love/releases/download/11.5/love-11.5-x86_64.AppImage -o ${{ env.APPIMAGE_PATH }}
|
||||||
chmod +x love-11.4-x86_64.AppImage
|
chmod +x ${{ env.APPIMAGE_PATH }}
|
||||||
- name: Prepare PulseAudio and AppImage
|
- name: Install dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install pulseaudio pulseaudio-utils pavucontrol alsa-oss alsa-utils libfuse2 -y
|
sudo apt-get install alsa-oss alsa-utils libfuse2 pavucontrol pulseaudio pulseaudio-utils x11-xserver-utils xvfb -y
|
||||||
- name: Run automated test
|
- name: Run automated test
|
||||||
uses: coactions/setup-xvfb@v1
|
shell: bash
|
||||||
with:
|
run: |
|
||||||
run: |
|
xvfb-run --auto-servernum ${{ env.APPIMAGE_PATH }} ${{ env.CORE_LOVE_PACKAGE_PATH }} --test
|
||||||
./love-11.4-x86_64.AppImage ${{ env.CORE_LOVE_PACKAGE_PATH }} --test
|
|
||||||
|
|
||||||
build-android:
|
build-android:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [get-info, build-core, auto-test]
|
needs: [get-info, build-core, auto-test]
|
||||||
if: github.event_name != 'pull_request'
|
if: github.event_name != 'pull_request'
|
||||||
env:
|
env:
|
||||||
|
COLD_CLEAR_FOLDER: ./libAndroid
|
||||||
OUTPUT_FOLDER: ./build
|
OUTPUT_FOLDER: ./build
|
||||||
RELEASE_FOLDER: ./release
|
RELEASE_FOLDER: ./release
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Process app name
|
- name: Process app name
|
||||||
@@ -178,6 +182,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
with open(os.getenv('GITHUB_OUTPUT'), 'a') as f:
|
with open(os.getenv('GITHUB_OUTPUT'), 'a') as f:
|
||||||
if "${{ env.BUILD_TYPE }}" == "dev":
|
if "${{ env.BUILD_TYPE }}" == "dev":
|
||||||
f.write('bundle-id=org.f26_studio.' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '.snapshot\n')
|
f.write('bundle-id=org.f26_studio.' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '.snapshot\n')
|
||||||
@@ -186,17 +191,17 @@ jobs:
|
|||||||
f.write('bundle-id=org.f26_studio.' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n')
|
f.write('bundle-id=org.f26_studio.' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n')
|
||||||
f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '-', '${{ needs.get-info.outputs.app-name }}') + '\n')
|
f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '-', '${{ needs.get-info.outputs.app-name }}') + '\n')
|
||||||
- name: Download core love package
|
- name: Download core love package
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||||
- name: Download ColdClear
|
- name: Download ColdClear
|
||||||
uses: ./.github/actions/get-cc
|
uses: ./.github/actions/get-unzip
|
||||||
with:
|
with:
|
||||||
platform: Android
|
url: ${{ env.COLD_CLEAR_DOWNLOAD_URL }}/Android.zip
|
||||||
dir: ./libAndroid
|
dir: ${{ env.COLD_CLEAR_FOLDER }}
|
||||||
- name: Build Android packages
|
- name: Build Android packages
|
||||||
id: build-packages
|
id: build-packages
|
||||||
uses: love-actions/love-actions-android@main
|
uses: love-actions/love-actions-android@v2
|
||||||
with:
|
with:
|
||||||
app-name: ${{ needs.get-info.outputs.app-name }}
|
app-name: ${{ needs.get-info.outputs.app-name }}
|
||||||
bundle-id: ${{ steps.process-app-name.outputs.bundle-id }}
|
bundle-id: ${{ steps.process-app-name.outputs.bundle-id }}
|
||||||
@@ -206,15 +211,15 @@ jobs:
|
|||||||
keystore-key-password: ${{ secrets.ANDROID_KEYSTORE_KEYPASSWORD }}
|
keystore-key-password: ${{ secrets.ANDROID_KEYSTORE_KEYPASSWORD }}
|
||||||
keystore-store-password: ${{ secrets.ANDROID_KEYSTORE_STOREPASSWORD }}
|
keystore-store-password: ${{ secrets.ANDROID_KEYSTORE_STOREPASSWORD }}
|
||||||
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
||||||
resource-path: ./.github/build/android/${{ env.BUILD_TYPE }}/res
|
resource-path: ${{ env.BUILD_ASSETS_FOLDER }}/android/${{ env.BUILD_TYPE }}/res
|
||||||
extra-assets: ./libAndroid/
|
extra-assets: ${{ env.COLD_CLEAR_FOLDER }}
|
||||||
custom-scheme: studio26f://oauth
|
custom-scheme: studio26f://oauth
|
||||||
product-name: ${{ steps.process-app-name.outputs.product-name }}
|
product-name: ${{ steps.process-app-name.outputs.product-name }}
|
||||||
version-string: ${{ needs.get-info.outputs.version-string }}
|
version-string: ${{ needs.get-info.outputs.version-string }}
|
||||||
version-code: ${{ needs.get-info.outputs.version-code }}
|
version-code: ${{ needs.get-info.outputs.version-code }}
|
||||||
output-folder: ${{ env.OUTPUT_FOLDER }}
|
output-folder: ${{ env.OUTPUT_FOLDER }}
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_Android_release
|
name: ${{ needs.get-info.outputs.base-name }}_Android_release
|
||||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}-release.apk
|
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}-release.apk
|
||||||
@@ -238,10 +243,11 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [get-info, build-core, auto-test]
|
needs: [get-info, build-core, auto-test]
|
||||||
env:
|
env:
|
||||||
|
COLD_CLEAR_FOLDER: ./ColdClear
|
||||||
OUTPUT_FOLDER: ./build
|
OUTPUT_FOLDER: ./build
|
||||||
RELEASE_FOLDER: ./release
|
RELEASE_FOLDER: ./release
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Process app name
|
- name: Process app name
|
||||||
@@ -256,45 +262,45 @@ jobs:
|
|||||||
f.write('bundle-id=org.26f-studio.' + product_name + '\n')
|
f.write('bundle-id=org.26f-studio.' + product_name + '\n')
|
||||||
f.write('product-name=' + product_name + '\n')
|
f.write('product-name=' + product_name + '\n')
|
||||||
- name: Download core love package
|
- name: Download core love package
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||||
- name: Add icon to love package
|
- name: Add icon to love package
|
||||||
run: |
|
run: |
|
||||||
cp ./.github/build/linux/${{ env.BUILD_TYPE }}/icon.png media/image/icon.png
|
cp ${{ env.BUILD_ASSETS_FOLDER }}/linux/${{ env.BUILD_TYPE }}/icon.png media/image/icon.png
|
||||||
zip -u ${{ env.CORE_LOVE_PACKAGE_PATH }} media/image/icon.png
|
zip -u ${{ env.CORE_LOVE_PACKAGE_PATH }} media/image/icon.png
|
||||||
rm media/image/icon.png
|
rm media/image/icon.png
|
||||||
- name: Download ColdClear
|
- name: Download ColdClear
|
||||||
uses: ./.github/actions/get-cc
|
uses: ./.github/actions/get-unzip
|
||||||
with:
|
with:
|
||||||
platform: Linux
|
url: ${{ env.COLD_CLEAR_DOWNLOAD_URL }}/Linux.zip
|
||||||
dir: ./ColdClear
|
dir: ${{ env.COLD_CLEAR_FOLDER }}
|
||||||
- name: Process ColdClear
|
- name: Process ColdClear
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
cd ./ColdClear
|
cd ${{ env.COLD_CLEAR_FOLDER }}
|
||||||
mkdir -p ./lib/lua/5.1
|
mkdir -p ./lib/lua/5.1
|
||||||
mv ./x64/CCloader.so ./lib/lua/5.1
|
mv ./x64/CCloader.so ./lib/lua/5.1
|
||||||
- name: Build Linux packages
|
- name: Build Linux packages
|
||||||
id: build-packages
|
id: build-packages
|
||||||
uses: love-actions/love-actions-linux@v1
|
uses: love-actions/love-actions-linux@v2
|
||||||
with:
|
with:
|
||||||
app-name: ${{ needs.get-info.outputs.app-name }}
|
app-name: ${{ needs.get-info.outputs.app-name }}
|
||||||
bundle-id: ${{ steps.process-app-name.outputs.bundle-id }}
|
bundle-id: ${{ steps.process-app-name.outputs.bundle-id }}
|
||||||
description: Techmino is fun!
|
description: Techmino is fun!
|
||||||
version-string: ${{ needs.get-info.outputs.version-string }}
|
version-string: ${{ needs.get-info.outputs.version-string }}
|
||||||
icon-path: ./.github/build/linux/${{ env.BUILD_TYPE }}/icon.png
|
icon-path: ${{ env.BUILD_ASSETS_FOLDER }}/linux/${{ env.BUILD_TYPE }}/icon.png
|
||||||
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
||||||
lib-path: ./ColdClear/lib
|
lib-path: ${{ env.COLD_CLEAR_FOLDER }}/lib
|
||||||
product-name: ${{ steps.process-app-name.outputs.product-name }}
|
product-name: ${{ steps.process-app-name.outputs.product-name }}
|
||||||
output-folder: ${{ env.OUTPUT_FOLDER }}
|
output-folder: ${{ env.OUTPUT_FOLDER }}
|
||||||
- name: Upload AppImage artifact
|
- name: Upload AppImage artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_Linux_AppImage
|
name: ${{ needs.get-info.outputs.base-name }}_Linux_AppImage
|
||||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.AppImage
|
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.AppImage
|
||||||
- name: Upload Debian artifact
|
- name: Upload Debian artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_Linux_Debian
|
name: ${{ needs.get-info.outputs.base-name }}_Linux_Debian
|
||||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.deb
|
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.deb
|
||||||
@@ -317,145 +323,58 @@ jobs:
|
|||||||
name: ${{ needs.get-info.outputs.update-title }}
|
name: ${{ needs.get-info.outputs.update-title }}
|
||||||
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}
|
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}
|
||||||
|
|
||||||
build-macos-portable:
|
build-web-compat:
|
||||||
runs-on: macos-latest
|
|
||||||
needs: [get-info, build-core, auto-test]
|
|
||||||
if: github.event_name != 'pull_request'
|
|
||||||
env:
|
|
||||||
OUTPUT_FOLDER: ./build
|
|
||||||
RELEASE_FOLDER: ./release
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
with:
|
|
||||||
submodules: recursive
|
|
||||||
- name: Process app name
|
|
||||||
id: process-app-name
|
|
||||||
shell: python3 {0}
|
|
||||||
run: |
|
|
||||||
import os
|
|
||||||
import re
|
|
||||||
with open(os.getenv('GITHUB_OUTPUT'), 'a') as f:
|
|
||||||
f.write('bundle-id=org.26f-studio.techmino\n')
|
|
||||||
f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n')
|
|
||||||
- name: Download core love package
|
|
||||||
uses: actions/download-artifact@v3
|
|
||||||
with:
|
|
||||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
|
||||||
- name: Download ColdClear
|
|
||||||
uses: ./.github/actions/get-cc
|
|
||||||
with:
|
|
||||||
platform: macOS
|
|
||||||
dir: ./ColdClear
|
|
||||||
- name: Process ColdClear
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
rm ./ColdClear/universal/libcold_clear.a
|
|
||||||
- name: Use Xcode 15.3
|
|
||||||
# Xcode 15.4 segfaults
|
|
||||||
# see https://forums.developer.apple.com/forums/thread/757398
|
|
||||||
uses: mobiledevops/xcode-select-version-action@v1
|
|
||||||
with:
|
|
||||||
xcode-select-version: 15.3
|
|
||||||
- name: Build macOS packages
|
|
||||||
id: build-packages
|
|
||||||
uses: love-actions/love-actions-macos-portable@v1
|
|
||||||
with:
|
|
||||||
app-name: ${{ needs.get-info.outputs.app-name }}
|
|
||||||
bundle-id: ${{ steps.process-app-name.outputs.bundle-id }}
|
|
||||||
copyright: "Copyright © 2019-2023 26F-Studio. Some Rights Reserved."
|
|
||||||
icon-path: ./.github/build/macOS/${{ env.BUILD_TYPE }}/icon.icns
|
|
||||||
love-ref: "11.5"
|
|
||||||
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
|
||||||
libs-path: ./ColdClear/universal/
|
|
||||||
product-name: ${{ steps.process-app-name.outputs.product-name }}
|
|
||||||
version-string: ${{ needs.get-info.outputs.version-string }}
|
|
||||||
output-folder: ${{ env.OUTPUT_FOLDER }}
|
|
||||||
account-username: ${{ secrets.APPLE_ACCOUNT_USERNAME }}
|
|
||||||
account-password: ${{ secrets.APPLE_ACCOUNT_PASSWORD }}
|
|
||||||
team-id: "${{ secrets.APPLE_DEVELOPER_TEAM_ID }}"
|
|
||||||
developer-id-application-base64: ${{ secrets.APPLE_CERT_DEVELOPER_ID_APPLICATION }}
|
|
||||||
developer-id-application-password: ${{ secrets.APPLE_CERT_DEVELOPER_ID_APPLICATION_PWD }}
|
|
||||||
developer-id-installer-base64: ${{ secrets.APPLE_CERT_DEVELOPER_ID_INSTALLER }}
|
|
||||||
developer-id-installer-password: ${{ secrets.APPLE_CERT_DEVELOPER_ID_INSTALLER_PWD }}
|
|
||||||
dmg-background-path: ./.github/build/macOS/${{ env.BUILD_TYPE }}/dmg.png
|
|
||||||
dmg-icon-position: "239 203"
|
|
||||||
dmg-icon-size: "100"
|
|
||||||
dmg-link-position: "565 203"
|
|
||||||
dmg-text-size: "12"
|
|
||||||
dmg-volume-icon-path: ./.github/build/macOS/${{ env.BUILD_TYPE }}/dmg.icns
|
|
||||||
dmg-volume-name: ${{ steps.process-app-name.outputs.product-name }}
|
|
||||||
dmg-window-position: "200 120"
|
|
||||||
dmg-window-size: "800 500"
|
|
||||||
- name: Upload pkg artifact
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_macOS_portable_pkg
|
|
||||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.pkg
|
|
||||||
- name: Upload dmg artifact
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_macOS_portable_dmg
|
|
||||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.dmg
|
|
||||||
- name: Upload bare artifact
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_macOS_portable_bare
|
|
||||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.zip
|
|
||||||
- name: Prepare for release
|
|
||||||
if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }}
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
mkdir -p ${{ env.RELEASE_FOLDER }}
|
|
||||||
cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.pkg ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_portable.pkg
|
|
||||||
cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.dmg ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_portable.dmg
|
|
||||||
- name: Upload release
|
|
||||||
if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }}
|
|
||||||
uses: ncipollo/release-action@v1
|
|
||||||
with:
|
|
||||||
allowUpdates: true
|
|
||||||
artifacts: |
|
|
||||||
${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_portable.pkg
|
|
||||||
${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_portable.dmg
|
|
||||||
body: ${{ needs.get-info.outputs.update-note }}
|
|
||||||
name: ${{ needs.get-info.outputs.update-title }}
|
|
||||||
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}
|
|
||||||
|
|
||||||
build-web:
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [get-info, build-core, auto-test]
|
needs: [get-info, build-core, auto-test]
|
||||||
|
env:
|
||||||
|
MEMORY_LIMIT: 128000000
|
||||||
|
OUTPUT_FOLDER: ./build
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Download core love package
|
- name: Download core love package
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||||
- name: Move core love package
|
- name: Build web packages
|
||||||
run: |
|
run: |
|
||||||
mv ${{ env.CORE_LOVE_PACKAGE_PATH }} ./.github/build/web/game.data
|
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 ${{ env.BUILD_ASSETS_FOLDER }}/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@v4
|
||||||
|
with:
|
||||||
|
name: ${{ needs.get-info.outputs.base-name }}_Web
|
||||||
|
path: ${{ env.OUTPUT_FOLDER }}
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
uses: crazy-max/ghaction-github-pages@v3
|
uses: crazy-max/ghaction-github-pages@v4
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
build_dir: ./.github/build/web/
|
build_dir: ${{ env.OUTPUT_FOLDER }}
|
||||||
keep_history: false
|
keep_history: false
|
||||||
target_branch: web-dev
|
target_branch: gh-pages
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_Web_PWA
|
|
||||||
path: ./.github/build/web/
|
|
||||||
|
|
||||||
build-windows:
|
build-windows:
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
needs: [get-info, build-core, auto-test]
|
needs: [get-info, build-core, auto-test]
|
||||||
env:
|
env:
|
||||||
|
COLD_CLEAR_FOLDER: ./ColdClear
|
||||||
OUTPUT_FOLDER: ./build
|
OUTPUT_FOLDER: ./build
|
||||||
RELEASE_FOLDER: ./release
|
RELEASE_FOLDER: ./release
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: Process app name
|
- name: Process app name
|
||||||
@@ -467,20 +386,20 @@ jobs:
|
|||||||
with open(os.getenv('GITHUB_OUTPUT'), 'a') as f:
|
with open(os.getenv('GITHUB_OUTPUT'), 'a') as f:
|
||||||
f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n')
|
f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n')
|
||||||
- name: Download core love package
|
- name: Download core love package
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||||
- name: Download ColdClear
|
- name: Download ColdClear
|
||||||
uses: ./.github/actions/get-cc
|
uses: ./.github/actions/get-unzip
|
||||||
with:
|
with:
|
||||||
platform: Windows
|
url: ${{ env.COLD_CLEAR_DOWNLOAD_URL }}/Windows.zip
|
||||||
dir: ./ColdClear
|
dir: ${{ env.COLD_CLEAR_FOLDER }}
|
||||||
- name: Update Windows template
|
- name: Update Windows template
|
||||||
shell: python3 {0}
|
shell: python3 {0}
|
||||||
run: |
|
run: |
|
||||||
version_string = "${{ needs.get-info.outputs.version-string }}"
|
version_string = "${{ needs.get-info.outputs.version-string }}"
|
||||||
file_version = (f"{version_string.replace('.', ',')},0")
|
file_version = (f"{version_string.replace('.', ',')},0")
|
||||||
with open("./.github/build/windows/${{ env.BUILD_TYPE }}/template.rc", "r+", encoding="utf8") as file:
|
with open("${{ env.BUILD_ASSETS_FOLDER }}/windows/${{ env.BUILD_TYPE }}/template.rc", "r+", encoding="utf8") as file:
|
||||||
data = file.read()
|
data = file.read()
|
||||||
data = data\
|
data = data\
|
||||||
.replace("@Version", version_string)\
|
.replace("@Version", version_string)\
|
||||||
@@ -490,30 +409,30 @@ jobs:
|
|||||||
file.write(data)
|
file.write(data)
|
||||||
- name: Build Windows packages
|
- name: Build Windows packages
|
||||||
id: build-packages
|
id: build-packages
|
||||||
uses: love-actions/love-actions-windows@v1
|
uses: love-actions/love-actions-windows@v2
|
||||||
with:
|
with:
|
||||||
icon-path: ./.github/build/windows/${{ env.BUILD_TYPE }}/icon.ico
|
icon-path: ${{ env.BUILD_ASSETS_FOLDER }}/windows/${{ env.BUILD_TYPE }}/icon.ico
|
||||||
rc-path: ./.github/build/windows/${{ env.BUILD_TYPE }}/template.rc
|
rc-path: ${{ env.BUILD_ASSETS_FOLDER }}/windows/${{ env.BUILD_TYPE }}/template.rc
|
||||||
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
|
||||||
extra-assets-x86: ./ColdClear/x86/CCloader.dll ./ColdClear/x86/cold_clear.dll ./.github/build/extraLibs/Windows_x64/discord-rpc.dll
|
extra-assets-x86: ${{ env.COLD_CLEAR_FOLDER }}/x86/CCloader.dll ${{ env.COLD_CLEAR_FOLDER }}/x86/cold_clear.dll ${{ env.BUILD_ASSETS_FOLDER }}/extraLibs/Windows_x64/discord-rpc.dll
|
||||||
extra-assets-x64: ./ColdClear/x64/CCloader.dll ./ColdClear/x64/cold_clear.dll ./.github/build/extraLibs/Windows_x86/discord-rpc.dll
|
extra-assets-x64: ${{ env.COLD_CLEAR_FOLDER }}/x64/CCloader.dll ${{ env.COLD_CLEAR_FOLDER }}/x64/cold_clear.dll ${{ env.BUILD_ASSETS_FOLDER }}/extraLibs/Windows_x86/discord-rpc.dll
|
||||||
product-name: ${{ steps.process-app-name.outputs.product-name }}
|
product-name: ${{ steps.process-app-name.outputs.product-name }}
|
||||||
app-id: ${{ secrets.WINDOWS_APP_ID }}
|
app-id: ${{ secrets.WINDOWS_APP_ID }}
|
||||||
project-website: https://www.studio26f.org/
|
project-website: https://www.studio26f.org/
|
||||||
installer-languages: ChineseSimplified.isl ChineseTraditional.isl English.isl Spanish.isl French.isl Indonesian.isl Japanese.isl Portuguese.isl
|
installer-languages: ChineseSimplified.isl ChineseTraditional.isl English.isl Spanish.isl French.isl Indonesian.isl Japanese.isl Portuguese.isl
|
||||||
output-folder: ${{ env.OUTPUT_FOLDER }}
|
output-folder: ${{ env.OUTPUT_FOLDER }}
|
||||||
- name: Upload 32-bit artifact
|
- name: Upload 32-bit artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_Windows_x86
|
name: ${{ needs.get-info.outputs.base-name }}_Windows_x86
|
||||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x86.zip
|
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x86.zip
|
||||||
- name: Upload 64-bit artifact
|
- name: Upload 64-bit artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_Windows_x64
|
name: ${{ needs.get-info.outputs.base-name }}_Windows_x64
|
||||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x64.zip
|
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x64.zip
|
||||||
- name: Upload installer artifact
|
- name: Upload installer artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.get-info.outputs.base-name }}_Windows_installer
|
name: ${{ needs.get-info.outputs.base-name }}_Windows_installer
|
||||||
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_installer.exe
|
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_installer.exe
|
||||||
@@ -548,38 +467,58 @@ jobs:
|
|||||||
build-core,
|
build-core,
|
||||||
build-android,
|
build-android,
|
||||||
build-linux,
|
build-linux,
|
||||||
build-macos-portable,
|
build-web-compat,
|
||||||
build-web,
|
|
||||||
build-windows,
|
build-windows,
|
||||||
]
|
]
|
||||||
env:
|
env:
|
||||||
ACTION_TYPE: ${{ fromJSON('[["Development", "Pre-release"], ["Release", "Release"]]')[startsWith(github.ref, 'refs/tags/v')][startsWith(github.ref, 'refs/tags/pre')] }}
|
ACTION_TYPE: ${{ fromJSON('[["Development", "Pre-release"], ["Release", "Release"]]')[startsWith(github.ref, 'refs/tags/v')][startsWith(github.ref, 'refs/tags/pre')] }}
|
||||||
steps:
|
steps:
|
||||||
- name: Cleanup
|
- name: Cleanup
|
||||||
uses: geekyeggo/delete-artifact@v2
|
uses: geekyeggo/delete-artifact@v5
|
||||||
with:
|
with:
|
||||||
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
|
||||||
- name: Send Discord message
|
- name: Send Discord message
|
||||||
if: github.event_name != 'pull_request'
|
if: github.ref == 'refs/heads/main'
|
||||||
uses: Sniddl/discord-commits@v1.6
|
shell: python
|
||||||
with:
|
run: |
|
||||||
webhook: ${{ secrets.DISCORD_WEBHOOK }}
|
import requests
|
||||||
message: "Github Actions for **${{ github.repository }}**."
|
import json
|
||||||
embed: '{
|
|
||||||
"author":{
|
headers = {
|
||||||
"name":"${{ needs.get-info.outputs.app-name }} [${{ env.ACTION_TYPE }}]",
|
'Content-Type': 'application/json',
|
||||||
"url":"https://github.com/${{ github.repository }}"
|
}
|
||||||
},
|
payload = json.dumps({
|
||||||
"title":"${{ needs.get-info.outputs.app-name }} (${{ needs.get-info.outputs.version-name }}) Build Result",
|
"content": "Github Actions for **${{ github.repository }}**.",
|
||||||
"description": "CI triggered at ${{ needs.get-info.outputs.commit-hash }}",
|
"embeds": [
|
||||||
"url":"https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
|
{
|
||||||
"thumbnail":{
|
"author": {
|
||||||
"url":"https://raw.githubusercontent.com/${{ github.repository }}/main/.github/build/linux/${{ env.BUILD_TYPE }}/icon.png"
|
"name": "${{ needs.get-info.outputs.app-name }} [${{ env.ACTION_TYPE }}]",
|
||||||
},
|
"url": "https://github.com/${{ github.repository }}"
|
||||||
"color":36863,
|
},
|
||||||
"fields":[
|
"title": "${{ needs.get-info.outputs.app-name }} (${{ needs.get-info.outputs.version-name }}) Build Result",
|
||||||
{"name":"Version","value":"${{ needs.get-info.outputs.version-string }}","inline": true},
|
"description": "CI triggered at ${{ needs.get-info.outputs.commit-hash }}",
|
||||||
{"name":"Package Name","value":"${{ needs.get-info.outputs.base-name }}","inline": true},
|
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
|
||||||
{"name":"Status","value":"**Automatic Test:** ${{ needs.auto-test.result }}\n**Core:** ${{ needs.build-core.result }}\n**Android:** ${{ needs.build-android.result }}\n**Linux:** ${{ needs.build-linux.result }}\n**macOS portable:** ${{ needs.build-macos-portable.result }}\n**Windows:** ${{ needs.build-windows.result }}"}
|
"thumbnail": {
|
||||||
|
"url": "https://raw.githubusercontent.com/${{ github.repository }}/main/.github/build/linux/${{ env.BUILD_TYPE }}/icon.png"
|
||||||
|
},
|
||||||
|
"color": 36863,
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "Version",
|
||||||
|
"value": "${{ needs.get-info.outputs.version-string }}",
|
||||||
|
"inline": True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Package Name",
|
||||||
|
"value": "${{ needs.get-info.outputs.base-name }}",
|
||||||
|
"inline": True
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Status",
|
||||||
|
"value": "**Automatic Test:** ${{ needs.auto-test.result }}\n**Core:** ${{ needs.build-core.result }}\n**Android:** ${{ needs.build-android.result }}\n**Linux:** ${{ needs.build-linux.result }}\n**Web compatible:** ${{ needs.build-web-compat.result }}\n**Windows:** ${{ needs.build-windows.result }}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}'
|
})
|
||||||
|
requests.request("POST", "${{ secrets.DISCORD_WEBHOOK }}", headers=headers, data=payload)
|
||||||
|
|||||||
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 sendCHN=love.thread.getChannel('HTTP_inputChannel')
|
||||||
local recvCHN=love.thread.getChannel('outputChannel')
|
local recvCHN=love.thread.getChannel('HTTP_outputChannel')
|
||||||
|
|
||||||
local threads={}
|
local threads={}
|
||||||
local threadCount=0
|
local threadCount=0
|
||||||
@@ -9,11 +9,15 @@ local threadCode=[[
|
|||||||
local http=require'socket.http'
|
local http=require'socket.http'
|
||||||
local ltn12=require'ltn12'
|
local ltn12=require'ltn12'
|
||||||
|
|
||||||
local sendCHN=love.thread.getChannel('inputChannel')
|
local sendCHN=love.thread.getChannel('HTTP_inputChannel')
|
||||||
local recvCHN=love.thread.getChannel('outputChannel')
|
local recvCHN=love.thread.getChannel('HTTP_outputChannel')
|
||||||
|
local sleep=require'love.timer'.sleep
|
||||||
|
|
||||||
while true do
|
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
|
if arg._destroy then
|
||||||
recvCHN:push{
|
recvCHN:push{
|
||||||
|
|||||||
@@ -3,8 +3,16 @@
|
|||||||
NONE={}function NULL() end PAPER=love.graphics.newCanvas(1,1)
|
NONE={}function NULL() end PAPER=love.graphics.newCanvas(1,1)
|
||||||
EDITING=""
|
EDITING=""
|
||||||
LOADED=false
|
LOADED=false
|
||||||
|
|
||||||
|
---@type 'Windows'|'Android'|'Linux'|'iOS'|'macOS'|'Web'
|
||||||
SYSTEM=love.system.getOS()
|
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
|
-- Bit module
|
||||||
local success
|
local success
|
||||||
@@ -72,6 +80,7 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Love-based modules (basic)
|
-- Love-based modules (basic)
|
||||||
|
CLIPBOARD= require'Zframework.clipboard'
|
||||||
HTTP= require'Zframework.http'
|
HTTP= require'Zframework.http'
|
||||||
WS= require'Zframework.websocket'
|
WS= require'Zframework.websocket'
|
||||||
FILE= require'Zframework.file'
|
FILE= require'Zframework.file'
|
||||||
@@ -94,6 +103,10 @@ IMG= require'Zframework.image'
|
|||||||
BGM= require'Zframework.bgm'
|
BGM= require'Zframework.bgm'
|
||||||
VOC= require'Zframework.voice'
|
VOC= require'Zframework.voice'
|
||||||
|
|
||||||
|
if SYSTEM=='Web' then
|
||||||
|
JS=require'Zframework.js'
|
||||||
|
end
|
||||||
|
|
||||||
local ms,kb=love.mouse,love.keyboard
|
local ms,kb=love.mouse,love.keyboard
|
||||||
local KBisDown=kb.isDown
|
local KBisDown=kb.isDown
|
||||||
|
|
||||||
@@ -174,6 +187,7 @@ local function updatePowerInfo()
|
|||||||
gc_pop()
|
gc_pop()
|
||||||
gc.setCanvas()
|
gc.setCanvas()
|
||||||
end
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
local lastX,lastY=0,0-- Last click pos
|
local lastX,lastY=0,0-- Last click pos
|
||||||
local function _updateMousePos(x,y,dx,dy)
|
local function _updateMousePos(x,y,dx,dy)
|
||||||
@@ -423,38 +437,38 @@ local dPadToKey={
|
|||||||
start='return',
|
start='return',
|
||||||
back='escape',
|
back='escape',
|
||||||
}
|
}
|
||||||
function love.joystickadded(JS)
|
function love.joystickadded(joystick)
|
||||||
table.insert(jsState,{
|
table.insert(jsState,{
|
||||||
_id=JS:getID(),
|
_id=joystick:getID(),
|
||||||
_jsObj=JS,
|
_jsObj=joystick,
|
||||||
leftx=0,lefty=0,
|
leftx=0,lefty=0,
|
||||||
rightx=0,righty=0,
|
rightx=0,righty=0,
|
||||||
triggerleft=0,triggerright=0
|
triggerleft=0,triggerright=0
|
||||||
})
|
})
|
||||||
MES.new('info',"Joystick added")
|
MES.new('info',"Joystick added")
|
||||||
end
|
end
|
||||||
function love.joystickremoved(JS)
|
function love.joystickremoved(joystick)
|
||||||
for i=1,#jsState do
|
for i=1,#jsState do
|
||||||
if jsState[i]._jsObj==JS then
|
if jsState[i]._jsObj==joystick then
|
||||||
for j=1,#gamePadKeys do
|
for j=1,#gamePadKeys do
|
||||||
if JS:isGamepadDown(gamePadKeys[j]) then
|
if joystick:isGamepadDown(gamePadKeys[j]) then
|
||||||
love.gamepadreleased(JS,gamePadKeys[j])
|
love.gamepadreleased(joystick,gamePadKeys[j])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
love.gamepadaxis(JS,'leftx',0)
|
love.gamepadaxis(joystick,'leftx',0)
|
||||||
love.gamepadaxis(JS,'lefty',0)
|
love.gamepadaxis(joystick,'lefty',0)
|
||||||
love.gamepadaxis(JS,'rightx',0)
|
love.gamepadaxis(joystick,'rightx',0)
|
||||||
love.gamepadaxis(JS,'righty',0)
|
love.gamepadaxis(joystick,'righty',0)
|
||||||
love.gamepadaxis(JS,'triggerleft',-1)
|
love.gamepadaxis(joystick,'triggerleft',-1)
|
||||||
love.gamepadaxis(JS,'triggerright',-1)
|
love.gamepadaxis(joystick,'triggerright',-1)
|
||||||
MES.new('info',"Joystick removed")
|
MES.new('info',"Joystick removed")
|
||||||
table.remove(jsState,i)
|
table.remove(jsState,i)
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
function love.gamepadaxis(JS,axis,val)
|
function love.gamepadaxis(joystick,axis,val)
|
||||||
if jsState[1] and JS==jsState[1]._jsObj then
|
if jsState[1] and joystick==jsState[1]._jsObj then
|
||||||
local js=jsState[1]
|
local js=jsState[1]
|
||||||
if axis=='leftx' or axis=='lefty' or axis=='rightx' or axis=='righty' then
|
if axis=='leftx' or axis=='lefty' or axis=='rightx' or axis=='righty' then
|
||||||
local newVal=-- range: [0,1]
|
local newVal=-- range: [0,1]
|
||||||
@@ -463,14 +477,14 @@ function love.gamepadaxis(JS,axis,val)
|
|||||||
0
|
0
|
||||||
if newVal~=js[axis] then
|
if newVal~=js[axis] then
|
||||||
if js[axis]==-1 then
|
if js[axis]==-1 then
|
||||||
love.gamepadreleased(JS,jsAxisEventName[axis][1])
|
love.gamepadreleased(joystick,jsAxisEventName[axis][1])
|
||||||
elseif js[axis]~=0 then
|
elseif js[axis]~=0 then
|
||||||
love.gamepadreleased(JS,jsAxisEventName[axis][2])
|
love.gamepadreleased(joystick,jsAxisEventName[axis][2])
|
||||||
end
|
end
|
||||||
if newVal==-1 then
|
if newVal==-1 then
|
||||||
love.gamepadpressed(JS,jsAxisEventName[axis][1])
|
love.gamepadpressed(joystick,jsAxisEventName[axis][1])
|
||||||
elseif newVal==1 then
|
elseif newVal==1 then
|
||||||
love.gamepadpressed(JS,jsAxisEventName[axis][2])
|
love.gamepadpressed(joystick,jsAxisEventName[axis][2])
|
||||||
end
|
end
|
||||||
js[axis]=newVal
|
js[axis]=newVal
|
||||||
end
|
end
|
||||||
@@ -478,9 +492,9 @@ function love.gamepadaxis(JS,axis,val)
|
|||||||
local newVal=val>.3 and 1 or 0-- range: [0,1]
|
local newVal=val>.3 and 1 or 0-- range: [0,1]
|
||||||
if newVal~=js[axis] then
|
if newVal~=js[axis] then
|
||||||
if newVal==1 then
|
if newVal==1 then
|
||||||
love.gamepadpressed(JS,jsAxisEventName[axis])
|
love.gamepadpressed(joystick,jsAxisEventName[axis])
|
||||||
else
|
else
|
||||||
love.gamepadreleased(JS,jsAxisEventName[axis])
|
love.gamepadreleased(joystick,jsAxisEventName[axis])
|
||||||
end
|
end
|
||||||
js[axis]=newVal
|
js[axis]=newVal
|
||||||
end
|
end
|
||||||
@@ -720,6 +734,10 @@ function love.run()
|
|||||||
|
|
||||||
-- UPDATE
|
-- UPDATE
|
||||||
STEP()
|
STEP()
|
||||||
|
if SYSTEM == 'Web' then
|
||||||
|
JS.retrieveData(dt)
|
||||||
|
CLIPBOARD._update(dt)
|
||||||
|
end
|
||||||
if mouseShow then mouse_update(dt) end
|
if mouseShow then mouse_update(dt) end
|
||||||
if next(jsState) then gp_update(jsState[1],dt) end
|
if next(jsState) then gp_update(jsState[1],dt) end
|
||||||
VOC.update()
|
VOC.update()
|
||||||
|
|||||||
142
Zframework/js.lua
Normal file
142
Zframework/js.lua
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
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
|
switch=not switch
|
||||||
if not switch then
|
if not switch then
|
||||||
profile.stop()
|
profile.stop()
|
||||||
love.system.setClipboardText(profile.report())
|
CLIPBOARD.set(profile.report())
|
||||||
profile.reset()
|
profile.reset()
|
||||||
return false
|
return false
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ do-- functions to shorted big numbers
|
|||||||
function STRING.bigInt(t)
|
function STRING.bigInt(t)
|
||||||
if t<1000 then
|
if t<1000 then
|
||||||
return tostring(t)
|
return tostring(t)
|
||||||
elseif t~=1e999 then
|
elseif t~=1/0 then
|
||||||
local e=floorint(lg(t)/3)
|
local e=floorint(lg(t)/3)
|
||||||
return(t/10^(e*3))..units[e+1]
|
return(t/10^(e*3))..units[e+1]
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -15,6 +15,29 @@ function TABLE.new(val,count)
|
|||||||
return L
|
return L
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Get a new empty table with __lock() and __unlock() to protect changes
|
||||||
|
function TABLE.newWithLockMetamethod()
|
||||||
|
local t
|
||||||
|
do
|
||||||
|
local lockedKey={}
|
||||||
|
local realTable={}
|
||||||
|
t=setmetatable( -- This is the fake table, act like a wrapper of realTable
|
||||||
|
{
|
||||||
|
__lock =function(k) if k then lockedKey[k]=true end end,
|
||||||
|
__unlock=function(k)
|
||||||
|
if k then lockedKey[k]=false else TABLE.cut(lockedKey) end
|
||||||
|
end,
|
||||||
|
},{
|
||||||
|
__index =realTable,
|
||||||
|
__newindex=function(_,k,v) if not lockedKey[k] then realTable[k]=v end end,
|
||||||
|
__len =function(_,_,_) return #realTable end,
|
||||||
|
__tostring=function(_,_,_) return tostring(realTable) end,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
end
|
||||||
|
return t
|
||||||
|
end
|
||||||
|
|
||||||
-- Get a copy of [1~#] elements
|
-- Get a copy of [1~#] elements
|
||||||
function TABLE.shift(org,depth)
|
function TABLE.shift(org,depth)
|
||||||
if not depth then depth=1e99 end
|
if not depth then depth=1e99 end
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
---@type love.Channel,love.Channel,love.Channel
|
||||||
local triggerCHN,sendCHN,readCHN=...
|
local triggerCHN,sendCHN,readCHN=...
|
||||||
|
|
||||||
local CHN_demand,CHN_getCount=triggerCHN.demand,triggerCHN.getCount
|
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 SOCK=require'socket'.tcp()
|
||||||
local JSON=require'Zframework.json'
|
local JSON=require'Zframework.json'
|
||||||
|
local sleep=require'love.timer'.sleep
|
||||||
|
|
||||||
do-- Connect
|
do-- Connect
|
||||||
local host=CHN_demand(sendCHN)
|
-- Warning: workaround for love.js, used to use CHN_demand instead
|
||||||
local port=CHN_demand(sendCHN)
|
while CHN_getCount(sendCHN)<5 do sleep(.0626) end
|
||||||
local path=CHN_demand(sendCHN)
|
local host=CHN_pop(sendCHN)
|
||||||
local head=CHN_demand(sendCHN)
|
local port=CHN_pop(sendCHN)
|
||||||
local timeout=CHN_demand(sendCHN)
|
local path=CHN_pop(sendCHN)
|
||||||
|
local head=CHN_pop(sendCHN)
|
||||||
|
local timeout=CHN_pop(sendCHN)
|
||||||
|
|
||||||
SOCK:settimeout(timeout)
|
SOCK:settimeout(timeout)
|
||||||
local res,err=SOCK:connect(host,port)
|
local res,err=SOCK:connect(host,port)
|
||||||
@@ -186,7 +190,8 @@ end)
|
|||||||
local success,err
|
local success,err
|
||||||
|
|
||||||
while true do-- Running
|
while true do-- Running
|
||||||
CHN_demand(triggerCHN)
|
while CHN_getCount(triggerCHN)==0 do sleep(.0626) end
|
||||||
|
CHN_pop(triggerCHN)
|
||||||
success,err=pcall(sendThread)
|
success,err=pcall(sendThread)
|
||||||
if not success or err then break end
|
if not success or err then break end
|
||||||
success,err=pcall(readThread)
|
success,err=pcall(readThread)
|
||||||
|
|||||||
13
conf.lua
13
conf.lua
@@ -1,9 +1,9 @@
|
|||||||
local OS=love._os
|
local system=love._os
|
||||||
if OS=='OS X' then OS='macOS' end
|
if system=='OS X' then system='macOS' end
|
||||||
MOBILE=OS=='Android' or OS=='iOS'
|
MOBILE=system=='Android' or system=='iOS'
|
||||||
FNNS=OS:find'\79\83' -- What does FNSF stand for? IDK so don't ask me lol
|
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
|
local oldRead=love.filesystem.read
|
||||||
function love.filesystem.read(name,size)
|
function love.filesystem.read(name,size)
|
||||||
if love.filesystem.getInfo(name) then
|
if love.filesystem.getInfo(name) then
|
||||||
@@ -23,12 +23,13 @@ function love.conf(t)
|
|||||||
local fileData=fs.read('conf/settings')
|
local fileData=fs.read('conf/settings')
|
||||||
if fileData then
|
if fileData then
|
||||||
msaa=tonumber(fileData:match('"msaa":(%d+)')) or 0;
|
msaa=tonumber(fileData:match('"msaa":(%d+)')) or 0;
|
||||||
|
msaa=msaa==0 and 0 or 2*msaa
|
||||||
portrait=MOBILE and fileData:find('"portrait":true') and true
|
portrait=MOBILE and fileData:find('"portrait":true') and true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
t.identity=identity -- Saving folder
|
t.identity=identity -- Saving folder
|
||||||
t.version="11.4"
|
t.version="11.5"
|
||||||
t.gammacorrect=false
|
t.gammacorrect=false
|
||||||
t.appendidentity=true -- Search files in source then in save directory
|
t.appendidentity=true -- Search files in source then in save directory
|
||||||
t.accelerometerjoystick=false -- Accelerometer=joystick on ios/android
|
t.accelerometerjoystick=false -- Accelerometer=joystick on ios/android
|
||||||
|
|||||||
83
main.lua
83
main.lua
@@ -49,6 +49,10 @@ SCR.setSize(1280,720) -- Initialize Screen size
|
|||||||
BGM.setMaxSources(5)
|
BGM.setMaxSources(5)
|
||||||
VOC.setDiversion(.62)
|
VOC.setDiversion(.62)
|
||||||
|
|
||||||
|
if SYSTEM == 'Web' and not WEB_COMPAT_MODE then
|
||||||
|
CLIPBOARD.setFreshInterval(.5)
|
||||||
|
end
|
||||||
|
|
||||||
WIDGET.setOnChange(function()
|
WIDGET.setOnChange(function()
|
||||||
if SCN.cur=='net_game' or SCN.cur=='custom_field' then return end
|
if SCN.cur=='net_game' or SCN.cur=='custom_field' then return end
|
||||||
local colorList=THEME.getThemeColor()
|
local colorList=THEME.getThemeColor()
|
||||||
@@ -294,41 +298,41 @@ IMG.init{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
SKIN.load{
|
SKIN.load{
|
||||||
{name="Arcade (Asriel)", path='media/image/skin/asriel/arcade.png'},
|
{name="Crystal (Scf)", path='media/image/skin/scf/crystal.png'},
|
||||||
{name="Cardboard (Asriel, slimenergy)", path='media/image/skin/asriel/cardboard.png'},
|
{name="Smooth (MrZ)", path='media/image/skin/mrz/smooth.png'},
|
||||||
{name="Crystal (Scf)", path='media/image/skin/scf/crystal.png'},
|
{name="Matte (MrZ)", path='media/image/skin/mrz/matte.png'},
|
||||||
{name="Matte (MrZ)", path='media/image/skin/mrz/matte.png'},
|
{name="Glass (Scf)", path='media/image/skin/scf/glass.png'},
|
||||||
{name="Shiny (CHNO)", path='media/image/skin/chno/shiny.png'},
|
{name="Jelly (Miya)", path='media/image/skin/miya/jelly.png'},
|
||||||
{name="Contrast (MrZ)", path='media/image/skin/mrz/contrast.png'},
|
{name="Simple (Scf)", path='media/image/skin/scf/simple.png'},
|
||||||
{name="Polkadots (Scf)", path='media/image/skin/scf/polkadots.png'},
|
{name="Contrast (MrZ)", path='media/image/skin/mrz/contrast.png'},
|
||||||
{name="Toy (Scf)", path='media/image/skin/scf/toy.png'},
|
{name="Plastic (MrZ)", path='media/image/skin/mrz/plastic.png'},
|
||||||
{name="Smooth (MrZ)", path='media/image/skin/mrz/smooth.png'},
|
{name="Glow (MrZ)", path='media/image/skin/mrz/glow.png'},
|
||||||
{name="Simple (Scf)", path='media/image/skin/scf/simple.png'},
|
{name="Bright (Scf)", path='media/image/skin/scf/bright.png'},
|
||||||
{name="Glass (Scf)", path='media/image/skin/scf/glass.png'},
|
{name="Penta (Scf)", path='media/image/skin/scf/penta.png'},
|
||||||
{name="Penta (Scf)", path='media/image/skin/scf/penta.png'},
|
{name="Bubble (Scf)", path='media/image/skin/scf/bubble.png'},
|
||||||
{name="Bubble (Scf)", path='media/image/skin/scf/bubble.png'},
|
{name="Pure (MrZ)", path='media/image/skin/mrz/pure.png'},
|
||||||
{name="Minoes (Scf)", path='media/image/skin/scf/minoes.png'},
|
{name="Letters (CHNO)", path='media/image/skin/chno/letters.png'},
|
||||||
{name="pure (MrZ)", path='media/image/skin/mrz/pure.png'},
|
{name="Kanji (CHNO)", path='media/image/skin/chno/kanji.png'},
|
||||||
{name="bright (Scf)", path='media/image/skin/scf/bright.png'},
|
{name="Pastel (CHNO)", path='media/image/skin/chno/pastel.png'},
|
||||||
{name="Glow (MrZ)", path='media/image/skin/mrz/glow.png'},
|
{name="Classic", path='media/image/skin/unknown/classic.png'},
|
||||||
{name="Plastic (MrZ)", path='media/image/skin/mrz/plastic.png'},
|
{name="Arcade (Asriel)", path='media/image/skin/asriel/arcade.png'},
|
||||||
{name="paper (MrZ)", path='media/image/skin/mrz/paper.png'},
|
{name="Shiny (CHNO)", path='media/image/skin/chno/shiny.png'},
|
||||||
{name="Yinyang (Scf)", path='media/image/skin/scf/yinyang.png'},
|
{name="Brick (Notypey)", path='media/image/skin/notypey/brick.png'},
|
||||||
{name="Cartooncup (Earety)", path='media/image/skin/earety/cartooncup.png'},
|
{name="Cartooncup (Earety)", path='media/image/skin/earety/cartooncup.png'},
|
||||||
{name="Jelly (Miya)", path='media/image/skin/miya/jelly.png'},
|
{name="Paper (MrZ)", path='media/image/skin/mrz/paper.png'},
|
||||||
{name="guidetris (xmiao, lusisi)",path='media/image/skin/guidetris_xmiao_lusisi.png'},
|
{name="Toy (Scf)", path='media/image/skin/scf/toy.png'},
|
||||||
{name="brick (Notypey)", path='media/image/skin/notypey/brick.png'},
|
{name="Polkadots (Scf)", path='media/image/skin/scf/polkadots.png'},
|
||||||
{name="Gem (Notypey)", path='media/image/skin/notypey/gem.png'},
|
{name="Yinyang (Scf)", path='media/image/skin/scf/yinyang.png'},
|
||||||
{name="Classic", path='media/image/skin/unknown/classic.png'},
|
{name="Minoes (Scf)", path='media/image/skin/scf/minoes.png'},
|
||||||
{name="Ball (Shaw)", path='media/image/skin/shaw/ball.png'},
|
{name="Cardboard (Asriel, slimenergy)", path='media/image/skin/asriel/cardboard.png'},
|
||||||
{name="Retro (Notypey)", path='media/image/skin/notypey/retro.png'},
|
{name="Ball (Shaw)", path='media/image/skin/shaw/ball.png'},
|
||||||
{name="Pixel (CHNO)", path='media/image/skin/chno/pixel.png'},
|
{name="Gem (Notypey)", path='media/image/skin/notypey/gem.png'},
|
||||||
{name="Pastel (CHNO)", path='media/image/skin/chno/pastel.png'},
|
{name="Pixel (CHNO)", path='media/image/skin/chno/pixel.png'},
|
||||||
{name="Letters (CHNO)", path='media/image/skin/chno/letters.png'},
|
{name="Retro (Notypey)", path='media/image/skin/notypey/retro.png'},
|
||||||
{name="Kanji (CHNO)", path='media/image/skin/chno/kanji.png'},
|
{name="Guidetris (xmiao, lusisi)", path='media/image/skin/guidetris_xmiao_lusisi.png'},
|
||||||
{name="Textbone (MrZ)", path='media/image/skin/mrz/textbone.png'},
|
{name="Textbone (MrZ)", path='media/image/skin/mrz/textbone.png'},
|
||||||
{name="Coloredbone (MrZ)", path='media/image/skin/mrz/coloredbone.png'},
|
{name="Coloredbone (MrZ)", path='media/image/skin/mrz/coloredbone.png'},
|
||||||
{name="WTF (MrZ)", path='media/image/skin/mrz/wtf.png'},
|
{name="WTF (MrZ)", path='media/image/skin/mrz/wtf.png'},
|
||||||
}
|
}
|
||||||
|
|
||||||
-- Initialize sound libs
|
-- Initialize sound libs
|
||||||
@@ -400,8 +404,12 @@ do
|
|||||||
RANKS.rhythm_h=nil; fs.remove('record/rhythm_h.rec')
|
RANKS.rhythm_h=nil; fs.remove('record/rhythm_h.rec')
|
||||||
RANKS.rhythm_u=nil; fs.remove('record/rhythm_u.rec')
|
RANKS.rhythm_u=nil; fs.remove('record/rhythm_u.rec')
|
||||||
end
|
end
|
||||||
if RANKS.bigbang then fs.remove('record/bigbang.rec') end
|
if RANKS.bigbang then RANKS.bigbang=nil; fs.remove('record/bigbang.rec') end
|
||||||
if RANKS.clearRush then fs.remove('record/clearRush.rec') end
|
if RANKS.clearRush then RANKS.clearRush=nil; fs.remove('record/clearRush.rec') end
|
||||||
|
if RANKS.strategy_e then RANKS.strategy_e=nil; fs.remove('record/strategy_e.rec') end
|
||||||
|
if RANKS.strategy_h_plus then RANKS.strategy_h_plus=nil; fs.remove('record/strategy_h_plus.rec') end
|
||||||
|
if RANKS.strategy_u_plus then RANKS.strategy_u_plus=nil; fs.remove('record/strategy_u_plus.rec') end
|
||||||
|
|
||||||
if STAT.version<1715 then fs.remove('record/dig_quad_10l.rec') end
|
if STAT.version<1715 then fs.remove('record/dig_quad_10l.rec') end
|
||||||
|
|
||||||
if STAT.version~=VERSION.code then
|
if STAT.version~=VERSION.code then
|
||||||
@@ -436,6 +444,7 @@ do
|
|||||||
if SETTING.reTime>3 or SETTING.reTime<.5 then SETTING.reTime=2 end
|
if SETTING.reTime>3 or SETTING.reTime<.5 then SETTING.reTime=2 end
|
||||||
if SETTING.locale=='zh_full' then SETTING.locale='zh' end
|
if SETTING.locale=='zh_full' then SETTING.locale='zh' end
|
||||||
if SETTING.vocPack=='rin' then SETTING.vocPack='miku' end
|
if SETTING.vocPack=='rin' then SETTING.vocPack='miku' end
|
||||||
|
if SETTING.msaa>4 then SETTING.msaa=4 end
|
||||||
if RANKS.infinite then RANKS.infinite=0 end
|
if RANKS.infinite then RANKS.infinite=0 end
|
||||||
if RANKS.infinite_dig then RANKS.infinite_dig=0 end
|
if RANKS.infinite_dig then RANKS.infinite_dig=0 end
|
||||||
if not RANKS.sprint_10l then RANKS.sprint_10l=0 end
|
if not RANKS.sprint_10l then RANKS.sprint_10l=0 end
|
||||||
|
|||||||
@@ -330,20 +330,20 @@ local L={
|
|||||||
},
|
},
|
||||||
cards={-- F0300 - F070F
|
cards={-- F0300 - F070F
|
||||||
cardBack= 0xF0300,
|
cardBack= 0xF0300,
|
||||||
clubA= 0xF0301,
|
spadeA= 0xF0301,
|
||||||
club2= 0xF0302,
|
spade2= 0xF0302,
|
||||||
club3= 0xF0303,
|
spade3= 0xF0303,
|
||||||
club4= 0xF0304,
|
spade4= 0xF0304,
|
||||||
club5= 0xF0305,
|
spade5= 0xF0305,
|
||||||
club6= 0xF0306,
|
spade6= 0xF0306,
|
||||||
club7= 0xF0307,
|
spade7= 0xF0307,
|
||||||
club8= 0xF0308,
|
spade8= 0xF0308,
|
||||||
club9= 0xF0309,
|
spade9= 0xF0309,
|
||||||
club10= 0xF030A,
|
spade10= 0xF030A,
|
||||||
clubJ= 0xF030B,
|
spadeJ= 0xF030B,
|
||||||
clubC= 0xF030C,
|
spadeC= 0xF030C,
|
||||||
clubQ= 0xF030D,
|
spadeQ= 0xF030D,
|
||||||
clubK= 0xF030E,
|
spadeK= 0xF030E,
|
||||||
heartA= 0xF0401,
|
heartA= 0xF0401,
|
||||||
heart2= 0xF0402,
|
heart2= 0xF0402,
|
||||||
heart3= 0xF0403,
|
heart3= 0xF0403,
|
||||||
|
|||||||
@@ -314,6 +314,7 @@ do-- function DATA.saveReplay()
|
|||||||
seed=GAME.seed,
|
seed=GAME.seed,
|
||||||
setting=GAME.setting,
|
setting=GAME.setting,
|
||||||
mod=_getModList(),
|
mod=_getModList(),
|
||||||
|
modApplyAt=GAME.modApplyAt,
|
||||||
tasUsed=GAME.tasUsed,
|
tasUsed=GAME.tasUsed,
|
||||||
}
|
}
|
||||||
if GAME.curMode.savePrivate then
|
if GAME.curMode.savePrivate then
|
||||||
@@ -373,6 +374,7 @@ function DATA.parseReplayData(fileName,fileData,ifFull)
|
|||||||
seed=metaData.seed,
|
seed=metaData.seed,
|
||||||
setting=metaData.setting,
|
setting=metaData.setting,
|
||||||
mod=metaData.mod,
|
mod=metaData.mod,
|
||||||
|
modApplyAt=metaData.modApplyAt,
|
||||||
tasUsed=metaData.tasUsed,
|
tasUsed=metaData.tasUsed,
|
||||||
}
|
}
|
||||||
if ifFull then rep.data=fileData end
|
if ifFull then rep.data=fileData end
|
||||||
|
|||||||
@@ -1,3 +1,7 @@
|
|||||||
|
if SYSTEM=='Web' then
|
||||||
|
return {update=NULL}
|
||||||
|
end
|
||||||
|
|
||||||
local appId='1288557386700951554'
|
local appId='1288557386700951554'
|
||||||
|
|
||||||
local ffi=require"ffi"
|
local ffi=require"ffi"
|
||||||
@@ -133,7 +137,7 @@ if RPC_C then
|
|||||||
|
|
||||||
local function checkIntArg(arg,maxBits,argName,func,maybeNil)
|
local function checkIntArg(arg,maxBits,argName,func,maybeNil)
|
||||||
maxBits=math.min(maxBits or 32,52) -- lua number (double) can only store integers < 2^53
|
maxBits=math.min(maxBits or 32,52) -- lua number (double) can only store integers < 2^53
|
||||||
local maxVal=2^(maxBits-1) -- assuming signed integers, which, for now, are the only ones in use
|
local maxVal=2^(maxBits-1) -- assuming signed integers, which, for now, are the only ones in use
|
||||||
assert(type(arg)=="number" and math.floor(arg)==arg
|
assert(type(arg)=="number" and math.floor(arg)==arg
|
||||||
and arg<maxVal and arg>=-maxVal
|
and arg<maxVal and arg>=-maxVal
|
||||||
or (maybeNil and arg==nil),
|
or (maybeNil and arg==nil),
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ do-- function applySettings()
|
|||||||
BG.set()
|
BG.set()
|
||||||
if SETTING.lockBG then
|
if SETTING.lockBG then
|
||||||
BG.lock()
|
BG.lock()
|
||||||
elseif reason=='lockBG' then -- Don't load theme too soon!
|
elseif reason=='lockBG' then -- We only reload theme again when at settings scene.
|
||||||
THEME.set(THEME.calculate(),GAME.playing)
|
THEME.set(THEME.calculate(),GAME.playing)
|
||||||
end
|
end
|
||||||
elseif SETTING.bg=='off' then
|
elseif SETTING.bg=='off' then
|
||||||
@@ -510,10 +510,8 @@ function mergeStat(stat,delta)-- Merge delta stat. to global stat.
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
function scoreValid()-- Check if any unranked mods are activated
|
function scoreValid()-- Check if any unranked mods are activated
|
||||||
for number,sel in next,GAME.mod do
|
for _,sel in next,GAME.mod do
|
||||||
if sel>0 and MODOPT[number].unranked then
|
if sel>0 then return false end
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
if GAME.playing and GAME.tasUsed then
|
if GAME.playing and GAME.tasUsed then
|
||||||
return false
|
return false
|
||||||
@@ -1000,23 +998,28 @@ do-- function dumpBasicConfig()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
do-- function resetGameData(args)
|
do-- function resetGameData(args)
|
||||||
local function task_showMods() -- TODO
|
local function task_showMods()
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
local counter=0
|
local counter=0
|
||||||
for number,sel in next,GAME.mod do
|
|
||||||
if sel>0 then
|
if usingMod() then
|
||||||
if counter==0 then
|
SFX.play('collect',.2)
|
||||||
coroutine.yield()
|
TEXT.show(GAME.modApplyAt,640,26,45,'spin')
|
||||||
else
|
for _=1,90 do coroutine.yield() end
|
||||||
|
|
||||||
|
for number,sel in next,GAME.mod do
|
||||||
|
if sel>0 then
|
||||||
for _=1,20 do
|
for _=1,20 do
|
||||||
coroutine.yield()
|
coroutine.yield()
|
||||||
end
|
end
|
||||||
|
local M=MODOPT[number]
|
||||||
|
SFX.play('collect',.2)
|
||||||
|
TEXT.show(M.id,640+(counter%5-2)*80,26,45,'spin')
|
||||||
|
counter=counter+1
|
||||||
end
|
end
|
||||||
local M=MODOPT[number]
|
|
||||||
SFX.play('collect',.2)
|
|
||||||
TEXT.show(M.id,640+(counter%5-2)*80,26,45,'spin')
|
|
||||||
counter=counter+1
|
|
||||||
end
|
end
|
||||||
|
for _=1,(counter%5)*20+90 do coroutine.yield() end
|
||||||
|
if GAME.playing then PLAYERS[1].showUsername=true end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local gameSetting={
|
local gameSetting={
|
||||||
|
|||||||
@@ -354,144 +354,172 @@ do-- Mod data
|
|||||||
local function _disableKey(P,key)
|
local function _disableKey(P,key)
|
||||||
table.insert(P.gameEnv.keyCancel,key)
|
table.insert(P.gameEnv.keyCancel,key)
|
||||||
end
|
end
|
||||||
|
local _invisibleTime={
|
||||||
|
['easy'] =300,
|
||||||
|
['slow'] =100,
|
||||||
|
['medium']=60,
|
||||||
|
['fast'] =20,
|
||||||
|
['none'] =0,
|
||||||
|
}
|
||||||
|
local function _lockVfunc(k) do
|
||||||
|
local K=k
|
||||||
|
return function(P,O)
|
||||||
|
P.gameEnv[K]=O or true
|
||||||
|
P.gameEnv.__lock(K)
|
||||||
|
end
|
||||||
|
end end
|
||||||
MODOPT={-- Mod options
|
MODOPT={-- Mod options
|
||||||
{no=0,id="NX",name="next",
|
{no=0,id="NX",name="next",
|
||||||
key="q",x=80,y=230,color='lO',
|
key="q",x=80,y=230,color='lO',
|
||||||
list={0,1,2,3,4,5,6},
|
list={0,1,2,3,4,5,6},
|
||||||
func=function(P,O) P.gameEnv.nextCount=O end,
|
funcInit =function(P,O) P.gameEnv.nextCount=O end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('nextCount'),
|
||||||
},
|
},
|
||||||
{no=1,id="HL",name="hold",
|
{no=1,id="HL",name="hold",
|
||||||
key="w",x=200,y=230,color='lO',
|
key="w",x=200,y=230,color='lO',
|
||||||
list={0,1,2,3,4,5,6},
|
list={0,1,2,3,4,5,6},
|
||||||
func=function(P,O) P.gameEnv.holdCount=O end,
|
funcInit =function(P,O) P.gameEnv.holdCount=O end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('holdCount'),
|
||||||
},
|
},
|
||||||
{no=2,id="FL",name="hideNext",
|
{no=2,id="FL",name="hideNext",
|
||||||
key="e",x=320,y=230,color='lA',
|
key="e",x=320,y=230,color='lA',
|
||||||
list={1,2,3,4,5},
|
list={1,2,3,4,5},
|
||||||
func=function(P,O) P.gameEnv.nextStartPos=O+1 end,
|
funcInit =function(P,O) P.gameEnv.nextStartPos=O+1 end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('nextStartPos'),
|
||||||
},
|
},
|
||||||
{no=3,id="IH",name="infHold",
|
{no=3,id="IH",name="infHold",
|
||||||
key="r",x=440,y=230,color='lA',
|
key="r",x=440,y=230,color='lA',
|
||||||
func=function(P) P.gameEnv.infHold=true end,
|
funcInit =function(P) P.gameEnv.infHold=true end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('infHold'),
|
||||||
},
|
},
|
||||||
{no=4,id="HB",name="hideBlock",
|
{no=4,id="HB",name="hideBlock",
|
||||||
key="y",x=680,y=230,color='lV',
|
key="y",x=680,y=230,color='lV',
|
||||||
func=function(P) P.gameEnv.block=false end,
|
funcInit =function(P) P.gameEnv.block=false end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('block'),
|
||||||
},
|
},
|
||||||
{no=5,id="HG",name="hideGhost",
|
{no=5,id="HG",name="hideGhost",
|
||||||
key="u",x=800,y=230,color='lV',
|
key="u",x=800,y=230,color='lV',
|
||||||
func=function(P) P.gameEnv.ghost=false end,
|
funcInit =function(P) P.gameEnv.ghost=false end,
|
||||||
unranked=true,
|
funcOnce =function(P) P.gameEnv.ghost=false; P.gameEnv.__lock('ghost') end,
|
||||||
},
|
},
|
||||||
{no=6,id="HD",name="hidden",
|
{no=6,id="HD",name="hidden",
|
||||||
key="i",x=920,y=230,color='lP',
|
key="i",x=920,y=230,color='lP',
|
||||||
list={'easy','slow','medium','fast','none'},
|
list={'easy','slow','medium','fast','none'},
|
||||||
func=function(P,O) P.gameEnv.visible=O end,
|
funcInit =function(P,O) P.gameEnv.visible=O end,
|
||||||
unranked=true,
|
funcRepeat=function(P,O)
|
||||||
|
if P.showTime~=_invisibleTime[O] then
|
||||||
|
P:setInvisible(_invisibleTime[O])
|
||||||
|
end
|
||||||
|
end,
|
||||||
},
|
},
|
||||||
{no=7,id="HB",name="hideBoard",
|
{no=7,id="HB",name="hideBoard",
|
||||||
key="o",x=1040,y=230,color='lP',
|
key="o",x=1040,y=230,color='lP',
|
||||||
list={'down','up','all'},
|
list={'down','up','all'},
|
||||||
func=function(P,O) P.gameEnv.hideBoard=O end,
|
funcInit =function(P,O) P.gameEnv.hideBoard=O end,
|
||||||
unranked=true,
|
|
||||||
},
|
},
|
||||||
{no=8,id="FB",name="flipBoard",
|
{no=8,id="FB",name="flipBoard",
|
||||||
key="p",x=1160,y=230,color='lJ',
|
key="p",x=1160,y=230,color='lJ',
|
||||||
list={'U-D','L-R','180'},
|
list={'U-D','L-R','180'},
|
||||||
func=function(P,O) P.gameEnv.flipBoard=O end,
|
funcInit =function(P,O) P.gameEnv.flipBoard=O end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('flipBoard'),
|
||||||
},
|
},
|
||||||
|
|
||||||
{no=9,id="DT",name="dropDelay",
|
{no=9,id="DT",name="dropDelay",
|
||||||
key="a",x=140,y=350,color='lR',
|
key="a",x=140,y=350,color='lR',
|
||||||
list={0,.125,.25,.5,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},
|
list={0,.125,.25,.5,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},
|
||||||
func=function(P,O) P.gameEnv.drop=O end,
|
funcInit =function(P,O) P.gameEnv.drop=O end,
|
||||||
unranked=true,
|
funcRepeat=function(P,O)
|
||||||
|
if P.dropDelay~=O then
|
||||||
|
P.gameEnv.drop=O
|
||||||
|
P:set20G(O==0)
|
||||||
|
end
|
||||||
|
end,
|
||||||
},
|
},
|
||||||
{no=10,id="LT",name="lockDelay",
|
{no=10,id="LT",name="lockDelay",
|
||||||
key="s",x=260,y=350,color='lR',
|
key="s",x=260,y=350,color='lR',
|
||||||
list={0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},
|
list={0,1,2,3,4,5,6,7,8,9,10,12,14,16,18,20,25,30,40,60,180,1e99},
|
||||||
func=function(P,O) P.gameEnv.lock=O end,
|
funcInit =function(P,O) P.gameEnv.lock=O end,
|
||||||
unranked=true,
|
funcRepeat=function(P,O) P.dropDelay=O end,
|
||||||
},
|
},
|
||||||
{no=11,id="ST",name="waitDelay",
|
{no=11,id="ST",name="waitDelay",
|
||||||
key="d",x=380,y=350,color='lR',
|
key="d",x=380,y=350,color='lR',
|
||||||
list={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
|
list={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
|
||||||
func=function(P,O) P.gameEnv.wait=O end,
|
funcInit =function(P,O) P.gameEnv.wait=O end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('waitDelay'),
|
||||||
},
|
},
|
||||||
{no=12,id="CT",name="fallDelay",
|
{no=12,id="CT",name="fallDelay",
|
||||||
key="f",x=500,y=350,color='lR',
|
key="f",x=500,y=350,color='lR',
|
||||||
list={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
|
list={0,1,2,3,4,5,6,7,8,10,15,20,30,60},
|
||||||
func=function(P,O) P.gameEnv.fall=O end,
|
funcInit =function(P,O) P.gameEnv.fall=O end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('fallDelay'),
|
||||||
},
|
},
|
||||||
{no=13,id="LF",name="life",
|
{no=13,id="LF",name="life",
|
||||||
key="j",x=860,y=350,color='lY',
|
key="j",x=860,y=350,color='lY',
|
||||||
list={0,1,2,3,5,10,15,26,42,87,500},
|
list={0,1,2,3,5,10,15,26,42,87,500},
|
||||||
func=function(P,O) P.gameEnv.life=O end,
|
funcInit =function(P,O) P.gameEnv.life=O end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('life'),
|
||||||
},
|
},
|
||||||
{no=14,id="FB",name="forceB2B",
|
{no=14,id="FB",name="forceB2B",
|
||||||
key="k",x=980,y=350,color='lY',
|
key="k",x=980,y=350,color='lY',
|
||||||
func=function(P) P.gameEnv.b2bKill=true end,
|
funcInit =function(P) P.gameEnv.b2bKill=true end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('b2bKill'),
|
||||||
},
|
},
|
||||||
{no=15,id="PF",name="forceFinesse",
|
{no=15,id="PF",name="forceFinesse",
|
||||||
key="l",x=1100,y=350,color='lY',
|
key="l",x=1100,y=350,color='lY',
|
||||||
func=function(P) P.gameEnv.fineKill=true end,
|
funcInit =function(P) P.gameEnv.fineKill=true end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('fineKill'),
|
||||||
},
|
},
|
||||||
|
|
||||||
{no=16,id="TL",name="tele",
|
{no=16,id="TL",name="tele",
|
||||||
key="z",x=200,y=470,color='lH',
|
key="z",x=200,y=470,color='lH',
|
||||||
func=function(P)
|
funcInit =function(P)
|
||||||
P.gameEnv.das,P.gameEnv.arr=0,0
|
P.gameEnv.das,P.gameEnv.arr=0,0
|
||||||
P.gameEnv.sddas,P.gameEnv.sdarr=0,0
|
P.gameEnv.sddas,P.gameEnv.sdarr=0,0
|
||||||
end,
|
end,
|
||||||
unranked=true,
|
funcOnce =function(P)
|
||||||
|
for _,k in pairs{'das','arr','sddas','sdarr'} do
|
||||||
|
P.gameEnv[k]=0
|
||||||
|
P.gameEnv.__lock(k)
|
||||||
|
end
|
||||||
|
end
|
||||||
},
|
},
|
||||||
{no=17,id="FX",name="noRotation",
|
{no=17,id="FX",name="noRotation",
|
||||||
key="x",x=320,y=470,color='lH',
|
key="x",x=320,y=470,color='lH',
|
||||||
func=function(P)
|
funcInit =function(P)
|
||||||
_disableKey(P,3)
|
_disableKey(P,3)
|
||||||
_disableKey(P,4)
|
_disableKey(P,4)
|
||||||
_disableKey(P,5)
|
_disableKey(P,5)
|
||||||
end,
|
end,
|
||||||
unranked=true,
|
|
||||||
},
|
},
|
||||||
{no=18,id="GL",name="noMove",
|
{no=18,id="GL",name="noMove",
|
||||||
key="c",x=440,y=470,color='lH',
|
key="c",x=440,y=470,color='lH',
|
||||||
func=function(P)
|
funcInit =function(P)
|
||||||
_disableKey(P,1)_disableKey(P,2)
|
_disableKey(P,1) _disableKey(P,2)
|
||||||
_disableKey(P,11)_disableKey(P,12)
|
_disableKey(P,11)_disableKey(P,12)
|
||||||
_disableKey(P,17)_disableKey(P,18)
|
_disableKey(P,17)_disableKey(P,18)
|
||||||
_disableKey(P,19)_disableKey(P,20)
|
_disableKey(P,19)_disableKey(P,20)
|
||||||
end,
|
end,
|
||||||
unranked=true,
|
|
||||||
},
|
},
|
||||||
{no=19,id="CS",name="customSeq",
|
{no=19,id="CS",name="customSeq",
|
||||||
key="b",x=680,y=470,color='lB',
|
key="b",x=680,y=470,color='lB',
|
||||||
list={'bag','bagES','his','hisPool','c2','bagP1inf','rnd','mess','reverb'},
|
list={'bag','bagES','his','hisPool','c2','bagP1inf','rnd','mess','reverb'},
|
||||||
func=function(P,O) P.gameEnv.sequence=O end,
|
funcInit =function(P,O) P.gameEnv.sequence=O end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('sequence'),
|
||||||
},
|
},
|
||||||
{no=20,id="PS",name="pushSpeed",
|
{no=20,id="PS",name="pushSpeed",
|
||||||
key="n",x=800,y=470,color='lB',
|
key="n",x=800,y=470,color='lB',
|
||||||
list={.5,1,2,3,5,15,1e99},
|
list={.5,1,2,3,5,15,1e99},
|
||||||
func=function(P,O) P.gameEnv.pushSpeed=O end,
|
funcInit =function(P,O) P.gameEnv.pushSpeed=O end,
|
||||||
unranked=true,
|
funcOnce =_lockVfunc('pushSpeed'),
|
||||||
},
|
},
|
||||||
{no=21,id="BN",name="boneBlock",
|
{no=21,id="BN",name="boneBlock",
|
||||||
key="m",x=920,y=470,color='lB',
|
key="m",x=920,y=470,color='lB',
|
||||||
list={'on','off'},
|
list={'on','off'},
|
||||||
func=function(P,O) P.gameEnv.bone=O=='on' end,
|
funcInit =function(P,O) P.gameEnv.bone=O=='on' end,
|
||||||
unranked=true,
|
funcOnce =function(P,O)
|
||||||
|
P.gameEnv.bone=O=='on'
|
||||||
|
P.gameEnv.__lock('bone')
|
||||||
|
end
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for i=1,#MODOPT do
|
for i=1,#MODOPT do
|
||||||
@@ -521,7 +549,9 @@ do-- Game data tables
|
|||||||
seed=1046101471, -- Game seed
|
seed=1046101471, -- Game seed
|
||||||
curMode=false, -- Current gamemode object
|
curMode=false, -- Current gamemode object
|
||||||
initPlayerCount=0, -- Player count when init game
|
initPlayerCount=0, -- Player count when init game
|
||||||
|
modUsed=false,
|
||||||
mod=TABLE.new(0,#MODOPT),-- List of loaded mods
|
mod=TABLE.new(0,#MODOPT),-- List of loaded mods
|
||||||
|
modApplyAt='postInit', -- Apply mod when? (preInit, postInit, always)
|
||||||
modeEnv=false, -- Current gamemode environment
|
modeEnv=false, -- Current gamemode environment
|
||||||
setting={}, -- Game settings
|
setting={}, -- Game settings
|
||||||
rep={}, -- Recording list, key,time,key,time...
|
rep={}, -- Recording list, key,time,key,time...
|
||||||
|
|||||||
@@ -30,11 +30,11 @@ return {
|
|||||||
"The official website of Techmino!\nYou can download the latest stable build of Techmino and change your profile there.\nClick on the globe icon to open the website in your browser.",
|
"The official website of Techmino!\nYou can download the latest stable build of Techmino and change your profile there.\nClick on the globe icon to open the website in your browser.",
|
||||||
"http://studio26f.org",
|
"http://studio26f.org",
|
||||||
},
|
},
|
||||||
{"Huiji Wiki",
|
{"Chinese Tetris Wiki",
|
||||||
"huiji wiki",
|
"china tetris wiki chinese tetris wiki",
|
||||||
"help",
|
"help",
|
||||||
"(灰机wiki)\nA Chinese Tetris wiki by Tetris enthusiasts from Chinese Tetris Research Community groups and affiliates. Most pages have been referenced and translated from Hard Drop Wiki and Tetris Wiki for now. Link in Simplified Chinese.",
|
"A Chinese Tetris wiki by Tetris enthusiasts from Chinese Tetris Study Community groups and affiliates. Most pages have been referenced and translated from Hard Drop Wiki and Tetris Wiki for now. Link in Simplified Chinese.",
|
||||||
"https://tetris.huijiwiki.com",
|
"http://tetriswiki.cn",
|
||||||
},
|
},
|
||||||
{"Hard Drop Wiki",
|
{"Hard Drop Wiki",
|
||||||
"harddrop hd wiki",
|
"harddrop hd wiki",
|
||||||
|
|||||||
@@ -29,12 +29,12 @@ return {
|
|||||||
"Techminoの公式ホームページです!\n最新の安定版Techminoをダウンロードしたり、プロフィールを編集したりできます\n地球儀ボタンから是非アクセスしてください",
|
"Techminoの公式ホームページです!\n最新の安定版Techminoをダウンロードしたり、プロフィールを編集したりできます\n地球儀ボタンから是非アクセスしてください",
|
||||||
"http://studio26f.org",
|
"http://studio26f.org",
|
||||||
},
|
},
|
||||||
{"灰机wiki",
|
-- {"Chinese Tetris Wiki",
|
||||||
"huiji wiki ウィキ うぃき 灰机 フイジ",
|
-- "china tetris wiki",
|
||||||
"help",
|
-- "help",
|
||||||
"huiji wiki\n\n中国のテトリス研究グループとそのサブグループに所属しているテトリスプレーヤー達が管理している中国のテトリスwikiです\n現在、大部分のページがHard drop wikiとTetris wikiから参照、翻訳されたページになっています",
|
-- "A Chinese Tetris wiki by Tetris enthusiasts from Chinese Tetris Research Community groups and affiliates. Most pages have been referenced and translated from Hard Drop Wiki and Tetris Wiki for now. Link in Simplified Chinese.",
|
||||||
"https://tetris.huijiwiki.com",
|
-- "http://tetriswiki.cn",
|
||||||
},
|
-- },
|
||||||
{"HardDrop wiki",
|
{"HardDrop wiki",
|
||||||
"harddrop hd wiki ハードドロップ ハードロ ウィキ うぃき",
|
"harddrop hd wiki ハードドロップ ハードロ ウィキ うぃき",
|
||||||
"help",
|
"help",
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ Bạn muốn đóng góp vào bản dịch? Bạn có thể vào trang dự án
|
|||||||
08. Bot: Cold Clear, ZZZbot
|
08. Bot: Cold Clear, ZZZbot
|
||||||
|
|
||||||
09. Wiki; các trang web bày setup & cung cấp câu đố, chia sẻ setup
|
09. Wiki; các trang web bày setup & cung cấp câu đố, chia sẻ setup
|
||||||
09A. Wiki: Huiji Wiki, Wiki Hard Drop, tetris.wiki, Tetris Wiki Fandom
|
09A. Wiki: Chinese Tetris Wiki, Wiki Hard Drop, tetris.wiki, Tetris Wiki Fandom
|
||||||
09B. Bày setup: Four.lol, Tetris Hall, Tetris Template Collections, tetristemplate.info, 4-Wide Trainer
|
09B. Bày setup: Four.lol, Tetris Hall, Tetris Template Collections, tetristemplate.info, 4-Wide Trainer
|
||||||
09C. Chia sẻ câu đố: TTT, TTPC, NAZO, TPO
|
09C. Chia sẻ câu đố: TTT, TTPC, NAZO, TPO
|
||||||
09D. Chia sẻ setup: Fumen, Fumen bản Điện thoại
|
09D. Chia sẻ setup: Fumen, Fumen bản Điện thoại
|
||||||
@@ -612,7 +612,7 @@ Xem mục tiếp theo để biết thêm.
|
|||||||
{"Lockdown Delay",
|
{"Lockdown Delay",
|
||||||
"nhom05e1 lockdelay lockdowndelay lockdowntimer ld; thời gian chờ khóa gạch",
|
"nhom05e1 lockdelay lockdowndelay lockdowntimer ld; thời gian chờ khóa gạch",
|
||||||
"term",
|
"term",
|
||||||
"Thời gian chờ khóa gạch, viết tắt là LD.\nGame sẽ chờ một khoảng thời gian, trước khi game khóa gạch (tức là gạch không thể điều khiển được nữa), bắt đầu tính từ khi gạch vừa chạm đất.\n\nTrong các game xếp gạch cổ điển, khoảng thời gian chờ này CHÍNH LÀ khoảng thời gian gạch cần có để di chuyển xuống 1 ô, và không có cơ chế nào để trì hoãn việc khóa gạch.\n\nTrong các game xếp gạch hiện đại, thời gian chờ được tính riêng và thoải mái hơn. Đi kèm với thời gian chờ dài hơn là cơ chế hoãn thời điểm khóa gạch, trong đó bạn có thể di chuyển hoặc xoay gạch bắt game chờ thêm một lúc nữa trước khi khóa gạch; nói theo cách khác, là đặt lại thời gian chờ (tối đa 15 lần trong hầu hết các game).",
|
"Thời gian chờ khóa gạch, viết tắt là LD.\nGame sẽ chờ một khoảng thời gian, trước khi game khóa gạch (tức là gạch không thể điều khiển được nữa), bắt đầu tính từ khi gạch vừa chạm đất.\n\nTrong các game xếp gạch cổ điển, khoảng thời gian chờ này CHÍNH LÀ khoảng thời gian gạch cần có để di chuyển xuống 1 ô, và không có cách nào để hoãn thời điểm khóa gạch.\n\nTrong các game xếp gạch hiện đại, thời gian chờ được tính riêng và thoải mái hơn. Đi kèm với thời gian chờ dài hơn là cơ chế hoãn thời điểm khóa gạch, trong đó bạn có thể di chuyển hoặc xoay gạch để đặt lại bộ đếm thời gian về 0, để bạn có thể hoãn thời điểm khóa gạch thêm một lúc nữa (tối đa 15 lần trong hầu hết các game).",
|
||||||
},
|
},
|
||||||
{"Spawn&ClearDelay",
|
{"Spawn&ClearDelay",
|
||||||
"nhom05e1 spawndelay cleardelay; thời gian chờ gạch sinh ra; thời gian chờ xóa hàng",
|
"nhom05e1 spawndelay cleardelay; thời gian chờ gạch sinh ra; thời gian chờ xóa hàng",
|
||||||
@@ -632,7 +632,7 @@ Xem mục tiếp theo để biết thêm.
|
|||||||
{"Death ARE",
|
{"Death ARE",
|
||||||
"nhom05e1 die delay",
|
"nhom05e1 die delay",
|
||||||
"term",
|
"term",
|
||||||
"Một cơ chế đặc biệt cho phép tránh game over trong một số trường hợp.\n\nDeath ARE sẽ được kích hoạt khi có một viên gạch chặn ngay tại vị trí xuất hiện của gạch mới (dẫn tới hiện tượng block out)\nKhi kích hoạt, spawn ARE sẽ được cộng với Death ARE để cho phép người chơi dùng IRS, IHS hoặc IMS.\n\nÝ tưởng về cơ chế này được đề xuất lần đầu bởi @NOT_A_ROBOT.",
|
"Một cơ chế đặc biệt cho phép tránh game over trong một số trường hợp.\n\nDeath ARE sẽ được kích hoạt khi có một viên gạch chặn ngay tại vị trí xuất hiện của gạch mới (dẫn tới hiện tượng block out)\nKhi kích hoạt, spawn ARE sẽ được cộng với Death ARE để cho phép người chơi có cơ hội dùng IRS, IHS và IMS.\n\nÝ tưởng về cơ chế này được đề xuất lần đầu bởi @NOT_A_ROBOT.",
|
||||||
},
|
},
|
||||||
{">E2|Thg số đ.khiển",
|
{">E2|Thg số đ.khiển",
|
||||||
"nhom05e2",
|
"nhom05e2",
|
||||||
@@ -1436,12 +1436,12 @@ NHÓM 07: MỘT VÀI CƠ CHẾ VÀ CHẾ ĐỘ CỦA MỘT SỐ GAME
|
|||||||
"",
|
"",
|
||||||
""
|
""
|
||||||
},
|
},
|
||||||
{"Huiji Wiki",
|
-- {"Chinese Tetris Wiki",
|
||||||
"nhom09a huiji wiki",
|
-- "china tetris wiki",
|
||||||
"help",
|
-- "help",
|
||||||
"(灰机wiki)\n\nMột wiki về Tetris của những người đam mê Tetris từ các nhóm và chi nhánh của Cộng đồng Nghiên cứu Tetris Trung Quốc. Hiện tại hầu hết các trang đều được tham khảo và dịch từ Wiki Hard Drop và Tetris Wiki. Liên kết sẽ dẫn bạn tới bản tiếng Trung giản thể.",
|
-- "A Chinese Tetris wiki by Tetris enthusiasts from Chinese Tetris Research Community groups and affiliates. Most pages have been referenced and translated from Hard Drop Wiki and Tetris Wiki for now. Link in Simplified Chinese.",
|
||||||
"https://tetris.huijiwiki.com",
|
-- "http://tetriswiki.cn",
|
||||||
},
|
-- },
|
||||||
{"Wiki Hard Drop",
|
{"Wiki Hard Drop",
|
||||||
"nhom09a harddrop hd wiki",
|
"nhom09a harddrop hd wiki",
|
||||||
"help",
|
"help",
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ return {
|
|||||||
"Techmino的官网!\n可以在上面下载游戏本体,或者修改头像以及个人信息。\n\n游戏作者的一些话:强烈不建议在任何公开场合提及甚至宣传Techmino,更不要随便对外发送我们的官网链接!请务必只在私下里向有基础或真的很有兴趣入坑认真玩的玩家推荐,不然很容易拉低社群质量破坏交流氛围,比较难处理,甚至有可能影响游戏的未来发展。为了保证游戏能够变得越来越好玩,千万慎重考虑您对游戏的推广方式!感谢您对Techmino的大力支持!!",
|
"Techmino的官网!\n可以在上面下载游戏本体,或者修改头像以及个人信息。\n\n游戏作者的一些话:强烈不建议在任何公开场合提及甚至宣传Techmino,更不要随便对外发送我们的官网链接!请务必只在私下里向有基础或真的很有兴趣入坑认真玩的玩家推荐,不然很容易拉低社群质量破坏交流氛围,比较难处理,甚至有可能影响游戏的未来发展。为了保证游戏能够变得越来越好玩,千万慎重考虑您对游戏的推广方式!感谢您对Techmino的大力支持!!",
|
||||||
"http://studio26f.org",
|
"http://studio26f.org",
|
||||||
},
|
},
|
||||||
{"灰机Wiki",
|
{"俄罗斯方块中文维基",
|
||||||
"huiji",
|
"zhongwenweiji wiki",
|
||||||
"help",
|
"help",
|
||||||
"俄罗斯方块中文维基,由一群来自俄罗斯方块研究群及下属群的方块同好建立的关于俄罗斯方块的中文百科全书。\n\n目前其大部分页面翻译和参考来自Hard Drop Wiki和Tetris Wiki",
|
"俄罗斯方块中文维基,由一群来自俄罗斯方块研究群及下属群的方块同好建立的关于俄罗斯方块的中文百科全书。\n\n目前其大部分页面翻译和参考来自Hard Drop Wiki和Tetris Wiki",
|
||||||
"https://tetris.huijiwiki.com",
|
"http://tetriswiki.cn",
|
||||||
},
|
},
|
||||||
{"HardDrop Wiki",
|
{"HardDrop Wiki",
|
||||||
"hd",
|
"hd",
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ return {
|
|||||||
tryAnotherBuild="UTF-8 decoding error. If you are using Microsoft Windows, please try to download the build with the different architecture. If you are using the x86 version of Techmino, try downloading the x64 version and vice versa.",
|
tryAnotherBuild="UTF-8 decoding error. If you are using Microsoft Windows, please try to download the build with the different architecture. If you are using the x86 version of Techmino, try downloading the x64 version and vice versa.",
|
||||||
|
|
||||||
modInstruction="Choose your modifiers here!\nMods allow you to change the rules in various ways, but they can also crash the game. Feel free to play the game your way!\nNote that scores are not saved when using mods. You can also toggle mods using your keyboard keys (hold Shift to reverse).",
|
modInstruction="Choose your modifiers here!\nMods allow you to change the rules in various ways, but they can also crash the game. Feel free to play the game your way!\nNote that scores are not saved when using mods. You can also toggle mods using your keyboard keys (hold Shift to reverse).",
|
||||||
|
modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations.",
|
||||||
modInfo={
|
modInfo={
|
||||||
next="NEXT\nOverrides the number of Next pieces displayed.",
|
next="NEXT\nOverrides the number of Next pieces displayed.",
|
||||||
hold="HOLD\nOverrides the number of Hold pieces displayed.",
|
hold="HOLD\nOverrides the number of Hold pieces displayed.",
|
||||||
@@ -449,6 +450,7 @@ C. Gamepad
|
|||||||
},
|
},
|
||||||
mod={
|
mod={
|
||||||
title="Mods",
|
title="Mods",
|
||||||
|
applyAt="Apply during",
|
||||||
reset="Reset (tab)",
|
reset="Reset (tab)",
|
||||||
unranked="Unranked",
|
unranked="Unranked",
|
||||||
},
|
},
|
||||||
@@ -920,12 +922,9 @@ C. Gamepad
|
|||||||
['master_g']= {"Master", "GRADED", "Get the highest grade you can!"},
|
['master_g']= {"Master", "GRADED", "Get the highest grade you can!"},
|
||||||
['master_ex']= {"GrandMaster", "EXTRA", "An eternity shorter than an instant"},
|
['master_ex']= {"GrandMaster", "EXTRA", "An eternity shorter than an instant"},
|
||||||
['master_instinct']= {"Master", "INSTINCT", "What if the active piece becomes invisible?"},
|
['master_instinct']= {"Master", "INSTINCT", "What if the active piece becomes invisible?"},
|
||||||
['strategy_e']= {"Strategy", "EASY", "Fast 20G decision"},
|
['strategy_e_plus']= {"Strategy", "EASY+", "Holdless strategy!"},
|
||||||
['strategy_h']= {"Strategy", "HARD", "Fast 20G decision"},
|
['strategy_h']= {"Strategy", "HARD", "Fast 20G decision"},
|
||||||
['strategy_u']= {"Strategy", "ULTIMATE", "Fast 20G decision"},
|
['strategy_u']= {"Strategy", "ULTIMATE", "Fast 20G decision"},
|
||||||
['strategy_e_plus']= {"Strategy", "EASY+", "Holdless strategy!"},
|
|
||||||
['strategy_h_plus']= {"Strategy", "HARD+", "Holdless strategy!"},
|
|
||||||
['strategy_u_plus']= {"Strategy", "ULTIMATE+", "Holdless strategy!"},
|
|
||||||
['blind_e']= {"Invisible", "SLOW", "For beginners"},
|
['blind_e']= {"Invisible", "SLOW", "For beginners"},
|
||||||
['blind_n']= {"Invisible", "FAST", "For intermediates"},
|
['blind_n']= {"Invisible", "FAST", "For intermediates"},
|
||||||
['blind_h']= {"Invisible", "INSTANT", "For the experienced"},
|
['blind_h']= {"Invisible", "INSTANT", "For the experienced"},
|
||||||
|
|||||||
@@ -208,6 +208,7 @@ return {
|
|||||||
tryAnotherBuild="[UTF-8 Inválido] Si estás usando Windows, intenta descargar Techmino-win32 o Techmino-win64 (el que no estés usando ahora).",
|
tryAnotherBuild="[UTF-8 Inválido] Si estás usando Windows, intenta descargar Techmino-win32 o Techmino-win64 (el que no estés usando ahora).",
|
||||||
|
|
||||||
modInstruction="¡Elige tus mods!\nLos mods permiten modificar el juego,\npero también es posible que lo crasheen.\nLos scores no se guardan durante el uso de mods.",
|
modInstruction="¡Elige tus mods!\nLos mods permiten modificar el juego,\npero también es posible que lo crasheen.\nLos scores no se guardan durante el uso de mods.",
|
||||||
|
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||||
modInfo={
|
modInfo={
|
||||||
next="NEXT\nSobreescribe el nro. de piezas siguientes a mostrar.",
|
next="NEXT\nSobreescribe el nro. de piezas siguientes a mostrar.",
|
||||||
hold="HOLD\nSobreescribe el nro. de piezas en reserva disponibles.",
|
hold="HOLD\nSobreescribe el nro. de piezas en reserva disponibles.",
|
||||||
@@ -411,6 +412,7 @@ return {
|
|||||||
mod={
|
mod={
|
||||||
title="Mods",
|
title="Mods",
|
||||||
reset="Reinic. (tab)",
|
reset="Reinic. (tab)",
|
||||||
|
-- applyAt="Apply during",
|
||||||
unranked="Sin rango",
|
unranked="Sin rango",
|
||||||
},
|
},
|
||||||
pause={
|
pause={
|
||||||
@@ -877,12 +879,9 @@ return {
|
|||||||
['master_g']= {"Master", "Con rangos", "¡Consigue el rango más alto que puedas!"},
|
['master_g']= {"Master", "Con rangos", "¡Consigue el rango más alto que puedas!"},
|
||||||
['master_ex']= {"GrandMaster", "Extra", "Una eternidad que dura un instante."},
|
['master_ex']= {"GrandMaster", "Extra", "Una eternidad que dura un instante."},
|
||||||
['master_instinct']={"Master", "Instintivo", "¿Y si la pieza activa es invisible?"},
|
['master_instinct']={"Master", "Instintivo", "¿Y si la pieza activa es invisible?"},
|
||||||
['strategy_e']= {"Strategy", "Fácil", "Decisiones rápidas en 20G."},
|
['strategy_e_plus']={"Strategy", "Fácil+", "Lo mismo pero sin reserva!"},
|
||||||
['strategy_h']= {"Strategy", "Difícil", "Decisiones rápidas en 20G."},
|
['strategy_h']= {"Strategy", "Difícil", "Decisiones rápidas en 20G."},
|
||||||
['strategy_u']= {"Strategy", "Supremo", "Decisiones rápidas en 20G."},
|
['strategy_u']= {"Strategy", "Supremo", "Decisiones rápidas en 20G."},
|
||||||
['strategy_e_plus']={"Strategy", "Fácil+", "Lo mismo pero sin reserva!"},
|
|
||||||
['strategy_h_plus']={"Strategy", "Difícil+", "Lo mismo pero sin reserva!"},
|
|
||||||
['strategy_u_plus']={"Strategy", "Supremo+", "Lo mismo pero sin reserva!"},
|
|
||||||
-- ['blind_e']= {"Invisible", "SLOW", "For beginners"},
|
-- ['blind_e']= {"Invisible", "SLOW", "For beginners"},
|
||||||
-- ['blind_n']= {"Invisible", "FAST", "For intermediates"},
|
-- ['blind_n']= {"Invisible", "FAST", "For intermediates"},
|
||||||
-- ['blind_h']= {"Invisible", "INSTANT", "For the experienced"},
|
-- ['blind_h']= {"Invisible", "INSTANT", "For the experienced"},
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ return {
|
|||||||
-- tryAnotherBuild="[Invalid UTF-8] If you are on Windows, try downloading Techmino-win32 or Techmino-win64 (different from what you are using now).",
|
-- tryAnotherBuild="[Invalid UTF-8] If you are on Windows, try downloading Techmino-win32 or Techmino-win64 (different from what you are using now).",
|
||||||
|
|
||||||
modInstruction="",
|
modInstruction="",
|
||||||
|
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||||
modInfo={},-- See lang_en.lua
|
modInfo={},-- See lang_en.lua
|
||||||
pauseStat={
|
pauseStat={
|
||||||
"Temps :",
|
"Temps :",
|
||||||
@@ -242,6 +243,7 @@ return {
|
|||||||
"Ceci est un simple jeu de blocs.",
|
"Ceci est un simple jeu de blocs.",
|
||||||
"On y joue comme sur C2/IO/JS/WWC/KOS et autres.",
|
"On y joue comme sur C2/IO/JS/WWC/KOS et autres.",
|
||||||
"",
|
"",
|
||||||
|
"Propulsé par LÖVE",
|
||||||
"Vous pouvez envoyer des rapports de bogues ou des suggestions via le groupe de test ou l'email du créateur ~",
|
"Vous pouvez envoyer des rapports de bogues ou des suggestions via le groupe de test ou l'email du créateur ~",
|
||||||
"Assurez-vous d'obtenir le jeu uniquement des canaux officiels,",
|
"Assurez-vous d'obtenir le jeu uniquement des canaux officiels,",
|
||||||
"Ne téléchargez pas ce jeu depuis une autre source au risque d'avoir des virus,",
|
"Ne téléchargez pas ce jeu depuis une autre source au risque d'avoir des virus,",
|
||||||
@@ -386,6 +388,7 @@ return {
|
|||||||
mod={
|
mod={
|
||||||
title="Mods",
|
title="Mods",
|
||||||
reset="Réinitialiser (tab)",
|
reset="Réinitialiser (tab)",
|
||||||
|
-- applyAt="Apply during",
|
||||||
unranked="Unranked",
|
unranked="Unranked",
|
||||||
},
|
},
|
||||||
pause={
|
pause={
|
||||||
@@ -850,12 +853,9 @@ return {
|
|||||||
['master_final']= {"Master", "FINAL", "20G : Un point final impossible à atteindre !"},
|
['master_final']= {"Master", "FINAL", "20G : Un point final impossible à atteindre !"},
|
||||||
-- ['master_ph']= {"Master", "FANTASMA", "20G: ???"},
|
-- ['master_ph']= {"Master", "FANTASMA", "20G: ???"},
|
||||||
['master_ex']= {"GrandMaster", "EXTRA", "Tentez de devenir un Grandmaster."},
|
['master_ex']= {"GrandMaster", "EXTRA", "Tentez de devenir un Grandmaster."},
|
||||||
['strategy_e']= {"Stratégie", "FACILE", "Décision rapide 20G"},
|
['strategy_e_plus']={"Stratégie", "FACILE+", "Stratégie sans retenue"},
|
||||||
['strategy_h']= {"Stratégie", "DIFFICILE", "Décision rapide 20G"},
|
['strategy_h']= {"Stratégie", "DIFFICILE", "Décision rapide 20G"},
|
||||||
['strategy_u']= {"Stratégie", "ULTIME", "Décision rapide 20G"},
|
['strategy_u']= {"Stratégie", "ULTIME", "Décision rapide 20G"},
|
||||||
['strategy_e_plus']={"Stratégie", "FACILE+", "Stratégie sans retenue"},
|
|
||||||
['strategy_h_plus']={"Stratégie", "DIFFICILE+", "Stratégie sans retenue"},
|
|
||||||
['strategy_u_plus']={"Stratégie", "ULTIME+", "Stratégie sans retenue"},
|
|
||||||
-- ['blind_e']= {"Invisible", "SLOW", "For beginners"},
|
-- ['blind_e']= {"Invisible", "SLOW", "For beginners"},
|
||||||
-- ['blind_n']= {"Invisible", "FAST", "For intermediates"},
|
-- ['blind_n']= {"Invisible", "FAST", "For intermediates"},
|
||||||
-- ['blind_h']= {"Invisible", "INSTANT", "For the experienced"},
|
-- ['blind_h']= {"Invisible", "INSTANT", "For the experienced"},
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ return {
|
|||||||
errorMsg="Techmino mengalami eror dan harus memuat ulang.\nAnda bisa mengirim log eror ke developer.",
|
errorMsg="Techmino mengalami eror dan harus memuat ulang.\nAnda bisa mengirim log eror ke developer.",
|
||||||
|
|
||||||
modInstruction="Pilih mod Anda!\nMod memungkinkan Anda untuk mengubah permainan,\ntetapi juga bisa menghancur permainan.\nNilai-nilai tidak akan disimpan saat menggunakan mod.",
|
modInstruction="Pilih mod Anda!\nMod memungkinkan Anda untuk mengubah permainan,\ntetapi juga bisa menghancur permainan.\nNilai-nilai tidak akan disimpan saat menggunakan mod.",
|
||||||
|
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||||
modInfo={
|
modInfo={
|
||||||
next="BLOK LANJUT\nMengubah jumlah pratinjau blok lanjut yang ditampilkan.",
|
next="BLOK LANJUT\nMengubah jumlah pratinjau blok lanjut yang ditampilkan.",
|
||||||
hold="SIMPAN\nMengubah jumlah blok yang bisa disimpan.",
|
hold="SIMPAN\nMengubah jumlah blok yang bisa disimpan.",
|
||||||
@@ -412,6 +413,7 @@ return {
|
|||||||
mod={
|
mod={
|
||||||
title="Mod",
|
title="Mod",
|
||||||
reset="Reset (tab)",
|
reset="Reset (tab)",
|
||||||
|
-- applyAt="Apply during",
|
||||||
unranked="Tidak Berperingkat",
|
unranked="Tidak Berperingkat",
|
||||||
},
|
},
|
||||||
pause={
|
pause={
|
||||||
@@ -881,12 +883,9 @@ return {
|
|||||||
['master_g']= {"Ahli", "BERTINGKAT", "Dapatkan tingkat tertinggi!"},
|
['master_g']= {"Ahli", "BERTINGKAT", "Dapatkan tingkat tertinggi!"},
|
||||||
['master_ex']= {"Sangat Ahli", "EKSTRA", "Blok tidak kelihatan"},
|
['master_ex']= {"Sangat Ahli", "EKSTRA", "Blok tidak kelihatan"},
|
||||||
['master_instinct']= {"Ahli", "INSTINK", "Bagaimana jika blok terkontrol tersembunyi?"},
|
['master_instinct']= {"Ahli", "INSTINK", "Bagaimana jika blok terkontrol tersembunyi?"},
|
||||||
['strategy_e']= {"Strategi", "MUDAH", "Keputusan 20G cepat"},
|
['strategy_e_plus']= {"Strategi", "MUDAH+", "Mode strategi, tetapi tanpa menyimpan"},
|
||||||
['strategy_h']= {"Strategi", "SULIT", "Keputusan 20G cepat"},
|
['strategy_h']= {"Strategi", "SULIT", "Keputusan 20G cepat"},
|
||||||
['strategy_u']= {"Strategi", "TERAKHIR", "Keputusan 20G cepat"},
|
['strategy_u']= {"Strategi", "TERAKHIR", "Keputusan 20G cepat"},
|
||||||
['strategy_e_plus']= {"Strategi", "MUDAH+", "Mode strategi, tetapi tanpa menyimpan"},
|
|
||||||
['strategy_h_plus']= {"Strategi", "SULIT+", "Mode strategi, tetapi tanpa menyimpan"},
|
|
||||||
['strategy_u_plus']= {"Strategi", "TERAKHIR+", "Mode strategi, tetapi tanpa menyimpan"},
|
|
||||||
['blind_e']= {"Tak Terlihat", "PELAN", "Untuk pemula"},
|
['blind_e']= {"Tak Terlihat", "PELAN", "Untuk pemula"},
|
||||||
['blind_n']= {"Tak Terlihat", "CEPAT", "Untuk amatir"},
|
['blind_n']= {"Tak Terlihat", "CEPAT", "Untuk amatir"},
|
||||||
['blind_h']= {"Tak Terlihat", "INSTAN", "Untuk orang berpengalaman"},
|
['blind_h']= {"Tak Terlihat", "INSTAN", "Untuk orang berpengalaman"},
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ return {
|
|||||||
tryAnotherBuild="[Invalid UTF-8]使用しているOSがMicrosoft WindowsであればTechmino-win32かTechmino-win64をダウンロードしてください! (現在使用しているソフトは違うバージョンです)",
|
tryAnotherBuild="[Invalid UTF-8]使用しているOSがMicrosoft WindowsであればTechmino-win32かTechmino-win64をダウンロードしてください! (現在使用しているソフトは違うバージョンです)",
|
||||||
|
|
||||||
modInstruction="Modを選択してください!\nModはゲームルールを変えられますが正常にプレイできなくなる可能性があります\nModを使用した場合、スコアは保存されません",
|
modInstruction="Modを選択してください!\nModはゲームルールを変えられますが正常にプレイできなくなる可能性があります\nModを使用した場合、スコアは保存されません",
|
||||||
|
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||||
modInfo={
|
modInfo={
|
||||||
next="NEXT\nNEXTの個数を変更します",
|
next="NEXT\nNEXTの個数を変更します",
|
||||||
hold="HOLD\nHOLDの個数を変更します",
|
hold="HOLD\nHOLDの個数を変更します",
|
||||||
@@ -456,6 +457,7 @@ C. ゲームパッド
|
|||||||
mod={
|
mod={
|
||||||
title="Mods",
|
title="Mods",
|
||||||
reset="リセット (tab)",
|
reset="リセット (tab)",
|
||||||
|
-- applyAt="Apply during",
|
||||||
unranked="記録不可",
|
unranked="記録不可",
|
||||||
},
|
},
|
||||||
pause={
|
pause={
|
||||||
@@ -925,12 +927,9 @@ C. ゲームパッド
|
|||||||
['master_g']= {"マスター", "GRADED", "最高段位を取れ!"},
|
['master_g']= {"マスター", "GRADED", "最高段位を取れ!"},
|
||||||
['master_ex']= {"グランドマスター", "EXTRA", "一瞬にも満たない永遠"},
|
['master_ex']= {"グランドマスター", "EXTRA", "一瞬にも満たない永遠"},
|
||||||
['master_instinct']= {"マスター", "INSTINCT", "もしミノが見えなくなったら?"},
|
['master_instinct']= {"マスター", "INSTINCT", "もしミノが見えなくなったら?"},
|
||||||
['strategy_e']= {"ストラテジー", "EASY", "20Gでの素早い判断"},
|
['strategy_e_plus']= {"ストラテジー", "EASY+", "20Gでの素早い判断"},
|
||||||
['strategy_h']= {"ストラテジー", "HARD", "20Gでの素早い判断"},
|
['strategy_h']= {"ストラテジー", "HARD", "20Gでの素早い判断"},
|
||||||
['strategy_u']= {"ストラテジー", "ULTIMATE", "20Gでの素早い判断"},
|
['strategy_u']= {"ストラテジー", "ULTIMATE", "20Gでの素早い判断"},
|
||||||
['strategy_e_plus']= {"ストラテジー", "EASY+", "20Gでの素早い判断"},
|
|
||||||
['strategy_h_plus']= {"ストラテジー", "HARD+", "20Gでの素早い判断"},
|
|
||||||
['strategy_u_plus']= {"ストラテジー", "ULTIMATE+", "20Gでの素早い判断"},
|
|
||||||
['blind_e']= {"インビジブル", "HALF", "初心者用"},
|
['blind_e']= {"インビジブル", "HALF", "初心者用"},
|
||||||
['blind_n']= {"インビジブル", "ALL", "中級者用"},
|
['blind_n']= {"インビジブル", "ALL", "中級者用"},
|
||||||
['blind_h']= {"インビジブル", "SUDDEN", "上級者用"},
|
['blind_h']= {"インビジブル", "SUDDEN", "上級者用"},
|
||||||
|
|||||||
@@ -197,6 +197,7 @@ return {
|
|||||||
-- tryAnotherBuild="[Invalid UTF-8] If you are on Windows, try downloading Techmino-win32 or Techmino-win64 (different from what you are using now).",
|
-- tryAnotherBuild="[Invalid UTF-8] If you are on Windows, try downloading Techmino-win32 or Techmino-win64 (different from what you are using now).",
|
||||||
|
|
||||||
modInstruction="Selecione mods (modificadores) para usar!\nMods irão modificar o jogo em formas diferentes\n(e possivelmente quebrar o jogo de formas estranhas).\nAlguns mods irão fazer seu jogo unranked.",
|
modInstruction="Selecione mods (modificadores) para usar!\nMods irão modificar o jogo em formas diferentes\n(e possivelmente quebrar o jogo de formas estranhas).\nAlguns mods irão fazer seu jogo unranked.",
|
||||||
|
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||||
modInfo={
|
modInfo={
|
||||||
next="Próximo\nSobrepõe a largura da fila de próximos",
|
next="Próximo\nSobrepõe a largura da fila de próximos",
|
||||||
hold="Segure\nSobrepõe a largura da fila de segurar",
|
hold="Segure\nSobrepõe a largura da fila de segurar",
|
||||||
@@ -400,6 +401,7 @@ return {
|
|||||||
mod={
|
mod={
|
||||||
title="Mods",
|
title="Mods",
|
||||||
reset="Reset (tab)",
|
reset="Reset (tab)",
|
||||||
|
-- applyAt="Apply during",
|
||||||
unranked="Unranked",
|
unranked="Unranked",
|
||||||
},
|
},
|
||||||
pause={
|
pause={
|
||||||
@@ -863,12 +865,9 @@ return {
|
|||||||
['master_final']= {"Mestre", "FINAL", "20G: Final inalcançável!"},
|
['master_final']= {"Mestre", "FINAL", "20G: Final inalcançável!"},
|
||||||
['master_ph']= {"Mestre", "FANTASMA", "20G: ???"},
|
['master_ph']= {"Mestre", "FANTASMA", "20G: ???"},
|
||||||
['master_ex']= {"GrandMaster", "EXTRA", "Para ser um Grand Master, aceite \nesse desafio."},
|
['master_ex']= {"GrandMaster", "EXTRA", "Para ser um Grand Master, aceite \nesse desafio."},
|
||||||
-- ['strategy_e']= {"Strategy", "EASY", "Fast 20G decision"},
|
-- ['strategy_e_plus']={"Strategy", "EASY+", "Holdless strategy"},
|
||||||
-- ['strategy_h']= {"Strategy", "HARD", "Fast 20G decision"},
|
-- ['strategy_h']= {"Strategy", "HARD", "Fast 20G decision"},
|
||||||
-- ['strategy_u']= {"Strategy", "ULTIMATE", "Fast 20G decision"},
|
-- ['strategy_u']= {"Strategy", "ULTIMATE", "Fast 20G decision"},
|
||||||
-- ['strategy_e_plus']={"Strategy", "EASY+", "Holdless strategy"},
|
|
||||||
-- ['strategy_h_plus']={"Strategy", "HARD+", "Holdless strategy"},
|
|
||||||
-- ['strategy_u_plus']={"Strategy", "ULTIMATE+", "Holdless strategy"},
|
|
||||||
-- ['blind_e']= {"Invisible", "SLOW", "For beginners"},
|
-- ['blind_e']= {"Invisible", "SLOW", "For beginners"},
|
||||||
-- ['blind_n']= {"Invisible", "FAST", "For intermediates"},
|
-- ['blind_n']= {"Invisible", "FAST", "For intermediates"},
|
||||||
-- ['blind_h']= {"Invisible", "INSTANT", "For the experienced"},
|
-- ['blind_h']= {"Invisible", "INSTANT", "For the experienced"},
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ return {
|
|||||||
mod={
|
mod={
|
||||||
title="?!?!?!",
|
title="?!?!?!",
|
||||||
reset="R (tab)",
|
reset="R (tab)",
|
||||||
|
applyAt="--:-- >[?!?!?!]",
|
||||||
unranked="X!!!",
|
unranked="X!!!",
|
||||||
},
|
},
|
||||||
pause={
|
pause={
|
||||||
|
|||||||
@@ -204,6 +204,7 @@ return {
|
|||||||
tryAnotherBuild="LOI UTF-8! Neu dang choi Techmino tren Windows: hay doi tu x86 sang x64 va nguoc lai.",
|
tryAnotherBuild="LOI UTF-8! Neu dang choi Techmino tren Windows: hay doi tu x86 sang x64 va nguoc lai.",
|
||||||
|
|
||||||
modInstruction="Hãy chọn modifier bạn muốn.\nMod cho phép bạn có thể tùy biến game, nhưng cũng có thể làm game sập.\nKể cả thế, hãy thoải mái và chơi theo cách của bạn!\nBạn có thể dùng bàn phím để chọn mod (giữ Shift để chọn lùi)\nĐiểm sẽ không được lưu lại khi dùng mod.",
|
modInstruction="Hãy chọn modifier bạn muốn.\nMod cho phép bạn có thể tùy biến game, nhưng cũng có thể làm game sập.\nKể cả thế, hãy thoải mái và chơi theo cách của bạn!\nBạn có thể dùng bàn phím để chọn mod (giữ Shift để chọn lùi)\nĐiểm sẽ không được lưu lại khi dùng mod.",
|
||||||
|
modApplyAtInstruction="Chọn thời điểm bạn muốn mod được áp dụng.\npreInit: Trước khi nạp game. Đây là tùy chọn mặc định từ phiên bản 0.17.15 trở về trước. Một số mod có thể gặp vấn đề nếu dùng tùy chọn này.\npostInit: Sau khi nạp chế độ chơi, có thể sửa được một số lỗi ở preInit. Tuy nhiên, mod có thể bị mất tác dụng ở một số trường hợp nhất định.\nalways: Luôn áp dụng trong cả game. Tùy chọn này sẽ giúp bạn giữ lại tác dụng của mod dù ở bất kì trường hợp nào.",
|
||||||
modInfo={
|
modInfo={
|
||||||
next="NEXT\nGhi đè số gạch hiển thị ở hàng NEXT",
|
next="NEXT\nGhi đè số gạch hiển thị ở hàng NEXT",
|
||||||
hold="HOLD\nGhi đè số lượng gạch được giữ ở cột HOLD",
|
hold="HOLD\nGhi đè số lượng gạch được giữ ở cột HOLD",
|
||||||
@@ -445,6 +446,7 @@ C. Tay cầm chơi game (Gamepad):
|
|||||||
mod={
|
mod={
|
||||||
title="Mods",
|
title="Mods",
|
||||||
reset="Đặt lại (tab)",
|
reset="Đặt lại (tab)",
|
||||||
|
applyAt="Áp dụng mod khi",
|
||||||
unranked="Không tính điểm",
|
unranked="Không tính điểm",
|
||||||
},
|
},
|
||||||
pause={
|
pause={
|
||||||
@@ -923,12 +925,9 @@ C. Tay cầm chơi game (Gamepad):
|
|||||||
['master_g']= {"Master", "GRADED", "Lấy điểm cao nhất có thể!"},
|
['master_g']= {"Master", "GRADED", "Lấy điểm cao nhất có thể!"},
|
||||||
['master_ex']= {"GrandMaster", "EXTRA", "Cũng là lấy điểm cao nhất có thể nhưng mà gắt hơn!"},
|
['master_ex']= {"GrandMaster", "EXTRA", "Cũng là lấy điểm cao nhất có thể nhưng mà gắt hơn!"},
|
||||||
['master_instinct']= {"Master", "INSTINCT", "Lấy điểm cao nhất có thể nhưng với gạch tàng hình!"},
|
['master_instinct']= {"Master", "INSTINCT", "Lấy điểm cao nhất có thể nhưng với gạch tàng hình!"},
|
||||||
['strategy_e']= {"Strategy", "DỄ", "Quyết định nhanh hoặc là thua"},
|
['strategy_e_plus']= {"Strategy", "DỄ+", "Quyết định nhanh và không được Hold!"},
|
||||||
['strategy_h']= {"Strategy", "KHÓ", "Quyết định nhanh hoặc là thua"},
|
['strategy_h']= {"Strategy", "KHÓ", "Quyết định nhanh hoặc là thua"},
|
||||||
['strategy_u']= {"Strategy", "THÁCH ĐẤU", "Quyết định nhanh hoặc là thua"},
|
['strategy_u']= {"Strategy", "THÁCH ĐẤU", "Quyết định nhanh hoặc là thua"},
|
||||||
['strategy_e_plus']= {"Strategy", "DỄ+", "Quyết định nhanh và không được Hold!"},
|
|
||||||
['strategy_h_plus']= {"Strategy", "KHÓ+", "Quyết định nhanh và không được Hold!"},
|
|
||||||
['strategy_u_plus']= {"Strategy", "THÁCH ĐẤU+", "Quyết định nhanh và không được Hold!"},
|
|
||||||
['blind_e']= {"Invisible", "DỄ", "Dành cho người mới"},
|
['blind_e']= {"Invisible", "DỄ", "Dành cho người mới"},
|
||||||
['blind_n']= {"Invisible", "THƯỜNG", "Dành cho người đã quen"},
|
['blind_n']= {"Invisible", "THƯỜNG", "Dành cho người đã quen"},
|
||||||
['blind_h']= {"Invisible", "KHÓ", "Dành cho người đã có kinh nghiệm"},
|
['blind_h']= {"Invisible", "KHÓ", "Dành cho người đã có kinh nghiệm"},
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ return {
|
|||||||
tryAnotherBuild="[解码UTF-8错误] 如果你现在用的是Windows系统,请重新下载 Techmino-32/64位 (和现在运行的不一样的那个)。",
|
tryAnotherBuild="[解码UTF-8错误] 如果你现在用的是Windows系统,请重新下载 Techmino-32/64位 (和现在运行的不一样的那个)。",
|
||||||
|
|
||||||
modInstruction="选择你要使用的Mod!\n不同Mod会用不同的方式改变初始游戏规则(可能导致不能正常游玩)\n来开发新玩法或者挑战自我吧!\n提醒:开启一些Mod会让成绩无效,你也可以用键盘开关Mod,按住shift反向",
|
modInstruction="选择你要使用的Mod!\n不同Mod会用不同的方式改变初始游戏规则(可能导致不能正常游玩)\n来开发新玩法或者挑战自我吧!\n提醒:开启一些Mod会让成绩无效,你也可以用键盘开关Mod,按住shift反向",
|
||||||
|
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||||
modInfo={
|
modInfo={
|
||||||
next="Next数量:\n强制使用Next的个数",
|
next="Next数量:\n强制使用Next的个数",
|
||||||
hold="Hold数量:\n强制使用Hold的个数",
|
hold="Hold数量:\n强制使用Hold的个数",
|
||||||
@@ -909,12 +910,9 @@ return {
|
|||||||
['master_g']= {"大师", "段位考试", "20G段位考试"},
|
['master_g']= {"大师", "段位考试", "20G段位考试"},
|
||||||
['master_ex']= {"宗师", "EX", "成为方块大师"},
|
['master_ex']= {"宗师", "EX", "成为方块大师"},
|
||||||
['master_instinct']={"大师", "本能", "当前块在出现后一小会后会隐形"},
|
['master_instinct']={"大师", "本能", "当前块在出现后一小会后会隐形"},
|
||||||
['strategy_e']= {"策略堆叠", "简单", "20G堆叠中速决策练习"},
|
['strategy_e_plus']={"策略堆叠", "简单+", "20G堆叠中速决策练习\n无Hold"},
|
||||||
['strategy_h']= {"策略堆叠", "困难", "20G堆叠快速决策练习"},
|
['strategy_h']= {"策略堆叠", "困难", "20G堆叠快速决策练习"},
|
||||||
['strategy_u']= {"策略堆叠", "极限", "20G堆叠极速决策练习"},
|
['strategy_u']= {"策略堆叠", "极限", "20G堆叠极速决策练习"},
|
||||||
['strategy_e_plus']={"策略堆叠", "简单+", "20G堆叠中速决策练习\n无Hold"},
|
|
||||||
['strategy_h_plus']={"策略堆叠", "困难+", "20G堆叠快速决策练习\n无Hold"},
|
|
||||||
['strategy_u_plus']={"策略堆叠", "极限+", "20G堆叠极速决策练习\n无Hold"},
|
|
||||||
['blind_e']= {"隐形", "半隐", "不强大脑"},
|
['blind_e']= {"隐形", "半隐", "不强大脑"},
|
||||||
['blind_n']= {"隐形", "全隐", "挺强大脑"},
|
['blind_n']= {"隐形", "全隐", "挺强大脑"},
|
||||||
['blind_h']= {"隐形", "瞬隐", "很强大脑"},
|
['blind_h']= {"隐形", "瞬隐", "很强大脑"},
|
||||||
@@ -1060,7 +1058,7 @@ return {
|
|||||||
"游戏原声已上架网易云音乐",
|
"游戏原声已上架网易云音乐",
|
||||||
"有建议的话可以反馈给作者~",
|
"有建议的话可以反馈给作者~",
|
||||||
"这不是休闲游戏……别怪关卡要求太高,多练吧",
|
"这不是休闲游戏……别怪关卡要求太高,多练吧",
|
||||||
"中文方块百科全书:tetris.huijiwiki.com",
|
"中文方块百科全书:tetriswiki.cn",
|
||||||
"众所周知mac不能拿来玩游戏",
|
"众所周知mac不能拿来玩游戏",
|
||||||
"作业没做完别玩手机",
|
"作业没做完别玩手机",
|
||||||
"作者40行sub26了",
|
"作者40行sub26了",
|
||||||
|
|||||||
@@ -157,6 +157,8 @@ return {
|
|||||||
tryAnotherBuild="Error.DecodeUTF8(); //如果你现在用的是Windows系统,请重新下载 Techmino-32/64位 (和现在运行的不一样的那个)。",
|
tryAnotherBuild="Error.DecodeUTF8(); //如果你现在用的是Windows系统,请重新下载 Techmino-32/64位 (和现在运行的不一样的那个)。",
|
||||||
|
|
||||||
modInstruction="Mod.Instruction();\n/*选择你要使用的Mod\n不同Mod会用不同的方式改变初始游戏规则(可能导致不能正常游玩)\n提醒:开启一些Mod会让成绩无效,你也可以用键盘开关Mod,按住shift反向*/",
|
modInstruction="Mod.Instruction();\n/*选择你要使用的Mod\n不同Mod会用不同的方式改变初始游戏规则(可能导致不能正常游玩)\n提醒:开启一些Mod会让成绩无效,你也可以用键盘开关Mod,按住shift反向*/",
|
||||||
|
-- [[[NEED TRANSLATING!]]]
|
||||||
|
modApplyAtInstruction="Mod.ApplyDuring=PLAYERS[1].username=='shoucandanghehe' ? 'preInit' : 'postInit' --[[\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations.]]",
|
||||||
modInfo={
|
modInfo={
|
||||||
next="Mod.Next();\n//强制使用Next的个数",
|
next="Mod.Next();\n//强制使用Next的个数",
|
||||||
hold="Mod.Hold\n//强制使用Hold的个数",
|
hold="Mod.Hold\n//强制使用Hold的个数",
|
||||||
@@ -359,6 +361,7 @@ return {
|
|||||||
},
|
},
|
||||||
mod={
|
mod={
|
||||||
title="GameMod.UI",
|
title="GameMod.UI",
|
||||||
|
applyAt="Mod.ApplyDuring=",
|
||||||
reset="Mod.Reset();",
|
reset="Mod.Reset();",
|
||||||
unranked="unranked=true",
|
unranked="unranked=true",
|
||||||
},
|
},
|
||||||
@@ -828,12 +831,9 @@ return {
|
|||||||
['master_g']= {"Master(Graded);", "", "20G段位考试"},
|
['master_g']= {"Master(Graded);", "", "20G段位考试"},
|
||||||
['master_ex']= {"Master(EX);", "", "成为方块大师"},
|
['master_ex']= {"Master(EX);", "", "成为方块大师"},
|
||||||
['master_instinct']= {"Master(Instinct);", "", "当前块在出现后一小会后会隐形"},
|
['master_instinct']= {"Master(Instinct);", "", "当前块在出现后一小会后会隐形"},
|
||||||
['strategy_e']= {"Strategy(Easy);", "", "20G堆叠中速决策练习"},
|
['strategy_e_plus']= {"Strategy(EasyP);", "", "20G堆叠中速决策练习\n无Hold"},
|
||||||
['strategy_h']= {"Strategy(Hard);", "", "20G堆叠快速决策练习"},
|
['strategy_h']= {"Strategy(Hard);", "", "20G堆叠快速决策练习"},
|
||||||
['strategy_u']= {"Strategy(Ultimate);", "", "20G堆叠极速决策练习"},
|
['strategy_u']= {"Strategy(Ultimate);", "", "20G堆叠极速决策练习"},
|
||||||
['strategy_e_plus']= {"Strategy(EasyP);", "", "20G堆叠中速决策练习\n无Hold"},
|
|
||||||
['strategy_h_plus']= {"Strategy(HardP);", "", "20G堆叠快速决策练习\n无Hold"},
|
|
||||||
['strategy_u_plus']= {"Strategy(UltimateP);", "", "20G堆叠极速决策练习\n无Hold"},
|
|
||||||
['blind_e']= {"Blind(Slow);", "", "不强大脑"},
|
['blind_e']= {"Blind(Slow);", "", "不强大脑"},
|
||||||
['blind_n']= {"Blind(Fast);", "", "挺强大脑"},
|
['blind_n']= {"Blind(Fast);", "", "挺强大脑"},
|
||||||
['blind_h']= {"Blind(Instant);", "", "很强大脑"},
|
['blind_h']= {"Blind(Instant);", "", "很强大脑"},
|
||||||
|
|||||||
@@ -209,6 +209,7 @@ return {
|
|||||||
tryAnotherBuild="[無效的UTF-8] 如果你使用的是Windows作業系統,請嘗試下載Techmino-win32或Techmino-win64(與你現在使用的不同的版本)。",
|
tryAnotherBuild="[無效的UTF-8] 如果你使用的是Windows作業系統,請嘗試下載Techmino-win32或Techmino-win64(與你現在使用的不同的版本)。",
|
||||||
|
|
||||||
modInstruction="選擇你想使用的Mod!\n不同的Mod會以不同的方式改變遊戲規則(可能導致遊戲異常)\n快來開發新玩法或挑戰自我吧!\n提醒:開啟Mod會使成績無效,你可以使用鍵盤開關Mod,按下shift反向",
|
modInstruction="選擇你想使用的Mod!\n不同的Mod會以不同的方式改變遊戲規則(可能導致遊戲異常)\n快來開發新玩法或挑戰自我吧!\n提醒:開啟Mod會使成績無效,你可以使用鍵盤開關Mod,按下shift反向",
|
||||||
|
-- modApplyAtInstruction="Choose when you want the modifier to be applied.\npreInit: Before loading the modes. The default option in V0.17.15 and earlier, but may cause problems with certain mods.\npostInit: After loading the game. This can fix some bugs in preInit, but some mods can still be disabled by modes in some situations.\nalways: Throughout the entire game. Keeps the effects of the mods in all situations. ",
|
||||||
modInfo={
|
modInfo={
|
||||||
next="Next數量:\n強制使用Next的個數",
|
next="Next數量:\n強制使用Next的個數",
|
||||||
hold="Hold數量:\n強制使用Hold的個數",
|
hold="Hold數量:\n強制使用Hold的個數",
|
||||||
@@ -412,6 +413,7 @@ return {
|
|||||||
mod={
|
mod={
|
||||||
title="Mods",
|
title="Mods",
|
||||||
reset="重設(tab)",
|
reset="重設(tab)",
|
||||||
|
-- applyAt="Apply during",
|
||||||
unranked="成績無效",
|
unranked="成績無效",
|
||||||
},
|
},
|
||||||
pause={
|
pause={
|
||||||
@@ -880,12 +882,9 @@ return {
|
|||||||
['master_g']= {"大師", "段位考試", "20G段位考試"},
|
['master_g']= {"大師", "段位考試", "20G段位考試"},
|
||||||
['master_ex']= {"宗師", "EX", "成為方塊大師"},
|
['master_ex']= {"宗師", "EX", "成為方塊大師"},
|
||||||
['master_instinct']={"大師", "本能", "隱藏當前塊"},
|
['master_instinct']={"大師", "本能", "隱藏當前塊"},
|
||||||
['strategy_e']= {"策略堆疊", "簡單", "20G堆疊中速決策練習"},
|
['strategy_e_plus']={"策略堆疊", "簡單+", "20G堆疊中速決策練習\n無Hold"},
|
||||||
['strategy_h']= {"策略堆疊", "困難", "20G堆疊快速決策練習"},
|
['strategy_h']= {"策略堆疊", "困難", "20G堆疊快速決策練習"},
|
||||||
['strategy_u']= {"策略堆疊", "極限", "20G堆疊極速決策練習"},
|
['strategy_u']= {"策略堆疊", "極限", "20G堆疊極速決策練習"},
|
||||||
['strategy_e_plus']={"策略堆疊", "簡單+", "20G堆疊中速決策練習\n無Hold"},
|
|
||||||
['strategy_h_plus']={"策略堆疊", "困難+", "20G堆疊快速決策練習\n無Hold"},
|
|
||||||
['strategy_u_plus']={"策略堆疊", "極限+", "20G堆疊極速決策練習\n無Hold"},
|
|
||||||
['blind_e']= {"隱形", "半隱", "不強大腦"},
|
['blind_e']= {"隱形", "半隱", "不強大腦"},
|
||||||
['blind_n']= {"隱形", "全隱", "挺強大腦"},
|
['blind_n']= {"隱形", "全隱", "挺強大腦"},
|
||||||
['blind_h']= {"隱形", "瞬隱", "很強大腦"},
|
['blind_h']= {"隱形", "瞬隱", "很強大腦"},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
Cách chơi:
|
Cách chơi:
|
||||||
Hệ thống sẽ cấp cho người chơi 7 loại tetromino (gạch 4 ô) bao gồm: Z, S, J, L, I, O, T;
|
Hệ thống sẽ cấp cho người chơi 7 loại tetromino (gạch 4 ô) bao gồm: Z, S, J, L, I, O, T;
|
||||||
và người chơi cần điều khiển chúng (di chuyển sang trái và phải; xoay 90 / 180 / 270 độ).
|
và người chơi cần điều khiển chúng (di chuyển sang trái và phải; xoay 90 / 180 / 270 độ).
|
||||||
Cứ mỗi hàng được lấp đầy trong bảng bởi các viên gạch, chúng sẽ bị xóa ra khỏi bảng.
|
Cứ mỗi hàng được lấp đầy trong bảng bởi các viên gạch, chúng sẽ bị xóa ra khỏi bảng.
|
||||||
Nếu có đối thủ, đối thủ sẽ bị tấn công mạnh hoặc nhẹ tùy theo số hàng bạn gửi.
|
Nếu có đối thủ, đối thủ sẽ bị tấn công mạnh hoặc nhẹ tùy theo số hàng bạn gửi.
|
||||||
Chơi hết hoặc đạt mục tiêu của cấp độ để thắng.
|
Chơi hết hoặc đạt mục tiêu của cấp độ để thắng.
|
||||||
@@ -25,19 +25,19 @@ Cách phát hiện spin: bằng cách sử dụng hệ thống điểm.
|
|||||||
|
|
||||||
|
|
||||||
Hệ thống tấn công:
|
Hệ thống tấn công:
|
||||||
Kiểu xóa nâng cao (Special clear):
|
Kiểu xóa Đặc biệt (Special clear):
|
||||||
Kiểu xóa nâng cao chỉ trường hợp bạn thực hiện Spin, Techrash, Techrash+ — xóa 5 hàng hoặc hơn, PC, HPC.
|
Kiểu xóa Đặc biệt chỉ trường hợp bạn thực hiện Spin, Techrash, Techrash+ — xóa 5 hàng hoặc hơn, PC, HPC.
|
||||||
Kiểu xóa nâng cao có thể sạc đầy thanh B2B.
|
Kiểu xóa Đặc biệt có thể sạc đầy thanh B2B.
|
||||||
|
|
||||||
Kiểu xóa Siêu cấp (Super clear):
|
Kiểu xóa Siêu cấp (Super clear):
|
||||||
Là Kiểu xóa nâng cao nhưng được thực hiện với B2B hoặc B3B
|
Là Kiểu xóa Đặc biệt nhưng được thực hiện với B2B hoặc B3B
|
||||||
|
|
||||||
Kiểu xóa nâng cao (spin): Gửi gấp đôi số hàng vừa xóa.
|
Kiểu xóa Đặc biệt (spin): Gửi gấp đôi số hàng vừa xóa.
|
||||||
— B2B gửi thêm 1/1/2/4/8 cho Spin Đơn/Spin Đôi/Spin Tam/Techrash/Techrash+
|
— B2B gửi thêm 1/1/2/4/8 cho Spin Đơn/Spin Đôi/Spin Tam/Techrash/Techrash+
|
||||||
— B2B2B gửi thêm (số hàng xóa × 0.5) trên B2B và +1 hàng để đánh chặn
|
— B2B2B gửi thêm (số hàng xóa × 0.5) trên B2B và +1 hàng để đánh chặn
|
||||||
— Mini sẽ bị cắt chỉ còn ¼ so với giá trị ban đầu
|
— Mini sẽ bị cắt chỉ còn ¼ so với giá trị ban đầu
|
||||||
|
|
||||||
Kiểu xóa nâng cao (Techrash/Techrash+ nhưng không spin):
|
Kiểu xóa Đặc biệt (Techrash/Techrash+ nhưng không spin):
|
||||||
— B2B gửi thêm 1 hàng
|
— B2B gửi thêm 1 hàng
|
||||||
— B3B boost 50% tấn công và +1 hàng để đánh chặn
|
— B3B boost 50% tấn công và +1 hàng để đánh chặn
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ Hệ thống tấn công:
|
|||||||
Perfect Clear (All Clear): Gửi 8 → 16 hàng rác
|
Perfect Clear (All Clear): Gửi 8 → 16 hàng rác
|
||||||
PC thứ nhất chỉ gửi 8 hàng rác, các PC sau đó sẽ thêm 2 hàng rác để tấn công (tổng hàng rác có thể gửi tối đa là 16 hàng)
|
PC thứ nhất chỉ gửi 8 hàng rác, các PC sau đó sẽ thêm 2 hàng rác để tấn công (tổng hàng rác có thể gửi tối đa là 16 hàng)
|
||||||
|
|
||||||
Sau khi tính toán xong, lượng sát thương sẽ bị làm tròn XUỐNG trước khi gửi.
|
Sau khi tính tổng xong, lượng sát thương sẽ bị làm tròn XUỐNG trước khi gửi.
|
||||||
|
|
||||||
|
|
||||||
Thanh Back to Back (B2B):
|
Thanh Back to Back (B2B):
|
||||||
@@ -64,7 +64,7 @@ Thanh Back to Back (B2B):
|
|||||||
Một người chơi đang ở trang thái B3B khi thanh có hơn 800 điểm.
|
Một người chơi đang ở trang thái B3B khi thanh có hơn 800 điểm.
|
||||||
|
|
||||||
Nếu có hàng được xóa:
|
Nếu có hàng được xóa:
|
||||||
Kiểu xóa nâng cao:
|
Kiểu xóa Đặc biệt:
|
||||||
— Spin Đơn/Đôi/Tam/Techrash/Techrash+ lần lượt cộng thêm 50/100/180/800/1000 (×50% nếu là Mini)
|
— Spin Đơn/Đôi/Tam/Techrash/Techrash+ lần lượt cộng thêm 50/100/180/800/1000 (×50% nếu là Mini)
|
||||||
— Techrash +150 điểm, nếu xóa hơn 4 hàng cùng lúc, mỗi hàng từ hàng thứ 5 trở đi cộng thêm 50 điểm.
|
— Techrash +150 điểm, nếu xóa hơn 4 hàng cùng lúc, mỗi hàng từ hàng thứ 5 trở đi cộng thêm 50 điểm.
|
||||||
— PC từ thứ 4 trở đi có giá trị 800 điểm
|
— PC từ thứ 4 trở đi có giá trị 800 điểm
|
||||||
@@ -82,12 +82,13 @@ Hệ thống tính điểm:
|
|||||||
Việc tính điểm cũng độc lập tùy vào từng chế độ.
|
Việc tính điểm cũng độc lập tùy vào từng chế độ.
|
||||||
|
|
||||||
|
|
||||||
Khoảng thời gian chờ trước khi tấn công:
|
Khoảng thời gian chờ trước khi gây sát thương:
|
||||||
Một đòn sát thương sẽ không có hiệu lực ngay lập tức để người chơi có chút thời gian phản ứng trước khi tràn vào bảng.
|
Một đòn sát thương sẽ không có hiệu lực ngay lập tức
|
||||||
Thời gian chờ của các đòn tấn công như sau, sắp xếp từ nhanh nhất tới lâu nhất:
|
để người chơi có chút thời gian phản ứng trước khi chúng có hiệu lực (rác tràn vào bảng).
|
||||||
|
Thời gian chờ của các đòn tấn công như sau, xếp từ ngắn nhất tới dài nhất:
|
||||||
— Double và Triple (Đôi và Tam) là nhanh nhất
|
— Double và Triple (Đôi và Tam) là nhanh nhất
|
||||||
— Theo sau là Techrash, Techrash+, spin; Mini, B2B và B3B có thêm thêm chút thời gian chờ nữa.
|
— Theo sau là Techrash, Techrash+, spin; Mini, B2B và B3B có thêm thêm chút thời gian chờ nữa.
|
||||||
— Sát thương từ combo có thời gian chờ lâu nhất..
|
— Sát thương từ combo có thời gian chờ lâu nhất.
|
||||||
|
|
||||||
|
|
||||||
Phản công:
|
Phản công:
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ return {
|
|||||||
{name='dig_eff_400l', x=-1200,y=0, size=40,shape=1,icon="dig_eff"},
|
{name='dig_eff_400l', x=-1200,y=0, size=40,shape=1,icon="dig_eff"},
|
||||||
|
|
||||||
{name='marathon_n', x=0, y=-600, size=60,shape=1,icon="marathon", unlock={'marathon_h','solo_e','round_e','big_n','blind_e','classic_e','survivor_e','c4wtrain_n','pctrain_n','sprintAtk','zen','construct_sg'}},
|
{name='marathon_n', x=0, y=-600, size=60,shape=1,icon="marathon", unlock={'marathon_h','solo_e','round_e','big_n','blind_e','classic_e','survivor_e','c4wtrain_n','pctrain_n','sprintAtk','zen','construct_sg'}},
|
||||||
{name='marathon_h', x=0, y=-800, size=50,shape=1,icon="marathon", unlock={'master_n','strategy_e'}},
|
{name='marathon_h', x=0, y=-800, size=50,shape=1,icon="marathon", unlock={'master_n','strategy_e_plus'}},
|
||||||
|
|
||||||
{name='solo_e', x=-600, y=-1000,size=40,shape=1,icon="solo", unlock={'solo_n'}},
|
{name='solo_e', x=-600, y=-1000,size=40,shape=1,icon="solo", unlock={'solo_n'}},
|
||||||
{name='solo_n', x=-800, y=-1000,size=40,shape=1,icon="solo", unlock={'solo_h'}},
|
{name='solo_n', x=-800, y=-1000,size=40,shape=1,icon="solo", unlock={'solo_h'}},
|
||||||
@@ -62,12 +62,9 @@ return {
|
|||||||
{name='master_g', x=0, y=-1600,size=40,shape=3,icon="master"},
|
{name='master_g', x=0, y=-1600,size=40,shape=3,icon="master"},
|
||||||
{name='master_ex', x=170, y=-1450,size=40,shape=2,icon="master_ex"},
|
{name='master_ex', x=170, y=-1450,size=40,shape=2,icon="master_ex"},
|
||||||
|
|
||||||
{name='strategy_e', x=-150, y=-1020,size=40,shape=3,icon="master", unlock={'strategy_e_plus'}},
|
{name='strategy_e_plus', x=-150, y=-1020,size=40,shape=3,icon="master"},
|
||||||
{name='strategy_h', x=-150, y=-1150,size=35,shape=3,icon="master", unlock={'strategy_h_plus'}},
|
{name='strategy_h', x=-150, y=-1150,size=35,shape=3,icon="master"},
|
||||||
{name='strategy_u', x=-150, y=-1280,size=30,shape=2,icon="master", unlock={'strategy_u_plus'}},
|
{name='strategy_u', x=-150, y=-1280,size=30,shape=2,icon="master"},
|
||||||
{name='strategy_e_plus', x=-300, y=-1120,size=40,shape=3,icon="master"},
|
|
||||||
{name='strategy_h_plus', x=-300, y=-1250,size=35,shape=3,icon="master"},
|
|
||||||
{name='strategy_u_plus', x=-300, y=-1380,size=30,shape=2,icon="master"},
|
|
||||||
|
|
||||||
{name='blind_e', x=150, y=-700, size=40,shape=1,icon="hidden", unlock={'blind_n','master_instinct'}},
|
{name='blind_e', x=150, y=-700, size=40,shape=1,icon="hidden", unlock={'blind_n','master_instinct'}},
|
||||||
{name='blind_n', x=150, y=-800, size=40,shape=1,icon="hidden2", unlock={'blind_h'}},
|
{name='blind_n', x=150, y=-800, size=40,shape=1,icon="hidden2", unlock={'blind_h'}},
|
||||||
|
|||||||
@@ -787,9 +787,11 @@ function draw.norm(P,repMode)
|
|||||||
gc_scale(P.size)
|
gc_scale(P.size)
|
||||||
|
|
||||||
-- Draw username
|
-- Draw username
|
||||||
setFont(30)
|
if P.showUsername then
|
||||||
gc_setColor(GROUP_COLORS[P.group])
|
setFont(30)
|
||||||
GC.mStr(P.username or USERS.getUsername(P.uid),300,-60)
|
gc_setColor(GROUP_COLORS[P.group])
|
||||||
|
GC.mStr(P.username or USERS.getUsername(P.uid),300,-60)
|
||||||
|
end
|
||||||
|
|
||||||
-- Draw HUD
|
-- Draw HUD
|
||||||
if ENV.nextCount>0 then _drawNext(P,repMode) end
|
if ENV.nextCount>0 then _drawNext(P,repMode) end
|
||||||
|
|||||||
@@ -175,8 +175,49 @@ local function _newEmptyPlayer(id,mini)
|
|||||||
}
|
}
|
||||||
return P
|
return P
|
||||||
end
|
end
|
||||||
|
local function _executeMod(P)
|
||||||
|
local applyStatus=GAME.modApplyAt
|
||||||
|
if applyStatus=='always' then
|
||||||
|
if not GAME.modCodeList then GAME.modCodeList={} end
|
||||||
|
if not GAME.modCodeList[P.id] then GAME.modCodeList[P.id]={} end
|
||||||
|
|
||||||
|
if not GAME.applyModsTask then
|
||||||
|
function GAME.applyModsTask()
|
||||||
|
while GAME.playing do
|
||||||
|
for _,p in pairs(GAME.modCodeList) do
|
||||||
|
for _,c in pairs(p) do pcall(c) end
|
||||||
|
end
|
||||||
|
coroutine.yield()
|
||||||
|
end
|
||||||
|
-- Kill mod patching function when game stopped
|
||||||
|
TASK.removeTask_code(GAME.applyModsTask)
|
||||||
|
TABLE.clear(GAME.modCodeList)
|
||||||
|
GAME.modCodeList=nil
|
||||||
|
GAME.applyModsTask=nil
|
||||||
|
end
|
||||||
|
TASK.new(GAME.applyModsTask)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for i=1,#GAME.mod do
|
||||||
|
if GAME.mod[i]>0 then
|
||||||
|
local M=MODOPT[i]
|
||||||
|
if applyStatus=='always' then
|
||||||
|
if M.funcOnce then
|
||||||
|
M.funcOnce(P,M.list and M.list[GAME.mod[i]])
|
||||||
|
elseif M.funcRepeat then
|
||||||
|
table.insert(GAME.modCodeList[P.id],function() M.funcInit(P,M.list and M.list[GAME.mod[i]]) end)
|
||||||
|
else
|
||||||
|
M.funcInit(P,M.list and M.list[GAME.mod[i]])
|
||||||
|
end
|
||||||
|
else -- Already checked pre or post before calling _executeMod()
|
||||||
|
M.funcInit(P,M.list and M.list[GAME.mod[i]])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
local function _loadGameEnv(P)-- Load gameEnv
|
local function _loadGameEnv(P)-- Load gameEnv
|
||||||
P.gameEnv={}-- Current game setting environment
|
P.gameEnv=TABLE.newWithLockMetamethod()-- Current game setting environment
|
||||||
local ENV=P.gameEnv
|
local ENV=P.gameEnv
|
||||||
local GAME,SETTING=GAME,SETTING
|
local GAME,SETTING=GAME,SETTING
|
||||||
-- Load game settings
|
-- Load game settings
|
||||||
@@ -199,13 +240,9 @@ local function _loadGameEnv(P)-- Load gameEnv
|
|||||||
ENV[k]=TABLE.copy(v)
|
ENV[k]=TABLE.copy(v)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if ENV.allowMod then
|
|
||||||
for i=1,#GAME.mod do
|
if ENV.allowMod and GAME.modApplyAt=='preInit' then
|
||||||
if GAME.mod[i]>0 then
|
_executeMod(P)
|
||||||
local M=MODOPT[i]
|
|
||||||
M.func(P,M.list and M.list[GAME.mod[i]])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function _loadRemoteEnv(P,confStr)-- Load gameEnv
|
local function _loadRemoteEnv(P,confStr)-- Load gameEnv
|
||||||
@@ -309,6 +346,10 @@ local function _applyGameEnv(P)-- Finish gameEnv processing
|
|||||||
break
|
break
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if ENV.allowMod and GAME.modApplyAt~='preInit' then
|
||||||
|
_executeMod(P)
|
||||||
|
end
|
||||||
|
|
||||||
P._20G=ENV.drop==0
|
P._20G=ENV.drop==0
|
||||||
P.dropDelay=ENV.drop
|
P.dropDelay=ENV.drop
|
||||||
P.lockDelay=ENV.lock
|
P.lockDelay=ENV.lock
|
||||||
@@ -389,9 +430,7 @@ local function _applyGameEnv(P)-- Finish gameEnv processing
|
|||||||
P:newNext()
|
P:newNext()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for _=1,ENV.trueNextCount do
|
for _=1,ENV.trueNextCount do P:newNext() end
|
||||||
P:newNext()
|
|
||||||
end
|
|
||||||
|
|
||||||
if P.miniMode then
|
if P.miniMode then
|
||||||
ENV.lockFX=false
|
ENV.lockFX=false
|
||||||
@@ -477,6 +516,7 @@ function PLY.newAIPlayer(id,AIdata,mini,p)
|
|||||||
group=0,
|
group=0,
|
||||||
} if p then TABLE.coverR(p,pData) end
|
} if p then TABLE.coverR(p,pData) end
|
||||||
P.username="BOT"..pData.uid
|
P.username="BOT"..pData.uid
|
||||||
|
P.showUsername=true
|
||||||
P.sid=NET.uid_sid[pData.uid] or pData.uid
|
P.sid=NET.uid_sid[pData.uid] or pData.uid
|
||||||
P.group=pData.group
|
P.group=pData.group
|
||||||
if not (P.group%1==0 and P.group>=1 and P.group<=6) then P.group=0 end
|
if not (P.group%1==0 and P.group>=1 and P.group<=6) then P.group=0 end
|
||||||
@@ -510,6 +550,8 @@ function PLY.newPlayer(id,mini,p)
|
|||||||
|
|
||||||
_loadGameEnv(P)
|
_loadGameEnv(P)
|
||||||
_applyGameEnv(P)
|
_applyGameEnv(P)
|
||||||
|
|
||||||
|
P.showUsername=not (P.gameEnv.allowMod and usingMod())
|
||||||
end
|
end
|
||||||
--------------------------</Public>--------------------------
|
--------------------------</Public>--------------------------
|
||||||
return PLY
|
return PLY
|
||||||
@@ -1023,7 +1023,7 @@ function Player:freshBlockGhost()
|
|||||||
if self.curY>self.ghoY then
|
if self.curY>self.ghoY then
|
||||||
self:createDropFX()
|
self:createDropFX()
|
||||||
if ENV.shakeFX then
|
if ENV.shakeFX then
|
||||||
self.swingOffset.vy=.5
|
self.swingOffset.vy=MATH.clamp((self.curY-self.ghoY-2.6)/10,0,0.626)
|
||||||
end
|
end
|
||||||
self.curY=self.ghoY
|
self.curY=self.ghoY
|
||||||
end
|
end
|
||||||
@@ -2915,6 +2915,9 @@ function Player:_die()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if GAME.applyModsTask then
|
||||||
|
TABLE.cut(GAME.modCodeList[self.id])
|
||||||
|
end
|
||||||
end
|
end
|
||||||
function Player:update(dt)
|
function Player:update(dt)
|
||||||
self.trigFrame=self.trigFrame+dt*60
|
self.trigFrame=self.trigFrame+dt*60
|
||||||
|
|||||||
@@ -6,6 +6,9 @@ local scene={}
|
|||||||
|
|
||||||
function scene.enter()
|
function scene.enter()
|
||||||
BG.set()
|
BG.set()
|
||||||
|
for i=1,#text.aboutTexts do
|
||||||
|
text.aboutTexts[i]=text.aboutTexts[i]:gsub("LÖVE%(?.*%)?",STRING.repD("LÖVE($1.$2)",love.getVersion()))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function scene.mouseDown(x,y)
|
function scene.mouseDown(x,y)
|
||||||
|
|||||||
@@ -949,16 +949,16 @@ end
|
|||||||
|
|
||||||
local combKey={
|
local combKey={
|
||||||
x=function()
|
x=function()
|
||||||
love.system.setClipboardText(inputBox:getText())
|
CLIPBOARD.set(inputBox:getText())
|
||||||
inputBox:clear()
|
inputBox:clear()
|
||||||
SFX.play('reach')
|
SFX.play('reach')
|
||||||
end,
|
end,
|
||||||
c=function()
|
c=function()
|
||||||
love.system.setClipboardText(inputBox:getText())
|
CLIPBOARD.set(inputBox:getText())
|
||||||
SFX.play('reach')
|
SFX.play('reach')
|
||||||
end,
|
end,
|
||||||
v=function()
|
v=function()
|
||||||
inputBox:addText(love.system.getClipboardText())
|
inputBox:addText(CLIPBOARD.get())
|
||||||
SFX.play('reach')
|
SFX.play('reach')
|
||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -204,7 +204,7 @@ function scene.update(dt)
|
|||||||
end
|
end
|
||||||
ct=ct-1
|
ct=ct-1
|
||||||
if ct==0 then
|
if ct==0 then
|
||||||
local t=love.system.getClipboardText()
|
local t=CLIPBOARD.get()
|
||||||
if type(t)=='string' then
|
if type(t)=='string' then
|
||||||
t=t:lower():match("^s=(%d+)$")
|
t=t:lower():match("^s=(%d+)$")
|
||||||
t=t and tonumber(t) and tonumber(t)>0 and tonumber(t)<=8000 and floor(tonumber(t))
|
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
|
time=0
|
||||||
score=0
|
score=0
|
||||||
|
|
||||||
local t=love.system.getClipboardText()
|
local t=CLIPBOARD.get()
|
||||||
if type(t)=='string' then
|
if type(t)=='string' then
|
||||||
t=t:lower():match("^s=(.+)")
|
t=t:lower():match("^s=(.+)")
|
||||||
t=t and tonumber(t) and tonumber(t)*2
|
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
|
if #CUSTOMGAME_LOCAL.bag>0 then str=str..DATA.copySequence(CUSTOMGAME_LOCAL.bag) end
|
||||||
str=str.."!"
|
str=str.."!"
|
||||||
if #CUSTOMGAME_LOCAL.mission>0 then str=str..DATA.copyMission(CUSTOMGAME_LOCAL.mission) end
|
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)
|
MES.new('check',text.exportSuccess)
|
||||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
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 args=str:sub((str:find(":") or 0)+1):split("!")
|
||||||
local hasTooHighField=false
|
local hasTooHighField=false
|
||||||
repeat
|
repeat
|
||||||
|
|||||||
@@ -226,10 +226,10 @@ function scene.keyDown(key)
|
|||||||
SFX.play('clear_4',.8)
|
SFX.play('clear_4',.8)
|
||||||
SFX.play('fall',.8)
|
SFX.play('fall',.8)
|
||||||
elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then
|
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)
|
MES.new('check',text.exportSuccess)
|
||||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
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*
|
local p=str:find(":")-- ptr*
|
||||||
if p then
|
if p then
|
||||||
if not str:sub(1,p-1):find("Field") then
|
if not str:sub(1,p-1):find("Field") then
|
||||||
|
|||||||
@@ -68,11 +68,11 @@ function scene.keyDown(key)
|
|||||||
end
|
end
|
||||||
elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then
|
elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then
|
||||||
if #MISSION>0 then
|
if #MISSION>0 then
|
||||||
sys.setClipboardText("Techmino Target:"..DATA.copyMission(MISSION))
|
CLIPBOARD.set("Techmino Target:"..DATA.copyMission(MISSION))
|
||||||
MES.new('check',text.exportSuccess)
|
MES.new('check',text.exportSuccess)
|
||||||
end
|
end
|
||||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
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*
|
local p=str:find(":")-- ptr*
|
||||||
if p then
|
if p then
|
||||||
if not str:sub(1,p-1):find("Target") then
|
if not str:sub(1,p-1):find("Target") then
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
local sys=love.system
|
|
||||||
local kb=love.keyboard
|
local kb=love.keyboard
|
||||||
|
|
||||||
local sin=math.sin
|
local sin=math.sin
|
||||||
@@ -76,11 +75,11 @@ function scene.keyDown(key)
|
|||||||
scene.widgetList.sequence:scroll(kb.isDown('lshift','rshift') and -1 or 1)
|
scene.widgetList.sequence:scroll(kb.isDown('lshift','rshift') and -1 or 1)
|
||||||
elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then
|
elseif key=='c' and kb.isDown('lctrl','rctrl') or key=='cC' then
|
||||||
if #BAG>0 then
|
if #BAG>0 then
|
||||||
sys.setClipboardText("Techmino SEQ:"..DATA.copySequence(BAG))
|
CLIPBOARD.set("Techmino SEQ:"..DATA.copySequence(BAG))
|
||||||
MES.new('check',text.exportSuccess)
|
MES.new('check',text.exportSuccess)
|
||||||
end
|
end
|
||||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
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*
|
local p=str:find(":")-- ptr*
|
||||||
if p then
|
if p then
|
||||||
if not str:sub(1,p-1):find("SEQ") then
|
if not str:sub(1,p-1):find("SEQ") then
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ end
|
|||||||
local function _copy()
|
local function _copy()
|
||||||
local t=_getList()[listBox.selected]
|
local t=_getList()[listBox.selected]
|
||||||
t=t.title_Org..":\n"..t.content_Org..(t.url and "\n[ "..t.url.." ]\n" or "\n")..text.dictNote
|
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
|
scene.widgetList.copy.hide=true
|
||||||
MES.new('info',text.copyDone)
|
MES.new('info',text.copyDone)
|
||||||
end
|
end
|
||||||
@@ -325,5 +325,5 @@ scene.widgetList={
|
|||||||
WIDGET.newButton{name='back',x=1185,y=60,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene},
|
WIDGET.newButton{name='back',x=1185,y=60,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene},
|
||||||
WIDGET.newKey{name='help',x=1170,y=140,w=200,h=60,font=40,fText=CHAR.controller.xboxY.."/[F1]: "..CHAR.icon.help,code=pressKey'f1'},
|
WIDGET.newKey{name='help',x=1170,y=140,w=200,h=60,font=40,fText=CHAR.controller.xboxY.."/[F1]: "..CHAR.icon.help,code=pressKey'f1'},
|
||||||
}
|
}
|
||||||
-- NOTE: The gap between Link-Copy, Zoom is 60*1.5-10=80; the gap between 2 buttons in one group is 60+10=70
|
|
||||||
return scene
|
return scene
|
||||||
@@ -14,7 +14,7 @@ local function _submit()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function _paste()
|
local function _paste()
|
||||||
local t=love.system.getClipboardText()
|
local t=CLIPBOARD.get()
|
||||||
if t then
|
if t then
|
||||||
t=STRING.trim(t)
|
t=STRING.trim(t)
|
||||||
if #t==128 and t:match("[0-9A-Z]+") then
|
if #t==128 and t:match("[0-9A-Z]+") then
|
||||||
|
|||||||
@@ -98,11 +98,11 @@ function scene.draw()
|
|||||||
local t=M.time*.01-- t range:0~0.1
|
local t=M.time*.01-- t range:0~0.1
|
||||||
GC.scale(1+3*t)
|
GC.scale(1+3*t)
|
||||||
GC.rotate(t)
|
GC.rotate(t)
|
||||||
local rad,side
|
local rad,side=45,5
|
||||||
if M.unranked then
|
if GAME.modApplyAt=='always' then
|
||||||
rad,side=45,5
|
if M.funcRepeat then side=nil
|
||||||
else
|
elseif M.funcOnce then side=8
|
||||||
rad=40
|
else side=5 end
|
||||||
end
|
end
|
||||||
local color=M.color
|
local color=M.color
|
||||||
GC.setColor(color[1],color[2],color[3],5*t)
|
GC.setColor(color[1],color[2],color[3],5*t)
|
||||||
@@ -130,6 +130,9 @@ function scene.draw()
|
|||||||
if selected then
|
if selected then
|
||||||
setFont(30)
|
setFont(30)
|
||||||
GC.printf(text.modInfo[selected.name],70,540,950)
|
GC.printf(text.modInfo[selected.name],70,540,950)
|
||||||
|
elseif WIDGET.isFocus(scene.widgetList.modApplyAt) then
|
||||||
|
setFont(20)
|
||||||
|
GC.printf(text.modApplyAtInstruction,70,540,950)
|
||||||
else
|
else
|
||||||
setFont(25)
|
setFont(25)
|
||||||
GC.printf(text.modInstruction,70,540,950)
|
GC.printf(text.modInstruction,70,540,950)
|
||||||
@@ -137,10 +140,11 @@ function scene.draw()
|
|||||||
end
|
end
|
||||||
|
|
||||||
scene.widgetList={
|
scene.widgetList={
|
||||||
WIDGET.newText{name='title', x=80,y=50,font=70,align='L'},
|
WIDGET.newText{name='title', x= 80,y=50,font=70,align='L'},
|
||||||
WIDGET.newText{name='unranked',x=1200,y=60,color='Y',font=50,align='R'},
|
WIDGET.newText{name='unranked', x= 970,y=70,color='Y',font=50,align='R'},
|
||||||
WIDGET.newButton{name='reset', x=1140,y=540,w=170,h=80,font=25,code=pressKey'tab'},
|
WIDGET.newSelector{name='applyAt',x=1100,y=100,w=230,color='Y',font=20,list={'preInit','postInit','always'},disp=function() return GAME.modApplyAt end,code=function(v) GAME.modApplyAt=v end},
|
||||||
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene},
|
WIDGET.newButton{name='reset', x=1140,y=540,w=170,h=80,font=25,code=pressKey'tab'},
|
||||||
|
WIDGET.newButton{name='back', x=1140,y=640,w=170,h=80,sound='back',font=60,fText=CHAR.icon.back,code=backScene},
|
||||||
}
|
}
|
||||||
|
|
||||||
return scene
|
return scene
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ local function _playRep(fileName)
|
|||||||
for _,m in next,rep.mod do
|
for _,m in next,rep.mod do
|
||||||
GAME.mod[m[1]+1]=m[2]
|
GAME.mod[m[1]+1]=m[2]
|
||||||
end
|
end
|
||||||
|
GAME.modApplyAt=rep.modApplyAt or 'preInit' -- For V0.17.15 and older
|
||||||
GAME.rep={}
|
GAME.rep={}
|
||||||
DATA.pumpRecording(rep.data,GAME.rep)
|
DATA.pumpRecording(rep.data,GAME.rep)
|
||||||
|
|
||||||
@@ -97,7 +98,7 @@ function scene.keyDown(key)
|
|||||||
if rep.available and rep.fileName then
|
if rep.available and rep.fileName then
|
||||||
local repStr=loadFile(rep.fileName,'-string')
|
local repStr=loadFile(rep.fileName,'-string')
|
||||||
if repStr then
|
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)
|
MES.new('info',text.exportSuccess)
|
||||||
else
|
else
|
||||||
MES.new('error',text.replayBroken)
|
MES.new('error',text.replayBroken)
|
||||||
@@ -107,7 +108,7 @@ function scene.keyDown(key)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
elseif key=='v' and kb.isDown('lctrl','rctrl') or key=='cV' then
|
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)
|
local res,fileData=pcall(love.data.decode,'string','base64',repStr)
|
||||||
if res then
|
if res then
|
||||||
local fileName=os.date("replay/%Y_%m_%d_%H%M%S_import.rep")
|
local fileName=os.date("replay/%Y_%m_%d_%H%M%S_import.rep")
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ local function _setPW()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
local function _paste()
|
local function _paste()
|
||||||
local t=love.system.getClipboardText()
|
local t=CLIPBOARD.get()
|
||||||
if t then
|
if t then
|
||||||
t=STRING.trim(t)
|
t=STRING.trim(t)
|
||||||
if #t==8 and t:match("[0-9]+") then
|
if #t==8 and t:match("[0-9]+") then
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ function scene.enter()
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function _dumpCB(T)
|
local function _dumpCB(T)
|
||||||
love.system.setClipboardText(STRING.packText(TABLE.dump(T)))
|
CLIPBOARD.set(STRING.packText(TABLE.dump(T)))
|
||||||
MES.new('check',text.exportSuccess)
|
MES.new('check',text.exportSuccess)
|
||||||
end
|
end
|
||||||
local function _parseCB()
|
local function _parseCB()
|
||||||
local _
|
local _
|
||||||
local s=love.system.getClipboardText()
|
local s=CLIPBOARD.get()
|
||||||
|
|
||||||
-- Decode
|
-- Decode
|
||||||
s=STRING.unpackText(s)
|
s=STRING.unpackText(s)
|
||||||
|
|||||||
@@ -91,7 +91,14 @@ scene.widgetList={
|
|||||||
WIDGET.newSwitch{name='clean', x=950,y=1100,lim=360,disp=SETval('cleanCanvas'), code=function() SETTING.cleanCanvas=not SETTING.cleanCanvas; applySettings() end},
|
WIDGET.newSwitch{name='clean', x=950,y=1100,lim=360,disp=SETval('cleanCanvas'), code=function() SETTING.cleanCanvas=not SETTING.cleanCanvas; applySettings() end},
|
||||||
WIDGET.newSwitch{name='fullscreen', x=950,y=1150,lim=360,disp=SETval('fullscreen'), code=function() SETTING.fullscreen=not SETTING.fullscreen; applySettings() end,hideF=function() return MOBILE end},
|
WIDGET.newSwitch{name='fullscreen', x=950,y=1150,lim=360,disp=SETval('fullscreen'), code=function() SETTING.fullscreen=not SETTING.fullscreen; applySettings() end,hideF=function() return MOBILE end},
|
||||||
WIDGET.newSwitch{name='portrait', x=950,y=1150,lim=360,disp=SETval('portrait'), code=function() SETTING.portrait=not SETTING.portrait; saveSettings(); MES.new('warn',text.settingWarn2,6.26) end,hideF=function() return not MOBILE end},
|
WIDGET.newSwitch{name='portrait', x=950,y=1150,lim=360,disp=SETval('portrait'), code=function() SETTING.portrait=not SETTING.portrait; saveSettings(); MES.new('warn',text.settingWarn2,6.26) end,hideF=function() return not MOBILE end},
|
||||||
WIDGET.newSlider{name='msaa', x=950,y=1220,lim=360,w=200,axis={0,4,1},show=_msaaShow,disp=function() return SETTING.msaa==0 and 0 or math.log(SETTING.msaa,2) end,code=function(v) SETTING.msaa=v==0 and 0 or 2^v; saveSettings(); if TASK.lock('warnMessage',6.26) then MES.new('warn',text.settingWarn2,6.26) end end},
|
WIDGET.newSlider{name='msaa', x=950,y=1220,lim=360,w=200,axis={0,4,1},disp=SETval('msaa'),show=_msaaShow,
|
||||||
|
code=function(v)
|
||||||
|
SETTING.msaa=v
|
||||||
|
if TASK.lock('warnMessage',6.26) then
|
||||||
|
MES.new('warn',text.settingWarn2,6.26)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
},
|
||||||
|
|
||||||
WIDGET.newKey{name='bg_on', x=680,y=1290,w=200,h=60,font=25,code=function() SETTING.bg='on' ; applySettings() end},
|
WIDGET.newKey{name='bg_on', x=680,y=1290,w=200,h=60,font=25,code=function() SETTING.bg='on' ; applySettings() end},
|
||||||
WIDGET.newKey{name='bg_off', x=900,y=1290,w=200,h=60,font=25,code=function() SETTING.bg='off'; applySettings() end},
|
WIDGET.newKey{name='bg_off', x=900,y=1290,w=200,h=60,font=25,code=function() SETTING.bg='off'; applySettings() end},
|
||||||
@@ -136,7 +143,7 @@ scene.widgetList={
|
|||||||
},
|
},
|
||||||
WIDGET.newKey{name='bg_custom_base64',x=1010,y=1502.5,w=420,h=135,align='M',
|
WIDGET.newKey{name='bg_custom_base64',x=1010,y=1502.5,w=420,h=135,align='M',
|
||||||
code=function()
|
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
|
if okay and pcall(gc.newImage,data) then
|
||||||
love.filesystem.write('conf/customBG',data)
|
love.filesystem.write('conf/customBG',data)
|
||||||
SETTING.bg='custom'
|
SETTING.bg='custom'
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ scene.widgetList={
|
|||||||
textBox,
|
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='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='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,
|
logList,
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ function THEME.calculate(Y,M,D)
|
|||||||
Y,M,D=os.date('%Y'),os.date('%m'),os.date('%d')
|
Y,M,D=os.date('%Y'),os.date('%m'),os.date('%d')
|
||||||
end
|
end
|
||||||
-- Festival calculate within one statement
|
-- Festival calculate within one statement
|
||||||
return
|
if not SETTING.noTheme then return
|
||||||
-- Christmas
|
-- Christmas
|
||||||
M=='12' and math.abs(D-25)<4 and
|
M=='12' and math.abs(D-25)<4 and
|
||||||
'xmas' or
|
'xmas' or
|
||||||
@@ -51,58 +51,54 @@ function THEME.calculate(Y,M,D)
|
|||||||
(M=='03' or M=='04' or M=='05' or M=='06') and 'zday1' or
|
(M=='03' or M=='04' or M=='05' or M=='06') and 'zday1' or
|
||||||
(M=='07' or M=='08' or M=='09' or M=='10') and 'zday2' or
|
(M=='07' or M=='08' or M=='09' or M=='10') and 'zday2' or
|
||||||
(M=='11' or M=='12' or M=='01' or M=='02') and 'zday3'
|
(M=='11' or M=='12' or M=='01' or M=='02') and 'zday3'
|
||||||
) or
|
|
||||||
|
|
||||||
-- Normal
|
|
||||||
(
|
|
||||||
(M=='02' or M=='03' or M=='04') and 'season1' or
|
|
||||||
(M=='05' or M=='06' or M=='07') and 'season2' or
|
|
||||||
(M=='08' or M=='09' or M=='10') and 'season3' or
|
|
||||||
(M=='11' or M=='12' or M=='01') and 'season4'
|
|
||||||
)
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If there is theme and theme is enabled, then we will never reach here
|
||||||
|
return -- Normal
|
||||||
|
(
|
||||||
|
(M=='02' or M=='03' or M=='04') and 'season1' or
|
||||||
|
(M=='05' or M=='06' or M=='07') and 'season2' or
|
||||||
|
(M=='08' or M=='09' or M=='10') and 'season3' or
|
||||||
|
(M=='11' or M=='12' or M=='01') and 'season4'
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
function THEME.set(theme,keepBGM,force)
|
---@param theme string
|
||||||
if type(theme)=='string' and theme:sub(1,6)=='season' then
|
---@param keepBGM boolean|false|nil
|
||||||
|
function THEME.set(theme,keepBGM)
|
||||||
|
if type(theme)~='string' then
|
||||||
|
return
|
||||||
|
elseif theme:sub(1,6)=='season' then
|
||||||
BG.setDefault(SETTING.defaultBG)
|
BG.setDefault(SETTING.defaultBG)
|
||||||
BGM.setDefault(({season1='null',season2='nil',season3='vacuum',season4='space'})[theme])
|
BGM.setDefault(({season1='null',season2='nil',season3='vacuum',season4='space'})[theme])
|
||||||
elseif not SETTING.noTheme or force then
|
elseif theme=='xmas' then
|
||||||
if theme=='xmas' then
|
BG.setDefault('snow')
|
||||||
BG.setDefault('snow')
|
BGM.setDefault('xmas')
|
||||||
BGM.setDefault('xmas')
|
MES.new('info',"==Merry Christmas==")
|
||||||
MES.new('info',"==Merry Christmas==")
|
elseif theme=='birth' then
|
||||||
elseif theme=='birth' then
|
BG.setDefault('firework')
|
||||||
BG.setDefault('firework')
|
BGM.setDefault('magicblock')
|
||||||
BGM.setDefault('magicblock')
|
elseif theme=='sprfes' then
|
||||||
elseif theme=='sprfes' then
|
BG.setDefault('firework')
|
||||||
BG.setDefault('firework')
|
BGM.setDefault('spring festival')
|
||||||
BGM.setDefault('spring festival')
|
MES.new('info',"★☆新年快乐☆★")
|
||||||
MES.new('info',"★☆新年快乐☆★")
|
elseif theme=='halloween' then
|
||||||
elseif theme=='halloween' then
|
BG.setDefault('glow')
|
||||||
BG.setDefault('glow')
|
BGM.setDefault('antispace')
|
||||||
BGM.setDefault('antispace')
|
MES.new('info',">>Happy halloween<<")
|
||||||
MES.new('info',">>Happy halloween<<")
|
elseif theme:sub(1,4)=='zday' then
|
||||||
elseif theme=='zday1' then
|
BG.setDefault('lanterns')
|
||||||
BG.setDefault('lanterns')
|
BGM.setDefault(({zday1='overzero',zday2='jazz nihilism',zday3='empty'})[theme])
|
||||||
BGM.setDefault('overzero')
|
elseif theme=='fool' then
|
||||||
elseif theme=='zday2' then
|
BG.setDefault('blockrain')
|
||||||
BG.setDefault('lanterns')
|
BGM.setDefault('how feeling')
|
||||||
BGM.setDefault('jazz nihilism')
|
elseif theme=='edm' then
|
||||||
elseif theme=='zday3' then
|
BG.setDefault('lightning2')
|
||||||
BG.setDefault('lanterns')
|
BGM.setDefault('malate')
|
||||||
BGM.setDefault('empty')
|
MES.new('music'," 红 色 电 音\n 极 地 大 冲 击\n 只要你敢触电——\n 7月14日、15日 天地人间完全放电\n不用麻醉,一样情不自禁HI起来,飞起来")
|
||||||
elseif theme=='fool' then
|
|
||||||
BG.setDefault('blockrain')
|
|
||||||
BGM.setDefault('how feeling')
|
|
||||||
elseif theme=='edm' then
|
|
||||||
BG.setDefault('lightning2')
|
|
||||||
BGM.setDefault('malate')
|
|
||||||
MES.new('music'," 红 色 电 音\n 极 地 大 冲 击\n 只要你敢触电——\n 7月14日、15日 天地人间完全放电\n不用麻醉,一样情不自禁HI起来,飞起来")
|
|
||||||
else
|
|
||||||
return
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
return THEME.set(THEME.calculate('0',os.date('%m'),'0'),keepBGM,true)
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
THEME.cur=theme
|
THEME.cur=theme
|
||||||
|
|||||||
@@ -8,8 +8,15 @@
|
|||||||
DiscordRPC支持
|
DiscordRPC支持
|
||||||
主菜单添加公告页面
|
主菜单添加公告页面
|
||||||
尝试重启联网
|
尝试重启联网
|
||||||
|
改动:
|
||||||
|
删除三个凑数的策略堆叠模式
|
||||||
|
3D方块效果微调
|
||||||
|
调整所有方块皮肤的名称
|
||||||
|
一些内部系统重构,尝试支持Web端
|
||||||
修复:
|
修复:
|
||||||
|
晃动特效开大了20g下颠到吐
|
||||||
hisPool序列算法错误(会影响部分模式录像)
|
hisPool序列算法错误(会影响部分模式录像)
|
||||||
|
开了“关闭节日主题”时可能导致启动就卡死
|
||||||
|
|
||||||
|
|
||||||
0.17.19: 暂停 Break
|
0.17.19: 暂停 Break
|
||||||
|
|||||||
Reference in New Issue
Block a user