Merge branch 'main' into macos-is-mean-yet-again
|
@ -15,7 +15,7 @@ runs:
|
|||
mkdir build-debug-info-preprocessed
|
||||
cd build
|
||||
sed 's/\\\\/\//g' compile_commands.json | sed 's/D:\//\/d\//' > uni_compile_commands.json
|
||||
pip install compile-commands
|
||||
pip install compile-commands --break-system-packages
|
||||
compile-commands --file=uni_compile_commands.json --filter_files='.*info\.rc.*' --filter='(.*) -o (.*)((?:/|\\).*)\.(?:obj|o) -c (.*)' --replacement="$BASH"' --noprofile --norc -c "mkdir -p ../build-debug-info-preprocessed/\g<2> && \g<1> -o ../build-debug-info-preprocessed/\g<2>\g<3>.i -E \g<4>"' -o ../build-debug-info/preprocess_commands.json --run --verbose
|
||||
|
||||
- name: Upload Build Debug Info
|
||||
|
|
10
.github/workflows/build.yml
vendored
|
@ -104,7 +104,7 @@ jobs:
|
|||
run: ${{ env.base-configure-command }} -DCMAKE_TOOLCHAIN_FILE=$TOOLCHAIN ${{ steps.build-debug-info.outputs.extra-configure }}
|
||||
env:
|
||||
SPLAT_DIR: ${{ github.workspace }}/.xwin-cache/splat
|
||||
TOOLCHAIN: ${{ github.workspace }}/toolchain/clang-cl-msvc.cmake
|
||||
TOOLCHAIN: ${{ github.workspace }}/toolchain/clang-msvc.cmake
|
||||
HOST_ARCH: x86_64
|
||||
|
||||
- name: Build
|
||||
|
@ -139,6 +139,9 @@ jobs:
|
|||
name: Build macOS
|
||||
runs-on: macos-latest
|
||||
|
||||
env:
|
||||
SCCACHE_CACHE_MULTIARCH: 1
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
@ -259,9 +262,8 @@ jobs:
|
|||
|
||||
- name: Fix Ubuntu libcstd++
|
||||
run: |
|
||||
sudo apt install ninja-build &&
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test &&
|
||||
sudo apt-get update &&
|
||||
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
|
||||
sudo apt-get update
|
||||
sudo apt-get install --only-upgrade libstdc++6
|
||||
|
||||
- name: Configure
|
||||
|
|
19
CHANGELOG.md
|
@ -1,5 +1,24 @@
|
|||
# Geode Changelog
|
||||
|
||||
## v3.2.0
|
||||
* Fix auto-updater on MacOS (d752bc2)
|
||||
* Use tasks for `FileSettingNode` (f94e95e)
|
||||
* Fix single argument overload of `Task` (6fe1ac9)
|
||||
* Fix the GLFW message box fix (09c188a)
|
||||
* Shrink `TextInput` input to give some padding (1da73cf)
|
||||
* Undither account and editor blank sprites, add missing editor blank sprites (427e86e, efc4a00, 9fd9a78)
|
||||
* Fix populating web headers and add some new getters (a96ec91)
|
||||
* Build mods to load stack statically (255066a)
|
||||
* Force internal mod to always appear enabled (e659b97)
|
||||
* Bring back uninstall Geode button on Windows (22b2580)
|
||||
* Add `geode::openChangelogPopup` (e432e72)
|
||||
* Add special visuals for paid tag (0082765)
|
||||
* Add 64-bit check to the Windows installer (c45d8f6)
|
||||
* Add `Mod::checkUpdates` (9d02155)
|
||||
* Error on attempting to hook missing or inlined functions (2dc989f)
|
||||
* Implement function bound checking on Windows crashlog for symbol resolution (66c2f9a)
|
||||
* Add new syntax for image scale arguments (#983)
|
||||
|
||||
## v3.1.1
|
||||
* Update Windows installer translations (ae589d2, dca28db, d12fb37, 08d8af3, f52cf02, 3fa1d9b)
|
||||
* Add safe mode by holding shift on MacOS (e4905a0)
|
||||
|
|
2
VERSION
|
@ -1 +1 @@
|
|||
3.1.1
|
||||
3.2.0
|
|
@ -8,6 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Tento průvodce vás provede odi
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nV této cestě se nenachází Geometry Dash!"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nVaše verze Geometry Dash je moc stará pro tuto verzi Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "V této cestě jsou již nainstalovány jiné mody!$\r$\nGeode bude nainstalován místo nich. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
|
|
@ -18,6 +18,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Setup will guide you through the
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nThis path does not have Geometry Dash installed!"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "This path has other mods installed!$\r$\nThey will be overwritten by Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
|
|
@ -8,8 +8,8 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Saat tarvittavia ohjeita sitä m
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nValitussa kansiossa ei ole Geometry Dash -peliä asennettuna."
|
||||
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "Valitussa kansiossa on jo Mega Hack v6/v7 asennettuna.$\r$\nGeode ei ole yhteensopiva MHv6/v7 kanssa (MHv8 on ensimmäinen yhteensopiva versio Geoden kanssa).$\r$\nPoistathan Mega Hackin ennen Geoden asentamista."
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Valitussa kansiossa on jo joitain modeja asennettuna.$\r$\nGeode ei ole yhteensopiva .DLL-muotoisten modien tai niiden lataajien kanssa.$\r$\nPoistathan .DLL-muotoiset modit ja niiden lataajat ennen Geoden asentamista. (the dll trademark)"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nGeometry Dash -pelisi on vanhentunut, eikä ole yhteensopiva tämän Geode-version kanssa!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Valitussa kansiossa on muita modeja asennettuna!$\r$\nGeode tulee poistamaan ne. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Le programme d'installation vous
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nGeometry Dash n'est pas installé sur ce chemin !"
|
||||
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "Ce chemin a déjà Mega Hack v6/v7 installé !$\r$\nGeode ne fonctionne pas avec MHv6/v7 (MHv8 sera compatible avec Geode).$\r$\nVeuillez le désinstaller avant de continuer."
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Ce chemin contient déjà un autre chargeur de mod installé !$\r$\nGeode ne fonctionne avec aucun autre chargeur de mod.$\r$\nVeuillez le désinstaller avant de continuer. (the dll trademark)"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "This path has other mods installed!$\r$\nThey will be overwritten by Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Το setup θα σας καθο
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nΑυτό το path δεν έχει το Geometry Dash εγκατεστημένο!"
|
||||
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "Αυτό το path έχει ήδη το Mega Hack v6/v7 εγκατεστημένο!$\r$\nΤο Geode δεν λειτουργεί με το MHv6/v7 (MHv8 θα είναι συμβατό με το Geode).$\r$\nΠαρακαλώ, απεγκαταστήστε το πριν προχωρήσετε."
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Αυτό το path έχει ήδη ένα mod loader εγκατεστημένο!$\r$\nΤο Geode δεν λειτουργεί με οποιοδήποτε άλλο mod loader.$\r$\nΠαρακαλώ, απεγκαταστήστε το πριν προχωρήσετε. (the dll trademark)"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "This path has other mods installed!$\r$\nThey will be overwritten by Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "このセットアップは$(^Na
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nこのパスにはGeometry Dashがインストールされていません!"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "このパスには他のモッドがインストールされています!$\r$\nそれらはGeodeによって上書きされます。(the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
|
|
@ -1,12 +1,6 @@
|
|||
!insertmacro LANGFILE_EXT Korean
|
||||
|
||||
!pragma warning disable 6030 ; overwriting default MUI strings on purpose
|
||||
; to translate these strings:
|
||||
; 1. copy them from C:\Program Files (x86)\NSIS\Contrib\Language Files\*.nsh
|
||||
; 2. copy the second line from uninstall text to install text and make it say "installation" instead of "uninstallation"
|
||||
; 3. replace $(^NameDA) in second line with Geometry Dash
|
||||
; 4. do not translate "(the dll trademark)", since that is replaced with the actual dll text
|
||||
|
||||
!pragma warning disable 6030
|
||||
${LangFileString} MUI_TEXT_WELCOME_INFO_TEXT "이 프로그램은 $(^NameDA)의 설치를 진행해줄 것입니다.$\r$\n$\r$\n설치를 시작하기 전에, Geometry Dash가 켜져있지 않은지 확인해주세요.$\r$\n$\r$\n$_CLICK"
|
||||
${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "이 프로그램은 $(^NameDA)의 삭제를 진행해줄 것입니다.$\r$\n$\r$\n삭제를 시작하기 전에, Geometry Dash가 켜져있지 않은지 확인해주세요.$\r$\n$\r$\n$_CLICK"
|
||||
!pragma warning default 6030
|
||||
|
@ -14,6 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "이 프로그램은 $(^NameDA)
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\n이 경로에는 Geometry Dash가 설치되어 있지 않습니다."
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "이 경로에는 다른 모드가 설치되어 있습니다!$\r$\nGeode에 의해 덮어쓰게 될 것입니다. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
|
|
@ -8,6 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Instalator przeprowadzi Cię prz
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nGeometry Dash nie jest zainstalowane w tym folderze!"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "W tym folderze zainstalowane są inne modyfikacje!$\r$\nZostaną one zastąpione przez Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
|
|
@ -8,6 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "O instalador guiará você atrav
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nEsse caminho não tem Geometry Dash instalado!"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nSua versão do Geometry Dash é muito antiga para essa versão do Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Esse caminho já tem outros mods instalados!$\r$\nEles serão substituídos pelo Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
|
|
@ -8,6 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Эта программа уда
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nПо этому пути не установлен Geometry Dash!"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nВаша версия Geometry Dash слишком старая для этой версии Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "По этому пути уже установлены другие моды!$\r$\nОни будут перезаписаны Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
|
|
@ -8,8 +8,8 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Setup会帮您卸载$(^NameDA)
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nGeometry Dash不在这文件夹,请再试一遍!"
|
||||
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "这文件夹已经安装了Mega Hack v6/v7!$\r$\nGeode不能跟MHv6/v7一起用(可是MHv8可以)。$\r$\n请先卸载MHv6/v7。"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "这文件夹已经安装了不同的游戏修改器加载器!$\r$\nGeode不能和不同的游戏修改器加载器一起用。$\r$\n请先卸载那个游戏修改器加载器。 (the dll trademark)"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "This path has other mods installed!$\r$\nThey will be overwritten by Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Este asistente te guiará durant
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\n¡Geometry Dash no está instalado en esta ruta!"
|
||||
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "¡Mega Hack v6/v7 está instalado en esta ruta!$\r$\nGeode no es compatible con MHv6/v7 (MHv8 será compatible con Geode).$\r$\nPor favor, desinstálalo antes de continuar."
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "¡Hay otro cargador de mods instalado en esta ruta!$\r$\nGeode no funciona con ningún otro cargador de mods.$\r$\nPor favor, desinstálalo antes de continuar. (the dll trademark)"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nTu versión de Geometry Dash es muy vieja para esta versión de Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Esta ruta ya tiene otros mods instalados!$\r$\nEstos serán sobreescritos por Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Este asistente le guiará durant
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\n¡Geometry Dash no está instalado en esta ruta!"
|
||||
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "¡Mega Hack v6/v7 está instalado en esta ruta!$\r$\nGeode no es compatible con MHv6/v7 (MHv8 será compatible con Geode).$\r$\nPor favor, desinstálelo antes de continuar."
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "¡Hay otro mod loader instalado en esta ruta!$\r$\nGeode no funciona con ningún otro mod loader.$\r$\nPor favor, desinstálelo antes de continuar. (the dll trademark)"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "This path has other mods installed!$\r$\nThey will be overwritten by Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Denna guide tar dig igenom avins
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nDen valda mappen innehåller ingen installation av Geometry Dash."
|
||||
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "Den valda mappen innehåller redan Mega Hack v6/v7.$\r$\nGeode är inte kompatibel med MHv6/v7 (MHv8 är den första versionen som är kompatibel med Geode).$\r$\nSe till att avinstallera Mega Hack innan du startar installationen av Geode."
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Den valda mappen innehåller redan några andra mod.$\r$\nGeode är inte kompatibel med .DLL-slag mod eller sin mod loader.$\r$\nSe till att avinstallera .DLL-slag mod och sin mod loader innan du startar installationen av Geode. (the dll trademark)"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nDin version av Geometry Dash är för gammal för denna versionen av Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Den valda versionen av Geometry Dash har andra mod redan installerad!$\r$\nDom ska skrivs över av Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Setup會幫您卸載$(^NameDA)
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nGeometry Dash不在這文件夾,請再試一遍!"
|
||||
${LangFileString} GEODE_TEXT_MH_ALREADY_INSTALLED "這文件夾已經安裝了Mega Hack v6/v7!$\r$\nGeode不能跟MHv6/v7一起用(可是MHv8可以跟Geode一起用)。$\r$\n請先卸載MHv6/v7。"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "這文件夾已經安裝了不同的遊戲修改器加載器!$\r$\nGeode不能跟不同的遊戲修改器加載器一起用。$\r$\n請先卸載那個遊戲修改器加載器。 (the dll trademark)"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nYour version of Geometry Dash is too old for this version of Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "This path has other mods installed!$\r$\nThey will be overwritten by Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Bu sihirbaz size $(^NameDA) prog
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nBu dizin yolunda Geometry Dash yüklü değildir!"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nGeometry Dash versiyonunuz bu Geode versiyonu için çok eskidir!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Bu dizin yolunda başka modlar yüklüdür!$\r$\nGeode bunların üzerine yazılacaktır. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
|
|
@ -8,6 +8,7 @@ ${LangFileString} MUI_UNTEXT_WELCOME_INFO_TEXT "Ця програма допом
|
|||
; installer
|
||||
|
||||
${LangFileString} GEODE_TEXT_GD_MISSING "$\r$\n$\r$\nУ цій теці не встановлено Geometry Dash!"
|
||||
${LangFileString} GEODE_TEXT_GD_OLD "$\r$\n$\r$\nВаша версія Geometry Dash занадто стара для цієї версії Geode!"
|
||||
${LangFileString} GEODE_TEXT_MOD_LOADER_ALREADY_INSTALLED "Ця тека вже містить інші моди!$\r$\nВони будуть замінені Geode. (the dll trademark)"
|
||||
|
||||
; uninstaller
|
||||
|
|
|
@ -407,6 +407,11 @@ Function .onVerifyInstDir
|
|||
IfFileExists $INSTDIR\*.exe 0 noGameNoLife
|
||||
IfFileExists $INSTDIR\libcocos2d.dll 0 noGameNoLife
|
||||
|
||||
; check if we're on 64-bit gd (checks for some of the DLLs introduced in 2.206)
|
||||
IfFileExists $INSTDIR\libpng16.dll 0 versionIssueImo
|
||||
IfFileExists $INSTDIR\pthreadVC3.dll 0 versionIssueImo
|
||||
IfFileExists $INSTDIR\libcrypto-3-x64.dll 0 versionIssueImo
|
||||
|
||||
; check if geode is already installed
|
||||
IfFileExists $INSTDIR\Geode.dll valid
|
||||
|
||||
|
@ -423,6 +428,9 @@ Function .onVerifyInstDir
|
|||
noGameNoLife:
|
||||
SendMessage $geode.DirectoryPage.ErrorText ${WM_SETTEXT} "" "STR:$(GEODE_TEXT_GD_MISSING)"
|
||||
Goto error
|
||||
versionIssueImo:
|
||||
SendMessage $geode.DirectoryPage.ErrorText ${WM_SETTEXT} "" "STR:$(GEODE_TEXT_GD_OLD)"
|
||||
Goto error
|
||||
other_hackpro:
|
||||
StrCpy $0 "hackpro.dll"
|
||||
Goto other
|
||||
|
|
|
@ -246,9 +246,10 @@ if (NOT GEODE_BUILDING_DOCS)
|
|||
set(MZ_BZIP2 OFF CACHE INTERNAL "")
|
||||
set(MZ_OPENSSL OFF CACHE INTERNAL "")
|
||||
set(MZ_LIBBSD OFF CACHE INTERNAL "")
|
||||
set(MZ_FETCH_LIBS ON CACHE INTERNAL "")
|
||||
set(MZ_FETCH_LIBS ON CACHE INTERNAL "" FORCE)
|
||||
set(MZ_FORCE_FETCH_LIBS ${WIN32} CACHE INTERNAL "")
|
||||
set(SKIP_INSTALL_ALL ON CACHE INTERNAL "")
|
||||
CPMAddPackage("gh:geode-sdk/minizip-ng#011a133")
|
||||
CPMAddPackage("gh:geode-sdk/minizip-ng#7548419")
|
||||
if (WIN32)
|
||||
set_target_properties(zlib PROPERTIES SUFFIX "1.dll")
|
||||
endif()
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
|
||||
#if defined(GEODE_IS_ANDROID)
|
||||
#include "gnustl.hpp"
|
||||
//#elif defined(GEODE_IS_WINDOWS)
|
||||
//#include "msvcstl.hpp"
|
||||
#else
|
||||
#include "aliastl.hpp"
|
||||
#endif
|
||||
|
|
|
@ -1,35 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <Geode/platform/platform.hpp>
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace geode::stl {
|
||||
|
||||
GEODE_DLL void* operatorNew(std::size_t size);
|
||||
GEODE_DLL void operatorDelete(void* ptr);
|
||||
|
||||
template <class T>
|
||||
struct allocator {
|
||||
using value_type = T;
|
||||
using size_type = std::size_t;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
using propagate_on_container_move_assignment = std::true_type;
|
||||
|
||||
constexpr allocator() noexcept {}
|
||||
constexpr allocator(const allocator& other) noexcept {}
|
||||
|
||||
template<class U>
|
||||
constexpr allocator(const allocator<U>& other) noexcept {}
|
||||
|
||||
constexpr ~allocator() {}
|
||||
|
||||
[[nodiscard]] T* allocate(std::size_t n) {
|
||||
return reinterpret_cast<T*>(operatorNew(n * sizeof(T)));
|
||||
}
|
||||
|
||||
void deallocate(T* p, std::size_t n) {
|
||||
operatorDelete(reinterpret_cast<void*>(p));
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,563 +0,0 @@
|
|||
// unordered_map standard header
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Per Apache License, Version 2.0, Section 4, Point b: I (kynex7510) changed this file.
|
||||
|
||||
#ifndef _GEODE_UNORDERED_MAP_
|
||||
#define _GEODE_UNORDERED_MAP_
|
||||
#include <yvals_core.h>
|
||||
#if _STL_COMPILER_PREPROCESSOR
|
||||
#include "xhash.hpp"
|
||||
|
||||
#if _HAS_CXX17
|
||||
#include <xpolymorphic_allocator.h>
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
#pragma pack(push, _CRT_PACKING)
|
||||
#pragma warning(push, _STL_WARNING_LEVEL)
|
||||
#pragma warning(disable : _STL_DISABLED_WARNINGS)
|
||||
_STL_DISABLE_CLANG_WARNINGS
|
||||
#pragma push_macro("new")
|
||||
#undef new
|
||||
|
||||
namespace geode::stl {
|
||||
|
||||
template <class _Kty, // key type
|
||||
class _Ty, // mapped type
|
||||
class _Tr, // comparator predicate type
|
||||
class _Alloc, // actual _STD allocator type (should be value _STD allocator)
|
||||
bool _Mfl> // true if multiple equivalent keys are permitted
|
||||
class _Umap_traits : public _Tr { // traits required to make _Hash behave like a map
|
||||
public:
|
||||
using key_type = _Kty;
|
||||
using value_type = _STD pair<const _Kty, _Ty>;
|
||||
using _Mutable_value_type = _STD pair<_Kty, _Ty>;
|
||||
using key_compare = _Tr;
|
||||
using allocator_type = _Alloc;
|
||||
#if _HAS_CXX17
|
||||
using node_type = _STD _Node_handle<_STD _List_node<value_type, typename _STD allocator_traits<_Alloc>::void_pointer>, _Alloc,
|
||||
_STD _Node_handle_map_base, _Kty, _Ty>;
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
static constexpr bool _Multi = _Mfl;
|
||||
static constexpr bool _Standard = true;
|
||||
|
||||
template <class... _Args>
|
||||
using _In_place_key_extractor = _STD _In_place_key_extract_map<_Kty, _Args...>;
|
||||
|
||||
_Umap_traits() = default;
|
||||
|
||||
explicit _Umap_traits(const _Tr& _Traits) noexcept(_STD is_nothrow_copy_constructible_v<_Tr>) : _Tr(_Traits) {}
|
||||
|
||||
using value_compare = void; // TRANSITION, remove when _Standard becomes unconditionally true
|
||||
|
||||
template <class _Ty1, class _Ty2>
|
||||
static const _Kty& _Kfn(const _STD pair<_Ty1, _Ty2>& _Val) noexcept { // extract key from element value
|
||||
return _Val.first;
|
||||
}
|
||||
|
||||
template <class _Ty1, class _Ty2>
|
||||
static const _Ty2& _Nonkfn(const _STD pair<_Ty1, _Ty2>& _Val) noexcept { // extract non-key from element value
|
||||
return _Val.second;
|
||||
}
|
||||
};
|
||||
|
||||
/*_EXPORT_STD*/ template <class _Kty, class _Ty, class _Hasher = _STD hash<_Kty>, class _Keyeq = _STD equal_to<_Kty>,
|
||||
class _Alloc = _STD allocator<_STD pair<const _Kty, _Ty>>>
|
||||
class unordered_map : public _Hash<_Umap_traits<_Kty, _Ty, _STD _Uhash_compare<_Kty, _Hasher, _Keyeq>, _Alloc, false>> {
|
||||
// hash table of {key, mapped} values, unique keys
|
||||
public:
|
||||
static_assert(!_ENFORCE_MATCHING_ALLOCATORS || _STD is_same_v<_STD pair<const _Kty, _Ty>, typename _Alloc::value_type>,
|
||||
_MISMATCHED_ALLOCATOR_MESSAGE("unordered_map<Key, Value, Hasher, Eq, Allocator>", "_STD pair<const Key, Value>"));
|
||||
static_assert(_STD is_object_v<_Kty>, "The C++ Standard forbids containers of non-object types "
|
||||
"because of [container.requirements].");
|
||||
|
||||
private:
|
||||
using _Mytraits = _STD _Uhash_compare<_Kty, _Hasher, _Keyeq>;
|
||||
using _Mybase = _Hash<_Umap_traits<_Kty, _Ty, _Mytraits, _Alloc, false>>;
|
||||
using _Alnode = typename _Mybase::_Alnode;
|
||||
using _Alnode_traits = typename _Mybase::_Alnode_traits;
|
||||
using _Nodeptr = typename _Mybase::_Nodeptr;
|
||||
using _Key_compare = typename _Mybase::_Key_compare;
|
||||
|
||||
public:
|
||||
using hasher = _Hasher;
|
||||
using key_type = _Kty;
|
||||
using mapped_type = _Ty;
|
||||
using key_equal = _Keyeq;
|
||||
|
||||
using value_type = _STD pair<const _Kty, _Ty>;
|
||||
using allocator_type = typename _Mybase::allocator_type;
|
||||
using size_type = typename _Mybase::size_type;
|
||||
using difference_type = typename _Mybase::difference_type;
|
||||
using pointer = typename _Mybase::pointer;
|
||||
using const_pointer = typename _Mybase::const_pointer;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using iterator = typename _Mybase::iterator;
|
||||
using const_iterator = typename _Mybase::const_iterator;
|
||||
|
||||
using local_iterator = typename _Mybase::iterator;
|
||||
using const_local_iterator = typename _Mybase::const_iterator;
|
||||
|
||||
#if _HAS_CXX17
|
||||
using insert_return_type = _STD _Insert_return_type<iterator, typename _Mybase::node_type>;
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
unordered_map() : _Mybase(_Key_compare(), allocator_type()) {}
|
||||
|
||||
explicit unordered_map(const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {}
|
||||
|
||||
unordered_map(const unordered_map& _Right)
|
||||
: _Mybase(_Right, _Alnode_traits::select_on_container_copy_construction(_Right._Getal())) {}
|
||||
|
||||
unordered_map(const unordered_map& _Right, const allocator_type& _Al) : _Mybase(_Right, _Al) {}
|
||||
|
||||
explicit unordered_map(size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
}
|
||||
|
||||
unordered_map(size_type _Buckets, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
}
|
||||
|
||||
unordered_map(size_type _Buckets, const hasher& _Hasharg) : _Mybase(_Key_compare(_Hasharg), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
}
|
||||
|
||||
unordered_map(size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
}
|
||||
|
||||
unordered_map(size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
}
|
||||
|
||||
unordered_map(size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_map(_Iter _First, _Iter _Last) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_map(_Iter _First, _Iter _Last, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
|
||||
insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_map(_Iter _First, _Iter _Last, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_map(_Iter _First, _Iter _Last, size_type _Buckets, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_map(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg)
|
||||
: _Mybase(_Key_compare(_Hasharg), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_map(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_map(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_map(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg,
|
||||
const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_First, _Last);
|
||||
}
|
||||
|
||||
#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_map(_STD from_range_t, _Rng&& _Range) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_map(_STD from_range_t, _Rng&& _Range, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_map(_STD from_range_t, _Rng&& _Range, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_map(_STD from_range_t, _Rng&& _Range, size_type _Buckets, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_map(_STD from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg)
|
||||
: _Mybase(_Key_compare(_Hasharg), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_map(_STD from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_map(_STD from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_map(_STD from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg,
|
||||
const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
|
||||
|
||||
unordered_map& operator=(const unordered_map& _Right) {
|
||||
_Mybase::operator=(_Right);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unordered_map(unordered_map&& _Right) : _Mybase(_STD move(_Right)) {}
|
||||
|
||||
unordered_map(unordered_map&& _Right, const allocator_type& _Al) : _Mybase(_STD move(_Right), _Al) {}
|
||||
|
||||
unordered_map& operator=(unordered_map&& _Right) noexcept(_Alnode_traits::is_always_equal::value&&
|
||||
_STD is_nothrow_move_assignable_v<_Hasher>&& _STD is_nothrow_move_assignable_v<_Keyeq>) {
|
||||
_Mybase::operator=(_STD move(_Right));
|
||||
return *this;
|
||||
}
|
||||
|
||||
mapped_type& operator[](key_type&& _Keyval) {
|
||||
return this->_Try_emplace(_STD move(_Keyval)).first->_Myval.second;
|
||||
}
|
||||
|
||||
void swap(unordered_map& _Right) noexcept(noexcept(_Mybase::swap(_Right))) {
|
||||
_Mybase::swap(_Right);
|
||||
}
|
||||
|
||||
using _Mybase::insert;
|
||||
|
||||
template <class _Valty, _STD enable_if_t<_STD is_constructible_v<value_type, _Valty>, int> = 0>
|
||||
_STD pair<iterator, bool> insert(_Valty&& _Val) {
|
||||
return this->emplace(_STD forward<_Valty>(_Val));
|
||||
}
|
||||
|
||||
template <class _Valty, _STD enable_if_t<_STD is_constructible_v<value_type, _Valty>, int> = 0>
|
||||
iterator insert(const_iterator _Where, _Valty&& _Val) {
|
||||
return this->emplace_hint(_Where, _STD forward<_Valty>(_Val));
|
||||
}
|
||||
|
||||
template <class... _Mappedty>
|
||||
_STD pair<iterator, bool> try_emplace(const key_type& _Keyval, _Mappedty&&... _Mapval) {
|
||||
const auto _Result = this->_Try_emplace(_Keyval, _STD forward<_Mappedty>(_Mapval)...);
|
||||
return {this->_List._Make_iter(_Result.first), _Result.second};
|
||||
}
|
||||
|
||||
template <class... _Mappedty>
|
||||
_STD pair<iterator, bool> try_emplace(key_type&& _Keyval, _Mappedty&&... _Mapval) {
|
||||
const auto _Result = this->_Try_emplace(_STD move(_Keyval), _STD forward<_Mappedty>(_Mapval)...);
|
||||
return {this->_List._Make_iter(_Result.first), _Result.second};
|
||||
}
|
||||
|
||||
template <class... _Mappedty>
|
||||
iterator try_emplace(const const_iterator _Hint, const key_type& _Keyval, _Mappedty&&... _Mapval) {
|
||||
return this->_List._Make_iter(
|
||||
this->_Try_emplace_hint(_Hint._Ptr, _Keyval, _STD forward<_Mappedty>(_Mapval)...));
|
||||
}
|
||||
|
||||
template <class... _Mappedty>
|
||||
iterator try_emplace(const const_iterator _Hint, key_type&& _Keyval, _Mappedty&&... _Mapval) {
|
||||
return this->_List._Make_iter(
|
||||
this->_Try_emplace_hint(_Hint._Ptr, _STD move(_Keyval), _STD forward<_Mappedty>(_Mapval)...));
|
||||
}
|
||||
|
||||
private:
|
||||
template <class _Keyty, class _Mappedty>
|
||||
_STD pair<iterator, bool> _Insert_or_assign(_Keyty&& _Keyval_arg, _Mappedty&& _Mapval) {
|
||||
const auto& _Keyval = _Keyval_arg;
|
||||
const size_t _Hashval = this->_Traitsobj(_Keyval);
|
||||
auto _Target = this->_Find_last(_Keyval, _Hashval);
|
||||
if (_Target._Duplicate) {
|
||||
_Target._Duplicate->_Myval.second = _STD forward<_Mappedty>(_Mapval);
|
||||
return {this->_List._Make_iter(_Target._Duplicate), false};
|
||||
}
|
||||
|
||||
this->_Check_max_size();
|
||||
// invalidates _Keyval:
|
||||
_STD _List_node_emplace_op2<_Alnode> _Newnode(
|
||||
this->_Getal(), _STD forward<_Keyty>(_Keyval_arg), _STD forward<_Mappedty>(_Mapval));
|
||||
if (this->_Check_rehash_required_1()) {
|
||||
this->_Rehash_for_1();
|
||||
_Target = this->_Find_last(_Newnode._Ptr->_Myval.first, _Hashval);
|
||||
}
|
||||
|
||||
return {this->_List._Make_iter(
|
||||
this->_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release())),
|
||||
true};
|
||||
}
|
||||
|
||||
template <class _Keyty, class _Mappedty>
|
||||
iterator _Insert_or_assign(const _Nodeptr _Hint, _Keyty&& _Keyval_arg, _Mappedty&& _Mapval) {
|
||||
const auto& _Keyval = _Keyval_arg;
|
||||
const size_t _Hashval = this->_Traitsobj(_Keyval);
|
||||
auto _Target = this->_Find_hint(_Hint, _Keyval, _Hashval);
|
||||
if (_Target._Duplicate) {
|
||||
_Target._Duplicate->_Myval.second = _STD forward<_Mappedty>(_Mapval);
|
||||
return this->_List._Make_iter(_Target._Duplicate);
|
||||
}
|
||||
|
||||
this->_Check_max_size();
|
||||
// invalidates _Keyval:
|
||||
_STD _List_node_emplace_op2<_Alnode> _Newnode(
|
||||
this->_Getal(), _STD forward<_Keyty>(_Keyval_arg), _STD forward<_Mappedty>(_Mapval));
|
||||
if (this->_Check_rehash_required_1()) {
|
||||
this->_Rehash_for_1();
|
||||
_Target = this->_Find_hint(_Hint, _Newnode._Ptr->_Myval.first, _Hashval);
|
||||
}
|
||||
|
||||
return this->_List._Make_iter(
|
||||
this->_Insert_new_node_before(_Hashval, _Target._Insert_before, _Newnode._Release()));
|
||||
}
|
||||
|
||||
public:
|
||||
template <class _Mappedty>
|
||||
_STD pair<iterator, bool> insert_or_assign(const key_type& _Keyval, _Mappedty&& _Mapval) {
|
||||
return _Insert_or_assign(_Keyval, _STD forward<_Mappedty>(_Mapval));
|
||||
}
|
||||
|
||||
template <class _Mappedty>
|
||||
_STD pair<iterator, bool> insert_or_assign(key_type&& _Keyval, _Mappedty&& _Mapval) {
|
||||
return _Insert_or_assign(_STD move(_Keyval), _STD forward<_Mappedty>(_Mapval));
|
||||
}
|
||||
|
||||
template <class _Mappedty>
|
||||
iterator insert_or_assign(const_iterator _Hint, const key_type& _Keyval, _Mappedty&& _Mapval) {
|
||||
return _Insert_or_assign(_Hint._Ptr, _Keyval, _STD forward<_Mappedty>(_Mapval));
|
||||
}
|
||||
|
||||
template <class _Mappedty>
|
||||
iterator insert_or_assign(const_iterator _Hint, key_type&& _Keyval, _Mappedty&& _Mapval) {
|
||||
return _Insert_or_assign(_Hint._Ptr, _STD move(_Keyval), _STD forward<_Mappedty>(_Mapval));
|
||||
}
|
||||
|
||||
unordered_map(_STD initializer_list<value_type> _Ilist) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_map(_STD initializer_list<value_type> _Ilist, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
|
||||
insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_map(_STD initializer_list<value_type> _Ilist, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_map(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_map(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg)
|
||||
: _Mybase(_Key_compare(_Hasharg), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_map(
|
||||
_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_map(
|
||||
_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_map(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg,
|
||||
const _Keyeq& _Keyeqarg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_map& operator=(_STD initializer_list<value_type> _Ilist) {
|
||||
_Mybase::clear();
|
||||
insert(_Ilist);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_NODISCARD hasher hash_function() const {
|
||||
return _Mybase::_Traitsobj._Mypair._Get_first();
|
||||
}
|
||||
|
||||
_NODISCARD key_equal key_eq() const {
|
||||
return _Mybase::_Traitsobj._Mypair._Myval2._Get_first();
|
||||
}
|
||||
|
||||
mapped_type& operator[](const key_type& _Keyval) {
|
||||
return this->_Try_emplace(_Keyval).first->_Myval.second;
|
||||
}
|
||||
|
||||
_NODISCARD mapped_type& at(const key_type& _Keyval) {
|
||||
const auto _Target = this->_Find_last(_Keyval, this->_Traitsobj(_Keyval));
|
||||
if (_Target._Duplicate) {
|
||||
return _Target._Duplicate->_Myval.second;
|
||||
}
|
||||
|
||||
_STD _Xout_of_range("invalid unordered_map<K, T> key");
|
||||
}
|
||||
|
||||
_NODISCARD const mapped_type& at(const key_type& _Keyval) const {
|
||||
const auto _Target = this->_Find_last(_Keyval, this->_Traitsobj(_Keyval));
|
||||
if (_Target._Duplicate) {
|
||||
return _Target._Duplicate->_Myval.second;
|
||||
}
|
||||
|
||||
_STD _Xout_of_range("invalid unordered_map<K, T> key");
|
||||
}
|
||||
|
||||
using _Mybase::_Unchecked_begin;
|
||||
using _Mybase::_Unchecked_end;
|
||||
};
|
||||
|
||||
#if _HAS_CXX17
|
||||
template <class _Iter, class _Hasher = _STD hash<_STD _Guide_key_t<_Iter>>, class _Keyeq = _STD equal_to<_STD _Guide_key_t<_Iter>>,
|
||||
class _Alloc = _STD allocator<_STD _Guide_pair_t<_Iter>>,
|
||||
_STD enable_if_t<
|
||||
_STD conjunction_v<_STD _Is_iterator<_Iter>, _Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>,
|
||||
int> = 0>
|
||||
unordered_map(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(), _Alloc = _Alloc())
|
||||
-> unordered_map<_STD _Guide_key_t<_Iter>, _STD _Guide_val_t<_Iter>, _Hasher, _Keyeq, _Alloc>;
|
||||
|
||||
template <class _Kty, class _Ty, class _Hasher = _STD hash<_Kty>, class _Keyeq = _STD equal_to<_Kty>,
|
||||
class _Alloc = _STD allocator<_STD pair<const _Kty, _Ty>>,
|
||||
_STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_map(_STD initializer_list<_STD pair<_Kty, _Ty>>, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(),
|
||||
_Alloc = _Alloc()) -> unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>;
|
||||
|
||||
template <class _Iter, class _Alloc, _STD enable_if_t<_STD conjunction_v<_STD _Is_iterator<_Iter>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_map(_Iter, _Iter, _Alloc) -> unordered_map<_STD _Guide_key_t<_Iter>, _STD _Guide_val_t<_Iter>,
|
||||
_STD hash<_STD _Guide_key_t<_Iter>>, _STD equal_to<_STD _Guide_key_t<_Iter>>, _Alloc>;
|
||||
|
||||
template <class _Iter, class _Alloc, _STD enable_if_t<_STD conjunction_v<_STD _Is_iterator<_Iter>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_map(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc>, _Alloc) -> unordered_map<_STD _Guide_key_t<_Iter>,
|
||||
_STD _Guide_val_t<_Iter>, _STD hash<_STD _Guide_key_t<_Iter>>, _STD equal_to<_STD _Guide_key_t<_Iter>>, _Alloc>;
|
||||
|
||||
template <class _Iter, class _Hasher, class _Alloc,
|
||||
_STD enable_if_t<_STD conjunction_v<_STD _Is_iterator<_Iter>, _Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_map(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
|
||||
-> unordered_map<_STD _Guide_key_t<_Iter>, _STD _Guide_val_t<_Iter>, _Hasher, _STD equal_to<_STD _Guide_key_t<_Iter>>, _Alloc>;
|
||||
|
||||
template <class _Kty, class _Ty, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
|
||||
unordered_map(_STD initializer_list<_STD pair<_Kty, _Ty>>, _Alloc)
|
||||
-> unordered_map<_Kty, _Ty, _STD hash<_Kty>, _STD equal_to<_Kty>, _Alloc>;
|
||||
|
||||
template <class _Kty, class _Ty, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
|
||||
unordered_map(_STD initializer_list<_STD pair<_Kty, _Ty>>, _STD _Guide_size_type_t<_Alloc>, _Alloc)
|
||||
-> unordered_map<_Kty, _Ty, _STD hash<_Kty>, _STD equal_to<_Kty>, _Alloc>;
|
||||
|
||||
template <class _Kty, class _Ty, class _Hasher, class _Alloc,
|
||||
_STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_map(_STD initializer_list<_STD pair<_Kty, _Ty>>, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
|
||||
-> unordered_map<_Kty, _Ty, _Hasher, _STD equal_to<_Kty>, _Alloc>;
|
||||
|
||||
#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
|
||||
template <_RANGES input_range _Rng, class _Hasher = _STD hash<_STD _Range_key_type<_Rng>>,
|
||||
class _Keyeq = _STD equal_to<_STD _Range_key_type<_Rng>>, class _Alloc = _STD allocator<_STD _Range_to_alloc_type<_Rng>>,
|
||||
_STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_map(_STD from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(),
|
||||
_Alloc = _Alloc()) -> unordered_map<_STD _Range_key_type<_Rng>, _STD _Range_mapped_type<_Rng>, _Hasher, _Keyeq, _Alloc>;
|
||||
|
||||
template <_RANGES input_range _Rng, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
|
||||
unordered_map(_STD from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc>, _Alloc) -> unordered_map<_STD _Range_key_type<_Rng>,
|
||||
_STD _Range_mapped_type<_Rng>, _STD hash<_STD _Range_key_type<_Rng>>, _STD equal_to<_STD _Range_key_type<_Rng>>, _Alloc>;
|
||||
|
||||
template <_RANGES input_range _Rng, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
|
||||
unordered_map(_STD from_range_t, _Rng&&, _Alloc) -> unordered_map<_STD _Range_key_type<_Rng>, _STD _Range_mapped_type<_Rng>,
|
||||
_STD hash<_STD _Range_key_type<_Rng>>, _STD equal_to<_STD _Range_key_type<_Rng>>, _Alloc>;
|
||||
|
||||
template <_RANGES input_range _Rng, class _Hasher, class _Alloc,
|
||||
_STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_map(_STD from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
|
||||
-> unordered_map<_STD _Range_key_type<_Rng>, _STD _Range_mapped_type<_Rng>, _Hasher, _STD equal_to<_STD _Range_key_type<_Rng>>, _Alloc>;
|
||||
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
/*_EXPORT_STD*/ template <class _Kty, class _Ty, class _Hasher, class _Keyeq, class _Alloc>
|
||||
void swap(unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left,
|
||||
unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Right) noexcept(noexcept(_Left.swap(_Right))) {
|
||||
_Left.swap(_Right);
|
||||
}
|
||||
|
||||
#if _HAS_CXX20
|
||||
/*_EXPORT_STD*/ template <class _Kty, class _Ty, class _Hasher, class _Keyeq, class _Alloc, class _Pr>
|
||||
unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>::size_type erase_if(
|
||||
unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) {
|
||||
return _STD _Erase_nodes_if(_Cont, _STD _Pass_fn(_Pred));
|
||||
}
|
||||
#endif // _HAS_CXX20
|
||||
|
||||
/*_EXPORT_STD*/ template <class _Kty, class _Ty, class _Hasher, class _Keyeq, class _Alloc>
|
||||
_NODISCARD bool operator==(const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left,
|
||||
const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Right) {
|
||||
return ::geode::stl:: _Hash_equal(_Left, _Right);
|
||||
}
|
||||
|
||||
#if !_HAS_CXX20
|
||||
template <class _Kty, class _Ty, class _Hasher, class _Keyeq, class _Alloc>
|
||||
_NODISCARD bool operator!=(const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Left,
|
||||
const unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>& _Right) {
|
||||
return !(_Left == _Right);
|
||||
}
|
||||
#endif // !_HAS_CXX20
|
||||
|
||||
} // namespace geode::stl
|
||||
|
||||
#pragma pop_macro("new")
|
||||
_STL_RESTORE_CLANG_WARNINGS
|
||||
#pragma warning(pop)
|
||||
#pragma pack(pop)
|
||||
#endif // _STL_COMPILER_PREPROCESSOR
|
||||
#endif // _GEODE_UNORDERED_MAP_
|
|
@ -1,418 +0,0 @@
|
|||
// unordered_set standard header
|
||||
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
|
||||
// Per Apache License, Version 2.0, Section 4, Point b: I (kynex7510) changed this file.
|
||||
|
||||
#ifndef _GEODE_UNORDERED_SET_
|
||||
#define _GEODE_UNORDERED_SET_
|
||||
#include <yvals_core.h>
|
||||
#if _STL_COMPILER_PREPROCESSOR
|
||||
#include "xhash.hpp"
|
||||
|
||||
#if _HAS_CXX17
|
||||
#include <xpolymorphic_allocator.h>
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
#pragma pack(push, _CRT_PACKING)
|
||||
#pragma warning(push, _STL_WARNING_LEVEL)
|
||||
#pragma warning(disable : _STL_DISABLED_WARNINGS)
|
||||
_STL_DISABLE_CLANG_WARNINGS
|
||||
#pragma push_macro("new")
|
||||
#undef new
|
||||
|
||||
namespace geode::stl {
|
||||
|
||||
template <class _Kty, // key type (same as value type)
|
||||
class _Tr, // comparator predicate type
|
||||
class _Alloc, // actual allocator type (should be value allocator)
|
||||
bool _Mfl> // true if multiple equivalent keys are permitted
|
||||
class _Uset_traits : public _Tr { // traits required to make _Hash behave like a set
|
||||
public:
|
||||
using key_type = _Kty;
|
||||
using value_type = _Kty;
|
||||
using _Mutable_value_type = _Kty;
|
||||
using key_compare = _Tr;
|
||||
using allocator_type = _Alloc;
|
||||
#if _HAS_CXX17
|
||||
using node_type = _STD _Node_handle<_STD _List_node<value_type, typename _STD allocator_traits<_Alloc>::void_pointer>, _Alloc,
|
||||
_STD _Node_handle_set_base, _Kty>;
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
static constexpr bool _Multi = _Mfl;
|
||||
static constexpr bool _Standard = true;
|
||||
|
||||
template <class... _Args>
|
||||
using _In_place_key_extractor = _STD _In_place_key_extract_set<_Kty, _Args...>;
|
||||
|
||||
_Uset_traits() = default;
|
||||
|
||||
explicit _Uset_traits(const _Tr& _Traits) noexcept(_STD is_nothrow_copy_constructible_v<_Tr>) : _Tr(_Traits) {}
|
||||
|
||||
using value_compare = void; // TRANSITION, remove when _Standard becomes unconditionally true
|
||||
|
||||
static const _Kty& _Kfn(const value_type& _Val) noexcept {
|
||||
return _Val;
|
||||
}
|
||||
|
||||
static int _Nonkfn(const value_type&) noexcept { // extract "non-key" from element value (for container equality)
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
/* _EXPORT_STD */ template <class _Kty, class _Hasher = _STD hash<_Kty>, class _Keyeq = _STD equal_to<_Kty>,
|
||||
class _Alloc = allocator<_Kty>>
|
||||
class unordered_set : public _Hash<_Uset_traits<_Kty, _STD _Uhash_compare<_Kty, _Hasher, _Keyeq>, _Alloc, false>> {
|
||||
// hash table of key-values, unique keys
|
||||
public:
|
||||
static_assert(!_ENFORCE_MATCHING_ALLOCATORS || _STD is_same_v<_Kty, typename _Alloc::value_type>,
|
||||
_MISMATCHED_ALLOCATOR_MESSAGE("unordered_set<T, Hasher, Eq, Allocator>", "T"));
|
||||
static_assert(_STD is_object_v<_Kty>, "The C++ Standard forbids containers of non-object types "
|
||||
"because of [container.requirements].");
|
||||
|
||||
private:
|
||||
using _Mytraits = _STD _Uhash_compare<_Kty, _Hasher, _Keyeq>;
|
||||
using _Mybase = _Hash<_Uset_traits<_Kty, _Mytraits, _Alloc, false>>;
|
||||
using _Alnode = typename _Mybase::_Alnode;
|
||||
using _Alnode_traits = typename _Mybase::_Alnode_traits;
|
||||
using _Key_compare = typename _Mybase::_Key_compare;
|
||||
|
||||
public:
|
||||
using hasher = _Hasher;
|
||||
using key_type = _Kty;
|
||||
using key_equal = _Keyeq;
|
||||
|
||||
using value_type = typename _Mybase::value_type;
|
||||
using allocator_type = typename _Mybase::allocator_type;
|
||||
using size_type = typename _Mybase::size_type;
|
||||
using difference_type = typename _Mybase::difference_type;
|
||||
using pointer = typename _Mybase::pointer;
|
||||
using const_pointer = typename _Mybase::const_pointer;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using iterator = typename _Mybase::iterator;
|
||||
using const_iterator = typename _Mybase::const_iterator;
|
||||
|
||||
using local_iterator = typename _Mybase::iterator;
|
||||
using const_local_iterator = typename _Mybase::const_iterator;
|
||||
|
||||
#if _HAS_CXX17
|
||||
using insert_return_type = _STD _Insert_return_type<iterator, typename _Mybase::node_type>;
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
unordered_set() : _Mybase(_Key_compare(), allocator_type()) {}
|
||||
|
||||
explicit unordered_set(const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {}
|
||||
|
||||
unordered_set(const unordered_set& _Right)
|
||||
: _Mybase(_Right, _Alnode_traits::select_on_container_copy_construction(_Right._Getal())) {}
|
||||
|
||||
unordered_set(const unordered_set& _Right, const allocator_type& _Al) : _Mybase(_Right, _Al) {}
|
||||
|
||||
explicit unordered_set(size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
this->rehash(_Buckets);
|
||||
}
|
||||
|
||||
unordered_set(size_type _Buckets, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
|
||||
this->rehash(_Buckets);
|
||||
}
|
||||
|
||||
unordered_set(size_type _Buckets, const hasher& _Hasharg) : _Mybase(_Key_compare(_Hasharg), allocator_type()) {
|
||||
this->rehash(_Buckets);
|
||||
}
|
||||
|
||||
unordered_set(size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg), _Al) {
|
||||
this->rehash(_Buckets);
|
||||
}
|
||||
|
||||
unordered_set(size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
|
||||
this->rehash(_Buckets);
|
||||
}
|
||||
|
||||
unordered_set(size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
|
||||
this->rehash(_Buckets);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_set(_Iter _First, _Iter _Last) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
this->insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_set(_Iter _First, _Iter _Last, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
|
||||
this->insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_set(_Iter _First, _Iter _Last, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_set(_Iter _First, _Iter _Last, size_type _Buckets, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(), _Al) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_set(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg)
|
||||
: _Mybase(_Key_compare(_Hasharg), allocator_type()) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_set(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg), _Al) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_set(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_First, _Last);
|
||||
}
|
||||
|
||||
template <class _Iter>
|
||||
unordered_set(_Iter _First, _Iter _Last, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg,
|
||||
const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_First, _Last);
|
||||
}
|
||||
|
||||
#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_set(_STD from_range_t, _Rng&& _Range) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_set(_STD from_range_t, _Rng&& _Range, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_set(_STD from_range_t, _Rng&& _Range, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_set(_STD from_range_t, _Rng&& _Range, size_type _Buckets, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_set(_STD from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg)
|
||||
: _Mybase(_Key_compare(_Hasharg), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_set(_STD from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_set(_STD from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
|
||||
template <_STD _Container_compatible_range<value_type> _Rng>
|
||||
unordered_set(_STD from_range_t, _Rng&& _Range, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg,
|
||||
const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
|
||||
_Mybase::rehash(_Buckets);
|
||||
this->_Insert_range_unchecked(_RANGES _Ubegin(_Range), _RANGES _Uend(_Range));
|
||||
}
|
||||
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
|
||||
|
||||
unordered_set& operator=(const unordered_set& _Right) {
|
||||
_Mybase::operator=(_Right);
|
||||
return *this;
|
||||
}
|
||||
|
||||
unordered_set(unordered_set&& _Right) : _Mybase(_STD move(_Right)) {}
|
||||
|
||||
unordered_set(unordered_set&& _Right, const allocator_type& _Al) : _Mybase(_STD move(_Right), _Al) {}
|
||||
|
||||
unordered_set& operator=(unordered_set&& _Right) noexcept(_Alnode_traits::is_always_equal::value&&
|
||||
_STD is_nothrow_move_assignable_v<_Hasher>&& _STD is_nothrow_move_assignable_v<_Keyeq>) {
|
||||
_Mybase::operator=(_STD move(_Right));
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(unordered_set& _Right) noexcept(noexcept(_Mybase::swap(_Right))) {
|
||||
_Mybase::swap(_Right);
|
||||
}
|
||||
|
||||
unordered_set(_STD initializer_list<value_type> _Ilist) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
this->insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_set(_STD initializer_list<value_type> _Ilist, const allocator_type& _Al) : _Mybase(_Key_compare(), _Al) {
|
||||
this->insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_set(_STD initializer_list<value_type> _Ilist, size_type _Buckets) : _Mybase(_Key_compare(), allocator_type()) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_set(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(), _Al) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_set(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg)
|
||||
: _Mybase(_Key_compare(_Hasharg), allocator_type()) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_set(
|
||||
_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg), _Al) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_set(
|
||||
_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg, const _Keyeq& _Keyeqarg)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), allocator_type()) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_set(_STD initializer_list<value_type> _Ilist, size_type _Buckets, const hasher& _Hasharg,
|
||||
const _Keyeq& _Keyeqarg, const allocator_type& _Al)
|
||||
: _Mybase(_Key_compare(_Hasharg, _Keyeqarg), _Al) {
|
||||
this->rehash(_Buckets);
|
||||
this->insert(_Ilist);
|
||||
}
|
||||
|
||||
unordered_set& operator=(_STD initializer_list<value_type> _Ilist) {
|
||||
this->clear();
|
||||
this->insert(_Ilist);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_NODISCARD hasher hash_function() const {
|
||||
return this->_Traitsobj._Mypair._Get_first();
|
||||
}
|
||||
|
||||
_NODISCARD key_equal key_eq() const {
|
||||
return this->_Traitsobj._Mypair._Myval2._Get_first();
|
||||
}
|
||||
|
||||
using _Mybase::_Unchecked_begin;
|
||||
using _Mybase::_Unchecked_end;
|
||||
};
|
||||
|
||||
#if _HAS_CXX17
|
||||
template <class _Iter, class _Hasher = _STD hash<_STD _Iter_value_t<_Iter>>, class _Keyeq = _STD equal_to<_STD _Iter_value_t<_Iter>>,
|
||||
class _Alloc = allocator<_STD _Iter_value_t<_Iter>>,
|
||||
_STD enable_if_t<
|
||||
_STD conjunction_v<_STD _Is_iterator<_Iter>, _Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>,
|
||||
int> = 0>
|
||||
unordered_set(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(), _Alloc = _Alloc())
|
||||
-> unordered_set<_STD _Iter_value_t<_Iter>, _Hasher, _Keyeq, _Alloc>;
|
||||
|
||||
template <class _Kty, class _Hasher = _STD hash<_Kty>, class _Keyeq = _STD equal_to<_Kty>, class _Alloc = allocator<_Kty>,
|
||||
_STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_set(_STD initializer_list<_Kty>, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(),
|
||||
_Alloc = _Alloc()) -> unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>;
|
||||
|
||||
template <class _Iter, class _Alloc, _STD enable_if_t<_STD conjunction_v<_STD _Is_iterator<_Iter>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_set(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc>, _Alloc)
|
||||
-> unordered_set<_STD _Iter_value_t<_Iter>, _STD hash<_STD _Iter_value_t<_Iter>>, _STD equal_to<_STD _Iter_value_t<_Iter>>, _Alloc>;
|
||||
|
||||
template <class _Iter, class _Hasher, class _Alloc,
|
||||
_STD enable_if_t<_STD conjunction_v<_STD _Is_iterator<_Iter>, _Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_set(_Iter, _Iter, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
|
||||
-> unordered_set<_STD _Iter_value_t<_Iter>, _Hasher, _STD equal_to<_STD _Iter_value_t<_Iter>>, _Alloc>;
|
||||
|
||||
template <class _Kty, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
|
||||
unordered_set(_STD initializer_list<_Kty>, _STD _Guide_size_type_t<_Alloc>, _Alloc)
|
||||
-> unordered_set<_Kty, _STD hash<_Kty>, _STD equal_to<_Kty>, _Alloc>;
|
||||
|
||||
template <class _Kty, class _Hasher, class _Alloc,
|
||||
_STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_set(_STD initializer_list<_Kty>, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
|
||||
-> unordered_set<_Kty, _Hasher, _STD equal_to<_Kty>, _Alloc>;
|
||||
|
||||
#if _HAS_CXX23 && defined(__cpp_lib_concepts) // TRANSITION, GH-395
|
||||
template <_RANGES input_range _Rng, class _Hasher = _STD hash<_RANGES range_value_t<_Rng>>,
|
||||
class _Keyeq = _STD equal_to<_RANGES range_value_t<_Rng>>, class _Alloc = allocator<_RANGES range_value_t<_Rng>>,
|
||||
_STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD negation<_STD _Is_allocator<_Keyeq>>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_set(_STD from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc> = 0, _Hasher = _Hasher(), _Keyeq = _Keyeq(),
|
||||
_Alloc = _Alloc()) -> unordered_set<_RANGES range_value_t<_Rng>, _Hasher, _Keyeq, _Alloc>;
|
||||
|
||||
template <_RANGES input_range _Rng, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
|
||||
unordered_set(_STD from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc>, _Alloc) -> unordered_set<_RANGES range_value_t<_Rng>,
|
||||
_STD hash<_RANGES range_value_t<_Rng>>, _STD equal_to<_RANGES range_value_t<_Rng>>, _Alloc>;
|
||||
|
||||
template <_RANGES input_range _Rng, class _Alloc, _STD enable_if_t<_STD _Is_allocator<_Alloc>::value, int> = 0>
|
||||
unordered_set(_STD from_range_t, _Rng&&, _Alloc) -> unordered_set<_RANGES range_value_t<_Rng>,
|
||||
_STD hash<_RANGES range_value_t<_Rng>>, _STD equal_to<_RANGES range_value_t<_Rng>>, _Alloc>;
|
||||
|
||||
template <_RANGES input_range _Rng, class _Hasher, class _Alloc,
|
||||
_STD enable_if_t<_STD conjunction_v<_Is_hasher<_Hasher>, _STD _Is_allocator<_Alloc>>, int> = 0>
|
||||
unordered_set(_STD from_range_t, _Rng&&, _STD _Guide_size_type_t<_Alloc>, _Hasher, _Alloc)
|
||||
-> unordered_set<_RANGES range_value_t<_Rng>, _Hasher, _STD equal_to<_RANGES range_value_t<_Rng>>, _Alloc>;
|
||||
#endif // _HAS_CXX23 && defined(__cpp_lib_concepts)
|
||||
#endif // _HAS_CXX17
|
||||
|
||||
/* _EXPORT_STD */ template <class _Kty, class _Hasher, class _Keyeq, class _Alloc>
|
||||
void swap(unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Left,
|
||||
unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Right) noexcept(noexcept(_Left.swap(_Right))) {
|
||||
_Left.swap(_Right);
|
||||
}
|
||||
|
||||
#if _HAS_CXX20
|
||||
/* _EXPORT_STD */ template <class _Kty, class _Hasher, class _Keyeq, class _Alloc, class _Pr>
|
||||
unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>::size_type erase_if(
|
||||
unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Cont, _Pr _Pred) {
|
||||
return _STD _Erase_nodes_if(_Cont, _STD _Pass_fn(_Pred));
|
||||
}
|
||||
#endif // _HAS_CXX20
|
||||
|
||||
/* _EXPORT_STD */ template <class _Kty, class _Hasher, class _Keyeq, class _Alloc>
|
||||
_NODISCARD bool operator==(const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Left,
|
||||
const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Right) {
|
||||
return geode::stl:: _Hash_equal(_Left, _Right);
|
||||
}
|
||||
|
||||
#if !_HAS_CXX20
|
||||
template <class _Kty, class _Hasher, class _Keyeq, class _Alloc>
|
||||
_NODISCARD bool operator!=(const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Left,
|
||||
const unordered_set<_Kty, _Hasher, _Keyeq, _Alloc>& _Right) {
|
||||
return !(_Left == _Right);
|
||||
}
|
||||
#endif // !_HAS_CXX20
|
||||
|
||||
} // namespace geode::stl
|
||||
|
||||
#pragma pop_macro("new")
|
||||
_STL_RESTORE_CLANG_WARNINGS
|
||||
#pragma warning(pop)
|
||||
#pragma pack(pop)
|
||||
#endif // _STL_COMPILER_PREPROCESSOR
|
||||
#endif // _GEODE_UNORDERED_SET_
|
|
@ -1,26 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include "msvc/allocator.hpp"
|
||||
#include "msvc/umap.hpp"
|
||||
#include "msvc/uset.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
|
||||
namespace gd {
|
||||
template <class T>
|
||||
using vector = std::vector<T>;
|
||||
|
||||
template <class K, class V>
|
||||
using map = std::map<K, V>;
|
||||
|
||||
template <class K, class V>
|
||||
using unordered_map = geode::stl::unordered_map<K, V, std::hash<K>, std::equal_to<K>, geode::stl::allocator<std::pair<const K, V>>>;
|
||||
|
||||
template <class K>
|
||||
using set = std::set<K>;
|
||||
|
||||
template <class K>
|
||||
using unordered_set = geode::stl::unordered_set<K, std::hash<K>, std::equal_to<K>, geode::stl::allocator<K>>;
|
||||
}
|
|
@ -183,7 +183,7 @@ public:
|
|||
private:
|
||||
void getSetOfTouchesEndOrCancel(CCSet& set, int num, int ids[], float xs[], float ys[]);
|
||||
|
||||
protected:
|
||||
public:
|
||||
EGLTouchDelegate* m_pDelegate;
|
||||
|
||||
// real screen size
|
||||
|
|
|
@ -244,130 +244,4 @@ namespace geode {
|
|||
|
||||
virtual ~Event();
|
||||
};
|
||||
|
||||
// template <is_filter F, std::move_constructible T>
|
||||
// class [[nodiscard]] EventMapper final {
|
||||
// public:
|
||||
// using Value = T;
|
||||
|
||||
// class Handle final {
|
||||
// std::optional<EventListener<F>> m_listener;
|
||||
|
||||
// class PrivateMarker final {};
|
||||
|
||||
// static std::shared_ptr<Handle> create() {
|
||||
// return std::make_shared<Handle>(PrivateMarker());
|
||||
// }
|
||||
|
||||
// friend class EventMapper;
|
||||
|
||||
// public:
|
||||
// Handle(PrivateMarker) {}
|
||||
// };
|
||||
|
||||
// class Event final : public geode::Event {
|
||||
// private:
|
||||
// std::shared_ptr<Handle> m_handle;
|
||||
// T m_value;
|
||||
|
||||
// Event(std::shared_ptr<Handle> handle, T&& value)
|
||||
// : m_handle(handle), m_value(std::move(value)) {}
|
||||
|
||||
// friend class EventMapper;
|
||||
|
||||
// public:
|
||||
// T& getValue() & {
|
||||
// return m_value;
|
||||
// }
|
||||
// T const& getValue() const& {
|
||||
// return m_value;
|
||||
// }
|
||||
// T&& getValue() && {
|
||||
// return std::move(m_value);
|
||||
// }
|
||||
|
||||
// operator T*() const {
|
||||
// return m_value;
|
||||
// }
|
||||
// T* operator*() const {
|
||||
// return m_value;
|
||||
// }
|
||||
// T* operator->() const {
|
||||
// return m_value;
|
||||
// }
|
||||
// };
|
||||
|
||||
// using Mapper = utils::MiniFunction<T(typename F::Event*)>;
|
||||
// using Callback = void(Event*);
|
||||
|
||||
// private:
|
||||
// EventListenerProtocol* m_listener = nullptr;
|
||||
// std::shared_ptr<Handle> m_handle;
|
||||
|
||||
// EventMapper(std::shared_ptr<Handle> handle) : m_handle(handle) {}
|
||||
|
||||
// public:
|
||||
// EventMapper() : m_handle(nullptr) {}
|
||||
|
||||
// static EventMapper immediate(T&& value) {
|
||||
// auto emapper = EventMapper(Handle::create());
|
||||
// Loader::get()->queueInMainThread([handle = emapper.m_handle, value = std::move(value)]() mutable {
|
||||
// EventMapper::Event(handle, std::move(value)).post();
|
||||
// });
|
||||
// return emapper;
|
||||
// }
|
||||
// static EventMapper create(F&& filter, Mapper&& mapper) {
|
||||
// auto emapper = EventMapper(Handle::create());
|
||||
// emapper.m_handle->m_listener.emplace(EventListener(
|
||||
// // The event listener should not own itself (circular ref = memory leak!!)
|
||||
// [handle = std::weak_ptr(emapper.m_handle), mapper = std::move(mapper)](F::Event* event) {
|
||||
// if (auto lock = handle.lock()) {
|
||||
// EventMapper::Event(lock, mapper(event)).post();
|
||||
// }
|
||||
// },
|
||||
// std::move(filter)
|
||||
// ));
|
||||
// return emapper;
|
||||
// }
|
||||
|
||||
// template <class NewMapper>
|
||||
// auto map(NewMapper&& mapper) {
|
||||
// using T2 = decltype(mapper(std::declval<T*>()));
|
||||
// return mapEvent(*this, [mapper = std::move(mapper)](Event* event) -> T2 {
|
||||
// return mapper(&event->getValue());
|
||||
// });
|
||||
// }
|
||||
|
||||
// ListenerResult handle(utils::MiniFunction<Callback> fn, Event* e) {
|
||||
// if (e->m_handle == m_handle) {
|
||||
// fn(e);
|
||||
// }
|
||||
// return ListenerResult::Propagate;
|
||||
// }
|
||||
|
||||
// // todo: i believe alk wanted these to be in their own pool
|
||||
// EventListenerPool* getPool() const {
|
||||
// return DefaultEventListenerPool::get();
|
||||
// }
|
||||
|
||||
// void setListener(EventListenerProtocol* listener) {
|
||||
// m_listener = listener;
|
||||
// }
|
||||
// EventListenerProtocol* getListener() const {
|
||||
// return m_listener;
|
||||
// }
|
||||
// };
|
||||
|
||||
// template <is_filter F, class Mapper>
|
||||
// static auto mapEvent(F&& filter, Mapper&& mapper) {
|
||||
// using T = decltype(mapper(std::declval<typename F::Event*>()));
|
||||
// return EventMapper<F, T>::create(std::move(filter), std::move(mapper));
|
||||
// }
|
||||
|
||||
// template <is_filter F, class Mapper>
|
||||
// requires std::copy_constructible<F>
|
||||
// static auto mapEvent(F const& filter, Mapper&& mapper) {
|
||||
// using T = decltype(mapper(std::declval<typename F::Event*>()));
|
||||
// return EventMapper<F, T>::create(F(filter), std::move(mapper));
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -142,8 +142,22 @@ namespace geode {
|
|||
* @returns The latest available version on the index if there are
|
||||
* updates for this mod
|
||||
*/
|
||||
[[deprecated("Use Mod::checkUpdates instead; this function always returns nullopt")]]
|
||||
std::optional<VersionInfo> hasAvailableUpdate() const;
|
||||
|
||||
using CheckUpdatesTask = Task<Result<std::optional<VersionInfo>, std::string>>;
|
||||
/**
|
||||
* Check if this Mod has updates available on the mods index. If
|
||||
* you're using this for automatic update checking, use
|
||||
* `openInfoPopup` from the `ui/GeodeUI.hpp` header to open the Mod's
|
||||
* page to let the user install the update
|
||||
* @returns A task that resolves to an option, either the latest
|
||||
* available version on the index if there are updates available, or
|
||||
* `std::nullopt` if there are no updates. On error, the Task returns
|
||||
* an error
|
||||
*/
|
||||
CheckUpdatesTask checkUpdates() const;
|
||||
|
||||
Result<> saveData();
|
||||
Result<> loadData();
|
||||
|
||||
|
|
|
@ -103,7 +103,6 @@ namespace geode {
|
|||
class FieldIntermediate;
|
||||
}
|
||||
|
||||
// TODO: make ordered
|
||||
using ModJson = matjson::Value;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,4 +41,11 @@ namespace geode::modifier {
|
|||
|
||||
GEODE_AS_STATIC_FUNCTION(constructor)
|
||||
GEODE_AS_STATIC_FUNCTION(destructor)
|
||||
|
||||
|
||||
#define GEODE_CONCEPT_FUNCTION_CHECK(FunctionName_) \
|
||||
template <class Class, class... Args> \
|
||||
concept FunctionExists_##FunctionName_ = requires(Class* self, Args... args) { \
|
||||
self->FunctionName_(args...); \
|
||||
};
|
||||
}
|
||||
|
|
|
@ -42,6 +42,38 @@
|
|||
} \
|
||||
} while (0);
|
||||
|
||||
#define GEODE_APPLY_MODIFY_FOR_FUNCTION_ERROR(ClassName_, FunctionName_, ...) \
|
||||
do { \
|
||||
static_assert(!FunctionExists_##FunctionName_<Derived __VA_ARGS__>, \
|
||||
"Function " #ClassName_ "::" #FunctionName_ " does not have an available address in the" \
|
||||
" bindings, please add it to the bindings to hook it." \
|
||||
); \
|
||||
} while (0);
|
||||
|
||||
#define GEODE_APPLY_MODIFY_FOR_FUNCTION_ERROR_DEFINED(ClassName_, FunctionName_, ...) \
|
||||
do { \
|
||||
static auto constexpr different = Unique::different< \
|
||||
Resolve<__VA_ARGS__>::func(&Base::FunctionName_), \
|
||||
Resolve<__VA_ARGS__>::func(&Derived::FunctionName_) \
|
||||
>(); \
|
||||
static_assert(!different, \
|
||||
"Function " #ClassName_ "::" #FunctionName_ " does not have an available address in the" \
|
||||
" bindings, please add it to the bindings to hook it." \
|
||||
); \
|
||||
} while (0);
|
||||
|
||||
#define GEODE_APPLY_MODIFY_FOR_FUNCTION_ERROR_INLINE(ClassName_, FunctionName_, ...) \
|
||||
do { \
|
||||
static auto constexpr different = Unique::different< \
|
||||
Resolve<__VA_ARGS__>::func(&Base::FunctionName_), \
|
||||
Resolve<__VA_ARGS__>::func(&Derived::FunctionName_) \
|
||||
>(); \
|
||||
static_assert(!different, \
|
||||
"Function " #ClassName_ "::" #FunctionName_ " cannot be hooked due to an inline definition" \
|
||||
" existing for the function." \
|
||||
); \
|
||||
} while (0);
|
||||
|
||||
#define GEODE_APPLY_MODIFY_FOR_CONSTRUCTOR(AddressInline_, Convention_, ClassName_, ...) \
|
||||
do { \
|
||||
if constexpr (HasConstructor<Derived>) { \
|
||||
|
|
|
@ -82,6 +82,10 @@ namespace geode {
|
|||
Teal = 6,
|
||||
Aqua = 7,
|
||||
Cyan = 8,
|
||||
Magenta = 9,
|
||||
DimGreen = 10,
|
||||
BrightGreen = 11,
|
||||
Salmon = 12,
|
||||
};
|
||||
GEODE_DLL const char* baseEnumToString(EditorBaseColor);
|
||||
|
||||
|
|
|
@ -11,6 +11,10 @@ namespace geode {
|
|||
* Open the info popup for a mod
|
||||
*/
|
||||
GEODE_DLL void openInfoPopup(Mod* mod);
|
||||
/**
|
||||
* Open the info popup for a mod on the changelog page
|
||||
*/
|
||||
GEODE_DLL void openChangelogPopup(Mod* mod);
|
||||
/**
|
||||
* Open the issue report popup for a mod
|
||||
*/
|
||||
|
@ -23,6 +27,7 @@ namespace geode {
|
|||
/**
|
||||
* Open the store page for a mod (if it exists)
|
||||
*/
|
||||
[[deprecated("Will be removed, use openInfoPopup instead")]]
|
||||
GEODE_DLL void openIndexPopup(Mod* mod);
|
||||
/**
|
||||
* Open the settings popup for a mod (if it has any settings)
|
||||
|
|
|
@ -126,7 +126,6 @@ namespace geode::utils::web {
|
|||
|
||||
WebRequest& header(std::string_view name, std::string_view value);
|
||||
WebRequest& param(std::string_view name, std::string_view value);
|
||||
|
||||
template <std::integral T>
|
||||
WebRequest& param(std::string_view name, T value) {
|
||||
return this->param(name, std::to_string(value));
|
||||
|
@ -251,5 +250,55 @@ namespace geode::utils::web {
|
|||
* @return WebRequest&
|
||||
*/
|
||||
WebRequest& bodyJSON(matjson::Value const& json);
|
||||
|
||||
|
||||
/**
|
||||
* Gets the request method as a string
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
std::string getMethod() const;
|
||||
|
||||
/**
|
||||
* Gets the request URL
|
||||
*
|
||||
* @return std::string
|
||||
*/
|
||||
std::string getUrl() const;
|
||||
|
||||
/**
|
||||
* Gets the request headers
|
||||
*
|
||||
* @return std::unordered_map<std::string, std::string>
|
||||
*/
|
||||
std::unordered_map<std::string, std::string> getHeaders() const;
|
||||
|
||||
/**
|
||||
* Gets the parameters inside the URL
|
||||
*
|
||||
* @return std::unordered_map<std::string, std::string>
|
||||
*/
|
||||
std::unordered_map<std::string, std::string> getUrlParams() const;
|
||||
|
||||
/**
|
||||
* Gets the post body stream
|
||||
*
|
||||
* @return std::optional<ByteVector>
|
||||
*/
|
||||
std::optional<ByteVector> getBody() const;
|
||||
|
||||
/**
|
||||
* Gets the request timeout in seconds
|
||||
*
|
||||
* @return std::optional<std::chrono::seconds>
|
||||
*/
|
||||
std::optional<std::chrono::seconds> getTimeout() const;
|
||||
|
||||
/**
|
||||
* Gets HTTP versions applied to the request
|
||||
*
|
||||
* @return HttpVersion
|
||||
*/
|
||||
HttpVersion getHttpVersion() const;
|
||||
};
|
||||
}
|
||||
|
|
Before ![]() (image error) Size: 18 KiB After ![]() (image error) Size: 5.3 KiB ![]() ![]() |
Before ![]() (image error) Size: 20 KiB After ![]() (image error) Size: 5.3 KiB ![]() ![]() |
Before ![]() (image error) Size: 23 KiB After ![]() (image error) Size: 6.8 KiB ![]() ![]() |
Before ![]() (image error) Size: 73 KiB After ![]() (image error) Size: 86 KiB ![]() ![]() |
Before ![]() (image error) Size: 20 KiB After ![]() (image error) Size: 11 KiB ![]() ![]() |
Before ![]() (image error) Size: 19 KiB After ![]() (image error) Size: 11 KiB ![]() ![]() |
BIN
loader/resources/blanks/baseCircle_Big_DarkAqua.png
Normal file
After ![]() (image error) Size: 12 KiB |
Before ![]() (image error) Size: 16 KiB After ![]() (image error) Size: 12 KiB ![]() ![]() |
Before ![]() (image error) Size: 23 KiB After ![]() (image error) Size: 12 KiB ![]() ![]() |
Before ![]() (image error) Size: 27 KiB After ![]() (image error) Size: 17 KiB ![]() ![]() |
Before ![]() (image error) Size: 26 KiB After ![]() (image error) Size: 17 KiB ![]() ![]() |
Before ![]() (image error) Size: 16 KiB After ![]() (image error) Size: 11 KiB ![]() ![]() |
Before ![]() (image error) Size: 15 KiB After ![]() (image error) Size: 11 KiB ![]() ![]() |
Before ![]() (image error) Size: 15 KiB After ![]() (image error) Size: 9.6 KiB ![]() ![]() |
Before ![]() (image error) Size: 14 KiB After ![]() (image error) Size: 9.5 KiB ![]() ![]() |
Before ![]() (image error) Size: 13 KiB After ![]() (image error) Size: 8.6 KiB ![]() ![]() |
Before ![]() (image error) Size: 12 KiB After ![]() (image error) Size: 8.6 KiB ![]() ![]() |
Before ![]() (image error) Size: 12 KiB After ![]() (image error) Size: 7.9 KiB ![]() ![]() |
Before ![]() (image error) Size: 12 KiB After ![]() (image error) Size: 7.9 KiB ![]() ![]() |
Before ![]() (image error) Size: 8.1 KiB After ![]() (image error) Size: 5.1 KiB ![]() ![]() |
Before ![]() (image error) Size: 7.8 KiB After ![]() (image error) Size: 5.1 KiB ![]() ![]() |
BIN
loader/resources/blanks/baseEditor_Normal_Blue.png
Normal file
After ![]() (image error) Size: 2.7 KiB |
BIN
loader/resources/blanks/baseEditor_Normal_BrightGreen.png
Normal file
After ![]() (image error) Size: 2.7 KiB |
Before ![]() (image error) Size: 18 KiB After ![]() (image error) Size: 2.6 KiB ![]() ![]() |
Before ![]() (image error) Size: 17 KiB After ![]() (image error) Size: 2.6 KiB ![]() ![]() |
BIN
loader/resources/blanks/baseEditor_Normal_DimGreen.png
Normal file
After ![]() (image error) Size: 2.7 KiB |
Before ![]() (image error) Size: 16 KiB After ![]() (image error) Size: 2.7 KiB ![]() ![]() |
Before ![]() (image error) Size: 17 KiB After ![]() (image error) Size: 2.6 KiB ![]() ![]() |
Before ![]() (image error) Size: 18 KiB After ![]() (image error) Size: 2.7 KiB ![]() ![]() |
BIN
loader/resources/blanks/baseEditor_Normal_Magenta.png
Normal file
After ![]() (image error) Size: 2.8 KiB |
Before ![]() (image error) Size: 17 KiB After ![]() (image error) Size: 2.7 KiB ![]() ![]() |
Before ![]() (image error) Size: 16 KiB After ![]() (image error) Size: 2.7 KiB ![]() ![]() |
BIN
loader/resources/blanks/baseEditor_Normal_Salmon.png
Normal file
After ![]() (image error) Size: 2.7 KiB |
Before ![]() (image error) Size: 15 KiB After ![]() (image error) Size: 2.6 KiB ![]() ![]() |
25
loader/resources/blanks/svgs/baseEditor_Normal.svg
Normal file
|
@ -0,0 +1,25 @@
|
|||
<svg width="132" height="138" viewBox="0 0 132 138" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d_922_144)">
|
||||
<rect x="4" y="7" width="124" height="124" rx="20" fill="white"/>
|
||||
</g>
|
||||
<rect x="8" y="11" width="116" height="116" rx="16" fill="black"/>
|
||||
<rect x="12" y="15" width="108" height="108" rx="14" fill="url(#paint0_linear_922_144)"/>
|
||||
<rect x="17" y="20" width="98" height="98" rx="8" fill="#7ADE2D"/>
|
||||
<defs>
|
||||
<filter id="filter0_d_922_144" x="4" y="7" width="128" height="131" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="4" dy="7"/>
|
||||
<feComposite in2="hardAlpha" operator="out"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.34 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_922_144"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_922_144" result="shape"/>
|
||||
</filter>
|
||||
<linearGradient id="paint0_linear_922_144" x1="12" y1="15" x2="120" y2="123" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#C6F249"/>
|
||||
<stop offset="0.495303" stop-color="#C6F249"/>
|
||||
<stop offset="0.495303" stop-color="#49851B"/>
|
||||
<stop offset="1" stop-color="#49851B"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
After (image error) Size: 1.4 KiB |
|
@ -27,7 +27,30 @@ colors = {
|
|||
"Cyan": ["#58FDFA", "#13D5EA", "#44F9F6", "#0B9FBE"],
|
||||
"Blue": ["#1AF1F8", "#0AB4FF", "#23DCFA", "#0077FA"],
|
||||
"Gray": ["#DEDEE0", "#979997", "#CACCCA", "#747472"],
|
||||
# "DarkPurple": ["#41384b", "#2f2937", "#393142", "#221e28"],
|
||||
"DarkPurple": ["#41384b", "#2f2937", "#393142", "#221e28"],
|
||||
"DarkAqua": ["#2a4559", "#1f3441", "#253d4e", "#17272f"],
|
||||
}
|
||||
|
||||
editor_sizes = [
|
||||
"Normal",
|
||||
]
|
||||
|
||||
editor_color_from = ["#C6F249", "#7ADE2D", "#49851B"]
|
||||
|
||||
editor_colors = {
|
||||
"Cyan": ["#0effff", "#00d2f6", "#007d94"],
|
||||
"Blue": ["#82d6ff", "#80a1ff", "#4d60d2"],
|
||||
"Teal": ["#3cfcbc", "#3cfcbc", "#0f7a68"],
|
||||
"Magenta": ["#ffafff", "#f67fff", "#944cca"],
|
||||
"Pink": ["#ff93fd", "#ff6fab", "#d44266"],
|
||||
"Green": ["#a2f30e", "#58d000", "#347c00"],
|
||||
"BrightGreen": ["#62ff2a", "#23dc23", "#148414"],
|
||||
"DimGreen": ["#ace83f", "#6ac227", "#3f7417"],
|
||||
"Orange": ["#ffd387", "#ffa83f", "#b35d1e"],
|
||||
"LightBlue": ["#52e8ff", "#4fb1ff", "#2f6ac7"],
|
||||
"Gray": ["#c8c7c9", "#9b9a9b", "#5c5c5d"],
|
||||
"DarkGray": ["#9a9a9a", "#717171", "#3a3a3a"],
|
||||
"Salmon": ["#ffbbb9", "#ff9260", "#e15032"],
|
||||
}
|
||||
|
||||
for size in sizes:
|
||||
|
@ -35,8 +58,19 @@ for size in sizes:
|
|||
svg_base = file.read()
|
||||
for name, cols in colors.items():
|
||||
svg = svg_base
|
||||
out = f"../baseCircle_{size}_{name.title()}.png"
|
||||
out = f"../baseCircle_{size}_{name}.png"
|
||||
print(f"Generating {out}")
|
||||
for color_orig, color_to in zip(color_from, cols):
|
||||
svg = svg.replace(color_orig, color_to)
|
||||
subprocess.run(["rsvg-convert", "-o", out], input=svg.encode())
|
||||
|
||||
for size in editor_sizes:
|
||||
with open(f"baseEditor_{size}.svg", "r") as file:
|
||||
svg_base = file.read()
|
||||
for name, cols in editor_colors.items():
|
||||
svg = svg_base
|
||||
out = f"../baseEditor_{size}_{name}.png"
|
||||
print(f"Generating {out}")
|
||||
for color_orig, color_to in zip(editor_color_from, cols):
|
||||
svg = svg.replace(color_orig, color_to)
|
||||
subprocess.run(["rsvg-convert", "-o", out], input=svg.encode())
|
||||
|
|
BIN
loader/resources/tag-featured.png
Normal file
After ![]() (image error) Size: 15 KiB |
BIN
loader/resources/tag-paid.png
Normal file
After ![]() (image error) Size: 33 KiB |
|
@ -13,13 +13,12 @@ using namespace geode::prelude;
|
|||
// no one knows how this is possible (he passes char* to wchar_t*).
|
||||
// so anyway, here's a fix for it
|
||||
|
||||
static void __cdecl fixedErrorHandler(int code, char const* description) {
|
||||
static void __cdecl fixedErrorHandler2(int code, char const* description) {
|
||||
log::error("GLFW Error {}: {}", code, description);
|
||||
MessageBoxA(
|
||||
nullptr,
|
||||
fmt::format(
|
||||
"GLFWError #{}: {}\nPlease contact the "
|
||||
"Geode Development Team for more information.",
|
||||
"GLFWError #{}: {}",
|
||||
code,
|
||||
description
|
||||
)
|
||||
|
@ -27,32 +26,37 @@ static void __cdecl fixedErrorHandler(int code, char const* description) {
|
|||
"OpenGL Error",
|
||||
MB_ICONERROR
|
||||
);
|
||||
|
||||
std::abort();
|
||||
}
|
||||
|
||||
static void __cdecl fixedErrorHandler(CCEGLView*, int code, char const* description) {
|
||||
fixedErrorHandler2(code, description);
|
||||
}
|
||||
|
||||
$execute {
|
||||
// updated for 2.206
|
||||
// check xrefs to "GLFWError #%d Happen, %s\n", now there's two functions with the same exact
|
||||
// behaviour, one is a member function though... call ds:MessageBoxW
|
||||
// patch MessageBoxW to MessageBoxA
|
||||
// geode::base::getCocos() + 0xe2670 = MessageBoxA in .idata
|
||||
// geode::base::getCocos() + 0xe26b8 = MessageBoxW in .idata
|
||||
// behaviour, one is a member function though...
|
||||
// hook them to call our own handler
|
||||
if (LoaderImpl::get()->isForwardCompatMode()) return;
|
||||
|
||||
#if GEODE_COMP_GD_VERSION == 22060
|
||||
// in x64 these became rip-relative jmp & call respectively, instead of absolute calls,
|
||||
// so this code is a bit more complicated than it used to be
|
||||
|
||||
const uintptr_t importedMessageBoxA = 0xe2670;
|
||||
const uintptr_t offset1 = 0x75d00; // member function in CCEGLView
|
||||
const uintptr_t offset2 = 0x75d60; // static function
|
||||
|
||||
const uintptr_t offset1 = 0x75d4a;
|
||||
const uint32_t rel1 = static_cast<uint32_t>(importedMessageBoxA - offset1 - 7);
|
||||
(void) Mod::get()->hook(
|
||||
reinterpret_cast<void*>(geode::base::getCocos() + offset1),
|
||||
fixedErrorHandler,
|
||||
"onGLFWError"
|
||||
);
|
||||
|
||||
(void) Mod::get()->patch(reinterpret_cast<void*>(geode::base::getCocos() + offset1 + 3), geode::toByteArray(rel1));
|
||||
(void) Mod::get()->hook(
|
||||
reinterpret_cast<void*>(geode::base::getCocos() + offset2),
|
||||
fixedErrorHandler2,
|
||||
"onGLFWError2"
|
||||
);
|
||||
|
||||
const uintptr_t offset2 = 0x75daf;
|
||||
const uint32_t rel2 = static_cast<uint32_t>(importedMessageBoxA - offset2 - 6);
|
||||
|
||||
(void) Mod::get()->patch(reinterpret_cast<void*>(geode::base::getCocos() + offset2 + 2), geode::toByteArray(rel2));
|
||||
#else
|
||||
#pragma message("Unsupported GD version!")
|
||||
#endif
|
||||
|
|
|
@ -384,11 +384,6 @@ void Loader::Impl::buildModGraph() {
|
|||
}
|
||||
|
||||
void Loader::Impl::loadModGraph(Mod* node, bool early) {
|
||||
if (early && !node->needsEarlyLoad()) {
|
||||
m_modsToLoad.push_back(node);
|
||||
return;
|
||||
}
|
||||
|
||||
if (node->hasUnresolvedDependencies()) {
|
||||
log::debug("{} {} has unresolved dependencies", node->getID(), node->getVersion());
|
||||
return;
|
||||
|
@ -402,9 +397,7 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
|
|||
log::pushNest();
|
||||
|
||||
if (node->isEnabled()) {
|
||||
for (auto const& dep : node->m_impl->m_dependants) {
|
||||
m_modsToLoad.push_front(dep);
|
||||
}
|
||||
log::warn("Mod {} already loaded, this should never happen", node->getID());
|
||||
log::popNest();
|
||||
return;
|
||||
}
|
||||
|
@ -434,10 +427,6 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) {
|
|||
m_refreshingModCount -= 1;
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto const& dep : node->m_impl->m_dependants) {
|
||||
m_modsToLoad.push_front(dep);
|
||||
}
|
||||
}
|
||||
|
||||
m_refreshingModCount -= 1;
|
||||
|
@ -702,11 +691,18 @@ void Loader::Impl::refreshModGraph() {
|
|||
this->buildModGraph();
|
||||
log::popNest();
|
||||
|
||||
log::debug("Ordering mod stack");
|
||||
log::pushNest();
|
||||
this->orderModStack();
|
||||
log::popNest();
|
||||
|
||||
m_loadingState = LoadingState::EarlyMods;
|
||||
log::debug("Loading early mods");
|
||||
log::pushNest();
|
||||
for (auto const& dep : ModImpl::get()->m_dependants) {
|
||||
this->loadModGraph(dep, true);
|
||||
while (!m_modsToLoad.empty() && m_modsToLoad.front()->needsEarlyLoad()) {
|
||||
auto mod = m_modsToLoad.front();
|
||||
m_modsToLoad.pop_front();
|
||||
this->loadModGraph(mod, true);
|
||||
}
|
||||
log::popNest();
|
||||
|
||||
|
@ -716,16 +712,60 @@ void Loader::Impl::refreshModGraph() {
|
|||
|
||||
log::popNest();
|
||||
|
||||
if (m_modsToLoad.empty())
|
||||
m_loadingState = LoadingState::Problems;
|
||||
else
|
||||
m_loadingState = LoadingState::Mods;
|
||||
m_loadingState = LoadingState::Mods;
|
||||
|
||||
queueInMainThread([&]() {
|
||||
this->continueRefreshModGraph();
|
||||
});
|
||||
}
|
||||
|
||||
void Loader::Impl::orderModStack() {
|
||||
std::unordered_set<Mod*> visited;
|
||||
visited.insert(Mod::get());
|
||||
Mod* selectedMod = nullptr;
|
||||
do {
|
||||
selectedMod = nullptr;
|
||||
for (auto const& mod : ModImpl::get()->m_dependants) {
|
||||
if (visited.count(mod) != 0) continue;
|
||||
|
||||
for (auto dep : mod->getMetadata().getDependencies()) {
|
||||
if (dep.mod && dep.importance == ModMetadata::Dependency::Importance::Required &&
|
||||
visited.count(dep.mod) == 0) {
|
||||
// the dependency is not visited yet
|
||||
// so we cant select this mod
|
||||
goto skip_mod;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedMod) {
|
||||
if (
|
||||
!selectedMod->m_impl->needsEarlyLoad() &&
|
||||
mod->m_impl->needsEarlyLoad()
|
||||
) {
|
||||
// this mod is implied to be loaded early
|
||||
// so we can override a mod that is not
|
||||
selectedMod = mod;
|
||||
}
|
||||
}
|
||||
else {
|
||||
selectedMod = mod;
|
||||
}
|
||||
|
||||
skip_mod:
|
||||
continue;
|
||||
}
|
||||
|
||||
if (selectedMod) {
|
||||
m_modsToLoad.push_back(selectedMod);
|
||||
visited.insert(selectedMod);
|
||||
}
|
||||
} while (selectedMod != nullptr);
|
||||
|
||||
for (auto mod : m_modsToLoad) {
|
||||
log::debug("{}, early: {}", mod->getID(), mod->needsEarlyLoad());
|
||||
}
|
||||
}
|
||||
|
||||
void Loader::Impl::continueRefreshModGraph() {
|
||||
if (m_refreshingModCount != 0) {
|
||||
queueInMainThread([&]() {
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include <queue>
|
||||
#include <tulip/TulipHook.hpp>
|
||||
|
||||
// TODO: Find a file convention for impl headers
|
||||
namespace geode {
|
||||
static constexpr std::string_view LAUNCH_ARG_PREFIX = "--geode:";
|
||||
|
||||
|
@ -100,6 +99,7 @@ namespace geode {
|
|||
void queueMods(std::vector<ModMetadata>& modQueue);
|
||||
void populateModList(std::vector<ModMetadata>& modQueue);
|
||||
void buildModGraph();
|
||||
void orderModStack();
|
||||
void loadModGraph(Mod* node, bool early);
|
||||
void findProblems();
|
||||
void refreshModGraph();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <Geode/loader/Mod.hpp>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <server/Server.hpp>
|
||||
|
||||
using namespace geode::prelude;
|
||||
|
||||
|
@ -101,17 +102,30 @@ std::vector<Mod*> Mod::getDependants() const {
|
|||
#endif
|
||||
|
||||
std::optional<VersionInfo> Mod::hasAvailableUpdate() const {
|
||||
// TODO
|
||||
// if (auto item = Index::get()->getItem(this->getID(), std::nullopt)) {
|
||||
// if (
|
||||
// item->getMetadata().getVersion() > this->getVersion() &&
|
||||
// item->getAvailablePlatforms().contains(GEODE_PLATFORM_TARGET)
|
||||
// ) {
|
||||
// return item->getMetadata().getVersion();
|
||||
// }
|
||||
// }
|
||||
return std::nullopt;
|
||||
}
|
||||
Mod::CheckUpdatesTask Mod::checkUpdates() const {
|
||||
return server::checkUpdates(this).map(
|
||||
[](auto* result) -> Mod::CheckUpdatesTask::Value {
|
||||
if (result->isOk()) {
|
||||
if (auto value = result->unwrap()) {
|
||||
if (value->replacement) {
|
||||
return Err(
|
||||
"Mod has been replaced by {} - please visit the Geode "
|
||||
"menu to install the replacement",
|
||||
value->replacement->id
|
||||
);
|
||||
}
|
||||
return Ok(value->version);
|
||||
}
|
||||
return Ok(std::nullopt);
|
||||
}
|
||||
auto err = result->unwrapErr();
|
||||
return Err("{} (code {})", err.details, err.code);
|
||||
},
|
||||
[](auto*) { return std::monostate(); }
|
||||
);
|
||||
}
|
||||
|
||||
Result<> Mod::saveData() {
|
||||
return m_impl->saveData();
|
||||
|
|
|
@ -140,7 +140,7 @@ matjson::Value& Mod::Impl::getSavedSettingsData() {
|
|||
}
|
||||
|
||||
bool Mod::Impl::isEnabled() const {
|
||||
return m_enabled;
|
||||
return m_enabled || this->isInternal();
|
||||
}
|
||||
|
||||
bool Mod::Impl::isInternal() const {
|
||||
|
@ -148,11 +148,11 @@ bool Mod::Impl::isInternal() const {
|
|||
}
|
||||
|
||||
bool Mod::Impl::needsEarlyLoad() const {
|
||||
auto deps = m_dependants;
|
||||
return getMetadata().needsEarlyLoad() ||
|
||||
!deps.empty() && std::any_of(deps.begin(), deps.end(), [&](auto& item) {
|
||||
return item->needsEarlyLoad();
|
||||
});
|
||||
if (this->getMetadata().needsEarlyLoad()) return true;
|
||||
for (auto& dep : m_dependants) {
|
||||
if (dep->needsEarlyLoad()) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<Hook*> Mod::Impl::getHooks() const {
|
||||
|
@ -800,7 +800,7 @@ void Mod::Impl::setLoggingEnabled(bool enabled) {
|
|||
}
|
||||
|
||||
bool Mod::Impl::shouldLoad() const {
|
||||
return Mod::get()->getSavedValue<bool>("should-load-" + m_metadata.getID(), true);
|
||||
return Mod::get()->getSavedValue<bool>("should-load-" + m_metadata.getID(), true) || this->isInternal();
|
||||
}
|
||||
|
||||
bool Mod::Impl::isCurrentlyLoading() const {
|
||||
|
|
|
@ -91,8 +91,36 @@ static Mod* modFromAddress(PVOID exceptionAddress) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
PVOID GeodeFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase);
|
||||
|
||||
typedef union _UNWIND_CODE {
|
||||
struct {
|
||||
uint8_t CodeOffset;
|
||||
uint8_t UnwindOp : 4;
|
||||
uint8_t OpInfo : 4;
|
||||
};
|
||||
uint16_t FrameOffset;
|
||||
} UNWIND_CODE, *PUNWIND_CODE;
|
||||
|
||||
typedef struct _UNWIND_INFO {
|
||||
uint8_t Version : 3;
|
||||
uint8_t Flags : 5;
|
||||
uint8_t SizeOfProlog;
|
||||
uint8_t CountOfCodes;
|
||||
uint8_t FrameRegister : 4;
|
||||
uint8_t FrameOffset : 4;
|
||||
UNWIND_CODE UnwindCode[1];
|
||||
/* UNWIND_CODE MoreUnwindCode[((CountOfCodes + 1) & ~1) - 1];
|
||||
* union {
|
||||
* OPTIONAL ULONG ExceptionHandler;
|
||||
* OPTIONAL ULONG FunctionEntry;
|
||||
* };
|
||||
* OPTIONAL ULONG ExceptionData[]; */
|
||||
} UNWIND_INFO, *PUNWIND_INFO;
|
||||
|
||||
static void printAddr(std::ostream& stream, void const* addr, bool fullPath = true) {
|
||||
HMODULE module = nullptr;
|
||||
auto proc = GetCurrentProcess();
|
||||
|
||||
if (GetModuleHandleEx(
|
||||
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
|
||||
|
@ -114,12 +142,26 @@ static void printAddr(std::ostream& stream, void const* addr, bool fullPath = tr
|
|||
symbolInfo->SizeOfStruct = sizeof(SYMBOL_INFO);
|
||||
symbolInfo->MaxNameLen = MAX_SYM_NAME;
|
||||
|
||||
auto proc = GetCurrentProcess();
|
||||
|
||||
if (SymFromAddr(
|
||||
proc, static_cast<DWORD64>(reinterpret_cast<uintptr_t>(addr)), &displacement,
|
||||
symbolInfo
|
||||
)) {
|
||||
if (auto entry = SymFunctionTableAccess64(proc, static_cast<DWORD64>(reinterpret_cast<uintptr_t>(addr)))) {
|
||||
auto moduleBase = SymGetModuleBase64(proc, static_cast<DWORD64>(reinterpret_cast<uintptr_t>(addr)));
|
||||
auto runtimeFunction = static_cast<PRUNTIME_FUNCTION>(entry);
|
||||
auto unwindInfo = reinterpret_cast<PUNWIND_INFO>(moduleBase + runtimeFunction->UnwindInfoAddress);
|
||||
|
||||
// This is a chain of unwind info structures, so we traverse back to the first one
|
||||
while (unwindInfo->Flags & UNW_FLAG_CHAININFO) {
|
||||
runtimeFunction = (PRUNTIME_FUNCTION)&(unwindInfo->UnwindCode[( unwindInfo->CountOfCodes + 1 ) & ~1]);
|
||||
unwindInfo = reinterpret_cast<PUNWIND_INFO>(moduleBase + runtimeFunction->UnwindInfoAddress);
|
||||
}
|
||||
|
||||
if (moduleBase + runtimeFunction->BeginAddress != symbolInfo->Address) {
|
||||
// the symbol address is not the same as the function address
|
||||
return;
|
||||
}
|
||||
}
|
||||
stream << " (" << std::string(symbolInfo->Name, symbolInfo->NameLen) << " + "
|
||||
<< displacement;
|
||||
|
||||
|
@ -141,11 +183,13 @@ static void printAddr(std::ostream& stream, void const* addr, bool fullPath = tr
|
|||
}
|
||||
else {
|
||||
stream << addr;
|
||||
|
||||
if (GeodeFunctionTableAccess64(proc, reinterpret_cast<DWORD64>(addr))) {
|
||||
stream << " (Hook handler)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PVOID GeodeFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase);
|
||||
|
||||
// https://stackoverflow.com/a/50208684/9124836
|
||||
static std::string getStacktrace(PCONTEXT context, Mod*& suspectedFaultyMod) {
|
||||
std::stringstream stream;
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
#include "../../c++stl/msvc/allocator.hpp"
|
||||
#include "../../c++stl/string-impl.hpp"
|
||||
|
||||
static auto constexpr NEW_SYM = "??2@YAPAXI@Z";
|
||||
static auto constexpr DELETE_SYM = "??3@YAXPAX@Z";
|
||||
|
||||
static void* getFn(const char* sym) {
|
||||
auto msvcr = GetModuleHandleW(L"MSVCR120.dll");
|
||||
if (msvcr != NULL)
|
||||
return reinterpret_cast<void*>(GetProcAddress(msvcr, sym));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* geode::stl::operatorNew(size_t size) {
|
||||
static auto fnPtr = reinterpret_cast<void*(*)(size_t)>(getFn(NEW_SYM));
|
||||
return fnPtr(size);
|
||||
}
|
||||
|
||||
void geode::stl::operatorDelete(void* ptr) {
|
||||
static auto fnPtr = reinterpret_cast<void(*)(void*)>(getFn(DELETE_SYM));
|
||||
return fnPtr(ptr);
|
||||
}
|
||||
|
||||
namespace geode::stl {
|
||||
void StringImpl::setEmpty() {
|
||||
data.m_size = 0;
|
||||
data.m_capacity = 15;
|
||||
data.m_smallStorage[0] = 0;
|
||||
}
|
||||
|
||||
void StringImpl::free() {
|
||||
if (data.m_capacity > 15) {
|
||||
delete data.m_bigStorage;
|
||||
}
|
||||
}
|
||||
|
||||
char* StringImpl::getStorage() {
|
||||
return data.m_capacity <= 15 ? data.m_smallStorage.data() : data.m_bigStorage;
|
||||
}
|
||||
void StringImpl::setStorage(const std::string_view str) {
|
||||
data.m_size = data.m_capacity = str.size();
|
||||
if (str.size() <= 15) {
|
||||
data.m_capacity = 15;
|
||||
} else {
|
||||
data.m_bigStorage = static_cast<char*>(operator new(str.size() + 1));
|
||||
}
|
||||
std::memcpy(getStorage(), str.data(), str.size());
|
||||
getStorage()[str.size()] = 0;
|
||||
}
|
||||
|
||||
size_t StringImpl::getSize() {
|
||||
return data.m_size;
|
||||
}
|
||||
void StringImpl::setSize(size_t size) {
|
||||
data.m_size = size;
|
||||
}
|
||||
|
||||
size_t StringImpl::getCapacity() {
|
||||
return data.m_capacity;
|
||||
}
|
||||
void StringImpl::setCapacity(size_t cap) {
|
||||
data.m_capacity = cap;
|
||||
}
|
||||
}
|
|
@ -770,7 +770,7 @@ ServerRequest<std::unordered_set<std::string>> server::getTags(bool useCache) {
|
|||
);
|
||||
}
|
||||
|
||||
ServerRequest<std::optional<ServerModUpdate>> server::checkUpdates(Mod* mod) {
|
||||
ServerRequest<std::optional<ServerModUpdate>> server::checkUpdates(Mod const* mod) {
|
||||
return checkAllUpdates().map(
|
||||
[mod](Result<std::vector<ServerModUpdate>, ServerError>* result) -> Result<std::optional<ServerModUpdate>, ServerError> {
|
||||
if (result->isOk()) {
|
||||
|
|
|
@ -150,7 +150,7 @@ namespace server {
|
|||
ServerRequest<ByteVector> getModLogo(std::string const& id, bool useCache = true);
|
||||
ServerRequest<std::unordered_set<std::string>> getTags(bool useCache = true);
|
||||
|
||||
ServerRequest<std::optional<ServerModUpdate>> checkUpdates(Mod* mod);
|
||||
ServerRequest<std::optional<ServerModUpdate>> checkUpdates(Mod const* mod);
|
||||
ServerRequest<std::vector<ServerModUpdate>> checkAllUpdates(bool useCache = true);
|
||||
|
||||
void clearServerCaches(bool clearGlobalCaches = false);
|
||||
|
|
|
@ -66,12 +66,17 @@ void geode::openSupportPopup(ModMetadata const& metadata) {
|
|||
}
|
||||
|
||||
void geode::openInfoPopup(Mod* mod) {
|
||||
// TODO
|
||||
// LocalModInfoPopup::create(mod, nullptr)->show();
|
||||
ModPopup::create(mod)->show();
|
||||
}
|
||||
void geode::openIndexPopup(Mod* mod) {
|
||||
// deprecated func
|
||||
openInfoPopup(mod);
|
||||
}
|
||||
|
||||
void geode::openIndexPopup(Mod* mod) {
|
||||
ModPopup::create(mod)->show();
|
||||
void geode::openChangelogPopup(Mod* mod) {
|
||||
auto popup = ModPopup::create(mod);
|
||||
popup->loadTab(ModPopup::Tab::Changelog);
|
||||
popup->show();
|
||||
}
|
||||
|
||||
void geode::openSettingsPopup(Mod* mod) {
|
||||
|
|
|
@ -20,7 +20,7 @@ $on_mod(Loaded) {
|
|||
ColorProvider::get()->define("mod-list-tab-deselected-bg"_spr, { 26, 24, 29, 255 });
|
||||
ColorProvider::get()->define("mod-list-tab-selected-bg"_spr, { 168, 147, 185, 255 });
|
||||
ColorProvider::get()->define("mod-list-tab-selected-bg-alt"_spr, { 147, 163, 185, 255 });
|
||||
ColorProvider::get()->define("mod-list-featured-color"_spr, { 255, 255, 120, 255 });
|
||||
ColorProvider::get()->define("mod-list-featured-color"_spr, { 240, 211, 42, 255 });
|
||||
ColorProvider::get()->define("mod-list-enabled"_spr, { 120, 255, 100, 255 });
|
||||
ColorProvider::get()->define("mod-list-disabled"_spr, { 255, 120, 100, 255 });
|
||||
ColorProvider::get()->define("mod-list-recommended-bg"_spr, ccc3(25, 255, 167));
|
||||
|
@ -28,6 +28,7 @@ $on_mod(Loaded) {
|
|||
ColorProvider::get()->define("mod-list-recommended-by-2"_spr, ccc3(47, 255, 255));
|
||||
ColorProvider::get()->define("mod-problems-item-bg"_spr, { 255, 255, 255, 15 });
|
||||
ColorProvider::get()->define("mod-developer-item-bg"_spr, { 255, 255, 255, 15 });
|
||||
ColorProvider::get()->define("mod-list-paid-color"_spr, { 0, 255, 63, 255 });
|
||||
|
||||
// Only used when GD theme is active
|
||||
ColorProvider::get()->define("mods-layer-gd-bg"_spr, { 0, 102, 255, 255 });
|
||||
|
|
|
@ -53,6 +53,7 @@ bool ModItem::init(ModSource&& source) {
|
|||
|
||||
m_titleLabel = CCLabelBMFont::create(m_source.getMetadata().getName().c_str(), "bigFont.fnt");
|
||||
m_titleLabel->setID("title-label");
|
||||
m_titleLabel->setLayoutOptions(AxisLayoutOptions::create()->setScalePriority(1));
|
||||
m_titleContainer->addChild(m_titleLabel);
|
||||
|
||||
m_versionLabel = CCLabelBMFont::create("", "bigFont.fnt");
|
||||
|
@ -182,16 +183,14 @@ bool ModItem::init(ModSource&& source) {
|
|||
},
|
||||
[this](server::ServerModMetadata const& metadata) {
|
||||
if (metadata.featured) {
|
||||
auto starBG = CCScale9Sprite::createWithSpriteFrameName("GJ_colorBtn_001.png");
|
||||
starBG->setContentSize({ 50, 38 });
|
||||
starBG->setColor(to3B(ColorProvider::get()->color("mod-list-featured-color"_spr)));
|
||||
starBG->setOpacity(45);
|
||||
|
||||
auto star = CCSprite::createWithSpriteFrameName("GJ_starsIcon_001.png");
|
||||
starBG->addChildAtPosition(star, Anchor::Center);
|
||||
starBG->setID("star-bg");
|
||||
|
||||
m_titleContainer->addChild(starBG);
|
||||
auto star = CCSprite::createWithSpriteFrameName("tag-featured.png"_spr);
|
||||
star->setLayoutOptions(AxisLayoutOptions::create()->setScaleLimits(.1f, .8f));
|
||||
m_titleContainer->addChild(star);
|
||||
}
|
||||
if (metadata.tags.contains("paid")) {
|
||||
auto paidModLabel = CCSprite::createWithSpriteFrameName("tag-paid.png"_spr);
|
||||
paidModLabel->setLayoutOptions(AxisLayoutOptions::create()->setScaleLimits(.1f, .8f));
|
||||
m_titleContainer->addChild(paidModLabel);
|
||||
}
|
||||
|
||||
// Show mod download count here already so people can make informed decisions
|
||||
|
@ -338,9 +337,15 @@ void ModItem::updateState() {
|
|||
[this](server::ServerModMetadata const& metadata) {
|
||||
m_bg->setColor(isGeodeTheme() ? ccWHITE : ccBLACK);
|
||||
m_bg->setOpacity(isGeodeTheme() ? 25 : 90);
|
||||
|
||||
if (metadata.tags.contains("paid")) {
|
||||
m_bg->setColor("mod-list-paid-color"_cc3b);
|
||||
m_bg->setOpacity(55);
|
||||
}
|
||||
|
||||
if (isGeodeTheme() && metadata.featured) {
|
||||
m_bg->setColor("mod-list-featured-color"_cc3b);
|
||||
m_bg->setOpacity(40);
|
||||
m_bg->setOpacity(65);
|
||||
}
|
||||
},
|
||||
[this](ModSuggestion const& suggestion) {
|
||||
|
@ -449,6 +454,22 @@ void ModItem::onCheckUpdates(typename server::ServerRequest<std::optional<server
|
|||
}
|
||||
|
||||
void ModItem::onView(CCObject*) {
|
||||
// This is a local static and not a mod saved value because we might want
|
||||
// to periodically remind users that paid mods are paid
|
||||
static bool shownPaidNotif = false;
|
||||
if (m_source.asServer() && m_source.asServer()->tags.contains("paid") && !shownPaidNotif) {
|
||||
shownPaidNotif = true;
|
||||
return FLAlertLayer::create(
|
||||
nullptr,
|
||||
"Paid Content",
|
||||
"This mod contains <cg>Paid Content</c>. This means that some or all "
|
||||
"features of the mod <cj>require money to use</c>.\n\n"
|
||||
"<cy>Geode does not handle any payments. The mod handles all transactions in their own way.</c>\n\n"
|
||||
"<cp>The paid content may not be available in your country.</c>",
|
||||
"OK", nullptr, 360
|
||||
)->show();
|
||||
}
|
||||
|
||||
// Always open up the popup for the installed mod page if that is possible
|
||||
ModPopup::create(m_source.convertForPopup())->show();
|
||||
}
|
||||
|
|
|
@ -19,6 +19,11 @@ bool ConfirmUninstallPopup::setup(Mod* mod) {
|
|||
deleteDataLabel->setScale(.35f);
|
||||
m_buttonMenu->addChildAtPosition(deleteDataLabel, Anchor::Center, ccp(-70, -15), ccp(0, .5f));
|
||||
|
||||
if (mod->isInternal()) {
|
||||
deleteDataLabel->setString("Delete ALL mods and their save data");
|
||||
deleteDataLabel->setScale(0.275f);
|
||||
}
|
||||
|
||||
m_deleteDataToggle = CCMenuItemToggler::createWithStandardSprites(this, nullptr, .6f);
|
||||
m_buttonMenu->addChildAtPosition(m_deleteDataToggle, Anchor::Center, ccp(-88, -15));
|
||||
|
||||
|
|
|
@ -648,9 +648,12 @@ void ModPopup::updateState() {
|
|||
|
||||
if (asMod && asMod->isInternal()) {
|
||||
m_enableBtn->setVisible(false);
|
||||
// you can uninstall loader ingame just fine on windows
|
||||
#if !defined(GEODE_IS_WINDOWS)
|
||||
m_uninstallBtn->setVisible(false);
|
||||
m_installStatusLabel->setString("N/A");
|
||||
m_installStatusLabel->setVisible(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
auto download = server::ModDownloadManager::get()->getDownload(m_source.getID());
|
||||
|
|
|
@ -10,13 +10,14 @@
|
|||
using namespace geode::prelude;
|
||||
|
||||
class ModPopup : public GeodePopup<ModSource&&> {
|
||||
protected:
|
||||
public:
|
||||
enum class Tab {
|
||||
Details,
|
||||
Changelog,
|
||||
Versions,
|
||||
};
|
||||
|
||||
protected:
|
||||
ModSource m_source;
|
||||
CCNode* m_stats;
|
||||
CCNode* m_tags;
|
||||
|
@ -51,7 +52,6 @@ protected:
|
|||
void onLoadTags(typename server::ServerRequest<std::unordered_set<std::string>>::Event* event);
|
||||
void onCheckUpdates(typename server::ServerRequest<std::optional<server::ServerModUpdate>>::Event* event);
|
||||
|
||||
void loadTab(Tab tab);
|
||||
void onTab(CCObject* sender);
|
||||
void onEnable(CCObject*);
|
||||
void onInstall(CCObject*);
|
||||
|
@ -63,5 +63,6 @@ protected:
|
|||
void onSupport(CCObject*);
|
||||
|
||||
public:
|
||||
void loadTab(Tab tab);
|
||||
static ModPopup* create(ModSource&& src);
|
||||
};
|
||||
|
|
|
@ -95,6 +95,10 @@ const char* geode::baseEnumToString(EditorBaseColor value) {
|
|||
case EditorBaseColor::Teal: return "Teal";
|
||||
case EditorBaseColor::Aqua: return "Aqua";
|
||||
case EditorBaseColor::Cyan: return "Cyan";
|
||||
case EditorBaseColor::Magenta: return "Magenta";
|
||||
case EditorBaseColor::DimGreen: return "DimGreen";
|
||||
case EditorBaseColor::BrightGreen: return "BrightGreen";
|
||||
case EditorBaseColor::Salmon: return "Salmon";
|
||||
}
|
||||
return "Unknown";
|
||||
}
|
||||
|
|
|
@ -335,24 +335,45 @@ struct MDParser {
|
|||
renderer->popDecoFlags();
|
||||
renderer->popColor();
|
||||
}
|
||||
else if (s_lastImage.size()) {
|
||||
else if (!s_lastImage.empty()) {
|
||||
bool isFrame = false;
|
||||
|
||||
std::vector<std::string> imgArguments = utils::string::split(s_lastImage, "&");
|
||||
s_lastImage = imgArguments.at(0);
|
||||
const auto splitOnce = [](const std::string& str, char delim) -> std::pair<std::string, std::string> {
|
||||
const auto pos = str.find(delim);
|
||||
if (pos == std::string::npos) {
|
||||
return { str, {} };
|
||||
}
|
||||
return { str.substr(0, pos), str.substr(pos + 1) };
|
||||
};
|
||||
|
||||
imgArguments.erase(imgArguments.begin()); //remove the image path
|
||||
// key value pair of arguments
|
||||
std::vector<std::pair<std::string, std::string>> imgArguments;
|
||||
auto split = splitOnce(s_lastImage, '?');
|
||||
s_lastImage = split.first;
|
||||
|
||||
// TODO: remove this in v4.0.0
|
||||
// check if this image is using the old format "my.mod/image.png&scale:0.5"
|
||||
// this will be deprecated and then removed in the future
|
||||
if (utils::string::contains(s_lastImage, "&")) {
|
||||
split = splitOnce(s_lastImage, '&');
|
||||
s_lastImage = split.first;
|
||||
imgArguments = ranges::map<decltype(imgArguments)>(utils::string::split(split.second, "&"), [&](auto str) {
|
||||
return splitOnce(str, ':');
|
||||
});
|
||||
} else {
|
||||
// new format "my.mod/image.png?scale=0.5"
|
||||
imgArguments = ranges::map<decltype(imgArguments)>(utils::string::split(split.second, "&"), [&](auto str) {
|
||||
return splitOnce(str, '=');
|
||||
});
|
||||
}
|
||||
|
||||
float spriteScale = 1.0f;
|
||||
|
||||
for(std::string arg : imgArguments){
|
||||
if(utils::string::startsWith(arg, "scale:")){
|
||||
std::string scaleValue = arg.substr(arg.find(":") + 1);
|
||||
std::stringstream s(scaleValue);
|
||||
|
||||
float scale;
|
||||
if (s >> scale) { //if valid float, put into spriteScale
|
||||
spriteScale = scale;
|
||||
for (auto [key, value] : imgArguments) {
|
||||
if (key == "scale") {
|
||||
auto scaleRes = utils::numFromString<float>(value);
|
||||
if (scaleRes) {
|
||||
spriteScale = *scaleRes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -368,7 +389,7 @@ struct MDParser {
|
|||
else {
|
||||
spr = CCSprite::create(s_lastImage.c_str());
|
||||
}
|
||||
if (spr) {
|
||||
if (spr && spr->getUserObject("geode.texture-loader/fallback") == nullptr) {
|
||||
spr->setScale(spriteScale);
|
||||
renderer->renderNode(spr);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ bool TextInput::init(float width, std::string const& placeholder, std::string co
|
|||
m_bgSprite->setContentSize({ width * 2, HEIGHT * 2 });
|
||||
this->addChildAtPosition(m_bgSprite, Anchor::Center);
|
||||
|
||||
m_input = CCTextInputNode::create(width, HEIGHT, placeholder.c_str(), 24, font.c_str());
|
||||
m_input = CCTextInputNode::create(width - 10.f, HEIGHT, placeholder.c_str(), 24, font.c_str());
|
||||
m_input->setLabelPlaceholderColor({ 150, 150, 150 });
|
||||
m_input->setLabelPlaceholderScale(.5f);
|
||||
m_input->setMaxLabelScale(.6f);
|
||||
|
@ -132,9 +132,12 @@ void TextInput::setPasswordMode(bool enable) {
|
|||
m_input->refreshLabel();
|
||||
}
|
||||
void TextInput::setWidth(float width) {
|
||||
m_input->m_maxLabelWidth = width;
|
||||
m_input->setContentWidth(width * 2);
|
||||
this->setContentWidth(width);
|
||||
m_input->m_maxLabelWidth = width - 10.f;
|
||||
m_input->setContentWidth(width);
|
||||
m_bgSprite->setContentWidth(width * 2);
|
||||
m_input->setPositionX(width / 2.f);
|
||||
m_bgSprite->setPositionX(width / 2.f);
|
||||
}
|
||||
void TextInput::setDelegate(TextInputDelegate* delegate, std::optional<int> tag) {
|
||||
m_input->m_delegate = delegate;
|
||||
|
|
|
@ -279,9 +279,9 @@ WebTask WebRequest::send(std::string_view method, std::string_view url) {
|
|||
|
||||
// Add parameters to the URL and pass it to curl
|
||||
auto url = impl->m_url;
|
||||
bool first = true;
|
||||
for (auto param : impl->m_urlParameters) {
|
||||
url += (first ? "?" : "&") + urlParamEncode(param.first) + "=" + urlParamEncode(param.second);
|
||||
bool first = url.find('?') == std::string::npos;
|
||||
for (auto& [key, value] : impl->m_urlParameters) {
|
||||
url += (first ? "?" : "&") + urlParamEncode(key) + "=" + urlParamEncode(value);
|
||||
first = false;
|
||||
}
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
|
@ -306,6 +306,7 @@ WebTask WebRequest::send(std::string_view method, std::string_view url) {
|
|||
} else if (impl->m_method == "POST") {
|
||||
// curl_easy_perform would freeze on a POST request with no fields, so set it to an empty string
|
||||
// why? god knows
|
||||
// SMJS: because the stream isn't complete without a body according to the spec
|
||||
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, "");
|
||||
}
|
||||
|
||||
|
@ -470,13 +471,39 @@ WebTask WebRequest::patch(std::string_view url) {
|
|||
}
|
||||
|
||||
WebRequest& WebRequest::header(std::string_view name, std::string_view value) {
|
||||
if (name == "User-Agent") {
|
||||
userAgent(value);
|
||||
|
||||
return *this;
|
||||
} if (name == "Accept-Encoding") {
|
||||
acceptEncoding(value);
|
||||
|
||||
return *this;
|
||||
} if (name == "Keep-Alive") {
|
||||
const size_t timeoutPos = value.find("timeout");
|
||||
|
||||
if (timeoutPos != std::string::npos) {
|
||||
// At this point idc what happens if I get NPOS or string ends, you shouldn't custom format a spec header
|
||||
const size_t numStart = value.find('=', timeoutPos) + 1;
|
||||
const size_t comma = value.find(',', numStart);
|
||||
const size_t numLength = (comma == std::string::npos ? value.size() : comma) - numStart;
|
||||
|
||||
timeout(std::chrono::seconds(std::stol(std::string(value.substr(numStart, numLength)))));
|
||||
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
m_impl->m_headers.insert_or_assign(std::string(name), std::string(value));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
WebRequest& WebRequest::param(std::string_view name, std::string_view value) {
|
||||
m_impl->m_urlParameters.insert_or_assign(std::string(name), std::string(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
WebRequest& WebRequest::userAgent(std::string_view name) {
|
||||
m_impl->m_userAgent = name;
|
||||
return *this;
|
||||
|
@ -540,3 +567,31 @@ WebRequest& WebRequest::bodyJSON(matjson::Value const& json) {
|
|||
m_impl->m_body = ByteVector { str.begin(), str.end() };
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::string WebRequest::getMethod() const {
|
||||
return m_impl->m_method;
|
||||
}
|
||||
|
||||
std::string WebRequest::getUrl() const {
|
||||
return m_impl->m_url;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string> WebRequest::getHeaders() const {
|
||||
return m_impl->m_headers;
|
||||
}
|
||||
|
||||
std::unordered_map<std::string, std::string> WebRequest::getUrlParams() const {
|
||||
return m_impl->m_urlParameters;
|
||||
}
|
||||
|
||||
std::optional<ByteVector> WebRequest::getBody() const {
|
||||
return m_impl->m_body;
|
||||
}
|
||||
|
||||
std::optional<std::chrono::seconds> WebRequest::getTimeout() const {
|
||||
return m_impl->m_timeout;
|
||||
}
|
||||
|
||||
HttpVersion WebRequest::getHttpVersion() const {
|
||||
return m_impl->m_httpVersion;
|
||||
}
|