[+] Generate example config via attributes

pull/78/head
Clansty 2024-10-27 22:44:12 +08:00
parent 5eb0424ee7
commit 6bb2685e03
No known key found for this signature in database
GPG Key ID: 3A6BE8BAF2EDE134
9 changed files with 541 additions and 510 deletions

View File

@ -31,6 +31,21 @@ jobs:
cd AquaMai
dotnet build -c Release
- name: Make example config
shell: cmd
run: |
cd AquaMai\Output
dotnet tool install -g dotnet-script
dotnet script genConfig.csx
- name: Prepare artifact
shell: cmd
run: |
cd AquaMai\Output
mkdir Upload
move AquaMai.dll Upload
move AquaMai.*.toml Upload
- uses: actions/upload-artifact@v4
with:
name: AquaMai
@ -39,10 +54,16 @@ jobs:
- name: Send to Telegram
if: github.event_name != 'pull_request'
run: |
$Uri = "https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendDocument"
$Uri = "https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendMediaGroup"
$Form = @{
chat_id = "-1002231087502"
caption = "${{ github.event.commits[0].message }}"
document = Get-Item AquaMai\Output\AquaMai.dll
media = @(
@{ type = "document"; media = "attach://aquamai_main"; caption = "${{ github.event.commits[0].message }}" },
@{ type = "document"; media = "attach://aquamai_zh" }
@{ type = "document"; media = "attach://aquamai_en" }
) | ConvertTo-Json
aquamai_main = Get-Item AquaMai\Output\Upload\AquaMai.dll
aquamai_zh = Get-Item AquaMai\Output\Upload\AquaMai.zh.toml
aquamai_en = Get-Item AquaMai\Output\Upload\AquaMai.en.toml
}
Invoke-RestMethod -Uri $uri -Form $Form -Method Post

View File

