mirror of
https://github.com/RYDE-WORK/ballistica.git
synced 2026-01-25 00:13:27 +08:00
Added storagename and store_deafult functionality to dataclassio
This commit is contained in:
parent
3cabcc0b9a
commit
cb2b3abf25
@ -420,24 +420,24 @@
|
||||
"assets/build/ba_data/audio/zoeOw.ogg": "https://files.ballistica.net/cache/ba1/14/f1/4f2995d78fc20dd79dfb39c5d554",
|
||||
"assets/build/ba_data/audio/zoePickup01.ogg": "https://files.ballistica.net/cache/ba1/57/ac/6ed0caecd25dc23688debed24c45",
|
||||
"assets/build/ba_data/audio/zoeScream01.ogg": "https://files.ballistica.net/cache/ba1/32/08/38dac4a79ab2acee76a75d32a310",
|
||||
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/dd/f3/f401d6adf6f91b8189d73f17aaf0",
|
||||
"assets/build/ba_data/data/langdata.json": "https://files.ballistica.net/cache/ba1/5a/7d/3a4c37ada60b546b1ff1dfaa6d3e",
|
||||
"assets/build/ba_data/data/languages/arabic.json": "https://files.ballistica.net/cache/ba1/46/d2/ffaeb8d34e72e5d4baee7ffa2df8",
|
||||
"assets/build/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/44/ed/5b972fa848cffb73723533c2ccb7",
|
||||
"assets/build/ba_data/data/languages/belarussian.json": "https://files.ballistica.net/cache/ba1/53/65/623cbd373025127bbce64ffb8979",
|
||||
"assets/build/ba_data/data/languages/chinese.json": "https://files.ballistica.net/cache/ba1/ce/d6/c90afebc5dfca2b43d2defc3a42c",
|
||||
"assets/build/ba_data/data/languages/chinesetraditional.json": "https://files.ballistica.net/cache/ba1/0b/8a/eafc8bcf22576fa24fc8a697ecfe",
|
||||
"assets/build/ba_data/data/languages/croatian.json": "https://files.ballistica.net/cache/ba1/66/bf/6e98398016da261296b8c306560e",
|
||||
"assets/build/ba_data/data/languages/czech.json": "https://files.ballistica.net/cache/ba1/e3/10/ace3a73616f1f36540e585e5bbce",
|
||||
"assets/build/ba_data/data/languages/danish.json": "https://files.ballistica.net/cache/ba1/3f/46/e4da3c1d2b0ebf916df55c608b28",
|
||||
"assets/build/ba_data/data/languages/dutch.json": "https://files.ballistica.net/cache/ba1/d1/07/37b7adc3dbec7328d26c5325f212",
|
||||
"assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/a0/78/7d4ef87f7f8c04f9684db7098b91",
|
||||
"assets/build/ba_data/data/languages/english.json": "https://files.ballistica.net/cache/ba1/b6/92/f245bd6c11a4ab2eaff037b38cfe",
|
||||
"assets/build/ba_data/data/languages/esperanto.json": "https://files.ballistica.net/cache/ba1/6e/fd/685a4e1da031474d47a1d9eb2731",
|
||||
"assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/41/30/040a5038fccbfeaa28e85d3bc863",
|
||||
"assets/build/ba_data/data/languages/french.json": "https://files.ballistica.net/cache/ba1/c5/9b/e627b5c99b11ac88e85267a02244",
|
||||
"assets/build/ba_data/data/languages/german.json": "https://files.ballistica.net/cache/ba1/d1/2d/47f4f84ca569a8b64bd500d4b36d",
|
||||
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/3d/88/6ca54f6089c255f9e788c1878965",
|
||||
"assets/build/ba_data/data/languages/gibberish.json": "https://files.ballistica.net/cache/ba1/17/82/e053185f86ba5c907185881273fb",
|
||||
"assets/build/ba_data/data/languages/greek.json": "https://files.ballistica.net/cache/ba1/51/31/64479524c0ee990b3e97ffdca068",
|
||||
"assets/build/ba_data/data/languages/hindi.json": "https://files.ballistica.net/cache/ba1/32/a4/fae7a30ead18c6cb97db60dd9445",
|
||||
"assets/build/ba_data/data/languages/hungarian.json": "https://files.ballistica.net/cache/ba1/f7/60/bfe1977d51b66db1084b123cd69e",
|
||||
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/69/cf/4a1e297b73613fd1b87fed8d2565",
|
||||
"assets/build/ba_data/data/languages/indonesian.json": "https://files.ballistica.net/cache/ba1/d6/43/599430105ffecff486da7fc32a4c",
|
||||
"assets/build/ba_data/data/languages/italian.json": "https://files.ballistica.net/cache/ba1/93/0d/b511ed987ac27769204b624e73b4",
|
||||
"assets/build/ba_data/data/languages/korean.json": "https://files.ballistica.net/cache/ba1/78/d3/16b37707d4ce4df826d0b0bc1766",
|
||||
"assets/build/ba_data/data/languages/persian.json": "https://files.ballistica.net/cache/ba1/c1/14/b013ec0a6557533f0ff49f27d000",
|
||||
@ -450,7 +450,7 @@
|
||||
"assets/build/ba_data/data/languages/spanish.json": "https://files.ballistica.net/cache/ba1/32/83/8fa66d906da02dde3a87f18999cb",
|
||||
"assets/build/ba_data/data/languages/swedish.json": "https://files.ballistica.net/cache/ba1/50/9f/be006ba19be6a69a57837eb6dca0",
|
||||
"assets/build/ba_data/data/languages/turkish.json": "https://files.ballistica.net/cache/ba1/5b/c4/2173bc10edea17ed3734f08a8c94",
|
||||
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/3e/f3/4e9003c88e959d0d75a225c7a87e",
|
||||
"assets/build/ba_data/data/languages/ukrainian.json": "https://files.ballistica.net/cache/ba1/20/b3/b52d8c6db509c2c74a97e202e335",
|
||||
"assets/build/ba_data/data/languages/venetian.json": "https://files.ballistica.net/cache/ba1/9b/b7/c9fd483742201911caeef3d89822",
|
||||
"assets/build/ba_data/data/languages/vietnamese.json": "https://files.ballistica.net/cache/ba1/5c/1c/8af479b70c9e6595b338dbb563c5",
|
||||
"assets/build/ba_data/data/maps/big_g.json": "https://files.ballistica.net/cache/ba1/47/0a/a617cc85d927b576c4e6fc1091ed",
|
||||
@ -3932,40 +3932,40 @@
|
||||
"assets/build/windows/Win32/ucrtbased.dll": "https://files.ballistica.net/cache/ba1/b5/85/f8b6d0558ddb87267f34254b1450",
|
||||
"assets/build/windows/Win32/vc_redist.x86.exe": "https://files.ballistica.net/cache/ba1/1c/e1/4a1a2eddda2f4aebd5f8b64ab08e",
|
||||
"assets/build/windows/Win32/vcruntime140d.dll": "https://files.ballistica.net/cache/ba1/50/8d/bc2600ac9491f1b14d659709451f",
|
||||
"build/prefab/full/linux_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/6c/7e/79149d8af4291810bbd832ef7701",
|
||||
"build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/3f/50/160d497455a7476adbf7c753a5e2",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/cd/9e/d9edf9e5583bb4f20ee8c73b38f3",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/09/5d/29f79e4288346f4d78a5afd906c0",
|
||||
"build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/2f/56/16f552d4a957cb1c575b12d1164c",
|
||||
"build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/51/7b/a018f0f6d8127bcad72b79a5c6b3",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/b7/c4/8d78dbe2a68936c252a7ed285d50",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/eb/8b/94351be14bb57ddf3b8907acf900",
|
||||
"build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/c8/1a/2e390a528232f76eb0cc9fe58aa9",
|
||||
"build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/19/4c/da621e6aad46901b735335d5e033",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/6c/83/4b689f57bb212538e852083acc41",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/7e/8d/957899a603943879ae09bee71b18",
|
||||
"build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/1f/3e/9bcc32d3032cc1201e5f57e9c261",
|
||||
"build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/66/73/be60f521a16f3b28fdf3769e9c5c",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4c/f0/66034910a954d533bff1c4e2f97a",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/21/a1/617bba8cc95bd35f333591cd02b1",
|
||||
"build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/00/70/a42d41cbcc0b332c93b8a330e3d8",
|
||||
"build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/c0/b4/aee6ae279007ef8f517ad7239082",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/c6/4d/3c89d6c16046f87e2de408f9b346",
|
||||
"build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/ae/ea/5ff962d1d91641d7a2d56e077655",
|
||||
"build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/ed/77/ede8e30345b9cd8e91e010572062",
|
||||
"build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/17/ac/7234096717caeab0184e614b92e2",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/25/db/c7cbb696d01b3e06473dd245f238",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a3/91/7ce48b71049da124347507beca0d",
|
||||
"build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/94/75/3d443e98f12ae5cdd1ffb721e778",
|
||||
"build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/16/95/102d669e9201cbb19d612aa8989a",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/95/66/80c8745d3b4cd1e094b497d5a26b",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/91/8f/2786d57375fa7fb6895df63ca912",
|
||||
"build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/df/96/85db2b907e626288067812fb1572",
|
||||
"build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0e/d5/4e4aa07be3cad0571fd5b7ef53b1",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/17/62/13517437b0f3a86ea60f20c98a46",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/26/ce/d5a5768d56bbcf3efc5ad447c97f",
|
||||
"build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/11/b4/9815e9f95ea41a6ea5ddceca4c68",
|
||||
"build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/53/3e/a46827f7195fa97c583cffad3798",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d5/68/49f82ac1f5161d843f2fdbd4dffe",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/88/a4/74dd159772dd8ae4d49f53e358dc"
|
||||
"build/prefab/full/linux_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/2b/e1/628191b4c0b260036e0d7abc6ee3",
|
||||
"build/prefab/full/linux_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/83/51/0511414b7d61f636b55bb6e63b00",
|
||||
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/83/a1/3046fc4c86fb31655da6b2d076cb",
|
||||
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ba/e7/d0c78aaf3c6982eee87471ff5637",
|
||||
"build/prefab/full/linux_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/a3/43/5e2dd209bedf7f3c5550f416fb6e",
|
||||
"build/prefab/full/linux_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/7b/e0/5c94fd10dfb247529548a76ddd75",
|
||||
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/13/54/1e3e4532fa176cca029fc448ac6e",
|
||||
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/d9/5b/d8a9b7d2cda3eaff208944273b08",
|
||||
"build/prefab/full/mac_arm64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/3b/37/1055f167fbab28003f7129e5aee6",
|
||||
"build/prefab/full/mac_arm64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/25/aa/6f6c4ef8ab7d39f46b8bf69fa18b",
|
||||
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f3/c4/619b03c16992b06d8162cdb96126",
|
||||
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/2f/1b/6ec4f564ea77d42a30917c8434c9",
|
||||
"build/prefab/full/mac_x86_64/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/b5/73/194f8c35a467b775eebe24de90a2",
|
||||
"build/prefab/full/mac_x86_64/release/ballisticacore": "https://files.ballistica.net/cache/ba1/b0/a7/7848042fbcd5764af31020e53ae1",
|
||||
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/28/a0/d2d53829a074e5c06cf5785af1cd",
|
||||
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4d/53/3027bbbab3c19fa2b8d0fa718d96",
|
||||
"build/prefab/full/windows_x86/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/f9/c7/b04b34fcdc0e0e0f9976b5639c0c",
|
||||
"build/prefab/full/windows_x86/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/87/a9/e295e82a1f3b423fb2f8f2eb462f",
|
||||
"build/prefab/full/windows_x86_server/debug/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/1c/bd/4afc4c92dcaf095928f66d5c61d3",
|
||||
"build/prefab/full/windows_x86_server/release/dist/ballisticacore_headless.exe": "https://files.ballistica.net/cache/ba1/ca/56/0923f65bb7c80211f614c4816ab5",
|
||||
"build/prefab/lib/linux_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/54/e0/8c89d241ca37ae32c9b46ea71456",
|
||||
"build/prefab/lib/linux_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e0/05/94ac67cbf2e665eeecfc77246caf",
|
||||
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0f/e1/be897ef0e73b0e52c59f3396e0cd",
|
||||
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f6/12/cbf8807fe66907ea9cc2a2da6a48",
|
||||
"build/prefab/lib/linux_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7e/b6/aa2c6f318fc52e6e76b31501a937",
|
||||
"build/prefab/lib/linux_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1f/b3/80375870a9ab83bbb63b50b03a73",
|
||||
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/5c/2e/a1b1f2126b3150c6f11e799c3805",
|
||||
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b6/6b/37174b3a0d72a05f1bb3d904b78b",
|
||||
"build/prefab/lib/mac_arm64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/43/b7/8f87aa950891250923c7cb617d32",
|
||||
"build/prefab/lib/mac_arm64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1a/e9/a0c9c846c00b5ed9645ddc70e44a",
|
||||
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8a/e5/1f93415fb55842479f5ce0d375af",
|
||||
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e7/36/2475ad00f41cf75d63c786f3db39",
|
||||
"build/prefab/lib/mac_x86_64/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/6c/52/ff241eeae0d43f433f66a8b2dcbb",
|
||||
"build/prefab/lib/mac_x86_64/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/40/a3/a2c2c741e551c40d0700888737a7",
|
||||
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/a1/ef/fa977c1c8a05781f6af8321b31f2",
|
||||
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0d/15/336d51f7894aeedba54f5aabb04a"
|
||||
}
|
||||
4
.idea/dictionaries/ericf.xml
generated
4
.idea/dictionaries/ericf.xml
generated
@ -67,6 +67,8 @@
|
||||
<w>androidstudiocode</w>
|
||||
<w>anim</w>
|
||||
<w>animcurve</w>
|
||||
<w>annarg</w>
|
||||
<w>annargs</w>
|
||||
<w>anntype</w>
|
||||
<w>anota</w>
|
||||
<w>anroid</w>
|
||||
@ -1087,6 +1089,7 @@
|
||||
<w>introspectable</w>
|
||||
<w>intstr</w>
|
||||
<w>iobj</w>
|
||||
<w>iometa</w>
|
||||
<w>ioprep</w>
|
||||
<w>ioprepped</w>
|
||||
<w>ipaddress</w>
|
||||
@ -1805,6 +1808,7 @@
|
||||
<w>rankbutton</w>
|
||||
<w>rankwindow</w>
|
||||
<w>raspbian</w>
|
||||
<w>rawkey</w>
|
||||
<w>rawpath</w>
|
||||
<w>rawpaths</w>
|
||||
<w>rcfile</w>
|
||||
|
||||
@ -41,6 +41,8 @@
|
||||
<w>anchorx</w>
|
||||
<w>animcurve</w>
|
||||
<w>aniso</w>
|
||||
<w>annarg</w>
|
||||
<w>annargs</w>
|
||||
<w>anntype</w>
|
||||
<w>ansiwrap</w>
|
||||
<w>anyofallof</w>
|
||||
@ -487,6 +489,7 @@
|
||||
<w>intstr</w>
|
||||
<w>invote</w>
|
||||
<w>iobj</w>
|
||||
<w>iometa</w>
|
||||
<w>ioprep</w>
|
||||
<w>ioprepped</w>
|
||||
<w>iserverget</w>
|
||||
@ -797,6 +800,7 @@
|
||||
<w>rakhov</w>
|
||||
<w>raspbian</w>
|
||||
<w>rasterizer</w>
|
||||
<w>rawkey</w>
|
||||
<w>reaaaly</w>
|
||||
<w>readset</w>
|
||||
<w>realloc</w>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<!-- THIS FILE IS AUTO GENERATED; DO NOT EDIT BY HAND -->
|
||||
<h4><em>last updated on 2021-05-14 for Ballistica version 1.6.3 build 20367</em></h4>
|
||||
<h4><em>last updated on 2021-05-24 for Ballistica version 1.6.3 build 20367</em></h4>
|
||||
<p>This page documents the Python classes and functions in the 'ba' module,
|
||||
which are the ones most relevant to modding in Ballistica. If you come across something you feel should be included here or could be better explained, please <a href="mailto:support@froemling.net">let me know</a>. Happy modding!</p>
|
||||
<hr>
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
namespace ballistica {
|
||||
|
||||
// These are set automatically via script; don't change here.
|
||||
const int kAppBuildNumber = 20367;
|
||||
const int kAppBuildNumber = 20368;
|
||||
const char* kAppVersion = "1.6.3";
|
||||
|
||||
// Our standalone globals.
|
||||
|
||||
@ -852,7 +852,7 @@ enum class NodeMessageType {
|
||||
kFooting
|
||||
};
|
||||
|
||||
enum class AccountState { kSignedOut, kSigningIn, kSignedIn };
|
||||
enum class LoginState { kSignedOut, kSigningIn, kSignedIn };
|
||||
|
||||
enum class CameraMode { kFollow, kOrbit };
|
||||
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
|
||||
namespace ballistica {
|
||||
|
||||
// Global account functionality.
|
||||
/// Global account functionality.
|
||||
class Account {
|
||||
public:
|
||||
Account();
|
||||
@ -20,25 +20,26 @@ class Account {
|
||||
static auto AccountTypeToString(AccountType type) -> std::string;
|
||||
static auto AccountTypeToIconString(AccountType type) -> std::string;
|
||||
|
||||
auto GetAccountName() -> std::string;
|
||||
auto GetAccountID() -> std::string;
|
||||
auto GetAccountToken() -> std::string;
|
||||
auto GetAccountExtra() -> std::string;
|
||||
auto GetAccountExtra2() -> std::string;
|
||||
auto GetLoginName() -> std::string;
|
||||
auto GetLoginID() -> std::string;
|
||||
auto GetToken() -> std::string;
|
||||
auto GetExtra() -> std::string;
|
||||
auto GetExtra2() -> std::string;
|
||||
|
||||
// Return the current account state.
|
||||
// If an int pointer is passed, state-num will also be returned.
|
||||
auto GetAccountState(int* state_num = nullptr) -> AccountState;
|
||||
/// Return the current account state.
|
||||
/// If an int pointer is passed, state-num will also be returned.
|
||||
auto GetLoginState(int* state_num = nullptr) -> LoginState;
|
||||
|
||||
// An extra value included when passing our account info to the server
|
||||
// ..(can be used for platform-specific install-signature stuff, etc).
|
||||
auto SetAccountExtra(const std::string& extra) -> void;
|
||||
auto SetAccountExtra2(const std::string& extra) -> void;
|
||||
auto SetAccountToken(const std::string& account_id, const std::string& token)
|
||||
auto SetExtra(const std::string& extra) -> void;
|
||||
auto SetExtra2(const std::string& extra) -> void;
|
||||
auto SetToken(const std::string& account_id, const std::string& token)
|
||||
-> void;
|
||||
|
||||
auto SetAccount(AccountType account_type, AccountState account_state,
|
||||
const std::string& name, const std::string& id) -> void;
|
||||
auto SetLogin(AccountType account_type, LoginState login_state,
|
||||
const std::string& login_name, const std::string& login_id)
|
||||
-> void;
|
||||
|
||||
auto SetProductsPurchased(const std::vector<std::string>& products) -> void;
|
||||
auto GetProductPurchased(const std::string& product) -> bool;
|
||||
@ -51,13 +52,13 @@ class Account {
|
||||
std::mutex mutex_;
|
||||
std::unordered_map<std::string, bool> product_purchases_;
|
||||
int product_purchases_state_{};
|
||||
std::string account_name_;
|
||||
std::string account_id_;
|
||||
std::string account_token_;
|
||||
std::string account_extra_;
|
||||
std::string account_extra_2_;
|
||||
AccountState account_state_{AccountState::kSignedOut};
|
||||
int account_state_num_{};
|
||||
std::string login_name_;
|
||||
std::string login_id_;
|
||||
std::string token_;
|
||||
std::string extra_;
|
||||
std::string extra_2_;
|
||||
LoginState login_state_{LoginState::kSignedOut};
|
||||
int login_state_num_{};
|
||||
};
|
||||
|
||||
} // namespace ballistica
|
||||
|
||||
@ -255,17 +255,14 @@ void Game::PushMediaPruneCall(int level) {
|
||||
|
||||
void Game::PushSetAccountTokenCall(const std::string& account_id,
|
||||
const std::string& token) {
|
||||
PushCall(
|
||||
[account_id, token] { g_account->SetAccountToken(account_id, token); });
|
||||
PushCall([account_id, token] { g_account->SetToken(account_id, token); });
|
||||
}
|
||||
|
||||
void Game::PushSetAccountCall(AccountType account_type,
|
||||
AccountState account_state,
|
||||
const std::string& account_name,
|
||||
const std::string& account_id) {
|
||||
void Game::PushSetLoginCall(AccountType account_type, LoginState account_state,
|
||||
const std::string& account_name,
|
||||
const std::string& account_id) {
|
||||
PushCall([this, account_type, account_state, account_name, account_id] {
|
||||
g_account->SetAccount(account_type, account_state, account_name,
|
||||
account_id);
|
||||
g_account->SetLogin(account_type, account_state, account_name, account_id);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -32,9 +32,9 @@ class Game : public Module {
|
||||
auto LaunchClientSession() -> void;
|
||||
auto LaunchReplaySession(const std::string& file_name) -> void;
|
||||
|
||||
auto PushSetAccountCall(AccountType account_type, AccountState account_state,
|
||||
const std::string& account_name,
|
||||
const std::string& account_id) -> void;
|
||||
auto PushSetLoginCall(AccountType account_type, LoginState account_state,
|
||||
const std::string& account_name,
|
||||
const std::string& account_id) -> void;
|
||||
auto PushSetAccountTokenCall(const std::string& account_id,
|
||||
const std::string& token) -> void;
|
||||
auto PushPartyInviteCall(const std::string& name,
|
||||
|
||||
@ -75,10 +75,10 @@ auto PlayerSpec::GetSpecString() const -> std::string {
|
||||
|
||||
auto PlayerSpec::GetAccountPlayerSpec() -> PlayerSpec {
|
||||
PlayerSpec spec;
|
||||
if (g_account->GetAccountState() == AccountState::kSignedIn) {
|
||||
if (g_account->GetLoginState() == LoginState::kSignedIn) {
|
||||
spec.account_type_ = g_app_globals->account_type;
|
||||
spec.name_ =
|
||||
Utils::GetValidUTF8(g_account->GetAccountName().c_str(), "bsgaps");
|
||||
Utils::GetValidUTF8(g_account->GetLoginName().c_str(), "bsgaps");
|
||||
} else {
|
||||
spec.name_ =
|
||||
Utils::GetValidUTF8(g_platform->GetDeviceName().c_str(), "bsgaps2");
|
||||
|
||||
@ -1072,7 +1072,7 @@ void Platform::SignIn(const std::string& account_type) {
|
||||
Log("SignIn() unimplemented");
|
||||
}
|
||||
|
||||
void Platform::AccountDidChange() {
|
||||
void Platform::LoginDidChange() {
|
||||
// Default is no-op.
|
||||
}
|
||||
|
||||
|
||||
@ -295,7 +295,7 @@ class Platform {
|
||||
virtual auto SignIn(const std::string& account_type) -> void;
|
||||
virtual auto SignOut() -> void;
|
||||
virtual auto GameCenterLogin() -> void;
|
||||
virtual auto AccountDidChange() -> void;
|
||||
virtual auto LoginDidChange() -> void;
|
||||
|
||||
#pragma mark MUSIC PLAYBACK ----------------------------------------------------
|
||||
|
||||
|
||||
@ -9,12 +9,13 @@ import datetime
|
||||
from dataclasses import field, dataclass
|
||||
from typing import (TYPE_CHECKING, Optional, List, Set, Any, Dict, Sequence,
|
||||
Union, Tuple)
|
||||
from typing_extensions import Annotated
|
||||
|
||||
import pytest
|
||||
|
||||
from efro.util import utc_now
|
||||
from efro.dataclassio import (dataclass_validate, dataclass_from_dict,
|
||||
dataclass_to_dict, ioprepped)
|
||||
dataclass_to_dict, ioprepped, IOMeta)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
pass
|
||||
@ -460,6 +461,58 @@ def test_extra_data() -> None:
|
||||
assert 'nonexistent' not in out
|
||||
|
||||
|
||||
def test_meta() -> None:
|
||||
"""Testing iometa annotations."""
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class _TestClass:
|
||||
dval: Annotated[Dict, IOMeta('d')]
|
||||
|
||||
obj = _TestClass(dval={'foo': 'bar'})
|
||||
|
||||
# Make sure key is working.
|
||||
assert dataclass_to_dict(obj) == {'d': {'foo': 'bar'}}
|
||||
|
||||
# Setting store_default False without providing a default or
|
||||
# default_factory should fail.
|
||||
with pytest.raises(TypeError):
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class _TestClass2:
|
||||
dval: Annotated[Dict, IOMeta('d', store_default=False)]
|
||||
|
||||
@ioprepped
|
||||
@dataclass
|
||||
class _TestClass3:
|
||||
dval: Annotated[Dict, IOMeta('d', store_default=False)] = field(
|
||||
default_factory=dict)
|
||||
ival: Annotated[int, IOMeta('i', store_default=False)] = 123
|
||||
|
||||
# Both attrs are default; should get stripped out.
|
||||
obj3 = _TestClass3()
|
||||
assert dataclass_to_dict(obj3) == {}
|
||||
|
||||
# Both attrs are non-default vals; should remain in output.
|
||||
obj3 = _TestClass3(dval={'foo': 'bar'}, ival=124)
|
||||
assert dataclass_to_dict(obj3) == {'d': {'foo': 'bar'}, 'i': 124}
|
||||
|
||||
# Test going the other way.
|
||||
obj3 = dataclass_from_dict(
|
||||
_TestClass3,
|
||||
{
|
||||
'd': {
|
||||
'foo': 'barf'
|
||||
},
|
||||
'i': 125
|
||||
},
|
||||
allow_unknown_attrs=False,
|
||||
)
|
||||
assert obj3.dval == {'foo': 'barf'}
|
||||
assert obj3.ival == 125
|
||||
|
||||
|
||||
def test_dict() -> None:
|
||||
"""Test various dict related bits."""
|
||||
|
||||
|
||||
@ -21,7 +21,10 @@ from enum import Enum
|
||||
import dataclasses
|
||||
import typing
|
||||
import datetime
|
||||
from typing import TYPE_CHECKING, TypeVar, Generic, get_type_hints
|
||||
from typing import TYPE_CHECKING, TypeVar, Generic
|
||||
# Note: can pull this from typing once we update to Python 3.9+
|
||||
# noinspection PyProtectedMember
|
||||
from typing_extensions import get_args, get_type_hints, _AnnotatedAlias
|
||||
|
||||
from efro.util import enum_by_value
|
||||
|
||||
@ -54,6 +57,27 @@ PREP_ATTR = '_DCIOPREP'
|
||||
EXTRA_ATTRS_ATTR = '_DCIOEXATTRS'
|
||||
|
||||
|
||||
class IOMeta:
|
||||
"""Metadata for specifying io behavior."""
|
||||
|
||||
def __init__(self, storagename: str = None, store_default: bool = True):
|
||||
self.storagename = storagename
|
||||
self.store_default = store_default
|
||||
|
||||
def validate_for_field(self, cls: Type, field: dataclasses.Field) -> None:
|
||||
"""Ensure the IOMeta instance is ok to use with the provided field."""
|
||||
|
||||
# Turning off store_default requires the field to have either
|
||||
# a default_factory or a default
|
||||
if not self.store_default:
|
||||
default_factory: Any = field.default_factory # type: ignore
|
||||
if (default_factory is dataclasses.MISSING
|
||||
and field.default is dataclasses.MISSING):
|
||||
raise TypeError(f'Field {field.name} of {cls} has'
|
||||
f' neither a default nor a default_factory;'
|
||||
f' store_default=False cannot be set for it.')
|
||||
|
||||
|
||||
def dataclass_to_dict(obj: Any, coerce_to_float: bool = True) -> dict:
|
||||
"""Given a dataclass object, return a json-friendly dict.
|
||||
|
||||
@ -192,6 +216,9 @@ class PrepData:
|
||||
# Resolved annotation data with 'live' classes.
|
||||
annotations: Dict[str, Any]
|
||||
|
||||
# Map of storage names to attr names.
|
||||
storage_names_to_attr_names: Dict[str, str]
|
||||
|
||||
|
||||
class PrepSession:
|
||||
"""Context for a prep."""
|
||||
@ -202,6 +229,7 @@ class PrepSession:
|
||||
def prep_dataclass(self, cls: Type, recursion_level: int) -> PrepData:
|
||||
"""Run prep on a dataclass if necessary and return its prep data."""
|
||||
|
||||
# We should only need to do this once per dataclass.
|
||||
existing_data = getattr(cls, PREP_ATTR, None)
|
||||
if existing_data is not None:
|
||||
assert isinstance(existing_data, PrepData)
|
||||
@ -227,11 +255,11 @@ class PrepSession:
|
||||
' @efro.dataclassio.prepped decorator).', cls)
|
||||
|
||||
try:
|
||||
# Use default globalns which should be the class' module,
|
||||
# but provide our own locals to cover things like typing.*
|
||||
# which are generally not actually present at runtime for us.
|
||||
# resolved_annotations = get_type_hints(cls, localns=localns)
|
||||
resolved_annotations = get_type_hints(cls)
|
||||
# NOTE: perhaps we want to expose the globalns/localns args
|
||||
# to this?
|
||||
# pylint: disable=unexpected-keyword-arg
|
||||
resolved_annotations = get_type_hints(cls, include_extras=True)
|
||||
# pylint: enable=unexpected-keyword-arg
|
||||
except Exception as exc:
|
||||
raise RuntimeError(
|
||||
f'dataclassio prep for {cls} failed with error: {exc}.'
|
||||
@ -239,17 +267,35 @@ class PrepSession:
|
||||
f' at the module level or add them as part of an explicit'
|
||||
f' prep call.') from exc
|
||||
|
||||
# noinspection PyDataclass
|
||||
fields = dataclasses.fields(cls)
|
||||
fields_by_name = {f.name: f for f in fields}
|
||||
|
||||
storage_names_to_attr_names: Dict[str, str] = {}
|
||||
|
||||
# Ok; we've resolved actual types for this dataclass.
|
||||
# now recurse through them, verifying that we support all contained
|
||||
# types and prepping any contained dataclass types.
|
||||
for attrname, attrtype in resolved_annotations.items():
|
||||
for attrname, anntype in resolved_annotations.items():
|
||||
|
||||
anntype, iometa = _parse_annotated(anntype)
|
||||
|
||||
# If we found attached IOMeta data, make sure it contains
|
||||
# valid values for the field it is attached to.
|
||||
if iometa is not None:
|
||||
iometa.validate_for_field(cls, fields_by_name[attrname])
|
||||
if iometa.storagename is not None:
|
||||
storage_names_to_attr_names[iometa.storagename] = attrname
|
||||
|
||||
self.prep_type(cls,
|
||||
attrname,
|
||||
attrtype,
|
||||
anntype,
|
||||
recursion_level=recursion_level + 1)
|
||||
|
||||
# Success! Store our resolved stuff with the class and we're done.
|
||||
prepdata = PrepData(annotations=resolved_annotations)
|
||||
prepdata = PrepData(
|
||||
annotations=resolved_annotations,
|
||||
storage_names_to_attr_names=storage_names_to_attr_names)
|
||||
setattr(cls, PREP_ATTR, prepdata)
|
||||
return prepdata
|
||||
|
||||
@ -279,10 +325,15 @@ class PrepSession:
|
||||
# Everything below this point assumes the annotation type resolves
|
||||
# to a concrete type.
|
||||
if not isinstance(origin, type):
|
||||
print('ORIGIN IS', origin, type(origin))
|
||||
raise TypeError(
|
||||
f'Unsupported type found for \'{attrname}\' on {cls}:'
|
||||
f' {anntype}')
|
||||
|
||||
# extras = get_args(anntype)
|
||||
# if extras:
|
||||
# print('FOUND EXTRAS FOR', anntype)
|
||||
|
||||
if origin in SIMPLE_TYPES:
|
||||
return
|
||||
|
||||
@ -467,6 +518,8 @@ class _Outputter:
|
||||
return self._process_dataclass(type(self._obj), self._obj, '')
|
||||
|
||||
def _process_dataclass(self, cls: Type, obj: Any, fieldpath: str) -> Any:
|
||||
# pylint: disable=too-many-locals
|
||||
# pylint: disable=too-many-branches
|
||||
prep = PrepSession(explicit=False).prep_dataclass(type(obj),
|
||||
recursion_level=0)
|
||||
fields = dataclasses.fields(obj)
|
||||
@ -477,12 +530,35 @@ class _Outputter:
|
||||
subfieldpath = f'{fieldpath}.{fieldname}'
|
||||
else:
|
||||
subfieldpath = fieldname
|
||||
fieldtype = prep.annotations[fieldname]
|
||||
anntype = prep.annotations[fieldname]
|
||||
value = getattr(obj, fieldname)
|
||||
outvalue = self._process_value(cls, subfieldpath, fieldtype, value)
|
||||
|
||||
anntype, iometa = _parse_annotated(anntype)
|
||||
|
||||
# If we're not storing default values for this fella,
|
||||
# we can skip all output processing if we've got a default value.
|
||||
if iometa is not None and not iometa.store_default:
|
||||
default_factory: Any = field.default_factory # type: ignore
|
||||
if default_factory is not dataclasses.MISSING:
|
||||
if default_factory() == value:
|
||||
continue
|
||||
elif field.default is not dataclasses.MISSING:
|
||||
if field.default == value:
|
||||
continue
|
||||
else:
|
||||
raise RuntimeError(
|
||||
f'Field {fieldname} of {cls} has'
|
||||
f' neither a default nor a default_factory;'
|
||||
f' store_default=False cannot be set for it.'
|
||||
f' (AND THIS SHOULD HAVE BEEN CAUGHT IN PREP!)')
|
||||
|
||||
outvalue = self._process_value(cls, subfieldpath, anntype, value)
|
||||
if self._create:
|
||||
assert out is not None
|
||||
out[fieldname] = outvalue
|
||||
storagename = (fieldname if
|
||||
(iometa is None or iometa.storagename is None)
|
||||
else iometa.storagename)
|
||||
out[storagename] = outvalue
|
||||
|
||||
# If there's extra-attrs stored on us, check/include them.
|
||||
extra_attrs = getattr(obj, EXTRA_ATTRS_ATTR, None)
|
||||
@ -820,8 +896,11 @@ class _Inputter(Generic[T]):
|
||||
fields = dataclasses.fields(cls)
|
||||
fields_by_name = {f.name: f for f in fields}
|
||||
args: Dict[str, Any] = {}
|
||||
for key, value in values.items():
|
||||
for rawkey, value in values.items():
|
||||
key = prep.storage_names_to_attr_names.get(rawkey, rawkey)
|
||||
field = fields_by_name.get(key)
|
||||
|
||||
# Store unknown attrs off to the side (or error if desired).
|
||||
if field is None:
|
||||
if self._allow_unknown_attrs:
|
||||
if self._discard_unknown_attrs:
|
||||
@ -840,11 +919,13 @@ class _Inputter(Generic[T]):
|
||||
f"'{cls.__name__}' has no '{key}' field.")
|
||||
else:
|
||||
fieldname = field.name
|
||||
fieldtype = prep.annotations[fieldname]
|
||||
anntype = prep.annotations[fieldname]
|
||||
anntype, _iometa = _parse_annotated(anntype)
|
||||
|
||||
subfieldpath = (f'{fieldpath}.{fieldname}'
|
||||
if fieldpath else fieldname)
|
||||
args[key] = self._value_from_input(cls, subfieldpath,
|
||||
fieldtype, value)
|
||||
args[key] = self._value_from_input(cls, subfieldpath, anntype,
|
||||
value)
|
||||
try:
|
||||
out = cls(**args)
|
||||
except Exception as exc:
|
||||
@ -1026,3 +1107,22 @@ class _Inputter(Generic[T]):
|
||||
|
||||
assert len(out) == len(childanntypes)
|
||||
return tuple(out)
|
||||
|
||||
|
||||
def _parse_annotated(anntype: Any) -> Tuple[Any, Optional[IOMeta]]:
|
||||
"""Parse Annotated() constructs, returning annotated type & IOMeta data."""
|
||||
# If we get an Annotated[foo, bar, eep] we take
|
||||
# foo as the actual type and we look for IOMeta instances in
|
||||
# bar/eep to affect our behavior.
|
||||
iometa: Optional[IOMeta] = None
|
||||
if isinstance(anntype, _AnnotatedAlias):
|
||||
annargs = get_args(anntype)
|
||||
for annarg in annargs[1:]:
|
||||
if isinstance(annarg, IOMeta):
|
||||
if iometa is not None:
|
||||
raise RuntimeError(
|
||||
'Multiple IOMeta instances found for a'
|
||||
' single annotation; this is not supported.')
|
||||
iometa = annarg
|
||||
anntype = annargs[0]
|
||||
return anntype, iometa
|
||||
|
||||
@ -48,9 +48,8 @@ class EntityMixin:
|
||||
Note that it is more efficient to pass data to an Entity's constructor
|
||||
than it is to create a default Entity and then call this on it.
|
||||
"""
|
||||
self.d_data = data
|
||||
assert isinstance(self, CompoundValue)
|
||||
self.apply_fields_to_data(self.d_data, error=error)
|
||||
self.d_data = self.filter_input(data, error=error)
|
||||
|
||||
def copy_data(self, target: Union[CompoundValue,
|
||||
BoundCompoundValue]) -> None:
|
||||
|
||||
@ -66,7 +66,7 @@ class SimpleValue(TypedValue[T]):
|
||||
self._allow_none = allow_none
|
||||
|
||||
# We store _default_data in our internal data format so need
|
||||
# to run user-facing value through our input filter.
|
||||
# to run user-facing values through our input filter.
|
||||
# Make sure we do this last since filter_input depends on above vals.
|
||||
self._default_data: T = self.filter_input(default, error=True)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user