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 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');

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] 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
@@ -130,10 +132,12 @@ jobs:
prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }} prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }}
auto-test: auto-test:
runs-on: ubuntu-latest 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
@@ -141,16 +145,35 @@ jobs:
with: with:
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
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: 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
@@ -159,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')
@@ -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('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 }}
@@ -187,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
@@ -219,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
@@ -237,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
@@ -298,138 +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: 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:
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
@@ -441,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)\
@@ -464,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 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 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
@@ -522,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)

1
.gitignore vendored
View File

@@ -1,5 +1,4 @@
.vscode .vscode
libAndroid
*.ini *.ini
.DS_Store .DS_Store
Thumbs.db 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 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{

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) 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
@@ -70,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'
@@ -92,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
@@ -172,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)
@@ -421,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]
@@ -461,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
@@ -476,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
@@ -718,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
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 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

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<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 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 -- floor seconds
timeUnits[#timeUnits]=floorint(timeUnits[#timeUnits]) timeUnits[#timeUnits]=floorint(timeUnits[#timeUnits])
local outputStr=''
for i=1,#timeUnits do 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] return timeUnits[i]..timeLetters[i]..' '..timeUnits[i+1]..timeLetters[i+1]
end end
end end
@@ -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

View File

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

View File

@@ -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,16 +6,20 @@ 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)
-- print('C0',res,err)
assert(res,err) assert(res,err)
-- WebSocket handshake -- WebSocket handshake
@@ -31,6 +36,7 @@ do-- Connect
-- First line of HTTP -- First line of HTTP
res,err=SOCK:receive('*l') res,err=SOCK:receive('*l')
-- print('C',res,err)
assert(res,err) assert(res,err)
local code,ctLen local code,ctLen
code=res:find(' ') code=res:find(' ')
@@ -39,22 +45,28 @@ do-- Connect
-- Get body length from headers and remove headers -- Get body length from headers and remove headers
repeat repeat
res,err=SOCK:receive('*l') res,err=SOCK:receive('*l')
-- print('H',res,err)
assert(res,err) assert(res,err)
if not ctLen and res:find('length') then if not ctLen and res:find('content-length') then
ctLen=tonumber(res:match('%d+')) ctLen=tonumber(res:match('%d+')) or 0
end end
until res=='' until res==''
-- Result -- Result
if code=='101' then
CHN_push(readCHN,'success')
end
-- Content(?)
if ctLen then if ctLen then
if code=='101' then res,err=SOCK:receive(ctLen)
CHN_push(readCHN,'success') -- print('R',res,err)
else if code~='101' then
res,err=SOCK:receive(ctLen)
res=JSON.decode(assert(res,err)) res=JSON.decode(assert(res,err))
error((code or "XXX")..":"..(res and res.reason or "Server Error")) error((code or "XXX")..":"..(res and res.reason or "Server Error"))
end end
end end
SOCK:settimeout(0) SOCK:settimeout(0)
end end
@@ -136,10 +148,10 @@ local readThread=coroutine.wrap(function()
assert(res,err) assert(res,err)
length=shl(byte(res,1),8)+byte(res,2) length=shl(byte(res,1),8)+byte(res,2)
elseif length==127 then elseif length==127 then
local lenData -- 'res' is 'lenData' here
lenData,err=_receive(SOCK,8) res,err=_receive(SOCK,8)
assert(res,err) 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 length=shl(_5,24)+shl(_6,16)+shl(_7,8)+_8
end end
res,err=_receive(SOCK,length) res,err=_receive(SOCK,length)
@@ -158,12 +170,14 @@ local readThread=coroutine.wrap(function()
lBuffer=lBuffer..res lBuffer=lBuffer..res
if fin then if fin then
CHN_push(readCHN,lBuffer) CHN_push(readCHN,lBuffer)
-- print('M',lBuffer)
lBuffer="" lBuffer=""
end end
else else
CHN_push(readCHN,op) CHN_push(readCHN,op)
if fin then if fin then
CHN_push(readCHN,res) CHN_push(readCHN,res)
-- print('S',res)
lBuffer="" lBuffer=""
else else
lBuffer=res lBuffer=res
@@ -176,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)

View File

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

View File

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

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