@ -287,8 +287,6 @@
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="AquaMai.zh.toml" WithCulture="false" />
<EmbeddedResource Include="AquaMai.toml" />
<EmbeddedResource Include="Resources\Locale.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Locale.Designer.cs</LastGenOutput>
@ -313,4 +311,10 @@
<PackageReference Include="Samboy063.Tomlet" Version="5.4.0" />
</ItemGroup>
<ItemGroup>
<None Update="genConfig.csx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -1,227 +0,0 @@
# ===================================
# Cheat: You control the buttons you press
[Cheat]
# Unlock normally event-only tickets
TicketUnlock=true
# Unlock maps that are not in this version
MapUnlock=true
# Unlock Utage without the need of DXRating 10000
UnlockUtage=true
# ===================================
# UX: User Experience Improvements
[UX]
# Single player: Show 1P only, at the center of the screen
SinglePlayer=true
# Remove the circle mask in the game
HideMask=true
# Set the version string displayed at the top-right corner of the screen
CustomVersionString=""
# Deprecated: Use `LoadAssetsPng` instead
# LoadJacketPng=true
# Load Jacket image from folder "LocalAssets" and filename "{MusicID}.png" for self-made charts
LoadAssetsPng=true
# Use the png jacket above as BGA if BGA is not found for self-made charts
# Use together with `LoadJacketPng`
LoadLocalBga=true
# Press key "7" for 1 second to skip to next step or restart current song
# Hold the bottom four buttons (3456) for official quick retry (non-utage only)
QuickSkip=true
# Add ".ab" image resources without the need of rebuilding a manifest
LoadAssetBundleWithoutManifest=true
# Random BGM, put Mai2Cue.{acb,awb} of old version of the game in `LocalAssets\Mai2Cue` and rename them
# Do not enable when SinglePlayer is off
RandomBgm=false
# Play "Master" difficulty on Demo screen
DemoMaster=true
# Execute some command on game idle or on game start
ExecOnIdle=""
ExecOnEntry=""
# Disable timers
# Not recommand to enable when SinglePlayer is off
ExtendTimer=true
# Save immediate after playing a song
ImmediateSave=true
# Prevent accidental touch of the Test button
TestProof=false
# Custom shop name in photo
# Also enable shop name display in SDGA
CustomPlaceName=""
# In the song selection screen, press the Service button or the "7" key (the round button in the middle of the arrow keys in the default ADX firmware) to toggle the display of self-made charts.
# A directory is considered to contain self-made charts if it does not have DataConfig.xml or OfficialChartsMark.txt in the Axxx directory.
HideSelfMadeCharts=true
# Place font.ttf in the LocalAssets directory to replace the game's global font
# Cannot be used together with FontFix
CustomFont=false
# Provide the ability to use custom note skins (advanced feature)
CustomNoteSkin=false
# Map touch actions to buttons
TouchToButtonInput=false
# Delayed the animation of the song start screen
# Hide "TRACK X" text and DX/Standard chart display box
# For recording chart confirmation
TrackStartProcessTweak=false
# Cannot be used together with HanabiFix
HideHanabi=false
[Fix]
# Allow login with higher data version
SkipVersionCheck=true
RemoveEncryption=true
ForceAsServer=true
# Force the game to be in FreePlay mode
ForceFreePlay=true
# Force the game to be in PaidPlay mode with 24 coins locked, conflicts with ForceFreePlay
ForcePaidPlay=false
# Add notes sprite to the pool to prevent use up
ExtendNotesPool=128
# Force the frame rate limit to 60 FPS and disable vSync. Do not use if your game has no issues
FrameRateLock=false
# Use Microsoft YaHei Bold to display characters not in the font library
# Cannot be used together with CustomFont
FontFix=true
# Make the Critical judgment of BreakSlide flash like BreakTap
# Align the judgment display of arc-shaped Slide with the judgment line accurately (it was slightly off before)
SlideJudgeTweak=true
# Cannot be used together with HideHanabi
HanabiFix=false
# Prevent gray network caused by mistakenly thinking it's an AimeDB server issue
IgnoreAimeServerError=true
[Utils]
# Log user ID on login
LogUserId=false
# Globally increase A judgment, unit is the same as in the game
JudgeAdjustA=0.0
# Globally increase B judgment, unit is the same as in the game
JudgeAdjustB=0.0
# Touch screen delay, unit is milliseconds, one second = 1000 milliseconds. Must be an integer
TouchDelay=0
# Show detail of selected song in music selection screen
SelectionDetail=true
# Show Network error detail in the game
ShowNetErrorDetail=true
# Show error log in the game
ShowErrorLog=false
# Display framerate
FrameRateDisplay=false
# Practice mode, activated by pressing Test in the game
# Must be used together with TestProof
PractiseMode=true
# Adjust the baud rate of the touch screen serial port, default value is 9600
# Requires hardware support. If you are unsure whether you can use it, you cannot use it
# Set to 0 to disable
TouchPanelBaudRate=0
# ===================================
# Save some potentially unnecessary time
[TimeSaving]
# Skip the warning screen and logo shown after the POST sequence
SkipWarningScreen=true
# Disable some useless delays to speed up the game boot process
ImproveLoadSpeed=true
# Directly enter the song selection screen after login
SkipToMusicSelection=false
# Skip possible prompts like "New area discovered", "New songs added", "There are events" during game login/registration
SkipEventInfo=true
# Skip the "Do not tap or slide vigorously" screen, immediately proceed to the next screen once data is loaded
IWontTapOrSlideVigorously=true
# Skip the "Goodbye" screen at the end of the game
SkipGameOverScreen=true
# Skip TrackStart screen
SkipTrackStart=true
# Show reason when net icon is gray
ShowNetErrorDetail=true
# Show a "skip" button like AstroDX after the notes end
ShowQuickEndPlay=true
[WindowState]
# If not enabled, no operations will be performed on the game window
Enable=false
# Window the game
Windowed=false
# Width and height for windowed mode, rendering resolution for fullscreen mode
# If set to 0, windowed mode will remember the user-set size, fullscreen mode will use the current display resolution
Width=0
Height=0
[CustomCameraId]
# Enable custom CameraId
# If enabled, you can customize the game to use the specified camera
Enable=false
PrintCameraList=false
LeftQrCamera=0
RightQrCamera=0
PhotoCamera=0
ChimeCamera=0
[TouchSensitivity]
# Enable custom sensitivity
# When enabled, the settings in Test mode will not take effect
# When disabled, the settings in Test mode can still be used
Enable=false
# Sensitivity adjustments in Test mode are not linear
# Default sensitivity in area A: 90, 80, 70, 60, 50, 40, 30, 26, 23, 20, 10
# Default sensitivity in other areas: 70, 60, 50, 40, 30, 20, 15, 10, 5, 1, 1
# A setting of 0 in Test mode corresponds to 40, 20 here, -5 corresponds to 90, 70, +5 corresponds to 10, 1
# The higher the number in Test mode, the lower the number here, resulting in higher sensitivity for official machines
# For ADX, the sensitivity is reversed, so the higher the number here, the higher the sensitivity
A1=40
A2=40
A3=40
A4=40
A5=40
A6=40
A7=40
A8=40
B1=20
B2=20
B3=20
B4=20
B5=20
B6=20
B7=20
B8=20
C1=20
C2=20
D1=20
D2=20
D3=20
D4=20
D5=20
D6=20
D7=20
D8=20
E1=20
E2=20
E3=20
E4=20
E5=20
E6=20
E7=20
E8=20
[CustomKeyMap]
Enable = false
# These settings will work regardless of whether you have enabled segatools' io4 emulation
Test = "ScrollLock"
Service = "Pause"
Button1_1P = "W"
Button2_1P = "E"
Button3_1P = "D"
Button4_1P = "C"
Button5_1P = "X"
Button6_1P = "Z"
Button7_1P = "A"
Button8_1P = "Q"
Select_1P = "Alpha3"
Button1_2P = "Keypad8"
Button2_2P = "Keypad9"
Button3_2P = "Keypad6"
Button4_2P = "Keypad3"
Button5_2P = "Keypad2"
Button6_2P = "Keypad1"
Button7_2P = "Keypad4"
Button8_2P = "Keypad7"
Select_2P = "KeypadMultiply"

View File

