Compare commits

...

170 Commits

Author SHA1 Message Date
MrZ_26
2226aa2e6b 中文方块维基名称调整 2024-11-09 14:12:09 +08:00
MrZ_26
12ae789239 更新词典关于方块中文维基的内容 2024-11-08 23:55:52 +08:00
Particle_G
2d7d02d5c9 CI update workflow (#1175)
(cherry picked from commit 64ddb09060)

Co-authored-by: MrZ_26 <1046101471@qq.com>
2024-11-08 01:59:37 +08:00
MrZ_26
64ddb09060 关于页面会显示当前love版本号了
(补法语缺一行文本)(补更新历史)
2024-11-06 09:36:27 +08:00
MrZ_26
0203bfa805 从地图删除三个策略堆叠模式(太无聊纯凑数) 2024-11-04 11:21:59 +08:00
SweetSea
c974db8c1c Update Vietnamese translation (#1172) 2024-11-04 11:03:37 +08:00
MrZ_26
8559b5e565 补充更新历史 2024-11-04 11:01:05 +08:00
MrZ_26
201ec079d6 修复晃动特效开大了20g模式会颠到吐 2024-11-04 11:01:05 +08:00
MrZ_26
f6e7e993f5 修msaa滑条在一些平台有问题 2024-11-04 11:01:05 +08:00
ParticleG
ff6a99999b Fix js.lua init error due to wrong grammar 2024-11-03 10:00:05 +08:00
MrZ_26
35aacc1a3e 整理代码 2024-11-03 01:51:46 +08:00
MrZ_26
59903397a7 Merge branch 'ci-test-jsapi' 2024-11-03 01:43:54 +08:00
MrZ_26
ca39c0ddf3 剪切板相关微调 2024-11-03 01:43:31 +08:00
ParticleG
6e6e1034b4 - Update timer 2024-11-03 01:36:15 +08:00
ParticleG
01efc218bf - Format codes 2024-11-03 01:07:11 +08:00
ParticleG
b4b602ae9d - Rename joystick related variables to joystick 2024-11-03 01:06:11 +08:00
ParticleG
bd395b2775 - Fix pop logic
- Retrieve data onlye when triggered
- Show message when thread is dead
- Push timer to thread
2024-11-03 01:05:39 +08:00
ParticleG
bf36bfb02b - Set setFreshInterval when system is web release 2024-11-03 01:03:38 +08:00
ParticleG
4bbf77b217 - 2024-11-02 22:12:58 +08:00
ParticleG
486e88e7bc - 2024-11-02 21:45:07 +08:00
SweetSea
46396efd09 Refactoring theme.lua (#1168) 2024-11-02 20:18:43 +08:00
ParticleG
57d42a84a4 - 2024-11-02 18:32:39 +08:00
ParticleG
eb7e20d157 - 2024-11-02 18:10:35 +08:00
ParticleG
725e8b35bd - 2024-11-02 17:55:32 +08:00
ParticleG
17a8181822 - 2024-11-02 17:45:27 +08:00
MrZ_26
6c40fb098f 整理皮肤顺序 2024-11-02 07:26:22 +08:00
MrZ_26
785935d26f 移除所有的Channel:demand,因为love.js不支持
整理代码
2024-11-02 05:52:36 +08:00
ParticleG
f2e064e900 - 2024-11-01 11:44:17 +08:00
ParticleG
2e537807a7 - Fix love.system not found 2024-11-01 11:41:32 +08:00
ParticleG
f4e04b32dd - Add compatible mode support 2024-11-01 11:03:52 +08:00
MrZ_26
d38ff06262 修万圣节日期判定 2024-11-01 10:57:44 +08:00
ParticleG
e1255e6124 - 2024-11-01 10:45:24 +08:00
ParticleG
37993c1669 - Add log 2024-11-01 10:14:45 +08:00
ParticleG
2fa653fffe - Log thread start 2024-11-01 10:03:11 +08:00
ParticleG
77fd519b43 - Add log 2024-11-01 08:48:25 +08:00
ParticleG
017f874f38 - Sanitize get and set 2024-11-01 08:25:24 +08:00
ParticleG
c642bd3857 - Fix missing dependence 2024-11-01 08:22:21 +08:00
ParticleG
bc831220b4 - Fix warnings in cards 2024-11-01 08:16:04 +08:00
ParticleG
b50147cace - Unify clipboard 2024-11-01 08:00:01 +08:00
MrZ_26
45a4b10d11 修关闭节日主题时特定条件无法启动 2024-11-01 03:26:37 +08:00
MrZ_26
fe12f397cc 修复皮肤设置的初始值相关 2024-11-01 00:40:27 +08:00
MrZ_26
801f67b194 Revert "fixed default skin not showing up"
This reverts commit 1cf3d101aa.
2024-11-01 00:37:35 +08:00
MrZ_26
e331c8f446 .gitignore删除一个不用的文件夹 2024-11-01 00:35:51 +08:00
MrZ_26
51897584a7 调整一个tip说法 2024-11-01 00:35:51 +08:00
Fab052
1cf3d101aa fixed default skin not showing up 2024-10-31 16:54:58 +01:00
ParticleG
eb3b8c9e9d - 2024-10-31 21:08:43 +08:00
ParticleG
9ddab37232 - Update source 2024-10-31 21:02:17 +08:00
ParticleG
cec7914c8f - fix error 2024-10-31 21:00:50 +08:00
ParticleG
b19a83ac23 - Update sources 2024-10-31 20:52:09 +08:00
ParticleG
1905960b51 - Remove print 2024-10-31 19:11:19 +08:00
ParticleG
68a806aa3e - Disable other actions 2024-10-31 19:07:32 +08:00
ParticleG
b555c44b8b - Update sources 2024-10-31 16:54:01 +08:00
ParticleG
d0c503e096 - Update sources 2024-10-31 16:37:28 +08:00
ParticleG
9ec2182252 - Wait until data is available 2024-10-31 16:23:07 +08:00
ParticleG
881d43c56d - Add logs 2024-10-31 12:18:27 +08:00
ParticleG
8a663e29a6 - Use dt in JS.retrieveData 2024-10-31 12:12:18 +08:00
ParticleG
7ae19b6431 - Add missing quotes 2024-10-31 11:58:10 +08:00
ParticleG
081b77f0e1 - Update index.html 2024-10-31 11:53:12 +08:00
ParticleG
b4a9766d14 - Add webdb.js 2024-10-31 11:51:57 +08:00
ParticleG
c33614a9cc - Add JS.retrieveData to main update loop 2024-10-31 11:45:24 +08:00
ParticleG
ae37fde4b9 - Use callbacks instead of await 2024-10-31 11:30:26 +08:00
ParticleG
64a86b260a - Replace clipboard methods if OS is Web 2024-10-31 11:22:13 +08:00
ParticleG
59cd9347c2 - Update.js.lua 2024-10-31 11:03:17 +08:00
ParticleG
0281d28a72 - Use compatible version 2024-10-31 10:51:56 +08:00
ParticleG
e517e6c65b - Disable test for now 2024-10-31 10:43:29 +08:00
ParticleG
95283b6fc7 - Update init.lua 2024-10-31 10:40:09 +08:00
ParticleG
1ed2cd468e - Update web build logics 2024-10-31 10:18:23 +08:00
ParticleG
eaba1cd0ab - Disable discordRPC when on Web env 2024-10-31 01:03:41 +08:00
ParticleG
421e74e357 - Update sourcces 2024-10-31 00:51:48 +08:00
ParticleG
6eba788236 - Update sources 2024-10-31 00:03:35 +08:00
ParticleG
d041461f0a - Change filename in game.js 2024-10-30 23:35:34 +08:00
ParticleG
13b277b35a - Update workflow 2024-10-30 23:25:33 +08:00
ParticleG
fc703f241c - Rename love package 2024-10-30 23:13:02 +08:00
Fab052
1830e849d8 better 3D effect (#1166) 2024-10-30 00:14:28 +08:00
Fab052
e3f246aa00 removed missing skin from main.lua (#1165) 2024-10-30 00:14:06 +08:00
Fab052
1eb679cf24 Reorganized the skins + Added "Arcade" and "Cardboard" skins (#1164) 2024-10-29 08:24:36 +08:00
Fuwuwuwu
1963dc9fb9 Fix the issue of AI passing Hold parameters in custom mode (#1163)
* 自定义游戏传递hold开关的问题

表现:即使holdCount为0,CC依旧会开启hold,导致无法预期运行,场地逐渐混乱
原因:传递了错误的类型(boolean->number)

* 非正常hold模式时,AI不启用hold

相关问题#1106
2024-10-29 08:24:10 +08:00
SweetSea
396293c8af Custom image from clipboard (#1157)
* Update how text renders in button and key

* Add a placeholder

* Add actual code and language entry

* Sort buttons

* Alter to keep original behaviour

* I HAVE OCD

* Add back legacy behaviour
2024-10-26 23:44:31 +08:00
Imple Lee
fbf6e910a3 Fix a wierd bug (#1161)
Steps to reproduce:
1. reset everything in custom game
2. restart the game
3. go to the custom game scene
4. go to the custom sequence scene and set a new sequence
5. leave the scene and go to the custom game scene
6. begin to clear

Unintended behavior:
The sequence is still the default old sequence (7-bag)

Intended behavior:
The sequence is the newly set sequence

Rationale:
The bug was introduced by #1139.
It deleted a line of `apply_locals()` which I wrongly believed that the custom modes will execute initialize() anyway, but it turned out initialization is only executed during the start of the whole game.
The patch is simple: just add back the deleted line
2024-10-18 00:45:37 +08:00
MrZ_26
9e4e861c32 继续加赞助名单 2024-10-14 23:51:46 +08:00
MrZ_26
d0b99a16c9 修单机录像播不出 2024-10-14 23:36:31 +08:00
MrZ_26
347e81c11c 更新赞助名单 2024-10-14 23:15:40 +08:00
MrZ_26
6b2a376dfe legals文件添加discord-rpc.dll的说明 2024-10-13 00:46:11 +08:00
MrZ_26
51e0ab7c48 赞助名单更新 2024-10-02 10:31:51 +08:00
MrZ_26
87fd26ab89 赞助名单更新 2024-09-29 20:14:36 +08:00
MrZ_26
0b1cee99bd 尝试添加一个paypal赞助按钮 2024-09-29 19:14:54 +08:00
MrZ_26
4768df6867 修discordRPC加载失败会崩溃 2024-09-27 03:50:12 +08:00
MrZ_26
423d502aa4 添加discordRPC支持 2024-09-26 02:29:24 +08:00
MrZ_26
a74e9033b3 添加500star贺图到仓库readme 2024-09-13 19:08:20 +08:00
SweetSea
dc6b7de15f Fix multiplayer chat (#1154)
* Fix multiplayer chat

* Update wrapping text param.

* Update net_game.lua
2024-09-11 20:31:41 +08:00
Imple Lee
74f67d0216 fix macos portable ci (#1152)
* use love 11.5 for macos portable

* use xcode 15.3
2024-09-04 17:03:16 +08:00
MrZ_26
d47f073d53 补irs打断的设置文本
补更新历史
2024-09-03 21:21:22 +08:00
MrZ_26
7407911914 Merge Electra's enhanced IRS 2024-09-03 21:12:32 +08:00
MrZ_26
9672a4fe57 修之前删goto的时候导致hisPool算法爆炸(也不知道怎么爆的,不管了) 2024-09-03 20:57:05 +08:00
Imple Lee
6c6ff26586 fix auto test: use appimage love instead of tar gz (#1141)
* use appimage love instead of tar gz

* install libfuse2 to run appimage

* replace deprecated `GabrielBB/xvfb-action`
2024-08-30 05:34:39 +08:00
Imple Lee
ca6f701084 Fix auto test (#1140)
* remove unnecessary space

* restart automatic test
2024-08-26 12:13:19 +08:00
Imple Lee
5793b7ca38 fix custom games (#1139)
Now you can `play custom_` without going through the `customGame` scene
2024-08-26 11:20:48 +08:00
MrZ_26
dee6ba95f2 修播放录像时初始化流程没重置暂停次数 close #1131 2024-08-20 01:28:39 +08:00
呵呵です
67aef1dbe3 更新tip里的40l世界纪录 close #1136 (#1137) 2024-08-20 01:26:37 +08:00
MrZ_26
90f41a20a3 整理ws模块代码 2024-08-13 21:54:11 +08:00
MrZ_26
5f5dd48ee8 修直接写在模式的env里的特殊事件不会被加载 2024-08-12 12:04:29 +08:00
MrZ_26
a8e0574f44 规则包加载流程优化 2024-08-11 13:18:36 +08:00
MrZ_26
40f148b6b3 更新赞助名单 2024-08-11 13:12:34 +08:00
MrZ_26
0eb37666f8 更新历史和版本号 2024-08-10 19:03:13 +08:00
MrZ_26
b73a653332 Merge branch 'eventsystem2' 2024-08-10 18:55:05 +08:00
MrZ_26
49f1b747b2 尝试修复新的事件系统允许自由参数数量导致网络卡顿情况且录像流最后的事件是攻击时frameRun有机会超过stream内数据导致玩家操作冻结(wtf so complicated, thank you Electra!) 2024-08-10 18:51:41 +08:00
Electra
2c75f0bc9c Simple solution? 2024-08-10 04:47:35 -04:00
MrZ_26
97e17edfae 继续修新的事件系统问题 2024-08-10 16:05:25 +08:00
MrZ_26
f7e4e47466 再修新的事件系统问题 2024-08-10 15:09:27 +08:00
MrZ_26
8779abef9a 修新的事件系统问题 2024-08-10 14:42:18 +08:00
MrZ_26
4d1caa7fe0 重构玩家交互事件系统,尝试支持可通过网络传递的自定义事件 2024-08-10 12:55:58 +08:00
MrZ_26
78f3c31db1 联网房间内的准备按钮不再会试图将自己设置为Gamer状态(已经是了) 2024-08-09 05:23:38 +08:00
MrZ_26
3c852f17a0 补翻译说明 2024-08-09 01:12:49 +08:00
MrZ_26
8737a00b44 补越南语翻译 2024-08-09 01:08:25 +08:00
MrZ_26
fff2c49f2e 补越南语翻译 2024-08-09 00:03:13 +08:00
MrZ_26
35c19a4d50 spinren加一些注释的代码 2024-08-08 23:43:01 +08:00
MrZ_26
137e707c63 删除ffa按钮
tech league改名galaxim,调整一些联网菜单文本
2024-08-08 23:42:41 +08:00
MrZ_26
d2e9439e38 更新版本号 2024-08-08 23:06:38 +08:00
MrZ_26
39cd7e4c1a 调整服务器url 2024-08-08 23:06:07 +08:00
MrZ_26
57f2b9541d 修几个词条不能通过拼音搜索 2024-08-08 16:14:53 +08:00
MrZ_26
9d4065a05a 修复创建联网房间时有好几个选项并没有生效 2024-08-08 16:08:51 +08:00
MrZ_26
424a3b3bee 公告页面信息更详细一点 2024-08-07 13:52:46 +08:00
MrZ_26
de3e1fcdc7 实现公告场景的功能 2024-08-07 13:25:03 +08:00
MrZ_26
59f390de93 尝试启用公告功能 2024-08-07 12:54:06 +08:00
MrZ_26
26287c8f35 更新历史和版本号 2024-08-07 12:19:53 +08:00
MrZ_26
24d552ba2b Merge branch 'ci-web-revive' 2024-08-07 12:11:32 +08:00
MrZ_26
f1a08ca325 更新历史和版本号 2024-08-03 13:05:09 +08:00
MrZ_26
28ec031afa 修time_short函数一个错误 2024-08-03 03:18:31 +08:00
MrZ_26
d9f606c56f 修地图布局
修spinren模式翻译
调整一些模式的外框形状
2024-08-03 01:45:37 +08:00
MrZ_26
de4b73cf83 spinren模式结束时显示的文本会根据是否到10行变化 2024-08-02 23:22:16 +08:00
MrZ_26
beff0c9d99 调整翻译文本,所有模式的“难度”一栏更统一 2024-08-02 23:04:49 +08:00
MrZ_26
4a76a929f5 更新spinren模式的越南语翻译 2024-08-02 22:58:32 +08:00
MrZ_26
aa981160e8 spinren少出两行防止一直响警报 2024-08-02 22:49:51 +08:00
MrZ_26
24a95a36d0 微调地图布局 2024-08-02 22:41:05 +08:00
MrZ_26
583819e8c4 优化spin模式并加到大地图,微调相关区域布局 2024-08-02 22:37:39 +08:00
Imple Lee
4c193efd41 add a new mode: spin ren (#1129)
* add a new mode: spin ren

* remove some bad cases; rework of the weights

* fix lines

* add different orientation for 323

* harder ranking

* Fix the map to sijun's mode

This mode can be used as big-bang!
2024-08-02 21:53:10 +08:00
MrZ_26
8208e7b132 修第三季度音乐名称打错 2024-08-01 21:47:25 +08:00
MrZ_26
7e2bd7b08d 词典里的“全消四”改成“全程消四” 2024-07-24 19:07:54 +08:00
MrZ_26
29258e2a35 添加edm节日 2024-07-14 04:10:26 +08:00
MrZ_26
9e028bc907 微调c4w普通模式评分标准 2024-07-04 02:07:00 +08:00
MrZ_26
75ae05ffc9 c4w普通的计分完全改为竞速 close #1126
改版本号和更新历史
2024-07-03 17:55:04 +08:00
MrZ_26
aec0b91039 补充更新历史 2024-07-03 16:29:00 +08:00
MrZ_26
34df33c9b0 readme更新官网链接,加一个techmino hub链接 2024-07-02 17:55:57 +08:00
MrZ_26
1674902727 修字体一个小问题 2024-07-01 23:14:13 +08:00
C₂₉H₂₅N₃O₅
4fd497fe9f Used more mathematically correct symbols for app calc (#1127) 2024-07-01 22:51:14 +08:00
MrZ_26
f01594b4d1 修背景锁定处理顺序问题 close #1122
Co-authored-by: SweetSea <106439598+SweetSea-ButImNotSweet@users.noreply.github.com>
2024-06-17 10:18:23 +08:00
MrZ_26
6f74693811 更新tip里的40l世界纪录 close #1121 2024-06-14 08:18:43 +08:00
MrZ_26
94d2af685c 消四挖掘模式非挖掘的消四越多会导致评分降低 2024-06-11 17:30:45 +08:00
MrZ_26
0b7c2fa59b 补两个中文文本
修改更新历史
2024-06-06 17:59:07 +08:00
MrZ_26
137f9a0d55 修两个消四模式的评级不等号错误 2024-06-06 17:38:05 +08:00
MrZ_26
23d8a34991 修highestGrade文本小问题 2024-06-03 10:15:34 +08:00
MrZ_26
3f0d4d3cdf 更新版本号和更新历史 2024-05-22 01:19:20 +08:00
MrZ_26
ac8f62de03 微调readme 2024-05-22 01:19:20 +08:00
C₂₉H₂₅N₃O₅
e518d91237 Font tweaks (#1116)
- Changed the glyph for the numeral `3` from “round-top” to “flat top” to increase eligibility
- Removed the serif on the bottom of the numeral “1” for cleaner looks
2024-05-20 22:44:35 +08:00
MrZ_26
c054a76504 修birs英文词条 2024-05-18 11:47:49 +08:00
MrZ_26
d3406c4a48 修一个TABLE.reverse用法错误 2024-05-13 15:12:23 +08:00
MrZ_26
3c0266ec02 补充更新历史 2024-04-29 11:16:56 +08:00
MrZ_26
4f4683d06c 更强大的ARS_Z fix #1094 2024-04-29 11:05:15 +08:00
MrZ_26
3441002758 c4w普通的模式说明改为和100l相同 close #1082 2024-04-29 10:45:37 +08:00
KonSola5
c2bf291029 Implementation of some of my English suggestions (#1104)
* Update lang_en.lua

* Some small changes

* "Block -> Piece" and some extras
2024-04-24 18:15:45 +08:00
MrZ_26
d70b04e7fb 优化neuro立绘动画和俊达萌身高 2024-04-24 05:14:27 +08:00
Petalzu
a979b6dbe6 Add neuro voicepack (#1109)
* update neuro

* change image & fix delay

change the image of neuro and fix delay between two vocal

* add vocal

* change vocal&image
2024-04-24 04:11:18 +08:00
MrZ_26
523b7ce443 给SRS+和SRS-X加一点注释说明 2024-04-24 04:08:37 +08:00
NOT_A_ROBOT
4e74c9456f Fix decay rate issues in Master Graded, close #1092 (#1113) 2024-04-24 04:06:41 +08:00
Imple Lee
7719b74b09 fix text in dig quad 10l (#1103)
fix #1102
2024-04-24 03:38:15 +08:00
Nguyễn Quốc Hưng
9d3aeeb50b Update Vietnamese translation and fix cannot entering Zictionary's manual (#1111)
* Fix cannot enter manual

* Update Zictionary

* Update dict_vi.lua

* Update dict_vi
2024-04-24 03:37:56 +08:00
MrZ_26
0459248556 修文本小bug 2024-04-16 00:16:20 +08:00
MrZ_26
288a6ba80a 微调readme 2024-04-07 04:56:09 +08:00
MrZ_26
97eee39266 调整词典中的BiRS词条(日文和越南文待其他人修改)
微调注释
2024-04-06 19:15:09 +08:00
MrZ_26
8c4446edac 修复拼花模式段位计算的1行偏差
补充拼花模式说明文本 close #1099
2024-03-03 14:27:36 +08:00
259 changed files with 2380 additions and 1439 deletions

16
.github/500stars/README.md vendored Normal file
View File

@@ -0,0 +1,16 @@
# Techmino - 500-star Banner
Created by NOT_A_ROBOT
13 September, 2024
**Don't forget to attribute me when using this.**
The image already includes sufficient attribution, so if you just don't crop that out, you shouldn't need to explicitly mention them.
## Attribution
Created by NOT_A_ROBOT
GitHub logo (on Z-character's screen) by GitHub
Background (space stars) originally by MrZ, ported to JS by NOT_A_ROBOT for rendering
Block skin (featured in the background) by Scf, slightly modified to make it darker
Z-character drawn by 葉枭, designed by MrZ
Techmino by MrZ and many contributors
Techmino is fun! https://github.com/26F-Studio/Techmino

BIN
.github/500stars/exported.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

View File

@@ -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 }}

Binary file not shown.

Binary file not shown.

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
View 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>

View File

@@ -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}]});
})();

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 305 KiB

After

Width:  |  Height:  |  Size: 305 KiB

View File

@@ -5,9 +5,10 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, minimum-scale=1, maximum-scale=1">
<title>Techmino</title>
<!-- Load custom style sheet -->
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" type="text/css" href="theme/love.css">
<script src="consolewrapper.js"></script>
<script src="webdb.js"></script>
</head>
<body>
<center>
@@ -61,7 +62,7 @@
var Module = {
arguments: ["./game.love"],
INITIAL_MEMORY: 536870912,
INITIAL_MEMORY: 128000000,
printErr: console.error.bind(console),
canvas: (function() {
var canvas = document.getElementById('canvas');

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.0 KiB

View File

@@ -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;
}

BIN
.github/donate/donate.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

View File

@@ -8,9 +8,11 @@ on:
branches: [main]
env:
BUILD_ASSETS_FOLDER: ./.github/build
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_PACKAGE_PATH: ./core.love
jobs:
get-info:
@@ -25,7 +27,7 @@ jobs:
commit-hash: ${{ steps.git-info.outputs.commit-hash }}
base-name: ${{ steps.assemble-base-name.outputs.base-name }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Install lua
run: |
sudo apt-get install lua5.3 -y
@@ -73,7 +75,7 @@ jobs:
OUTPUT_FOLDER: ./build
RELEASE_FOLDER: ./release
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Process app name
@@ -95,13 +97,13 @@ jobs:
build-list: ./media/ ./parts/ ./Zframework/ ./conf.lua ./main.lua ./version.lua ./legals.md ./license.txt
package-path: ${{ env.CORE_LOVE_PACKAGE_PATH }}
- name: Upload core love package
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
path: ${{ env.CORE_LOVE_PACKAGE_PATH }}
- name: Add icon to love package
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
rm media/image/icon.png
- name: Rename love package
@@ -109,7 +111,7 @@ jobs:
mkdir -p ${{ env.OUTPUT_FOLDER }}
mv ${{ env.CORE_LOVE_PACKAGE_PATH }} ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.love
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ needs.get-info.outputs.base-name }}_Core_love
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.love
@@ -130,10 +132,12 @@ jobs:
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}
auto-test:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
needs: build-core
env:
APPIMAGE_PATH: ./love.AppImage
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Love actions for testing
@@ -141,16 +145,35 @@ jobs:
with:
font-path: ./parts/fonts/proportional.otf
language-folder: ./parts/language
- name: Download core love package
uses: actions/download-artifact@v4
with:
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
- name: Download love
shell: bash
run: |
curl --retry 5 https://github.com/love2d/love/releases/download/11.5/love-11.5-x86_64.AppImage -o ${{ env.APPIMAGE_PATH }}
chmod +x ${{ env.APPIMAGE_PATH }}
- name: Install dependencies
shell: bash
run: |
sudo apt-get update
sudo apt-get install alsa-oss alsa-utils libfuse2 pavucontrol pulseaudio pulseaudio-utils x11-xserver-utils xvfb -y
- name: Run automated test
shell: bash
run: |
xvfb-run --auto-servernum ${{ env.APPIMAGE_PATH }} ${{ env.CORE_LOVE_PACKAGE_PATH }} --test
build-android:
runs-on: ubuntu-latest
needs: [get-info, build-core, auto-test]
if: github.event_name != 'pull_request'
env:
COLD_CLEAR_FOLDER: ./libAndroid
OUTPUT_FOLDER: ./build
RELEASE_FOLDER: ./release
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Process app name
@@ -159,6 +182,7 @@ jobs:
run: |
import os
import re
with open(os.getenv('GITHUB_OUTPUT'), 'a') as f:
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')
@@ -167,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('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
uses: actions/download-artifact@v4
with:
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
- name: Download ColdClear
uses: ./.github/actions/get-cc
uses: ./.github/actions/get-unzip
with:
platform: Android
dir: ./libAndroid
url: ${{ env.COLD_CLEAR_DOWNLOAD_URL }}/Android.zip
dir: ${{ env.COLD_CLEAR_FOLDER }}
- name: Build Android packages
id: build-packages
uses: love-actions/love-actions-android@main
uses: love-actions/love-actions-android@v2
with:
app-name: ${{ needs.get-info.outputs.app-name }}
bundle-id: ${{ steps.process-app-name.outputs.bundle-id }}
@@ -187,15 +211,15 @@ jobs:
keystore-key-password: ${{ secrets.ANDROID_KEYSTORE_KEYPASSWORD }}
keystore-store-password: ${{ secrets.ANDROID_KEYSTORE_STOREPASSWORD }}
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
resource-path: ./.github/build/android/${{ env.BUILD_TYPE }}/res
extra-assets: ./libAndroid/
resource-path: ${{ env.BUILD_ASSETS_FOLDER }}/android/${{ env.BUILD_TYPE }}/res
extra-assets: ${{ env.COLD_CLEAR_FOLDER }}
custom-scheme: studio26f://oauth
product-name: ${{ steps.process-app-name.outputs.product-name }}
version-string: ${{ needs.get-info.outputs.version-string }}
version-code: ${{ needs.get-info.outputs.version-code }}
output-folder: ${{ env.OUTPUT_FOLDER }}
- name: Upload artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ needs.get-info.outputs.base-name }}_Android_release
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}-release.apk
@@ -219,10 +243,11 @@ jobs:
runs-on: ubuntu-latest
needs: [get-info, build-core, auto-test]
env:
COLD_CLEAR_FOLDER: ./ColdClear
OUTPUT_FOLDER: ./build
RELEASE_FOLDER: ./release
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Process app name
@@ -237,45 +262,45 @@ jobs:
f.write('bundle-id=org.26f-studio.' + product_name + '\n')
f.write('product-name=' + product_name + '\n')
- name: Download core love package
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
- name: Add icon to love package
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
rm media/image/icon.png
- name: Download ColdClear
uses: ./.github/actions/get-cc
uses: ./.github/actions/get-unzip
with:
platform: Linux
dir: ./ColdClear
url: ${{ env.COLD_CLEAR_DOWNLOAD_URL }}/Linux.zip
dir: ${{ env.COLD_CLEAR_FOLDER }}
- name: Process ColdClear
shell: bash
run: |
cd ./ColdClear
cd ${{ env.COLD_CLEAR_FOLDER }}
mkdir -p ./lib/lua/5.1
mv ./x64/CCloader.so ./lib/lua/5.1
- name: Build Linux packages
id: build-packages
uses: love-actions/love-actions-linux@v1
uses: love-actions/love-actions-linux@v2
with:
app-name: ${{ needs.get-info.outputs.app-name }}
bundle-id: ${{ steps.process-app-name.outputs.bundle-id }}
description: Techmino is fun!
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 }}
lib-path: ./ColdClear/lib
lib-path: ${{ env.COLD_CLEAR_FOLDER }}/lib
product-name: ${{ steps.process-app-name.outputs.product-name }}
output-folder: ${{ env.OUTPUT_FOLDER }}
- name: Upload AppImage artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ needs.get-info.outputs.base-name }}_Linux_AppImage
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.AppImage
- name: Upload Debian artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ needs.get-info.outputs.base-name }}_Linux_Debian
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.deb
@@ -298,138 +323,58 @@ jobs:
name: ${{ needs.get-info.outputs.update-title }}
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}
build-macos-portable:
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: 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-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:
build-web-compat:
runs-on: ubuntu-latest
needs: [get-info, build-core, auto-test]
env:
MEMORY_LIMIT: 128000000
OUTPUT_FOLDER: ./build
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Download core love package
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
- name: Move core love package
- name: Build web packages
run: |
mv ${{ env.CORE_LOVE_PACKAGE_PATH }} ./.github/build/web/game.data
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
uses: crazy-max/ghaction-github-pages@v3
uses: crazy-max/ghaction-github-pages@v4
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
build_dir: ./.github/build/web/
build_dir: ${{ env.OUTPUT_FOLDER }}
keep_history: false
target_branch: web-dev
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: ${{ needs.get-info.outputs.base-name }}_Web_PWA
path: ./.github/build/web/
target_branch: gh-pages
build-windows:
runs-on: windows-latest
needs: [get-info, build-core, auto-test]
env:
COLD_CLEAR_FOLDER: ./ColdClear
OUTPUT_FOLDER: ./build
RELEASE_FOLDER: ./release
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Process app name
@@ -441,20 +386,20 @@ jobs:
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')
- name: Download core love package
uses: actions/download-artifact@v3
uses: actions/download-artifact@v4
with:
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
- name: Download ColdClear
uses: ./.github/actions/get-cc
uses: ./.github/actions/get-unzip
with:
platform: Windows
dir: ./ColdClear
url: ${{ env.COLD_CLEAR_DOWNLOAD_URL }}/Windows.zip
dir: ${{ env.COLD_CLEAR_FOLDER }}
- name: Update Windows template
shell: python3 {0}
run: |
version_string = "${{ needs.get-info.outputs.version-string }}"
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 = data\
.replace("@Version", version_string)\
@@ -464,30 +409,30 @@ jobs:
file.write(data)
- name: Build Windows packages
id: build-packages
uses: love-actions/love-actions-windows@v1
uses: love-actions/love-actions-windows@v2
with:
icon-path: ./.github/build/windows/${{ env.BUILD_TYPE }}/icon.ico
rc-path: ./.github/build/windows/${{ env.BUILD_TYPE }}/template.rc
icon-path: ${{ env.BUILD_ASSETS_FOLDER }}/windows/${{ env.BUILD_TYPE }}/icon.ico
rc-path: ${{ env.BUILD_ASSETS_FOLDER }}/windows/${{ env.BUILD_TYPE }}/template.rc
love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }}
extra-assets-x86: ./ColdClear/x86/CCloader.dll ./ColdClear/x86/cold_clear.dll
extra-assets-x64: ./ColdClear/x64/CCloader.dll ./ColdClear/x64/cold_clear.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: ${{ 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 }}
app-id: ${{ secrets.WINDOWS_APP_ID }}
project-website: https://www.studio26f.org/
installer-languages: ChineseSimplified.isl ChineseTraditional.isl English.isl Spanish.isl French.isl Indonesian.isl Japanese.isl Portuguese.isl
output-folder: ${{ env.OUTPUT_FOLDER }}
- name: Upload 32-bit artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ needs.get-info.outputs.base-name }}_Windows_x86
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x86.zip
- name: Upload 64-bit artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ needs.get-info.outputs.base-name }}_Windows_x64
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x64.zip
- name: Upload installer artifact
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: ${{ needs.get-info.outputs.base-name }}_Windows_installer
path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_installer.exe
@@ -522,38 +467,58 @@ jobs:
build-core,
build-android,
build-linux,
build-macos-portable,
build-web,
build-web-compat,
build-windows,
]
env:
ACTION_TYPE: ${{ fromJSON('[["Development", "Pre-release"], ["Release", "Release"]]')[startsWith(github.ref, 'refs/tags/v')][startsWith(github.ref, 'refs/tags/pre')] }}
steps:
- name: Cleanup
uses: geekyeggo/delete-artifact@v2
uses: geekyeggo/delete-artifact@v5
with:
name: ${{ env.CORE_LOVE_ARTIFACT_NAME }}
- name: Send Discord message
if: github.event_name != 'pull_request'
uses: Sniddl/discord-commits@v1.6
with:
webhook: ${{ secrets.DISCORD_WEBHOOK }}
message: "Github Actions for **${{ github.repository }}**."
embed: '{
"author":{
"name":"${{ needs.get-info.outputs.app-name }} [${{ env.ACTION_TYPE }}]",
"url":"https://github.com/${{ github.repository }}"
},
"title":"${{ needs.get-info.outputs.app-name }} (${{ needs.get-info.outputs.version-name }}) Build Result",
"description": "CI triggered at ${{ needs.get-info.outputs.commit-hash }}",
"url":"https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"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**macOS portable:** ${{ needs.build-macos-portable.result }}\n**Windows:** ${{ needs.build-windows.result }}"}
if: github.ref == 'refs/heads/main'
shell: python
run: |
import requests
import json
headers = {
'Content-Type': 'application/json',
}
payload = json.dumps({
"content": "Github Actions for **${{ github.repository }}**.",
"embeds": [
{
"author": {
"name": "${{ needs.get-info.outputs.app-name }} [${{ env.ACTION_TYPE }}]",
"url": "https://github.com/${{ github.repository }}"
},
"title": "${{ needs.get-info.outputs.app-name }} (${{ needs.get-info.outputs.version-name }}) Build Result",
"description": "CI triggered at ${{ needs.get-info.outputs.commit-hash }}",
"url": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}",
"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)

1
.gitignore vendored
View File

@@ -1,5 +1,4 @@
.vscode
libAndroid
*.ini
.DS_Store
Thumbs.db

103
Zframework/clipboard.lua Normal file
View 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,
}

View 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

View File

@@ -1,5 +1,5 @@
local sendCHN=love.thread.getChannel('inputChannel')
local recvCHN=love.thread.getChannel('outputChannel')
local sendCHN=love.thread.getChannel('HTTP_inputChannel')
local recvCHN=love.thread.getChannel('HTTP_outputChannel')
local threads={}
local threadCount=0
@@ -9,11 +9,15 @@ local threadCode=[[
local http=require'socket.http'
local ltn12=require'ltn12'
local sendCHN=love.thread.getChannel('inputChannel')
local recvCHN=love.thread.getChannel('outputChannel')
local sendCHN=love.thread.getChannel('HTTP_inputChannel')
local recvCHN=love.thread.getChannel('HTTP_outputChannel')
local sleep=require'love.timer'.sleep
while true do
local arg=sendCHN:demand()
-- local arg=sendCHN:demand()
-- Warning: workaround for love.js
while sendCHN:getCount()==0 do sleep(.0626) end
local arg=sendCHN:pop()
if arg._destroy then
recvCHN:push{

View File

@@ -1,8 +1,18 @@
-- WARNING: This framework has been remade and renamed to Zenitha. Do not use this deprecated framework for your project
NONE={}function NULL() end PAPER=love.graphics.newCanvas(1,1)
EDITING=""
LOADED=false
---@type 'Windows'|'Android'|'Linux'|'iOS'|'macOS'|'Web'
SYSTEM=love.system.getOS()
if SYSTEM=='OS X' then SYSTEM='macOS' end
WEB_COMPAT_MODE=false
if SYSTEM=='OS X' then
SYSTEM='macOS'
elseif SYSTEM=='Web' then
WEB_COMPAT_MODE=not love.thread.newThread('\n'):start()
print('Web compatible mode: ', WEB_COMPAT_MODE)
end
-- Bit module
local success
@@ -70,6 +80,7 @@ do
end
-- Love-based modules (basic)
CLIPBOARD= require'Zframework.clipboard'
HTTP= require'Zframework.http'
WS= require'Zframework.websocket'
FILE= require'Zframework.file'
@@ -92,6 +103,10 @@ IMG= require'Zframework.image'
BGM= require'Zframework.bgm'
VOC= require'Zframework.voice'
if SYSTEM=='Web' then
JS=require'Zframework.js'
end
local ms,kb=love.mouse,love.keyboard
local KBisDown=kb.isDown
@@ -172,6 +187,7 @@ local function updatePowerInfo()
gc_pop()
gc.setCanvas()
end
-------------------------------------------------------------
local lastX,lastY=0,0-- Last click pos
local function _updateMousePos(x,y,dx,dy)
@@ -421,38 +437,38 @@ local dPadToKey={
start='return',
back='escape',
}
function love.joystickadded(JS)
function love.joystickadded(joystick)
table.insert(jsState,{
_id=JS:getID(),
_jsObj=JS,
_id=joystick:getID(),
_jsObj=joystick,
leftx=0,lefty=0,
rightx=0,righty=0,
triggerleft=0,triggerright=0
})
MES.new('info',"Joystick added")
end
function love.joystickremoved(JS)
function love.joystickremoved(joystick)
for i=1,#jsState do
if jsState[i]._jsObj==JS then
if jsState[i]._jsObj==joystick then
for j=1,#gamePadKeys do
if JS:isGamepadDown(gamePadKeys[j]) then
love.gamepadreleased(JS,gamePadKeys[j])
if joystick:isGamepadDown(gamePadKeys[j]) then
love.gamepadreleased(joystick,gamePadKeys[j])
end
end
love.gamepadaxis(JS,'leftx',0)
love.gamepadaxis(JS,'lefty',0)
love.gamepadaxis(JS,'rightx',0)
love.gamepadaxis(JS,'righty',0)
love.gamepadaxis(JS,'triggerleft',-1)
love.gamepadaxis(JS,'triggerright',-1)
love.gamepadaxis(joystick,'leftx',0)
love.gamepadaxis(joystick,'lefty',0)
love.gamepadaxis(joystick,'rightx',0)
love.gamepadaxis(joystick,'righty',0)
love.gamepadaxis(joystick,'triggerleft',-1)
love.gamepadaxis(joystick,'triggerright',-1)
MES.new('info',"Joystick removed")
table.remove(jsState,i)
break
end
end
end
function love.gamepadaxis(JS,axis,val)
if jsState[1] and JS==jsState[1]._jsObj then
function love.gamepadaxis(joystick,axis,val)
if jsState[1] and joystick==jsState[1]._jsObj then
local js=jsState[1]
if axis=='leftx' or axis=='lefty' or axis=='rightx' or axis=='righty' then
local newVal=-- range: [0,1]
@@ -461,14 +477,14 @@ function love.gamepadaxis(JS,axis,val)
0
if newVal~=js[axis] then
if js[axis]==-1 then
love.gamepadreleased(JS,jsAxisEventName[axis][1])
love.gamepadreleased(joystick,jsAxisEventName[axis][1])
elseif js[axis]~=0 then
love.gamepadreleased(JS,jsAxisEventName[axis][2])
love.gamepadreleased(joystick,jsAxisEventName[axis][2])
end
if newVal==-1 then
love.gamepadpressed(JS,jsAxisEventName[axis][1])
love.gamepadpressed(joystick,jsAxisEventName[axis][1])
elseif newVal==1 then
love.gamepadpressed(JS,jsAxisEventName[axis][2])
love.gamepadpressed(joystick,jsAxisEventName[axis][2])
end
js[axis]=newVal
end
@@ -476,9 +492,9 @@ function love.gamepadaxis(JS,axis,val)
local newVal=val>.3 and 1 or 0-- range: [0,1]
if newVal~=js[axis] then
if newVal==1 then
love.gamepadpressed(JS,jsAxisEventName[axis])
love.gamepadpressed(joystick,jsAxisEventName[axis])
else
love.gamepadreleased(JS,jsAxisEventName[axis])
love.gamepadreleased(joystick,jsAxisEventName[axis])
end
js[axis]=newVal
end
@@ -718,6 +734,10 @@ function love.run()
-- UPDATE
STEP()
if SYSTEM == 'Web' then
JS.retrieveData(dt)
CLIPBOARD._update(dt)
end
if mouseShow then mouse_update(dt) end
if next(jsState) then gp_update(jsState[1],dt) end
VOC.update()

142
Zframework/js.lua Normal file
View 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

View File

@@ -140,7 +140,7 @@ function profile.switch()
switch=not switch
if not switch then
profile.stop()
love.system.setClipboardText(profile.report())
CLIPBOARD.set(profile.report())
profile.reset()
return false
else

View File

@@ -125,14 +125,14 @@ function STRING.time_short(t)
if t<1 then return math.floor(t*1000)..timeLetters[6] end -- 123 ms
if t<MINUTE then return math.floor(t)..timeLetters[5]..' '..math.floor((t%1)*1000)..timeLetters[6] end -- 12s 345ms
local timeUnits=TABLE.reverse({convertSecondsToUnits(t)})
local timeUnits={convertSecondsToUnits(t)}
TABLE.reverse(timeUnits)
-- floor seconds
timeUnits[#timeUnits]=floorint(timeUnits[#timeUnits])
local outputStr=''
for i=1,#timeUnits do
if timeUnits>0 then
if timeUnits[i]>0 then
return timeUnits[i]..timeLetters[i]..' '..timeUnits[i+1]..timeLetters[i+1]
end
end
@@ -189,7 +189,7 @@ do-- functions to shorted big numbers
function STRING.bigInt(t)
if t<1000 then
return tostring(t)
elseif t~=1e999 then
elseif t~=1/0 then
local e=floorint(lg(t)/3)
return(t/10^(e*3))..units[e+1]
else

View File

@@ -8,8 +8,6 @@ local path=''
local type=type
local timer=love.timer.getTime
local TRD=love.thread.newThread("\n")
local TRD_isRunning=TRD.isRunning
local WS={}
local wsList=setmetatable({},{
@@ -151,7 +149,7 @@ function WS.update(dt)
local time=timer()
for name,ws in next,wsList do
if ws.real and ws.status~='dead' then
if TRD_isRunning(ws.thread) then
if ws.thread:isRunning() then
if ws.triggerCHN:getCount()==0 then
ws.triggerCHN:push(0)
end

View File

@@ -1,3 +1,4 @@
---@type love.Channel,love.Channel,love.Channel
local triggerCHN,sendCHN,readCHN=...
local CHN_demand,CHN_getCount=triggerCHN.demand,triggerCHN.getCount
@@ -5,16 +6,20 @@ local CHN_push,CHN_pop=triggerCHN.push,triggerCHN.pop
local SOCK=require'socket'.tcp()
local JSON=require'Zframework.json'
local sleep=require'love.timer'.sleep
do-- Connect
local host=CHN_demand(sendCHN)
local port=CHN_demand(sendCHN)
local path=CHN_demand(sendCHN)
local head=CHN_demand(sendCHN)
local timeout=CHN_demand(sendCHN)
-- Warning: workaround for love.js, used to use CHN_demand instead
while CHN_getCount(sendCHN)<5 do sleep(.0626) end
local host=CHN_pop(sendCHN)
local port=CHN_pop(sendCHN)
local path=CHN_pop(sendCHN)
local head=CHN_pop(sendCHN)
local timeout=CHN_pop(sendCHN)
SOCK:settimeout(timeout)
local res,err=SOCK:connect(host,port)
-- print('C0',res,err)
assert(res,err)
-- WebSocket handshake
@@ -31,6 +36,7 @@ do-- Connect
-- First line of HTTP
res,err=SOCK:receive('*l')
-- print('C',res,err)
assert(res,err)
local code,ctLen
code=res:find(' ')
@@ -39,22 +45,28 @@ do-- Connect
-- Get body length from headers and remove headers
repeat
res,err=SOCK:receive('*l')
-- print('H',res,err)
assert(res,err)
if not ctLen and res:find('length') then
ctLen=tonumber(res:match('%d+'))
if not ctLen and res:find('content-length') then
ctLen=tonumber(res:match('%d+')) or 0
end
until res==''
-- Result
if code=='101' then
CHN_push(readCHN,'success')
end
-- Content(?)
if ctLen then
if code=='101' then
CHN_push(readCHN,'success')
else
res,err=SOCK:receive(ctLen)
res,err=SOCK:receive(ctLen)
-- print('R',res,err)
if code~='101' then
res=JSON.decode(assert(res,err))
error((code or "XXX")..":"..(res and res.reason or "Server Error"))
end
end
SOCK:settimeout(0)
end
@@ -136,10 +148,10 @@ local readThread=coroutine.wrap(function()
assert(res,err)
length=shl(byte(res,1),8)+byte(res,2)
elseif length==127 then
local lenData
lenData,err=_receive(SOCK,8)
-- 'res' is 'lenData' here
res,err=_receive(SOCK,8)
assert(res,err)
local _,_,_,_,_5,_6,_7,_8=byte(lenData,1,8)
local _,_,_,_,_5,_6,_7,_8=byte(res,1,8)
length=shl(_5,24)+shl(_6,16)+shl(_7,8)+_8
end
res,err=_receive(SOCK,length)
@@ -158,12 +170,14 @@ local readThread=coroutine.wrap(function()
lBuffer=lBuffer..res
if fin then
CHN_push(readCHN,lBuffer)
-- print('M',lBuffer)
lBuffer=""
end
else
CHN_push(readCHN,op)
if fin then
CHN_push(readCHN,res)
-- print('S',res)
lBuffer=""
else
lBuffer=res
@@ -176,7 +190,8 @@ end)
local success,err
while true do-- Running
CHN_demand(triggerCHN)
while CHN_getCount(triggerCHN)==0 do sleep(.0626) end
CHN_pop(triggerCHN)
success,err=pcall(sendThread)
if not success or err then break end
success,err=pcall(readThread)

View File

@@ -15,6 +15,7 @@ local timer=love.timer.getTime
local next=next
local floor,ceil=math.floor,math.ceil
local max,min=math.max,math.min
local match=string.match
local sub,ins,rem=string.sub,table.insert,table.remove
local xOy=SCR.xOy
local FONT=FONT
@@ -142,13 +143,21 @@ local button={
type='button',
mustHaveText=true,
ATV=0,-- Activating time(0~8)
textAlreadyWrapped=false,-- Text already wrapped? (Managed by :setObject, can be override, this will be true if obj has a '\n')
}
function button:reset()
self.ATV=0
end
function button:setObject(obj)
if type(obj)=='string' or type(obj)=='number' then
self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
if match(obj,"\n") then
self.textAlreadyWrapped=true
self.obj=gc.newText(FONT.get(self.font,self.fType))
self.obj:addf(obj,self.w-self.edge*2,(self.align=='L' and 'left') or (self.align=='R' and 'right') or 'center')
else
self.textAlreadyWrapped=false
self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
end
elseif obj then
self.obj=obj
end
@@ -194,16 +203,7 @@ function button:draw()
local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5
local y0=y+h*.5
gc_setColor(1,1,1,.2+ATV*.05)
if self.align=='M' then
local x0=x+w*.5
local kx=obj:type()=='Text' and min(w/ox/2,1) or 1
gc_draw(obj,x0-1,y0-1,nil,kx,1,ox,oy)
gc_draw(obj,x0-1,y0+1,nil,kx,1,ox,oy)
gc_draw(obj,x0+1,y0-1,nil,kx,1,ox,oy)
gc_draw(obj,x0+1,y0+1,nil,kx,1,ox,oy)
gc_setColor(r*.55,g*.55,b*.55)
gc_draw(obj,x0,y0,nil,kx,1,ox,oy)
elseif self.align=='L' then
if self.align=='L' or self.textAlreadyWrapped then
local edge=self.edge
gc_draw(obj,x+edge-1,y0-1-oy)
gc_draw(obj,x+edge-1,y0+1-oy)
@@ -219,6 +219,15 @@ function button:draw()
gc_draw(obj,x0+1,y0+1-oy)
gc_setColor(r*.55,g*.55,b*.55)
gc_draw(obj,x0,y0-oy)
else--if self.align=='M' then
local x0=x+w*.5
local kx=obj:type()=='Text' and min(w/ox/2,1) or 1
gc_draw(obj,x0-1,y0-1,nil,kx,1,ox,oy)
gc_draw(obj,x0-1,y0+1,nil,kx,1,ox,oy)
gc_draw(obj,x0+1,y0-1,nil,kx,1,ox,oy)
gc_draw(obj,x0+1,y0+1,nil,kx,1,ox,oy)
gc_setColor(r*.55,g*.55,b*.55)
gc_draw(obj,x0,y0,nil,kx,1,ox,oy)
end
end
function button:getInfo()
@@ -290,13 +299,21 @@ local key={
type='key',
mustHaveText=true,
ATV=0,-- Activating time(0~4)
textAlreadyWrapped=false,---See button.setObject (line 146)
}
function key:reset()
self.ATV=0
end
function key:setObject(obj)
if type(obj)=='string' or type(obj)=='number' then
self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
if match(obj,"\n") then
self.textAlreadyWrapped=true
self.obj=gc.newText(FONT.get(self.font,self.fType))
self.obj:addf(obj,self.w-self.edge*2,(self.align=='L' and 'left') or (self.align=='R' and 'right') or 'center')
else
self.textAlreadyWrapped=false
self.obj=gc.newText(FONT.get(self.font,self.fType),obj)
end
elseif obj then
self.obj=obj
end
@@ -354,14 +371,15 @@ function key:draw()
-- Drawable
local obj=self.obj
local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5
gc_setColor(r,g,b)
if align=='M' then
local kx=obj:type()=='Text' and min(w/ox/2,1) or 1
gc_draw(obj,x+w*.5,y+h*.5,nil,kx,1,ox,oy)
elseif align=='L' then
gc_draw(obj,x+self.edge,y-oy+h*.5)
if align=='L' or self.textAlreadyWrapped then
gc_draw(obj,x+self.edge,y+h*.5-oy)
elseif align=='R' then
gc_draw(obj,x+w-self.edge-ox*2,y-oy+h*.5)
else--if align=='M' then
local kx=obj:type()=='Text' and min(w/ox/2,1) or 1
gc_draw(obj,x+w*.5,y+h*.5,nil,kx,1,ox,oy)
end
end
function key:getInfo()
@@ -1382,10 +1400,13 @@ function WIDGET.setLang(widgetText)
t=W.name or "##"
W.color=COLOR.dV
end
if type(t)=='string' and W.font then
t=gc.newText(FONT.get(W.font),t)
if type(W.setObject)=='function' then
W:setObject(t)
elseif type(t)=='string' and W.font then
W.obj=gc.newText(FONT.get(W.font or 30),t)
else
W.obj=t
end
W.obj=t
end
end
end

View File

@@ -1,9 +1,9 @@
local OS=love._os
if OS=='OS X' then OS='macOS' end
MOBILE=OS=='Android' or OS=='iOS'
FNNS=OS:find'\79\83' -- What does FNSF stand for? IDK so don't ask me lol
local system=love._os
if system=='OS X' then system='macOS' end
MOBILE=system=='Android' or system=='iOS'
FNNS=system:find'\79\83' -- What does FNSF stand for? IDK so don't ask me lol
if OS=='Web' then
if system=='Web' then
local oldRead=love.filesystem.read
function love.filesystem.read(name,size)
if love.filesystem.getInfo(name) then
@@ -23,12 +23,13 @@ function love.conf(t)
local fileData=fs.read('conf/settings')
if fileData then
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
end
end
t.identity=identity -- Saving folder
t.version="11.4"
t.version="11.5"
t.gammacorrect=false
t.appendidentity=true -- Search files in source then in save directory
t.accelerometerjoystick=false -- Accelerometer=joystick on ios/android

View File

@@ -12,6 +12,8 @@ Lua is free software distributed under the terms of the MIT license. Copyright
json.lua is copyrighted by rxi. © 2022 rxi.
discord-rpc.dll is copyrighted by Discord, Inc. © 2017 Discord, Inc.
IBM Plex is copyrighted by the International Business Machines Corporation. IBM and IBM Plex are trademarks of IBM Corp, registered in many jurisdictions worldwide. IBM Plex is licensed under the SIL Open Font License, Version 1.1.

101
main.lua
View File

@@ -23,7 +23,7 @@ TIME=love.timer.getTime
-- Global Vars & Settings
SFXPACKS={'chiptune'}
VOCPACKS={'miya','mono','xiaoya','flore','miku','zundamon'}
VOCPACKS={'miya','mono','xiaoya','flore','neuro','miku','zundamon'}
FIRSTLAUNCH=false
DAILYLAUNCH=false
@@ -49,6 +49,10 @@ SCR.setSize(1280,720) -- Initialize Screen size
BGM.setMaxSources(5)
VOC.setDiversion(.62)
if SYSTEM == 'Web' and not WEB_COMPAT_MODE then
CLIPBOARD.setFreshInterval(.5)
end
WIDGET.setOnChange(function()
if SCN.cur=='net_game' or SCN.cur=='custom_field' then return end
local colorList=THEME.getThemeColor()
@@ -271,6 +275,7 @@ IMG.init{
floreCH='media/image/characters/flore.png',
mikuCH='media/image/characters/miku.png',
zundamonCH='media/image/characters/zundamon.png',
neuroCH='media/image/characters/neuro.png',
z={
character='media/image/characters/z_character.png',
screen1='media/image/characters/z_screen1.png',
@@ -293,39 +298,41 @@ IMG.init{
},
}
SKIN.load{
{name="crystal_scf", path='media/image/skin/crystal_scf.png'},
{name="matte_mrz", path='media/image/skin/matte_mrz.png'},
{name="shiny_chno", path='media/image/skin/shiny_chno.png'},
{name="contrast_mrz", path='media/image/skin/contrast_mrz.png'},
{name="polkadots_scf", path='media/image/skin/polkadots_scf.png'},
{name="toy_scf", path='media/image/skin/toy_scf.png'},
{name="smooth_mrz", path='media/image/skin/smooth_mrz.png'},
{name="simple_scf", path='media/image/skin/simple_scf.png'},
{name="glass_scf", path='media/image/skin/glass_scf.png'},
{name="penta_scf", path='media/image/skin/penta_scf.png'},
{name="bubble_scf", path='media/image/skin/bubble_scf.png'},
{name="minoes_scf", path='media/image/skin/minoes_scf.png'},
{name="pure_mrz", path='media/image/skin/pure_mrz.png'},
{name="bright_scf", path='media/image/skin/bright_scf.png'},
{name="glow_mrz", path='media/image/skin/glow_mrz.png'},
{name="plastic_mrz", path='media/image/skin/plastic_mrz.png'},
{name="paper_mrz", path='media/image/skin/paper_mrz.png'},
{name="yinyang_scf", path='media/image/skin/yinyang_scf.png'},
{name="cartooncup_earety", path='media/image/skin/cartooncup_earety.png'},
{name="jelly_miya", path='media/image/skin/jelly_miya.png'},
{name="guidetris_xmiao_lusisi",path='media/image/skin/guidetris_xmiao_lusisi.png'},
{name="brick_notypey", path='media/image/skin/brick_notypey.png'},
{name="gem_notypey", path='media/image/skin/gem_notypey.png'},
{name="classic", path='media/image/skin/classic_unknown.png'},
{name="ball_shaw", path='media/image/skin/ball_shaw.png'},
{name="retro_notypey", path='media/image/skin/retro_notypey.png'},
{name="pixel_chno", path='media/image/skin/pixel_chno.png'},
{name="pastel_chno", path='media/image/skin/pastel_chno.png'},
{name="letters_chno", path='media/image/skin/letters_chno.png'},
{name="kanji_chno", path='media/image/skin/kanji_chno.png'},
{name="textbone_mrz", path='media/image/skin/textbone_mrz.png'},
{name="coloredbone_mrz", path='media/image/skin/coloredbone_mrz.png'},
{name="wtf", path='media/image/skin/wtf_mrz.png'},
{name="Crystal (Scf)", path='media/image/skin/scf/crystal.png'},
{name="Smooth (MrZ)", path='media/image/skin/mrz/smooth.png'},
{name="Matte (MrZ)", path='media/image/skin/mrz/matte.png'},
{name="Glass (Scf)", path='media/image/skin/scf/glass.png'},
{name="Jelly (Miya)", path='media/image/skin/miya/jelly.png'},
{name="Simple (Scf)", path='media/image/skin/scf/simple.png'},
{name="Contrast (MrZ)", path='media/image/skin/mrz/contrast.png'},
{name="Plastic (MrZ)", path='media/image/skin/mrz/plastic.png'},
{name="Glow (MrZ)", path='media/image/skin/mrz/glow.png'},
{name="Bright (Scf)", path='media/image/skin/scf/bright.png'},
{name="Penta (Scf)", path='media/image/skin/scf/penta.png'},
{name="Bubble (Scf)", path='media/image/skin/scf/bubble.png'},
{name="Pure (MrZ)", path='media/image/skin/mrz/pure.png'},
{name="Letters (CHNO)", path='media/image/skin/chno/letters.png'},
{name="Kanji (CHNO)", path='media/image/skin/chno/kanji.png'},
{name="Pastel (CHNO)", path='media/image/skin/chno/pastel.png'},
{name="Classic", path='media/image/skin/unknown/classic.png'},
{name="Arcade (Asriel)", path='media/image/skin/asriel/arcade.png'},
{name="Shiny (CHNO)", path='media/image/skin/chno/shiny.png'},
{name="Brick (Notypey)", path='media/image/skin/notypey/brick.png'},
{name="Cartooncup (Earety)", path='media/image/skin/earety/cartooncup.png'},
{name="Paper (MrZ)", path='media/image/skin/mrz/paper.png'},
{name="Toy (Scf)", path='media/image/skin/scf/toy.png'},
{name="Polkadots (Scf)", path='media/image/skin/scf/polkadots.png'},
{name="Yinyang (Scf)", path='media/image/skin/scf/yinyang.png'},
{name="Minoes (Scf)", path='media/image/skin/scf/minoes.png'},
{name="Cardboard (Asriel, slimenergy)", path='media/image/skin/asriel/cardboard.png'},
{name="Ball (Shaw)", path='media/image/skin/shaw/ball.png'},
{name="Gem (Notypey)", path='media/image/skin/notypey/gem.png'},
{name="Pixel (CHNO)", path='media/image/skin/chno/pixel.png'},
{name="Retro (Notypey)", path='media/image/skin/notypey/retro.png'},
{name="Guidetris (xmiao, lusisi)", path='media/image/skin/guidetris_xmiao_lusisi.png'},
{name="Textbone (MrZ)", path='media/image/skin/mrz/textbone.png'},
{name="Coloredbone (MrZ)", path='media/image/skin/mrz/coloredbone.png'},
{name="WTF (MrZ)", path='media/image/skin/mrz/wtf.png'},
}
-- Initialize sound libs
@@ -397,8 +404,12 @@ do
RANKS.rhythm_h=nil; fs.remove('record/rhythm_h.rec')
RANKS.rhythm_u=nil; fs.remove('record/rhythm_u.rec')
end
if RANKS.bigbang then fs.remove('record/bigbang.rec') end
if RANKS.clearRush then fs.remove('record/clearRush.rec') end
if RANKS.bigbang then RANKS.bigbang=nil; fs.remove('record/bigbang.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~=VERSION.code then
@@ -424,7 +435,8 @@ do
for _,v in next,SETTING.skin do if v<1 or v>17 then v=17 end end
if not RSlist[SETTING.RS] then SETTING.RS='TRS' end
if SETTING.ghostType=='greyCell' then SETTING.ghostType='grayCell' end
if type(SETTING.skinSet)=='number' then SETTING.skinSet='crystal_scf' end
if type(SETTING.skinSet)=='number' then SETTING.skinSet='Crystal (Scf)' end
if string.find(SETTING.skinSet,"_") then SETTING.skinSet='Crystal (Scf)' end
if not TABLE.find({8,10,13,17,22,29,37,47,62,80,100},SETTING.frameMul) then SETTING.frameMul=100 end
if SETTING.cv then SETTING.vocPack,SETTING.cv=SETTING.cv end
if type(SETTING.bg)~='string' then SETTING.bg='on' end
@@ -432,6 +444,7 @@ do
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.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_dig then RANKS.infinite_dig=0 end
if not RANKS.sprint_10l then RANKS.sprint_10l=0 end
@@ -590,18 +603,22 @@ for _,fileName in next,fs.getDirectoryItems('replay') do
end
table.sort(REPLAY,function(a,b) return a.fileName>b.fileName end)
AUTHURL="https://studio26f.org/oauth?product=techmino"
AUTHHOST="cafuuchino1.3322.org:8081"
WS.switchHost('cafuuchino1.3322.org','10026','/techmino/ws/v1')
HTTP.setHost("cafuuchino1.3322.org:10026")
AUTHURL="https://www.studio26f.org/oauth?product=techmino"
AUTHHOST="www.studio26f.org:8080"
WS.switchHost('www.studio26f.org','8081','/techmino/ws/v1')
HTTP.setHost("www.studio26f.org:8081")
HTTP.setThreadCount(1)
-- Discord RPC
DiscordRPC=require'parts.discordRPC'
DiscordRPC.update()
table.insert(_LOADTIMELIST_,("Load Resources: %.3fs"):format(TIME()-_LOADTIME_))
for i=1,#_LOADTIMELIST_ do LOG(_LOADTIMELIST_[i]) end
-- Launch testing task if launch param received
if TABLE.find(arg,'-- test') then
if TABLE.find(arg,'--test') then
TASK.new(function()
while not LOADED do coroutine.yield() end

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 41 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

Before

Width:  |  Height:  |  Size: 613 B

After

Width:  |  Height:  |  Size: 613 B

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

View File

Before

Width:  |  Height:  |  Size: 91 B

After

Width:  |  Height:  |  Size: 91 B

View File

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.6 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View File

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

Before

Width:  |  Height:  |  Size: 837 B

After

Width:  |  Height:  |  Size: 837 B

View File

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
media/vocal/neuro/air.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
media/vocal/neuro/b2b.ogg Normal file

Binary file not shown.

BIN
media/vocal/neuro/b3b.ogg Normal file

Binary file not shown.

BIN
media/vocal/neuro/bye.ogg Normal file

Binary file not shown.

BIN
media/vocal/neuro/clear.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
media/vocal/neuro/cspin.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
media/vocal/neuro/deep.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
media/vocal/neuro/doubt.ogg Normal file

Binary file not shown.

BIN
media/vocal/neuro/espin.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
media/vocal/neuro/fspin.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
media/vocal/neuro/happy.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
media/vocal/neuro/hspin.ogg Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
media/vocal/neuro/ispin.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
media/vocal/neuro/jspin.ogg Normal file

Binary file not shown.

Binary file not shown.

BIN
media/vocal/neuro/lose.ogg Normal file

Binary file not shown.

BIN
media/vocal/neuro/lose0.ogg Normal file

Binary file not shown.

BIN
media/vocal/neuro/lspin.ogg Normal file

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More