7.2 KiB
maimai2 dev notes
Item types
| ItemKind | Name |
|---|---|
| 1 | Nameplate |
| 2 | Title |
| 3 | Icon |
| 5 | Music Unlock |
| 6 | Music Master Unlock |
| 7 | Music Re:Master Unlock |
| 8 | Music Strong Unlock (?) |
| 9 | Character |
| 10 | Partner |
| 11 | Frame |
| 12 | Tickets |
| 13 | Mile |
| 14 | Intimate Item |
| 15 | Kaleidx Scope Key |
Kaleidx Scope gates
Kaleidx Scope gate visibility is controlled by three server responses:
GetGameEventApimust return open event rows for the gate/course event IDs used by the game's static data.GetGameKaleidxScopeApimust return agameKaleidxScopeListrow for each gate the user can see. Current known gate IDs are1..6for the original gates,7for Prism/Center Tower,8for the post-Prism boss gate,9for Hope Gate, and10for the final challenge.GetUserKaleidxScopeApimust return auserKaleidxScopeListrow for the samegateId.
The client hides a gate when the user row is missing, the event is closed, or the row has isGateFound = false. A visible selectable gate needs at least:
{
"gateId": 8,
"isGateFound": true,
"isKeyFound": true,
"isClear": false
}
The unlock announcement can still appear when isGateFound = true, isKeyFound = true, and isInfoWatched = false; that announcement alone does not prove that the gate will be listed in the menu on the next download.
For progression past Prism Tower, UpsertUserAllApi must persist upsertUserAll.userKaleidxScopeList by (userId, gateId). AquaDX unlocks Prism/Center Tower gate 7 after gate 6 is clear. After gate 7 is clear, the next GetUserKaleidxScopeApi response must include gate 7 as clear and a gate 8 row with both found/key true. The same pattern applies for gates 9 and 10 after their preceding gates are clear.
Fixed AquaDX.v1 issue: older code advertised gates 1..10 from GetGameKaleidxScopeApi and saved uploaded Kaleidx rows in UpsertUserAllApi, but GetUserKaleidxScopeApi only backfilled missing rows for gates 1..6. It also forced every persisted row to isKeyFound = true before returning it. Existing users without usable rows for gate 7 or later could therefore receive an unlock-style message but still have no visible Prism Tower or post-Prism gate in the Kaleidx Scope menu.
To confirm the failure for a user, inspect their rows:
SELECT gate_id, is_gate_found, is_key_found, is_clear, is_info_watched
FROM maimai2_user_kaleidx
WHERE user_id = <internal_user_id>
ORDER BY gate_id;
If gate 7 is clear and gate 8 is missing, or if any target gate row has is_gate_found = 0, the menu will not show the next gate.
Multiplayer
Party Host/Client/Member
Manager.Party.Party/Host.cs : Host :
- TCP Listen 50100 (Accept into Member)
- UDP Broadcast 50100
- Send: StartRecruit, FinishRecruit
PartyLink/Party.cs : Party.Host : Exact same as Host.cs
Manager.Party.Party/Member.cs : Member :
- TCP Connect 50100
- Send: JoinResult, Kick, StartPlay, StartClientState, PartyMember{Info/State}, PartyPlayInfo, RequestMeasure
- Recv: RequestJoin, ClientState, ClientPlayInfo, UpdateMechaInfo, ResponseMeasure, FinishNews
PartyLink/Party.cs : Party.Member : Exact same as Member.cs
Manager.Party.Party/Client.cs : Client :
- UDP Listen 50100
- Recv: StartRecruit, FinishRecruit
- TCP Connect 50100
- Recv: JoinResult, Kick, StartPlay, StartClientState,PartyMember{Info/State}, PartyPlayInfo, RequestMeasure
- Send: RequestJoin, ClientState, ClientPlayInfo, UpdateMechaInfo, ResponseMeasure, FinishNews
PartyLink/Party.cs : Party.Client : Exact same as Client.cs
Enums
- ClientStateID: {Setup, Wait, Connect, Request, Joined, FinishSetting, ToReady, BeginPlay, AllBeginPlay, Ready, Sync, Play, FinishPlay, News, NewsEnd, Result, Disconnected, Finish, Error}
- JoinResult: {Success, Full, NoRecruit, Disconnect, AlreadyJoined, DifferentGroup, DifferentMusic, DifferentEventMode}
Models
- MechaInfo: IsJoin (bool), IP Address, MusicID, Entries[2], UserIDs[2], Rating[2], ...
- RecruitInfo: MechaInfo, MusicID, GroupID, EventModeID, JoinNumber, PartyStance, Start time, Recv time
- MemberPlayInfo: IP Address, Rankings[2], Achieves[2], Combos[2], Miss[2], ...
- ChainHistory: PacketNo (int), Chain (int)
Commands
- StartRecruit/FinishRecruit: RecruitInfo
- JoinResult: JoinResult (enum)
- RequestJoin: MechaInfo, GroupID, EventModeID
- UpdateMechaInfo: MechaInfo
- Kick: RecruitInfo, KickBy {Cancel, Start, Disconnect}
- RequestMeasure/ResponseMeasure: {} - Sync delay
- StartPlay: MaxMeasure (long), MyMeasure (long) - Sync delay
- StartClientState: ClientStateID (enum)
- ClientState: ClientStateID (enum)
- PartyMemberInfo: MechaInfo[2]
- PartyMemberState: ClientStateID[2]
- PartyPlayInfo: MemberPlayInfo[2], ChainHistory[10], Chain (int), ChainMiss (int), MaxChain (int), IsFullChain (bool), CalcStatus (int)
- ClientPlayInfo: IP Address, Count, IsValids[2], Achieves[2], Combos[2], Miss[2], ...
- FinishNews: IP Address, IsValids[2], GaugeClears[2], GaugeStockNums[2]
Setting Host/Client/Member
This might be for synchronizing event settings across different cabs, I'm not sure if this is relevant for multiplayer.
PartyLink/Setting.cs : Setting.Host :
- TCP Listen 50101 (Accept into Setting.Member)
- UDP Broadcast 50101
- Send: SettingHostAddress
- UDP Listen 50101
- Recv: SettingHostAddress (Check duplicate host)
PartyLink/Setting.cs : Setting.Client :
- TCP Connect 50101
- Send: SettingRequest
- Recv: SettingResponse, HeartBeat{}
- UDP Listen 50101
- Recv: SettingHostAddress
PartyLink/Setting.cs : Setting.Member :
- TCP Connect 50101
- Recv: SettingRequest, HeartBeat{}
- Send: SettingResponse, HeartBeat{}
Models
- SettingHostAddress: IP Address (u32), Group (int)
- SettingRequest: Group (int)
- SettingResponse: Group (int), Data (isEventMode, eventModeMusicCount, memberNumber)
Advertise
For finding IP addresses of other cabs and checking their latency.
PartyLink/Advertise.cs : Advertise.Manager :
- UDP Listen 50102
- Recv: AdvertiseRequest, AdvertiseResponse, AdvertiseGo
- UDP Broadcast 50102
- Send: AdvertiseRequest, AdvertiseResponse, AdvertiseGo
Models
- AdvertiseRequest: IP Address (u32), Group (int), Kind (int)
- AdvertiseResponse: IP Address (u32), Group (int), Kind (int)
- AdvertiseGo: IP Address (u32), Group (int), Kind (int), MaxUsec (long), MyUsec (long)
!! sendTo is not necessarily broadcast !!
DeliveryChecker
PartyLink/DeliveryChecker : DeliveryChecker.Manager :
- UDP Listen 50103
- Recv: AdvocateDelivery
- UDP Broadcast 50103
- Send: AdvocateDelivery
Models
- AdvocateDelivery: IP Address (u32)