@ -1,244 +0,0 @@
# 试试使用 MaiChartManager 图形化配置 AquaMai 吧!
# https://github.com/clansty/MaiChartManager
# ===================================
# “作弊”功能
[Cheat]
# 解锁游戏里所有可能的跑图券
TicketUnlock=true
# 解锁游戏里所有的区域,包括非当前版本的(并不会帮你跑完)
MapUnlock=true
# 不需要万分也可以进宴会场
UnlockUtage=true
# ===================================
# 用户体验改进
[UX]
# 单人模式,不显示 2P
SinglePlayer=true
# 移除遮罩
HideMask=true
# 把右上角的版本更改为自定义文本
CustomVersionString=""
# 已弃用,请使用 LoadAssetsPng
# LoadJacketPng=true
# 通过游戏目录下 `LocalAssets\000000歌曲 ID.png` 加载封面,自制谱用
LoadAssetsPng=true
# 如果没有 dat 格式的 BGA 的话,就用歌曲的封面做背景,而不是显示迪拉熊的笑脸
# 请和 `LoadJacketPng` 一起用
LoadLocalBga=true
# 长按 Service 键或者键盘上的 “7” 键ADX 默认固件下箭头键中间的圆形按键)可以:
# - 跳过登录过程中的界面直接进入选歌界面
# - 在选歌界面直接结束游戏
# 在游玩界面,按一下 “7” 或者 Service 键重开当前的歌,按 1P 的“选择”键立即结束当前乐曲
# 打完最后一个音符之后也可以
# 按住下方四个按钮3456使用官方快速重开仅对非宴谱有效
QuickSkip=true
# 优化图片资源的加载,就算没有 AssetBundleImages.manifest 也可以正常加载 ab 格式的图片资源
# 导入了删除曲包之类的话,应该需要开启这个
LoadAssetBundleWithoutManifest=true
# 在 `LocalAssets\Mai2Cue` 这个目录下放置了旧版游戏的 Mai2Cue.{acb,awb} 并重命名的话,可以在播放游戏 BGM 的时候随机播放这里面的旧版游戏 BGM
# 和 2P 模式有冲突,如果你没有开启 'SinglePlayer' 的话,请关闭这个
RandomBgm=false
# 在闲置时的演示画面上播放紫谱而不是绿谱
DemoMaster=true
# 在游戏闲置或者玩家登录的时候执行指定的命令脚本
# 比如说可以在游戏闲置是降低显示器的亮度
ExecOnIdle=""
ExecOnEntry=""
# 关掉那些游戏中的倒计时
# 如果你没有开启 'SinglePlayer' 的话,不建议开这个,不过要开的话也不是不可以
ExtendTimer=true
# 打完一首歌的时候立即向服务器保存成绩
ImmediateSave=true
# 防止你不小心按到 Test 键Test 键需要长按 1 秒才能生效
TestProof=false
# 自定义拍照的店铺名称
# 同时在 SDGA 中会启用店铺名称的显示(但是不会在游戏里有设置)
CustomPlaceName=""
# 选歌界面按下 Service 键或者键盘上的 “7” 键ADX 默认固件下箭头键中间的圆形按键)切换自制谱的显示和隐藏
# 是否是自制谱的判断方式是 Axxx 目录里没有 DataConfig.xml 或 OfficialChartsMark.txt 就认为这个目录里是自制谱
HideSelfMadeCharts=true
# 在 LocalAssets 目录下放置 font.ttf 可以替换游戏的全局字体
# 不可以和 FontFix 一起使用
CustomFont=false
# 提供自定义音符皮肤的能力(高级功能)
CustomNoteSkin=false
# 映射触摸操作至实体按键
TouchToButtonInput=false
# 推迟了歌曲开始界面的动画
# 隐藏“TRACK X”字样和 DX/标准谱面的显示框
# 录制谱面确认用
TrackStartProcessTweak=false
# 完全隐藏烟花
# 不能和 HanabiFix 一起使用
HideHanabi=false
# ===================================
# 修复一些潜在的问题
[Fix]
# 原先如果你的账号版本比当前游戏设定的版本高的话,就会不能登录
# 开了这个选项之后就可以登录了,不过你的账号版本还是会被设定为当前游戏的版本
SkipVersionCheck=true
# 如果你在用未经修改的客户端,会默认加密到服务器的连接,而连接私服的时候不应该加密
# 开了这个选项之后就不会加密连接了,同时也会移除不同版本的客户端可能会对 API 接口加的后缀
# 正常情况下,请保持这个选项开启
RemoveEncryption=true
# 如果要配置店内招募的话,应该要把这个关闭
ForceAsServer=true
# 强制改为免费游玩FreePlay
ForceFreePlay=true
# 强制付费游玩并锁定 24 个币,和 ForceFreePlay 冲突
ForcePaidPlay=false
# 增加更多待命的音符贴图,防止奇怪的自制谱用完音符贴图池
ExtendNotesPool=128
# 强制设置帧率上限为 60 帧并关闭垂直同步。如果你的游戏没有问题,请不要使用
FrameRateLock=false
# 在显示字库里没有的字时使用微软雅黑 Bold 显示
# 不可以和 CustomFont 一起使用
FontFix=true
# 让 BreakSlide 的 Critical 判定也可以像 BreakTap 一样闪烁
# 让圆弧形的 Slide 的判定显示与判定线精确对齐 (原本会有一点歪)
SlideJudgeTweak=true
# 修复 1p 模式下的烟花大小
# 不能和 HideHanabi 一起使用
HanabiFix=true
# 防止因错误认为 AimeDB 服务器问题引起的灰网
IgnoreAimeServerError=true
[Utils]
# 登录时将 UserID 输出到日志
LogUserId=false
# 全局增加 A 判,单位和游戏里一样
JudgeAdjustA=0.0
# 全局增加 B 判,单位和游戏里一样
JudgeAdjustB=0.0
# 触摸屏延迟,单位为毫秒,一秒 = 1000 毫秒。必须是整数
TouchDelay=0
# 选歌界面显示选择的歌曲的详情
SelectionDetail=true
# 出现灰网时显示原因
ShowNetErrorDetail=true
# 在游戏中显示错误日志窗口而不是关闭游戏进程
ShowErrorLog=false
# 显示帧率
FrameRateDisplay=false
# 练习模式,在游戏中按 Test 打开
# 必须和 TestProof 一起用
PractiseMode=true
# 调整触摸屏串口波特率,默认值 9600
# 需要硬件配合。如果你不清楚你是否可以使用,那你不能使用
# 改为 0 禁用
TouchPanelBaudRate=0
# ===================================
# 节省一些不知道有用没用的时间
[TimeSaving]
# 跳过日服启动时候的 WARNING 界面
SkipWarningScreen=true
# 在自检界面,每个屏幕结束的时候都会等两秒才进入下一个屏幕,很浪费时间
# 开了这个选项之后就不会等了
ImproveLoadSpeed=true
# 登录完成后直接进入选歌界面
SkipToMusicSelection=false
# 跳过登录 / 注册游戏时候可能的 “发现了新的区域哟” “乐曲增加” “有活动哟” 之类的提示
SkipEventInfo=true
# 跳过“不要大力拍打或滑动哦”这个界面,数据一旦加载完就立马进入下一个界面
IWontTapOrSlideVigorously=true
# 跳过游戏结束的“再见”界面
SkipGameOverScreen=true
# 跳过乐曲开始界面
SkipTrackStart=true
# 音符结束之后显示像 AstroDX 一样的“跳过”按钮
ShowQuickEndPlay=true
[WindowState]
# 不启用的话,不会对游戏窗口做任何操作
Enable=false
# 窗口化游戏
Windowed=false
# 宽度和高度窗口化时为游戏窗口大小,全屏时为渲染分辨率
# 如果设为 0窗口化将记住用户设定的大小全屏时将使用当前显示器分辨率
Width=0
Height=0
[CustomCameraId]
# 是否启用自定义摄像头ID
# 启用后可以指定游戏使用的摄像头
Enable=false
PrintCameraList=false
LeftQrCamera=0
RightQrCamera=0
PhotoCamera=0
ChimeCamera=0
[TouchSensitivity]
# 是否启用自定义灵敏度
# 这里启用之后 Test 里的就不再起作用了
# 这里禁用之后就还是可以用 Test 里的调
Enable=false
# 在 Test 模式下调整的灵敏度不是线性的
# A 区默认灵敏度 90, 80, 70, 60, 50, 40, 30, 26, 23, 20, 10
# 其他区域默认灵敏度 70, 60, 50, 40, 30, 20, 15, 10, 5, 1, 1
# Test 里设置的 0 对应的是 40, 20 这一档,-5 是 90, 70+5 是 10, 1
# Test 里的数字越大,这里的数字越小,对于官机来说,灵敏度更大
# 而 ADX 的灵敏度是反的,所以对于 ADX这里的数字越大灵敏度越大
A1=40
A2=40
A3=40
A4=40
A5=40
A6=40
A7=40
A8=40
B1=20
B2=20
B3=20
B4=20
B5=20
B6=20
B7=20
B8=20
C1=20
C2=20
D1=20
D2=20
D3=20
D4=20
D5=20
D6=20
D7=20
D8=20
E1=20
E2=20
E3=20
E4=20
E5=20
E6=20
E7=20
E8=20
[CustomKeyMap]
Enable = false
# 这里的设置无论你是否启用了 segatools 的 io4 模拟都会工作
Test = "ScrollLock"
Service = "Pause"
Button1_1P = "W"
Button2_1P = "E"
Button3_1P = "D"
Button4_1P = "C"
Button5_1P = "X"
Button6_1P = "Z"
Button7_1P = "A"
Button8_1P = "Q"
Select_1P = "Alpha3"
Button1_2P = "Keypad8"
Button2_2P = "Keypad9"
Button3_2P = "Keypad6"
Button4_2P = "Keypad3"
Button5_2P = "Keypad2"
Button6_2P = "Keypad1"
Button7_2P = "Keypad4"
Button8_2P = "Keypad7"
Select_2P = "KeypadMultiply"

View File

@ -0,0 +1,10 @@
using System;
namespace AquaMai.Attributes;
[AttributeUsage(AttributeTargets.Property)]
public class ConfigCommentAttribute(string en = null, string zh = null) : Attribute
{
public string CommentEn { get; } = en;
public string CommentZh { get; } = zh;
}

View File

@ -1,4 +1,5 @@
using System.Diagnostics.CodeAnalysis;
using AquaMai.Attributes;
using AquaMai.CustomKeyMap;
namespace AquaMai
@ -6,113 +7,537 @@ namespace AquaMai
[SuppressMessage("ReSharper", "ClassNeverInstantiated.Global")]
public class Config
{
[ConfigComment(
en: "UX: User Experience Improvements",
zh: """
使 MaiChartManager AquaMai
https://github.com/clansty/MaiChartManager
""")]
public UXConfig UX { get; set; } = new();
[ConfigComment(
en: "Cheat: You control the buttons you press",
zh: "“作弊”功能")]
public CheatConfig Cheat { get; set; } = new();
[ConfigComment(
en: "Fix: Fix some potential issues",
zh: "修复一些潜在的问题")]
public FixConfig Fix { get; set; } = new();
[ConfigComment(
zh: "实用工具")]
public UtilsConfig Utils { get; set; } = new();
[ConfigComment(
en: "Time Saving: Skip some unnecessary screens",
zh: "节省一些不知道有用没用的时间,跳过一些不必要的界面")]
public TimeSavingConfig TimeSaving { get; set; } = new();
[ConfigComment(
zh: "窗口相关设置")]
public WindowStateConfig WindowState { get; set; } = new();
[ConfigComment(
en: "Custom camera ID settings",
zh: "自定义摄像头 ID")]
public CustomCameraIdConfig CustomCameraId { get; set; } = new();
[ConfigComment(
zh: "触摸灵敏度设置")]
public TouchSensitivityConfig TouchSensitivity { get; set; } = new();
[ConfigComment(
zh: "自定义按键映射")]
public CustomKeyMapConfig CustomKeyMap { get; set; } = new();
public class CheatConfig
{
[ConfigComment(
en: "Unlock normally event-only tickets",
zh: "解锁游戏里所有可能的跑图券")]
public bool TicketUnlock { get; set; }
[ConfigComment(
en: "Unlock maps that are not in this version",
zh: "解锁游戏里所有的区域,包括非当前版本的(并不会帮你跑完)")]
public bool MapUnlock { get; set; }
[ConfigComment(
en: "Unlock Utage without the need of DXRating 10000",
zh: "不需要万分也可以进宴会场")]
public bool UnlockUtage { get; set; }
}
public class UXConfig
{
public string Locale { get; set; }
[ConfigComment(
en: "Language for mod UI, supports en and zh",
zh: "Mod 界面的语言,支持 en 和 zh")]
public string Locale { get; set; } = "";
[ConfigComment(
en: "Single player: Show 1P only, at the center of the screen",
zh: "单人模式,不显示 2P")]
public bool SinglePlayer { get; set; }
[ConfigComment(
en: "Remove the circle mask in the game",
zh: "移除遮罩")]
public bool HideMask { get; set; }
[ConfigComment(
en: "Load Jacket image from folder \"LocalAssets\" and filename \"{MusicID}.png\" for self-made charts",
zh: "通过游戏目录下 `LocalAssets\\000000歌曲 ID.png` 加载封面,自制谱用")]
public bool LoadAssetsPng { get; set; }
public bool LoadJacketPng { get; set; }
[ConfigComment(
en: "Add \".ab\" image resources without the need of rebuilding a manifest",
zh: """
AssetBundleImages.manifest ab
""")]
public bool LoadAssetBundleWithoutManifest { get; set; }
[ConfigComment(
en: """
Press key "7" for 1 second to skip to next step or restart current song
Hold the bottom four buttons (3456) for official quick retry (non-utage only)
""",
zh: """
Service 7 ADX
-
-
7 Service 1P
3456使
""")]
public bool QuickSkip { get; set; }
[ConfigComment(
en: """
Random BGM, put Mai2Cue.{acb,awb} of old version of the game in `LocalAssets\Mai2Cue` and rename them
Do not enable when SinglePlayer is off
""",
zh: """
`LocalAssets\Mai2Cue` Mai2Cue.{acb,awb} BGM BGM
2P 'SinglePlayer'
""")]
public bool RandomBgm { get; set; }
[ConfigComment(
en: "Play \"Master\" difficulty on Demo screen",
zh: "在闲置时的演示画面上播放紫谱而不是绿谱")]
public bool DemoMaster { get; set; }
[ConfigComment(
en: """
Disable timers
Not recommand to enable when SinglePlayer is off
""",
zh: """
'SinglePlayer'
""")]
public bool ExtendTimer { get; set; }
[ConfigComment(
en: "Save immediate after playing a song",
zh: "打完一首歌的时候立即向服务器保存成绩")]
public bool ImmediateSave { get; set; }
[ConfigComment(
en: """
Use the png jacket above as BGA if BGA is not found for self-made charts
Use together with `LoadJacketPng`
""",
zh: """
dat BGA
`LoadJacketPng`
""")]
public bool LoadLocalBga { get; set; }
[ConfigComment(
en: "Prevent accidental touch of the Test button, requires 1 second long press to take effect",
zh: "防止你不小心按到 Test 键Test 键需要长按 1 秒才能生效")]
public bool TestProof { get; set; }
[ConfigComment(
en: """
In the song selection screen, press the Service button or the "7" key (the round button in the middle of the arrow keys in the default ADX firmware) to toggle the display of self-made charts.
A directory is considered to contain self-made charts if it does not have DataConfig.xml or OfficialChartsMark.txt in the Axxx directory.
""",
zh: """
Service 7 ADX
Axxx DataConfig.xml OfficialChartsMark.txt
""")]
public bool HideSelfMadeCharts { get; set; }
[ConfigComment(
en: """
Place font.ttf in the LocalAssets directory to replace the game's global font
Cannot be used together with FontFix
""",
zh: """
LocalAssets font.ttf
FontFix 使
""")]
public bool CustomFont { get; set; }
[ConfigComment(
en: "Provide the ability to use custom note skins (advanced feature)",
zh: "提供自定义音符皮肤的能力(高级功能)")]
public bool CustomNoteSkin { get; set; }
[ConfigComment(
en: "Map touch actions to buttons",
zh: "映射触摸操作至实体按键")]
public bool TouchToButtonInput { get; set; }
[ConfigComment(
en: """
Delayed the animation of the song start screen
Hide "TRACK X" text and DX/Standard chart display box
For recording chart confirmation
""",
zh: """
TRACK X DX/
""")]
public bool TrackStartProcessTweak { get; set; }
[ConfigComment(
en: "Cannot be used together with HanabiFix",
zh: """
HanabiFix 使
""")]
public bool HideHanabi { get; set; }
[ConfigComment(
en: "Set the version string displayed at the top-right corner of the screen",
zh: "把右上角的版本更改为自定义文本")]
public string CustomVersionString { get; set; } = "";
[ConfigComment(
en: """
Custom shop name in photo
Also enable shop name display in SDGA
""",
zh: """
SDGA
""")]
public string CustomPlaceName { get; set; } = "";
[ConfigComment(
en: "Execute some command on game idle",
zh: """
""")]
public string ExecOnIdle { get; set; } = "";
[ConfigComment(
en: "Execute some command on game start",
zh: "在玩家登录的时候执行指定的命令脚本")]
public string ExecOnEntry { get; set; } = "";
}
public class FixConfig
{
[ConfigComment(
en: "Allow login with higher data version",
zh: """
""")]
public bool SkipVersionCheck { get; set; }
[ConfigComment(
zh: """
API
""")]
public bool RemoveEncryption { get; set; }
[ConfigComment(
zh: "如果要配置店内招募的话,应该要把这个关闭")]
public bool ForceAsServer { get; set; } = true;
[ConfigComment(
en: "Force the game to be in FreePlay mode",
zh: "强制改为免费游玩FreePlay")]
public bool ForceFreePlay { get; set; } = true;
[ConfigComment(
en: "Force the game to be in PaidPlay mode with 24 coins locked, conflicts with ForceFreePlay",
zh: "强制付费游玩并锁定 24 个币,和 ForceFreePlay 冲突")]
public bool ForcePaidPlay { get; set; }
[ConfigComment(
en: "Add notes sprite to the pool to prevent use up",
zh: "增加更多待命的音符贴图,防止奇怪的自制谱用完音符贴图池")]
public int ExtendNotesPool { get; set; }
[ConfigComment(
en: "Force the frame rate limit to 60 FPS and disable vSync. Do not use if your game has no issues",
zh: "强制设置帧率上限为 60 帧并关闭垂直同步。如果你的游戏没有问题,请不要使用")]
public bool FrameRateLock { get; set; }
[ConfigComment(
en: """
Use Microsoft YaHei Bold to display characters not in the font library
Cannot be used together with CustomFont
""",
zh: """
使 Bold
CustomFont 使
""")]
public bool FontFix { get; set; }
[ConfigComment(
en: """
Make the Critical judgment of BreakSlide flash like BreakTap
Align the judgment display of arc-shaped Slide with the judgment line accurately (it was slightly off before)
""",
zh: """
BreakSlide Critical BreakTap
Slide 线 ()
""")]
public bool SlideJudgeTweak { get; set; }
[ConfigComment(
en: "Cannot be used together with HideHanabi",
zh: """
1p
HideHanabi 使
""")]
public bool HanabiFix { get; set; }
[ConfigComment(
en: "Prevent gray network caused by mistakenly thinking it's an AimeDB server issue",
zh: "防止因错误认为 AimeDB 服务器问题引起的灰网,建议开启")]
public bool IgnoreAimeServerError { get; set; }
}
public class UtilsConfig
{
[ConfigComment(
en: "Log user ID on login",
zh: "登录时将 UserID 输出到日志")]
public bool LogUserId { get; set; }
[ConfigComment(
en: "Globally increase A judgment, unit is the same as in the game",
zh: "全局增加 A 判,单位和游戏里一样")]
public float JudgeAdjustA { get; set; }
[ConfigComment(
en: "Globally increase B judgment, unit is the same as in the game",
zh: "全局增加 B 判,单位和游戏里一样")]
public float JudgeAdjustB { get; set; }
[ConfigComment(
en: "Touch screen delay, unit is milliseconds, one second = 1000 milliseconds. Must be an integer",
zh: "触摸屏延迟,单位为毫秒,一秒 = 1000 毫秒。必须是整数")]
public int TouchDelay { get; set; }
[ConfigComment(
en: """
Practice mode, activated by pressing Test in the game
Must be used together with TestProof
""",
zh: """
Test
TestProof
""")]
public bool PractiseMode { get; set; }
[ConfigComment(
en: "Show detail of selected song in music selection screen",
zh: "选歌界面显示选择的歌曲的详情")]
public bool SelectionDetail { get; set; }
[ConfigComment(
en: "Show Network error detail in the game",
zh: "出现灰网时显示原因")]
public bool ShowNetErrorDetail { get; set; }
[ConfigComment(
en: "Show error log in the game",
zh: "在游戏中显示错误日志窗口而不是关闭游戏进程")]
public bool ShowErrorLog { get; set; }
[ConfigComment(
en: "Display framerate",
zh: "显示帧率")]
public bool FrameRateDisplay { get; set; }
[ConfigComment(
en: """
Adjust the baud rate of the touch screen serial port, default value is 9600
Requires hardware support. If you are unsure whether you can use it, you cannot use it
Set to 0 to disable
""",
zh: """
9600
使使
0
""")]
public int TouchPanelBaudRate { get; set; }
}
public class TimeSavingConfig
{
[ConfigComment(
en: "Skip the warning screen and logo shown after the POST sequence",
zh: "跳过日服启动时候的 WARNING 界面")]
public bool SkipWarningScreen { get; set; }
[ConfigComment(
en: "Disable some useless delays to speed up the game boot process",
zh: """
""")]
public bool ImproveLoadSpeed { get; set; }
[ConfigComment(
en: "Directly enter the song selection screen after login",
zh: "登录完成后直接进入选歌界面")]
public bool SkipToMusicSelection { get; set; }
[ConfigComment(
en: "Skip possible prompts like \"New area discovered\", \"New songs added\", \"There are events\" during game login/registration",
zh: "跳过登录 / 注册游戏时候可能的 “发现了新的区域哟” “乐曲增加” “有活动哟” 之类的提示")]
public bool SkipEventInfo { get; set; }
[ConfigComment(
en: "Skip the \"Do not tap or slide vigorously\" screen, immediately proceed to the next screen once data is loaded",
zh: "跳过“不要大力拍打或滑动哦”这个界面,数据一旦加载完就立马进入下一个界面")]
public bool IWontTapOrSlideVigorously { get; set; }
[ConfigComment(
en: "Skip the \"Goodbye\" screen at the end of the game",
zh: "跳过游戏结束的“再见”界面")]
public bool SkipGameOverScreen { get; set; }
[ConfigComment(
en: "Skip TrackStart screen",
zh: "跳过乐曲开始界面")]
public bool SkipTrackStart { get; set; }
[ConfigComment(
en: "Show a \"skip\" button like AstroDX after the notes end",
zh: "音符结束之后显示像 AstroDX 一样的“跳过”按钮")]
public bool ShowQuickEndPlay { get; set; }
}
public class WindowStateConfig
{
[ConfigComment(
en: "If not enabled, no operations will be performed on the game window",
zh: "不启用的话,不会对游戏窗口做任何操作")]
public bool Enable { get; set; }
[ConfigComment(
en: "Window the game",
zh: "窗口化游戏")]
public bool Windowed { get; set; }
[ConfigComment(
en: """
Width and height for windowed mode, rendering resolution for fullscreen mode
If set to 0, windowed mode will remember the user-set size, fullscreen mode will use the current display resolution
""",
zh: """
0使
""")]
public int Width { get; set; }
[ConfigComment(
zh: "高度")]
public int Height { get; set; }
}
public class CustomCameraIdConfig
{
[ConfigComment(
en: """
Enable custom CameraId
If enabled, you can customize the game to use the specified camera
""",
zh: """
ID
使
""")]
public bool Enable { get; set; }
[ConfigComment(
en: "Print the camera list to the log when starting, can be used as a basis for modification",
zh: "启动时打印摄像头列表到日志中,可以作为修改的依据")]
public bool PrintCameraList { get; set; } = false;
[ConfigComment(
en: "DX Pass 1P",
zh: "DX Pass 1P")]
public int LeftQrCamera { get; set; } = 0;
[ConfigComment(
en: "DX Pass 2P",
zh: "DX Pass 2P")]
public int RightQrCamera { get; set; } = 0;
[ConfigComment(
zh: "玩家摄像头")]
public int PhotoCamera { get; set; } = 0;
[ConfigComment(
zh: "二维码扫描摄像头")]
public int ChimeCamera { get; set; } = 0;
}
public class TouchSensitivityConfig
{
[ConfigComment(
en: """
Enable custom sensitivity
When enabled, the settings in Test mode will not take effect
When disabled, the settings in Test mode can still be used
""",
zh: """
Test
Test
""")]
public bool Enable { get; set; }
[ConfigComment(
en: """
Sensitivity adjustments in Test mode are not linear
Default sensitivity in area A: 90, 80, 70, 60, 50, 40, 30, 26, 23, 20, 10
Default sensitivity in other areas: 70, 60, 50, 40, 30, 20, 15, 10, 5, 1, 1
A setting of 0 in Test mode corresponds to 40, 20 here, -5 corresponds to 90, 70, +5 corresponds to 10, 1
The higher the number in Test mode, the lower the number here, resulting in higher sensitivity for official machines
For ADX, the sensitivity is reversed, so the higher the number here, the higher the sensitivity
""",
zh: """
Test 线
A 90, 80, 70, 60, 50, 40, 30, 26, 23, 20, 10
70, 60, 50, 40, 30, 20, 15, 10, 5, 1, 1
Test 0 40, 20 -5 90, 70+5 10, 1
Test
ADX ADX
""")]
public byte A1 { get; set; } = 40;
public byte A2 { get; set; } = 40;
public byte A3 { get; set; } = 40;
public byte A4 { get; set; } = 40;
@ -150,7 +575,11 @@ namespace AquaMai
public class CustomKeyMapConfig
{
[ConfigComment(
en: "These settings will work regardless of whether you have enabled segatools' io4 emulation",
zh: "这里的设置无论你是否启用了 segatools 的 io4 模拟都会工作")]
public bool Enable { get; set; }
public KeyCodeID Test { get; set; } = (KeyCodeID)115;
public KeyCodeID Service { get; set; } = (KeyCodeID)5;
public KeyCodeID Button1_1P { get; set; } = (KeyCodeID)67;

View File

@ -0,0 +1,50 @@
using System;
using System.IO;
using System.Reflection;
using AquaMai.Attributes;
using Tomlet;
using Tomlet.Models;
namespace AquaMai;
public static class ConfigGenerator
{
public static void GenerateConfig()
{
var defaultConfig = new Config();
foreach (var lang in (string[]) ["en", "zh"])
{
File.WriteAllText($"AquaMai.{lang}.toml", SerializeConfigWithComments(defaultConfig, lang));
}
}
public static string SerializeConfigWithComments(Config config, string lang)
{
var tomlDoc = TomletMain.DocumentFrom(config);
MakeComments(tomlDoc, typeof(Config), lang);
return tomlDoc.SerializedValue;
}
private static void MakeComments(TomlTable table, Type configType, string lang)
{
foreach (var property in configType.GetProperties())
{
var value = table.GetValue(property.Name);
var comment = property.GetCustomAttribute<ConfigCommentAttribute>();
if (comment != null)
{
value.Comments.PrecedingComment = lang switch
{
"en" => comment.CommentEn,
"zh" => comment.CommentZh,
_ => throw new ArgumentException($"Unsupported language: {lang}")
};
}
if (value is TomlTable subTable)
{
MakeComments(subTable, property.PropertyType, lang);
}
}
}
}

View File

@ -3,15 +3,12 @@ using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using AquaMai.Fix;
using AquaMai.Helpers;
using AquaMai.MaimaiDX2077;
using AquaMai.Resources;
using AquaMai.Utils;
using AquaMai.UX;
using MelonLoader;
using Monitor;
using Tomlet;
using UnityEngine;
@ -90,13 +87,6 @@ namespace AquaMai
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetConsoleOutputCP(uint wCodePageID);
private void WriteEmbeddedResourceToFile(string resource, string file)
{
using var s = MelonAssembly.Assembly.GetManifestResourceStream(resource);
using var fs = File.Open(file, FileMode.Create);
s.CopyTo(fs);
}
private static void InitLocale()
{
if (!string.IsNullOrEmpty(AppConfig.UX.Locale))
@ -123,13 +113,12 @@ namespace AquaMai
// Check if AquaMai.toml exists
if (!File.Exists("AquaMai.toml"))
{
WriteEmbeddedResourceToFile("AquaMai.AquaMai.toml", "AquaMai.example.toml");
WriteEmbeddedResourceToFile("AquaMai.AquaMai.zh.toml", "AquaMai.example.zh.toml");
ConfigGenerator.GenerateConfig();
MelonLogger.Error("======================================!!!");
MelonLogger.Error("AquaMai.toml not found! Please create it.");
MelonLogger.Error("找不到配置文件 AquaMai.toml请创建。");
MelonLogger.Error("Example copied to AquaMai.example.toml");
MelonLogger.Error("示例已复制到 AquaMai.example.zh.toml");
MelonLogger.Error("Example copied to AquaMai.en.toml");
MelonLogger.Error("示例已复制到 AquaMai.zh.toml");
MelonLogger.Error("=========================================");
return;
}
@ -137,10 +126,6 @@ namespace AquaMai
// Read AquaMai.toml to load settings
AppConfig = TomletMain.To<Config>(File.ReadAllText("AquaMai.toml"));
// Migrate old settings
AppConfig.UX.LoadAssetsPng = AppConfig.UX.LoadAssetsPng || AppConfig.UX.LoadJacketPng;
AppConfig.UX.LoadJacketPng = false;
// Init locale with patching C# runtime
// https://stackoverflow.com/questions/1952638/single-assembly-multi-language-windows-forms-deployment-ilmerge-and-satellite-a
Patch(typeof(I18nSingleAssemblyHook));
@ -179,24 +164,24 @@ namespace AquaMai
// New Features & Changes
// 现在自定义皮肤相关的功能应该有 CustomSkin, JudgeDisplay4B, CustomTrackStartDiff
// 后续应该还会接着做, 所以也许可以考虑把自定义皮肤相关的部分单独分一类 ?
Patch(typeof(CustomSkins)); // Rename: CustomNoteSkin -> CustomSkins
Patch(typeof(JudgeDisplay4B));
Patch(typeof(CustomTrackStartDiff));
Patch(typeof(RealisticRandomJudge)); // 本来是用来调试判定显示4B的, 觉得还挺有趣就单独做成功能了
Patch(typeof(DisableTrackStartTabs)); // 从 TrackStartProcessTweak 里单独拆出来了
// Patch(typeof(CustomSkins)); // Rename: CustomNoteSkin -> CustomSkins
// Patch(typeof(JudgeDisplay4B));
// Patch(typeof(CustomTrackStartDiff));
// Patch(typeof(RealisticRandomJudge)); // 本来是用来调试判定显示4B的, 觉得还挺有趣就单独做成功能了
// Patch(typeof(DisableTrackStartTabs)); // 从 TrackStartProcessTweak 里单独拆出来了
// 以下三项拆分自 SlideJudgeTweak
Patch(typeof(FanJudgeFlip));
Patch(typeof(BreakSlideJudgeBlink));
Patch(typeof(FixCircleSlideJudge)); // 这个我觉得算无副作用, 可以常开
// Patch(typeof(FanJudgeFlip));
// Patch(typeof(BreakSlideJudgeBlink));
// Patch(typeof(FixCircleSlideJudge)); // 这个我觉得算无副作用, 可以常开
// 这是一项往 Sinmai 里加各种新 note 的企划, 目前只完成了可高度自定义形状的星星
// 未来还会缓慢更新, 我建议单开一个功能分类
// 注意需要往 UserLib 里放入 System.Numeric.dll
Patch(typeof(CustomNoteTypePatch));
// Patch(typeof(CustomNoteTypePatch));
# if DEBUG
Patch(typeof(LogNetworkErrors));
# endif

View File

@ -0,0 +1,3 @@
#r "AquaMai.dll"
AquaMai.ConfigGenerator.GenerateConfig();