diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..176a458f9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto diff --git a/.github/.gitattributes b/.github/.gitattributes new file mode 100644 index 000000000..4c92bf546 --- /dev/null +++ b/.github/.gitattributes @@ -0,0 +1,2 @@ +actions/**/*.yml text eol=lf +workflows/*.yml text eol=lf diff --git a/.github/actions/automatic-test/action.yml b/.github/actions/automatic-test/action.yml deleted file mode 100644 index 4b5326cb0..000000000 --- a/.github/actions/automatic-test/action.yml +++ /dev/null @@ -1,24 +0,0 @@ -name: 'Automatic Test' -description: 'Check for obvious errors.' - -runs: - using: "composite" - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/build-love - with: - file-path: Techmino.love - - name: Download love - shell: bash - run: | - curl -L https://github.com/love2d/love/releases/download/11.3/love-11.3-linux-x86_64.tar.gz | tar xz - - name: Prepare PulseAudio - shell: bash - run: | - sudo apt-get update - sudo apt-get install pulseaudio pulseaudio-utils pavucontrol alsa-oss alsa-utils -y - - name: Run automated test - uses: GabrielBB/xvfb-action@v1 - with: - run: | - ./dest/love Techmino.love --test \ No newline at end of file diff --git a/.github/actions/build-android/action.yml b/.github/actions/build-android/action.yml deleted file mode 100644 index 889cdc420..000000000 --- a/.github/actions/build-android/action.yml +++ /dev/null @@ -1,102 +0,0 @@ -name: 'build Android' -description: 'build Android package' -inputs: - type: - required: true - apkCode: - required: true - name: - required: true - file-path: - required: true - SIGNING_KEY: - required: true - KEY_STORE_PASSWORD: - required: true - ALIAS: - required: true - KEY_PASSWORD: - required: true -runs: - using: "composite" - steps: - - uses: actions/setup-java@v2 - with: - distribution: 'adopt' - java-version: '8' - - name: Clone love-android - shell: bash - run: | - git clone --recurse-submodules https://github.com/26F-Studio/love-android -b CI --depth 1 --shallow-submodules - - uses: ./.github/actions/build-love - with: - file-path: love-android/app/src/main/assets/game.love - - name: Download ColdClear arm64-v8a - uses: ./.github/actions/get-cc - with: - arch: android_aarch64 - dir: ColdClear/arm64-v8a - - name: Process ColdClear arm64-v8a - shell: bash - run: | - mkdir -p love-android/app/libs/arm64-v8a - mv ColdClear/arm64-v8a/love-11.3-android/lib/arm64-v8a/libcold_clear.so love-android/app/libs/arm64-v8a - mkdir -p libAndroid/arm64-v8a - mv ColdClear/arm64-v8a/libs/arm64-v8a/libCCloader.so libAndroid/arm64-v8a - - name: Download ColdClear armeabi-v7a - uses: ./.github/actions/get-cc - with: - arch: android_armv7 - dir: ColdClear/armeabi-v7a - - name: Process ColdClear armeabi-v7a - shell: bash - run: | - mkdir -p love-android/app/libs/armeabi-v7a - mv ColdClear/armeabi-v7a/love-11.3-android/lib/armeabi-v7a/libcold_clear.so love-android/app/libs/armeabi-v7a - mkdir -p libAndroid/armeabi-v7a - mv ColdClear/armeabi-v7a/libs/armeabi-v7a/libCCloader.so libAndroid/armeabi-v7a - - name: Pack ColdClear - shell: bash - run: | - 7z a -tzip love-android/app/src/main/assets/game.love libAndroid - - name: update Android information - shell: python - run: | - if '${{ inputs.type }}' == 'Release': - appName = 'Techmino' - packageName = 'org.love2d.MrZ.Techmino' - edition = 'release' - elif '${{ inputs.type }}' == 'Snapshot': - appName = 'Techmino_Snapshot' - packageName = 'org.love2d.MrZ.Techmino.Snapshot' - edition = 'snapshot' - with open('./love-android/app/src/main/AndroidManifest.xml', "r+", encoding='utf-8') as file: - data = file.read() - data = data\ - .replace('@appName', appName)\ - .replace('@edition', edition) - file.seek(0) - file.truncate() - file.write(data) - with open("./love-android/app/build.gradle", "r+", encoding='utf-8') as file: - data = file.read() - data = data\ - .replace('@packageName', packageName)\ - .replace('@versionCode', '${{ inputs.apkCode }}')\ - .replace('@versionName', '${{ inputs.name }}')\ - .replace('@storePassword', '${{ inputs.KEY_STORE_PASSWORD }}')\ - .replace('@keyAlias', '${{ inputs.ALIAS }}')\ - .replace('@keyPassword', '${{ inputs.KEY_PASSWORD }}') - file.seek(0) - file.truncate() - file.write(data) - - name: Build Techmino - shell: bash - run: | - echo "${{ inputs.SIGNING_KEY }}" | base64 -d > love-android/app/android.keystore - chmod 777 love-android/gradlew - cd love-android/ - ./gradlew assembleRelease - - name: rename apk - shell: bash - run: mv love-android/app/build/outputs/apk/release/app-release.apk ${{ inputs.file-path }} diff --git a/.github/actions/build-ios/action.yml b/.github/actions/build-ios/action.yml deleted file mode 100644 index fa1ddcede..000000000 --- a/.github/actions/build-ios/action.yml +++ /dev/null @@ -1,96 +0,0 @@ -name: 'build iOS' -description: 'build iOS package' -inputs: - name: - required: true - description: "Version name" - type: - required: true - description: "Build type" - APPLE_API_ID: - required: true - description: "API key ID" - APPLE_API_ISSUER: - required: true - description: "API issuer ID" - APPLE_API_KEY: - required: true - description: "API key content" - APPLE_APP_BUILD: - required: true - description: "Build number" - APPLE_APP_CHANGELOG: - required: true - description: "Changelog" - APPLE_APP_ID: - required: true - description: "AppStore Apple ID" - APPLE_APP_IDENTIFIER: - required: true - description: "Bundle ID" - APPLE_APP_PROFILE: - required: true - description: "Provisioning Profile specifer" - APPLE_KEYCHAIN_NAME: - required: true - description: "Temporary keychain name" - APPLE_KEYCHAIN_PWD: - required: true - description: "Temporary keychain password" - FASTLANE_DISCORD_WEBHOOK: - required: true - description: "Fastlane Discord webhook" - FASTLANE_ACTION_ID: - required: true - description: "Fastlane Action ID" - FASTLANE_MATCH_PWD: - required: true - description: "Fastlane Match description password" - FASTLANE_MATCH_TOKEN: - required: true - description: "Fastlane Match Github token" -runs: - using: "composite" - steps: - - uses: ./.github/actions/build-love - - name: Checkout source codes - uses: actions/checkout@v2 - with: - repository: '26F-Studio/Techmino-iOS' - path: 'Techmino-iOS' - - name: Download CCloader - uses: ./.github/actions/get-cc - with: - arch: iOS - - name: Update source codes - shell: bash - run: | - mv Techmino.love Techmino-iOS/platform/xcode - mv libcold_clear.a Techmino-iOS/platform/xcode - mv libCCloader.a Techmino-iOS/platform/xcode - - name: Run fastlane - uses: maierj/fastlane-action@v2.0.1 - with: - lane: '${{ inputs.type }}' - subdirectory: 'Techmino-iOS/platform/xcode' - env: - ACTION_ID: '${{ inputs.FASTLANE_ACTION_ID }}' - API_ID: '${{ inputs.APPLE_API_ID }}' - API_ISSUER: '${{ inputs.APPLE_API_ISSUER }}' - API_KEY: '${{ inputs.APPLE_API_KEY }}' - APP_BUILD: '${{ inputs.APPLE_APP_BUILD }}' - APP_CHANGELOG: '${{ inputs.APPLE_APP_CHANGELOG }}' - APP_ID: '${{ inputs.APPLE_APP_ID }}' - APP_IDENTIFIER: '${{ inputs.APPLE_APP_IDENTIFIER }}' - APP_PROFILE: '${{ inputs.APPLE_APP_PROFILE }}' - APP_VERSION: '${{ inputs.name }}' - DISCORD_WEBHOOK: '${{ inputs.FASTLANE_DISCORD_WEBHOOK }}' - KEYCHAIN_NAME: '${{ inputs.APPLE_KEYCHAIN_NAME }}' - KEYCHAIN_PWD: '${{ inputs.APPLE_KEYCHAIN_PWD }}' - MATCH_PASSWORD: '${{ inputs.FASTLANE_MATCH_PWD }}' - MATCH_TOKEN: '${{ inputs.FASTLANE_MATCH_TOKEN }}' - - name: Move ipa - shell: bash - run: | - mv Techmino-iOS/platform/xcode/Techmino.ipa Techmino.ipa - \ No newline at end of file diff --git a/.github/actions/build-linux/action.yml b/.github/actions/build-linux/action.yml deleted file mode 100644 index 66090a866..000000000 --- a/.github/actions/build-linux/action.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: 'build Linux' -description: 'build Linux package' -inputs: - file-path: - required: false - default: Techmino.AppImage - icon: - required: true -runs: - using: "composite" - steps: - - name: Download AppImageKit - shell: bash - run: | - curl -OL https://github.com/AppImage/AppImageKit/releases/download/13/appimagetool-x86_64.AppImage - - name: Download love - shell: bash - run: | - curl -OL https://github.com/love2d/love/releases/download/11.3/love-11.3-x86_64.AppImage - chmod 777 love-11.3-x86_64.AppImage - ./love-11.3-x86_64.AppImage --appimage-extract - - name: Download ColdClear - uses: ./.github/actions/get-cc - with: - arch: linux - - name: Pack Techmino - shell: bash - run: | - rm -rf squashfs-root/love squashfs-root/love.desktop squashfs-root/love.svg squashfs-root/.DirIcon - mv .github/build/Linux/love.template squashfs-root/love - mv .github/build/Linux/Techmino.desktop.template squashfs-root/Techmino.desktop - mv ${{ inputs.icon }} squashfs-root/icon.png - cp squashfs-root/icon.png squashfs-root/.DirIcon - chmod 777 squashfs-root/love - mkdir -p squashfs-root/usr/share/Techmino - mv media parts Zframework conf.lua main.lua version.lua legals.md license.txt squashfs-root/usr/share/Techmino - mv CCloader.so squashfs-root/usr/share/Techmino - mv libcold_clear.so squashfs-root/usr/lib - chmod 777 appimagetool-x86_64.AppImage - ./appimagetool-x86_64.AppImage squashfs-root ${{ inputs.file-path }} diff --git a/.github/actions/build-love/action.yml b/.github/actions/build-love/action.yml deleted file mode 100644 index 623dbc7a2..000000000 --- a/.github/actions/build-love/action.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: 'build love' -description: 'build love file' -inputs: - file-path: - required: true - default: Techmino.love -runs: - using: "composite" - steps: - - run: 7z a -tzip ${{ inputs.file-path }} media parts Zframework conf.lua main.lua version.lua legals.md license.txt - shell: bash diff --git a/.github/actions/build-macos/action.yml b/.github/actions/build-macos/action.yml deleted file mode 100644 index dcf1ed8c4..000000000 --- a/.github/actions/build-macos/action.yml +++ /dev/null @@ -1,152 +0,0 @@ -name: 'build Mac OS' -description: 'build Mac OS package' -inputs: - name: - required: true - description: "Version name" - icon: - required: true - description: "App icons (.icns)" - APPLE_API_ID: - required: true - description: "API key ID" - APPLE_API_ISSUER: - required: true - description: "API issuer ID" - APPLE_API_KEY: - required: true - description: "API key content" - APPLE_APP_IDENTIFIER: - required: true - description: "Bundle ID" - APPLE_KEYCHAIN_NAME: - required: true - description: "Temporary keychain name" - APPLE_KEYCHAIN_PWD: - required: true - description: "Temporary keychain password" - FASTLANE_MATCH_PWD: - required: true - description: "Fastlane Match description password" - FASTLANE_MATCH_TOKEN: - required: true - description: "Fastlane Match Github token" -runs: - using: "composite" - steps: - - uses: ./.github/actions/build-love - - name: Checkout template - uses: actions/checkout@v2 - with: - repository: '26F-Studio/Techmino-macOS' - path: 'Techmino-macOS' - - name: Download ColdClear - uses: ./.github/actions/get-cc - with: - arch: macOS - - name: Fastlane match - uses: maierj/fastlane-action@v2.0.1 - with: - lane: 'get_cert' - subdirectory: 'Techmino-macOS' - env: - API_ID: '${{ inputs.APPLE_API_ID }}' - API_ISSUER: '${{ inputs.APPLE_API_ISSUER }}' - API_KEY: '${{ inputs.APPLE_API_KEY }}' - APP_IDENTIFIER: '${{ inputs.APPLE_APP_IDENTIFIER }}' - KEYCHAIN_NAME: '${{ inputs.APPLE_KEYCHAIN_NAME }}' - KEYCHAIN_PWD: '${{ inputs.APPLE_KEYCHAIN_PWD }}' - MATCH_PASSWORD: '${{ inputs.FASTLANE_MATCH_PWD }}' - MATCH_TOKEN: '${{ inputs.FASTLANE_MATCH_TOKEN }}' - - name: Modify template - shell: python - run: | - import datetime - from io import open - thisYear = str(datetime.datetime.today().year) - with open('./.github/build/macOS/info.plist.template', 'r', encoding='utf-8') as file: - data = file.read() - data = data\ - .replace('@versionName', '${{ inputs.name }}'[1:])\ - .replace('@thisYear', thisYear)\ - .replace('@bundleId', '${{ inputs.APPLE_APP_IDENTIFIER }}') - with open('./Techmino-macOS/Techmino.app/Contents/info.plist', 'w+', encoding='utf-8') as file: - file.write(data) - - name: Pack - shell: bash - run: | - mv Techmino.love Techmino-macOS/Techmino.app/Contents/Resources - mv CCloader.dylib Techmino-macOS/Techmino.app/Contents/Frameworks - mv ${{ inputs.icon }} Techmino-macOS/Techmino.app/Contents/Resources/iconfile.icns - - chmod +x Techmino-macOS/Techmino.app/Contents/Frameworks/CCloader.dylib - chmod +x Techmino-macOS/Techmino.app/Contents/MacOS/love - - name: Codesign executable - shell: bash - run: | - security unlock-keychain -p ${{ inputs.TEMP_KEYCHAIN_PASSWORD }} \ - ~/Library/Keychains/${{ inputs.TEMP_KEYCHAIN_USER }}-db - - [[ $(security find-identity) =~ ([0-9A-F]{40}) ]] - - codesign --timestamp --force --strict --deep -v \ - --options runtime \ - -s ${BASH_REMATCH[1]} \ - --entitlements Techmino-macOS/love.entitlements \ - Techmino-macOS/Techmino.app - - name: Fastlane notarize - uses: maierj/fastlane-action@v2.0.1 - with: - lane: 'make_safe' - subdirectory: 'Techmino-macOS' - env: - API_ID: '${{ inputs.APPLE_API_ID }}' - API_ISSUER: '${{ inputs.APPLE_API_ISSUER }}' - API_KEY: '${{ inputs.APPLE_API_KEY }}' - APP_IDENTIFIER: '${{ inputs.APPLE_APP_IDENTIFIER }}' - NOTARIZE_OBJECT: 'Techmino.app' - - name: Create DMG file - shell: bash - run: | - brew install create-dmg - create-dmg \ - --volname "Techmino for MacOS" \ - --volicon "./.github/build/macOS/Techminodisk.icns" \ - --window-pos 200 120 \ - --window-size 800 500 \ - --icon-size 100 \ - --icon "Techmino.app" 239 203 \ - --background ".github/build/macOS/backgroundImage.tiff" \ - --hide-extension "Techmino.app" \ - --app-drop-link 565 203 \ - "Techmino-macOS/Techmino-macOS.dmg" \ - "Techmino-macOS/Techmino.app/" - - name: Codesign DMG - shell: bash - run: | - security unlock-keychain -p ${{ inputs.TEMP_KEYCHAIN_PASSWORD }} \ - ~/Library/Keychains/${{ inputs.TEMP_KEYCHAIN_USER }}-db - - [[ $(security find-identity) =~ ([0-9A-F]{40}) ]] - - codesign --timestamp --force --strict --deep -v \ - --options runtime \ - -s ${BASH_REMATCH[1]} \ - --entitlements Techmino-macOS/love.entitlements \ - Techmino-macOS/Techmino-macOS.dmg - - name: Fastlane notarize - uses: maierj/fastlane-action@v2.0.1 - with: - lane: 'make_safe' - subdirectory: 'Techmino-macOS' - env: - API_ID: '${{ inputs.APPLE_API_ID }}' - API_ISSUER: '${{ inputs.APPLE_API_ISSUER }}' - API_KEY: '${{ inputs.APPLE_API_KEY }}' - APP_IDENTIFIER: '${{ inputs.APPLE_APP_IDENTIFIER }}' - NOTARIZE_OBJECT: 'Techmino-macOS.dmg' - - name: Finalize - shell: bash - run: | - mv Techmino-macOS/Techmino-macOS.dmg Techmino.dmg - spctl -a -t open --context context:primary-signature -vv Techmino.dmg diff --git a/.github/actions/build-windows/action.yml b/.github/actions/build-windows/action.yml deleted file mode 100644 index 546d3a943..000000000 --- a/.github/actions/build-windows/action.yml +++ /dev/null @@ -1,60 +0,0 @@ -name: 'build Windows' -description: 'build Windows package' -inputs: - love-url: - required: true - love-dir: - required: true - arch: - required: true - version: - required: true - icon: - required: true -runs: - using: "composite" - steps: - - name: Download love - uses: ./.github/actions/get-unzip - with: - url: ${{ inputs.love-url }} - - name: move love - shell: bash - run: mv ${{ inputs.love-dir }} love - - name: Download ColdClear - uses: ./.github/actions/get-cc - with: - arch: ${{ inputs.arch }} - - name: Download ResourceHacker - uses: ./.github/actions/get-unzip - with: - url: http://www.angusj.com/resourcehacker/resource_hacker.zip - - uses: ./.github/actions/build-love - - name: update Windows template - shell: python - run: | - Version = '${{ inputs.version }}'.replace('V', '') - FileVersion = (f"{Version.replace('.', ',')},0") - with open('./.github/build/Windows/Techmino.rc.template', 'r', encoding='utf8') as file: - data = file.read() - data = data\ - .replace('@FileVersion', FileVersion)\ - .replace('@Version', Version) - with open('Techmino.rc', 'w+', encoding='utf8') as file: - file.write(data) - - name: Pack Techmino - shell: pwsh - run: | - cmd /c copy /b .\love\love.exe + .\Techmino.love .\love\Techmino.exe - del .\love\love.exe - del .\love\lovec.exe - del .\love\game.ico - del .\love\love.ico - del .\love\changes.txt - del .\love\readme.txt - move .\cold_clear.dll .\love - move .\CCloader.dll .\love - cmd /c '.\ResourceHacker.exe -open .\love\Techmino.exe -save .\love\Techmino.exe -action delete -mask ICONGROUP,,' - cmd /c '.\ResourceHacker.exe -open .\Techmino.rc -save .\Techmino.res -action compile' - cmd /c '.\ResourceHacker.exe -open .\love\Techmino.exe -save .\love\Techmino.exe -action addoverwrite -res "${{ inputs.icon }}" -mask ICONGROUP,1,' - cmd /c '.\ResourceHacker.exe -open .\love\Techmino.exe -save .\love\Techmino.exe -action addoverwrite -res ".\Techmino.res" -mask VERSIONINFO,1,' diff --git a/.github/actions/get-cc/action.yml b/.github/actions/get-cc/action.yml index 595b1dcb7..ea348ee96 100644 --- a/.github/actions/get-cc/action.yml +++ b/.github/actions/get-cc/action.yml @@ -3,8 +3,8 @@ description: 'download cc into specific dir' inputs: tag: required: false - default: - arch: + default: "11.4.2" + platform: required: true dir: required: false @@ -19,14 +19,14 @@ runs: using: "composite" steps: - run: | - echo "::set-output name=tag::"$(if [ -z "${{ inputs.tag }}" ] + echo "tag="$(if [ -z "${{ inputs.tag }}" ] then curl -w '%{url_effective}' -I -L -s -S https://github.com/${{ inputs.repo }}/releases/latest -o /dev/null | grep -o '\<[^/]*$' else echo ${{ inputs.tag }} - fi) + fi) >> $GITHUB_OUTPUT id: get-tag shell: bash - uses: ./.github/actions/get-unzip with: - url: https://github.com/${{ inputs.repo }}/releases/download/${{ steps.get-tag.outputs.tag }}/${{ inputs.arch }}.zip + url: https://github.com/${{ inputs.repo }}/releases/download/${{ steps.get-tag.outputs.tag }}/${{ inputs.platform }}.zip dir: ${{ inputs.dir }} temp-file: ${{ inputs.temp-file }} diff --git a/.github/build/Linux/Techmino.desktop.template b/.github/build/Linux/Techmino.desktop.template deleted file mode 100644 index bed656e1d..000000000 --- a/.github/build/Linux/Techmino.desktop.template +++ /dev/null @@ -1,8 +0,0 @@ -[Desktop Entry] -Name=Techmino Alpha -Comment=Techmino is fun! -Exec=wrapper-love %f -Type=Application -Categories=Game; -Terminal=false -Icon=icon diff --git a/.github/build/Linux/love.template b/.github/build/Linux/love.template deleted file mode 100644 index 370228276..000000000 --- a/.github/build/Linux/love.template +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -export LOVE_LAUNCHER_LOCATION="$(dirname "$(which "$0")")" -export LD_LIBRARY_PATH="${LOVE_LAUNCHER_LOCATION}/lib/x86_64-linux-gnu:${LOVE_LAUNCHER_LOCATION}/usr/bin:${LOVE_LAUNCHER_LOCATION}/usr/lib:${LOVE_LAUNCHER_LOCATION}/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH" -/sbin/ldconfig -p | grep -q libstdc++ || export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${LOVE_LAUNCHER_LOCATION}/libstdc++/" -exec ${LOVE_BIN_WRAPPER} "${LOVE_LAUNCHER_LOCATION}/usr/bin/love" "${LOVE_LAUNCHER_LOCATION}/usr/share/Techmino" diff --git a/.github/build/Windows/icon.png b/.github/build/Windows/icon.png deleted file mode 100644 index 7a92a48ad..000000000 Binary files a/.github/build/Windows/icon.png and /dev/null differ diff --git a/.github/build/android/dev/res/icon-playstore.png b/.github/build/android/dev/res/icon-playstore.png new file mode 100644 index 000000000..8c7eb6709 Binary files /dev/null and b/.github/build/android/dev/res/icon-playstore.png differ diff --git a/.github/build/android/dev/res/mipmap-anydpi-v26/icon.xml b/.github/build/android/dev/res/mipmap-anydpi-v26/icon.xml new file mode 100644 index 000000000..1ed403703 --- /dev/null +++ b/.github/build/android/dev/res/mipmap-anydpi-v26/icon.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.github/build/android/dev/res/mipmap-anydpi-v26/icon_round.xml b/.github/build/android/dev/res/mipmap-anydpi-v26/icon_round.xml new file mode 100644 index 000000000..1ed403703 --- /dev/null +++ b/.github/build/android/dev/res/mipmap-anydpi-v26/icon_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.github/build/android/dev/res/mipmap-hdpi/icon.png b/.github/build/android/dev/res/mipmap-hdpi/icon.png new file mode 100644 index 000000000..47002e9c6 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-hdpi/icon.png differ diff --git a/.github/build/android/dev/res/mipmap-hdpi/icon_background.png b/.github/build/android/dev/res/mipmap-hdpi/icon_background.png new file mode 100644 index 000000000..6f05b8ad6 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-hdpi/icon_background.png differ diff --git a/.github/build/android/dev/res/mipmap-hdpi/icon_foreground.png b/.github/build/android/dev/res/mipmap-hdpi/icon_foreground.png new file mode 100644 index 000000000..2ae7cd22b Binary files /dev/null and b/.github/build/android/dev/res/mipmap-hdpi/icon_foreground.png differ diff --git a/.github/build/android/dev/res/mipmap-hdpi/icon_round.png b/.github/build/android/dev/res/mipmap-hdpi/icon_round.png new file mode 100644 index 000000000..a74a1029e Binary files /dev/null and b/.github/build/android/dev/res/mipmap-hdpi/icon_round.png differ diff --git a/.github/build/android/dev/res/mipmap-mdpi/icon.png b/.github/build/android/dev/res/mipmap-mdpi/icon.png new file mode 100644 index 000000000..e2803d9fa Binary files /dev/null and b/.github/build/android/dev/res/mipmap-mdpi/icon.png differ diff --git a/.github/build/android/dev/res/mipmap-mdpi/icon_background.png b/.github/build/android/dev/res/mipmap-mdpi/icon_background.png new file mode 100644 index 000000000..08b119c9a Binary files /dev/null and b/.github/build/android/dev/res/mipmap-mdpi/icon_background.png differ diff --git a/.github/build/android/dev/res/mipmap-mdpi/icon_foreground.png b/.github/build/android/dev/res/mipmap-mdpi/icon_foreground.png new file mode 100644 index 000000000..e0b0176a9 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-mdpi/icon_foreground.png differ diff --git a/.github/build/android/dev/res/mipmap-mdpi/icon_round.png b/.github/build/android/dev/res/mipmap-mdpi/icon_round.png new file mode 100644 index 000000000..2d145b854 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-mdpi/icon_round.png differ diff --git a/.github/build/android/dev/res/mipmap-xhdpi/icon.png b/.github/build/android/dev/res/mipmap-xhdpi/icon.png new file mode 100644 index 000000000..c56d513a5 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xhdpi/icon.png differ diff --git a/.github/build/android/dev/res/mipmap-xhdpi/icon_background.png b/.github/build/android/dev/res/mipmap-xhdpi/icon_background.png new file mode 100644 index 000000000..39f0f544a Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xhdpi/icon_background.png differ diff --git a/.github/build/android/dev/res/mipmap-xhdpi/icon_foreground.png b/.github/build/android/dev/res/mipmap-xhdpi/icon_foreground.png new file mode 100644 index 000000000..ef0dcd6b9 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xhdpi/icon_foreground.png differ diff --git a/.github/build/android/dev/res/mipmap-xhdpi/icon_round.png b/.github/build/android/dev/res/mipmap-xhdpi/icon_round.png new file mode 100644 index 000000000..dd43ba714 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xhdpi/icon_round.png differ diff --git a/.github/build/android/dev/res/mipmap-xxhdpi/icon.png b/.github/build/android/dev/res/mipmap-xxhdpi/icon.png new file mode 100644 index 000000000..6a0d67876 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xxhdpi/icon.png differ diff --git a/.github/build/android/dev/res/mipmap-xxhdpi/icon_background.png b/.github/build/android/dev/res/mipmap-xxhdpi/icon_background.png new file mode 100644 index 000000000..663c585a8 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xxhdpi/icon_background.png differ diff --git a/.github/build/android/dev/res/mipmap-xxhdpi/icon_foreground.png b/.github/build/android/dev/res/mipmap-xxhdpi/icon_foreground.png new file mode 100644 index 000000000..7b6a2c087 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xxhdpi/icon_foreground.png differ diff --git a/.github/build/android/dev/res/mipmap-xxhdpi/icon_round.png b/.github/build/android/dev/res/mipmap-xxhdpi/icon_round.png new file mode 100644 index 000000000..482bd717d Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xxhdpi/icon_round.png differ diff --git a/.github/build/android/dev/res/mipmap-xxxhdpi/icon.png b/.github/build/android/dev/res/mipmap-xxxhdpi/icon.png new file mode 100644 index 000000000..3deefaa45 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xxxhdpi/icon.png differ diff --git a/.github/build/android/dev/res/mipmap-xxxhdpi/icon_background.png b/.github/build/android/dev/res/mipmap-xxxhdpi/icon_background.png new file mode 100644 index 000000000..2ae710fa3 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xxxhdpi/icon_background.png differ diff --git a/.github/build/android/dev/res/mipmap-xxxhdpi/icon_foreground.png b/.github/build/android/dev/res/mipmap-xxxhdpi/icon_foreground.png new file mode 100644 index 000000000..4257fcf70 Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xxxhdpi/icon_foreground.png differ diff --git a/.github/build/android/dev/res/mipmap-xxxhdpi/icon_round.png b/.github/build/android/dev/res/mipmap-xxxhdpi/icon_round.png new file mode 100644 index 000000000..671afb0eb Binary files /dev/null and b/.github/build/android/dev/res/mipmap-xxxhdpi/icon_round.png differ diff --git a/.github/build/android/release/res/icon-playstore.png b/.github/build/android/release/res/icon-playstore.png new file mode 100644 index 000000000..db9d09224 Binary files /dev/null and b/.github/build/android/release/res/icon-playstore.png differ diff --git a/.github/build/android/release/res/mipmap-anydpi-v26/icon.xml b/.github/build/android/release/res/mipmap-anydpi-v26/icon.xml new file mode 100644 index 000000000..1ed403703 --- /dev/null +++ b/.github/build/android/release/res/mipmap-anydpi-v26/icon.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.github/build/android/release/res/mipmap-anydpi-v26/icon_round.xml b/.github/build/android/release/res/mipmap-anydpi-v26/icon_round.xml new file mode 100644 index 000000000..1ed403703 --- /dev/null +++ b/.github/build/android/release/res/mipmap-anydpi-v26/icon_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/.github/build/android/release/res/mipmap-hdpi/icon.png b/.github/build/android/release/res/mipmap-hdpi/icon.png new file mode 100644 index 000000000..f355645b3 Binary files /dev/null and b/.github/build/android/release/res/mipmap-hdpi/icon.png differ diff --git a/.github/build/android/release/res/mipmap-hdpi/icon_background.png b/.github/build/android/release/res/mipmap-hdpi/icon_background.png new file mode 100644 index 000000000..0a212c9cb Binary files /dev/null and b/.github/build/android/release/res/mipmap-hdpi/icon_background.png differ diff --git a/.github/build/android/release/res/mipmap-hdpi/icon_foreground.png b/.github/build/android/release/res/mipmap-hdpi/icon_foreground.png new file mode 100644 index 000000000..e09b9a4e1 Binary files /dev/null and b/.github/build/android/release/res/mipmap-hdpi/icon_foreground.png differ diff --git a/.github/build/android/release/res/mipmap-hdpi/icon_round.png b/.github/build/android/release/res/mipmap-hdpi/icon_round.png new file mode 100644 index 000000000..f70ee81e4 Binary files /dev/null and b/.github/build/android/release/res/mipmap-hdpi/icon_round.png differ diff --git a/.github/build/android/release/res/mipmap-mdpi/icon.png b/.github/build/android/release/res/mipmap-mdpi/icon.png new file mode 100644 index 000000000..6021f04a9 Binary files /dev/null and b/.github/build/android/release/res/mipmap-mdpi/icon.png differ diff --git a/.github/build/android/release/res/mipmap-mdpi/icon_background.png b/.github/build/android/release/res/mipmap-mdpi/icon_background.png new file mode 100644 index 000000000..a961ca12b Binary files /dev/null and b/.github/build/android/release/res/mipmap-mdpi/icon_background.png differ diff --git a/.github/build/android/release/res/mipmap-mdpi/icon_foreground.png b/.github/build/android/release/res/mipmap-mdpi/icon_foreground.png new file mode 100644 index 000000000..b48065554 Binary files /dev/null and b/.github/build/android/release/res/mipmap-mdpi/icon_foreground.png differ diff --git a/.github/build/android/release/res/mipmap-mdpi/icon_round.png b/.github/build/android/release/res/mipmap-mdpi/icon_round.png new file mode 100644 index 000000000..5b80f445a Binary files /dev/null and b/.github/build/android/release/res/mipmap-mdpi/icon_round.png differ diff --git a/.github/build/android/release/res/mipmap-xhdpi/icon.png b/.github/build/android/release/res/mipmap-xhdpi/icon.png new file mode 100644 index 000000000..aaad54e64 Binary files /dev/null and b/.github/build/android/release/res/mipmap-xhdpi/icon.png differ diff --git a/.github/build/android/release/res/mipmap-xhdpi/icon_background.png b/.github/build/android/release/res/mipmap-xhdpi/icon_background.png new file mode 100644 index 000000000..f644dec4d Binary files /dev/null and b/.github/build/android/release/res/mipmap-xhdpi/icon_background.png differ diff --git a/.github/build/android/release/res/mipmap-xhdpi/icon_foreground.png b/.github/build/android/release/res/mipmap-xhdpi/icon_foreground.png new file mode 100644 index 000000000..a0a86e8fb Binary files /dev/null and b/.github/build/android/release/res/mipmap-xhdpi/icon_foreground.png differ diff --git a/.github/build/android/release/res/mipmap-xhdpi/icon_round.png b/.github/build/android/release/res/mipmap-xhdpi/icon_round.png new file mode 100644 index 000000000..758807bca Binary files /dev/null and b/.github/build/android/release/res/mipmap-xhdpi/icon_round.png differ diff --git a/.github/build/android/release/res/mipmap-xxhdpi/icon.png b/.github/build/android/release/res/mipmap-xxhdpi/icon.png new file mode 100644 index 000000000..50b2e0a82 Binary files /dev/null and b/.github/build/android/release/res/mipmap-xxhdpi/icon.png differ diff --git a/.github/build/android/release/res/mipmap-xxhdpi/icon_background.png b/.github/build/android/release/res/mipmap-xxhdpi/icon_background.png new file mode 100644 index 000000000..5937963db Binary files /dev/null and b/.github/build/android/release/res/mipmap-xxhdpi/icon_background.png differ diff --git a/.github/build/android/release/res/mipmap-xxhdpi/icon_foreground.png b/.github/build/android/release/res/mipmap-xxhdpi/icon_foreground.png new file mode 100644 index 000000000..89629566b Binary files /dev/null and b/.github/build/android/release/res/mipmap-xxhdpi/icon_foreground.png differ diff --git a/.github/build/android/release/res/mipmap-xxhdpi/icon_round.png b/.github/build/android/release/res/mipmap-xxhdpi/icon_round.png new file mode 100644 index 000000000..7e0f8100b Binary files /dev/null and b/.github/build/android/release/res/mipmap-xxhdpi/icon_round.png differ diff --git a/.github/build/android/release/res/mipmap-xxxhdpi/icon.png b/.github/build/android/release/res/mipmap-xxxhdpi/icon.png new file mode 100644 index 000000000..ad14c4590 Binary files /dev/null and b/.github/build/android/release/res/mipmap-xxxhdpi/icon.png differ diff --git a/.github/build/android/release/res/mipmap-xxxhdpi/icon_background.png b/.github/build/android/release/res/mipmap-xxxhdpi/icon_background.png new file mode 100644 index 000000000..c9674ee27 Binary files /dev/null and b/.github/build/android/release/res/mipmap-xxxhdpi/icon_background.png differ diff --git a/.github/build/android/release/res/mipmap-xxxhdpi/icon_foreground.png b/.github/build/android/release/res/mipmap-xxxhdpi/icon_foreground.png new file mode 100644 index 000000000..f67b32c64 Binary files /dev/null and b/.github/build/android/release/res/mipmap-xxxhdpi/icon_foreground.png differ diff --git a/.github/build/android/release/res/mipmap-xxxhdpi/icon_round.png b/.github/build/android/release/res/mipmap-xxxhdpi/icon_round.png new file mode 100644 index 000000000..d280f49e3 Binary files /dev/null and b/.github/build/android/release/res/mipmap-xxxhdpi/icon_round.png differ diff --git a/.github/build/iOS/dev/icon/icon_1024x1024.png b/.github/build/iOS/dev/icon/icon_1024x1024.png new file mode 100644 index 000000000..8712fe618 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_1024x1024.png differ diff --git a/.github/build/iOS/dev/icon/icon_20x20.png b/.github/build/iOS/dev/icon/icon_20x20.png new file mode 100644 index 000000000..19a62fd82 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_20x20.png differ diff --git a/.github/build/iOS/dev/icon/icon_20x20@2x.png b/.github/build/iOS/dev/icon/icon_20x20@2x.png new file mode 100644 index 000000000..bd20a69ad Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_20x20@2x.png differ diff --git a/.github/build/iOS/dev/icon/icon_20x20@3x.png b/.github/build/iOS/dev/icon/icon_20x20@3x.png new file mode 100644 index 000000000..d9d83def5 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_20x20@3x.png differ diff --git a/.github/build/iOS/dev/icon/icon_29x29.png b/.github/build/iOS/dev/icon/icon_29x29.png new file mode 100644 index 000000000..10132af01 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_29x29.png differ diff --git a/.github/build/iOS/dev/icon/icon_29x29@2x.png b/.github/build/iOS/dev/icon/icon_29x29@2x.png new file mode 100644 index 000000000..2876828c7 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_29x29@2x.png differ diff --git a/.github/build/iOS/dev/icon/icon_29x29@3x.png b/.github/build/iOS/dev/icon/icon_29x29@3x.png new file mode 100644 index 000000000..03677d99d Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_29x29@3x.png differ diff --git a/.github/build/iOS/dev/icon/icon_40x40.png b/.github/build/iOS/dev/icon/icon_40x40.png new file mode 100644 index 000000000..bd20a69ad Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_40x40.png differ diff --git a/.github/build/iOS/dev/icon/icon_40x40@2x.png b/.github/build/iOS/dev/icon/icon_40x40@2x.png new file mode 100644 index 000000000..b8a9728fc Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_40x40@2x.png differ diff --git a/.github/build/iOS/dev/icon/icon_40x40@3x.png b/.github/build/iOS/dev/icon/icon_40x40@3x.png new file mode 100644 index 000000000..7147ed2a2 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_40x40@3x.png differ diff --git a/.github/build/iOS/dev/icon/icon_60x60@2x.png b/.github/build/iOS/dev/icon/icon_60x60@2x.png new file mode 100644 index 000000000..7147ed2a2 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_60x60@2x.png differ diff --git a/.github/build/iOS/dev/icon/icon_60x60@3x.png b/.github/build/iOS/dev/icon/icon_60x60@3x.png new file mode 100644 index 000000000..7ab3e05f7 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_60x60@3x.png differ diff --git a/.github/build/iOS/dev/icon/icon_76x76.png b/.github/build/iOS/dev/icon/icon_76x76.png new file mode 100644 index 000000000..924b176e0 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_76x76.png differ diff --git a/.github/build/iOS/dev/icon/icon_76x76@2x.png b/.github/build/iOS/dev/icon/icon_76x76@2x.png new file mode 100644 index 000000000..c172865d8 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_76x76@2x.png differ diff --git a/.github/build/iOS/dev/icon/icon_83.5x83.5@2x.png b/.github/build/iOS/dev/icon/icon_83.5x83.5@2x.png new file mode 100644 index 000000000..9b7572ca0 Binary files /dev/null and b/.github/build/iOS/dev/icon/icon_83.5x83.5@2x.png differ diff --git a/.github/build/iOS/love.patch b/.github/build/iOS/love.patch new file mode 100644 index 000000000..701b560da --- /dev/null +++ b/.github/build/iOS/love.patch @@ -0,0 +1,106 @@ +diff --git a/src/common/ios.h b/src/common/ios.h +index c1932555..552e432e 100644 +--- a/src/common/ios.h ++++ b/src/common/ios.h +@@ -66,7 +66,7 @@ std::string getExecutablePath(); + /** + * Causes devices with vibration support to vibrate for about 0.5 seconds. + **/ +-void vibrate(); ++void vibrate(const double seconds); + + /** + * Enable mix mode (e.g. with background music apps) and playback with a muted device. +diff --git a/src/common/ios.mm b/src/common/ios.mm +index 7730991e..4ba8e708 100644 +--- a/src/common/ios.mm ++++ b/src/common/ios.mm +@@ -36,6 +36,8 @@ + #include + #include + ++#include ++ + static NSArray *getLovesInDocuments(); + static bool deleteFileInDocuments(NSString *filename); + +@@ -391,10 +393,40 @@ std::string getExecutablePath() + } + } + +-void vibrate() ++void vibrate(const double seconds) + { + @autoreleasepool + { ++ struct utsname systemInfo; ++ uname(&systemInfo); ++ NSString *deviceString = [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding]; ++ NSRange iPhoneRange = [deviceString rangeOfString:@"iPhone"]; ++ if (iPhoneRange.length == 6) { ++ NSRange commaRange = [deviceString rangeOfString:@","]; ++ NSString *iPhone = [deviceString substringWithRange:iPhoneRange]; ++ NSRange numRange = NSMakeRange(iPhoneRange.location + iPhoneRange.length, commaRange.location - iPhoneRange.location - iPhoneRange.length); ++ NSString *num = [deviceString substringWithRange:numRange]; ++ ++ if ([num intValue] >= 9) { ++ // iPhone 7 and above, see: https://gist.github.com/adamawolf/3048717#file-apple_mobile_device_types-txt-L22 ++ ++ if (@available(iOS 10.0, *)) { ++ // iOS 10.0 and above ++ UIImpactFeedbackGenerator *impact = nil; ++ if (seconds >= 0.5 && seconds < 1.5) { ++ impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight]; // 轻 ++ } else if (seconds >= 1.5 && seconds < 2.5) { ++ impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleMedium]; // 中 ++ } else if (seconds >= 2.5) { ++ impact = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleHeavy]; // 重 ++ } else { ++ return; ++ } ++ [impact impactOccurred]; ++ return; ++ } ++ } ++ } + AudioServicesPlaySystemSound(kSystemSoundID_Vibrate); + } + } +diff --git a/src/love.cpp b/src/love.cpp +index c8af8596..ae7a5e32 100644 +--- a/src/love.cpp ++++ b/src/love.cpp +@@ -140,6 +140,10 @@ enum DoneAction + DONE_RESTART, + }; + ++extern "C" { ++ int luaopen_CCloader(lua_State *L); ++} ++ + static DoneAction runlove(int argc, char **argv, int &retval) + { + // Oh, you just want the version? Okay! +@@ -158,6 +162,9 @@ static DoneAction runlove(int argc, char **argv, int &retval) + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + ++ // Init CCloader ++ luaopen_CCloader(L); ++ + // LuaJIT-specific setup needs to be done as early as possible - before + // get_app_arguments because that loads external library code. This is also + // loaded inside require("love"). Note that it doesn't use the love table. +diff --git a/src/modules/system/System.cpp b/src/modules/system/System.cpp +index e1de16d5..e0f03557 100644 +--- a/src/modules/system/System.cpp ++++ b/src/modules/system/System.cpp +@@ -174,7 +174,7 @@ void System::vibrate(double seconds) const + #ifdef LOVE_ANDROID + love::android::vibrate(seconds); + #elif defined(LOVE_IOS) +- love::ios::vibrate(); ++ love::ios::vibrate(seconds); + #else + LOVE_UNUSED(seconds); + #endif diff --git a/.github/build/iOS/release/icon/icon_1024x1024.png b/.github/build/iOS/release/icon/icon_1024x1024.png new file mode 100644 index 000000000..c80bf4202 Binary files /dev/null and b/.github/build/iOS/release/icon/icon_1024x1024.png differ diff --git a/.github/build/iOS/release/icon/icon_20x20.png b/.github/build/iOS/release/icon/icon_20x20.png new file mode 100644 index 000000000..93dac5191 Binary files /dev/null and b/.github/build/iOS/release/icon/icon_20x20.png differ diff --git a/.github/build/iOS/release/icon/icon_20x20@2x.png b/.github/build/iOS/release/icon/icon_20x20@2x.png new file mode 100644 index 000000000..887721240 Binary files /dev/null and b/.github/build/iOS/release/icon/icon_20x20@2x.png differ diff --git a/.github/build/iOS/release/icon/icon_20x20@3x.png b/.github/build/iOS/release/icon/icon_20x20@3x.png new file mode 100644 index 000000000..cace38818 Binary files /dev/null and b/.github/build/iOS/release/icon/icon_20x20@3x.png differ diff --git a/.github/build/iOS/release/icon/icon_29x29.png b/.github/build/iOS/release/icon/icon_29x29.png new file mode 100644 index 000000000..bab7dac11 Binary files /dev/null and b/.github/build/iOS/release/icon/icon_29x29.png differ diff --git a/.github/build/iOS/release/icon/icon_29x29@2x.png b/.github/build/iOS/release/icon/icon_29x29@2x.png new file mode 100644 index 000000000..bfb79f21a Binary files /dev/null and b/.github/build/iOS/release/icon/icon_29x29@2x.png differ diff --git a/.github/build/iOS/release/icon/icon_29x29@3x.png b/.github/build/iOS/release/icon/icon_29x29@3x.png new file mode 100644 index 000000000..e1de7c286 Binary files /dev/null and b/.github/build/iOS/release/icon/icon_29x29@3x.png differ diff --git a/.github/build/iOS/release/icon/icon_40x40.png b/.github/build/iOS/release/icon/icon_40x40.png new file mode 100644 index 000000000..887721240 Binary files /dev/null and b/.github/build/iOS/release/icon/icon_40x40.png differ diff --git a/.github/build/iOS/release/icon/icon_40x40@2x.png b/.github/build/iOS/release/icon/icon_40x40@2x.png new file mode 100644 index 000000000..9f08f7614 Binary files /dev/null and b/.github/build/iOS/release/icon/icon_40x40@2x.png differ diff --git a/.github/build/iOS/release/icon/icon_40x40@3x.png b/.github/build/iOS/release/icon/icon_40x40@3x.png new file mode 100644 index 000000000..6ed8550ff Binary files /dev/null and b/.github/build/iOS/release/icon/icon_40x40@3x.png differ diff --git a/.github/build/iOS/release/icon/icon_60x60@2x.png b/.github/build/iOS/release/icon/icon_60x60@2x.png new file mode 100644 index 000000000..6ed8550ff Binary files /dev/null and b/.github/build/iOS/release/icon/icon_60x60@2x.png differ diff --git a/.github/build/iOS/release/icon/icon_60x60@3x.png b/.github/build/iOS/release/icon/icon_60x60@3x.png new file mode 100644 index 000000000..ec6b2bb4e Binary files /dev/null and b/.github/build/iOS/release/icon/icon_60x60@3x.png differ diff --git a/.github/build/iOS/release/icon/icon_76x76.png b/.github/build/iOS/release/icon/icon_76x76.png new file mode 100644 index 000000000..ec239362d Binary files /dev/null and b/.github/build/iOS/release/icon/icon_76x76.png differ diff --git a/.github/build/iOS/release/icon/icon_76x76@2x.png b/.github/build/iOS/release/icon/icon_76x76@2x.png new file mode 100644 index 000000000..1c0955c86 Binary files /dev/null and b/.github/build/iOS/release/icon/icon_76x76@2x.png differ diff --git a/.github/build/iOS/release/icon/icon_83.5x83.5@2x.png b/.github/build/iOS/release/icon/icon_83.5x83.5@2x.png new file mode 100644 index 000000000..d9968bd3a Binary files /dev/null and b/.github/build/iOS/release/icon/icon_83.5x83.5@2x.png differ diff --git a/.github/build/Linux/icon_snapshot.png b/.github/build/linux/dev/icon.png similarity index 100% rename from .github/build/Linux/icon_snapshot.png rename to .github/build/linux/dev/icon.png diff --git a/.github/build/Linux/icon.png b/.github/build/linux/release/icon.png similarity index 100% rename from .github/build/Linux/icon.png rename to .github/build/linux/release/icon.png diff --git a/.github/build/macOS/Techminodisk.icns b/.github/build/macOS/dev/dmg.icns similarity index 100% rename from .github/build/macOS/Techminodisk.icns rename to .github/build/macOS/dev/dmg.icns diff --git a/.github/build/macOS/backgroundImage.tiff b/.github/build/macOS/dev/dmg.png similarity index 100% rename from .github/build/macOS/backgroundImage.tiff rename to .github/build/macOS/dev/dmg.png diff --git a/.github/build/macOS/icon_snapshot.icns b/.github/build/macOS/dev/icon.icns similarity index 100% rename from .github/build/macOS/icon_snapshot.icns rename to .github/build/macOS/dev/icon.icns diff --git a/.github/build/macOS/info.plist.template b/.github/build/macOS/info.plist.template deleted file mode 100644 index c4f251ef7..000000000 --- a/.github/build/macOS/info.plist.template +++ /dev/null @@ -1,56 +0,0 @@ - - - - - BuildMachineOSBuild - 19B88 - CFBundleDevelopmentRegion - English - CFBundleExecutable - love - CFBundleIconFile - iconfile - CFBundleIdentifier - @bundleId - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - Techmino - CFBundlePackageType - APPL - CFBundleShortVersionString - @versionName - CFBundleSignature - LoVe - CFBundleSupportedPlatforms - - MacOSX - - DTCompiler - com.apple.compilers.llvm.clang.1_0 - DTPlatformBuild - 11C504 - DTPlatformVersion - GM - DTSDKBuild - 19B90 - DTSDKName - macosx10.15 - DTXcode - 1130 - DTXcodeBuild - 11C504 - LSApplicationCategoryType - public.app-category.games - LSMinimumSystemVersion - 10.7 - NSHighResolutionCapable - - NSHumanReadableCopyright - ©2020-@thisYear 26F Studio, GNU LGPLv3.0 - NSPrincipalClass - NSApplication - NSSupportsAutomaticGraphicsSwitching - - - diff --git a/.github/build/macOS/release/dmg.icns b/.github/build/macOS/release/dmg.icns new file mode 100644 index 000000000..f1a560cbc Binary files /dev/null and b/.github/build/macOS/release/dmg.icns differ diff --git a/.github/build/macOS/release/dmg.png b/.github/build/macOS/release/dmg.png new file mode 100644 index 000000000..e50fad1fc Binary files /dev/null and b/.github/build/macOS/release/dmg.png differ diff --git a/.github/build/macOS/icon.icns b/.github/build/macOS/release/icon.icns similarity index 100% rename from .github/build/macOS/icon.icns rename to .github/build/macOS/release/icon.icns diff --git a/.github/build/web/favicon.ico b/.github/build/web/favicon.ico new file mode 100644 index 000000000..40793b9d8 Binary files /dev/null and b/.github/build/web/favicon.ico differ diff --git a/.github/build/web/game.js b/.github/build/web/game.js new file mode 100644 index 000000000..f0755e5f7 --- /dev/null +++ b/.github/build/web/game.js @@ -0,0 +1,288 @@ + +var Module; + +if (typeof Module === 'undefined') Module = eval('(function() { try { return Module || {} } catch(e) { return {} } })()'); + +if (!Module.expectedDataFileDownloads) { + Module.expectedDataFileDownloads = 0; + Module.finishedDataFileDownloads = 0; +} +Module.expectedDataFileDownloads++; +(function() { + var loadPackage = function(metadata) { + + var PACKAGE_PATH; + if (typeof window === 'object') { + PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/'); + } else if (typeof location !== 'undefined') { + // worker + PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/'); + } else { + throw 'using preloaded data can only be done on a web page or in a web worker'; + } + var PACKAGE_NAME = 'game.data'; + var REMOTE_PACKAGE_BASE = 'game.data'; + if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) { + Module['locateFile'] = Module['locateFilePackage']; + Module.printErr('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)'); + } + var REMOTE_PACKAGE_NAME = typeof Module['locateFile'] === 'function' ? + Module['locateFile'](REMOTE_PACKAGE_BASE) : + ((Module['filePackagePrefixURL'] || '') + REMOTE_PACKAGE_BASE); + + var REMOTE_PACKAGE_SIZE = metadata.remote_package_size; + var PACKAGE_UUID = metadata.package_uuid; + + function fetchRemotePackage(packageName, packageSize, callback, errback) { + var xhr = new XMLHttpRequest(); + xhr.open('GET', packageName, true); + xhr.responseType = 'arraybuffer'; + xhr.onprogress = function(event) { + var url = packageName; + var size = packageSize; + if (event.total) size = event.total; + if (event.loaded) { + if (!xhr.addedTotal) { + xhr.addedTotal = true; + if (!Module.dataFileDownloads) Module.dataFileDownloads = {}; + Module.dataFileDownloads[url] = { + loaded: event.loaded, + total: size + }; + } else { + Module.dataFileDownloads[url].loaded = event.loaded; + } + var total = 0; + var loaded = 0; + var num = 0; + for (var download in Module.dataFileDownloads) { + var data = Module.dataFileDownloads[download]; + total += data.total; + loaded += data.loaded; + num++; + } + total = Math.ceil(total * Module.expectedDataFileDownloads/num); + if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')'); + } else if (!Module.dataFileDownloads) { + if (Module['setStatus']) Module['setStatus']('Downloading data...'); + } + }; + xhr.onerror = function(event) { + throw new Error("NetworkError for: " + packageName); + } + xhr.onload = function(event) { + if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0 + var packageData = xhr.response; + callback(packageData); + } else { + throw new Error(xhr.statusText + " : " + xhr.responseURL); + } + }; + xhr.send(null); + }; + + function handleError(error) { + console.error('package error:', error); + }; + + function runWithFS() { + + function assert(check, msg) { + if (!check) throw msg + new Error().stack; + } + + function DataRequest(start, end, crunched, audio) { + this.start = start; + this.end = end; + this.crunched = crunched; + this.audio = audio; + } + DataRequest.prototype = { + requests: {}, + open: function(mode, name) { + this.name = name; + this.requests[name] = this; + Module['addRunDependency']('fp ' + this.name); + }, + send: function() {}, + onload: function() { + var byteArray = this.byteArray.subarray(this.start, this.end); + + this.finish(byteArray); + + }, + finish: function(byteArray) { + var that = this; + + Module['FS_createDataFile'](this.name, null, byteArray, true, true, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change + Module['removeRunDependency']('fp ' + that.name); + + this.requests[this.name] = null; + } + }; + + var files = metadata.files; + for (i = 0; i < files.length; ++i) { + new DataRequest(files[i].start, files[i].end, files[i].crunched, files[i].audio).open('GET', files[i].filename); + } + + + var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + var IDB_RO = "readonly"; + var IDB_RW = "readwrite"; + var DB_NAME = "EM_PRELOAD_CACHE"; + var DB_VERSION = 1; + var METADATA_STORE_NAME = 'METADATA'; + var PACKAGE_STORE_NAME = 'PACKAGES'; + function openDatabase(callback, errback) { + try { + var openRequest = indexedDB.open(DB_NAME, DB_VERSION); + } catch (e) { + return errback(e); + } + openRequest.onupgradeneeded = function(event) { + var db = event.target.result; + + if(db.objectStoreNames.contains(PACKAGE_STORE_NAME)) { + db.deleteObjectStore(PACKAGE_STORE_NAME); + } + var packages = db.createObjectStore(PACKAGE_STORE_NAME); + + if(db.objectStoreNames.contains(METADATA_STORE_NAME)) { + db.deleteObjectStore(METADATA_STORE_NAME); + } + var metadata = db.createObjectStore(METADATA_STORE_NAME); + }; + openRequest.onsuccess = function(event) { + var db = event.target.result; + callback(db); + }; + openRequest.onerror = function(error) { + errback(error); + }; + }; + + /* Check if there's a cached package, and if so whether it's the latest available */ + function checkCachedPackage(db, packageName, callback, errback) { + var transaction = db.transaction([METADATA_STORE_NAME], IDB_RO); + var metadata = transaction.objectStore(METADATA_STORE_NAME); + + var getRequest = metadata.get("metadata/" + packageName); + getRequest.onsuccess = function(event) { + var result = event.target.result; + if (!result) { + return callback(false); + } else { + return callback(PACKAGE_UUID === result.uuid); + } + }; + getRequest.onerror = function(error) { + errback(error); + }; + }; + + function fetchCachedPackage(db, packageName, callback, errback) { + var transaction = db.transaction([PACKAGE_STORE_NAME], IDB_RO); + var packages = transaction.objectStore(PACKAGE_STORE_NAME); + + var getRequest = packages.get("package/" + packageName); + getRequest.onsuccess = function(event) { + var result = event.target.result; + callback(result); + }; + getRequest.onerror = function(error) { + errback(error); + }; + }; + + function cacheRemotePackage(db, packageName, packageData, packageMeta, callback, errback) { + var transaction_packages = db.transaction([PACKAGE_STORE_NAME], IDB_RW); + var packages = transaction_packages.objectStore(PACKAGE_STORE_NAME); + + var putPackageRequest = packages.put(packageData, "package/" + packageName); + putPackageRequest.onsuccess = function(event) { + var transaction_metadata = db.transaction([METADATA_STORE_NAME], IDB_RW); + var metadata = transaction_metadata.objectStore(METADATA_STORE_NAME); + var putMetadataRequest = metadata.put(packageMeta, "metadata/" + packageName); + putMetadataRequest.onsuccess = function(event) { + callback(packageData); + }; + putMetadataRequest.onerror = function(error) { + errback(error); + }; + }; + putPackageRequest.onerror = function(error) { + errback(error); + }; + }; + + function processPackageData(arrayBuffer) { + Module.finishedDataFileDownloads++; + assert(arrayBuffer, 'Loading data file failed.'); + assert(arrayBuffer instanceof ArrayBuffer, 'bad input to processPackageData'); + var byteArray = new Uint8Array(arrayBuffer); + var curr; + + // copy the entire loaded file into a spot in the heap. Files will refer to slices in that. They cannot be freed though + // (we may be allocating before malloc is ready, during startup). + if (Module['SPLIT_MEMORY']) Module.printErr('warning: you should run the file packager with --no-heap-copy when SPLIT_MEMORY is used, otherwise copying into the heap may fail due to the splitting'); + var ptr = Module['getMemory'](byteArray.length); + Module['HEAPU8'].set(byteArray, ptr); + DataRequest.prototype.byteArray = Module['HEAPU8'].subarray(ptr, ptr+byteArray.length); + + var files = metadata.files; + for (i = 0; i < files.length; ++i) { + DataRequest.prototype.requests[files[i].filename].onload(); + } + Module['removeRunDependency']('datafile_game.data'); + + }; + Module['addRunDependency']('datafile_game.data'); + + if (!Module.preloadResults) Module.preloadResults = {}; + + function preloadFallback(error) { + console.error(error); + console.error('falling back to default preload behavior'); + fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, processPackageData, handleError); + }; + + openDatabase( + function(db) { + checkCachedPackage(db, PACKAGE_PATH + PACKAGE_NAME, + function(useCached) { + Module.preloadResults[PACKAGE_NAME] = {fromCache: useCached}; + if (useCached) { + console.info('loading ' + PACKAGE_NAME + ' from cache'); + fetchCachedPackage(db, PACKAGE_PATH + PACKAGE_NAME, processPackageData, preloadFallback); + } else { + console.info('loading ' + PACKAGE_NAME + ' from remote'); + fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, + function(packageData) { + cacheRemotePackage(db, PACKAGE_PATH + PACKAGE_NAME, packageData, {uuid:PACKAGE_UUID}, processPackageData, + function(error) { + console.error(error); + processPackageData(packageData); + }); + } + , preloadFallback); + } + } + , preloadFallback); + } + , preloadFallback); + + if (Module['setStatus']) Module['setStatus']('Downloading...'); + + } + if (Module['calledRun']) { + runWithFS(); + } else { + if (!Module['preRun']) Module['preRun'] = []; + Module["preRun"].push(runWithFS); // FS is not initialized yet, wait for it + } + + } + loadPackage({"package_uuid":"80826f15-f924-4428-a8c4-e984743417c6","remote_package_size":62246034,"files":[{"filename":"/game.love","crunched":0,"start":0,"end":62246034,"audio":false}]}); + +})(); diff --git a/.github/build/web/index.html b/.github/build/web/index.html new file mode 100644 index 000000000..8e28dc34e --- /dev/null +++ b/.github/build/web/index.html @@ -0,0 +1,111 @@ + + + + + + + Techmino + + + + + +
+
+

Techmino

+ + +
+
+ + + + +
+

Built with love.js
Hint: Reload the page if screen is blank

+
+ + diff --git a/.github/build/web/love.js b/.github/build/web/love.js new file mode 100644 index 000000000..22e07ac9f --- /dev/null +++ b/.github/build/web/love.js @@ -0,0 +1,22 @@ + +var Love = (function() { + var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; + if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; + return ( +function(Love) { + Love = Love || {}; + +var Module=typeof Love!=="undefined"?Love:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var STACK_ALIGN=16;function dynamicAlloc(size){var ret=HEAP32[DYNAMICTOP_PTR>>2];var end=ret+size+15&-16;HEAP32[DYNAMICTOP_PTR>>2]=end;return ret}function alignMemory(size,factor){if(!factor)factor=STACK_ALIGN;return Math.ceil(size/factor)*factor}function getNativeTypeSize(type){switch(type){case"i1":case"i8":return 1;case"i16":return 2;case"i32":return 4;case"i64":return 8;case"float":return 4;case"double":return 8;default:{if(type[type.length-1]==="*"){return 4}else if(type[0]==="i"){var bits=Number(type.substr(1));assert(bits%8===0,"getNativeTypeSize invalid bits "+bits+", type "+type);return bits/8}else{return 0}}}}function warnOnce(text){if(!warnOnce.shown)warnOnce.shown={};if(!warnOnce.shown[text]){warnOnce.shown[text]=1;err(text)}}function convertJsFunctionToWasm(func,sig){if(typeof WebAssembly.Function==="function"){var typeNames={"i":"i32","j":"i64","f":"f32","d":"f64"};var type={parameters:[],results:sig[0]=="v"?[]:[typeNames[sig[0]]]};for(var i=1;i>0]=value;break;case"i8":HEAP8[ptr>>0]=value;break;case"i16":HEAP16[ptr>>1]=value;break;case"i32":HEAP32[ptr>>2]=value;break;case"i64":tempI64=[value>>>0,(tempDouble=value,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[ptr>>2]=tempI64[0],HEAP32[ptr+4>>2]=tempI64[1];break;case"float":HEAPF32[ptr>>2]=value;break;case"double":HEAPF64[ptr>>3]=value;break;default:abort("invalid type for setValue: "+type)}}var wasmMemory;var wasmTable=new WebAssembly.Table({"initial":5397,"maximum":5397,"element":"anyfunc"});var ABORT=false;var EXITSTATUS=0;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}function getCFunc(ident){var func=Module["_"+ident];assert(func,"Cannot call unknown function "+ident+", make sure it is exported");return func}function ccall(ident,returnType,argTypes,args,opts){var toC={"string":function(str){var ret=0;if(str!==null&&str!==undefined&&str!==0){var len=(str.length<<2)+1;ret=stackAlloc(len);stringToUTF8(str,ret,len)}return ret},"array":function(arr){var ret=stackAlloc(arr.length);writeArrayToMemory(arr,ret);return ret}};function convertReturnValue(ret){if(returnType==="string")return UTF8ToString(ret);if(returnType==="boolean")return Boolean(ret);return ret}var func=getCFunc(ident);var cArgs=[];var stack=0;if(args){for(var i=0;i>2]=0}stop=ret+size;while(ptr>0]=0}return ret}if(singleType==="i8"){if(slab.subarray||slab.slice){HEAPU8.set(slab,ret)}else{HEAPU8.set(new Uint8Array(slab),ret)}return ret}var i=0,type,typeSize,previousType;while(i=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function allocateUTF8(str){var size=lengthBytesUTF8(str)+1;var ret=_malloc(size);if(ret)stringToUTF8Array(str,HEAP8,ret,size);return ret}function allocateUTF8OnStack(str){var size=lengthBytesUTF8(str)+1;var ret=stackAlloc(size);stringToUTF8Array(str,HEAP8,ret,size);return ret}function writeArrayToMemory(array,buffer){HEAP8.set(array,buffer)}function writeAsciiToMemory(str,buffer,dontAddNull){for(var i=0;i>0]=str.charCodeAt(i)}if(!dontAddNull)HEAP8[buffer>>0]=0}var WASM_PAGE_SIZE=65536;function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var STACK_BASE=7161696,DYNAMIC_BASE=7161696,DYNAMICTOP_PTR=1918800;var INITIAL_INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;if(Module["wasmMemory"]){wasmMemory=Module["wasmMemory"]}else{wasmMemory=new WebAssembly.Memory({"initial":INITIAL_INITIAL_MEMORY/WASM_PAGE_SIZE,"maximum":2147483648/WASM_PAGE_SIZE})}if(wasmMemory){buffer=wasmMemory.buffer}INITIAL_INITIAL_MEMORY=buffer.byteLength;updateGlobalBufferAndViews(buffer);HEAP32[DYNAMICTOP_PTR>>2]=DYNAMIC_BASE;var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATEXIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;var runtimeExited=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;if(!Module["noFSInit"]&&!FS.init.initialized)FS.init();TTY.init();SOCKFS.root=FS.mount(SOCKFS,{},null);callRuntimeCallbacks(__ATINIT__)}function preMain(){FS.ignorePermissions=false;callRuntimeCallbacks(__ATMAIN__)}function exitRuntime(){runtimeExited=true}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var Math_abs=Math.abs;var Math_ceil=Math.ceil;var Math_floor=Math.floor;var Math_min=Math.min;var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function getUniqueRunDependency(id){return id}function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="love.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return Promise.resolve().then(getBinary)}function createWasm(){var info={"env":asmLibraryArg,"wasi_snapshot_preview1":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync();return{}}var tempDouble;var tempI64;var ASM_CONSTS={354316:function($0){window.open(UTF8ToString($0));return 0},1016846:function($0,$1){alert(UTF8ToString($0)+"\n\n"+UTF8ToString($1))},1019084:function($0,$1,$2){var w=$0;var h=$1;var pixels=$2;if(!Module["SDL2"])Module["SDL2"]={};var SDL2=Module["SDL2"];if(SDL2.ctxCanvas!==Module["canvas"]){SDL2.ctx=Module["createContext"](Module["canvas"],false,true);SDL2.ctxCanvas=Module["canvas"]}if(SDL2.w!==w||SDL2.h!==h||SDL2.imageCtx!==SDL2.ctx){SDL2.image=SDL2.ctx.createImageData(w,h);SDL2.w=w;SDL2.h=h;SDL2.imageCtx=SDL2.ctx}var data=SDL2.image.data;var src=pixels>>2;var dst=0;var num;if(typeof CanvasPixelArray!=="undefined"&&data instanceof CanvasPixelArray){num=data.length;while(dst>8&255;data[dst+2]=val>>16&255;data[dst+3]=255;src++;dst+=4}}else{if(SDL2.data32Data!==data){SDL2.data32=new Int32Array(data.buffer);SDL2.data8=new Uint8Array(data.buffer)}var data32=SDL2.data32;num=data32.length;data32.set(HEAP32.subarray(src,src+num));var data8=SDL2.data8;var i=3;var j=i+4*num;if(num%8==0){while(i>2;var dst=0;var num;if(typeof CanvasPixelArray!=="undefined"&&data instanceof CanvasPixelArray){num=data.length;while(dst>8&255;data[dst+2]=val>>16&255;data[dst+3]=val>>24&255;src++;dst+=4}}else{var data32=new Int32Array(data.buffer);num=data32.length;data32.set(HEAP32.subarray(src,src+num))}ctx.putImageData(image,0,0);var url=hot_x===0&&hot_y===0?"url("+canvas.toDataURL()+"), auto":"url("+canvas.toDataURL()+") "+hot_x+" "+hot_y+", auto";var urlBuf=_malloc(url.length+1);stringToUTF8(url,urlBuf,url.length+1);return urlBuf},1021552:function($0){if(Module["canvas"]){Module["canvas"].style["cursor"]=UTF8ToString($0)}return 0},1021645:function(){if(Module["canvas"]){Module["canvas"].style["cursor"]="none"}},1022870:function(){return screen.width},1022897:function(){return screen.height},1022925:function(){return window.innerWidth},1022957:function(){return window.innerHeight},1023035:function($0){if(typeof setWindowTitle!=="undefined"){setWindowTitle(UTF8ToString($0))}return 0},1023169:function(){if(typeof AudioContext!=="undefined"){return 1}else if(typeof webkitAudioContext!=="undefined"){return 1}return 0},1023335:function(){if(typeof navigator.mediaDevices!=="undefined"&&typeof navigator.mediaDevices.getUserMedia!=="undefined"){return 1}else if(typeof navigator.webkitGetUserMedia!=="undefined"){return 1}return 0},1023561:function($0){if(typeof Module["SDL2"]==="undefined"){Module["SDL2"]={}}var SDL2=Module["SDL2"];if(!$0){SDL2.audio={}}else{SDL2.capture={}}if(!SDL2.audioContext){if(typeof AudioContext!=="undefined"){SDL2.audioContext=new AudioContext}else if(typeof webkitAudioContext!=="undefined"){SDL2.audioContext=new webkitAudioContext}if(SDL2.audioContext){autoResumeAudioContext(SDL2.audioContext)}}return SDL2.audioContext===undefined?-1:0},1024114:function(){var SDL2=Module["SDL2"];return SDL2.audioContext.sampleRate},1024184:function($0,$1,$2,$3){var SDL2=Module["SDL2"];var have_microphone=function(stream){if(SDL2.capture.silenceTimer!==undefined){clearTimeout(SDL2.capture.silenceTimer);SDL2.capture.silenceTimer=undefined}SDL2.capture.mediaStreamNode=SDL2.audioContext.createMediaStreamSource(stream);SDL2.capture.scriptProcessorNode=SDL2.audioContext.createScriptProcessor($1,$0,1);SDL2.capture.scriptProcessorNode.onaudioprocess=function(audioProcessingEvent){if(SDL2===undefined||SDL2.capture===undefined){return}audioProcessingEvent.outputBuffer.getChannelData(0).fill(0);SDL2.capture.currentCaptureBuffer=audioProcessingEvent.inputBuffer;dynCall("vi",$2,[$3])};SDL2.capture.mediaStreamNode.connect(SDL2.capture.scriptProcessorNode);SDL2.capture.scriptProcessorNode.connect(SDL2.audioContext.destination);SDL2.capture.stream=stream};var no_microphone=function(error){};SDL2.capture.silenceBuffer=SDL2.audioContext.createBuffer($0,$1,SDL2.audioContext.sampleRate);SDL2.capture.silenceBuffer.getChannelData(0).fill(0);var silence_callback=function(){SDL2.capture.currentCaptureBuffer=SDL2.capture.silenceBuffer;dynCall("vi",$2,[$3])};SDL2.capture.silenceTimer=setTimeout(silence_callback,$1/SDL2.audioContext.sampleRate*1e3);if(navigator.mediaDevices!==undefined&&navigator.mediaDevices.getUserMedia!==undefined){navigator.mediaDevices.getUserMedia({audio:true,video:false}).then(have_microphone).catch(no_microphone)}else if(navigator.webkitGetUserMedia!==undefined){navigator.webkitGetUserMedia({audio:true,video:false},have_microphone,no_microphone)}},1025836:function($0,$1,$2,$3){var SDL2=Module["SDL2"];SDL2.audio.scriptProcessorNode=SDL2.audioContext["createScriptProcessor"]($1,0,$0);SDL2.audio.scriptProcessorNode["onaudioprocess"]=function(e){if(SDL2===undefined||SDL2.audio===undefined){return}SDL2.audio.currentOutputBuffer=e["outputBuffer"];dynCall("vi",$2,[$3])};SDL2.audio.scriptProcessorNode["connect"](SDL2.audioContext["destination"])},1026246:function($0,$1){var SDL2=Module["SDL2"];var numChannels=SDL2.capture.currentCaptureBuffer.numberOfChannels;for(var c=0;c>2]}}},1027331:function($0){var SDL2=Module["SDL2"];if($0){if(SDL2.capture.silenceTimer!==undefined){clearTimeout(SDL2.capture.silenceTimer)}if(SDL2.capture.stream!==undefined){var tracks=SDL2.capture.stream.getAudioTracks();for(var i=0;i0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){wasmTable.get(func)()}else{wasmTable.get(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}function demangle(func){return func}function demangleAll(text){var regex=/\b_Z[\w\d_]+/g;return text.replace(regex,function(x){var y=demangle(x);return x===y?x:y+" ["+x+"]"})}function dynCallLegacy(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}return Module["dynCall_"+sig].call(null,ptr)}function dynCall(sig,ptr,args){if(sig.indexOf("j")!=-1){return dynCallLegacy(sig,ptr,args)}return wasmTable.get(ptr).apply(null,args)}function jsStackTrace(){var error=new Error;if(!error.stack){try{throw new Error}catch(e){error=e}if(!error.stack){return"(no stack trace available)"}}return error.stack.toString()}function stackTrace(){var js=jsStackTrace();if(Module["extraStackTrace"])js+="\n"+Module["extraStackTrace"]();return demangleAll(js)}var _emscripten_get_now;if(ENVIRONMENT_IS_NODE){_emscripten_get_now=function(){var t=process["hrtime"]();return t[0]*1e3+t[1]/1e6}}else if(typeof dateNow!=="undefined"){_emscripten_get_now=dateNow}else _emscripten_get_now=function(){return performance.now()};var _emscripten_get_now_is_monotonic=true;function setErrNo(value){HEAP32[___errno_location()>>2]=value;return value}function _clock_gettime(clk_id,tp){var now;if(clk_id===0){now=Date.now()}else if((clk_id===1||clk_id===4)&&_emscripten_get_now_is_monotonic){now=_emscripten_get_now()}else{setErrNo(28);return-1}HEAP32[tp>>2]=now/1e3|0;HEAP32[tp+4>>2]=now%1e3*1e3*1e3|0;return 0}function ___clock_gettime(a0,a1){return _clock_gettime(a0,a1)}var ExceptionInfoAttrs={DESTRUCTOR_OFFSET:0,REFCOUNT_OFFSET:4,TYPE_OFFSET:8,CAUGHT_OFFSET:12,RETHROWN_OFFSET:13,SIZE:16};function ___cxa_allocate_exception(size){return _malloc(size+ExceptionInfoAttrs.SIZE)+ExceptionInfoAttrs.SIZE}function _atexit(func,arg){}function ___cxa_atexit(a0,a1){return _atexit(a0,a1)}function ExceptionInfo(excPtr){this.excPtr=excPtr;this.ptr=excPtr-ExceptionInfoAttrs.SIZE;this.set_type=function(type){HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]=type};this.get_type=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.TYPE_OFFSET>>2]};this.set_destructor=function(destructor){HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]=destructor};this.get_destructor=function(){return HEAP32[this.ptr+ExceptionInfoAttrs.DESTRUCTOR_OFFSET>>2]};this.set_refcount=function(refcount){HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=refcount};this.set_caught=function(caught){caught=caught?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]=caught};this.get_caught=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.CAUGHT_OFFSET>>0]!=0};this.set_rethrown=function(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]=rethrown};this.get_rethrown=function(){return HEAP8[this.ptr+ExceptionInfoAttrs.RETHROWN_OFFSET>>0]!=0};this.init=function(type,destructor){this.set_type(type);this.set_destructor(destructor);this.set_refcount(0);this.set_caught(false);this.set_rethrown(false)};this.add_ref=function(){var value=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=value+1};this.release_ref=function(){var prev=HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2];HEAP32[this.ptr+ExceptionInfoAttrs.REFCOUNT_OFFSET>>2]=prev-1;return prev===1}}function CatchInfo(ptr){this.free=function(){_free(this.ptr);this.ptr=0};this.set_base_ptr=function(basePtr){HEAP32[this.ptr>>2]=basePtr};this.get_base_ptr=function(){return HEAP32[this.ptr>>2]};this.set_adjusted_ptr=function(adjustedPtr){var ptrSize=4;HEAP32[this.ptr+ptrSize>>2]=adjustedPtr};this.get_adjusted_ptr=function(){var ptrSize=4;return HEAP32[this.ptr+ptrSize>>2]};this.get_exception_ptr=function(){var isPointer=___cxa_is_pointer_type(this.get_exception_info().get_type());if(isPointer){return HEAP32[this.get_base_ptr()>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.get_base_ptr()};this.get_exception_info=function(){return new ExceptionInfo(this.get_base_ptr())};if(ptr===undefined){this.ptr=_malloc(8);this.set_adjusted_ptr(0)}else{this.ptr=ptr}}var exceptionCaught=[];function exception_addRef(info){info.add_ref()}function __ZSt18uncaught_exceptionv(){return __ZSt18uncaught_exceptionv.uncaught_exceptions>0}function ___cxa_begin_catch(ptr){var catchInfo=new CatchInfo(ptr);var info=catchInfo.get_exception_info();if(!info.get_caught()){info.set_caught(true);__ZSt18uncaught_exceptionv.uncaught_exceptions--}info.set_rethrown(false);exceptionCaught.push(catchInfo);exception_addRef(info);return catchInfo.get_exception_ptr()}var exceptionLast=0;function ___cxa_free_exception(ptr){return _free(new ExceptionInfo(ptr).ptr)}function exception_decRef(info){if(info.release_ref()&&!info.get_rethrown()){var destructor=info.get_destructor();if(destructor){wasmTable.get(destructor)(info.excPtr)}___cxa_free_exception(info.excPtr)}}function ___cxa_end_catch(){_setThrew(0);var catchInfo=exceptionCaught.pop();exception_decRef(catchInfo.get_exception_info());catchInfo.free();exceptionLast=0}function ___resumeException(catchInfoPtr){var catchInfo=new CatchInfo(catchInfoPtr);var ptr=catchInfo.get_base_ptr();if(!exceptionLast){exceptionLast=ptr}catchInfo.free();throw ptr}var exceptionThrowBuf=0;function ___cxa_find_matching_catch_2(){var thrown=exceptionLast;if(!thrown){return(setTempRet0(0),0)|0}var info=new ExceptionInfo(thrown);var thrownType=info.get_type();var catchInfo=new CatchInfo;catchInfo.set_base_ptr(thrown);if(!thrownType){return(setTempRet0(0),catchInfo.ptr)|0}var typeArray=Array.prototype.slice.call(arguments);if(!exceptionThrowBuf){exceptionThrowBuf=_malloc(4)}HEAP32[exceptionThrowBuf>>2]=thrown;for(var i=0;i>2];if(thrown!==adjusted){catchInfo.set_adjusted_ptr(adjusted)}return(setTempRet0(caughtType),catchInfo.ptr)|0}}return(setTempRet0(thrownType),catchInfo.ptr)|0}function ___cxa_find_matching_catch_3(){var thrown=exceptionLast;if(!thrown){return(setTempRet0(0),0)|0}var info=new ExceptionInfo(thrown);var thrownType=info.get_type();var catchInfo=new CatchInfo;catchInfo.set_base_ptr(thrown);if(!thrownType){return(setTempRet0(0),catchInfo.ptr)|0}var typeArray=Array.prototype.slice.call(arguments);if(!exceptionThrowBuf){exceptionThrowBuf=_malloc(4)}HEAP32[exceptionThrowBuf>>2]=thrown;for(var i=0;i>2];if(thrown!==adjusted){catchInfo.set_adjusted_ptr(adjusted)}return(setTempRet0(caughtType),catchInfo.ptr)|0}}return(setTempRet0(thrownType),catchInfo.ptr)|0}function ___cxa_rethrow(){var catchInfo=exceptionCaught.pop();var info=catchInfo.get_exception_info();var ptr=catchInfo.get_base_ptr();if(!info.get_rethrown()){exceptionCaught.push(catchInfo);info.set_rethrown(true)}else{catchInfo.free()}exceptionLast=ptr;throw ptr}function ___cxa_throw(ptr,type,destructor){var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;if(!("uncaught_exception"in __ZSt18uncaught_exceptionv)){__ZSt18uncaught_exceptionv.uncaught_exceptions=1}else{__ZSt18uncaught_exceptionv.uncaught_exceptions++}throw ptr}function ___cxa_uncaught_exceptions(){return __ZSt18uncaught_exceptionv.uncaught_exceptions}function _gmtime_r(time,tmPtr){var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getUTCSeconds();HEAP32[tmPtr+4>>2]=date.getUTCMinutes();HEAP32[tmPtr+8>>2]=date.getUTCHours();HEAP32[tmPtr+12>>2]=date.getUTCDate();HEAP32[tmPtr+16>>2]=date.getUTCMonth();HEAP32[tmPtr+20>>2]=date.getUTCFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getUTCDay();HEAP32[tmPtr+36>>2]=0;HEAP32[tmPtr+32>>2]=0;var start=Date.UTC(date.getUTCFullYear(),0,1,0,0,0,0);var yday=(date.getTime()-start)/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;if(!_gmtime_r.GMTString)_gmtime_r.GMTString=allocateUTF8("GMT");HEAP32[tmPtr+40>>2]=_gmtime_r.GMTString;return tmPtr}function ___gmtime_r(a0,a1){return _gmtime_r(a0,a1)}function _tzset(){if(_tzset.called)return;_tzset.called=true;HEAP32[__get_timezone()>>2]=(new Date).getTimezoneOffset()*60;var currentYear=(new Date).getFullYear();var winter=new Date(currentYear,0,1);var summer=new Date(currentYear,6,1);HEAP32[__get_daylight()>>2]=Number(winter.getTimezoneOffset()!=summer.getTimezoneOffset());function extractZone(date){var match=date.toTimeString().match(/\(([A-Za-z ]+)\)$/);return match?match[1]:"GMT"}var winterName=extractZone(winter);var summerName=extractZone(summer);var winterNamePtr=allocateUTF8(winterName);var summerNamePtr=allocateUTF8(summerName);if(summer.getTimezoneOffset()>2]=winterNamePtr;HEAP32[__get_tzname()+4>>2]=summerNamePtr}else{HEAP32[__get_tzname()>>2]=summerNamePtr;HEAP32[__get_tzname()+4>>2]=winterNamePtr}}function _localtime_r(time,tmPtr){_tzset();var date=new Date(HEAP32[time>>2]*1e3);HEAP32[tmPtr>>2]=date.getSeconds();HEAP32[tmPtr+4>>2]=date.getMinutes();HEAP32[tmPtr+8>>2]=date.getHours();HEAP32[tmPtr+12>>2]=date.getDate();HEAP32[tmPtr+16>>2]=date.getMonth();HEAP32[tmPtr+20>>2]=date.getFullYear()-1900;HEAP32[tmPtr+24>>2]=date.getDay();var start=new Date(date.getFullYear(),0,1);var yday=(date.getTime()-start.getTime())/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;HEAP32[tmPtr+36>>2]=-(date.getTimezoneOffset()*60);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dst=(summerOffset!=winterOffset&&date.getTimezoneOffset()==Math.min(winterOffset,summerOffset))|0;HEAP32[tmPtr+32>>2]=dst;var zonePtr=HEAP32[__get_tzname()+(dst?4:0)>>2];HEAP32[tmPtr+40>>2]=zonePtr;return tmPtr}function ___localtime_r(a0,a1){return _localtime_r(a0,a1)}function ___map_file(pathname,size){setErrNo(63);return-1}var PATH={splitPath:function(filename){var splitPathRe=/^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;return splitPathRe.exec(filename).slice(1)},normalizeArray:function(parts,allowAboveRoot){var up=0;for(var i=parts.length-1;i>=0;i--){var last=parts[i];if(last==="."){parts.splice(i,1)}else if(last===".."){parts.splice(i,1);up++}else if(up){parts.splice(i,1);up--}}if(allowAboveRoot){for(;up;up--){parts.unshift("..")}}return parts},normalize:function(path){var isAbsolute=path.charAt(0)==="/",trailingSlash=path.substr(-1)==="/";path=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),!isAbsolute).join("/");if(!path&&!isAbsolute){path="."}if(path&&trailingSlash){path+="/"}return(isAbsolute?"/":"")+path},dirname:function(path){var result=PATH.splitPath(path),root=result[0],dir=result[1];if(!root&&!dir){return"."}if(dir){dir=dir.substr(0,dir.length-1)}return root+dir},basename:function(path){if(path==="/")return"/";path=PATH.normalize(path);path=path.replace(/\/$/,"");var lastSlash=path.lastIndexOf("/");if(lastSlash===-1)return path;return path.substr(lastSlash+1)},extname:function(path){return PATH.splitPath(path)[3]},join:function(){var paths=Array.prototype.slice.call(arguments,0);return PATH.normalize(paths.join("/"))},join2:function(l,r){return PATH.normalize(l+"/"+r)}};var PATH_FS={resolve:function(){var resolvedPath="",resolvedAbsolute=false;for(var i=arguments.length-1;i>=-1&&!resolvedAbsolute;i--){var path=i>=0?arguments[i]:FS.cwd();if(typeof path!=="string"){throw new TypeError("Arguments to path.resolve must be strings")}else if(!path){return""}resolvedPath=path+"/"+resolvedPath;resolvedAbsolute=path.charAt(0)==="/"}resolvedPath=PATH.normalizeArray(resolvedPath.split("/").filter(function(p){return!!p}),!resolvedAbsolute).join("/");return(resolvedAbsolute?"/":"")+resolvedPath||"."},relative:function(from,to){from=PATH_FS.resolve(from).substr(1);to=PATH_FS.resolve(to).substr(1);function trim(arr){var start=0;for(;start=0;end--){if(arr[end]!=="")break}if(start>end)return[];return arr.slice(start,end-start+1)}var fromParts=trim(from.split("/"));var toParts=trim(to.split("/"));var length=Math.min(fromParts.length,toParts.length);var samePartsLength=length;for(var i=0;i0){result=buf.slice(0,bytesRead).toString("utf-8")}else{result=null}}else if(typeof window!="undefined"&&typeof window.prompt=="function"){result=window.prompt("Input: ");if(result!==null){result+="\n"}}else if(typeof readline=="function"){result=readline();if(result!==null){result+="\n"}}if(!result){return null}tty.input=intArrayFromString(result,true)}return tty.input.shift()},put_char:function(tty,val){if(val===null||val===10){out(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){out(UTF8ArrayToString(tty.output,0));tty.output=[]}}},default_tty1_ops:{put_char:function(tty,val){if(val===null||val===10){err(UTF8ArrayToString(tty.output,0));tty.output=[]}else{if(val!=0)tty.output.push(val)}},flush:function(tty){if(tty.output&&tty.output.length>0){err(UTF8ArrayToString(tty.output,0));tty.output=[]}}}};var MEMFS={ops_table:null,mount:function(mount){return MEMFS.createNode(null,"/",16384|511,0)},createNode:function(parent,name,mode,dev){if(FS.isBlkdev(mode)||FS.isFIFO(mode)){throw new FS.ErrnoError(63)}if(!MEMFS.ops_table){MEMFS.ops_table={dir:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,lookup:MEMFS.node_ops.lookup,mknod:MEMFS.node_ops.mknod,rename:MEMFS.node_ops.rename,unlink:MEMFS.node_ops.unlink,rmdir:MEMFS.node_ops.rmdir,readdir:MEMFS.node_ops.readdir,symlink:MEMFS.node_ops.symlink},stream:{llseek:MEMFS.stream_ops.llseek}},file:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:{llseek:MEMFS.stream_ops.llseek,read:MEMFS.stream_ops.read,write:MEMFS.stream_ops.write,allocate:MEMFS.stream_ops.allocate,mmap:MEMFS.stream_ops.mmap,msync:MEMFS.stream_ops.msync}},link:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr,readlink:MEMFS.node_ops.readlink},stream:{}},chrdev:{node:{getattr:MEMFS.node_ops.getattr,setattr:MEMFS.node_ops.setattr},stream:FS.chrdev_stream_ops}}}var node=FS.createNode(parent,name,mode,dev);if(FS.isDir(node.mode)){node.node_ops=MEMFS.ops_table.dir.node;node.stream_ops=MEMFS.ops_table.dir.stream;node.contents={}}else if(FS.isFile(node.mode)){node.node_ops=MEMFS.ops_table.file.node;node.stream_ops=MEMFS.ops_table.file.stream;node.usedBytes=0;node.contents=null}else if(FS.isLink(node.mode)){node.node_ops=MEMFS.ops_table.link.node;node.stream_ops=MEMFS.ops_table.link.stream}else if(FS.isChrdev(node.mode)){node.node_ops=MEMFS.ops_table.chrdev.node;node.stream_ops=MEMFS.ops_table.chrdev.stream}node.timestamp=Date.now();if(parent){parent.contents[name]=node}return node},getFileDataAsRegularArray:function(node){if(node.contents&&node.contents.subarray){var arr=[];for(var i=0;i=newCapacity)return;var CAPACITY_DOUBLING_MAX=1024*1024;newCapacity=Math.max(newCapacity,prevCapacity*(prevCapacity>>0);if(prevCapacity!=0)newCapacity=Math.max(newCapacity,256);var oldContents=node.contents;node.contents=new Uint8Array(newCapacity);if(node.usedBytes>0)node.contents.set(oldContents.subarray(0,node.usedBytes),0);return},resizeFileStorage:function(node,newSize){if(node.usedBytes==newSize)return;if(newSize==0){node.contents=null;node.usedBytes=0;return}if(!node.contents||node.contents.subarray){var oldContents=node.contents;node.contents=new Uint8Array(newSize);if(oldContents){node.contents.set(oldContents.subarray(0,Math.min(newSize,node.usedBytes)))}node.usedBytes=newSize;return}if(!node.contents)node.contents=[];if(node.contents.length>newSize)node.contents.length=newSize;else while(node.contents.length=stream.node.usedBytes)return 0;var size=Math.min(stream.node.usedBytes-position,length);if(size>8&&contents.subarray){buffer.set(contents.subarray(position,position+size),offset)}else{for(var i=0;i0||position+lengthe2["timestamp"]){create.push(key);total++}});var remove=[];Object.keys(dst.entries).forEach(function(key){var e=dst.entries[key];var e2=src.entries[key];if(!e2){remove.push(key);total++}});if(!total){return callback(null)}var errored=false;var db=src.type==="remote"?src.db:dst.db;var transaction=db.transaction([IDBFS.DB_STORE_NAME],"readwrite");var store=transaction.objectStore(IDBFS.DB_STORE_NAME);function done(err){if(err&&!errored){errored=true;return callback(err)}}transaction.onerror=function(e){done(this.error);e.preventDefault()};transaction.oncomplete=function(e){if(!errored){callback(null)}};create.sort().forEach(function(path){if(dst.type==="local"){IDBFS.loadRemoteEntry(store,path,function(err,entry){if(err)return done(err);IDBFS.storeLocalEntry(path,entry,done)})}else{IDBFS.loadLocalEntry(path,function(err,entry){if(err)return done(err);IDBFS.storeRemoteEntry(store,path,entry,done)})}});remove.sort().reverse().forEach(function(path){if(dst.type==="local"){IDBFS.removeLocalEntry(path,done)}else{IDBFS.removeRemoteEntry(store,path,done)}})}};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:function(e){if(!(e instanceof FS.ErrnoError))throw e+" : "+stackTrace();return setErrNo(e.errno)},lookupPath:function(path,opts){path=PATH_FS.resolve(FS.cwd(),path);opts=opts||{};if(!path)return{path:"",node:null};var defaults={follow_mount:true,recurse_count:0};for(var key in defaults){if(opts[key]===undefined){opts[key]=defaults[key]}}if(opts.recurse_count>8){throw new FS.ErrnoError(32)}var parts=PATH.normalizeArray(path.split("/").filter(function(p){return!!p}),false);var current=FS.root;var current_path="/";for(var i=0;i40){throw new FS.ErrnoError(32)}}}}return{path:current_path,node:current}},getPath:function(node){var path;while(true){if(FS.isRoot(node)){var mount=node.mount.mountpoint;if(!path)return mount;return mount[mount.length-1]!=="/"?mount+"/"+path:mount+path}path=path?node.name+"/"+path:node.name;node=node.parent}},hashName:function(parentid,name){var hash=0;name=name.toLowerCase();for(var i=0;i>>0)%FS.nameTable.length},hashAddNode:function(node){var hash=FS.hashName(node.parent.id,node.name);node.name_next=FS.nameTable[hash];FS.nameTable[hash]=node},hashRemoveNode:function(node){var hash=FS.hashName(node.parent.id,node.name);if(FS.nameTable[hash]===node){FS.nameTable[hash]=node.name_next}else{var current=FS.nameTable[hash];while(current){if(current.name_next===node){current.name_next=node.name_next;break}current=current.name_next}}},lookupNode:function(parent,name){var errCode=FS.mayLookup(parent);if(errCode){throw new FS.ErrnoError(errCode,parent)}var hash=FS.hashName(parent.id,name);name=name.toLowerCase();for(var node=FS.nameTable[hash];node;node=node.name_next){var nodeName=node.name;nodeName=nodeName.toLowerCase();if(node.parent.id===parent.id&&nodeName===name){return node}}return FS.lookup(parent,name)},createNode:function(parent,name,mode,rdev){var node=new FS.FSNode(parent,name,mode,rdev);FS.hashAddNode(node);return node},destroyNode:function(node){FS.hashRemoveNode(node)},isRoot:function(node){return node===node.parent},isMountpoint:function(node){return!!node.mounted},isFile:function(mode){return(mode&61440)===32768},isDir:function(mode){return(mode&61440)===16384},isLink:function(mode){return(mode&61440)===40960},isChrdev:function(mode){return(mode&61440)===8192},isBlkdev:function(mode){return(mode&61440)===24576},isFIFO:function(mode){return(mode&61440)===4096},isSocket:function(mode){return(mode&49152)===49152},flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(str){var flags=FS.flagModes[str];if(typeof flags==="undefined"){throw new Error("Unknown file open mode: "+str)}return flags},flagsToPermissionString:function(flag){var perms=["r","w","rw"][flag&3];if(flag&512){perms+="w"}return perms},nodePermissions:function(node,perms){if(FS.ignorePermissions){return 0}if(perms.indexOf("r")!==-1&&!(node.mode&292)){return 2}else if(perms.indexOf("w")!==-1&&!(node.mode&146)){return 2}else if(perms.indexOf("x")!==-1&&!(node.mode&73)){return 2}return 0},mayLookup:function(dir){var errCode=FS.nodePermissions(dir,"x");if(errCode)return errCode;if(!dir.node_ops.lookup)return 2;return 0},mayCreate:function(dir,name){try{var node=FS.lookupNode(dir,name);return 20}catch(e){}return FS.nodePermissions(dir,"wx")},mayDelete:function(dir,name,isdir){var node;try{node=FS.lookupNode(dir,name)}catch(e){return e.errno}var errCode=FS.nodePermissions(dir,"wx");if(errCode){return errCode}if(isdir){if(!FS.isDir(node.mode)){return 54}if(FS.isRoot(node)||FS.getPath(node)===FS.cwd()){return 10}}else{if(FS.isDir(node.mode)){return 31}}return 0},mayOpen:function(node,flags){if(!node){return 44}if(FS.isLink(node.mode)){return 32}else if(FS.isDir(node.mode)){if(FS.flagsToPermissionString(flags)!=="r"||flags&512){return 31}}return FS.nodePermissions(node,FS.flagsToPermissionString(flags))},MAX_OPEN_FDS:4096,nextfd:function(fd_start,fd_end){fd_start=fd_start||0;fd_end=fd_end||FS.MAX_OPEN_FDS;for(var fd=fd_start;fd<=fd_end;fd++){if(!FS.streams[fd]){return fd}}throw new FS.ErrnoError(33)},getStream:function(fd){return FS.streams[fd]},createStream:function(stream,fd_start,fd_end){if(!FS.FSStream){FS.FSStream=function(){};FS.FSStream.prototype={object:{get:function(){return this.node},set:function(val){this.node=val}},isRead:{get:function(){return(this.flags&2097155)!==1}},isWrite:{get:function(){return(this.flags&2097155)!==0}},isAppend:{get:function(){return this.flags&1024}}}}var newStream=new FS.FSStream;for(var p in stream){newStream[p]=stream[p]}stream=newStream;var fd=FS.nextfd(fd_start,fd_end);stream.fd=fd;FS.streams[fd]=stream;return stream},closeStream:function(fd){FS.streams[fd]=null},chrdev_stream_ops:{open:function(stream){var device=FS.getDevice(stream.node.rdev);stream.stream_ops=device.stream_ops;if(stream.stream_ops.open){stream.stream_ops.open(stream)}},llseek:function(){throw new FS.ErrnoError(70)}},major:function(dev){return dev>>8},minor:function(dev){return dev&255},makedev:function(ma,mi){return ma<<8|mi},registerDevice:function(dev,ops){FS.devices[dev]={stream_ops:ops}},getDevice:function(dev){return FS.devices[dev]},getMounts:function(mount){var mounts=[];var check=[mount];while(check.length){var m=check.pop();mounts.push(m);check.push.apply(check,m.mounts)}return mounts},syncfs:function(populate,callback){if(typeof populate==="function"){callback=populate;populate=false}FS.syncFSRequests++;if(FS.syncFSRequests>1){err("warning: "+FS.syncFSRequests+" FS.syncfs operations in flight at once, probably just doing extra work")}var mounts=FS.getMounts(FS.root.mount);var completed=0;function doCallback(errCode){FS.syncFSRequests--;return callback(errCode)}function done(errCode){if(errCode){if(!done.errored){done.errored=true;return doCallback(errCode)}return}if(++completed>=mounts.length){doCallback(null)}}mounts.forEach(function(mount){if(!mount.type.syncfs){return done(null)}mount.type.syncfs(mount,populate,done)})},mount:function(type,opts,mountpoint){var root=mountpoint==="/";var pseudo=!mountpoint;var node;if(root&&FS.root){throw new FS.ErrnoError(10)}else if(!root&&!pseudo){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});mountpoint=lookup.path;node=lookup.node;if(FS.isMountpoint(node)){throw new FS.ErrnoError(10)}if(!FS.isDir(node.mode)){throw new FS.ErrnoError(54)}}var mount={type:type,opts:opts,mountpoint:mountpoint,mounts:[]};var mountRoot=type.mount(mount);mountRoot.mount=mount;mount.root=mountRoot;if(root){FS.root=mountRoot}else if(node){node.mounted=mount;if(node.mount){node.mount.mounts.push(mount)}}return mountRoot},unmount:function(mountpoint){var lookup=FS.lookupPath(mountpoint,{follow_mount:false});if(!FS.isMountpoint(lookup.node)){throw new FS.ErrnoError(28)}var node=lookup.node;var mount=node.mounted;var mounts=FS.getMounts(mount);Object.keys(FS.nameTable).forEach(function(hash){var current=FS.nameTable[hash];while(current){var next=current.name_next;if(mounts.indexOf(current.mount)!==-1){FS.destroyNode(current)}current=next}});node.mounted=null;var idx=node.mount.mounts.indexOf(mount);node.mount.mounts.splice(idx,1)},lookup:function(parent,name){return parent.node_ops.lookup(parent,name)},mknod:function(path,mode,dev){var lookup=FS.lookupPath(path,{parent:true});var parent=lookup.node;var name=PATH.basename(path);if(!name||name==="."||name===".."){throw new FS.ErrnoError(28)}var errCode=FS.mayCreate(parent,name);if(errCode){throw new FS.ErrnoError(errCode)}if(!parent.node_ops.mknod){throw new FS.ErrnoError(63)}return parent.node_ops.mknod(parent,name,mode,dev)},create:function(path,mode){mode=mode!==undefined?mode:438;mode&=4095;mode|=32768;return FS.mknod(path,mode,0)},mkdir:function(path,mode){mode=mode!==undefined?mode:511;mode&=511|512;mode|=16384;return FS.mknod(path,mode,0)},mkdirTree:function(path,mode){var dirs=path.split("/");var d="";for(var i=0;ithis.length-1||idx<0){return undefined}var chunkOffset=idx%this.chunkSize;var chunkNum=idx/this.chunkSize|0;return this.getter(chunkNum)[chunkOffset]};LazyUint8Array.prototype.setDataGetter=function LazyUint8Array_setDataGetter(getter){this.getter=getter};LazyUint8Array.prototype.cacheLength=function LazyUint8Array_cacheLength(){var xhr=new XMLHttpRequest;xhr.open("HEAD",url,false);xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);var datalength=Number(xhr.getResponseHeader("Content-length"));var header;var hasByteServing=(header=xhr.getResponseHeader("Accept-Ranges"))&&header==="bytes";var usesGzip=(header=xhr.getResponseHeader("Content-Encoding"))&&header==="gzip";var chunkSize=1024*1024;if(!hasByteServing)chunkSize=datalength;var doXHR=function(from,to){if(from>to)throw new Error("invalid range ("+from+", "+to+") or no bytes requested!");if(to>datalength-1)throw new Error("only "+datalength+" bytes available! programmer error!");var xhr=new XMLHttpRequest;xhr.open("GET",url,false);if(datalength!==chunkSize)xhr.setRequestHeader("Range","bytes="+from+"-"+to);if(typeof Uint8Array!="undefined")xhr.responseType="arraybuffer";if(xhr.overrideMimeType){xhr.overrideMimeType("text/plain; charset=x-user-defined")}xhr.send(null);if(!(xhr.status>=200&&xhr.status<300||xhr.status===304))throw new Error("Couldn't load "+url+". Status: "+xhr.status);if(xhr.response!==undefined){return new Uint8Array(xhr.response||[])}else{return intArrayFromString(xhr.responseText||"",true)}};var lazyArray=this;lazyArray.setDataGetter(function(chunkNum){var start=chunkNum*chunkSize;var end=(chunkNum+1)*chunkSize-1;end=Math.min(end,datalength-1);if(typeof lazyArray.chunks[chunkNum]==="undefined"){lazyArray.chunks[chunkNum]=doXHR(start,end)}if(typeof lazyArray.chunks[chunkNum]==="undefined")throw new Error("doXHR failed!");return lazyArray.chunks[chunkNum]});if(usesGzip||!datalength){chunkSize=datalength=1;datalength=this.getter(0).length;chunkSize=datalength;out("LazyFiles on gzip forces download of the whole file when length is accessed")}this._length=datalength;this._chunkSize=chunkSize;this.lengthKnown=true};if(typeof XMLHttpRequest!=="undefined"){if(!ENVIRONMENT_IS_WORKER)throw"Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc";var lazyArray=new LazyUint8Array;Object.defineProperties(lazyArray,{length:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._length}},chunkSize:{get:function(){if(!this.lengthKnown){this.cacheLength()}return this._chunkSize}}});var properties={isDevice:false,contents:lazyArray}}else{var properties={isDevice:false,url:url}}var node=FS.createFile(parent,name,properties,canRead,canWrite);if(properties.contents){node.contents=properties.contents}else if(properties.url){node.contents=null;node.url=properties.url}Object.defineProperties(node,{usedBytes:{get:function(){return this.contents.length}}});var stream_ops={};var keys=Object.keys(node.stream_ops);keys.forEach(function(key){var fn=node.stream_ops[key];stream_ops[key]=function forceLoadLazyFile(){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(29)}return fn.apply(null,arguments)}});stream_ops.read=function stream_ops_read(stream,buffer,offset,length,position){if(!FS.forceLoadFile(node)){throw new FS.ErrnoError(29)}var contents=stream.node.contents;if(position>=contents.length)return 0;var size=Math.min(contents.length-position,length);if(contents.slice){for(var i=0;i>2]=stat.dev;HEAP32[buf+4>>2]=0;HEAP32[buf+8>>2]=stat.ino;HEAP32[buf+12>>2]=stat.mode;HEAP32[buf+16>>2]=stat.nlink;HEAP32[buf+20>>2]=stat.uid;HEAP32[buf+24>>2]=stat.gid;HEAP32[buf+28>>2]=stat.rdev;HEAP32[buf+32>>2]=0;tempI64=[stat.size>>>0,(tempDouble=stat.size,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+40>>2]=tempI64[0],HEAP32[buf+44>>2]=tempI64[1];HEAP32[buf+48>>2]=4096;HEAP32[buf+52>>2]=stat.blocks;HEAP32[buf+56>>2]=stat.atime.getTime()/1e3|0;HEAP32[buf+60>>2]=0;HEAP32[buf+64>>2]=stat.mtime.getTime()/1e3|0;HEAP32[buf+68>>2]=0;HEAP32[buf+72>>2]=stat.ctime.getTime()/1e3|0;HEAP32[buf+76>>2]=0;tempI64=[stat.ino>>>0,(tempDouble=stat.ino,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[buf+80>>2]=tempI64[0],HEAP32[buf+84>>2]=tempI64[1];return 0},doMsync:function(addr,stream,len,flags,offset){var buffer=HEAPU8.slice(addr,addr+len);FS.msync(stream,buffer,offset,len,flags)},doMkdir:function(path,mode){path=PATH.normalize(path);if(path[path.length-1]==="/")path=path.substr(0,path.length-1);FS.mkdir(path,mode,0);return 0},doMknod:function(path,mode,dev){switch(mode&61440){case 32768:case 8192:case 24576:case 4096:case 49152:break;default:return-28}FS.mknod(path,mode,dev);return 0},doReadlink:function(path,buf,bufsize){if(bufsize<=0)return-28;var ret=FS.readlink(path);var len=Math.min(bufsize,lengthBytesUTF8(ret));var endChar=HEAP8[buf+len];stringToUTF8(ret,buf,bufsize+1);HEAP8[buf+len]=endChar;return len},doAccess:function(path,amode){if(amode&~7){return-28}var node;var lookup=FS.lookupPath(path,{follow:true});node=lookup.node;if(!node){return-44}var perms="";if(amode&4)perms+="r";if(amode&2)perms+="w";if(amode&1)perms+="x";if(perms&&FS.nodePermissions(node,perms)){return-2}return 0},doDup:function(path,flags,suggestFD){var suggest=FS.getStream(suggestFD);if(suggest)FS.close(suggest);return FS.open(path,flags,0,suggestFD,suggestFD).fd},doReadv:function(stream,iov,iovcnt,offset){var ret=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.read(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr;if(curr>2];var len=HEAP32[iov+(i*8+4)>>2];var curr=FS.write(stream,HEAP8,ptr,len,offset);if(curr<0)return-1;ret+=curr}return ret},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},getStreamFromFD:function(fd){var stream=FS.getStream(fd);if(!stream)throw new FS.ErrnoError(8);return stream},get64:function(low,high){return low}};function ___sys__newselect(nfds,readfds,writefds,exceptfds,timeout){try{var total=0;var srcReadLow=readfds?HEAP32[readfds>>2]:0,srcReadHigh=readfds?HEAP32[readfds+4>>2]:0;var srcWriteLow=writefds?HEAP32[writefds>>2]:0,srcWriteHigh=writefds?HEAP32[writefds+4>>2]:0;var srcExceptLow=exceptfds?HEAP32[exceptfds>>2]:0,srcExceptHigh=exceptfds?HEAP32[exceptfds+4>>2]:0;var dstReadLow=0,dstReadHigh=0;var dstWriteLow=0,dstWriteHigh=0;var dstExceptLow=0,dstExceptHigh=0;var allLow=(readfds?HEAP32[readfds>>2]:0)|(writefds?HEAP32[writefds>>2]:0)|(exceptfds?HEAP32[exceptfds>>2]:0);var allHigh=(readfds?HEAP32[readfds+4>>2]:0)|(writefds?HEAP32[writefds+4>>2]:0)|(exceptfds?HEAP32[exceptfds+4>>2]:0);var check=function(fd,low,high,val){return fd<32?low&val:high&val};for(var fd=0;fd>2]=dstReadLow;HEAP32[readfds+4>>2]=dstReadHigh}if(writefds){HEAP32[writefds>>2]=dstWriteLow;HEAP32[writefds+4>>2]=dstWriteHigh}if(exceptfds){HEAP32[exceptfds>>2]=dstExceptLow;HEAP32[exceptfds+4>>2]=dstExceptHigh}return total}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_access(path,amode){try{path=SYSCALLS.getStr(path);return SYSCALLS.doAccess(path,amode)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_dup2(oldfd,suggestFD){try{var old=SYSCALLS.getStreamFromFD(oldfd);if(old.fd===suggestFD)return suggestFD;return SYSCALLS.doDup(old.path,old.flags,suggestFD)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_dup3(fd,suggestFD,flags){try{var old=SYSCALLS.getStreamFromFD(fd);if(old.fd===suggestFD)return-28;return SYSCALLS.doDup(old.path,old.flags,suggestFD)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_fcntl64(fd,cmd,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(cmd){case 0:{var arg=SYSCALLS.get();if(arg<0){return-28}var newStream;newStream=FS.open(stream.path,stream.flags,0,arg);return newStream.fd}case 1:case 2:return 0;case 3:return stream.flags;case 4:{var arg=SYSCALLS.get();stream.flags|=arg;return 0}case 12:{var arg=SYSCALLS.get();var offset=0;HEAP16[arg+offset>>1]=2;return 0}case 13:case 14:return 0;case 16:case 8:return-28;case 9:setErrNo(28);return-1;default:{return-28}}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_fstat64(fd,buf){try{var stream=SYSCALLS.getStreamFromFD(fd);return SYSCALLS.doStat(FS.stat,stream.path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_getcwd(buf,size){try{if(size===0)return-28;var cwd=FS.cwd();var cwdLengthInBytes=lengthBytesUTF8(cwd);if(size>>0,(tempDouble=id,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos>>2]=tempI64[0],HEAP32[dirp+pos+4>>2]=tempI64[1];tempI64=[(idx+1)*struct_size>>>0,(tempDouble=(idx+1)*struct_size,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[dirp+pos+8>>2]=tempI64[0],HEAP32[dirp+pos+12>>2]=tempI64[1];HEAP16[dirp+pos+16>>1]=280;HEAP8[dirp+pos+18>>0]=type;stringToUTF8(name,dirp+pos+19,256);pos+=struct_size;idx+=1}FS.llseek(stream,idx*struct_size,0);return pos}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_getpid(){return 42}function ___sys_getegid32(){return 0}function ___sys_getuid32(){return ___sys_getegid32()}function ___sys_ioctl(fd,op,varargs){SYSCALLS.varargs=varargs;try{var stream=SYSCALLS.getStreamFromFD(fd);switch(op){case 21509:case 21505:{if(!stream.tty)return-59;return 0}case 21510:case 21511:case 21512:case 21506:case 21507:case 21508:{if(!stream.tty)return-59;return 0}case 21519:{if(!stream.tty)return-59;var argp=SYSCALLS.get();HEAP32[argp>>2]=0;return 0}case 21520:{if(!stream.tty)return-59;return-28}case 21531:{var argp=SYSCALLS.get();return FS.ioctl(stream,op,argp)}case 21523:{if(!stream.tty)return-59;return 0}case 21524:{if(!stream.tty)return-59;return 0}default:abort("bad ioctl syscall "+op)}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_lstat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.lstat,path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_mkdir(path,mode){try{path=SYSCALLS.getStr(path);return SYSCALLS.doMkdir(path,mode)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function syscallMunmap(addr,len){if((addr|0)===-1||len===0){return-28}var info=SYSCALLS.mappings[addr];if(!info)return 0;if(len===info.len){var stream=FS.getStream(info.fd);if(info.prot&2){SYSCALLS.doMsync(addr,stream,len,info.flags,info.offset)}FS.munmap(stream);SYSCALLS.mappings[addr]=null;if(info.allocated){_free(info.malloc)}}return 0}function ___sys_munmap(addr,len){try{return syscallMunmap(addr,len)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_open(path,flags,varargs){SYSCALLS.varargs=varargs;try{var pathname=SYSCALLS.getStr(path);var mode=SYSCALLS.get();var stream=FS.open(pathname,flags,mode);return stream.fd}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_poll(fds,nfds,timeout){try{var nonzero=0;for(var i=0;i>2];var events=HEAP16[pollfd+4>>1];var mask=32;var stream=FS.getStream(fd);if(stream){mask=SYSCALLS.DEFAULT_POLLMASK;if(stream.stream_ops.poll){mask=stream.stream_ops.poll(stream)}}mask&=events|8|16;if(mask)nonzero++;HEAP16[pollfd+6>>1]=mask}return nonzero}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_read(fd,buf,count){try{var stream=SYSCALLS.getStreamFromFD(fd);return FS.read(stream,HEAP8,buf,count)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_readlink(path,buf,bufsize){try{path=SYSCALLS.getStr(path);return SYSCALLS.doReadlink(path,buf,bufsize)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_rename(old_path,new_path){try{old_path=SYSCALLS.getStr(old_path);new_path=SYSCALLS.getStr(new_path);FS.rename(old_path,new_path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_rmdir(path){try{path=SYSCALLS.getStr(path);FS.rmdir(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var SOCKFS={mount:function(mount){Module["websocket"]=Module["websocket"]&&"object"===typeof Module["websocket"]?Module["websocket"]:{};Module["websocket"]._callbacks={};Module["websocket"]["on"]=function(event,callback){if("function"===typeof callback){this._callbacks[event]=callback}return this};Module["websocket"].emit=function(event,param){if("function"===typeof this._callbacks[event]){this._callbacks[event].call(this,param)}};return FS.createNode(null,"/",16384|511,0)},createSocket:function(family,type,protocol){type&=~526336;var streaming=type==1;if(protocol){assert(streaming==(protocol==6))}var sock={family:family,type:type,protocol:protocol,server:null,error:null,peers:{},pending:[],recv_queue:[],sock_ops:SOCKFS.websocket_sock_ops};var name=SOCKFS.nextname();var node=FS.createNode(SOCKFS.root,name,49152,0);node.sock=sock;var stream=FS.createStream({path:name,node:node,flags:FS.modeStringToFlags("r+"),seekable:false,stream_ops:SOCKFS.stream_ops});sock.stream=stream;return sock},getSocket:function(fd){var stream=FS.getStream(fd);if(!stream||!FS.isSocket(stream.node.mode)){return null}return stream.node.sock},stream_ops:{poll:function(stream){var sock=stream.node.sock;return sock.sock_ops.poll(sock)},ioctl:function(stream,request,varargs){var sock=stream.node.sock;return sock.sock_ops.ioctl(sock,request,varargs)},read:function(stream,buffer,offset,length,position){var sock=stream.node.sock;var msg=sock.sock_ops.recvmsg(sock,length);if(!msg){return 0}buffer.set(msg.buffer,offset);return msg.buffer.length},write:function(stream,buffer,offset,length,position){var sock=stream.node.sock;return sock.sock_ops.sendmsg(sock,buffer,offset,length)},close:function(stream){var sock=stream.node.sock;sock.sock_ops.close(sock)}},nextname:function(){if(!SOCKFS.nextname.current){SOCKFS.nextname.current=0}return"socket["+SOCKFS.nextname.current+++"]"},websocket_sock_ops:{createPeer:function(sock,addr,port){var ws;if(typeof addr==="object"){ws=addr;addr=null;port=null}if(ws){if(ws._socket){addr=ws._socket.remoteAddress;port=ws._socket.remotePort}else{var result=/ws[s]?:\/\/([^:]+):(\d+)/.exec(ws.url);if(!result){throw new Error("WebSocket URL must be in the format ws(s)://address:port")}addr=result[1];port=parseInt(result[2],10)}}else{try{var runtimeConfig=Module["websocket"]&&"object"===typeof Module["websocket"];var url="ws:#".replace("#","//");if(runtimeConfig){if("string"===typeof Module["websocket"]["url"]){url=Module["websocket"]["url"]}}if(url==="ws://"||url==="wss://"){var parts=addr.split("/");url=url+parts[0]+":"+port+"/"+parts.slice(1).join("/")}var subProtocols="binary";if(runtimeConfig){if("string"===typeof Module["websocket"]["subprotocol"]){subProtocols=Module["websocket"]["subprotocol"]}}var opts=undefined;if(subProtocols!=="null"){subProtocols=subProtocols.replace(/^ +| +$/g,"").split(/ *, */);opts=ENVIRONMENT_IS_NODE?{"protocol":subProtocols.toString()}:subProtocols}if(runtimeConfig&&null===Module["websocket"]["subprotocol"]){subProtocols="null";opts=undefined}var WebSocketConstructor;if(ENVIRONMENT_IS_NODE){WebSocketConstructor=require("ws")}else{WebSocketConstructor=WebSocket}ws=new WebSocketConstructor(url,opts);ws.binaryType="arraybuffer"}catch(e){throw new FS.ErrnoError(ERRNO_CODES.EHOSTUNREACH)}}var peer={addr:addr,port:port,socket:ws,dgram_send_queue:[]};SOCKFS.websocket_sock_ops.addPeer(sock,peer);SOCKFS.websocket_sock_ops.handlePeerEvents(sock,peer);if(sock.type===2&&typeof sock.sport!=="undefined"){peer.dgram_send_queue.push(new Uint8Array([255,255,255,255,"p".charCodeAt(0),"o".charCodeAt(0),"r".charCodeAt(0),"t".charCodeAt(0),(sock.sport&65280)>>8,sock.sport&255]))}return peer},getPeer:function(sock,addr,port){return sock.peers[addr+":"+port]},addPeer:function(sock,peer){sock.peers[peer.addr+":"+peer.port]=peer},removePeer:function(sock,peer){delete sock.peers[peer.addr+":"+peer.port]},handlePeerEvents:function(sock,peer){var first=true;var handleOpen=function(){Module["websocket"].emit("open",sock.stream.fd);try{var queued=peer.dgram_send_queue.shift();while(queued){peer.socket.send(queued);queued=peer.dgram_send_queue.shift()}}catch(e){peer.socket.close()}};function handleMessage(data){if(typeof data==="string"){var encoder=new TextEncoder;data=encoder.encode(data)}else{assert(data.byteLength!==undefined);if(data.byteLength==0){return}else{data=new Uint8Array(data)}}var wasfirst=first;first=false;if(wasfirst&&data.length===10&&data[0]===255&&data[1]===255&&data[2]===255&&data[3]===255&&data[4]==="p".charCodeAt(0)&&data[5]==="o".charCodeAt(0)&&data[6]==="r".charCodeAt(0)&&data[7]==="t".charCodeAt(0)){var newport=data[8]<<8|data[9];SOCKFS.websocket_sock_ops.removePeer(sock,peer);peer.port=newport;SOCKFS.websocket_sock_ops.addPeer(sock,peer);return}sock.recv_queue.push({addr:peer.addr,port:peer.port,data:data});Module["websocket"].emit("message",sock.stream.fd)}if(ENVIRONMENT_IS_NODE){peer.socket.on("open",handleOpen);peer.socket.on("message",function(data,flags){if(!flags.binary){return}handleMessage(new Uint8Array(data).buffer)});peer.socket.on("close",function(){Module["websocket"].emit("close",sock.stream.fd)});peer.socket.on("error",function(error){sock.error=ERRNO_CODES.ECONNREFUSED;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])})}else{peer.socket.onopen=handleOpen;peer.socket.onclose=function(){Module["websocket"].emit("close",sock.stream.fd)};peer.socket.onmessage=function peer_socket_onmessage(event){handleMessage(event.data)};peer.socket.onerror=function(error){sock.error=ERRNO_CODES.ECONNREFUSED;Module["websocket"].emit("error",[sock.stream.fd,sock.error,"ECONNREFUSED: Connection refused"])}}},poll:function(sock){if(sock.type===1&&sock.server){return sock.pending.length?64|1:0}var mask=0;var dest=sock.type===1?SOCKFS.websocket_sock_ops.getPeer(sock,sock.daddr,sock.dport):null;if(sock.recv_queue.length||!dest||dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=64|1}if(!dest||dest&&dest.socket.readyState===dest.socket.OPEN){mask|=4}if(dest&&dest.socket.readyState===dest.socket.CLOSING||dest&&dest.socket.readyState===dest.socket.CLOSED){mask|=16}return mask},ioctl:function(sock,request,arg){switch(request){case 21531:var bytes=0;if(sock.recv_queue.length){bytes=sock.recv_queue[0].data.length}HEAP32[arg>>2]=bytes;return 0;default:return ERRNO_CODES.EINVAL}},close:function(sock){if(sock.server){try{sock.server.close()}catch(e){}sock.server=null}var peers=Object.keys(sock.peers);for(var i=0;i>>0}function jstoi_q(str){return parseInt(str)}function __inet_pton6_raw(str){var words;var w,offset,z;var valid6regx=/^((?=.*::)(?!.*::.+::)(::)?([\dA-F]{1,4}:(:|\b)|){5}|([\dA-F]{1,4}:){6})((([\dA-F]{1,4}((?!\3)::|:\b|$))|(?!\2\3)){2}|(((2[0-4]|1\d|[1-9])?\d|25[0-5])\.?\b){4})$/i;var parts=[];if(!valid6regx.test(str)){return null}if(str==="::"){return[0,0,0,0,0,0,0,0]}if(str.indexOf("::")===0){str=str.replace("::","Z:")}else{str=str.replace("::",":Z:")}if(str.indexOf(".")>0){str=str.replace(new RegExp("[.]","g"),":");words=str.split(":");words[words.length-4]=jstoi_q(words[words.length-4])+jstoi_q(words[words.length-3])*256;words[words.length-3]=jstoi_q(words[words.length-2])+jstoi_q(words[words.length-1])*256;words=words.slice(0,words.length-2)}else{words=str.split(":")}offset=0;z=0;for(w=0;w>8&255)+"."+(addr>>16&255)+"."+(addr>>24&255)}function __inet_ntop6_raw(ints){var str="";var word=0;var longest=0;var lastzero=0;var zstart=0;var len=0;var i=0;var parts=[ints[0]&65535,ints[0]>>16,ints[1]&65535,ints[1]>>16,ints[2]&65535,ints[2]>>16,ints[3]&65535,ints[3]>>16];var hasipv4=true;var v4part="";for(i=0;i<5;i++){if(parts[i]!==0){hasipv4=false;break}}if(hasipv4){v4part=__inet_ntop4_raw(parts[6]|parts[7]<<16);if(parts[5]===-1){str="::ffff:";str+=v4part;return str}if(parts[5]===0){str="::";if(v4part==="0.0.0.0")v4part="";if(v4part==="0.0.0.1")v4part="1";str+=v4part;return str}}for(word=0;word<8;word++){if(parts[word]===0){if(word-lastzero>1){len=0}lastzero=word;len++}if(len>longest){longest=len;zstart=word-longest+1}}for(word=0;word<8;word++){if(longest>1){if(parts[word]===0&&word>=zstart&&word>1];var port=_ntohs(HEAPU16[sa+2>>1]);var addr;switch(family){case 2:if(salen!==16){return{errno:28}}addr=HEAP32[sa+4>>2];addr=__inet_ntop4_raw(addr);break;case 10:if(salen!==28){return{errno:28}}addr=[HEAP32[sa+8>>2],HEAP32[sa+12>>2],HEAP32[sa+16>>2],HEAP32[sa+20>>2]];addr=__inet_ntop6_raw(addr);break;default:return{errno:5}}return{family:family,addr:addr,port:port}}function __write_sockaddr(sa,family,addr,port){switch(family){case 2:addr=__inet_pton4_raw(addr);HEAP16[sa>>1]=family;HEAP32[sa+4>>2]=addr;HEAP16[sa+2>>1]=_htons(port);break;case 10:addr=__inet_pton6_raw(addr);HEAP32[sa>>2]=family;HEAP32[sa+8>>2]=addr[0];HEAP32[sa+12>>2]=addr[1];HEAP32[sa+16>>2]=addr[2];HEAP32[sa+20>>2]=addr[3];HEAP16[sa+2>>1]=_htons(port);HEAP32[sa+4>>2]=0;HEAP32[sa+24>>2]=0;break;default:return{errno:5}}return{}}function ___sys_socketcall(call,socketvararg){try{SYSCALLS.varargs=socketvararg;var getSocketFromFD=function(){var socket=SOCKFS.getSocket(SYSCALLS.get());if(!socket)throw new FS.ErrnoError(8);return socket};var getSocketAddress=function(allowNull){var addrp=SYSCALLS.get(),addrlen=SYSCALLS.get();if(allowNull&&addrp===0)return null;var info=__read_sockaddr(addrp,addrlen);if(info.errno)throw new FS.ErrnoError(info.errno);info.addr=DNS.lookup_addr(info.addr)||info.addr;return info};switch(call){case 1:{var domain=SYSCALLS.get(),type=SYSCALLS.get(),protocol=SYSCALLS.get();var sock=SOCKFS.createSocket(domain,type,protocol);return sock.stream.fd}case 2:{var sock=getSocketFromFD(),info=getSocketAddress();sock.sock_ops.bind(sock,info.addr,info.port);return 0}case 3:{var sock=getSocketFromFD(),info=getSocketAddress();sock.sock_ops.connect(sock,info.addr,info.port);return 0}case 4:{var sock=getSocketFromFD(),backlog=SYSCALLS.get();sock.sock_ops.listen(sock,backlog);return 0}case 5:{var sock=getSocketFromFD(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();var newsock=sock.sock_ops.accept(sock);if(addr){var res=__write_sockaddr(addr,newsock.family,DNS.lookup_name(newsock.daddr),newsock.dport)}return newsock.stream.fd}case 6:{var sock=getSocketFromFD(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();var res=__write_sockaddr(addr,sock.family,DNS.lookup_name(sock.saddr||"0.0.0.0"),sock.sport);return 0}case 7:{var sock=getSocketFromFD(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();if(!sock.daddr){return-53}var res=__write_sockaddr(addr,sock.family,DNS.lookup_name(sock.daddr),sock.dport);return 0}case 11:{var sock=getSocketFromFD(),message=SYSCALLS.get(),length=SYSCALLS.get(),flags=SYSCALLS.get(),dest=getSocketAddress(true);if(!dest){return FS.write(sock.stream,HEAP8,message,length)}else{return sock.sock_ops.sendmsg(sock,HEAP8,message,length,dest.addr,dest.port)}}case 12:{var sock=getSocketFromFD(),buf=SYSCALLS.get(),len=SYSCALLS.get(),flags=SYSCALLS.get(),addr=SYSCALLS.get(),addrlen=SYSCALLS.get();var msg=sock.sock_ops.recvmsg(sock,len);if(!msg)return 0;if(addr){var res=__write_sockaddr(addr,sock.family,DNS.lookup_name(msg.addr),msg.port)}HEAPU8.set(msg.buffer,buf);return msg.buffer.byteLength}case 14:{return-50}case 15:{var sock=getSocketFromFD(),level=SYSCALLS.get(),optname=SYSCALLS.get(),optval=SYSCALLS.get(),optlen=SYSCALLS.get();if(level===1){if(optname===4){HEAP32[optval>>2]=sock.error;HEAP32[optlen>>2]=4;sock.error=null;return 0}}return-50}case 16:{var sock=getSocketFromFD(),message=SYSCALLS.get(),flags=SYSCALLS.get();var iov=HEAP32[message+8>>2];var num=HEAP32[message+12>>2];var addr,port;var name=HEAP32[message>>2];var namelen=HEAP32[message+4>>2];if(name){var info=__read_sockaddr(name,namelen);if(info.errno)return-info.errno;port=info.port;addr=DNS.lookup_addr(info.addr)||info.addr}var total=0;for(var i=0;i>2]}var view=new Uint8Array(total);var offset=0;for(var i=0;i>2];var iovlen=HEAP32[iov+(8*i+4)>>2];for(var j=0;j>0]}}return sock.sock_ops.sendmsg(sock,view,0,total,addr,port)}case 17:{var sock=getSocketFromFD(),message=SYSCALLS.get(),flags=SYSCALLS.get();var iov=HEAP32[message+8>>2];var num=HEAP32[message+12>>2];var total=0;for(var i=0;i>2]}var msg=sock.sock_ops.recvmsg(sock,total);if(!msg)return 0;var name=HEAP32[message>>2];if(name){var res=__write_sockaddr(name,sock.family,DNS.lookup_name(msg.addr),msg.port)}var bytesRead=0;var bytesRemaining=msg.buffer.byteLength;for(var i=0;bytesRemaining>0&&i>2];var iovlen=HEAP32[iov+(8*i+4)>>2];if(!iovlen){continue}var length=Math.min(iovlen,bytesRemaining);var buf=msg.buffer.subarray(bytesRead,bytesRead+length);HEAPU8.set(buf,iovbase+bytesRead);bytesRead+=length;bytesRemaining-=length}return bytesRead}default:{return-52}}}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_stat64(path,buf){try{path=SYSCALLS.getStr(path);return SYSCALLS.doStat(FS.stat,path,buf)}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_uname(buf){try{if(!buf)return-21;var layout={"__size__":390,"sysname":0,"nodename":65,"release":130,"version":195,"machine":260,"domainname":325};var copyString=function(element,value){var offset=layout[element];writeAsciiToMemory(value,buf+offset)};copyString("sysname","Emscripten");copyString("nodename","emscripten");copyString("release","1.0");copyString("version","#1");copyString("machine","x86-JS");return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function ___sys_unlink(path){try{path=SYSCALLS.getStr(path);FS.unlink(path);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return-e.errno}}function _abort(){abort()}function _emscripten_set_main_loop_timing(mode,value){Browser.mainLoop.timingMode=mode;Browser.mainLoop.timingValue=value;if(!Browser.mainLoop.func){return 1}if(mode==0){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setTimeout(){var timeUntilNextTick=Math.max(0,Browser.mainLoop.tickStartTime+value-_emscripten_get_now())|0;setTimeout(Browser.mainLoop.runner,timeUntilNextTick)};Browser.mainLoop.method="timeout"}else if(mode==1){Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_rAF(){Browser.requestAnimationFrame(Browser.mainLoop.runner)};Browser.mainLoop.method="rAF"}else if(mode==2){if(typeof setImmediate==="undefined"){var setImmediates=[];var emscriptenMainLoopMessageId="setimmediate";var Browser_setImmediate_messageHandler=function(event){if(event.data===emscriptenMainLoopMessageId||event.data.target===emscriptenMainLoopMessageId){event.stopPropagation();setImmediates.shift()()}};addEventListener("message",Browser_setImmediate_messageHandler,true);setImmediate=function Browser_emulated_setImmediate(func){setImmediates.push(func);if(ENVIRONMENT_IS_WORKER){if(Module["setImmediates"]===undefined)Module["setImmediates"]=[];Module["setImmediates"].push(func);postMessage({target:emscriptenMainLoopMessageId})}else postMessage(emscriptenMainLoopMessageId,"*")}}Browser.mainLoop.scheduler=function Browser_mainLoop_scheduler_setImmediate(){setImmediate(Browser.mainLoop.runner)};Browser.mainLoop.method="immediate"}return 0}function setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg,noSetTiming){noExitRuntime=true;assert(!Browser.mainLoop.func,"emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.");Browser.mainLoop.func=browserIterationFunc;Browser.mainLoop.arg=arg;var thisMainLoopId=Browser.mainLoop.currentlyRunningMainloop;Browser.mainLoop.runner=function Browser_mainLoop_runner(){if(ABORT)return;if(Browser.mainLoop.queue.length>0){var start=Date.now();var blocker=Browser.mainLoop.queue.shift();blocker.func(blocker.arg);if(Browser.mainLoop.remainingBlockers){var remaining=Browser.mainLoop.remainingBlockers;var next=remaining%1==0?remaining-1:Math.floor(remaining);if(blocker.counted){Browser.mainLoop.remainingBlockers=next}else{next=next+.5;Browser.mainLoop.remainingBlockers=(8*remaining+next)/9}}console.log('main loop blocker "'+blocker.name+'" took '+(Date.now()-start)+" ms");Browser.mainLoop.updateStatus();if(thisMainLoopId1&&Browser.mainLoop.currentFrameNumber%Browser.mainLoop.timingValue!=0){Browser.mainLoop.scheduler();return}else if(Browser.mainLoop.timingMode==0){Browser.mainLoop.tickStartTime=_emscripten_get_now()}GL.newRenderingFrameStarted();Browser.mainLoop.runIter(browserIterationFunc);if(thisMainLoopId0)_emscripten_set_main_loop_timing(0,1e3/fps);else _emscripten_set_main_loop_timing(1,1);Browser.mainLoop.scheduler()}if(simulateInfiniteLoop){throw"unwind"}}var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function(){Browser.mainLoop.scheduler=null;Browser.mainLoop.currentlyRunningMainloop++},resume:function(){Browser.mainLoop.currentlyRunningMainloop++;var timingMode=Browser.mainLoop.timingMode;var timingValue=Browser.mainLoop.timingValue;var func=Browser.mainLoop.func;Browser.mainLoop.func=null;setMainLoop(func,0,false,Browser.mainLoop.arg,true);_emscripten_set_main_loop_timing(timingMode,timingValue);Browser.mainLoop.scheduler()},updateStatus:function(){if(Module["setStatus"]){var message=Module["statusMessage"]||"Please wait...";var remaining=Browser.mainLoop.remainingBlockers;var expected=Browser.mainLoop.expectedBlockers;if(remaining){if(remaining=6){var curr=leftchar>>leftbits-6&63;leftbits-=6;ret+=BASE[curr]}}if(leftbits==2){ret+=BASE[(leftchar&3)<<4];ret+=PAD+PAD}else if(leftbits==4){ret+=BASE[(leftchar&15)<<2];ret+=PAD}return ret}audio.src="data:audio/x-"+name.substr(-3)+";base64,"+encode64(byteArray);finish(audio)};audio.src=url;Browser.safeSetTimeout(function(){finish(audio)},1e4)}else{return fail()}};Module["preloadPlugins"].push(audioPlugin);function pointerLockChange(){Browser.pointerLock=document["pointerLockElement"]===Module["canvas"]||document["mozPointerLockElement"]===Module["canvas"]||document["webkitPointerLockElement"]===Module["canvas"]||document["msPointerLockElement"]===Module["canvas"]}var canvas=Module["canvas"];if(canvas){canvas.requestPointerLock=canvas["requestPointerLock"]||canvas["mozRequestPointerLock"]||canvas["webkitRequestPointerLock"]||canvas["msRequestPointerLock"]||function(){};canvas.exitPointerLock=document["exitPointerLock"]||document["mozExitPointerLock"]||document["webkitExitPointerLock"]||document["msExitPointerLock"]||function(){};canvas.exitPointerLock=canvas.exitPointerLock.bind(document);document.addEventListener("pointerlockchange",pointerLockChange,false);document.addEventListener("mozpointerlockchange",pointerLockChange,false);document.addEventListener("webkitpointerlockchange",pointerLockChange,false);document.addEventListener("mspointerlockchange",pointerLockChange,false);if(Module["elementPointerLock"]){canvas.addEventListener("click",function(ev){if(!Browser.pointerLock&&Module["canvas"].requestPointerLock){Module["canvas"].requestPointerLock();ev.preventDefault()}},false)}}},createContext:function(canvas,useWebGL,setInModule,webGLContextAttributes){if(useWebGL&&Module.ctx&&canvas==Module.canvas)return Module.ctx;var ctx;var contextHandle;if(useWebGL){var contextAttributes={antialias:false,alpha:false,majorVersion:1};if(webGLContextAttributes){for(var attribute in webGLContextAttributes){contextAttributes[attribute]=webGLContextAttributes[attribute]}}if(typeof GL!=="undefined"){contextHandle=GL.createContext(canvas,contextAttributes);if(contextHandle){ctx=GL.getContext(contextHandle).GLctx}}}else{ctx=canvas.getContext("2d")}if(!ctx)return null;if(setInModule){if(!useWebGL)assert(typeof GLctx==="undefined","cannot set in module if GLctx is used, but we are a non-GL context that would replace it");Module.ctx=ctx;if(useWebGL)GL.makeContextCurrent(contextHandle);Module.useWebGL=useWebGL;Browser.moduleContextCreatedCallbacks.forEach(function(callback){callback()});Browser.init()}return ctx},destroyContext:function(canvas,useWebGL,setInModule){},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer,resizeCanvas){Browser.lockPointer=lockPointer;Browser.resizeCanvas=resizeCanvas;if(typeof Browser.lockPointer==="undefined")Browser.lockPointer=true;if(typeof Browser.resizeCanvas==="undefined")Browser.resizeCanvas=false;var canvas=Module["canvas"];function fullscreenChange(){Browser.isFullscreen=false;var canvasContainer=canvas.parentNode;if((document["fullscreenElement"]||document["mozFullScreenElement"]||document["msFullscreenElement"]||document["webkitFullscreenElement"]||document["webkitCurrentFullScreenElement"])===canvasContainer){canvas.exitFullscreen=Browser.exitFullscreen;if(Browser.lockPointer)canvas.requestPointerLock();Browser.isFullscreen=true;if(Browser.resizeCanvas){Browser.setFullscreenCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}else{canvasContainer.parentNode.insertBefore(canvas,canvasContainer);canvasContainer.parentNode.removeChild(canvasContainer);if(Browser.resizeCanvas){Browser.setWindowedCanvasSize()}else{Browser.updateCanvasDimensions(canvas)}}if(Module["onFullScreen"])Module["onFullScreen"](Browser.isFullscreen);if(Module["onFullscreen"])Module["onFullscreen"](Browser.isFullscreen)}if(!Browser.fullscreenHandlersInstalled){Browser.fullscreenHandlersInstalled=true;document.addEventListener("fullscreenchange",fullscreenChange,false);document.addEventListener("mozfullscreenchange",fullscreenChange,false);document.addEventListener("webkitfullscreenchange",fullscreenChange,false);document.addEventListener("MSFullscreenChange",fullscreenChange,false)}var canvasContainer=document.createElement("div");canvas.parentNode.insertBefore(canvasContainer,canvas);canvasContainer.appendChild(canvas);canvasContainer.requestFullscreen=canvasContainer["requestFullscreen"]||canvasContainer["mozRequestFullScreen"]||canvasContainer["msRequestFullscreen"]||(canvasContainer["webkitRequestFullscreen"]?function(){canvasContainer["webkitRequestFullscreen"](Element["ALLOW_KEYBOARD_INPUT"])}:null)||(canvasContainer["webkitRequestFullScreen"]?function(){canvasContainer["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"])}:null);canvasContainer.requestFullscreen()},exitFullscreen:function(){if(!Browser.isFullscreen){return false}var CFS=document["exitFullscreen"]||document["cancelFullScreen"]||document["mozCancelFullScreen"]||document["msExitFullscreen"]||document["webkitCancelFullScreen"]||function(){};CFS.apply(document,[]);return true},nextRAF:0,fakeRequestAnimationFrame:function(func){var now=Date.now();if(Browser.nextRAF===0){Browser.nextRAF=now+1e3/60}else{while(now+2>=Browser.nextRAF){Browser.nextRAF+=1e3/60}}var delay=Math.max(Browser.nextRAF-now,0);setTimeout(func,delay)},requestAnimationFrame:function(func){if(typeof requestAnimationFrame==="function"){requestAnimationFrame(func);return}var RAF=Browser.fakeRequestAnimationFrame;RAF(func)},safeCallback:function(func){return function(){if(!ABORT)return func.apply(null,arguments)}},allowAsyncCallbacks:true,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function(){Browser.allowAsyncCallbacks=false},resumeAsyncCallbacks:function(){Browser.allowAsyncCallbacks=true;if(Browser.queuedAsyncCallbacks.length>0){var callbacks=Browser.queuedAsyncCallbacks;Browser.queuedAsyncCallbacks=[];callbacks.forEach(function(func){func()})}},safeRequestAnimationFrame:function(func){return Browser.requestAnimationFrame(function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}else{Browser.queuedAsyncCallbacks.push(func)}})},safeSetTimeout:function(func,timeout){noExitRuntime=true;return setTimeout(function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}else{Browser.queuedAsyncCallbacks.push(func)}},timeout)},safeSetInterval:function(func,timeout){noExitRuntime=true;return setInterval(function(){if(ABORT)return;if(Browser.allowAsyncCallbacks){func()}},timeout)},getMimetype:function(name){return{"jpg":"image/jpeg","jpeg":"image/jpeg","png":"image/png","bmp":"image/bmp","ogg":"audio/ogg","wav":"audio/wav","mp3":"audio/mpeg"}[name.substr(name.lastIndexOf(".")+1)]},getUserMedia:function(func){if(!window.getUserMedia){window.getUserMedia=navigator["getUserMedia"]||navigator["mozGetUserMedia"]}window.getUserMedia(func)},getMovementX:function(event){return event["movementX"]||event["mozMovementX"]||event["webkitMovementX"]||0},getMovementY:function(event){return event["movementY"]||event["mozMovementY"]||event["webkitMovementY"]||0},getMouseWheelDelta:function(event){var delta=0;switch(event.type){case"DOMMouseScroll":delta=event.detail/3;break;case"mousewheel":delta=event.wheelDelta/120;break;case"wheel":delta=event.deltaY;switch(event.deltaMode){case 0:delta/=100;break;case 1:delta/=3;break;case 2:delta*=80;break;default:throw"unrecognized mouse wheel delta mode: "+event.deltaMode}break;default:throw"unrecognized mouse wheel event: "+event.type}return delta},mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(event){if(Browser.pointerLock){if(event.type!="mousemove"&&"mozMovementX"in event){Browser.mouseMovementX=Browser.mouseMovementY=0}else{Browser.mouseMovementX=Browser.getMovementX(event);Browser.mouseMovementY=Browser.getMovementY(event)}if(typeof SDL!="undefined"){Browser.mouseX=SDL.mouseX+Browser.mouseMovementX;Browser.mouseY=SDL.mouseY+Browser.mouseMovementY}else{Browser.mouseX+=Browser.mouseMovementX;Browser.mouseY+=Browser.mouseMovementY}}else{var rect=Module["canvas"].getBoundingClientRect();var cw=Module["canvas"].width;var ch=Module["canvas"].height;var scrollX=typeof window.scrollX!=="undefined"?window.scrollX:window.pageXOffset;var scrollY=typeof window.scrollY!=="undefined"?window.scrollY:window.pageYOffset;if(event.type==="touchstart"||event.type==="touchend"||event.type==="touchmove"){var touch=event.touch;if(touch===undefined){return}var adjustedX=touch.pageX-(scrollX+rect.left);var adjustedY=touch.pageY-(scrollY+rect.top);adjustedX=adjustedX*(cw/rect.width);adjustedY=adjustedY*(ch/rect.height);var coords={x:adjustedX,y:adjustedY};if(event.type==="touchstart"){Browser.lastTouches[touch.identifier]=coords;Browser.touches[touch.identifier]=coords}else if(event.type==="touchend"||event.type==="touchmove"){var last=Browser.touches[touch.identifier];if(!last)last=coords;Browser.lastTouches[touch.identifier]=last;Browser.touches[touch.identifier]=coords}return}var x=event.pageX-(scrollX+rect.left);var y=event.pageY-(scrollY+rect.top);x=x*(cw/rect.width);y=y*(ch/rect.height);Browser.mouseMovementX=x-Browser.mouseX;Browser.mouseMovementY=y-Browser.mouseY;Browser.mouseX=x;Browser.mouseY=y}},asyncLoad:function(url,onload,onerror,noRunDep){var dep=!noRunDep?getUniqueRunDependency("al "+url):"";readAsync(url,function(arrayBuffer){assert(arrayBuffer,'Loading data file "'+url+'" failed (no arrayBuffer).');onload(new Uint8Array(arrayBuffer));if(dep)removeRunDependency(dep)},function(event){if(onerror){onerror()}else{throw'Loading data file "'+url+'" failed.'}});if(dep)addRunDependency(dep)},resizeListeners:[],updateResizeListeners:function(){var canvas=Module["canvas"];Browser.resizeListeners.forEach(function(listener){listener(canvas.width,canvas.height)})},setCanvasSize:function(width,height,noUpdates){var canvas=Module["canvas"];Browser.updateCanvasDimensions(canvas,width,height);if(!noUpdates)Browser.updateResizeListeners()},windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen>>2];flags=flags|8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module["canvas"]);Browser.updateResizeListeners()},setWindowedCanvasSize:function(){if(typeof SDL!="undefined"){var flags=HEAPU32[SDL.screen>>2];flags=flags&~8388608;HEAP32[SDL.screen>>2]=flags}Browser.updateCanvasDimensions(Module["canvas"]);Browser.updateResizeListeners()},updateCanvasDimensions:function(canvas,wNative,hNative){if(wNative&&hNative){canvas.widthNative=wNative;canvas.heightNative=hNative}else{wNative=canvas.widthNative;hNative=canvas.heightNative}var w=wNative;var h=hNative;if(Module["forcedAspectRatio"]&&Module["forcedAspectRatio"]>0){if(w/h0?AL.freeIds.pop():AL._nextId++},freeIds:[],scheduleContextAudio:function(ctx){if(Browser.mainLoop.timingMode===1&&document["visibilityState"]!="visible"){return}for(var i in ctx.sources){AL.scheduleSourceAudio(ctx.sources[i])}},scheduleSourceAudio:function(src,lookahead){if(Browser.mainLoop.timingMode===1&&document["visibilityState"]!="visible"){return}if(src.state!==4114){return}var currentTime=AL.updateSourceTime(src);var startTime=src.bufStartTime;var startOffset=src.bufOffset;var bufCursor=src.bufsProcessed;for(var i=0;i=src.bufQueue.length){if(src.looping){bufCursor%=src.bufQueue.length}else{break}}var buf=src.bufQueue[bufCursor%src.bufQueue.length];if(buf.length===0){skipCount++;if(skipCount===src.bufQueue.length){break}}else{var audioSrc=src.context.audioCtx.createBufferSource();audioSrc.buffer=buf.audioBuf;audioSrc.playbackRate.value=src.playbackRate;if(buf.audioBuf._loopStart||buf.audioBuf._loopEnd){audioSrc.loopStart=buf.audioBuf._loopStart;audioSrc.loopEnd=buf.audioBuf._loopEnd}var duration=0;if(src.type===4136&&src.looping){duration=Number.POSITIVE_INFINITY;audioSrc.loop=true;if(buf.audioBuf._loopStart){audioSrc.loopStart=buf.audioBuf._loopStart}if(buf.audioBuf._loopEnd){audioSrc.loopEnd=buf.audioBuf._loopEnd}}else{duration=(buf.audioBuf.duration-startOffset)/src.playbackRate}audioSrc._startOffset=startOffset;audioSrc._duration=duration;audioSrc._skipCount=skipCount;skipCount=0;audioSrc.connect(src.gain);if(typeof audioSrc.start!=="undefined"){startTime=Math.max(startTime,src.context.audioCtx.currentTime);audioSrc.start(startTime,startOffset)}else if(typeof audioSrc.noteOn!=="undefined"){startTime=Math.max(startTime,src.context.audioCtx.currentTime);audioSrc.noteOn(startTime)}audioSrc._startTime=startTime;src.audioQueue.push(audioSrc);startTime+=duration}startOffset=0;bufCursor++}},updateSourceTime:function(src){var currentTime=src.context.audioCtx.currentTime;if(src.state!==4114){return currentTime}if(!isFinite(src.bufStartTime)){src.bufStartTime=currentTime-src.bufOffset/src.playbackRate;src.bufOffset=0}var nextStartTime=0;while(src.audioQueue.length){var audioSrc=src.audioQueue[0];src.bufsProcessed+=audioSrc._skipCount;nextStartTime=audioSrc._startTime+audioSrc._duration;if(currentTime=src.bufQueue.length&&!src.looping){AL.setSourceState(src,4116)}else if(src.type===4136&&src.looping){var buf=src.bufQueue[0];if(buf.length===0){src.bufOffset=0}else{var delta=(currentTime-src.bufStartTime)*src.playbackRate;var loopStart=buf.audioBuf._loopStart||0;var loopEnd=buf.audioBuf._loopEnd||buf.audioBuf.duration;if(loopEnd<=loopStart){loopEnd=buf.audioBuf.duration}if(delta0){src.bufStartTime+=Math.floor((currentTime-src.bufStartTime)/srcDuration)*srcDuration}}for(var i=0;i=src.bufQueue.length){if(src.looping){src.bufsProcessed%=src.bufQueue.length}else{AL.setSourceState(src,4116);break}}var buf=src.bufQueue[src.bufsProcessed];if(buf.length>0){nextStartTime=src.bufStartTime+buf.audioBuf.duration/src.playbackRate;if(currentTime1){src.audioQueue.length=1}},stopSourceAudio:function(src){for(var i=0;isrc.bufQueue[src.bufsProcessed].audioBuf.duration){offset-=src.bufQueue[src.bufsProcessed].audiobuf.duration;src.bufsProcessed++}src.bufOffset=offset}if(playing){AL.setSourceState(src,4114)}},getGlobalParam:function(funcname,param){if(!AL.currentCtx){return null}switch(param){case 49152:return AL.currentCtx.dopplerFactor;case 49155:return AL.currentCtx.speedOfSound;case 53248:return AL.currentCtx.distanceModel;default:AL.currentCtx.err=40962;return null}},setGlobalParam:function(funcname,param,value){if(!AL.currentCtx){return}switch(param){case 49152:if(!Number.isFinite(value)||value<0){AL.currentCtx.err=40963;return}AL.currentCtx.dopplerFactor=value;AL.updateListenerSpace(AL.currentCtx);break;case 49155:if(!Number.isFinite(value)||value<=0){AL.currentCtx.err=40963;return}AL.currentCtx.speedOfSound=value;AL.updateListenerSpace(AL.currentCtx);break;case 53248:switch(value){case 0:case 53249:case 53250:case 53251:case 53252:case 53253:case 53254:AL.currentCtx.distanceModel=value;AL.updateContextGlobal(AL.currentCtx);break;default:AL.currentCtx.err=40963;return}break;default:AL.currentCtx.err=40962;return}},getListenerParam:function(funcname,param){if(!AL.currentCtx){return null}switch(param){case 4100:return AL.currentCtx.listener.position;case 4102:return AL.currentCtx.listener.velocity;case 4111:return AL.currentCtx.listener.direction.concat(AL.currentCtx.listener.up);case 4106:return AL.currentCtx.gain.gain.value;default:AL.currentCtx.err=40962;return null}},setListenerParam:function(funcname,param,value){if(!AL.currentCtx){return}if(value===null){AL.currentCtx.err=40962;return}var listener=AL.currentCtx.listener;switch(param){case 4100:if(!Number.isFinite(value[0])||!Number.isFinite(value[1])||!Number.isFinite(value[2])){AL.currentCtx.err=40963;return}listener.position[0]=value[0];listener.position[1]=value[1];listener.position[2]=value[2];AL.updateListenerSpace(AL.currentCtx);break;case 4102:if(!Number.isFinite(value[0])||!Number.isFinite(value[1])||!Number.isFinite(value[2])){AL.currentCtx.err=40963;return}listener.velocity[0]=value[0];listener.velocity[1]=value[1];listener.velocity[2]=value[2];AL.updateListenerSpace(AL.currentCtx);break;case 4106:if(!Number.isFinite(value)||value<0){AL.currentCtx.err=40963;return}AL.currentCtx.gain.gain.value=value;break;case 4111:if(!Number.isFinite(value[0])||!Number.isFinite(value[1])||!Number.isFinite(value[2])||!Number.isFinite(value[3])||!Number.isFinite(value[4])||!Number.isFinite(value[5])){AL.currentCtx.err=40963;return}listener.direction[0]=value[0];listener.direction[1]=value[1];listener.direction[2]=value[2];listener.up[0]=value[3];listener.up[1]=value[4];listener.up[2]=value[5];AL.updateListenerSpace(AL.currentCtx);break;default:AL.currentCtx.err=40962;return}},getBufferParam:function(funcname,bufferId,param){if(!AL.currentCtx){return}var buf=AL.buffers[bufferId];if(!buf||bufferId===0){AL.currentCtx.err=40961;return}switch(param){case 8193:return buf.frequency;case 8194:return buf.bytesPerSample*8;case 8195:return buf.channels;case 8196:return buf.length*buf.bytesPerSample*buf.channels;case 8213:if(buf.length===0){return[0,0]}else{return[(buf.audioBuf._loopStart||0)*buf.frequency,(buf.audioBuf._loopEnd||buf.length)*buf.frequency]}default:AL.currentCtx.err=40962;return null}},setBufferParam:function(funcname,bufferId,param,value){if(!AL.currentCtx){return}var buf=AL.buffers[bufferId];if(!buf||bufferId===0){AL.currentCtx.err=40961;return}if(value===null){AL.currentCtx.err=40962;return}switch(param){case 8196:if(value!==0){AL.currentCtx.err=40963;return}break;case 8213:if(value[0]<0||value[0]>buf.length||value[1]<0||value[1]>buf.Length||value[0]>=value[1]){AL.currentCtx.err=40963;return}if(buf.refCount>0){AL.currentCtx.err=40964;return}if(buf.audioBuf){buf.audioBuf._loopStart=value[0]/buf.frequency;buf.audioBuf._loopEnd=value[1]/buf.frequency}break;default:AL.currentCtx.err=40962;return}},getSourceParam:function(funcname,sourceId,param){if(!AL.currentCtx){return null}var src=AL.currentCtx.sources[sourceId];if(!src){AL.currentCtx.err=40961;return null}switch(param){case 514:return src.relative;case 4097:return src.coneInnerAngle;case 4098:return src.coneOuterAngle;case 4099:return src.pitch;case 4100:return src.position;case 4101:return src.direction;case 4102:return src.velocity;case 4103:return src.looping;case 4105:if(src.type===4136){return src.bufQueue[0].id}else{return 0}case 4106:return src.gain.gain.value;case 4109:return src.minGain;case 4110:return src.maxGain;case 4112:return src.state;case 4117:if(src.bufQueue.length===1&&src.bufQueue[0].id===0){return 0}else{return src.bufQueue.length}case 4118:if(src.bufQueue.length===1&&src.bufQueue[0].id===0||src.looping){return 0}else{return src.bufsProcessed}case 4128:return src.refDistance;case 4129:return src.rolloffFactor;case 4130:return src.coneOuterGain;case 4131:return src.maxDistance;case 4132:return AL.sourceTell(src);case 4133:var offset=AL.sourceTell(src);if(offset>0){offset*=src.bufQueue[0].frequency}return offset;case 4134:var offset=AL.sourceTell(src);if(offset>0){offset*=src.bufQueue[0].frequency*src.bufQueue[0].bytesPerSample}return offset;case 4135:return src.type;case 4628:return src.spatialize;case 8201:var length=0;var bytesPerFrame=0;for(var i=0;i0){var audioSrc=src.audioQueue[0];audioSrc.loop=true;audioSrc._duration=Number.POSITIVE_INFINITY}}else if(value===0){src.looping=false;var currentTime=AL.updateSourceTime(src);if(src.type===4136&&src.audioQueue.length>0){var audioSrc=src.audioQueue[0];audioSrc.loop=false;audioSrc._duration=src.bufQueue[0].audioBuf.duration/src.playbackRate;audioSrc._startTime=currentTime-src.bufOffset/src.playbackRate}}else{AL.currentCtx.err=40963;return}break;case 4105:if(src.state===4114||src.state===4115){AL.currentCtx.err=40964;return}if(value===0){for(var i in src.bufQueue){src.bufQueue[i].refCount--}src.bufQueue.length=1;src.bufQueue[0]=AL.buffers[0];src.bufsProcessed=0;src.type=4144}else{var buf=AL.buffers[value];if(!buf){AL.currentCtx.err=40963;return}for(var i in src.bufQueue){src.bufQueue[i].refCount--}src.bufQueue.length=0;buf.refCount++;src.bufQueue=[buf];src.bufsProcessed=0;src.type=4136}AL.initSourcePanner(src);AL.scheduleSourceAudio(src);break;case 4106:if(!Number.isFinite(value)||value<0){AL.currentCtx.err=40963;return}src.gain.gain.value=value;break;case 4109:if(!Number.isFinite(value)||value<0||value>Math.min(src.maxGain,1)){AL.currentCtx.err=40963;return}src.minGain=value;break;case 4110:if(!Number.isFinite(value)||value1){AL.currentCtx.err=40963;return}src.maxGain=value;break;case 4128:if(!Number.isFinite(value)||value<0){AL.currentCtx.err=40963;return}src.refDistance=value;if(src.panner){src.panner.refDistance=value}break;case 4129:if(!Number.isFinite(value)||value<0){AL.currentCtx.err=40963;return}src.rolloffFactor=value;if(src.panner){src.panner.rolloffFactor=value}break;case 4130:if(!Number.isFinite(value)||value<0||value>1){AL.currentCtx.err=40963;return}src.coneOuterGain=value;if(src.panner){src.panner.coneOuterGain=value}break;case 4131:if(!Number.isFinite(value)||value<0){AL.currentCtx.err=40963;return}src.maxDistance=value;if(src.panner){src.panner.maxDistance=value}break;case 4132:if(value<0||value>AL.sourceDuration(src)){AL.currentCtx.err=40963;return}AL.sourceSeek(src,value);break;case 4133:var srcLen=AL.sourceDuration(src);if(srcLen>0){var frequency;for(var bufId in src.bufQueue){if(bufId){frequency=src.bufQueue[bufId].frequency;break}}value/=frequency}if(value<0||value>srcLen){AL.currentCtx.err=40963;return}AL.sourceSeek(src,value);break;case 4134:var srcLen=AL.sourceDuration(src);if(srcLen>0){var bytesPerSec;for(var bufId in src.bufQueue){if(bufId){var buf=src.bufQueue[bufId];bytesPerSec=buf.frequency*buf.bytesPerSample*buf.channels;break}}value/=bytesPerSec}if(value<0||value>srcLen){AL.currentCtx.err=40963;return}AL.sourceSeek(src,value);break;case 4628:if(value!==0&&value!==1&&value!==2){AL.currentCtx.err=40963;return}src.spatialize=value;AL.initSourcePanner(src);break;case 8201:case 8202:case 8203:AL.currentCtx.err=40964;break;case 53248:switch(value){case 0:case 53249:case 53250:case 53251:case 53252:case 53253:case 53254:src.distanceModel=value;if(AL.currentCtx.sourceDistanceModel){AL.updateContextGlobal(AL.currentCtx)}break;default:AL.currentCtx.err=40963;return}break;default:AL.currentCtx.err=40962;return}},captures:{},sharedCaptureAudioCtx:null,requireValidCaptureDevice:function(deviceId,funcname){if(deviceId===0){AL.alcErr=40961;return null}var c=AL.captures[deviceId];if(!c){AL.alcErr=40961;return null}var err=c.mediaStreamError;if(err){AL.alcErr=40961;return null}return c}};function _alBufferData(bufferId,format,pData,size,freq){if(!AL.currentCtx){return}var buf=AL.buffers[bufferId];if(!buf){AL.currentCtx.err=40963;return}if(freq<=0){AL.currentCtx.err=40963;return}var audioBuf=null;try{switch(format){case 4352:if(size>0){audioBuf=AL.currentCtx.audioCtx.createBuffer(1,size,freq);var channel0=audioBuf.getChannelData(0);for(var i=0;i0){audioBuf=AL.currentCtx.audioCtx.createBuffer(1,size>>1,freq);var channel0=audioBuf.getChannelData(0);pData>>=1;for(var i=0;i>1;++i){channel0[i]=HEAP16[pData++]*30517578125e-15}}buf.bytesPerSample=2;buf.channels=1;buf.length=size>>1;break;case 4354:if(size>0){audioBuf=AL.currentCtx.audioCtx.createBuffer(2,size>>1,freq);var channel0=audioBuf.getChannelData(0);var channel1=audioBuf.getChannelData(1);for(var i=0;i>1;++i){channel0[i]=HEAPU8[pData++]*.0078125-1;channel1[i]=HEAPU8[pData++]*.0078125-1}}buf.bytesPerSample=1;buf.channels=2;buf.length=size>>1;break;case 4355:if(size>0){audioBuf=AL.currentCtx.audioCtx.createBuffer(2,size>>2,freq);var channel0=audioBuf.getChannelData(0);var channel1=audioBuf.getChannelData(1);pData>>=1;for(var i=0;i>2;++i){channel0[i]=HEAP16[pData++]*30517578125e-15;channel1[i]=HEAP16[pData++]*30517578125e-15}}buf.bytesPerSample=2;buf.channels=2;buf.length=size>>2;break;case 65552:if(size>0){audioBuf=AL.currentCtx.audioCtx.createBuffer(1,size>>2,freq);var channel0=audioBuf.getChannelData(0);pData>>=2;for(var i=0;i>2;++i){channel0[i]=HEAPF32[pData++]}}buf.bytesPerSample=4;buf.channels=1;buf.length=size>>2;break;case 65553:if(size>0){audioBuf=AL.currentCtx.audioCtx.createBuffer(2,size>>3,freq);var channel0=audioBuf.getChannelData(0);var channel1=audioBuf.getChannelData(1);pData>>=2;for(var i=0;i>3;++i){channel0[i]=HEAPF32[pData++];channel1[i]=HEAPF32[pData++]}}buf.bytesPerSample=4;buf.channels=2;buf.length=size>>3;break;default:AL.currentCtx.err=40963;return}buf.frequency=freq;buf.audioBuf=audioBuf}catch(e){AL.currentCtx.err=40963;return}}function _alDeleteBuffers(count,pBufferIds){if(!AL.currentCtx){return}for(var i=0;i>2];if(bufId===0){continue}if(!AL.buffers[bufId]){AL.currentCtx.err=40961;return}if(AL.buffers[bufId].refCount){AL.currentCtx.err=40964;return}}for(var i=0;i>2];if(bufId===0){continue}AL.deviceRefCounts[AL.buffers[bufId].deviceId]--;delete AL.buffers[bufId];AL.freeIds.push(bufId)}}function _alSourcei(sourceId,param,value){switch(param){case 514:case 4097:case 4098:case 4103:case 4105:case 4128:case 4129:case 4131:case 4132:case 4133:case 4134:case 4628:case 8201:case 8202:case 53248:AL.setSourceParam("alSourcei",sourceId,param,value);break;default:AL.setSourceParam("alSourcei",sourceId,param,null);break}}function _alDeleteSources(count,pSourceIds){if(!AL.currentCtx){return}for(var i=0;i>2];if(!AL.currentCtx.sources[srcId]){AL.currentCtx.err=40961;return}}for(var i=0;i>2];AL.setSourceState(AL.currentCtx.sources[srcId],4116);_alSourcei(srcId,4105,0);delete AL.currentCtx.sources[srcId];AL.freeIds.push(srcId)}}function _alDistanceModel(model){AL.setGlobalParam("alDistanceModel",53248,model)}function _alDopplerFactor(value){AL.setGlobalParam("alDopplerFactor",49152,value)}function _alGenBuffers(count,pBufferIds){if(!AL.currentCtx){return}for(var i=0;i>2]=buf.id}}function _alGenSources(count,pSourceIds){if(!AL.currentCtx){return}for(var i=0;i>2]=src.id}}function _alGetBufferi(bufferId,param,pValue){var val=AL.getBufferParam("alGetBufferi",bufferId,param);if(val===null){return}if(!pValue){AL.currentCtx.err=40963;return}switch(param){case 8193:case 8194:case 8195:case 8196:HEAP32[pValue>>2]=val;break;default:AL.currentCtx.err=40962;return}}function _alGetError(){if(!AL.currentCtx){return 40964}else{var err=AL.currentCtx.err;AL.currentCtx.err=0;return err}}function _alGetFloat(param){var val=AL.getGlobalParam("alGetFloat",param);if(val===null){return 0}switch(param){case 49152:case 49155:case 53248:return val;default:return 0}}function _alGetListenerf(param,pValue){var val=AL.getListenerParam("alGetListenerf",param);if(val===null){return}if(!pValue){AL.currentCtx.err=40963;return}switch(param){case 4106:HEAPF32[pValue>>2]=val;break;default:AL.currentCtx.err=40962;return}}function _alGetListenerfv(param,pValues){var val=AL.getListenerParam("alGetListenerfv",param);if(val===null){return}if(!pValues){AL.currentCtx.err=40963;return}switch(param){case 4100:case 4102:HEAPF32[pValues>>2]=val[0];HEAPF32[pValues+4>>2]=val[1];HEAPF32[pValues+8>>2]=val[2];break;case 4111:HEAPF32[pValues>>2]=val[0];HEAPF32[pValues+4>>2]=val[1];HEAPF32[pValues+8>>2]=val[2];HEAPF32[pValues+12>>2]=val[3];HEAPF32[pValues+16>>2]=val[4];HEAPF32[pValues+20>>2]=val[5];break;default:AL.currentCtx.err=40962;return}}function _alGetSourcef(sourceId,param,pValue){var val=AL.getSourceParam("alGetSourcef",sourceId,param);if(val===null){return}if(!pValue){AL.currentCtx.err=40963;return}switch(param){case 4097:case 4098:case 4099:case 4106:case 4109:case 4110:case 4128:case 4129:case 4130:case 4131:case 4132:case 4133:case 4134:case 8203:HEAPF32[pValue>>2]=val;break;default:AL.currentCtx.err=40962;return}}function _alGetSourcefv(sourceId,param,pValues){var val=AL.getSourceParam("alGetSourcefv",sourceId,param);if(val===null){return}if(!pValues){AL.currentCtx.err=40963;return}switch(param){case 4097:case 4098:case 4099:case 4106:case 4109:case 4110:case 4128:case 4129:case 4130:case 4131:case 4132:case 4133:case 4134:case 8203:HEAPF32[pValues>>2]=val[0];break;case 4100:case 4101:case 4102:HEAPF32[pValues>>2]=val[0];HEAPF32[pValues+4>>2]=val[1];HEAPF32[pValues+8>>2]=val[2];break;default:AL.currentCtx.err=40962;return}}function _alGetSourcei(sourceId,param,pValue){var val=AL.getSourceParam("alGetSourcei",sourceId,param);if(val===null){return}if(!pValue){AL.currentCtx.err=40963;return}switch(param){case 514:case 4097:case 4098:case 4103:case 4105:case 4112:case 4117:case 4118:case 4128:case 4129:case 4131:case 4132:case 4133:case 4134:case 4135:case 4628:case 8201:case 8202:case 53248:HEAP32[pValue>>2]=val;break;default:AL.currentCtx.err=40962;return}}function _alListenerf(param,value){switch(param){case 4106:AL.setListenerParam("alListenerf",param,value);break;default:AL.setListenerParam("alListenerf",param,null);break}}function _alListenerfv(param,pValues){if(!AL.currentCtx){return}if(!pValues){AL.currentCtx.err=40963;return}switch(param){case 4100:case 4102:AL.paramArray[0]=HEAPF32[pValues>>2];AL.paramArray[1]=HEAPF32[pValues+4>>2];AL.paramArray[2]=HEAPF32[pValues+8>>2];AL.setListenerParam("alListenerfv",param,AL.paramArray);break;case 4111:AL.paramArray[0]=HEAPF32[pValues>>2];AL.paramArray[1]=HEAPF32[pValues+4>>2];AL.paramArray[2]=HEAPF32[pValues+8>>2];AL.paramArray[3]=HEAPF32[pValues+12>>2];AL.paramArray[4]=HEAPF32[pValues+16>>2];AL.paramArray[5]=HEAPF32[pValues+20>>2];AL.setListenerParam("alListenerfv",param,AL.paramArray);break;default:AL.setListenerParam("alListenerfv",param,null);break}}function _alSourcePause(sourceId){if(!AL.currentCtx){return}var src=AL.currentCtx.sources[sourceId];if(!src){AL.currentCtx.err=40961;return}AL.setSourceState(src,4115)}function _alSourcePausev(count,pSourceIds){if(!AL.currentCtx){return}if(!pSourceIds){AL.currentCtx.err=40963}for(var i=0;i>2]]){AL.currentCtx.err=40961;return}}for(var i=0;i>2],4115)}}function _alSourcePlay(sourceId){if(!AL.currentCtx){return}var src=AL.currentCtx.sources[sourceId];if(!src){AL.currentCtx.err=40961;return}AL.setSourceState(src,4114)}function _alSourcePlayv(count,pSourceIds){if(!AL.currentCtx){return}if(!pSourceIds){AL.currentCtx.err=40963}for(var i=0;i>2]]){AL.currentCtx.err=40961;return}}for(var i=0;i>2],4114)}}function _alSourceQueueBuffers(sourceId,count,pBufferIds){if(!AL.currentCtx){return}var src=AL.currentCtx.sources[sourceId];if(!src){AL.currentCtx.err=40961;return}if(src.type===4136){AL.currentCtx.err=40964;return}if(count===0){return}var templateBuf=AL.buffers[0];for(var i=0;i>2];var buf=AL.buffers[bufId];if(!buf){AL.currentCtx.err=40961;return}if(templateBuf.id!==0&&(buf.frequency!==templateBuf.frequency||buf.bytesPerSample!==templateBuf.bytesPerSample||buf.channels!==templateBuf.channels)){AL.currentCtx.err=40964}}if(src.bufQueue.length===1&&src.bufQueue[0].id===0){src.bufQueue.length=0}src.type=4137;for(var i=0;i>2];var buf=AL.buffers[bufId];buf.refCount++;src.bufQueue.push(buf)}if(src.looping){AL.cancelPendingSourceAudio(src)}AL.initSourcePanner(src);AL.scheduleSourceAudio(src)}function _alSourceStop(sourceId){if(!AL.currentCtx){return}var src=AL.currentCtx.sources[sourceId];if(!src){AL.currentCtx.err=40961;return}AL.setSourceState(src,4116)}function _alSourceStopv(count,pSourceIds){if(!AL.currentCtx){return}if(!pSourceIds){AL.currentCtx.err=40963}for(var i=0;i>2]]){AL.currentCtx.err=40961;return}}for(var i=0;i>2],4116)}}function _alSourceUnqueueBuffers(sourceId,count,pBufferIds){if(!AL.currentCtx){return}var src=AL.currentCtx.sources[sourceId];if(!src){AL.currentCtx.err=40961;return}if(count>(src.bufQueue.length===1&&src.bufQueue[0].id===0?0:src.bufsProcessed)){AL.currentCtx.err=40963;return}if(count===0){return}for(var i=0;i>2]=buf.id;src.bufsProcessed--}if(src.bufQueue.length===0){src.bufQueue.push(AL.buffers[0])}AL.initSourcePanner(src);AL.scheduleSourceAudio(src)}function _alSourcef(sourceId,param,value){switch(param){case 4097:case 4098:case 4099:case 4106:case 4109:case 4110:case 4128:case 4129:case 4130:case 4131:case 4132:case 4133:case 4134:case 8203:AL.setSourceParam("alSourcef",sourceId,param,value);break;default:AL.setSourceParam("alSourcef",sourceId,param,null);break}}function _alSourcefv(sourceId,param,pValues){if(!AL.currentCtx){return}if(!pValues){AL.currentCtx.err=40963;return}switch(param){case 4097:case 4098:case 4099:case 4106:case 4109:case 4110:case 4128:case 4129:case 4130:case 4131:case 4132:case 4133:case 4134:case 8203:var val=HEAPF32[pValues>>2];AL.setSourceParam("alSourcefv",sourceId,param,val);break;case 4100:case 4101:case 4102:AL.paramArray[0]=HEAPF32[pValues>>2];AL.paramArray[1]=HEAPF32[pValues+4>>2];AL.paramArray[2]=HEAPF32[pValues+8>>2];AL.setSourceParam("alSourcefv",sourceId,param,AL.paramArray);break;default:AL.setSourceParam("alSourcefv",sourceId,param,null);break}}function _alcCaptureCloseDevice(deviceId){var c=AL.requireValidCaptureDevice(deviceId,"alcCaptureCloseDevice");if(!c)return false;delete AL.captures[deviceId];AL.freeIds.push(deviceId);if(c.mediaStreamSourceNode)c.mediaStreamSourceNode.disconnect();if(c.mergerNode)c.mergerNode.disconnect();if(c.splitterNode)c.splitterNode.disconnect();if(c.scriptProcessorNode)c.scriptProcessorNode.disconnect();if(c.mediaStream){c.mediaStream.getTracks().forEach(function(track){track.stop()})}delete c.buffers;c.capturedFrameCount=0;c.isCapturing=false;return true}function _alcCaptureOpenDevice(pDeviceName,requestedSampleRate,format,bufferFrameCapacity){var resolvedDeviceName=AL.CAPTURE_DEVICE_NAME;if(pDeviceName!==0){resolvedDeviceName=UTF8ToString(pDeviceName);if(resolvedDeviceName!==AL.CAPTURE_DEVICE_NAME){AL.alcErr=40965;return 0}}if(bufferFrameCapacity<0){AL.alcErr=40964;return 0}navigator.getUserMedia=navigator.getUserMedia||navigator.webkitGetUserMedia||navigator.mozGetUserMedia||navigator.msGetUserMedia;var has_getUserMedia=navigator.getUserMedia||navigator.mediaDevices&&navigator.mediaDevices.getUserMedia;if(!has_getUserMedia){AL.alcErr=40965;return 0}var AudioContext=window.AudioContext||window.webkitAudioContext;if(!AL.sharedCaptureAudioCtx){try{AL.sharedCaptureAudioCtx=new AudioContext}catch(e){AL.alcErr=40965;return 0}}autoResumeAudioContext(AL.sharedCaptureAudioCtx);var outputChannelCount;switch(format){case 65552:case 4353:case 4352:outputChannelCount=1;break;case 65553:case 4355:case 4354:outputChannelCount=2;break;default:AL.alcErr=40964;return 0}function newF32Array(cap){return new Float32Array(cap)}function newI16Array(cap){return new Int16Array(cap)}function newU8Array(cap){return new Uint8Array(cap)}var requestedSampleType;var newSampleArray;switch(format){case 65552:case 65553:requestedSampleType="f32";newSampleArray=newF32Array;break;case 4353:case 4355:requestedSampleType="i16";newSampleArray=newI16Array;break;case 4352:case 4354:requestedSampleType="u8";newSampleArray=newU8Array;break}var buffers=[];try{for(var chan=0;chanoutputChannelCount){newCapture.mergerNode=newCapture.audioCtx.createChannelMerger(inputChannelCount);newCapture.mediaStreamSourceNode.connect(newCapture.mergerNode);newCapture.mergerNode.connect(newCapture.scriptProcessorNode)}else if(inputChannelCountc.capturedFrameCount){console.error("alcCaptureSamples() with invalid bufferSize");AL.alcErr=40964;return}function setF32Sample(i,sample){HEAPF32[pFrames+4*i>>2]=sample}function setI16Sample(i,sample){HEAP16[pFrames+2*i>>1]=sample}function setU8Sample(i,sample){HEAP8[pFrames+i>>0]=sample}var setSample;switch(c.requestedSampleType){case"f32":setSample=setF32Sample;break;case"i16":setSample=setI16Sample;break;case"u8":setSample=setU8Sample;break;default:return}var dstfreq=c.requestedSampleRate;var srcfreq=c.audioCtx.sampleRate;if(srcfreq==dstfreq){for(var i=0,frame_i=0;frame_i0){return 0}delete AL.deviceRefCounts[deviceId];AL.freeIds.push(deviceId);return 1}function _alcCreateContext(deviceId,pAttrList){if(!(deviceId in AL.deviceRefCounts)){AL.alcErr=40961;return 0}var options=null;var attrs=[];var hrtf=null;pAttrList>>=2;if(pAttrList){var attr=0;var val=0;while(true){attr=HEAP32[pAttrList++];attrs.push(attr);if(attr===0){break}val=HEAP32[pAttrList++];attrs.push(val);switch(attr){case 4103:if(!options){options={}}options.sampleRate=val;break;case 4112:case 4113:break;case 6546:switch(val){case 0:hrtf=false;break;case 1:hrtf=true;break;case 2:break;default:AL.alcErr=40964;return 0}break;case 6550:if(val!==0){AL.alcErr=40964;return 0}break;default:AL.alcErr=40964;return 0}}}var AudioContext=window.AudioContext||window.webkitAudioContext;var ac=null;try{if(options){ac=new AudioContext(options)}else{ac=new AudioContext}}catch(e){if(e.name==="NotSupportedError"){AL.alcErr=40964}else{AL.alcErr=40961}return 0}autoResumeAudioContext(ac);if(typeof ac.createGain==="undefined"){ac.createGain=ac.createGainNode}var gain=ac.createGain();gain.connect(ac.destination);var ctx={deviceId:deviceId,id:AL.newId(),attrs:attrs,audioCtx:ac,listener:{position:[0,0,0],velocity:[0,0,0],direction:[0,0,0],up:[0,0,0]},sources:[],interval:setInterval(function(){AL.scheduleContextAudio(ctx)},AL.QUEUE_INTERVAL),gain:gain,distanceModel:53250,speedOfSound:343.3,dopplerFactor:1,sourceDistanceModel:false,hrtf:hrtf||false,_err:0,get err(){return this._err},set err(val){if(this._err===0||val===0){this._err=val}}};AL.deviceRefCounts[deviceId]++;AL.contexts[ctx.id]=ctx;if(hrtf!==null){for(var ctxId in AL.contexts){var c=AL.contexts[ctxId];if(c.deviceId===deviceId){c.hrtf=hrtf;AL.updateContextGlobal(c)}}}return ctx.id}function _alcDestroyContext(contextId){var ctx=AL.contexts[contextId];if(AL.currentCtx===ctx){AL.alcErr=40962;return}if(AL.contexts[contextId].interval){clearInterval(AL.contexts[contextId].interval)}AL.deviceRefCounts[ctx.deviceId]--;delete AL.contexts[contextId];AL.freeIds.push(contextId)}function _alcGetCurrentContext(){if(AL.currentCtx!==null){return AL.currentCtx.id}else{return 0}}function _alcGetError(deviceId){var err=AL.alcErr;AL.alcErr=0;return err}function _alcGetIntegerv(deviceId,param,size,pValues){if(size===0||!pValues){return}switch(param){case 4096:HEAP32[pValues>>2]=1;break;case 4097:HEAP32[pValues>>2]=1;break;case 4098:if(!(deviceId in AL.deviceRefCounts)){AL.alcErr=40961;return}if(!AL.currentCtx){AL.alcErr=40962;return}HEAP32[pValues>>2]=AL.currentCtx.attrs.length;break;case 4099:if(!(deviceId in AL.deviceRefCounts)){AL.alcErr=40961;return}if(!AL.currentCtx){AL.alcErr=40962;return}for(var i=0;i>2]=AL.currentCtx.attrs[i]}break;case 4103:if(!(deviceId in AL.deviceRefCounts)){AL.alcErr=40961;return}if(!AL.currentCtx){AL.alcErr=40962;return}HEAP32[pValues>>2]=AL.currentCtx.audioCtx.sampleRate;break;case 4112:case 4113:if(!(deviceId in AL.deviceRefCounts)){AL.alcErr=40961;return}if(!AL.currentCtx){AL.alcErr=40962;return}HEAP32[pValues>>2]=2147483647;break;case 6546:case 6547:if(!(deviceId in AL.deviceRefCounts)){AL.alcErr=40961;return}var hrtfStatus=0;for(var ctxId in AL.contexts){var ctx=AL.contexts[ctxId];if(ctx.deviceId===deviceId){hrtfStatus=ctx.hrtf?1:0}}HEAP32[pValues>>2]=hrtfStatus;break;case 6548:if(!(deviceId in AL.deviceRefCounts)){AL.alcErr=40961;return}HEAP32[pValues>>2]=1;break;case 131075:if(!(deviceId in AL.deviceRefCounts)){AL.alcErr=40961;return}if(!AL.currentCtx){AL.alcErr=40962;return}HEAP32[pValues>>2]=1;case 786:var c=AL.requireValidCaptureDevice(deviceId,"alcGetIntegerv");if(!c){return}var n=c.capturedFrameCount;var dstfreq=c.requestedSampleRate;var srcfreq=c.audioCtx.sampleRate;var nsamples=Math.floor(n*(dstfreq/srcfreq));HEAP32[pValues>>2]=nsamples;break;default:AL.alcErr=40963;return}}function _alcGetString(deviceId,param){if(AL.alcStringCache[param]){return AL.alcStringCache[param]}var ret;switch(param){case 0:ret="No Error";break;case 40961:ret="Invalid Device";break;case 40962:ret="Invalid Context";break;case 40963:ret="Invalid Enum";break;case 40964:ret="Invalid Value";break;case 40965:ret="Out of Memory";break;case 4100:if(typeof AudioContext!=="undefined"||typeof webkitAudioContext!=="undefined"){ret=AL.DEVICE_NAME}else{return 0}break;case 4101:if(typeof AudioContext!=="undefined"||typeof webkitAudioContext!=="undefined"){ret=AL.DEVICE_NAME.concat("\0")}else{ret="\0"}break;case 785:ret=AL.CAPTURE_DEVICE_NAME;break;case 784:if(deviceId===0)ret=AL.CAPTURE_DEVICE_NAME.concat("\0");else{var c=AL.requireValidCaptureDevice(deviceId,"alcGetString");if(!c){return 0}ret=c.deviceName}break;case 4102:if(!deviceId){AL.alcErr=40961;return 0}ret="";for(var ext in AL.ALC_EXTENSIONS){ret=ret.concat(ext);ret=ret.concat(" ")}ret=ret.trim();break;default:AL.alcErr=40963;return 0}ret=allocate(intArrayFromString(ret),"i8",ALLOC_NORMAL);AL.alcStringCache[param]=ret;return ret}function _alcMakeContextCurrent(contextId){if(contextId===0){AL.currentCtx=null;return 0}else{AL.currentCtx=AL.contexts[contextId];return 1}}function _alcOpenDevice(pDeviceName){if(pDeviceName){var name=UTF8ToString(pDeviceName);if(name!==AL.DEVICE_NAME){return 0}}if(typeof AudioContext!=="undefined"||typeof webkitAudioContext!=="undefined"){var deviceId=AL.newId();AL.deviceRefCounts[deviceId]=0;return deviceId}else{return 0}}function _clock(){if(_clock.start===undefined)_clock.start=Date.now();return(Date.now()-_clock.start)*(1e6/1e3)|0}function _difftime(time1,time0){return time1-time0}function _dlclose(handle){abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking")}function _dlerror(){abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking")}function _dlopen(filename,flag){abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking")}function _dlsym(handle,symbol){abort("To use dlopen, you need to use Emscripten's linking support, see https://github.com/emscripten-core/emscripten/wiki/Linking")}var EGL={errorCode:12288,defaultDisplayInitialized:false,currentContext:0,currentReadSurface:0,currentDrawSurface:0,contextAttributes:{alpha:false,depth:false,stencil:false,antialias:false},stringCache:{},setErrorCode:function(code){EGL.errorCode=code},chooseConfig:function(display,attribList,config,config_size,numConfigs){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(attribList){for(;;){var param=HEAP32[attribList>>2];if(param==12321){var alphaSize=HEAP32[attribList+4>>2];EGL.contextAttributes.alpha=alphaSize>0}else if(param==12325){var depthSize=HEAP32[attribList+4>>2];EGL.contextAttributes.depth=depthSize>0}else if(param==12326){var stencilSize=HEAP32[attribList+4>>2];EGL.contextAttributes.stencil=stencilSize>0}else if(param==12337){var samples=HEAP32[attribList+4>>2];EGL.contextAttributes.antialias=samples>0}else if(param==12338){var samples=HEAP32[attribList+4>>2];EGL.contextAttributes.antialias=samples==1}else if(param==12544){var requestedPriority=HEAP32[attribList+4>>2];EGL.contextAttributes.lowLatency=requestedPriority!=12547}else if(param==12344){break}attribList+=8}}if((!config||!config_size)&&!numConfigs){EGL.setErrorCode(12300);return 0}if(numConfigs){HEAP32[numConfigs>>2]=1}if(config&&config_size>0){HEAP32[config>>2]=62002}EGL.setErrorCode(12288);return 1}};function _eglBindAPI(api){if(api==12448){EGL.setErrorCode(12288);return 1}else{EGL.setErrorCode(12300);return 0}}function _eglChooseConfig(display,attrib_list,configs,config_size,numConfigs){return EGL.chooseConfig(display,attrib_list,configs,config_size,numConfigs)}function __webgl_enable_ANGLE_instanced_arrays(ctx){var ext=ctx.getExtension("ANGLE_instanced_arrays");if(ext){ctx["vertexAttribDivisor"]=function(index,divisor){ext["vertexAttribDivisorANGLE"](index,divisor)};ctx["drawArraysInstanced"]=function(mode,first,count,primcount){ext["drawArraysInstancedANGLE"](mode,first,count,primcount)};ctx["drawElementsInstanced"]=function(mode,count,type,indices,primcount){ext["drawElementsInstancedANGLE"](mode,count,type,indices,primcount)};return 1}}function __webgl_enable_OES_vertex_array_object(ctx){var ext=ctx.getExtension("OES_vertex_array_object");if(ext){ctx["createVertexArray"]=function(){return ext["createVertexArrayOES"]()};ctx["deleteVertexArray"]=function(vao){ext["deleteVertexArrayOES"](vao)};ctx["bindVertexArray"]=function(vao){ext["bindVertexArrayOES"](vao)};ctx["isVertexArray"]=function(vao){return ext["isVertexArrayOES"](vao)};return 1}}function __webgl_enable_WEBGL_draw_buffers(ctx){var ext=ctx.getExtension("WEBGL_draw_buffers");if(ext){ctx["drawBuffers"]=function(n,bufs){ext["drawBuffersWEBGL"](n,bufs)};return 1}}function __webgl_enable_WEBGL_multi_draw(ctx){return!!(ctx.multiDrawWebgl=ctx.getExtension("WEBGL_multi_draw"))}var GL={counter:1,buffers:[],programs:[],framebuffers:[],renderbuffers:[],textures:[],uniforms:[],shaders:[],vaos:[],contexts:[],offscreenCanvases:{},timerQueriesEXT:[],byteSizeByTypeRoot:5120,byteSizeByType:[1,1,2,2,4,4,4,2,3,4,8],programInfos:{},stringCache:{},unpackAlignment:4,recordError:function recordError(errorCode){if(!GL.lastError){GL.lastError=errorCode}},getNewId:function(table){var ret=GL.counter++;for(var i=table.length;i>1;var quadIndexes=new Uint16Array(numIndexes);var i=0,v=0;while(1){quadIndexes[i++]=v;if(i>=numIndexes)break;quadIndexes[i++]=v+1;if(i>=numIndexes)break;quadIndexes[i++]=v+2;if(i>=numIndexes)break;quadIndexes[i++]=v;if(i>=numIndexes)break;quadIndexes[i++]=v+2;if(i>=numIndexes)break;quadIndexes[i++]=v+3;if(i>=numIndexes)break;v+=4}context.GLctx.bufferData(34963,quadIndexes,35044);context.GLctx.bindBuffer(34963,null)}},getTempVertexBuffer:function getTempVertexBuffer(sizeBytes){var idx=GL.log2ceilLookup(sizeBytes);var ringbuffer=GL.currentContext.tempVertexBuffers1[idx];var nextFreeBufferIndex=GL.currentContext.tempVertexBufferCounters1[idx];GL.currentContext.tempVertexBufferCounters1[idx]=GL.currentContext.tempVertexBufferCounters1[idx]+1&GL.numTempVertexBuffersPerSize-1;var vbo=ringbuffer[nextFreeBufferIndex];if(vbo){return vbo}var prevVBO=GLctx.getParameter(34964);ringbuffer[nextFreeBufferIndex]=GLctx.createBuffer();GLctx.bindBuffer(34962,ringbuffer[nextFreeBufferIndex]);GLctx.bufferData(34962,1<>2]:-1;source+=UTF8ToString(HEAP32[string+i*4>>2],len<0?undefined:len)}return source},calcBufLength:function calcBufLength(size,type,stride,count){if(stride>0){return count*stride}var typeSize=GL.byteSizeByType[type-GL.byteSizeByTypeRoot];return size*typeSize*count},usedTempBuffers:[],preDrawHandleClientVertexAttribBindings:function preDrawHandleClientVertexAttribBindings(count){GL.resetBufferBinding=false;for(var i=0;i>2];if(param==12440){glesContextVersion=HEAP32[contextAttribs+4>>2]}else if(param==12344){break}else{EGL.setErrorCode(12292);return 0}contextAttribs+=8}if(glesContextVersion!=2){EGL.setErrorCode(12293);return 0}EGL.contextAttributes.majorVersion=glesContextVersion-1;EGL.contextAttributes.minorVersion=0;EGL.context=GL.createContext(Module["canvas"],EGL.contextAttributes);if(EGL.context!=0){EGL.setErrorCode(12288);GL.makeContextCurrent(EGL.context);Module.useWebGL=true;Browser.moduleContextCreatedCallbacks.forEach(function(callback){callback()});GL.makeContextCurrent(null);return 62004}else{EGL.setErrorCode(12297);return 0}}function _eglCreateWindowSurface(display,config,win,attrib_list){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(config!=62002){EGL.setErrorCode(12293);return 0}EGL.setErrorCode(12288);return 62006}function _eglDestroyContext(display,context){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(context!=62004){EGL.setErrorCode(12294);return 0}GL.deleteContext(EGL.context);EGL.setErrorCode(12288);if(EGL.currentContext==context){EGL.currentContext=0}return 1}function _eglDestroySurface(display,surface){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(surface!=62006){EGL.setErrorCode(12301);return 1}if(EGL.currentReadSurface==surface){EGL.currentReadSurface=0}if(EGL.currentDrawSurface==surface){EGL.currentDrawSurface=0}EGL.setErrorCode(12288);return 1}function _eglGetConfigAttrib(display,config,attribute,value){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(config!=62002){EGL.setErrorCode(12293);return 0}if(!value){EGL.setErrorCode(12300);return 0}EGL.setErrorCode(12288);switch(attribute){case 12320:HEAP32[value>>2]=EGL.contextAttributes.alpha?32:24;return 1;case 12321:HEAP32[value>>2]=EGL.contextAttributes.alpha?8:0;return 1;case 12322:HEAP32[value>>2]=8;return 1;case 12323:HEAP32[value>>2]=8;return 1;case 12324:HEAP32[value>>2]=8;return 1;case 12325:HEAP32[value>>2]=EGL.contextAttributes.depth?24:0;return 1;case 12326:HEAP32[value>>2]=EGL.contextAttributes.stencil?8:0;return 1;case 12327:HEAP32[value>>2]=12344;return 1;case 12328:HEAP32[value>>2]=62002;return 1;case 12329:HEAP32[value>>2]=0;return 1;case 12330:HEAP32[value>>2]=4096;return 1;case 12331:HEAP32[value>>2]=16777216;return 1;case 12332:HEAP32[value>>2]=4096;return 1;case 12333:HEAP32[value>>2]=0;return 1;case 12334:HEAP32[value>>2]=0;return 1;case 12335:HEAP32[value>>2]=12344;return 1;case 12337:HEAP32[value>>2]=EGL.contextAttributes.antialias?4:0;return 1;case 12338:HEAP32[value>>2]=EGL.contextAttributes.antialias?1:0;return 1;case 12339:HEAP32[value>>2]=4;return 1;case 12340:HEAP32[value>>2]=12344;return 1;case 12341:case 12342:case 12343:HEAP32[value>>2]=-1;return 1;case 12345:case 12346:HEAP32[value>>2]=0;return 1;case 12347:HEAP32[value>>2]=0;return 1;case 12348:HEAP32[value>>2]=1;return 1;case 12349:case 12350:HEAP32[value>>2]=0;return 1;case 12351:HEAP32[value>>2]=12430;return 1;case 12352:HEAP32[value>>2]=4;return 1;case 12354:HEAP32[value>>2]=0;return 1;default:EGL.setErrorCode(12292);return 0}}function _eglGetDisplay(nativeDisplayType){EGL.setErrorCode(12288);return 62e3}function _eglGetError(){return EGL.errorCode}function _eglGetProcAddress(name_){return _emscripten_GetProcAddress(name_)}function _eglInitialize(display,majorVersion,minorVersion){if(display==62e3){if(majorVersion){HEAP32[majorVersion>>2]=1}if(minorVersion){HEAP32[minorVersion>>2]=4}EGL.defaultDisplayInitialized=true;EGL.setErrorCode(12288);return 1}else{EGL.setErrorCode(12296);return 0}}function _eglMakeCurrent(display,draw,read,context){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(context!=0&&context!=62004){EGL.setErrorCode(12294);return 0}if(read!=0&&read!=62006||draw!=0&&draw!=62006){EGL.setErrorCode(12301);return 0}GL.makeContextCurrent(context?EGL.context:null);EGL.currentContext=context;EGL.currentDrawSurface=draw;EGL.currentReadSurface=read;EGL.setErrorCode(12288);return 1}function _eglQueryString(display,name){if(display!=62e3){EGL.setErrorCode(12296);return 0}EGL.setErrorCode(12288);if(EGL.stringCache[name])return EGL.stringCache[name];var ret;switch(name){case 12371:ret=allocateUTF8("Emscripten");break;case 12372:ret=allocateUTF8("1.4 Emscripten EGL");break;case 12373:ret=allocateUTF8("");break;case 12429:ret=allocateUTF8("OpenGL_ES");break;default:EGL.setErrorCode(12300);return 0}EGL.stringCache[name]=ret;return ret}function _eglSwapBuffers(){if(!EGL.defaultDisplayInitialized){EGL.setErrorCode(12289)}else if(!Module.ctx){EGL.setErrorCode(12290)}else if(Module.ctx.isContextLost()){EGL.setErrorCode(12302)}else{EGL.setErrorCode(12288);return 1}return 0}function _eglSwapInterval(display,interval){if(display!=62e3){EGL.setErrorCode(12296);return 0}if(interval==0)_emscripten_set_main_loop_timing(0,0);else _emscripten_set_main_loop_timing(1,interval);EGL.setErrorCode(12288);return 1}function _eglTerminate(display){if(display!=62e3){EGL.setErrorCode(12296);return 0}EGL.currentContext=0;EGL.currentReadSurface=0;EGL.currentDrawSurface=0;EGL.defaultDisplayInitialized=false;EGL.setErrorCode(12288);return 1}function _eglWaitClient(){EGL.setErrorCode(12288);return 1}function _eglWaitGL(){return _eglWaitClient()}function _eglWaitNative(nativeEngineId){EGL.setErrorCode(12288);return 1}function _emscripten_asm_const_int(code,sigPtr,argbuf){var args=readAsmConstArgs(sigPtr,argbuf);return ASM_CONSTS[code].apply(null,args)}function _emscripten_cancel_main_loop(){Browser.mainLoop.pause();Browser.mainLoop.func=null}var JSEvents={inEventHandler:0,removeAllEventListeners:function(){for(var i=JSEvents.eventHandlers.length-1;i>=0;--i){JSEvents._removeHandler(i)}JSEvents.eventHandlers=[];JSEvents.deferredCalls=[]},registerRemoveEventListeners:function(){if(!JSEvents.removeEventListenersRegistered){__ATEXIT__.push(JSEvents.removeAllEventListeners);JSEvents.removeEventListenersRegistered=true}},deferredCalls:[],deferCall:function(targetFunction,precedence,argsList){function arraysHaveEqualContent(arrA,arrB){if(arrA.length!=arrB.length)return false;for(var i in arrA){if(arrA[i]!=arrB[i])return false}return true}for(var i in JSEvents.deferredCalls){var call=JSEvents.deferredCalls[i];if(call.targetFunction==targetFunction&&arraysHaveEqualContent(call.argsList,argsList)){return}}JSEvents.deferredCalls.push({targetFunction:targetFunction,precedence:precedence,argsList:argsList});JSEvents.deferredCalls.sort(function(x,y){return x.precedence2?UTF8ToString(cString):cString}var specialHTMLTargets=[0,typeof document!=="undefined"?document:0,typeof window!=="undefined"?window:0];function findEventTarget(target){target=maybeCStringToJsString(target);var domElement=specialHTMLTargets[target]||(typeof document!=="undefined"?document.querySelector(target):undefined);return domElement}function findCanvasEventTarget(target){return findEventTarget(target)}function _emscripten_get_canvas_element_size(target,width,height){var canvas=findCanvasEventTarget(target);if(!canvas)return-4;HEAP32[width>>2]=canvas.width;HEAP32[height>>2]=canvas.height}function __get_canvas_element_size(target){var stackTop=stackSave();var w=stackAlloc(8);var h=w+4;var targetInt=stackAlloc(target.id.length+1);stringToUTF8(target.id,targetInt,target.id.length+1);var ret=_emscripten_get_canvas_element_size(targetInt,w,h);var size=[HEAP32[w>>2],HEAP32[h>>2]];stackRestore(stackTop);return size}function _emscripten_set_canvas_element_size(target,width,height){var canvas=findCanvasEventTarget(target);if(!canvas)return-4;canvas.width=width;canvas.height=height;return 0}function __set_canvas_element_size(target,width,height){if(!target.controlTransferredOffscreen){target.width=width;target.height=height}else{var stackTop=stackSave();var targetInt=stackAlloc(target.id.length+1);stringToUTF8(target.id,targetInt,target.id.length+1);_emscripten_set_canvas_element_size(targetInt,width,height);stackRestore(stackTop)}}function __registerRestoreOldStyle(canvas){var canvasSize=__get_canvas_element_size(canvas);var oldWidth=canvasSize[0];var oldHeight=canvasSize[1];var oldCssWidth=canvas.style.width;var oldCssHeight=canvas.style.height;var oldBackgroundColor=canvas.style.backgroundColor;var oldDocumentBackgroundColor=document.body.style.backgroundColor;var oldPaddingLeft=canvas.style.paddingLeft;var oldPaddingRight=canvas.style.paddingRight;var oldPaddingTop=canvas.style.paddingTop;var oldPaddingBottom=canvas.style.paddingBottom;var oldMarginLeft=canvas.style.marginLeft;var oldMarginRight=canvas.style.marginRight;var oldMarginTop=canvas.style.marginTop;var oldMarginBottom=canvas.style.marginBottom;var oldDocumentBodyMargin=document.body.style.margin;var oldDocumentOverflow=document.documentElement.style.overflow;var oldDocumentScroll=document.body.scroll;var oldImageRendering=canvas.style.imageRendering;function restoreOldStyle(){var fullscreenElement=document.fullscreenElement||document.webkitFullscreenElement||document.msFullscreenElement;if(!fullscreenElement){document.removeEventListener("fullscreenchange",restoreOldStyle);document.removeEventListener("webkitfullscreenchange",restoreOldStyle);__set_canvas_element_size(canvas,oldWidth,oldHeight);canvas.style.width=oldCssWidth;canvas.style.height=oldCssHeight;canvas.style.backgroundColor=oldBackgroundColor;if(!oldDocumentBackgroundColor)document.body.style.backgroundColor="white";document.body.style.backgroundColor=oldDocumentBackgroundColor;canvas.style.paddingLeft=oldPaddingLeft;canvas.style.paddingRight=oldPaddingRight;canvas.style.paddingTop=oldPaddingTop;canvas.style.paddingBottom=oldPaddingBottom;canvas.style.marginLeft=oldMarginLeft;canvas.style.marginRight=oldMarginRight;canvas.style.marginTop=oldMarginTop;canvas.style.marginBottom=oldMarginBottom;document.body.style.margin=oldDocumentBodyMargin;document.documentElement.style.overflow=oldDocumentOverflow;document.body.scroll=oldDocumentScroll;canvas.style.imageRendering=oldImageRendering;if(canvas.GLctxObject)canvas.GLctxObject.GLctx.viewport(0,0,oldWidth,oldHeight);if(__currentFullscreenStrategy.canvasResizedCallback){wasmTable.get(__currentFullscreenStrategy.canvasResizedCallback)(37,0,__currentFullscreenStrategy.canvasResizedCallbackUserData)}}}document.addEventListener("fullscreenchange",restoreOldStyle);document.addEventListener("webkitfullscreenchange",restoreOldStyle);return restoreOldStyle}function __setLetterbox(element,topBottom,leftRight){element.style.paddingLeft=element.style.paddingRight=leftRight+"px";element.style.paddingTop=element.style.paddingBottom=topBottom+"px"}function __getBoundingClientRect(e){return specialHTMLTargets.indexOf(e)<0?e.getBoundingClientRect():{"left":0,"top":0}}function _JSEvents_resizeCanvasForFullscreen(target,strategy){var restoreOldStyle=__registerRestoreOldStyle(target);var cssWidth=strategy.softFullscreen?innerWidth:screen.width;var cssHeight=strategy.softFullscreen?innerHeight:screen.height;var rect=__getBoundingClientRect(target);var windowedCssWidth=rect.width;var windowedCssHeight=rect.height;var canvasSize=__get_canvas_element_size(target);var windowedRttWidth=canvasSize[0];var windowedRttHeight=canvasSize[1];if(strategy.scaleMode==3){__setLetterbox(target,(cssHeight-windowedCssHeight)/2,(cssWidth-windowedCssWidth)/2);cssWidth=windowedCssWidth;cssHeight=windowedCssHeight}else if(strategy.scaleMode==2){if(cssWidth*windowedRttHeight>3]=e.chargingTime;HEAPF64[eventStruct+8>>3]=e.dischargingTime;HEAPF64[eventStruct+16>>3]=e.level;HEAP32[eventStruct+24>>2]=e.charging}function __battery(){return navigator.battery||navigator.mozBattery||navigator.webkitBattery}function _emscripten_get_battery_status(batteryState){if(!__battery())return-1;__fillBatteryEventData(batteryState,__battery());return 0}function _emscripten_get_device_pixel_ratio(){return typeof devicePixelRatio==="number"&&devicePixelRatio||1}function _emscripten_get_element_css_size(target,width,height){target=findEventTarget(target);if(!target)return-4;var rect=__getBoundingClientRect(target);HEAPF64[width>>3]=rect.width;HEAPF64[height>>3]=rect.height;return 0}function __fillGamepadEventData(eventStruct,e){HEAPF64[eventStruct>>3]=e.timestamp;for(var i=0;i>3]=e.axes[i]}for(var i=0;i>3]=e.buttons[i].value}else{HEAPF64[eventStruct+i*8+528>>3]=e.buttons[i]}}for(var i=0;i>2]=e.buttons[i].pressed}else{HEAP32[eventStruct+i*4+1040>>2]=e.buttons[i]==1}}HEAP32[eventStruct+1296>>2]=e.connected;HEAP32[eventStruct+1300>>2]=e.index;HEAP32[eventStruct+8>>2]=e.axes.length;HEAP32[eventStruct+12>>2]=e.buttons.length;stringToUTF8(e.id,eventStruct+1304,64);stringToUTF8(e.mapping,eventStruct+1368,64)}function _emscripten_get_gamepad_status(index,gamepadState){if(index<0||index>=JSEvents.lastGamepadState.length)return-5;if(!JSEvents.lastGamepadState[index])return-7;__fillGamepadEventData(gamepadState,JSEvents.lastGamepadState[index]);return 0}function _emscripten_get_num_gamepads(){return JSEvents.lastGamepadState.length}function _emscripten_get_sbrk_ptr(){return 1918800}function _emscripten_glActiveTexture(x0){GLctx["activeTexture"](x0)}function _emscripten_glAttachShader(program,shader){GLctx.attachShader(GL.programs[program],GL.shaders[shader])}function _emscripten_glBeginQueryEXT(target,id){GLctx.disjointTimerQueryExt["beginQueryEXT"](target,GL.timerQueriesEXT[id])}function _emscripten_glBindAttribLocation(program,index,name){GLctx.bindAttribLocation(GL.programs[program],index,UTF8ToString(name))}function _emscripten_glBindBuffer(target,buffer){if(target==34962){GLctx.currentArrayBufferBinding=buffer}else if(target==34963){GLctx.currentElementArrayBufferBinding=buffer}GLctx.bindBuffer(target,GL.buffers[buffer])}function _emscripten_glBindFramebuffer(target,framebuffer){GLctx.bindFramebuffer(target,GL.framebuffers[framebuffer])}function _emscripten_glBindRenderbuffer(target,renderbuffer){GLctx.bindRenderbuffer(target,GL.renderbuffers[renderbuffer])}function _emscripten_glBindTexture(target,texture){GLctx.bindTexture(target,GL.textures[texture])}function _emscripten_glBindVertexArrayOES(vao){GLctx["bindVertexArray"](GL.vaos[vao]);var ibo=GLctx.getParameter(34965);GLctx.currentElementArrayBufferBinding=ibo?ibo.name|0:0}function _emscripten_glBlendColor(x0,x1,x2,x3){GLctx["blendColor"](x0,x1,x2,x3)}function _emscripten_glBlendEquation(x0){GLctx["blendEquation"](x0)}function _emscripten_glBlendEquationSeparate(x0,x1){GLctx["blendEquationSeparate"](x0,x1)}function _emscripten_glBlendFunc(x0,x1){GLctx["blendFunc"](x0,x1)}function _emscripten_glBlendFuncSeparate(x0,x1,x2,x3){GLctx["blendFuncSeparate"](x0,x1,x2,x3)}function _emscripten_glBufferData(target,size,data,usage){GLctx.bufferData(target,data?HEAPU8.subarray(data,data+size):size,usage)}function _emscripten_glBufferSubData(target,offset,size,data){GLctx.bufferSubData(target,offset,HEAPU8.subarray(data,data+size))}function _emscripten_glCheckFramebufferStatus(x0){return GLctx["checkFramebufferStatus"](x0)}function _emscripten_glClear(x0){GLctx["clear"](x0)}function _emscripten_glClearColor(x0,x1,x2,x3){GLctx["clearColor"](x0,x1,x2,x3)}function _emscripten_glClearDepthf(x0){GLctx["clearDepth"](x0)}function _emscripten_glClearStencil(x0){GLctx["clearStencil"](x0)}function _emscripten_glColorMask(red,green,blue,alpha){GLctx.colorMask(!!red,!!green,!!blue,!!alpha)}function _emscripten_glCompileShader(shader){GLctx.compileShader(GL.shaders[shader])}function _emscripten_glCompressedTexImage2D(target,level,internalFormat,width,height,border,imageSize,data){GLctx["compressedTexImage2D"](target,level,internalFormat,width,height,border,data?HEAPU8.subarray(data,data+imageSize):null)}function _emscripten_glCompressedTexSubImage2D(target,level,xoffset,yoffset,width,height,format,imageSize,data){GLctx["compressedTexSubImage2D"](target,level,xoffset,yoffset,width,height,format,data?HEAPU8.subarray(data,data+imageSize):null)}function _emscripten_glCopyTexImage2D(x0,x1,x2,x3,x4,x5,x6,x7){GLctx["copyTexImage2D"](x0,x1,x2,x3,x4,x5,x6,x7)}function _emscripten_glCopyTexSubImage2D(x0,x1,x2,x3,x4,x5,x6,x7){GLctx["copyTexSubImage2D"](x0,x1,x2,x3,x4,x5,x6,x7)}function _emscripten_glCreateProgram(){var id=GL.getNewId(GL.programs);var program=GLctx.createProgram();program.name=id;GL.programs[id]=program;return id}function _emscripten_glCreateShader(shaderType){var id=GL.getNewId(GL.shaders);GL.shaders[id]=GLctx.createShader(shaderType);return id}function _emscripten_glCullFace(x0){GLctx["cullFace"](x0)}function _emscripten_glDeleteBuffers(n,buffers){for(var i=0;i>2];var buffer=GL.buffers[id];if(!buffer)continue;GLctx.deleteBuffer(buffer);buffer.name=0;GL.buffers[id]=null;if(id==GLctx.currentArrayBufferBinding)GLctx.currentArrayBufferBinding=0;if(id==GLctx.currentElementArrayBufferBinding)GLctx.currentElementArrayBufferBinding=0}}function _emscripten_glDeleteFramebuffers(n,framebuffers){for(var i=0;i>2];var framebuffer=GL.framebuffers[id];if(!framebuffer)continue;GLctx.deleteFramebuffer(framebuffer);framebuffer.name=0;GL.framebuffers[id]=null}}function _emscripten_glDeleteProgram(id){if(!id)return;var program=GL.programs[id];if(!program){GL.recordError(1281);return}GLctx.deleteProgram(program);program.name=0;GL.programs[id]=null;GL.programInfos[id]=null}function _emscripten_glDeleteQueriesEXT(n,ids){for(var i=0;i>2];var query=GL.timerQueriesEXT[id];if(!query)continue;GLctx.disjointTimerQueryExt["deleteQueryEXT"](query);GL.timerQueriesEXT[id]=null}}function _emscripten_glDeleteRenderbuffers(n,renderbuffers){for(var i=0;i>2];var renderbuffer=GL.renderbuffers[id];if(!renderbuffer)continue;GLctx.deleteRenderbuffer(renderbuffer);renderbuffer.name=0;GL.renderbuffers[id]=null}}function _emscripten_glDeleteShader(id){if(!id)return;var shader=GL.shaders[id];if(!shader){GL.recordError(1281);return}GLctx.deleteShader(shader);GL.shaders[id]=null}function _emscripten_glDeleteTextures(n,textures){for(var i=0;i>2];var texture=GL.textures[id];if(!texture)continue;GLctx.deleteTexture(texture);texture.name=0;GL.textures[id]=null}}function _emscripten_glDeleteVertexArraysOES(n,vaos){for(var i=0;i>2];GLctx["deleteVertexArray"](GL.vaos[id]);GL.vaos[id]=null}}function _emscripten_glDepthFunc(x0){GLctx["depthFunc"](x0)}function _emscripten_glDepthMask(flag){GLctx.depthMask(!!flag)}function _emscripten_glDepthRangef(x0,x1){GLctx["depthRange"](x0,x1)}function _emscripten_glDetachShader(program,shader){GLctx.detachShader(GL.programs[program],GL.shaders[shader])}function _emscripten_glDisable(x0){GLctx["disable"](x0)}function _emscripten_glDisableVertexAttribArray(index){var cb=GL.currentContext.clientBuffers[index];cb.enabled=false;GLctx.disableVertexAttribArray(index)}function _emscripten_glDrawArrays(mode,first,count){GL.preDrawHandleClientVertexAttribBindings(first+count);GLctx.drawArrays(mode,first,count);GL.postDrawHandleClientVertexAttribBindings()}function _emscripten_glDrawArraysInstancedANGLE(mode,first,count,primcount){GLctx["drawArraysInstanced"](mode,first,count,primcount)}var tempFixedLengthArray=[];function _emscripten_glDrawBuffersWEBGL(n,bufs){var bufArray=tempFixedLengthArray[n];for(var i=0;i>2]}GLctx["drawBuffers"](bufArray)}function _emscripten_glDrawElements(mode,count,type,indices){var buf;if(!GLctx.currentElementArrayBufferBinding){var size=GL.calcBufLength(1,type,0,count);buf=GL.getTempIndexBuffer(size);GLctx.bindBuffer(34963,buf);GLctx.bufferSubData(34963,0,HEAPU8.subarray(indices,indices+size));indices=0}GL.preDrawHandleClientVertexAttribBindings(count);GLctx.drawElements(mode,count,type,indices);GL.postDrawHandleClientVertexAttribBindings(count);if(!GLctx.currentElementArrayBufferBinding){GLctx.bindBuffer(34963,null)}}function _emscripten_glDrawElementsInstancedANGLE(mode,count,type,indices,primcount){GLctx["drawElementsInstanced"](mode,count,type,indices,primcount)}function _emscripten_glEnable(x0){GLctx["enable"](x0)}function _emscripten_glEnableVertexAttribArray(index){var cb=GL.currentContext.clientBuffers[index];cb.enabled=true;GLctx.enableVertexAttribArray(index)}function _emscripten_glEndQueryEXT(target){GLctx.disjointTimerQueryExt["endQueryEXT"](target)}function _emscripten_glFinish(){GLctx["finish"]()}function _emscripten_glFlush(){GLctx["flush"]()}function _emscripten_glFramebufferRenderbuffer(target,attachment,renderbuffertarget,renderbuffer){GLctx.framebufferRenderbuffer(target,attachment,renderbuffertarget,GL.renderbuffers[renderbuffer])}function _emscripten_glFramebufferTexture2D(target,attachment,textarget,texture,level){GLctx.framebufferTexture2D(target,attachment,textarget,GL.textures[texture],level)}function _emscripten_glFrontFace(x0){GLctx["frontFace"](x0)}function __glGenObject(n,buffers,createFunction,objectTable){for(var i=0;i>2]=id}}function _emscripten_glGenBuffers(n,buffers){__glGenObject(n,buffers,"createBuffer",GL.buffers)}function _emscripten_glGenFramebuffers(n,ids){__glGenObject(n,ids,"createFramebuffer",GL.framebuffers)}function _emscripten_glGenQueriesEXT(n,ids){for(var i=0;i>2]=0;return}var id=GL.getNewId(GL.timerQueriesEXT);query.name=id;GL.timerQueriesEXT[id]=query;HEAP32[ids+i*4>>2]=id}}function _emscripten_glGenRenderbuffers(n,renderbuffers){__glGenObject(n,renderbuffers,"createRenderbuffer",GL.renderbuffers)}function _emscripten_glGenTextures(n,textures){__glGenObject(n,textures,"createTexture",GL.textures)}function _emscripten_glGenVertexArraysOES(n,arrays){__glGenObject(n,arrays,"createVertexArray",GL.vaos)}function _emscripten_glGenerateMipmap(x0){GLctx["generateMipmap"](x0)}function __glGetActiveAttribOrUniform(funcName,program,index,bufSize,length,size,type,name){program=GL.programs[program];var info=GLctx[funcName](program,index);if(info){var numBytesWrittenExclNull=name&&stringToUTF8(info.name,name,bufSize);if(length)HEAP32[length>>2]=numBytesWrittenExclNull;if(size)HEAP32[size>>2]=info.size;if(type)HEAP32[type>>2]=info.type}}function _emscripten_glGetActiveAttrib(program,index,bufSize,length,size,type,name){__glGetActiveAttribOrUniform("getActiveAttrib",program,index,bufSize,length,size,type,name)}function _emscripten_glGetActiveUniform(program,index,bufSize,length,size,type,name){__glGetActiveAttribOrUniform("getActiveUniform",program,index,bufSize,length,size,type,name)}function _emscripten_glGetAttachedShaders(program,maxCount,count,shaders){var result=GLctx.getAttachedShaders(GL.programs[program]);var len=result.length;if(len>maxCount){len=maxCount}HEAP32[count>>2]=len;for(var i=0;i>2]=id}}function _emscripten_glGetAttribLocation(program,name){return GLctx.getAttribLocation(GL.programs[program],UTF8ToString(name))}function writeI53ToI64(ptr,num){HEAPU32[ptr>>2]=num;HEAPU32[ptr+4>>2]=(num-HEAPU32[ptr>>2])/4294967296}function emscriptenWebGLGet(name_,p,type){if(!p){GL.recordError(1281);return}var ret=undefined;switch(name_){case 36346:ret=1;break;case 36344:if(type!=0&&type!=1){GL.recordError(1280)}return;case 36345:ret=0;break;case 34466:var formats=GLctx.getParameter(34467);ret=formats?formats.length:0;break}if(ret===undefined){var result=GLctx.getParameter(name_);switch(typeof result){case"number":ret=result;break;case"boolean":ret=result?1:0;break;case"string":GL.recordError(1280);return;case"object":if(result===null){switch(name_){case 34964:case 35725:case 34965:case 36006:case 36007:case 32873:case 34229:case 34068:{ret=0;break}default:{GL.recordError(1280);return}}}else if(result instanceof Float32Array||result instanceof Uint32Array||result instanceof Int32Array||result instanceof Array){for(var i=0;i>2]=result[i];break;case 2:HEAPF32[p+i*4>>2]=result[i];break;case 4:HEAP8[p+i>>0]=result[i]?1:0;break}}return}else{try{ret=result.name|0}catch(e){GL.recordError(1280);err("GL_INVALID_ENUM in glGet"+type+"v: Unknown object returned from WebGL getParameter("+name_+")! (error: "+e+")");return}}break;default:GL.recordError(1280);err("GL_INVALID_ENUM in glGet"+type+"v: Native code calling glGet"+type+"v("+name_+") and it returns "+result+" of type "+typeof result+"!");return}}switch(type){case 1:writeI53ToI64(p,ret);break;case 0:HEAP32[p>>2]=ret;break;case 2:HEAPF32[p>>2]=ret;break;case 4:HEAP8[p>>0]=ret?1:0;break}}function _emscripten_glGetBooleanv(name_,p){emscriptenWebGLGet(name_,p,4)}function _emscripten_glGetBufferParameteriv(target,value,data){if(!data){GL.recordError(1281);return}HEAP32[data>>2]=GLctx.getBufferParameter(target,value)}function _emscripten_glGetError(){var error=GLctx.getError()||GL.lastError;GL.lastError=0;return error}function _emscripten_glGetFloatv(name_,p){emscriptenWebGLGet(name_,p,2)}function _emscripten_glGetFramebufferAttachmentParameteriv(target,attachment,pname,params){var result=GLctx.getFramebufferAttachmentParameter(target,attachment,pname);if(result instanceof WebGLRenderbuffer||result instanceof WebGLTexture){result=result.name|0}HEAP32[params>>2]=result}function _emscripten_glGetIntegerv(name_,p){emscriptenWebGLGet(name_,p,0)}function _emscripten_glGetProgramInfoLog(program,maxLength,length,infoLog){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _emscripten_glGetProgramiv(program,pname,p){if(!p){GL.recordError(1281);return}if(program>=GL.counter){GL.recordError(1281);return}var ptable=GL.programInfos[program];if(!ptable){GL.recordError(1282);return}if(pname==35716){var log=GLctx.getProgramInfoLog(GL.programs[program]);if(log===null)log="(unknown error)";HEAP32[p>>2]=log.length+1}else if(pname==35719){HEAP32[p>>2]=ptable.maxUniformLength}else if(pname==35722){if(ptable.maxAttributeLength==-1){program=GL.programs[program];var numAttribs=GLctx.getProgramParameter(program,35721);ptable.maxAttributeLength=0;for(var i=0;i>2]=ptable.maxAttributeLength}else if(pname==35381){if(ptable.maxUniformBlockNameLength==-1){program=GL.programs[program];var numBlocks=GLctx.getProgramParameter(program,35382);ptable.maxUniformBlockNameLength=0;for(var i=0;i>2]=ptable.maxUniformBlockNameLength}else{HEAP32[p>>2]=GLctx.getProgramParameter(GL.programs[program],pname)}}function _emscripten_glGetQueryObjecti64vEXT(id,pname,params){if(!params){GL.recordError(1281);return}var query=GL.timerQueriesEXT[id];var param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}writeI53ToI64(params,ret)}function _emscripten_glGetQueryObjectivEXT(id,pname,params){if(!params){GL.recordError(1281);return}var query=GL.timerQueriesEXT[id];var param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}HEAP32[params>>2]=ret}function _emscripten_glGetQueryObjectui64vEXT(id,pname,params){if(!params){GL.recordError(1281);return}var query=GL.timerQueriesEXT[id];var param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}writeI53ToI64(params,ret)}function _emscripten_glGetQueryObjectuivEXT(id,pname,params){if(!params){GL.recordError(1281);return}var query=GL.timerQueriesEXT[id];var param=GLctx.disjointTimerQueryExt["getQueryObjectEXT"](query,pname);var ret;if(typeof param=="boolean"){ret=param?1:0}else{ret=param}HEAP32[params>>2]=ret}function _emscripten_glGetQueryivEXT(target,pname,params){if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.disjointTimerQueryExt["getQueryEXT"](target,pname)}function _emscripten_glGetRenderbufferParameteriv(target,pname,params){if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getRenderbufferParameter(target,pname)}function _emscripten_glGetShaderInfoLog(shader,maxLength,length,infoLog){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var numBytesWrittenExclNull=maxLength>0&&infoLog?stringToUTF8(log,infoLog,maxLength):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _emscripten_glGetShaderPrecisionFormat(shaderType,precisionType,range,precision){var result=GLctx.getShaderPrecisionFormat(shaderType,precisionType);HEAP32[range>>2]=result.rangeMin;HEAP32[range+4>>2]=result.rangeMax;HEAP32[precision>>2]=result.precision}function _emscripten_glGetShaderSource(shader,bufSize,length,source){var result=GLctx.getShaderSource(GL.shaders[shader]);if(!result)return;var numBytesWrittenExclNull=bufSize>0&&source?stringToUTF8(result,source,bufSize):0;if(length)HEAP32[length>>2]=numBytesWrittenExclNull}function _emscripten_glGetShaderiv(shader,pname,p){if(!p){GL.recordError(1281);return}if(pname==35716){var log=GLctx.getShaderInfoLog(GL.shaders[shader]);if(log===null)log="(unknown error)";var logLength=log?log.length+1:0;HEAP32[p>>2]=logLength}else if(pname==35720){var source=GLctx.getShaderSource(GL.shaders[shader]);var sourceLength=source?source.length+1:0;HEAP32[p>>2]=sourceLength}else{HEAP32[p>>2]=GLctx.getShaderParameter(GL.shaders[shader],pname)}}function stringToNewUTF8(jsString){var length=lengthBytesUTF8(jsString)+1;var cString=_malloc(length);stringToUTF8(jsString,cString,length);return cString}function _emscripten_glGetString(name_){if(GL.stringCache[name_])return GL.stringCache[name_];var ret;switch(name_){case 7939:var exts=GLctx.getSupportedExtensions()||[];exts=exts.concat(exts.map(function(e){return"GL_"+e}));ret=stringToNewUTF8(exts.join(" "));break;case 7936:case 7937:case 37445:case 37446:var s=GLctx.getParameter(name_);if(!s){GL.recordError(1280)}ret=stringToNewUTF8(s);break;case 7938:var glVersion=GLctx.getParameter(7938);{glVersion="OpenGL ES 2.0 ("+glVersion+")"}ret=stringToNewUTF8(glVersion);break;case 35724:var glslVersion=GLctx.getParameter(35724);var ver_re=/^WebGL GLSL ES ([0-9]\.[0-9][0-9]?)(?:$| .*)/;var ver_num=glslVersion.match(ver_re);if(ver_num!==null){if(ver_num[1].length==3)ver_num[1]=ver_num[1]+"0";glslVersion="OpenGL ES GLSL ES "+ver_num[1]+" ("+glslVersion+")"}ret=stringToNewUTF8(glslVersion);break;default:GL.recordError(1280);return 0}GL.stringCache[name_]=ret;return ret}function _emscripten_glGetTexParameterfv(target,pname,params){if(!params){GL.recordError(1281);return}HEAPF32[params>>2]=GLctx.getTexParameter(target,pname)}function _emscripten_glGetTexParameteriv(target,pname,params){if(!params){GL.recordError(1281);return}HEAP32[params>>2]=GLctx.getTexParameter(target,pname)}function _emscripten_glGetUniformLocation(program,name){name=UTF8ToString(name);var arrayIndex=0;if(name[name.length-1]=="]"){var leftBrace=name.lastIndexOf("[");arrayIndex=name[leftBrace+1]!="]"?jstoi_q(name.slice(leftBrace+1)):0;name=name.slice(0,leftBrace)}var uniformInfo=GL.programInfos[program]&&GL.programInfos[program].uniforms[name];if(uniformInfo&&arrayIndex>=0&&arrayIndex>2]=data;break;case 2:HEAPF32[params>>2]=data;break}}else{for(var i=0;i>2]=data[i];break;case 2:HEAPF32[params+i*4>>2]=data[i];break}}}}function _emscripten_glGetUniformfv(program,location,params){emscriptenWebGLGetUniform(program,location,params,2)}function _emscripten_glGetUniformiv(program,location,params){emscriptenWebGLGetUniform(program,location,params,0)}function _emscripten_glGetVertexAttribPointerv(index,pname,pointer){if(!pointer){GL.recordError(1281);return}if(GL.currentContext.clientBuffers[index].enabled){err("glGetVertexAttribPointer on client-side array: not supported, bad data returned")}HEAP32[pointer>>2]=GLctx.getVertexAttribOffset(index,pname)}function emscriptenWebGLGetVertexAttrib(index,pname,params,type){if(!params){GL.recordError(1281);return}if(GL.currentContext.clientBuffers[index].enabled){err("glGetVertexAttrib*v on client-side array: not supported, bad data returned")}var data=GLctx.getVertexAttrib(index,pname);if(pname==34975){HEAP32[params>>2]=data&&data["name"]}else if(typeof data=="number"||typeof data=="boolean"){switch(type){case 0:HEAP32[params>>2]=data;break;case 2:HEAPF32[params>>2]=data;break;case 5:HEAP32[params>>2]=Math.fround(data);break}}else{for(var i=0;i>2]=data[i];break;case 2:HEAPF32[params+i*4>>2]=data[i];break;case 5:HEAP32[params+i*4>>2]=Math.fround(data[i]);break}}}}function _emscripten_glGetVertexAttribfv(index,pname,params){emscriptenWebGLGetVertexAttrib(index,pname,params,2)}function _emscripten_glGetVertexAttribiv(index,pname,params){emscriptenWebGLGetVertexAttrib(index,pname,params,5)}function _emscripten_glHint(x0,x1){GLctx["hint"](x0,x1)}function _emscripten_glIsBuffer(buffer){var b=GL.buffers[buffer];if(!b)return 0;return GLctx.isBuffer(b)}function _emscripten_glIsEnabled(x0){return GLctx["isEnabled"](x0)}function _emscripten_glIsFramebuffer(framebuffer){var fb=GL.framebuffers[framebuffer];if(!fb)return 0;return GLctx.isFramebuffer(fb)}function _emscripten_glIsProgram(program){program=GL.programs[program];if(!program)return 0;return GLctx.isProgram(program)}function _emscripten_glIsQueryEXT(id){var query=GL.timerQueriesEXT[id];if(!query)return 0;return GLctx.disjointTimerQueryExt["isQueryEXT"](query)}function _emscripten_glIsRenderbuffer(renderbuffer){var rb=GL.renderbuffers[renderbuffer];if(!rb)return 0;return GLctx.isRenderbuffer(rb)}function _emscripten_glIsShader(shader){var s=GL.shaders[shader];if(!s)return 0;return GLctx.isShader(s)}function _emscripten_glIsTexture(id){var texture=GL.textures[id];if(!texture)return 0;return GLctx.isTexture(texture)}function _emscripten_glIsVertexArrayOES(array){var vao=GL.vaos[array];if(!vao)return 0;return GLctx["isVertexArray"](vao)}function _emscripten_glLineWidth(x0){GLctx["lineWidth"](x0)}function _emscripten_glLinkProgram(program){GLctx.linkProgram(GL.programs[program]);GL.populateUniformTable(program)}function _emscripten_glPixelStorei(pname,param){if(pname==3317){GL.unpackAlignment=param}GLctx.pixelStorei(pname,param)}function _emscripten_glPolygonOffset(x0,x1){GLctx["polygonOffset"](x0,x1)}function _emscripten_glQueryCounterEXT(id,target){GLctx.disjointTimerQueryExt["queryCounterEXT"](GL.timerQueriesEXT[id],target)}function computeUnpackAlignedImageSize(width,height,sizePerPixel,alignment){function roundedToNextMultipleOf(x,y){return x+y-1&-y}var plainRowSize=width*sizePerPixel;var alignedRowSize=roundedToNextMultipleOf(plainRowSize,alignment);return height*alignedRowSize}function __colorChannelsInGlTextureFormat(format){var colorChannels={5:3,6:4,8:2,29502:3,29504:4};return colorChannels[format-6402]||1}function heapObjectForWebGLType(type){type-=5120;if(type==1)return HEAPU8;if(type==4)return HEAP32;if(type==6)return HEAPF32;if(type==5||type==28922)return HEAPU32;return HEAPU16}function heapAccessShiftForWebGLHeap(heap){return 31-Math.clz32(heap.BYTES_PER_ELEMENT)}function emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat){var heap=heapObjectForWebGLType(type);var shift=heapAccessShiftForWebGLHeap(heap);var byteSize=1<>shift,pixels+bytes>>shift)}function _emscripten_glReadPixels(x,y,width,height,format,type,pixels){var pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,format);if(!pixelData){GL.recordError(1280);return}GLctx.readPixels(x,y,width,height,format,type,pixelData)}function _emscripten_glReleaseShaderCompiler(){}function _emscripten_glRenderbufferStorage(x0,x1,x2,x3){GLctx["renderbufferStorage"](x0,x1,x2,x3)}function _emscripten_glSampleCoverage(value,invert){GLctx.sampleCoverage(value,!!invert)}function _emscripten_glScissor(x0,x1,x2,x3){GLctx["scissor"](x0,x1,x2,x3)}function _emscripten_glShaderBinary(){GL.recordError(1280)}function _emscripten_glShaderSource(shader,count,string,length){var source=GL.getSource(shader,count,string,length);GLctx.shaderSource(GL.shaders[shader],source)}function _emscripten_glStencilFunc(x0,x1,x2){GLctx["stencilFunc"](x0,x1,x2)}function _emscripten_glStencilFuncSeparate(x0,x1,x2,x3){GLctx["stencilFuncSeparate"](x0,x1,x2,x3)}function _emscripten_glStencilMask(x0){GLctx["stencilMask"](x0)}function _emscripten_glStencilMaskSeparate(x0,x1){GLctx["stencilMaskSeparate"](x0,x1)}function _emscripten_glStencilOp(x0,x1,x2){GLctx["stencilOp"](x0,x1,x2)}function _emscripten_glStencilOpSeparate(x0,x1,x2,x3){GLctx["stencilOpSeparate"](x0,x1,x2,x3)}function _emscripten_glTexImage2D(target,level,internalFormat,width,height,border,format,type,pixels){GLctx.texImage2D(target,level,internalFormat,width,height,border,format,type,pixels?emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,internalFormat):null)}function _emscripten_glTexParameterf(x0,x1,x2){GLctx["texParameterf"](x0,x1,x2)}function _emscripten_glTexParameterfv(target,pname,params){var param=HEAPF32[params>>2];GLctx.texParameterf(target,pname,param)}function _emscripten_glTexParameteri(x0,x1,x2){GLctx["texParameteri"](x0,x1,x2)}function _emscripten_glTexParameteriv(target,pname,params){var param=HEAP32[params>>2];GLctx.texParameteri(target,pname,param)}function _emscripten_glTexSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixels){var pixelData=null;if(pixels)pixelData=emscriptenWebGLGetTexPixelData(type,format,width,height,pixels,0);GLctx.texSubImage2D(target,level,xoffset,yoffset,width,height,format,type,pixelData)}function _emscripten_glUniform1f(location,v0){GLctx.uniform1f(GL.uniforms[location],v0)}var miniTempWebGLFloatBuffers=[];function _emscripten_glUniform1fv(location,count,value){if(count<=288){var view=miniTempWebGLFloatBuffers[count-1];for(var i=0;i>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1fv(GL.uniforms[location],view)}function _emscripten_glUniform1i(location,v0){GLctx.uniform1i(GL.uniforms[location],v0)}var __miniTempWebGLIntBuffers=[];function _emscripten_glUniform1iv(location,count,value){if(count<=288){var view=__miniTempWebGLIntBuffers[count-1];for(var i=0;i>2]}}else{var view=HEAP32.subarray(value>>2,value+count*4>>2)}GLctx.uniform1iv(GL.uniforms[location],view)}function _emscripten_glUniform2f(location,v0,v1){GLctx.uniform2f(GL.uniforms[location],v0,v1)}function _emscripten_glUniform2fv(location,count,value){if(count<=144){var view=miniTempWebGLFloatBuffers[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2fv(GL.uniforms[location],view)}function _emscripten_glUniform2i(location,v0,v1){GLctx.uniform2i(GL.uniforms[location],v0,v1)}function _emscripten_glUniform2iv(location,count,value){if(count<=144){var view=__miniTempWebGLIntBuffers[2*count-1];for(var i=0;i<2*count;i+=2){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*8>>2)}GLctx.uniform2iv(GL.uniforms[location],view)}function _emscripten_glUniform3f(location,v0,v1,v2){GLctx.uniform3f(GL.uniforms[location],v0,v1,v2)}function _emscripten_glUniform3fv(location,count,value){if(count<=96){var view=miniTempWebGLFloatBuffers[3*count-1];for(var i=0;i<3*count;i+=3){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3fv(GL.uniforms[location],view)}function _emscripten_glUniform3i(location,v0,v1,v2){GLctx.uniform3i(GL.uniforms[location],v0,v1,v2)}function _emscripten_glUniform3iv(location,count,value){if(count<=96){var view=__miniTempWebGLIntBuffers[3*count-1];for(var i=0;i<3*count;i+=3){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*12>>2)}GLctx.uniform3iv(GL.uniforms[location],view)}function _emscripten_glUniform4f(location,v0,v1,v2,v3){GLctx.uniform4f(GL.uniforms[location],v0,v1,v2,v3)}function _emscripten_glUniform4fv(location,count,value){if(count<=72){var view=miniTempWebGLFloatBuffers[4*count-1];var heap=HEAPF32;value>>=2;for(var i=0;i<4*count;i+=4){var dst=value+i;view[i]=heap[dst];view[i+1]=heap[dst+1];view[i+2]=heap[dst+2];view[i+3]=heap[dst+3]}}else{var view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4fv(GL.uniforms[location],view)}function _emscripten_glUniform4i(location,v0,v1,v2,v3){GLctx.uniform4i(GL.uniforms[location],v0,v1,v2,v3)}function _emscripten_glUniform4iv(location,count,value){if(count<=72){var view=__miniTempWebGLIntBuffers[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAP32[value+4*i>>2];view[i+1]=HEAP32[value+(4*i+4)>>2];view[i+2]=HEAP32[value+(4*i+8)>>2];view[i+3]=HEAP32[value+(4*i+12)>>2]}}else{var view=HEAP32.subarray(value>>2,value+count*16>>2)}GLctx.uniform4iv(GL.uniforms[location],view)}function _emscripten_glUniformMatrix2fv(location,count,transpose,value){if(count<=72){var view=miniTempWebGLFloatBuffers[4*count-1];for(var i=0;i<4*count;i+=4){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*16>>2)}GLctx.uniformMatrix2fv(GL.uniforms[location],!!transpose,view)}function _emscripten_glUniformMatrix3fv(location,count,transpose,value){if(count<=32){var view=miniTempWebGLFloatBuffers[9*count-1];for(var i=0;i<9*count;i+=9){view[i]=HEAPF32[value+4*i>>2];view[i+1]=HEAPF32[value+(4*i+4)>>2];view[i+2]=HEAPF32[value+(4*i+8)>>2];view[i+3]=HEAPF32[value+(4*i+12)>>2];view[i+4]=HEAPF32[value+(4*i+16)>>2];view[i+5]=HEAPF32[value+(4*i+20)>>2];view[i+6]=HEAPF32[value+(4*i+24)>>2];view[i+7]=HEAPF32[value+(4*i+28)>>2];view[i+8]=HEAPF32[value+(4*i+32)>>2]}}else{var view=HEAPF32.subarray(value>>2,value+count*36>>2)}GLctx.uniformMatrix3fv(GL.uniforms[location],!!transpose,view)}function _emscripten_glUniformMatrix4fv(location,count,transpose,value){if(count<=18){var view=miniTempWebGLFloatBuffers[16*count-1];var heap=HEAPF32;value>>=2;for(var i=0;i<16*count;i+=16){var dst=value+i;view[i]=heap[dst];view[i+1]=heap[dst+1];view[i+2]=heap[dst+2];view[i+3]=heap[dst+3];view[i+4]=heap[dst+4];view[i+5]=heap[dst+5];view[i+6]=heap[dst+6];view[i+7]=heap[dst+7];view[i+8]=heap[dst+8];view[i+9]=heap[dst+9];view[i+10]=heap[dst+10];view[i+11]=heap[dst+11];view[i+12]=heap[dst+12];view[i+13]=heap[dst+13];view[i+14]=heap[dst+14];view[i+15]=heap[dst+15]}}else{var view=HEAPF32.subarray(value>>2,value+count*64>>2)}GLctx.uniformMatrix4fv(GL.uniforms[location],!!transpose,view)}function _emscripten_glUseProgram(program){GLctx.useProgram(GL.programs[program])}function _emscripten_glValidateProgram(program){GLctx.validateProgram(GL.programs[program])}function _emscripten_glVertexAttrib1f(x0,x1){GLctx["vertexAttrib1f"](x0,x1)}function _emscripten_glVertexAttrib1fv(index,v){GLctx.vertexAttrib1f(index,HEAPF32[v>>2])}function _emscripten_glVertexAttrib2f(x0,x1,x2){GLctx["vertexAttrib2f"](x0,x1,x2)}function _emscripten_glVertexAttrib2fv(index,v){GLctx.vertexAttrib2f(index,HEAPF32[v>>2],HEAPF32[v+4>>2])}function _emscripten_glVertexAttrib3f(x0,x1,x2,x3){GLctx["vertexAttrib3f"](x0,x1,x2,x3)}function _emscripten_glVertexAttrib3fv(index,v){GLctx.vertexAttrib3f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2])}function _emscripten_glVertexAttrib4f(x0,x1,x2,x3,x4){GLctx["vertexAttrib4f"](x0,x1,x2,x3,x4)}function _emscripten_glVertexAttrib4fv(index,v){GLctx.vertexAttrib4f(index,HEAPF32[v>>2],HEAPF32[v+4>>2],HEAPF32[v+8>>2],HEAPF32[v+12>>2])}function _emscripten_glVertexAttribDivisorANGLE(index,divisor){GLctx["vertexAttribDivisor"](index,divisor)}function _emscripten_glVertexAttribPointer(index,size,type,normalized,stride,ptr){var cb=GL.currentContext.clientBuffers[index];if(!GLctx.currentArrayBufferBinding){cb.size=size;cb.type=type;cb.normalized=normalized;cb.stride=stride;cb.ptr=ptr;cb.clientside=true;cb.vertexAttribPointerAdaptor=function(index,size,type,normalized,stride,ptr){this.vertexAttribPointer(index,size,type,normalized,stride,ptr)};return}cb.clientside=false;GLctx.vertexAttribPointer(index,size,type,!!normalized,stride,ptr)}function _emscripten_glViewport(x0,x1,x2,x3){GLctx["viewport"](x0,x1,x2,x3)}function _emscripten_has_asyncify(){return 0}function _longjmp(env,value){_setThrew(env,value||1);throw"longjmp"}function _emscripten_longjmp(env,value){_longjmp(env,value)}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function __emscripten_do_request_fullscreen(target,strategy){if(!JSEvents.fullscreenEnabled())return-1;target=findEventTarget(target);if(!target)return-4;if(!target.requestFullscreen&&!target.webkitRequestFullscreen){return-3}var canPerformRequests=JSEvents.canPerformEventHandlerRequests();if(!canPerformRequests){if(strategy.deferUntilInEventHandler){JSEvents.deferCall(_JSEvents_requestFullscreen,1,[target,strategy]);return 1}else{return-2}}return _JSEvents_requestFullscreen(target,strategy)}function _emscripten_request_fullscreen_strategy(target,deferUntilInEventHandler,fullscreenStrategy){var strategy={scaleMode:HEAP32[fullscreenStrategy>>2],canvasResolutionScaleMode:HEAP32[fullscreenStrategy+4>>2],filteringMode:HEAP32[fullscreenStrategy+8>>2],deferUntilInEventHandler:deferUntilInEventHandler,canvasResizedCallback:HEAP32[fullscreenStrategy+12>>2],canvasResizedCallbackUserData:HEAP32[fullscreenStrategy+16>>2]};return __emscripten_do_request_fullscreen(target,strategy)}function _emscripten_request_pointerlock(target,deferUntilInEventHandler){target=findEventTarget(target);if(!target)return-4;if(!target.requestPointerLock&&!target.msRequestPointerLock){return-1}var canPerformRequests=JSEvents.canPerformEventHandlerRequests();if(!canPerformRequests){if(deferUntilInEventHandler){JSEvents.deferCall(__requestPointerLock,2,[target]);return 1}else{return-2}}return __requestPointerLock(target)}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}function _emscripten_run_script(ptr){eval(UTF8ToString(ptr))}function _emscripten_sample_gamepad_data(){return(JSEvents.lastGamepadState=navigator.getGamepads?navigator.getGamepads():navigator.webkitGetGamepads?navigator.webkitGetGamepads():null)?0:-1}function __registerBeforeUnloadEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString){var beforeUnloadEventHandlerFunc=function(ev){var e=ev||event;var confirmationMessage=wasmTable.get(callbackfunc)(eventTypeId,0,userData);if(confirmationMessage){confirmationMessage=UTF8ToString(confirmationMessage)}if(confirmationMessage){e.preventDefault();e.returnValue=confirmationMessage;return confirmationMessage}};var eventHandler={target:findEventTarget(target),eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:beforeUnloadEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_beforeunload_callback_on_thread(userData,callbackfunc,targetThread){if(typeof onbeforeunload==="undefined")return-1;if(targetThread!==1)return-5;__registerBeforeUnloadEventCallback(2,userData,true,callbackfunc,28,"beforeunload");return 0}function __registerFocusEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.focusEvent)JSEvents.focusEvent=_malloc(256);var focusEventHandlerFunc=function(ev){var e=ev||event;var nodeName=JSEvents.getNodeNameForTarget(e.target);var id=e.target.id?e.target.id:"";var focusEvent=JSEvents.focusEvent;stringToUTF8(nodeName,focusEvent+0,128);stringToUTF8(id,focusEvent+128,128);if(wasmTable.get(callbackfunc)(eventTypeId,focusEvent,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:focusEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_blur_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerFocusEventCallback(target,userData,useCapture,callbackfunc,12,"blur",targetThread);return 0}function _emscripten_set_element_css_size(target,width,height){target=findEventTarget(target);if(!target)return-4;target.style.width=width+"px";target.style.height=height+"px";return 0}function _emscripten_set_focus_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerFocusEventCallback(target,userData,useCapture,callbackfunc,13,"focus",targetThread);return 0}function __fillFullscreenChangeEventData(eventStruct){var fullscreenElement=document.fullscreenElement||document.mozFullScreenElement||document.webkitFullscreenElement||document.msFullscreenElement;var isFullscreen=!!fullscreenElement;HEAP32[eventStruct>>2]=isFullscreen;HEAP32[eventStruct+4>>2]=JSEvents.fullscreenEnabled();var reportedElement=isFullscreen?fullscreenElement:JSEvents.previousFullscreenElement;var nodeName=JSEvents.getNodeNameForTarget(reportedElement);var id=reportedElement&&reportedElement.id?reportedElement.id:"";stringToUTF8(nodeName,eventStruct+8,128);stringToUTF8(id,eventStruct+136,128);HEAP32[eventStruct+264>>2]=reportedElement?reportedElement.clientWidth:0;HEAP32[eventStruct+268>>2]=reportedElement?reportedElement.clientHeight:0;HEAP32[eventStruct+272>>2]=screen.width;HEAP32[eventStruct+276>>2]=screen.height;if(isFullscreen){JSEvents.previousFullscreenElement=fullscreenElement}}function __registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.fullscreenChangeEvent)JSEvents.fullscreenChangeEvent=_malloc(280);var fullscreenChangeEventhandlerFunc=function(ev){var e=ev||event;var fullscreenChangeEvent=JSEvents.fullscreenChangeEvent;__fillFullscreenChangeEventData(fullscreenChangeEvent);if(wasmTable.get(callbackfunc)(eventTypeId,fullscreenChangeEvent,userData))e.preventDefault()};var eventHandler={target:target,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:fullscreenChangeEventhandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_fullscreenchange_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){if(!JSEvents.fullscreenEnabled())return-1;target=findEventTarget(target);if(!target)return-4;__registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,19,"fullscreenchange",targetThread);__registerFullscreenChangeEventCallback(target,userData,useCapture,callbackfunc,19,"webkitfullscreenchange",targetThread);return 0}function __registerGamepadEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.gamepadEvent)JSEvents.gamepadEvent=_malloc(1432);var gamepadEventHandlerFunc=function(ev){var e=ev||event;var gamepadEvent=JSEvents.gamepadEvent;__fillGamepadEventData(gamepadEvent,e["gamepad"]);if(wasmTable.get(callbackfunc)(eventTypeId,gamepadEvent,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:gamepadEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_gamepadconnected_callback_on_thread(userData,useCapture,callbackfunc,targetThread){if(!navigator.getGamepads&&!navigator.webkitGetGamepads)return-1;__registerGamepadEventCallback(2,userData,useCapture,callbackfunc,26,"gamepadconnected",targetThread);return 0}function _emscripten_set_gamepaddisconnected_callback_on_thread(userData,useCapture,callbackfunc,targetThread){if(!navigator.getGamepads&&!navigator.webkitGetGamepads)return-1;__registerGamepadEventCallback(2,userData,useCapture,callbackfunc,27,"gamepaddisconnected",targetThread);return 0}function __registerKeyEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.keyEvent)JSEvents.keyEvent=_malloc(164);var keyEventHandlerFunc=function(e){var keyEventData=JSEvents.keyEvent;var idx=keyEventData>>2;HEAP32[idx+0]=e.location;HEAP32[idx+1]=e.ctrlKey;HEAP32[idx+2]=e.shiftKey;HEAP32[idx+3]=e.altKey;HEAP32[idx+4]=e.metaKey;HEAP32[idx+5]=e.repeat;HEAP32[idx+6]=e.charCode;HEAP32[idx+7]=e.keyCode;HEAP32[idx+8]=e.which;stringToUTF8(e.key||"",keyEventData+36,32);stringToUTF8(e.code||"",keyEventData+68,32);stringToUTF8(e.char||"",keyEventData+100,32);stringToUTF8(e.locale||"",keyEventData+132,32);if(wasmTable.get(callbackfunc)(eventTypeId,keyEventData,userData))e.preventDefault()};var eventHandler={target:findEventTarget(target),allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:keyEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_keydown_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerKeyEventCallback(target,userData,useCapture,callbackfunc,2,"keydown",targetThread);return 0}function _emscripten_set_keypress_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerKeyEventCallback(target,userData,useCapture,callbackfunc,1,"keypress",targetThread);return 0}function _emscripten_set_keyup_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerKeyEventCallback(target,userData,useCapture,callbackfunc,3,"keyup",targetThread);return 0}function _emscripten_set_main_loop_arg(func,arg,fps,simulateInfiniteLoop){var browserIterationFunc=function(){wasmTable.get(func)(arg)};setMainLoop(browserIterationFunc,fps,simulateInfiniteLoop,arg)}function __fillMouseEventData(eventStruct,e,target){var idx=eventStruct>>2;HEAP32[idx+0]=e.screenX;HEAP32[idx+1]=e.screenY;HEAP32[idx+2]=e.clientX;HEAP32[idx+3]=e.clientY;HEAP32[idx+4]=e.ctrlKey;HEAP32[idx+5]=e.shiftKey;HEAP32[idx+6]=e.altKey;HEAP32[idx+7]=e.metaKey;HEAP16[idx*2+16]=e.button;HEAP16[idx*2+17]=e.buttons;HEAP32[idx+9]=e["movementX"];HEAP32[idx+10]=e["movementY"];var rect=__getBoundingClientRect(target);HEAP32[idx+11]=e.clientX-rect.left;HEAP32[idx+12]=e.clientY-rect.top}function __registerMouseEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.mouseEvent)JSEvents.mouseEvent=_malloc(64);target=findEventTarget(target);var mouseEventHandlerFunc=function(ev){var e=ev||event;__fillMouseEventData(JSEvents.mouseEvent,e,target);if(wasmTable.get(callbackfunc)(eventTypeId,JSEvents.mouseEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString!="mousemove"&&eventTypeString!="mouseenter"&&eventTypeString!="mouseleave",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:mouseEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_mousedown_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerMouseEventCallback(target,userData,useCapture,callbackfunc,5,"mousedown",targetThread);return 0}function _emscripten_set_mouseenter_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerMouseEventCallback(target,userData,useCapture,callbackfunc,33,"mouseenter",targetThread);return 0}function _emscripten_set_mouseleave_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerMouseEventCallback(target,userData,useCapture,callbackfunc,34,"mouseleave",targetThread);return 0}function _emscripten_set_mousemove_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerMouseEventCallback(target,userData,useCapture,callbackfunc,8,"mousemove",targetThread);return 0}function _emscripten_set_mouseup_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerMouseEventCallback(target,userData,useCapture,callbackfunc,6,"mouseup",targetThread);return 0}function __fillPointerlockChangeEventData(eventStruct){var pointerLockElement=document.pointerLockElement||document.mozPointerLockElement||document.webkitPointerLockElement||document.msPointerLockElement;var isPointerlocked=!!pointerLockElement;HEAP32[eventStruct>>2]=isPointerlocked;var nodeName=JSEvents.getNodeNameForTarget(pointerLockElement);var id=pointerLockElement&&pointerLockElement.id?pointerLockElement.id:"";stringToUTF8(nodeName,eventStruct+4,128);stringToUTF8(id,eventStruct+132,128)}function __registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.pointerlockChangeEvent)JSEvents.pointerlockChangeEvent=_malloc(260);var pointerlockChangeEventHandlerFunc=function(ev){var e=ev||event;var pointerlockChangeEvent=JSEvents.pointerlockChangeEvent;__fillPointerlockChangeEventData(pointerlockChangeEvent);if(wasmTable.get(callbackfunc)(eventTypeId,pointerlockChangeEvent,userData))e.preventDefault()};var eventHandler={target:target,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:pointerlockChangeEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_pointerlockchange_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){if(!document||!document.body||!document.body.requestPointerLock&&!document.body.mozRequestPointerLock&&!document.body.webkitRequestPointerLock&&!document.body.msRequestPointerLock){return-1}target=findEventTarget(target);if(!target)return-4;__registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"pointerlockchange",targetThread);__registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"mozpointerlockchange",targetThread);__registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"webkitpointerlockchange",targetThread);__registerPointerlockChangeEventCallback(target,userData,useCapture,callbackfunc,20,"mspointerlockchange",targetThread);return 0}function __registerUiEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.uiEvent)JSEvents.uiEvent=_malloc(36);target=findEventTarget(target);var uiEventHandlerFunc=function(ev){var e=ev||event;if(e.target!=target){return}var uiEvent=JSEvents.uiEvent;var b=document.body;HEAP32[uiEvent>>2]=e.detail;HEAP32[uiEvent+4>>2]=b.clientWidth;HEAP32[uiEvent+8>>2]=b.clientHeight;HEAP32[uiEvent+12>>2]=innerWidth;HEAP32[uiEvent+16>>2]=innerHeight;HEAP32[uiEvent+20>>2]=outerWidth;HEAP32[uiEvent+24>>2]=outerHeight;HEAP32[uiEvent+28>>2]=pageXOffset;HEAP32[uiEvent+32>>2]=pageYOffset;if(wasmTable.get(callbackfunc)(eventTypeId,uiEvent,userData))e.preventDefault()};var eventHandler={target:target,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:uiEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_resize_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerUiEventCallback(target,userData,useCapture,callbackfunc,10,"resize",targetThread);return 0}function __registerTouchEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.touchEvent)JSEvents.touchEvent=_malloc(1684);target=findEventTarget(target);var touchEventHandlerFunc=function(e){var touches={};var et=e.touches;for(var i=0;i>2;HEAP32[idx+1]=e.ctrlKey;HEAP32[idx+2]=e.shiftKey;HEAP32[idx+3]=e.altKey;HEAP32[idx+4]=e.metaKey;idx+=5;var targetRect=__getBoundingClientRect(target);var numTouches=0;for(var i in touches){var t=touches[i];HEAP32[idx+0]=t.identifier;HEAP32[idx+1]=t.screenX;HEAP32[idx+2]=t.screenY;HEAP32[idx+3]=t.clientX;HEAP32[idx+4]=t.clientY;HEAP32[idx+5]=t.pageX;HEAP32[idx+6]=t.pageY;HEAP32[idx+7]=t.isChanged;HEAP32[idx+8]=t.onTarget;HEAP32[idx+9]=t.clientX-targetRect.left;HEAP32[idx+10]=t.clientY-targetRect.top;idx+=13;if(++numTouches>31){break}}HEAP32[touchEvent>>2]=numTouches;if(wasmTable.get(callbackfunc)(eventTypeId,touchEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:eventTypeString=="touchstart"||eventTypeString=="touchend",eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:touchEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_touchcancel_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerTouchEventCallback(target,userData,useCapture,callbackfunc,25,"touchcancel",targetThread);return 0}function _emscripten_set_touchend_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerTouchEventCallback(target,userData,useCapture,callbackfunc,23,"touchend",targetThread);return 0}function _emscripten_set_touchmove_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerTouchEventCallback(target,userData,useCapture,callbackfunc,24,"touchmove",targetThread);return 0}function _emscripten_set_touchstart_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){__registerTouchEventCallback(target,userData,useCapture,callbackfunc,22,"touchstart",targetThread);return 0}function __fillVisibilityChangeEventData(eventStruct){var visibilityStates=["hidden","visible","prerender","unloaded"];var visibilityState=visibilityStates.indexOf(document.visibilityState);HEAP32[eventStruct>>2]=document.hidden;HEAP32[eventStruct+4>>2]=visibilityState}function __registerVisibilityChangeEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.visibilityChangeEvent)JSEvents.visibilityChangeEvent=_malloc(8);var visibilityChangeEventHandlerFunc=function(ev){var e=ev||event;var visibilityChangeEvent=JSEvents.visibilityChangeEvent;__fillVisibilityChangeEventData(visibilityChangeEvent);if(wasmTable.get(callbackfunc)(eventTypeId,visibilityChangeEvent,userData))e.preventDefault()};var eventHandler={target:target,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:visibilityChangeEventHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_visibilitychange_callback_on_thread(userData,useCapture,callbackfunc,targetThread){if(!specialHTMLTargets[1]){return-4}__registerVisibilityChangeEventCallback(specialHTMLTargets[1],userData,useCapture,callbackfunc,21,"visibilitychange",targetThread);return 0}function __registerWheelEventCallback(target,userData,useCapture,callbackfunc,eventTypeId,eventTypeString,targetThread){if(!JSEvents.wheelEvent)JSEvents.wheelEvent=_malloc(96);var wheelHandlerFunc=function(ev){var e=ev||event;var wheelEvent=JSEvents.wheelEvent;__fillMouseEventData(wheelEvent,e,target);HEAPF64[wheelEvent+64>>3]=e["deltaX"];HEAPF64[wheelEvent+72>>3]=e["deltaY"];HEAPF64[wheelEvent+80>>3]=e["deltaZ"];HEAP32[wheelEvent+88>>2]=e["deltaMode"];if(wasmTable.get(callbackfunc)(eventTypeId,wheelEvent,userData))e.preventDefault()};var eventHandler={target:target,allowsDeferredCalls:true,eventTypeString:eventTypeString,callbackfunc:callbackfunc,handlerFunc:wheelHandlerFunc,useCapture:useCapture};JSEvents.registerOrRemoveHandler(eventHandler)}function _emscripten_set_wheel_callback_on_thread(target,userData,useCapture,callbackfunc,targetThread){target=findEventTarget(target);if(typeof target.onwheel!=="undefined"){__registerWheelEventCallback(target,userData,useCapture,callbackfunc,9,"wheel",targetThread);return 0}else{return-1}}function _emscripten_sleep(){throw"Please compile your program with async support in order to use asynchronous operations like emscripten_sleep"}var ENV={};function getExecutableName(){return thisProgram||"./this.program"}function getEnvStrings(){if(!getEnvStrings.strings){var lang=(typeof navigator==="object"&&navigator.languages&&navigator.languages[0]||"C").replace("-","_")+".UTF-8";var env={"USER":"web_user","LOGNAME":"web_user","PATH":"/","PWD":"/","HOME":"/home/web_user","LANG":lang,"_":getExecutableName()};for(var x in ENV){env[x]=ENV[x]}var strings=[];for(var x in env){strings.push(x+"="+env[x])}getEnvStrings.strings=strings}return getEnvStrings.strings}function _environ_get(__environ,environ_buf){var bufSize=0;getEnvStrings().forEach(function(string,i){var ptr=environ_buf+bufSize;HEAP32[__environ+i*4>>2]=ptr;writeAsciiToMemory(string,ptr);bufSize+=string.length+1});return 0}function _environ_sizes_get(penviron_count,penviron_buf_size){var strings=getEnvStrings();HEAP32[penviron_count>>2]=strings.length;var bufSize=0;strings.forEach(function(string){bufSize+=string.length+1});HEAP32[penviron_buf_size>>2]=bufSize;return 0}function _exit(status){exit(status)}function _fd_close(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);FS.close(stream);return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_fdstat_get(fd,pbuf){try{var stream=SYSCALLS.getStreamFromFD(fd);var type=stream.tty?2:FS.isDir(stream.mode)?3:FS.isLink(stream.mode)?7:4;HEAP8[pbuf>>0]=type;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_read(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=SYSCALLS.doReadv(stream,iov,iovcnt);HEAP32[pnum>>2]=num;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){try{var stream=SYSCALLS.getStreamFromFD(fd);var HIGH_OFFSET=4294967296;var offset=offset_high*HIGH_OFFSET+(offset_low>>>0);var DOUBLE_LIMIT=9007199254740992;if(offset<=-DOUBLE_LIMIT||offset>=DOUBLE_LIMIT){return-61}FS.llseek(stream,offset,whence);tempI64=[stream.position>>>0,(tempDouble=stream.position,+Math_abs(tempDouble)>=1?tempDouble>0?(Math_min(+Math_floor(tempDouble/4294967296),4294967295)|0)>>>0:~~+Math_ceil((tempDouble-+(~~tempDouble>>>0))/4294967296)>>>0:0)],HEAP32[newOffset>>2]=tempI64[0],HEAP32[newOffset+4>>2]=tempI64[1];if(stream.getdents&&offset===0&&whence===0)stream.getdents=null;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_sync(fd){try{var stream=SYSCALLS.getStreamFromFD(fd);if(stream.stream_ops&&stream.stream_ops.fsync){return-stream.stream_ops.fsync(stream)}return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}function _fd_write(fd,iov,iovcnt,pnum){try{var stream=SYSCALLS.getStreamFromFD(fd);var num=SYSCALLS.doWritev(stream,iov,iovcnt);HEAP32[pnum>>2]=num;return 0}catch(e){if(typeof FS==="undefined"||!(e instanceof FS.ErrnoError))abort(e);return e.errno}}var GAI_ERRNO_MESSAGES={};function _gai_strerror(val){var buflen=256;if(!_gai_strerror.buffer){_gai_strerror.buffer=_malloc(buflen);GAI_ERRNO_MESSAGES["0"]="Success";GAI_ERRNO_MESSAGES[""+-1]="Invalid value for 'ai_flags' field";GAI_ERRNO_MESSAGES[""+-2]="NAME or SERVICE is unknown";GAI_ERRNO_MESSAGES[""+-3]="Temporary failure in name resolution";GAI_ERRNO_MESSAGES[""+-4]="Non-recoverable failure in name res";GAI_ERRNO_MESSAGES[""+-6]="'ai_family' not supported";GAI_ERRNO_MESSAGES[""+-7]="'ai_socktype' not supported";GAI_ERRNO_MESSAGES[""+-8]="SERVICE not supported for 'ai_socktype'";GAI_ERRNO_MESSAGES[""+-10]="Memory allocation failure";GAI_ERRNO_MESSAGES[""+-11]="System error returned in 'errno'";GAI_ERRNO_MESSAGES[""+-12]="Argument buffer overflow"}var msg="Unknown error";if(val in GAI_ERRNO_MESSAGES){if(GAI_ERRNO_MESSAGES[val].length>buflen-1){msg="Message too long"}else{msg=GAI_ERRNO_MESSAGES[val]}}writeAsciiToMemory(msg,_gai_strerror.buffer);return _gai_strerror.buffer}function _getTempRet0(){return getTempRet0()|0}function _getaddrinfo(node,service,hint,out){var addr=0;var port=0;var flags=0;var family=0;var type=0;var proto=0;var ai;function allocaddrinfo(family,type,proto,canon,addr,port){var sa,salen,ai;var res;salen=family===10?28:16;addr=family===10?__inet_ntop6_raw(addr):__inet_ntop4_raw(addr);sa=_malloc(salen);res=__write_sockaddr(sa,family,addr,port);assert(!res.errno);ai=_malloc(32);HEAP32[ai+4>>2]=family;HEAP32[ai+8>>2]=type;HEAP32[ai+12>>2]=proto;HEAP32[ai+24>>2]=canon;HEAP32[ai+20>>2]=sa;if(family===10){HEAP32[ai+16>>2]=28}else{HEAP32[ai+16>>2]=16}HEAP32[ai+28>>2]=0;return ai}if(hint){flags=HEAP32[hint>>2];family=HEAP32[hint+4>>2];type=HEAP32[hint+8>>2];proto=HEAP32[hint+12>>2]}if(type&&!proto){proto=type===2?17:6}if(!type&&proto){type=proto===17?2:1}if(proto===0){proto=6}if(type===0){type=1}if(!node&&!service){return-2}if(flags&~(1|2|4|1024|8|16|32)){return-1}if(hint!==0&&HEAP32[hint>>2]&2&&!node){return-1}if(flags&32){return-2}if(type!==0&&type!==1&&type!==2){return-7}if(family!==0&&family!==2&&family!==10){return-6}if(service){service=UTF8ToString(service);port=parseInt(service,10);if(isNaN(port)){if(flags&1024){return-2}return-8}}if(!node){if(family===0){family=2}if((flags&1)===0){if(family===2){addr=_htonl(2130706433)}else{addr=[0,0,0,1]}}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAP32[out>>2]=ai;return 0}node=UTF8ToString(node);addr=__inet_pton4_raw(node);if(addr!==null){if(family===0||family===2){family=2}else if(family===10&&flags&8){addr=[0,0,_htonl(65535),addr];family=10}else{return-2}}else{addr=__inet_pton6_raw(node);if(addr!==null){if(family===0||family===10){family=10}else{return-2}}}if(addr!=null){ai=allocaddrinfo(family,type,proto,node,addr,port);HEAP32[out>>2]=ai;return 0}if(flags&4){return-2}node=DNS.lookup_name(node);addr=__inet_pton4_raw(node);if(family===0){family=2}else if(family===10){addr=[0,0,_htonl(65535),addr]}ai=allocaddrinfo(family,type,proto,null,addr,port);HEAP32[out>>2]=ai;return 0}function _gethostbyname(name){name=UTF8ToString(name);var ret=_malloc(20);var nameBuf=_malloc(name.length+1);stringToUTF8(name,nameBuf,name.length+1);HEAP32[ret>>2]=nameBuf;var aliasesBuf=_malloc(4);HEAP32[aliasesBuf>>2]=0;HEAP32[ret+4>>2]=aliasesBuf;var afinet=2;HEAP32[ret+8>>2]=afinet;HEAP32[ret+12>>2]=4;var addrListBuf=_malloc(12);HEAP32[addrListBuf>>2]=addrListBuf+8;HEAP32[addrListBuf+4>>2]=0;HEAP32[addrListBuf+8>>2]=__inet_pton4_raw(DNS.lookup_name(name));HEAP32[ret+16>>2]=addrListBuf;return ret}function _gethostbyaddr(addr,addrlen,type){if(type!==2){setErrNo(5);return null}addr=HEAP32[addr>>2];var host=__inet_ntop4_raw(addr);var lookup=DNS.lookup_addr(host);if(lookup){host=lookup}var hostp=allocate(intArrayFromString(host),"i8",ALLOC_STACK);return _gethostbyname(hostp)}function _getnameinfo(sa,salen,node,nodelen,serv,servlen,flags){var info=__read_sockaddr(sa,salen);if(info.errno){return-6}var port=info.port;var addr=info.addr;var overflowed=false;if(node&&nodelen){var lookup;if(flags&1||!(lookup=DNS.lookup_addr(addr))){if(flags&8){return-2}}else{addr=lookup}var numBytesWrittenExclNull=stringToUTF8(addr,node,nodelen);if(numBytesWrittenExclNull+1>=nodelen){overflowed=true}}if(serv&&servlen){port=""+port;var numBytesWrittenExclNull=stringToUTF8(port,serv,servlen);if(numBytesWrittenExclNull+1>=servlen){overflowed=true}}if(overflowed){return-12}return 0}function _getpwuid(){throw"getpwuid: TODO"}function _gettimeofday(ptr){var now=Date.now();HEAP32[ptr>>2]=now/1e3|0;HEAP32[ptr+4>>2]=now%1e3*1e3|0;return 0}function _mktime(tmPtr){_tzset();var date=new Date(HEAP32[tmPtr+20>>2]+1900,HEAP32[tmPtr+16>>2],HEAP32[tmPtr+12>>2],HEAP32[tmPtr+8>>2],HEAP32[tmPtr+4>>2],HEAP32[tmPtr>>2],0);var dst=HEAP32[tmPtr+32>>2];var guessedOffset=date.getTimezoneOffset();var start=new Date(date.getFullYear(),0,1);var summerOffset=new Date(date.getFullYear(),6,1).getTimezoneOffset();var winterOffset=start.getTimezoneOffset();var dstOffset=Math.min(winterOffset,summerOffset);if(dst<0){HEAP32[tmPtr+32>>2]=Number(summerOffset!=winterOffset&&dstOffset==guessedOffset)}else if(dst>0!=(dstOffset==guessedOffset)){var nonDstOffset=Math.max(winterOffset,summerOffset);var trueOffset=dst>0?dstOffset:nonDstOffset;date.setTime(date.getTime()+(trueOffset-guessedOffset)*6e4)}HEAP32[tmPtr+24>>2]=date.getDay();var yday=(date.getTime()-start.getTime())/(1e3*60*60*24)|0;HEAP32[tmPtr+28>>2]=yday;return date.getTime()/1e3|0}function _usleep(useconds){var start=_emscripten_get_now();while(_emscripten_get_now()-start>2];var nanoseconds=HEAP32[rqtp+4>>2];if(nanoseconds<0||nanoseconds>999999999||seconds<0){setErrNo(28);return-1}if(rmtp!==0){HEAP32[rmtp>>2]=0;HEAP32[rmtp+4>>2]=0}return _usleep(seconds*1e6+nanoseconds/1e3)}function _pthread_mutexattr_init(){}function _pthread_mutexattr_settype(){}function _setTempRet0($i){setTempRet0($i|0)}function _sigaction(signum,act,oldact){return 0}var __sigalrm_handler=0;function _signal(sig,func){if(sig==14){__sigalrm_handler=func}else{}return 0}function __isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0)}function __arraySum(array,index){var sum=0;for(var i=0;i<=index;sum+=array[i++]){}return sum}var __MONTH_DAYS_LEAP=[31,29,31,30,31,30,31,31,30,31,30,31];var __MONTH_DAYS_REGULAR=[31,28,31,30,31,30,31,31,30,31,30,31];function __addDays(date,days){var newDate=new Date(date.getTime());while(days>0){var leap=__isLeapYear(newDate.getFullYear());var currentMonth=newDate.getMonth();var daysInCurrentMonth=(leap?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR)[currentMonth];if(days>daysInCurrentMonth-newDate.getDate()){days-=daysInCurrentMonth-newDate.getDate()+1;newDate.setDate(1);if(currentMonth<11){newDate.setMonth(currentMonth+1)}else{newDate.setMonth(0);newDate.setFullYear(newDate.getFullYear()+1)}}else{newDate.setDate(newDate.getDate()+days);return newDate}}return newDate}function _strftime(s,maxsize,format,tm){var tm_zone=HEAP32[tm+40>>2];var date={tm_sec:HEAP32[tm>>2],tm_min:HEAP32[tm+4>>2],tm_hour:HEAP32[tm+8>>2],tm_mday:HEAP32[tm+12>>2],tm_mon:HEAP32[tm+16>>2],tm_year:HEAP32[tm+20>>2],tm_wday:HEAP32[tm+24>>2],tm_yday:HEAP32[tm+28>>2],tm_isdst:HEAP32[tm+32>>2],tm_gmtoff:HEAP32[tm+36>>2],tm_zone:tm_zone?UTF8ToString(tm_zone):""};var pattern=UTF8ToString(format);var EXPANSION_RULES_1={"%c":"%a %b %d %H:%M:%S %Y","%D":"%m/%d/%y","%F":"%Y-%m-%d","%h":"%b","%r":"%I:%M:%S %p","%R":"%H:%M","%T":"%H:%M:%S","%x":"%m/%d/%y","%X":"%H:%M:%S","%Ec":"%c","%EC":"%C","%Ex":"%m/%d/%y","%EX":"%H:%M:%S","%Ey":"%y","%EY":"%Y","%Od":"%d","%Oe":"%e","%OH":"%H","%OI":"%I","%Om":"%m","%OM":"%M","%OS":"%S","%Ou":"%u","%OU":"%U","%OV":"%V","%Ow":"%w","%OW":"%W","%Oy":"%y"};for(var rule in EXPANSION_RULES_1){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_1[rule])}var WEEKDAYS=["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"];var MONTHS=["January","February","March","April","May","June","July","August","September","October","November","December"];function leadingSomething(value,digits,character){var str=typeof value==="number"?value.toString():value||"";while(str.length0?1:0}var compare;if((compare=sgn(date1.getFullYear()-date2.getFullYear()))===0){if((compare=sgn(date1.getMonth()-date2.getMonth()))===0){compare=sgn(date1.getDate()-date2.getDate())}}return compare}function getFirstWeekStartDate(janFourth){switch(janFourth.getDay()){case 0:return new Date(janFourth.getFullYear()-1,11,29);case 1:return janFourth;case 2:return new Date(janFourth.getFullYear(),0,3);case 3:return new Date(janFourth.getFullYear(),0,2);case 4:return new Date(janFourth.getFullYear(),0,1);case 5:return new Date(janFourth.getFullYear()-1,11,31);case 6:return new Date(janFourth.getFullYear()-1,11,30)}}function getWeekBasedYear(date){var thisDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);var janFourthThisYear=new Date(thisDate.getFullYear(),0,4);var janFourthNextYear=new Date(thisDate.getFullYear()+1,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);if(compareByDay(firstWeekStartThisYear,thisDate)<=0){if(compareByDay(firstWeekStartNextYear,thisDate)<=0){return thisDate.getFullYear()+1}else{return thisDate.getFullYear()}}else{return thisDate.getFullYear()-1}}var EXPANSION_RULES_2={"%a":function(date){return WEEKDAYS[date.tm_wday].substring(0,3)},"%A":function(date){return WEEKDAYS[date.tm_wday]},"%b":function(date){return MONTHS[date.tm_mon].substring(0,3)},"%B":function(date){return MONTHS[date.tm_mon]},"%C":function(date){var year=date.tm_year+1900;return leadingNulls(year/100|0,2)},"%d":function(date){return leadingNulls(date.tm_mday,2)},"%e":function(date){return leadingSomething(date.tm_mday,2," ")},"%g":function(date){return getWeekBasedYear(date).toString().substring(2)},"%G":function(date){return getWeekBasedYear(date)},"%H":function(date){return leadingNulls(date.tm_hour,2)},"%I":function(date){var twelveHour=date.tm_hour;if(twelveHour==0)twelveHour=12;else if(twelveHour>12)twelveHour-=12;return leadingNulls(twelveHour,2)},"%j":function(date){return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900)?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,date.tm_mon-1),3)},"%m":function(date){return leadingNulls(date.tm_mon+1,2)},"%M":function(date){return leadingNulls(date.tm_min,2)},"%n":function(){return"\n"},"%p":function(date){if(date.tm_hour>=0&&date.tm_hour<12){return"AM"}else{return"PM"}},"%S":function(date){return leadingNulls(date.tm_sec,2)},"%t":function(){return"\t"},"%u":function(date){return date.tm_wday||7},"%U":function(date){var janFirst=new Date(date.tm_year+1900,0,1);var firstSunday=janFirst.getDay()===0?janFirst:__addDays(janFirst,7-janFirst.getDay());var endDate=new Date(date.tm_year+1900,date.tm_mon,date.tm_mday);if(compareByDay(firstSunday,endDate)<0){var februaryFirstUntilEndMonth=__arraySum(__isLeapYear(endDate.getFullYear())?__MONTH_DAYS_LEAP:__MONTH_DAYS_REGULAR,endDate.getMonth()-1)-31;var firstSundayUntilEndJanuary=31-firstSunday.getDate();var days=firstSundayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();return leadingNulls(Math.ceil(days/7),2)}return compareByDay(firstSunday,janFirst)===0?"01":"00"},"%V":function(date){var janFourthThisYear=new Date(date.tm_year+1900,0,4);var janFourthNextYear=new Date(date.tm_year+1901,0,4);var firstWeekStartThisYear=getFirstWeekStartDate(janFourthThisYear);var firstWeekStartNextYear=getFirstWeekStartDate(janFourthNextYear);var endDate=__addDays(new Date(date.tm_year+1900,0,1),date.tm_yday);if(compareByDay(endDate,firstWeekStartThisYear)<0){return"53"}if(compareByDay(firstWeekStartNextYear,endDate)<=0){return"01"}var daysDifference;if(firstWeekStartThisYear.getFullYear()=0;off=Math.abs(off)/60;off=off/60*100+off%60;return(ahead?"+":"-")+String("0000"+off).slice(-4)},"%Z":function(date){return date.tm_zone},"%%":function(){return"%"}};for(var rule in EXPANSION_RULES_2){if(pattern.indexOf(rule)>=0){pattern=pattern.replace(new RegExp(rule,"g"),EXPANSION_RULES_2[rule](date))}}var bytes=intArrayFromString(pattern,false);if(bytes.length>maxsize){return 0}writeArrayToMemory(bytes,s);return bytes.length-1}function _strftime_l(s,maxsize,format,tm){return _strftime(s,maxsize,format,tm)}function _sysconf(name){switch(name){case 30:return 16384;case 85:var maxHeapSize=2147483648;return maxHeapSize/16384;case 132:case 133:case 12:case 137:case 138:case 15:case 235:case 16:case 17:case 18:case 19:case 20:case 149:case 13:case 10:case 236:case 153:case 9:case 21:case 22:case 159:case 154:case 14:case 77:case 78:case 139:case 80:case 81:case 82:case 68:case 67:case 164:case 11:case 29:case 47:case 48:case 95:case 52:case 51:case 46:case 79:return 200809;case 27:case 246:case 127:case 128:case 23:case 24:case 160:case 161:case 181:case 182:case 242:case 183:case 184:case 243:case 244:case 245:case 165:case 178:case 179:case 49:case 50:case 168:case 169:case 175:case 170:case 171:case 172:case 97:case 76:case 32:case 173:case 35:return-1;case 176:case 177:case 7:case 155:case 8:case 157:case 125:case 126:case 92:case 93:case 129:case 130:case 131:case 94:case 91:return 1;case 74:case 60:case 69:case 70:case 4:return 1024;case 31:case 42:case 72:return 32;case 87:case 26:case 33:return 2147483647;case 34:case 1:return 47839;case 38:case 36:return 99;case 43:case 37:return 2048;case 0:return 2097152;case 3:return 65536;case 28:return 32768;case 44:return 32767;case 75:return 16384;case 39:return 1e3;case 89:return 700;case 71:return 256;case 40:return 255;case 2:return 100;case 180:return 64;case 25:return 20;case 5:return 16;case 6:return 6;case 73:return 4;case 84:{if(typeof navigator==="object")return navigator["hardwareConcurrency"]||1;return 1}}setErrNo(28);return-1}function _system(command){if(ENVIRONMENT_IS_NODE){if(!command)return 1;var cmdstr=UTF8ToString(command);if(!cmdstr.length)return 0;var cp=require("child_process");var ret=cp.spawnSync(cmdstr,[],{shell:true,stdio:"inherit"});var _W_EXITCODE=function(ret,sig){return ret<<8|sig};if(ret.status===null){var signalToNumber=function(sig){switch(sig){case"SIGHUP":return 1;case"SIGINT":return 2;case"SIGQUIT":return 3;case"SIGFPE":return 8;case"SIGKILL":return 9;case"SIGALRM":return 14;case"SIGTERM":return 15}return 2};return _W_EXITCODE(0,signalToNumber(ret.signal))}return _W_EXITCODE(ret.status,0)}if(!command)return 0;setErrNo(6);return-1}function _time(ptr){var ret=Date.now()/1e3|0;if(ptr){HEAP32[ptr>>2]=ret}return ret}var readAsmConstArgsArray=[];function readAsmConstArgs(sigPtr,buf){readAsmConstArgsArray.length=0;var ch;buf>>=2;while(ch=HEAPU8[sigPtr++]){var double=ch<105;if(double&&buf&1)buf++;readAsmConstArgsArray.push(double?HEAPF64[buf++>>1]:HEAP32[buf]);++buf}return readAsmConstArgsArray}var FSNode=function(parent,name,mode,rdev){if(!parent){parent=this}this.parent=parent;this.mount=parent.mount;this.mounted=null;this.id=FS.nextInode++;this.name=name;this.mode=mode;this.node_ops={};this.stream_ops={};this.rdev=rdev};var readMode=292|73;var writeMode=146;Object.defineProperties(FSNode.prototype,{read:{get:function(){return(this.mode&readMode)===readMode},set:function(val){val?this.mode|=readMode:this.mode&=~readMode}},write:{get:function(){return(this.mode&writeMode)===writeMode},set:function(val){val?this.mode|=writeMode:this.mode&=~writeMode}},isFolder:{get:function(){return FS.isDir(this.mode)}},isDevice:{get:function(){return FS.isChrdev(this.mode)}}});FS.FSNode=FSNode;FS.staticInit();Module["FS_createFolder"]=FS.createFolder;Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createLink"]=FS.createLink;Module["FS_createDevice"]=FS.createDevice;Module["FS_unlink"]=FS.unlink;Module["requestFullscreen"]=function Module_requestFullscreen(lockPointer,resizeCanvas){Browser.requestFullscreen(lockPointer,resizeCanvas)};Module["requestAnimationFrame"]=function Module_requestAnimationFrame(func){Browser.requestAnimationFrame(func)};Module["setCanvasSize"]=function Module_setCanvasSize(width,height,noUpdates){Browser.setCanvasSize(width,height,noUpdates)};Module["pauseMainLoop"]=function Module_pauseMainLoop(){Browser.mainLoop.pause()};Module["resumeMainLoop"]=function Module_resumeMainLoop(){Browser.mainLoop.resume()};Module["getUserMedia"]=function Module_getUserMedia(){Browser.getUserMedia()};Module["createContext"]=function Module_createContext(canvas,useWebGL,setInModule,webGLContextAttributes){return Browser.createContext(canvas,useWebGL,setInModule,webGLContextAttributes)};var GLctx;for(var i=0;i<32;++i)tempFixedLengthArray.push(new Array(i));var miniTempWebGLFloatBuffersStorage=new Float32Array(288);for(var i=0;i<288;++i){miniTempWebGLFloatBuffers[i]=miniTempWebGLFloatBuffersStorage.subarray(0,i+1)}var __miniTempWebGLIntBuffersStorage=new Int32Array(288);for(var i=0;i<288;++i){__miniTempWebGLIntBuffers[i]=__miniTempWebGLIntBuffersStorage.subarray(0,i+1)}var ASSERTIONS=false;function intArrayFromString(stringy,dontAddNull,length){var len=length>0?length:lengthBytesUTF8(stringy)+1;var u8array=new Array(len);var numBytesWritten=stringToUTF8Array(stringy,u8array,0,u8array.length);if(dontAddNull)u8array.length=numBytesWritten;return u8array}var asmLibraryArg={"__clock_gettime":___clock_gettime,"__cxa_allocate_exception":___cxa_allocate_exception,"__cxa_atexit":___cxa_atexit,"__cxa_begin_catch":___cxa_begin_catch,"__cxa_end_catch":___cxa_end_catch,"__cxa_find_matching_catch_2":___cxa_find_matching_catch_2,"__cxa_find_matching_catch_3":___cxa_find_matching_catch_3,"__cxa_free_exception":___cxa_free_exception,"__cxa_rethrow":___cxa_rethrow,"__cxa_throw":___cxa_throw,"__cxa_uncaught_exceptions":___cxa_uncaught_exceptions,"__gmtime_r":___gmtime_r,"__localtime_r":___localtime_r,"__map_file":___map_file,"__resumeException":___resumeException,"__sys__newselect":___sys__newselect,"__sys_access":___sys_access,"__sys_dup2":___sys_dup2,"__sys_dup3":___sys_dup3,"__sys_fcntl64":___sys_fcntl64,"__sys_fstat64":___sys_fstat64,"__sys_getcwd":___sys_getcwd,"__sys_getdents64":___sys_getdents64,"__sys_getpid":___sys_getpid,"__sys_getuid32":___sys_getuid32,"__sys_ioctl":___sys_ioctl,"__sys_lstat64":___sys_lstat64,"__sys_mkdir":___sys_mkdir,"__sys_munmap":___sys_munmap,"__sys_open":___sys_open,"__sys_poll":___sys_poll,"__sys_read":___sys_read,"__sys_readlink":___sys_readlink,"__sys_rename":___sys_rename,"__sys_rmdir":___sys_rmdir,"__sys_socketcall":___sys_socketcall,"__sys_stat64":___sys_stat64,"__sys_uname":___sys_uname,"__sys_unlink":___sys_unlink,"abort":_abort,"alBufferData":_alBufferData,"alDeleteBuffers":_alDeleteBuffers,"alDeleteSources":_alDeleteSources,"alDistanceModel":_alDistanceModel,"alDopplerFactor":_alDopplerFactor,"alGenBuffers":_alGenBuffers,"alGenSources":_alGenSources,"alGetBufferi":_alGetBufferi,"alGetError":_alGetError,"alGetFloat":_alGetFloat,"alGetListenerf":_alGetListenerf,"alGetListenerfv":_alGetListenerfv,"alGetSourcef":_alGetSourcef,"alGetSourcefv":_alGetSourcefv,"alGetSourcei":_alGetSourcei,"alListenerf":_alListenerf,"alListenerfv":_alListenerfv,"alSourcePause":_alSourcePause,"alSourcePausev":_alSourcePausev,"alSourcePlay":_alSourcePlay,"alSourcePlayv":_alSourcePlayv,"alSourceQueueBuffers":_alSourceQueueBuffers,"alSourceStop":_alSourceStop,"alSourceStopv":_alSourceStopv,"alSourceUnqueueBuffers":_alSourceUnqueueBuffers,"alSourcef":_alSourcef,"alSourcefv":_alSourcefv,"alSourcei":_alSourcei,"alcCaptureCloseDevice":_alcCaptureCloseDevice,"alcCaptureOpenDevice":_alcCaptureOpenDevice,"alcCaptureSamples":_alcCaptureSamples,"alcCaptureStart":_alcCaptureStart,"alcCaptureStop":_alcCaptureStop,"alcCloseDevice":_alcCloseDevice,"alcCreateContext":_alcCreateContext,"alcDestroyContext":_alcDestroyContext,"alcGetCurrentContext":_alcGetCurrentContext,"alcGetError":_alcGetError,"alcGetIntegerv":_alcGetIntegerv,"alcGetString":_alcGetString,"alcMakeContextCurrent":_alcMakeContextCurrent,"alcOpenDevice":_alcOpenDevice,"atexit":_atexit,"clock":_clock,"clock_gettime":_clock_gettime,"difftime":_difftime,"dlclose":_dlclose,"dlerror":_dlerror,"dlopen":_dlopen,"dlsym":_dlsym,"eglBindAPI":_eglBindAPI,"eglChooseConfig":_eglChooseConfig,"eglCreateContext":_eglCreateContext,"eglCreateWindowSurface":_eglCreateWindowSurface,"eglDestroyContext":_eglDestroyContext,"eglDestroySurface":_eglDestroySurface,"eglGetConfigAttrib":_eglGetConfigAttrib,"eglGetDisplay":_eglGetDisplay,"eglGetError":_eglGetError,"eglGetProcAddress":_eglGetProcAddress,"eglInitialize":_eglInitialize,"eglMakeCurrent":_eglMakeCurrent,"eglQueryString":_eglQueryString,"eglSwapBuffers":_eglSwapBuffers,"eglSwapInterval":_eglSwapInterval,"eglTerminate":_eglTerminate,"eglWaitGL":_eglWaitGL,"eglWaitNative":_eglWaitNative,"emscripten_asm_const_int":_emscripten_asm_const_int,"emscripten_cancel_main_loop":_emscripten_cancel_main_loop,"emscripten_exit_fullscreen":_emscripten_exit_fullscreen,"emscripten_exit_pointerlock":_emscripten_exit_pointerlock,"emscripten_get_battery_status":_emscripten_get_battery_status,"emscripten_get_device_pixel_ratio":_emscripten_get_device_pixel_ratio,"emscripten_get_element_css_size":_emscripten_get_element_css_size,"emscripten_get_gamepad_status":_emscripten_get_gamepad_status,"emscripten_get_now":_emscripten_get_now,"emscripten_get_num_gamepads":_emscripten_get_num_gamepads,"emscripten_get_sbrk_ptr":_emscripten_get_sbrk_ptr,"emscripten_glActiveTexture":_emscripten_glActiveTexture,"emscripten_glAttachShader":_emscripten_glAttachShader,"emscripten_glBeginQueryEXT":_emscripten_glBeginQueryEXT,"emscripten_glBindAttribLocation":_emscripten_glBindAttribLocation,"emscripten_glBindBuffer":_emscripten_glBindBuffer,"emscripten_glBindFramebuffer":_emscripten_glBindFramebuffer,"emscripten_glBindRenderbuffer":_emscripten_glBindRenderbuffer,"emscripten_glBindTexture":_emscripten_glBindTexture,"emscripten_glBindVertexArrayOES":_emscripten_glBindVertexArrayOES,"emscripten_glBlendColor":_emscripten_glBlendColor,"emscripten_glBlendEquation":_emscripten_glBlendEquation,"emscripten_glBlendEquationSeparate":_emscripten_glBlendEquationSeparate,"emscripten_glBlendFunc":_emscripten_glBlendFunc,"emscripten_glBlendFuncSeparate":_emscripten_glBlendFuncSeparate,"emscripten_glBufferData":_emscripten_glBufferData,"emscripten_glBufferSubData":_emscripten_glBufferSubData,"emscripten_glCheckFramebufferStatus":_emscripten_glCheckFramebufferStatus,"emscripten_glClear":_emscripten_glClear,"emscripten_glClearColor":_emscripten_glClearColor,"emscripten_glClearDepthf":_emscripten_glClearDepthf,"emscripten_glClearStencil":_emscripten_glClearStencil,"emscripten_glColorMask":_emscripten_glColorMask,"emscripten_glCompileShader":_emscripten_glCompileShader,"emscripten_glCompressedTexImage2D":_emscripten_glCompressedTexImage2D,"emscripten_glCompressedTexSubImage2D":_emscripten_glCompressedTexSubImage2D,"emscripten_glCopyTexImage2D":_emscripten_glCopyTexImage2D,"emscripten_glCopyTexSubImage2D":_emscripten_glCopyTexSubImage2D,"emscripten_glCreateProgram":_emscripten_glCreateProgram,"emscripten_glCreateShader":_emscripten_glCreateShader,"emscripten_glCullFace":_emscripten_glCullFace,"emscripten_glDeleteBuffers":_emscripten_glDeleteBuffers,"emscripten_glDeleteFramebuffers":_emscripten_glDeleteFramebuffers,"emscripten_glDeleteProgram":_emscripten_glDeleteProgram,"emscripten_glDeleteQueriesEXT":_emscripten_glDeleteQueriesEXT,"emscripten_glDeleteRenderbuffers":_emscripten_glDeleteRenderbuffers,"emscripten_glDeleteShader":_emscripten_glDeleteShader,"emscripten_glDeleteTextures":_emscripten_glDeleteTextures,"emscripten_glDeleteVertexArraysOES":_emscripten_glDeleteVertexArraysOES,"emscripten_glDepthFunc":_emscripten_glDepthFunc,"emscripten_glDepthMask":_emscripten_glDepthMask,"emscripten_glDepthRangef":_emscripten_glDepthRangef,"emscripten_glDetachShader":_emscripten_glDetachShader,"emscripten_glDisable":_emscripten_glDisable,"emscripten_glDisableVertexAttribArray":_emscripten_glDisableVertexAttribArray,"emscripten_glDrawArrays":_emscripten_glDrawArrays,"emscripten_glDrawArraysInstancedANGLE":_emscripten_glDrawArraysInstancedANGLE,"emscripten_glDrawBuffersWEBGL":_emscripten_glDrawBuffersWEBGL,"emscripten_glDrawElements":_emscripten_glDrawElements,"emscripten_glDrawElementsInstancedANGLE":_emscripten_glDrawElementsInstancedANGLE,"emscripten_glEnable":_emscripten_glEnable,"emscripten_glEnableVertexAttribArray":_emscripten_glEnableVertexAttribArray,"emscripten_glEndQueryEXT":_emscripten_glEndQueryEXT,"emscripten_glFinish":_emscripten_glFinish,"emscripten_glFlush":_emscripten_glFlush,"emscripten_glFramebufferRenderbuffer":_emscripten_glFramebufferRenderbuffer,"emscripten_glFramebufferTexture2D":_emscripten_glFramebufferTexture2D,"emscripten_glFrontFace":_emscripten_glFrontFace,"emscripten_glGenBuffers":_emscripten_glGenBuffers,"emscripten_glGenFramebuffers":_emscripten_glGenFramebuffers,"emscripten_glGenQueriesEXT":_emscripten_glGenQueriesEXT,"emscripten_glGenRenderbuffers":_emscripten_glGenRenderbuffers,"emscripten_glGenTextures":_emscripten_glGenTextures,"emscripten_glGenVertexArraysOES":_emscripten_glGenVertexArraysOES,"emscripten_glGenerateMipmap":_emscripten_glGenerateMipmap,"emscripten_glGetActiveAttrib":_emscripten_glGetActiveAttrib,"emscripten_glGetActiveUniform":_emscripten_glGetActiveUniform,"emscripten_glGetAttachedShaders":_emscripten_glGetAttachedShaders,"emscripten_glGetAttribLocation":_emscripten_glGetAttribLocation,"emscripten_glGetBooleanv":_emscripten_glGetBooleanv,"emscripten_glGetBufferParameteriv":_emscripten_glGetBufferParameteriv,"emscripten_glGetError":_emscripten_glGetError,"emscripten_glGetFloatv":_emscripten_glGetFloatv,"emscripten_glGetFramebufferAttachmentParameteriv":_emscripten_glGetFramebufferAttachmentParameteriv,"emscripten_glGetIntegerv":_emscripten_glGetIntegerv,"emscripten_glGetProgramInfoLog":_emscripten_glGetProgramInfoLog,"emscripten_glGetProgramiv":_emscripten_glGetProgramiv,"emscripten_glGetQueryObjecti64vEXT":_emscripten_glGetQueryObjecti64vEXT,"emscripten_glGetQueryObjectivEXT":_emscripten_glGetQueryObjectivEXT,"emscripten_glGetQueryObjectui64vEXT":_emscripten_glGetQueryObjectui64vEXT,"emscripten_glGetQueryObjectuivEXT":_emscripten_glGetQueryObjectuivEXT,"emscripten_glGetQueryivEXT":_emscripten_glGetQueryivEXT,"emscripten_glGetRenderbufferParameteriv":_emscripten_glGetRenderbufferParameteriv,"emscripten_glGetShaderInfoLog":_emscripten_glGetShaderInfoLog,"emscripten_glGetShaderPrecisionFormat":_emscripten_glGetShaderPrecisionFormat,"emscripten_glGetShaderSource":_emscripten_glGetShaderSource,"emscripten_glGetShaderiv":_emscripten_glGetShaderiv,"emscripten_glGetString":_emscripten_glGetString,"emscripten_glGetTexParameterfv":_emscripten_glGetTexParameterfv,"emscripten_glGetTexParameteriv":_emscripten_glGetTexParameteriv,"emscripten_glGetUniformLocation":_emscripten_glGetUniformLocation,"emscripten_glGetUniformfv":_emscripten_glGetUniformfv,"emscripten_glGetUniformiv":_emscripten_glGetUniformiv,"emscripten_glGetVertexAttribPointerv":_emscripten_glGetVertexAttribPointerv,"emscripten_glGetVertexAttribfv":_emscripten_glGetVertexAttribfv,"emscripten_glGetVertexAttribiv":_emscripten_glGetVertexAttribiv,"emscripten_glHint":_emscripten_glHint,"emscripten_glIsBuffer":_emscripten_glIsBuffer,"emscripten_glIsEnabled":_emscripten_glIsEnabled,"emscripten_glIsFramebuffer":_emscripten_glIsFramebuffer,"emscripten_glIsProgram":_emscripten_glIsProgram,"emscripten_glIsQueryEXT":_emscripten_glIsQueryEXT,"emscripten_glIsRenderbuffer":_emscripten_glIsRenderbuffer,"emscripten_glIsShader":_emscripten_glIsShader,"emscripten_glIsTexture":_emscripten_glIsTexture,"emscripten_glIsVertexArrayOES":_emscripten_glIsVertexArrayOES,"emscripten_glLineWidth":_emscripten_glLineWidth,"emscripten_glLinkProgram":_emscripten_glLinkProgram,"emscripten_glPixelStorei":_emscripten_glPixelStorei,"emscripten_glPolygonOffset":_emscripten_glPolygonOffset,"emscripten_glQueryCounterEXT":_emscripten_glQueryCounterEXT,"emscripten_glReadPixels":_emscripten_glReadPixels,"emscripten_glReleaseShaderCompiler":_emscripten_glReleaseShaderCompiler,"emscripten_glRenderbufferStorage":_emscripten_glRenderbufferStorage,"emscripten_glSampleCoverage":_emscripten_glSampleCoverage,"emscripten_glScissor":_emscripten_glScissor,"emscripten_glShaderBinary":_emscripten_glShaderBinary,"emscripten_glShaderSource":_emscripten_glShaderSource,"emscripten_glStencilFunc":_emscripten_glStencilFunc,"emscripten_glStencilFuncSeparate":_emscripten_glStencilFuncSeparate,"emscripten_glStencilMask":_emscripten_glStencilMask,"emscripten_glStencilMaskSeparate":_emscripten_glStencilMaskSeparate,"emscripten_glStencilOp":_emscripten_glStencilOp,"emscripten_glStencilOpSeparate":_emscripten_glStencilOpSeparate,"emscripten_glTexImage2D":_emscripten_glTexImage2D,"emscripten_glTexParameterf":_emscripten_glTexParameterf,"emscripten_glTexParameterfv":_emscripten_glTexParameterfv,"emscripten_glTexParameteri":_emscripten_glTexParameteri,"emscripten_glTexParameteriv":_emscripten_glTexParameteriv,"emscripten_glTexSubImage2D":_emscripten_glTexSubImage2D,"emscripten_glUniform1f":_emscripten_glUniform1f,"emscripten_glUniform1fv":_emscripten_glUniform1fv,"emscripten_glUniform1i":_emscripten_glUniform1i,"emscripten_glUniform1iv":_emscripten_glUniform1iv,"emscripten_glUniform2f":_emscripten_glUniform2f,"emscripten_glUniform2fv":_emscripten_glUniform2fv,"emscripten_glUniform2i":_emscripten_glUniform2i,"emscripten_glUniform2iv":_emscripten_glUniform2iv,"emscripten_glUniform3f":_emscripten_glUniform3f,"emscripten_glUniform3fv":_emscripten_glUniform3fv,"emscripten_glUniform3i":_emscripten_glUniform3i,"emscripten_glUniform3iv":_emscripten_glUniform3iv,"emscripten_glUniform4f":_emscripten_glUniform4f,"emscripten_glUniform4fv":_emscripten_glUniform4fv,"emscripten_glUniform4i":_emscripten_glUniform4i,"emscripten_glUniform4iv":_emscripten_glUniform4iv,"emscripten_glUniformMatrix2fv":_emscripten_glUniformMatrix2fv,"emscripten_glUniformMatrix3fv":_emscripten_glUniformMatrix3fv,"emscripten_glUniformMatrix4fv":_emscripten_glUniformMatrix4fv,"emscripten_glUseProgram":_emscripten_glUseProgram,"emscripten_glValidateProgram":_emscripten_glValidateProgram,"emscripten_glVertexAttrib1f":_emscripten_glVertexAttrib1f,"emscripten_glVertexAttrib1fv":_emscripten_glVertexAttrib1fv,"emscripten_glVertexAttrib2f":_emscripten_glVertexAttrib2f,"emscripten_glVertexAttrib2fv":_emscripten_glVertexAttrib2fv,"emscripten_glVertexAttrib3f":_emscripten_glVertexAttrib3f,"emscripten_glVertexAttrib3fv":_emscripten_glVertexAttrib3fv,"emscripten_glVertexAttrib4f":_emscripten_glVertexAttrib4f,"emscripten_glVertexAttrib4fv":_emscripten_glVertexAttrib4fv,"emscripten_glVertexAttribDivisorANGLE":_emscripten_glVertexAttribDivisorANGLE,"emscripten_glVertexAttribPointer":_emscripten_glVertexAttribPointer,"emscripten_glViewport":_emscripten_glViewport,"emscripten_has_asyncify":_emscripten_has_asyncify,"emscripten_longjmp":_emscripten_longjmp,"emscripten_memcpy_big":_emscripten_memcpy_big,"emscripten_request_fullscreen_strategy":_emscripten_request_fullscreen_strategy,"emscripten_request_pointerlock":_emscripten_request_pointerlock,"emscripten_resize_heap":_emscripten_resize_heap,"emscripten_run_script":_emscripten_run_script,"emscripten_sample_gamepad_data":_emscripten_sample_gamepad_data,"emscripten_set_beforeunload_callback_on_thread":_emscripten_set_beforeunload_callback_on_thread,"emscripten_set_blur_callback_on_thread":_emscripten_set_blur_callback_on_thread,"emscripten_set_canvas_element_size":_emscripten_set_canvas_element_size,"emscripten_set_element_css_size":_emscripten_set_element_css_size,"emscripten_set_focus_callback_on_thread":_emscripten_set_focus_callback_on_thread,"emscripten_set_fullscreenchange_callback_on_thread":_emscripten_set_fullscreenchange_callback_on_thread,"emscripten_set_gamepadconnected_callback_on_thread":_emscripten_set_gamepadconnected_callback_on_thread,"emscripten_set_gamepaddisconnected_callback_on_thread":_emscripten_set_gamepaddisconnected_callback_on_thread,"emscripten_set_keydown_callback_on_thread":_emscripten_set_keydown_callback_on_thread,"emscripten_set_keypress_callback_on_thread":_emscripten_set_keypress_callback_on_thread,"emscripten_set_keyup_callback_on_thread":_emscripten_set_keyup_callback_on_thread,"emscripten_set_main_loop_arg":_emscripten_set_main_loop_arg,"emscripten_set_mousedown_callback_on_thread":_emscripten_set_mousedown_callback_on_thread,"emscripten_set_mouseenter_callback_on_thread":_emscripten_set_mouseenter_callback_on_thread,"emscripten_set_mouseleave_callback_on_thread":_emscripten_set_mouseleave_callback_on_thread,"emscripten_set_mousemove_callback_on_thread":_emscripten_set_mousemove_callback_on_thread,"emscripten_set_mouseup_callback_on_thread":_emscripten_set_mouseup_callback_on_thread,"emscripten_set_pointerlockchange_callback_on_thread":_emscripten_set_pointerlockchange_callback_on_thread,"emscripten_set_resize_callback_on_thread":_emscripten_set_resize_callback_on_thread,"emscripten_set_touchcancel_callback_on_thread":_emscripten_set_touchcancel_callback_on_thread,"emscripten_set_touchend_callback_on_thread":_emscripten_set_touchend_callback_on_thread,"emscripten_set_touchmove_callback_on_thread":_emscripten_set_touchmove_callback_on_thread,"emscripten_set_touchstart_callback_on_thread":_emscripten_set_touchstart_callback_on_thread,"emscripten_set_visibilitychange_callback_on_thread":_emscripten_set_visibilitychange_callback_on_thread,"emscripten_set_wheel_callback_on_thread":_emscripten_set_wheel_callback_on_thread,"emscripten_sleep":_emscripten_sleep,"environ_get":_environ_get,"environ_sizes_get":_environ_sizes_get,"exit":_exit,"fd_close":_fd_close,"fd_fdstat_get":_fd_fdstat_get,"fd_read":_fd_read,"fd_seek":_fd_seek,"fd_sync":_fd_sync,"fd_write":_fd_write,"gai_strerror":_gai_strerror,"getTempRet0":_getTempRet0,"getaddrinfo":_getaddrinfo,"gethostbyaddr":_gethostbyaddr,"gethostbyname":_gethostbyname,"getnameinfo":_getnameinfo,"getpwuid":_getpwuid,"gettimeofday":_gettimeofday,"invoke_diii":invoke_diii,"invoke_fiii":invoke_fiii,"invoke_i":invoke_i,"invoke_ii":invoke_ii,"invoke_iii":invoke_iii,"invoke_iiii":invoke_iiii,"invoke_iiiii":invoke_iiiii,"invoke_iiiiii":invoke_iiiiii,"invoke_iiiiiii":invoke_iiiiiii,"invoke_iiiiiiii":invoke_iiiiiiii,"invoke_iiiiiiiiiii":invoke_iiiiiiiiiii,"invoke_iiiiiiiiiiii":invoke_iiiiiiiiiiii,"invoke_iiiiiiiiiiiii":invoke_iiiiiiiiiiiii,"invoke_iiiiij":invoke_iiiiij,"invoke_jiiii":invoke_jiiii,"invoke_v":invoke_v,"invoke_vi":invoke_vi,"invoke_vii":invoke_vii,"invoke_viii":invoke_viii,"invoke_viiii":invoke_viiii,"invoke_viiiiiii":invoke_viiiiiii,"invoke_viiiiiiiiii":invoke_viiiiiiiiii,"invoke_viiiiiiiiiiiiiii":invoke_viiiiiiiiiiiiiii,"memory":wasmMemory,"mktime":_mktime,"nanosleep":_nanosleep,"pthread_mutexattr_init":_pthread_mutexattr_init,"pthread_mutexattr_settype":_pthread_mutexattr_settype,"setTempRet0":_setTempRet0,"sigaction":_sigaction,"signal":_signal,"strftime":_strftime,"strftime_l":_strftime_l,"sysconf":_sysconf,"system":_system,"table":wasmTable,"time":_time};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["__wasm_call_ctors"]).apply(null,arguments)};var _main=Module["_main"]=function(){return(_main=Module["_main"]=Module["asm"]["main"]).apply(null,arguments)};var _memcpy=Module["_memcpy"]=function(){return(_memcpy=Module["_memcpy"]=Module["asm"]["memcpy"]).apply(null,arguments)};var _realloc=Module["_realloc"]=function(){return(_realloc=Module["_realloc"]=Module["asm"]["realloc"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["malloc"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["free"]).apply(null,arguments)};var _strstr=Module["_strstr"]=function(){return(_strstr=Module["_strstr"]=Module["asm"]["strstr"]).apply(null,arguments)};var ___errno_location=Module["___errno_location"]=function(){return(___errno_location=Module["___errno_location"]=Module["asm"]["__errno_location"]).apply(null,arguments)};var _testSetjmp=Module["_testSetjmp"]=function(){return(_testSetjmp=Module["_testSetjmp"]=Module["asm"]["testSetjmp"]).apply(null,arguments)};var _saveSetjmp=Module["_saveSetjmp"]=function(){return(_saveSetjmp=Module["_saveSetjmp"]=Module["asm"]["saveSetjmp"]).apply(null,arguments)};var _htons=Module["_htons"]=function(){return(_htons=Module["_htons"]=Module["asm"]["htons"]).apply(null,arguments)};var _htonl=Module["_htonl"]=function(){return(_htonl=Module["_htonl"]=Module["asm"]["htonl"]).apply(null,arguments)};var _ntohs=Module["_ntohs"]=function(){return(_ntohs=Module["_ntohs"]=Module["asm"]["ntohs"]).apply(null,arguments)};var _emscripten_GetProcAddress=Module["_emscripten_GetProcAddress"]=function(){return(_emscripten_GetProcAddress=Module["_emscripten_GetProcAddress"]=Module["asm"]["emscripten_GetProcAddress"]).apply(null,arguments)};var __get_tzname=Module["__get_tzname"]=function(){return(__get_tzname=Module["__get_tzname"]=Module["asm"]["_get_tzname"]).apply(null,arguments)};var __get_daylight=Module["__get_daylight"]=function(){return(__get_daylight=Module["__get_daylight"]=Module["asm"]["_get_daylight"]).apply(null,arguments)};var __get_timezone=Module["__get_timezone"]=function(){return(__get_timezone=Module["__get_timezone"]=Module["asm"]["_get_timezone"]).apply(null,arguments)};var _setThrew=Module["_setThrew"]=function(){return(_setThrew=Module["_setThrew"]=Module["asm"]["setThrew"]).apply(null,arguments)};var stackSave=Module["stackSave"]=function(){return(stackSave=Module["stackSave"]=Module["asm"]["stackSave"]).apply(null,arguments)};var stackRestore=Module["stackRestore"]=function(){return(stackRestore=Module["stackRestore"]=Module["asm"]["stackRestore"]).apply(null,arguments)};var stackAlloc=Module["stackAlloc"]=function(){return(stackAlloc=Module["stackAlloc"]=Module["asm"]["stackAlloc"]).apply(null,arguments)};var dynCall_iiiiij=Module["dynCall_iiiiij"]=function(){return(dynCall_iiiiij=Module["dynCall_iiiiij"]=Module["asm"]["dynCall_iiiiij"]).apply(null,arguments)};var dynCall_jiiii=Module["dynCall_jiiii"]=function(){return(dynCall_jiiii=Module["dynCall_jiiii"]=Module["asm"]["dynCall_jiiii"]).apply(null,arguments)};var dynCall_viiiji=Module["dynCall_viiiji"]=function(){return(dynCall_viiiji=Module["dynCall_viiiji"]=Module["asm"]["dynCall_viiiji"]).apply(null,arguments)};var dynCall_ji=Module["dynCall_ji"]=function(){return(dynCall_ji=Module["dynCall_ji"]=Module["asm"]["dynCall_ji"]).apply(null,arguments)};var dynCall_iij=Module["dynCall_iij"]=function(){return(dynCall_iij=Module["dynCall_iij"]=Module["asm"]["dynCall_iij"]).apply(null,arguments)};var dynCall_jiij=Module["dynCall_jiij"]=function(){return(dynCall_jiij=Module["dynCall_jiij"]=Module["asm"]["dynCall_jiij"]).apply(null,arguments)};var dynCall_iiij=Module["dynCall_iiij"]=function(){return(dynCall_iiij=Module["dynCall_iiij"]=Module["asm"]["dynCall_iiij"]).apply(null,arguments)};var dynCall_viiij=Module["dynCall_viiij"]=function(){return(dynCall_viiij=Module["dynCall_viiij"]=Module["asm"]["dynCall_viiij"]).apply(null,arguments)};var dynCall_viijii=Module["dynCall_viijii"]=function(){return(dynCall_viijii=Module["dynCall_viijii"]=Module["asm"]["dynCall_viijii"]).apply(null,arguments)};var dynCall_iiji=Module["dynCall_iiji"]=function(){return(dynCall_iiji=Module["dynCall_iiji"]=Module["asm"]["dynCall_iiji"]).apply(null,arguments)};var dynCall_jiji=Module["dynCall_jiji"]=function(){return(dynCall_jiji=Module["dynCall_jiji"]=Module["asm"]["dynCall_jiji"]).apply(null,arguments)};var dynCall_jij=Module["dynCall_jij"]=function(){return(dynCall_jij=Module["dynCall_jij"]=Module["asm"]["dynCall_jij"]).apply(null,arguments)};var dynCall_ij=Module["dynCall_ij"]=function(){return(dynCall_ij=Module["dynCall_ij"]=Module["asm"]["dynCall_ij"]).apply(null,arguments)};var dynCall_iiiiijj=Module["dynCall_iiiiijj"]=function(){return(dynCall_iiiiijj=Module["dynCall_iiiiijj"]=Module["asm"]["dynCall_iiiiijj"]).apply(null,arguments)};var dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=function(){return(dynCall_iiiiiijj=Module["dynCall_iiiiiijj"]=Module["asm"]["dynCall_iiiiiijj"]).apply(null,arguments)};var __growWasmMemory=Module["__growWasmMemory"]=function(){return(__growWasmMemory=Module["__growWasmMemory"]=Module["asm"]["__growWasmMemory"]).apply(null,arguments)};function invoke_viiii(index,a1,a2,a3,a4){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iii(index,a1,a2){var sp=stackSave();try{return wasmTable.get(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiii(index,a1,a2,a3){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_vi(index,a1){var sp=stackSave();try{wasmTable.get(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_vii(index,a1,a2){var sp=stackSave();try{wasmTable.get(index)(a1,a2)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_v(index){var sp=stackSave();try{wasmTable.get(index)()}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_ii(index,a1){var sp=stackSave();try{return wasmTable.get(index)(a1)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiiii(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiii(index,a1,a2,a3,a4,a5){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_fiii(index,a1,a2,a3){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_diii(index,a1,a2,a3){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_i(index){var sp=stackSave();try{return wasmTable.get(index)()}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11){var sp=stackSave();try{return wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viii(index,a1,a2,a3){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_viiiiiiiiiiiiiii(index,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15){var sp=stackSave();try{wasmTable.get(index)(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14,a15)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_iiiiij(index,a1,a2,a3,a4,a5,a6){var sp=stackSave();try{return dynCall_iiiiij(index,a1,a2,a3,a4,a5,a6)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}function invoke_jiiii(index,a1,a2,a3,a4){var sp=stackSave();try{return dynCall_jiiii(index,a1,a2,a3,a4)}catch(e){stackRestore(sp);if(e!==e+0&&e!=="longjmp")throw e;_setThrew(1,0)}}Module["getMemory"]=getMemory;Module["addRunDependency"]=addRunDependency;Module["removeRunDependency"]=removeRunDependency;Module["FS_createFolder"]=FS.createFolder;Module["FS_createPath"]=FS.createPath;Module["FS_createDataFile"]=FS.createDataFile;Module["FS_createPreloadedFile"]=FS.createPreloadedFile;Module["FS_createLazyFile"]=FS.createLazyFile;Module["FS_createLink"]=FS.createLink;Module["FS_createDevice"]=FS.createDevice;Module["FS_unlink"]=FS.unlink;var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}var calledMain=false;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function callMain(args){var entryFunction=Module["_main"];args=args||[];var argc=args.length+1;var argv=stackAlloc((argc+1)*4);HEAP32[argv>>2]=allocateUTF8OnStack(thisProgram);for(var i=1;i>2)+i]=allocateUTF8OnStack(args[i-1])}HEAP32[(argv>>2)+argc]=0;try{var ret=entryFunction(argc,argv);exit(ret,true)}catch(e){if(e instanceof ExitStatus){return}else if(e=="unwind"){noExitRuntime=true;return}else{var toLog=e;if(e&&typeof e==="object"&&e.stack){toLog=[e,e.stack]}err("exception thrown: "+toLog);quit_(1,e)}}finally{calledMain=true}}function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();if(shouldRunNow)callMain(args);postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;function exit(status,implicit){if(implicit&&noExitRuntime&&status===0){return}if(noExitRuntime){}else{ABORT=true;EXITSTATUS=status;exitRuntime();if(Module["onExit"])Module["onExit"](status)}quit_(status,new ExitStatus(status))}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}var shouldRunNow=true;if(Module["noInitialRun"])shouldRunNow=false;noExitRuntime=true;run();if(typeof ENVIRONMENT_IS_PTHREAD==="undefined"||!ENVIRONMENT_IS_PTHREAD){Module.addRunDependency("IDBFS_sync");FS.mkdir("/home/web_user/love");FS.mount(IDBFS,{},"/home/web_user/love");FS.syncfs(true,function(err){if(err){Module["printErr"](err)}else{Module.removeRunDependency("IDBFS_sync")}});window.addEventListener("beforeunload",function(event){FS.syncfs(false,function(err){if(err){Module["printErr"](err)}})})} + + + return Love.ready +} +); +})(); +if (typeof exports === 'object' && typeof module === 'object') + module.exports = Love; + else if (typeof define === 'function' && define['amd']) + define([], function() { return Love; }); + else if (typeof exports === 'object') + exports["Love"] = Love; + \ No newline at end of file diff --git a/.github/build/web/love.wasm b/.github/build/web/love.wasm new file mode 100644 index 000000000..ab96086b0 Binary files /dev/null and b/.github/build/web/love.wasm differ diff --git a/.github/build/web/theme/bg.png b/.github/build/web/theme/bg.png new file mode 100644 index 000000000..77ef798d9 Binary files /dev/null and b/.github/build/web/theme/bg.png differ diff --git a/.github/build/web/theme/love.css b/.github/build/web/theme/love.css new file mode 100644 index 000000000..96bc2c23b --- /dev/null +++ b/.github/build/web/theme/love.css @@ -0,0 +1,49 @@ +* { + box-sizing: border-box; +} + +h1 { + font-family: arial; + color: rgb( 11, 86, 117 ); +} + +body { + background-image: url(bg.png); + background-repeat: no-repeat; + font-family: arial; + margin: 0; + padding: none; + background-color: rgb( 154, 205, 237 ); + color: rgb( 28, 78, 104 ); +} + +footer { + font-family: arial; + font-size: 12px; + padding-left: 10px; + position:absolute; + bottom: 0; + width: 100%; +} + +/* Links */ +a { + text-decoration: none; +} +a:link { + color: rgb( 233, 73, 154 ); +} +a:visited { + color: rgb( 110, 30, 71 ); +} +a:hover { + color: rgb( 252, 207, 230 ); +} + +/* the canvas *must not* have any border or padding, or mouse coords will be wrong */ +#canvas { + padding-right: 0; + display: block; + border: 0px none; + visibility: hidden; +} diff --git a/.github/build/windows/dev/.gitattributes b/.github/build/windows/dev/.gitattributes new file mode 100644 index 000000000..20947f93f --- /dev/null +++ b/.github/build/windows/dev/.gitattributes @@ -0,0 +1 @@ +*.rc text eol=crlf diff --git a/.github/build/Windows/icon_snapshot.ico b/.github/build/windows/dev/icon.ico similarity index 100% rename from .github/build/Windows/icon_snapshot.ico rename to .github/build/windows/dev/icon.ico diff --git a/.github/build/windows/dev/template.rc b/.github/build/windows/dev/template.rc new file mode 100644 index 000000000..f1774d581 --- /dev/null +++ b/.github/build/windows/dev/template.rc @@ -0,0 +1,26 @@ +1 VERSIONINFO +FILEVERSION @FileVersion +PRODUCTVERSION @FileVersion +FILEOS 0x40004 +FILETYPE 0x1 +{ + BLOCK "StringFileInfo" + { + BLOCK "040904B0" + { + VALUE "CompanyName", "26F Studio" + VALUE "FileDescription", "Techmino Development" + VALUE "FileVersion", "@Version" + VALUE "InternalName", "Techmino" + VALUE "LegalCopyright", "Copyright © 2019-2023 26F-Studio. Some Rights Reserved." + VALUE "OriginalFilename", "Techmino.exe" + VALUE "ProductName", "Techmino" + VALUE "ProductVersion", "@Version" + } + } + + BLOCK "VarFileInfo" + { + VALUE "Translation", 0x0409 0x04E4 + } +} diff --git a/.github/build/windows/release/.gitattributes b/.github/build/windows/release/.gitattributes new file mode 100644 index 000000000..20947f93f --- /dev/null +++ b/.github/build/windows/release/.gitattributes @@ -0,0 +1 @@ +*.rc text eol=crlf diff --git a/.github/build/Windows/icon.ico b/.github/build/windows/release/icon.ico similarity index 100% rename from .github/build/Windows/icon.ico rename to .github/build/windows/release/icon.ico diff --git a/.github/build/Windows/Techmino.rc.template b/.github/build/windows/release/template.rc similarity index 58% rename from .github/build/Windows/Techmino.rc.template rename to .github/build/windows/release/template.rc index 30c8207da..1e94e1dd9 100644 --- a/.github/build/Windows/Techmino.rc.template +++ b/.github/build/windows/release/template.rc @@ -8,9 +8,12 @@ FILETYPE 0x1 { BLOCK "040904B0" { - VALUE "FileDescription", "Techmino Alpha" VALUE "CompanyName", "26F Studio" - VALUE "LegalCopyright", "Copyright @ 26F Studio" + VALUE "FileDescription", "Techmino" + VALUE "FileVersion", "@Version" + VALUE "InternalName", "Techmino" + VALUE "LegalCopyright", "Copyright © 2019-2023 26F-Studio. Some Rights Reserved." + VALUE "OriginalFilename", "Techmino.exe" VALUE "ProductName", "Techmino" VALUE "ProductVersion", "@Version" } diff --git a/.github/workflows/dev.yml b/.github/workflows/dev.yml deleted file mode 100644 index dee4e5d07..000000000 --- a/.github/workflows/dev.yml +++ /dev/null @@ -1,203 +0,0 @@ -name: Techmino Develop CI - -on: - push: - branches: [ main, ci* ] - pull_request: - branches: [ main ] - -jobs: - get-info: - runs-on: ubuntu-20.04 - outputs: - name: ${{ steps.actual-get-info.outputs.name }} - apkCode: ${{ steps.actual-get-info.outputs.apkCode }} - code: ${{ steps.actual-get-info.outputs.code }} - commit: ${{ steps.actual-get-info.outputs.commit }} - steps: - - uses: actions/checkout@v2 - - name: Install lua - run: | - sudo apt-get install lua5.3 -y - - name: Get Version - id: actual-get-info - run: | - echo "::set-output name=name::$(lua .github/workflows/getVersion.lua -name)" - echo "::set-output name=apkCode::$(lua .github/workflows/getVersion.lua -apkCode)" - echo "::set-output name=code::$(lua .github/workflows/getVersion.lua -code)" - echo "::set-output name=commit::$(git rev-parse --short ${{ GITHUB.SHA }})" - - automatic-test: - runs-on: ubuntu-20.04 - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/automatic-test - - build-windows: - runs-on: windows-latest - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - uses: ./.github/actions/build-windows - with: - love-url: https://github.com/love2d/love/releases/download/11.3/love-11.3-win64.zip - love-dir: love-11.3-win64 - arch: win64 - version: ${{ needs.get-info.outputs.name }} - icon: .\.github\build\Windows\icon_snapshot.ico - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_Windows - path: love - - build-linux: - runs-on: ubuntu-20.04 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - uses: ./.github/actions/build-linux - with: - icon: .github/build/Linux/icon_snapshot.png - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_Linux - path: Techmino.AppImage - - build-android: - runs-on: ubuntu-20.04 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - uses: ./.github/actions/build-android - with: - type: Snapshot - apkCode: ${{ needs.get-info.outputs.apkCode }} - name: ${{ needs.get-info.outputs.name }} - file-path: Techmino_Snapshot.apk - SIGNING_KEY: ${{ secrets.SIGNING_KEY }} - KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }} - ALIAS: ${{ secrets.ALIAS }} - KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_Android - path: Techmino_Snapshot.apk - - build-android-mini: - runs-on: ubuntu-20.04 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - name: remove media - run: | - rm -rf media/music media/effect media/vocal - - uses: ./.github/actions/build-android - with: - type: Snapshot - apkCode: ${{ needs.get-info.outputs.apkCode }} - name: ${{ needs.get-info.outputs.name }} - file-path: Techmino_Snapshot_Mini.apk - SIGNING_KEY: ${{ secrets.SIGNING_KEY }} - KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }} - ALIAS: ${{ secrets.ALIAS }} - KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_Android_Mini - path: Techmino_Snapshot_Mini.apk - - build-macOS: - runs-on: macos-10.15 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - uses: ./.github/actions/build-macos - with: - name: ${{ needs.get-info.outputs.name }} - icon: .github/build/macOS/icon_snapshot.icns - APPLE_API_ID: '${{ secrets.APPLE_API_ID }}' - APPLE_API_ISSUER: '${{ secrets.APPLE_API_ISSUER }}' - APPLE_API_KEY: '${{ secrets.APPLE_API_KEY }}' - APPLE_APP_IDENTIFIER: '${{ secrets.APPLE_APP_IDENTIFIER }}' - APPLE_KEYCHAIN_NAME: '${{ secrets.APPLE_KEYCHAIN_NAME }}' - APPLE_KEYCHAIN_PWD: '${{ secrets.APPLE_KEYCHAIN_PWD }}' - FASTLANE_MATCH_PWD: '${{ secrets.FASTLANE_MATCH_PWD }}' - FASTLANE_MATCH_TOKEN: '${{ secrets.FASTLANE_MATCH_TOKEN }}' - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_macOS - path: Techmino.dmg - - build-iOS: - runs-on: macos-latest - if: (!startsWith( github.ref , 'refs/heads/ci-')) || startsWith( github.ref , 'refs/heads/ci-ios-') - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - uses: ./.github/actions/build-ios - with: - name: ${{ needs.get-info.outputs.name }} - type: 'dev' - APPLE_API_ID: '${{ secrets.APPLE_API_ID }}' - APPLE_API_ISSUER: '${{ secrets.APPLE_API_ISSUER }}' - APPLE_API_KEY: '${{ secrets.APPLE_API_KEY }}' - APPLE_APP_BUILD: '${{ needs.get-info.outputs.code }}.2.${{ github.run_number }}.${{ github.run_attempt }}' - APPLE_APP_CHANGELOG: '${{ github.event.commits[0].message }}' - APPLE_APP_ID: '${{ secrets.APPLE_APP_ID }}' - APPLE_APP_IDENTIFIER: '${{ secrets.APPLE_APP_IDENTIFIER }}' - APPLE_APP_PROFILE: '${{ secrets.APPLE_APP_PROFILE }}' - APPLE_KEYCHAIN_NAME: '${{ secrets.APPLE_KEYCHAIN_NAME }}' - APPLE_KEYCHAIN_PWD: '${{ secrets.APPLE_KEYCHAIN_PWD }}' - FASTLANE_ACTION_ID: '${{ github.run_id }}' - FASTLANE_DISCORD_WEBHOOK: '${{ secrets.FASTLANE_DISCORD_WEBHOOK }}' - FASTLANE_MATCH_PWD: '${{ secrets.FASTLANE_MATCH_PWD }}' - FASTLANE_MATCH_TOKEN: '${{ secrets.FASTLANE_MATCH_TOKEN }}' - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_iOS - path: Techmino.ipa - - build-love: - runs-on: ubuntu-20.04 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - - uses: ./.github/actions/build-love - with: - file-path: Techmino.love - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_${{ needs.get-info.outputs.name }}_${{ GITHUB.RUN_NUMBER }}_${{ needs.get-info.outputs.commit }}_Love - path: Techmino.love diff --git a/.github/workflows/getVersion.lua b/.github/workflows/getVersion.lua deleted file mode 100644 index b50b09017..000000000 --- a/.github/workflows/getVersion.lua +++ /dev/null @@ -1,28 +0,0 @@ -local arg=arg[1] -if arg=="-apkCode"then - local code=require"version".apkCode - print(code) -elseif arg=="-code"then - local str=require"version".code - print(str) -elseif arg=="-name"then - local str=require"version".string - print(str) -elseif arg=="-release"then - local str=require"version".string:gsub("V","",1) - print(str) -elseif arg=="-updateTitle"then - local note=require"parts.updateLog" - local p1=note:find("\n%d")+1 - local p2=note:find("\n",p1)-1 - note=note:sub(p1,p2) - print(note) -elseif arg=="-updateNote"then - local note=require"parts.updateLog" - local p1=note:find("\n",note:find("\n%d")+1)+1 - local p2=note:find("\n%d",p1+1) - note=note:sub(p1,p2-2) - :gsub(" ","- ") - :gsub(" ","# ") - print(note) -end diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 000000000..99ab5c2ce --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,724 @@ +name: Techmino CI + +on: + push: + branches: [main, ci*] + tags: [pre*, v*] + pull_request: + branches: [main] + +env: + BUILD_TYPE: ${{ fromJSON('["dev", "release"]')[startsWith(github.ref, 'refs/tags/v')] }} + CORE_LOVE_PACKAGE_PATH: ./core.love + CORE_LOVE_ARTIFACT_NAME: core_love_package + +jobs: + get-info: + runs-on: ubuntu-latest + outputs: + app-name: ${{ steps.app-info.outputs.app-name }} + version-name: ${{ steps.app-info.outputs.version-name }} + version-string: ${{ steps.app-info.outputs.version-string }} + version-code: ${{ steps.app-info.outputs.version-code }} + update-title: ${{ steps.app-info.outputs.update-title }} + update-note: ${{ steps.app-info.outputs.update-note }} + commit-hash: ${{ steps.git-info.outputs.commit-hash }} + base-name: ${{ steps.assemble-base-name.outputs.base-name }} + steps: + - uses: actions/checkout@v3 + - name: Install lua + run: | + sudo apt-get install lua5.3 -y + - name: Get app info + id: app-info + shell: lua {0} + run: | + local version = require "version" + os.execute('echo "app-name=Techmino" >> $GITHUB_OUTPUT') + os.execute('echo "version-name=' .. version.name .. '" >> $GITHUB_OUTPUT') + os.execute('echo "version-string=' .. version.string:gsub("%a", "") .. '" >> $GITHUB_OUTPUT') + os.execute('echo "version-code=' .. tostring(version.code) .. '" >> $GITHUB_OUTPUT') + + local note = require 'parts.updateLog' + local p1 = note:find("\n%d") + 1 + local p2 = note:find("\n", p1) - 1 + os.execute('echo "update-title=' .. note:sub(p1, p2) .. '" >> $GITHUB_OUTPUT') + local p3 = note:find("\n", note:find("\n%d") + 1) + 1 + local p4 = note:find("\n%d", p3 + 1) + updateNote = note:sub(p3, p4 - 2) + :gsub(" ", "- ") + :gsub(" ", "# ") + os.execute('echo "update-note<> $GITHUB_OUTPUT') + os.execute('echo "' .. updateNote .. '" >> $GITHUB_OUTPUT') + os.execute('echo "EOF" >> $GITHUB_OUTPUT') + - name: Get git info + id: git-info + shell: bash + run: | + COMMIT_HASH=$(git rev-parse --short ${{ GITHUB.SHA }}) + echo "commit-hash=$COMMIT_HASH" >> $GITHUB_OUTPUT + - name: Assemble package base name + id: assemble-base-name + shell: bash + run: | + BASE_NAME=Techmino_${{ steps.app-info.outputs.version-string }}_${{ steps.git-info.outputs.commit-hash }}_#${{ GITHUB.RUN_NUMBER }} + echo "base-name=$BASE_NAME" >> $GITHUB_OUTPUT + + build-core: + runs-on: ubuntu-latest + needs: get-info + env: + OUTPUT_FOLDER: ./build + RELEASE_FOLDER: ./release + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Process app name + id: process-app-name + shell: python3 {0} + run: | + import os + import re + with open(os.getenv('GITHUB_OUTPUT'), 'a') as f: + f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n') + - uses: ./.github/actions/update-version + if: ${{ !startsWith(github.ref, 'refs/tags/v') }} + with: + commit: ${{ needs.get-info.outputs.commit-hash }} + type: snapshot + - name: Build core love package + uses: love-actions/love-actions-core@v1 + with: + build-list: ./media/ ./parts/ ./Zframework/ ./conf.lua ./main.lua ./version.lua + package-path: ${{ env.CORE_LOVE_PACKAGE_PATH }} + - name: Upload core love package + uses: actions/upload-artifact@v3 + with: + name: ${{ env.CORE_LOVE_ARTIFACT_NAME }} + path: ${{ env.CORE_LOVE_PACKAGE_PATH }} + - name: Add icon to love package + run: | + cp ./.github/build/linux/${{ env.BUILD_TYPE }}/icon.png media/image/icon.png + zip -u ${{ env.CORE_LOVE_PACKAGE_PATH }} media/image/icon.png + rm media/image/icon.png + - name: Rename love package + run: | + mkdir -p ${{ env.OUTPUT_FOLDER }} + mv ${{ env.CORE_LOVE_PACKAGE_PATH }} ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.love + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_Core_love + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.love + - name: Prepare for release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + mkdir -p ${{ env.RELEASE_FOLDER }} + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.love ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Bare.love + - name: Upload release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifacts: ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Bare.love + body: ${{ needs.get-info.outputs.update-note }} + name: ${{ needs.get-info.outputs.update-title }} + prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }} + + auto-test: + runs-on: ubuntu-latest + needs: build-core + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Love actions for testing + uses: love-actions/love-actions-test@v1 + with: + font-path: ./parts/fonts/proportional.otf + language-folder: ./parts/language + + build-android: + runs-on: ubuntu-latest + needs: [get-info, build-core, auto-test] + if: github.event_name != 'pull_request' + env: + OUTPUT_FOLDER: ./build + RELEASE_FOLDER: ./release + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Process app name + id: process-app-name + shell: python3 {0} + run: | + import os + import re + with open(os.getenv('GITHUB_OUTPUT'), 'a') as f: + if "${{ env.BUILD_TYPE }}" == "dev": + f.write('bundle-id=org.f26_studio.' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '.snapshot\n') + f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '-', '${{ needs.get-info.outputs.app-name }}') + '_Snapshot\n') + else: + f.write('bundle-id=org.f26_studio.' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n') + f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '-', '${{ needs.get-info.outputs.app-name }}') + '\n') + - name: Download core love package + uses: actions/download-artifact@v3 + with: + name: ${{ env.CORE_LOVE_ARTIFACT_NAME }} + - name: Download ColdClear + uses: ./.github/actions/get-cc + with: + platform: Android + dir: ./libAndroid + - name: Build Android packages + id: build-packages + uses: love-actions/love-actions-android@main + with: + app-name: ${{ needs.get-info.outputs.app-name }} + bundle-id: ${{ steps.process-app-name.outputs.bundle-id }} + icon-specifier: "@mipmap/icon" + keystore-alias: ${{ secrets.ANDROID_KEYSTORE_ALIAS }} + keystore-base64: ${{ secrets.ANDROID_KEYSTORE_BASE64 }} + keystore-key-password: ${{ secrets.ANDROID_KEYSTORE_KEYPASSWORD }} + keystore-store-password: ${{ secrets.ANDROID_KEYSTORE_STOREPASSWORD }} + love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }} + resource-path: ./.github/build/android/${{ env.BUILD_TYPE }}/res + extra-assets: ./libAndroid/ + custom-scheme: studio26f://oauth + product-name: ${{ steps.process-app-name.outputs.product-name }} + version-string: ${{ needs.get-info.outputs.version-string }} + version-code: ${{ needs.get-info.outputs.version-code }} + output-folder: ${{ env.OUTPUT_FOLDER }} + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_Android_release + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}-release.apk + - name: Prepare for release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + mkdir -p ${{ env.RELEASE_FOLDER }} + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}-release.apk ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Android.apk + - name: Upload release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifacts: ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Android.apk + body: ${{ needs.get-info.outputs.update-note }} + name: ${{ needs.get-info.outputs.update-title }} + prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }} + + build-ios: + runs-on: macos-latest + needs: [get-info, build-core, auto-test] + if: github.event_name != 'pull_request' + env: + OUTPUT_FOLDER: ./build + RELEASE_FOLDER: ./release + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Process app name + id: process-app-name + shell: python3 {0} + run: | + import os + import re + with open(os.getenv('GITHUB_OUTPUT'), 'a') as f: + f.write('bundle-id=org.26f-studio.techmino\n') + f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n') + - name: Download core love package + uses: actions/download-artifact@v3 + with: + name: ${{ env.CORE_LOVE_ARTIFACT_NAME }} + - name: Download ColdClear + uses: ./.github/actions/get-cc + with: + platform: iOS + dir: ./ColdClear + - name: Build iOS packages + id: build-packages + uses: love-actions/love-actions-ios@v1 + with: + app-name: ${{ needs.get-info.outputs.app-name }} + bundle-id: ${{ steps.process-app-name.outputs.bundle-id }} + copyright: "Copyright © 2019-2023 26F-Studio. Some Rights Reserved." + icon-path: ./.github/build/iOS/${{ env.BUILD_TYPE }}/icon + love-patch: ./.github/build/iOS/love.patch + love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }} + libs-path: ./ColdClear/arm64/ + product-name: ${{ steps.process-app-name.outputs.product-name }} + version-string: ${{ needs.get-info.outputs.version-string }} + output-folder: ${{ env.OUTPUT_FOLDER }} + apple-development-base64: ${{ secrets.APPLE_CERT_APPLE_DEVELOPMENT_BASE64 }} + apple-development-password: ${{ secrets.APPLE_CERT_APPLE_DEVELOPMENT_PWD }} + api-key: ${{ secrets.APPLE_API_KEY }} + api-key-id: ${{ secrets.APPLE_API_KEY_ID }} + api-issuer-id: ${{ secrets.APPLE_API_ISSUER_ID }} + team-id: ${{ secrets.APPLE_DEVELOPER_TEAM_ID }} + apple-id: ${{ secrets.APPLE_APPLE_ID }} + external-test: ${{ startsWith(github.ref, 'refs/tags/pre') }} + store-release: ${{ startsWith(github.ref, 'refs/tags/v') }} + - name: Upload logs artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_iOS_logs + path: | + ${{ env.OUTPUT_FOLDER }}/DistributionSummary.plist + ${{ env.OUTPUT_FOLDER }}/ExportOptions.plist + ${{ env.OUTPUT_FOLDER }}/Packaging.log + - name: Upload ipa artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_iOS_ipa + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.ipa + - name: Prepare for release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + mkdir -p ${{ env.RELEASE_FOLDER }} + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.ipa ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_iOS.ipa + - name: Upload release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifacts: ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_iOS.ipa + body: ${{ needs.get-info.outputs.update-note }} + name: ${{ needs.get-info.outputs.update-title }} + prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }} + + build-linux: + runs-on: ubuntu-latest + needs: [get-info, build-core, auto-test] + env: + OUTPUT_FOLDER: ./build + RELEASE_FOLDER: ./release + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Process app name + id: process-app-name + shell: python3 {0} + run: | + import os + import re + + product_name = re.sub(r'[^A-Za-z0-9]+', '-', '${{ needs.get-info.outputs.app-name }}').strip('-').lower() + with open(os.getenv('GITHUB_OUTPUT'), 'a') as f: + f.write('bundle-id=org.26f-studio.' + product_name + '\n') + f.write('product-name=' + product_name + '\n') + - name: Download core love package + uses: actions/download-artifact@v3 + with: + name: ${{ env.CORE_LOVE_ARTIFACT_NAME }} + - name: Add icon to love package + run: | + cp ./.github/build/linux/${{ env.BUILD_TYPE }}/icon.png media/image/icon.png + zip -u ${{ env.CORE_LOVE_PACKAGE_PATH }} media/image/icon.png + rm media/image/icon.png + - name: Download ColdClear + uses: ./.github/actions/get-cc + with: + platform: Linux + dir: ./ColdClear + - name: Process ColdClear + shell: bash + run: | + cd ./ColdClear + mkdir -p ./lib/lua/5.1 + mv ./x64/CCloader.so ./lib/lua/5.1 + - name: Build Linux packages + id: build-packages + uses: love-actions/love-actions-linux@v1 + with: + app-name: ${{ needs.get-info.outputs.app-name }} + bundle-id: ${{ steps.process-app-name.outputs.bundle-id }} + description: Techmino is fun! + version-string: ${{ needs.get-info.outputs.version-string }} + icon-path: ./.github/build/linux/${{ env.BUILD_TYPE }}/icon.png + love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }} + lib-path: ./ColdClear/lib + product-name: ${{ steps.process-app-name.outputs.product-name }} + output-folder: ${{ env.OUTPUT_FOLDER }} + - name: Upload AppImage artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_Linux_AppImage + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.AppImage + - name: Upload Debian artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_Linux_Debian + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.deb + - name: Prepare for release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + mkdir -p ${{ env.RELEASE_FOLDER }} + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.AppImage ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Linux.AppImage + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.deb ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Linux.deb + - name: Upload release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifacts: | + ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Linux.AppImage + ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Linux.deb + body: ${{ needs.get-info.outputs.update-note }} + name: ${{ needs.get-info.outputs.update-title }} + prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }} + + build-macos-appstore: + runs-on: macos-latest + needs: [get-info, build-core, auto-test] + if: github.event_name != 'pull_request' + env: + OUTPUT_FOLDER: ./build + RELEASE_FOLDER: ./release + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Process app name + id: process-app-name + shell: python3 {0} + run: | + import os + import re + with open(os.getenv('GITHUB_OUTPUT'), 'a') as f: + f.write('bundle-id=org.26f-studio.techmino\n') + f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n') + - name: Download core love package + uses: actions/download-artifact@v3 + with: + name: ${{ env.CORE_LOVE_ARTIFACT_NAME }} + - name: Download ColdClear + uses: ./.github/actions/get-cc + with: + platform: macOS + dir: ./ColdClear + - name: Process ColdClear + shell: bash + run: | + rm ./ColdClear/universal/libcold_clear.a + - name: Build macOS packages + id: build-packages + uses: love-actions/love-actions-macos-appstore@v1 + with: + app-name: ${{ needs.get-info.outputs.app-name }} + bundle-id: ${{ steps.process-app-name.outputs.bundle-id }} + copyright: "Copyright © 2019-2023 26F-Studio. Some Rights Reserved." + icon-path: ./.github/build/macOS/${{ env.BUILD_TYPE }}/icon.icns + love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }} + libs-path: ./ColdClear/universal/ + product-name: ${{ steps.process-app-name.outputs.product-name }} + version-string: ${{ needs.get-info.outputs.version-string }} + output-folder: ${{ env.OUTPUT_FOLDER }} + apple-development-base64: ${{ secrets.APPLE_CERT_APPLE_DEVELOPMENT_BASE64 }} + apple-development-password: ${{ secrets.APPLE_CERT_APPLE_DEVELOPMENT_PWD }} + api-key: ${{ secrets.APPLE_API_KEY }} + api-key-id: ${{ secrets.APPLE_API_KEY_ID }} + api-issuer-id: ${{ secrets.APPLE_API_ISSUER_ID }} + team-id: ${{ secrets.APPLE_DEVELOPER_TEAM_ID }} + apple-id: ${{ secrets.APPLE_APPLE_ID }} + external-test: ${{ startsWith(github.ref, 'refs/tags/pre') }} + store-release: ${{ startsWith(github.ref, 'refs/tags/v') }} + - name: Upload logs artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_macOS_appstore_logs + path: | + ${{ env.OUTPUT_FOLDER }}/DistributionSummary.plist + ${{ env.OUTPUT_FOLDER }}/ExportOptions.plist + ${{ env.OUTPUT_FOLDER }}/Packaging.log + - name: Upload pkg artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_macOS_appstore_pkg + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.pkg + - name: Prepare for release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + mkdir -p ${{ env.RELEASE_FOLDER }} + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.pkg ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_appstore.pkg + - name: Upload release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifacts: ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_appstore.pkg + body: ${{ needs.get-info.outputs.update-note }} + name: ${{ needs.get-info.outputs.update-title }} + prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }} + + build-macos-portable: + runs-on: macos-latest + needs: [get-info, build-core, auto-test] + if: github.event_name != 'pull_request' + env: + OUTPUT_FOLDER: ./build + RELEASE_FOLDER: ./release + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Process app name + id: process-app-name + shell: python3 {0} + run: | + import os + import re + with open(os.getenv('GITHUB_OUTPUT'), 'a') as f: + f.write('bundle-id=org.26f-studio.techmino\n') + f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n') + - name: Download core love package + uses: actions/download-artifact@v3 + with: + name: ${{ env.CORE_LOVE_ARTIFACT_NAME }} + - name: Download ColdClear + uses: ./.github/actions/get-cc + with: + platform: macOS + dir: ./ColdClear + - name: Process ColdClear + shell: bash + run: | + rm ./ColdClear/universal/libcold_clear.a + - name: Build macOS packages + id: build-packages + uses: love-actions/love-actions-macos-portable@v1 + with: + app-name: ${{ needs.get-info.outputs.app-name }} + bundle-id: ${{ steps.process-app-name.outputs.bundle-id }} + copyright: "Copyright © 2019-2023 26F-Studio. Some Rights Reserved." + icon-path: ./.github/build/macOS/${{ env.BUILD_TYPE }}/icon.icns + love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }} + libs-path: ./ColdClear/universal/ + product-name: ${{ steps.process-app-name.outputs.product-name }} + version-string: ${{ needs.get-info.outputs.version-string }} + output-folder: ${{ env.OUTPUT_FOLDER }} + account-username: ${{ secrets.APPLE_ACCOUNT_USERNAME }} + account-password: ${{ secrets.APPLE_ACCOUNT_PASSWORD }} + team-id: "${{ secrets.APPLE_DEVELOPER_TEAM_ID }}" + developer-id-application-base64: ${{ secrets.APPLE_CERT_DEVELOPER_ID_APPLICATION }} + developer-id-application-password: ${{ secrets.APPLE_CERT_DEVELOPER_ID_APPLICATION_PWD }} + developer-id-installer-base64: ${{ secrets.APPLE_CERT_DEVELOPER_ID_INSTALLER }} + developer-id-installer-password: ${{ secrets.APPLE_CERT_DEVELOPER_ID_INSTALLER_PWD }} + dmg-background-path: ./.github/build/macOS/${{ env.BUILD_TYPE }}/dmg.png + dmg-icon-position: "239 203" + dmg-icon-size: "100" + dmg-link-position: "565 203" + dmg-text-size: "12" + dmg-volume-icon-path: ./.github/build/macOS/${{ env.BUILD_TYPE }}/dmg.icns + dmg-volume-name: ${{ steps.process-app-name.outputs.product-name }} + dmg-window-position: "200 120" + dmg-window-size: "800 500" + - name: Upload pkg artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_macOS_portable_pkg + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.pkg + - name: Upload dmg artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_macOS_portable_dmg + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.dmg + - name: Upload bare artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_macOS_portable_bare + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.zip + - name: Prepare for release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + mkdir -p ${{ env.RELEASE_FOLDER }} + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.pkg ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_portable.pkg + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}.dmg ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_portable.dmg + - name: Upload release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifacts: | + ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_portable.pkg + ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_macOS_portable.dmg + body: ${{ needs.get-info.outputs.update-note }} + name: ${{ needs.get-info.outputs.update-title }} + prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }} + + build-web: + runs-on: ubuntu-latest + needs: [get-info, build-core, auto-test] + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Download core love package + uses: actions/download-artifact@v3 + with: + name: ${{ env.CORE_LOVE_ARTIFACT_NAME }} + - name: Move core love package + run: | + mv ${{ env.CORE_LOVE_PACKAGE_PATH }} ./.github/build/web/game.data + - name: Deploy to GitHub Pages + uses: crazy-max/ghaction-github-pages@v3 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + build_dir: ./.github/build/web/ + keep_history: false + target_branch: web-dev + - name: Upload artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_Web_PWA + path: ./.github/build/web/ + + build-windows: + runs-on: windows-latest + needs: [get-info, build-core, auto-test] + env: + OUTPUT_FOLDER: ./build + RELEASE_FOLDER: ./release + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - name: Process app name + id: process-app-name + shell: python3 {0} + run: | + import os + import re + with open(os.getenv('GITHUB_OUTPUT'), 'a') as f: + f.write('product-name=' + re.sub(r'[^A-Za-z0-9]+', '_', '${{ needs.get-info.outputs.app-name }}') + '\n') + - name: Download core love package + uses: actions/download-artifact@v3 + with: + name: ${{ env.CORE_LOVE_ARTIFACT_NAME }} + - name: Download ColdClear + uses: ./.github/actions/get-cc + with: + platform: Windows + dir: ./ColdClear + - name: Update Windows template + shell: python3 {0} + run: | + version_string = "${{ needs.get-info.outputs.version-string }}" + file_version = (f"{version_string.replace('.', ',')},0") + with open("./.github/build/windows/${{ env.BUILD_TYPE }}/template.rc", "r+", encoding="utf8") as file: + data = file.read() + data = data\ + .replace("@Version", version_string)\ + .replace("@FileVersion", file_version) + file.seek(0) + file.truncate() + file.write(data) + - name: Build Windows packages + id: build-packages + uses: love-actions/love-actions-windows@v1 + with: + icon-path: ./.github/build/windows/${{ env.BUILD_TYPE }}/icon.ico + rc-path: ./.github/build/windows/${{ env.BUILD_TYPE }}/template.rc + love-package: ${{ env.CORE_LOVE_PACKAGE_PATH }} + extra-assets-x86: ./ColdClear/x86/CCloader.dll ./ColdClear/x86/cold_clear.dll + extra-assets-x64: ./ColdClear/x64/CCloader.dll ./ColdClear/x64/cold_clear.dll + product-name: ${{ steps.process-app-name.outputs.product-name }} + app-id: ${{ secrets.WINDOWS_APP_ID }} + project-website: https://www.studio26f.org/ + installer-languages: ChineseSimplified.isl ChineseTraditional.isl English.isl Spanish.isl French.isl Indonesian.isl Japanese.isl Portuguese.isl + output-folder: ${{ env.OUTPUT_FOLDER }} + - name: Upload 32-bit artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_Windows_x86 + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x86.zip + - name: Upload 64-bit artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_Windows_x64 + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x64.zip + - name: Upload installer artifact + uses: actions/upload-artifact@v3 + with: + name: ${{ needs.get-info.outputs.base-name }}_Windows_installer + path: ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_installer.exe + - name: Prepare for release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + shell: bash + run: | + mkdir -p ${{ env.RELEASE_FOLDER }} + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x86.zip ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_x86.zip + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_x64.zip ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_x64.zip + cp ${{ env.OUTPUT_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_installer.exe ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_installer.exe + - name: Upload release + if: ${{ startsWith(github.ref, 'refs/tags/pre') || startsWith(github.ref, 'refs/tags/v') }} + uses: ncipollo/release-action@v1 + with: + allowUpdates: true + artifacts: | + ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_x86.zip + ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_x64.zip + ${{ env.RELEASE_FOLDER }}/${{ steps.process-app-name.outputs.product-name }}_Windows_installer.exe + body: ${{ needs.get-info.outputs.update-note }} + name: ${{ needs.get-info.outputs.update-title }} + prerelease: ${{ startsWith(github.ref, 'refs/tags/pre') }} + + post-build: + runs-on: ubuntu-latest + if: ${{ always() }} + needs: + [ + get-info, + auto-test, + build-core, + build-android, + build-ios, + build-linux, + build-macos-appstore, + build-macos-portable, + build-web, + build-windows, + ] + env: + ACTION_TYPE: ${{ fromJSON('[["Development", "Pre-release"], ["Release", "Release"]]')[startsWith(github.ref, 'refs/tags/v')][startsWith(github.ref, 'refs/tags/pre')] }} + steps: + - name: Cleanup + uses: geekyeggo/delete-artifact@v2 + with: + name: ${{ env.CORE_LOVE_ARTIFACT_NAME }} + - name: Send Discord message + if: github.event_name != 'pull_request' + uses: Sniddl/discord-commits@v1.6 + with: + webhook: ${{ secrets.DISCORD_WEBHOOK }} + message: "Github Actions for **${{ github.repository }}**." + embed: '{ + "author":{ + "name":"${{ needs.get-info.outputs.app-name }} [${{ env.ACTION_TYPE }}]", + "url":"https://github.com/${{ github.repository }}" + }, + "title":"${{ needs.get-info.outputs.app-name }} (${{ needs.get-info.outputs.version-name }}) Build Result", + "description": "CI triggered at ${{ needs.get-info.outputs.commit-hash }}", + "url":"https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}", + "thumbnail":{ + "url":"https://raw.githubusercontent.com/${{ github.repository }}/main/.github/build/linux/${{ env.BUILD_TYPE }}/icon.png" + }, + "color":36863, + "fields":[ + {"name":"Version","value":"${{ needs.get-info.outputs.version-string }}","inline": true}, + {"name":"Package Name","value":"${{ needs.get-info.outputs.base-name }}","inline": true}, + {"name":"Status","value":"**Automatic Test:** ${{ needs.auto-test.result }}\n**Core:** ${{ needs.build-core.result }}\n**Android:** ${{ needs.build-android.result }}\n**iOS:** ${{ needs.build-ios.result }}\n**Linux:** ${{ needs.build-linux.result }}\n**macOS App Store:** ${{ needs.build-macos-appstore.result }}\n**macOS portable:** ${{ needs.build-macos-portable.result }}\n**Windows:** ${{ needs.build-windows.result }}"} + ] + }' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index 1fd139632..000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,189 +0,0 @@ -name: Techmino Release CI - -on: - push: - tags: - - "v*" - -jobs: - get-info: - runs-on: ubuntu-20.04 - outputs: - name: ${{ steps.actual-get-info.outputs.name }} - apkCode: ${{ steps.actual-get-info.outputs.apkCode }} - code: ${{ steps.actual-get-info.outputs.code }} - release: ${{ steps.actual-get-info.outputs.release }} - updateTitle: ${{ steps.actual-get-info.outputs.updateTitle }} - updateNote: ${{ steps.actual-get-info.outputs.updateNote }} - commit: ${{ steps.actual-get-info.outputs.commit }} - steps: - - uses: actions/checkout@v2 - - name: Install lua - run: | - sudo apt-get install lua5.3 -y - - name: Get Version - id: actual-get-info - run: | - UPDATE_NOTE=$(lua .github/workflows/getVersion.lua -updateNote) - UPDATE_NOTE="${UPDATE_NOTE//'%'/'%25'}" - UPDATE_NOTE="${UPDATE_NOTE//$'\n'/'%0A'}" - UPDATE_NOTE="${UPDATE_NOTE//$'\r'/'%0D'}" - echo "::set-output name=name::$(lua .github/workflows/getVersion.lua -name)" - echo "::set-output name=apkCode::$(lua .github/workflows/getVersion.lua -apkCode)" - echo "::set-output name=code::$(lua .github/workflows/getVersion.lua -code)" - echo "::set-output name=release::$(lua .github/workflows/getVersion.lua -release)" - echo "::set-output name=updateTitle::$(lua .github/workflows/getVersion.lua -updateTitle)" - echo "::set-output name=updateNote::$UPDATE_NOTE" - echo "::set-output name=commit::$(git rev-parse --short ${{ GITHUB.SHA }})" - - build-windows-x64: - runs-on: windows-latest - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - - uses: ./.github/actions/build-windows - with: - love-url: https://github.com/love2d/love/releases/download/11.3/love-11.3-win64.zip - love-dir: love-11.3-win64 - arch: win64 - version: ${{ needs.get-info.outputs.release }} - icon: .\.github\build\Windows\icon.ico - - name: Pack Techmino - run: 7z a -tzip .\Techmino_a${{ needs.get-info.outputs.release }}_Win64.zip .\love - - name: Release - uses: softprops/action-gh-release@v1 - with: - name: ${{ needs.get-info.outputs.updateTitle }} - files: Techmino_a${{ needs.get-info.outputs.release }}_Win64.zip - - build-windows-x86: - runs-on: windows-latest - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - - uses: ./.github/actions/build-windows - with: - love-url: https://github.com/love2d/love/releases/download/11.3/love-11.3-win32.zip - love-dir: love-11.3-win32 - arch: win32 - version: ${{ needs.get-info.outputs.release }} - icon: .\.github\build\Windows\icon.ico - - name: Pack Techmino - run: 7z a -tzip .\Techmino_a${{ needs.get-info.outputs.release }}_Win32.zip .\love - - name: Release - uses: softprops/action-gh-release@v1 - with: - name: ${{ needs.get-info.outputs.updateTitle }} - files: Techmino_a${{ needs.get-info.outputs.release }}_Win32.zip - - build-linux: - runs-on: ubuntu-20.04 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - - uses: ./.github/actions/build-linux - with: - file-path: Techmino_a${{ needs.get-info.outputs.release }}_Linux.AppImage - icon: .github/build/Linux/icon.png - - name: Release - uses: softprops/action-gh-release@v1 - with: - name: ${{ needs.get-info.outputs.updateTitle }} - files: Techmino_a${{ needs.get-info.outputs.release }}_Linux.AppImage - - build-android: - runs-on: ubuntu-20.04 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - - uses: ./.github/actions/build-android - with: - type: Release - apkCode: ${{ needs.get-info.outputs.apkCode }} - name: ${{ needs.get-info.outputs.name }} - file-path: Techmino_a${{ needs.get-info.outputs.release }}_Android.apk - SIGNING_KEY: ${{ secrets.SIGNING_KEY }} - KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }} - ALIAS: ${{ secrets.ALIAS }} - KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - - name: Release - uses: softprops/action-gh-release@v1 - with: - name: ${{ needs.get-info.outputs.updateTitle }} - files: Techmino_a${{ needs.get-info.outputs.release }}_Android.apk - - build-macOS: - runs-on: macos-10.15 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - - uses: ./.github/actions/build-macos - with: - name: ${{ needs.get-info.outputs.name }} - icon: .github/build/macOS/icon.icns - APPLE_API_ID: "${{ secrets.APPLE_API_ID }}" - APPLE_API_ISSUER: "${{ secrets.APPLE_API_ISSUER }}" - APPLE_API_KEY: "${{ secrets.APPLE_API_KEY }}" - APPLE_APP_IDENTIFIER: "${{ secrets.APPLE_APP_IDENTIFIER }}" - APPLE_KEYCHAIN_NAME: "${{ secrets.APPLE_KEYCHAIN_NAME }}" - APPLE_KEYCHAIN_PWD: "${{ secrets.APPLE_KEYCHAIN_PWD }}" - FASTLANE_MATCH_PWD: "${{ secrets.FASTLANE_MATCH_PWD }}" - FASTLANE_MATCH_TOKEN: "${{ secrets.FASTLANE_MATCH_TOKEN }}" - - name: Pack Techmino - run: | - mv Techmino.dmg Techmino_a${{ needs.get-info.outputs.release }}_MacOS.dmg - - name: Release - uses: softprops/action-gh-release@v1 - with: - name: ${{ needs.get-info.outputs.updateTitle }} - files: Techmino_a${{ needs.get-info.outputs.release }}_MacOS.dmg - - build-iOS: - runs-on: macos-latest - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - - uses: ./.github/actions/build-ios - with: - name: ${{ needs.get-info.outputs.name }} - type: "release" - APPLE_API_ID: "${{ secrets.APPLE_API_ID }}" - APPLE_API_ISSUER: "${{ secrets.APPLE_API_ISSUER }}" - APPLE_API_KEY: "${{ secrets.APPLE_API_KEY }}" - APPLE_APP_BUILD: "${{ needs.get-info.outputs.code }}.0.${{ github.run_number }}.${{ github.run_attempt }}" - APPLE_APP_CHANGELOG: "${{ needs.get-info.outputs.updateNote }}" - APPLE_APP_ID: "${{ secrets.APPLE_APP_ID }}" - APPLE_APP_IDENTIFIER: "${{ secrets.APPLE_APP_IDENTIFIER }}" - APPLE_APP_PROFILE: "${{ secrets.APPLE_APP_PROFILE }}" - APPLE_KEYCHAIN_NAME: "${{ secrets.APPLE_KEYCHAIN_NAME }}" - APPLE_KEYCHAIN_PWD: "${{ secrets.APPLE_KEYCHAIN_PWD }}" - FASTLANE_ACTION_ID: "${{ github.run_id }}" - FASTLANE_DISCORD_WEBHOOK: "${{ secrets.FASTLANE_DISCORD_WEBHOOK }}" - FASTLANE_MATCH_PWD: "${{ secrets.FASTLANE_MATCH_PWD }}" - FASTLANE_MATCH_TOKEN: "${{ secrets.FASTLANE_MATCH_TOKEN }}" - - name: Rename ipa - shell: bash - run: | - mv Techmino.ipa Techmino_a${{ needs.get-info.outputs.release }}_iOS.ipa - - name: Release - uses: softprops/action-gh-release@v1 - with: - name: ${{ needs.get-info.outputs.updateTitle }} - files: Techmino_a${{ needs.get-info.outputs.release }}_iOS.ipa - - Add-Release-note: - runs-on: ubuntu-20.04 - needs: get-info - steps: - - uses: actions/checkout@v2 - - name: Release - uses: softprops/action-gh-release@v1 - with: - name: ${{ needs.get-info.outputs.updateTitle }} - body: ${{ needs.get-info.outputs.updateNote }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml deleted file mode 100644 index 399d18620..000000000 --- a/.github/workflows/test.yml +++ /dev/null @@ -1,154 +0,0 @@ -name: Techmino Test CI - -on: - push: - tags: - - 'pre*' - -jobs: - get-info: - runs-on: ubuntu-20.04 - outputs: - name: ${{ steps.actual-get-info.outputs.name }} - apkCode: ${{ steps.actual-get-info.outputs.apkCode }} - code: ${{ steps.actual-get-info.outputs.code }} - release: ${{ steps.actual-get-info.outputs.release }} - commit: ${{ steps.actual-get-info.outputs.commit }} - steps: - - uses: actions/checkout@v2 - - name: Install lua - run: | - sudo apt-get install lua5.3 -y - - name: Get Version - id: actual-get-info - run: | - echo "::set-output name=name::$(lua .github/workflows/getVersion.lua -name)" - echo "::set-output name=apkCode::$(lua .github/workflows/getVersion.lua -apkCode)" - echo "::set-output name=code::$(lua .github/workflows/getVersion.lua -code)" - echo "::set-output name=release::$(lua .github/workflows/getVersion.lua -release)" - echo "::set-output name=commit::$(git rev-parse --short ${{ GITHUB.SHA }})" - - build-windows: - runs-on: windows-latest - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - uses: ./.github/actions/build-windows - with: - love-url: https://github.com/love2d/love/releases/download/11.3/love-11.3-win64.zip - love-dir: love-11.3-win64 - arch: win64 - version: ${{ needs.get-info.outputs.name }} - icon: .\.github\build\Windows\icon_snapshot.ico - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Windows - path: love - - build-linux: - runs-on: ubuntu-20.04 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - uses: ./.github/actions/build-linux - with: - icon: .github/build/Linux/icon_snapshot.png - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Linux - path: Techmino.AppImage - - build-android: - runs-on: ubuntu-20.04 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - uses: ./.github/actions/build-android - with: - type: Snapshot - apkCode: ${{ needs.get-info.outputs.apkCode }} - name: ${{ needs.get-info.outputs.name }} - file-path: Techmino_Snapshot.apk - SIGNING_KEY: ${{ secrets.SIGNING_KEY }} - KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }} - ALIAS: ${{ secrets.ALIAS }} - KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_Android - path: Techmino_Snapshot.apk - - build-macOS: - runs-on: macos-10.15 - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - uses: ./.github/actions/build-macos - with: - name: ${{ needs.get-info.outputs.name }} - icon: .github/build/macOS/icon_snapshot.icns - APPLE_API_ID: '${{ secrets.APPLE_API_ID }}' - APPLE_API_ISSUER: '${{ secrets.APPLE_API_ISSUER }}' - APPLE_API_KEY: '${{ secrets.APPLE_API_KEY }}' - APPLE_APP_IDENTIFIER: '${{ secrets.APPLE_APP_IDENTIFIER }}' - APPLE_KEYCHAIN_NAME: '${{ secrets.APPLE_KEYCHAIN_NAME }}' - APPLE_KEYCHAIN_PWD: '${{ secrets.APPLE_KEYCHAIN_PWD }}' - FASTLANE_MATCH_PWD: '${{ secrets.FASTLANE_MATCH_PWD }}' - FASTLANE_MATCH_TOKEN: '${{ secrets.FASTLANE_MATCH_TOKEN }}' - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_MacOS - path: Techmino.dmg - - build-iOS: - runs-on: macos-latest - needs: get-info - steps: - - uses: actions/checkout@v2 - - uses: ./.github/actions/update-version - with: - commit: ${{ needs.get-info.outputs.commit }} - type: snapshot - - uses: ./.github/actions/build-ios - with: - name: ${{ needs.get-info.outputs.name }} - type: 'test' - APPLE_API_ID: '${{ secrets.APPLE_API_ID }}' - APPLE_API_ISSUER: '${{ secrets.APPLE_API_ISSUER }}' - APPLE_API_KEY: '${{ secrets.APPLE_API_KEY }}' - APPLE_APP_BUILD: '${{ needs.get-info.outputs.code }}.1.${{ github.run_number }}.${{ github.run_attempt }}' - APPLE_APP_CHANGELOG: '${{ github.event.commits[0].message }}' - APPLE_APP_ID: '${{ secrets.APPLE_APP_ID }}' - APPLE_APP_IDENTIFIER: '${{ secrets.APPLE_APP_IDENTIFIER }}' - APPLE_APP_PROFILE: '${{ secrets.APPLE_APP_PROFILE }}' - APPLE_KEYCHAIN_NAME: '${{ secrets.APPLE_KEYCHAIN_NAME }}' - APPLE_KEYCHAIN_PWD: '${{ secrets.APPLE_KEYCHAIN_PWD }}' - FASTLANE_ACTION_ID: '${{ github.run_id }}' - FASTLANE_DISCORD_WEBHOOK: '${{ secrets.FASTLANE_DISCORD_WEBHOOK }}' - FASTLANE_MATCH_PWD: '${{ secrets.FASTLANE_MATCH_PWD }}' - FASTLANE_MATCH_TOKEN: '${{ secrets.FASTLANE_MATCH_TOKEN }}' - - name: Upload - uses: actions/upload-artifact@v2 - with: - name: Techmino_pre${{ needs.get-info.outputs.release }}_${{ needs.get-info.outputs.commit }}_iOS - path: Techmino.ipa diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..9f049b305 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "Zframework"] + path = Zframework + url = https://github.com/26F-Studio/Zframework.git diff --git a/Zframework b/Zframework new file mode 160000 index 000000000..359539073 --- /dev/null +++ b/Zframework @@ -0,0 +1 @@ +Subproject commit 3595390738cf1374dc54fe1210e38b0560764657 diff --git a/Zframework/background.lua b/Zframework/background.lua deleted file mode 100644 index 22f817868..000000000 --- a/Zframework/background.lua +++ /dev/null @@ -1,56 +0,0 @@ -local gc_clear=love.graphics.clear -local BGs={ - none={draw=function()gc_clear(.08,.08,.084)end} -} -local BGlist={'none'} -local BG={ - default='none', - locked=false, - cur='none', - init=false, - resize=false, - update=NULL, - draw=BGs.none.draw, - event=false, - discard=NULL, -} - -function BG.lock()BG.locked=true end -function BG.unlock()BG.locked=false end -function BG.add(name,bg) - BGs[name]=bg - BGlist[#BGlist+1]=name -end -function BG.getList() - return BGlist -end -function BG.remList(name) - table.remove(BGlist,TABLE.find(BGlist,name)) -end -function BG.send(...) - if BG.event then - BG.event(...) - end -end -function BG.setDefault(bg) - BG.default=bg -end -function BG.set(name) - name=name or BG.default - if not BGs[name]or BG.locked then return end - if name~=BG.cur then - BG.discard() - BG.cur=name - local bg=BGs[name] - - BG.init= bg.init or NULL - BG.resize= bg.resize or NULL - BG.update= bg.update or NULL - BG.draw= bg.draw or NULL - BG.event= bg.event or NULL - BG.discard=bg.discard or NULL - BG.init() - end - return true -end -return BG diff --git a/Zframework/bgm.lua b/Zframework/bgm.lua deleted file mode 100644 index 924f1a46b..000000000 --- a/Zframework/bgm.lua +++ /dev/null @@ -1,182 +0,0 @@ -local lastLoaded={} -local maxLoadedCount=3 -local nameList={} -local SourceObjList={} -local volume=1 - -local BGM={ - default=false, - onChange=NULL, - --nowPlay=[str:playing ID] - --playing=[src:playing SRC] - --lastPlayed=[str:lastPlayed ID] -} - -local function _tryReleaseSources() - local n=#lastLoaded - while #lastLoaded>maxLoadedCount do - local name=lastLoaded[n] - if SourceObjList[name].source:isPlaying()then - n=n-1 - if n<=0 then return end - else - SourceObjList[name].source=SourceObjList[name].source:release()and nil - table.remove(lastLoaded,n) - return - end - end -end -local function _addFile(name,path) - if not SourceObjList[name]then - table.insert(nameList,name) - SourceObjList[name]={path=path,source=false} - end -end - -function BGM.getList()return nameList end -function BGM.getCount()return #nameList end -function BGM.load(name,path) - if type(name)=='table'then - for k,v in next,name do - _addFile(k,v) - end - else - _addFile(name,path) - end - table.sort(nameList) - LOG(BGM.getCount().." BGM files added") -end - -function BGM.setDefault(bgm) - BGM.default=bgm -end -function BGM.setMaxSources(count) - maxLoadedCount=count - _tryReleaseSources() -end -function BGM.setChange(func) - BGM.onChange=func -end -function BGM.setVol(v) - assert(type(v)=='number'and v>=0 and v<=1,'Wrong volume') - volume=v - if BGM.playing then - if volume>0 then - BGM.playing:setVolume(volume) - BGM.playing:play() - elseif BGM.nowPlay then - BGM.playing:pause() - end - end -end - -local function task_fadeOut(src) - while true do - coroutine.yield() - local v=src:getVolume()-volume/40 - src:setVolume(v>0 and v or 0) - if v<=0 then - src:stop() - return true - end - end -end -local function task_fadeIn(src) - while true do - coroutine.yield() - local v=volume - v=math.min(v,src:getVolume()+v/40) - src:setVolume(v) - if v>=volume then - return true - end - end -end -local function check_curFadeOut(task,code,src) - return task.code==code and task.args[1]==src -end -local function _tryLoad(name) - if SourceObjList[name]then - if SourceObjList[name].source then - return true - elseif love.filesystem.getInfo(SourceObjList[name].path)then - SourceObjList[name].source=love.audio.newSource(SourceObjList[name].path,'stream') - SourceObjList[name].source:setVolume(0) - table.insert(lastLoaded,1,name) - _tryReleaseSources() - return true - else - LOG("No BGM: "..SourceObjList[name],5) - end - elseif name then - LOG("No BGM: "..name,5) - end -end -function BGM.play(name,args) - name=name or BGM.default - args=args or"" - if not _tryLoad(name)or args:sArg('-preLoad')then return end - if volume==0 then - BGM.nowPlay=name - BGM.playing=SourceObjList[name].source - return true - end - if name and SourceObjList[name].source then - if BGM.nowPlay~=name then - if BGM.nowPlay then - if not args:sArg('-sdout')then - TASK.new(task_fadeOut,BGM.playing) - else - BGM.playing:pause() - end - end - TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[name].source) - TASK.removeTask_code(task_fadeIn) - - BGM.nowPlay=name - BGM.playing=SourceObjList[name].source - if not args:sArg('-sdin')then - BGM.playing:setVolume(0) - TASK.new(task_fadeIn,BGM.playing) - else - BGM.playing:setVolume(volume) - BGM.playing:play() - end - SourceObjList[name].source:setLooping(not args:sArg('-noloop')) - BGM.lastPlayed=BGM.nowPlay - BGM.playing:play() - BGM.onChange(name) - end - return true - end -end -function BGM.seek(t) - if BGM.playing then - BGM.playing:seek(t) - end -end -function BGM.isPlaying() - return BGM.playing and BGM.playing:isPlaying() -end -function BGM.continue() - if BGM.lastPlayed then - BGM.nowPlay,BGM.playing=BGM.lastPlayed,SourceObjList[BGM.lastPlayed].source - TASK.removeTask_iterate(check_curFadeOut,task_fadeOut,SourceObjList[BGM.nowPlay].source) - TASK.removeTask_code(task_fadeIn) - TASK.new(task_fadeIn,BGM.playing) - BGM.playing:play() - end -end -function BGM.stop(args) - args=args or"" - TASK.removeTask_code(task_fadeIn) - if not args:sArg('-s')then - if BGM.nowPlay then - TASK.new(task_fadeOut,BGM.playing) - end - elseif BGM.playing then - BGM.playing:pause() - end - BGM.nowPlay,BGM.playing=nil -end -return BGM diff --git a/Zframework/color.lua b/Zframework/color.lua deleted file mode 100644 index 3b1ded1c3..000000000 --- a/Zframework/color.lua +++ /dev/null @@ -1,148 +0,0 @@ -local abs=math.abs -local function hsv(h,s,v,a)--Color type, Color amount, Light - if s<=0 then return v,v,v,a end - h=h*6 - local c=v*s - local x=abs((h-1)%2-1)*c - if h<1 then return v,x+v-c,v-c,a - elseif h<2 then return x+v-c,v,v-c,a - elseif h<3 then return v-c,v,x+v-c,a - elseif h<4 then return v-c,x+v-c,v,a - elseif h<5 then return x+v-c,v-c,v,a - else return v,v-c,x+v-c,a - end -end - -local COLOR={ - hsv=hsv, - - red= {hsv(0.00, 0.89, 0.91)}, - fire= {hsv(0.04, 0.93, 0.94)}, - orange= {hsv(0.09, 0.99, 0.96)}, - yellow= {hsv(0.15, 0.82, 0.90)}, - lime= {hsv(0.20, 0.89, 0.88)}, - jade= {hsv(0.25, 1.00, 0.82)}, - green= {hsv(0.33, 1.00, 0.81)}, - aqua= {hsv(0.47, 1.00, 0.76)}, - cyan= {hsv(0.53, 1.00, 0.88)}, - navy= {hsv(0.56, 1.00, 1.00)}, - sea= {hsv(0.61, 1.00, 1.00)}, - blue= {hsv(0.64, 1.00, 0.95)}, - violet= {hsv(0.74, 1.00, 0.91)}, - purple= {hsv(0.80, 1.00, 0.81)}, - magenta= {hsv(0.86, 1.00, 0.78)}, - wine= {hsv(0.92, 0.98, 0.91)}, - - lRed= {hsv(0.00, 0.38, 0.93)}, - lFire= {hsv(0.04, 0.45, 0.91)}, - lOrange= {hsv(0.10, 0.53, 0.92)}, - lYellow= {hsv(0.14, 0.61, 0.95)}, - lLime= {hsv(0.20, 0.66, 0.92)}, - lJade= {hsv(0.26, 0.56, 0.90)}, - lGreen= {hsv(0.34, 0.49, 0.89)}, - lAqua= {hsv(0.47, 0.59, 0.86)}, - lCyan= {hsv(0.51, 0.77, 0.88)}, - lNavy= {hsv(0.54, 0.80, 0.95)}, - lSea= {hsv(0.57, 0.72, 0.97)}, - lBlue= {hsv(0.64, 0.44, 0.96)}, - lViolet= {hsv(0.72, 0.47, 0.95)}, - lPurple= {hsv(0.80, 0.62, 0.89)}, - lMagenta= {hsv(0.86, 0.61, 0.89)}, - lWine= {hsv(0.93, 0.57, 0.92)}, - - dRed= {hsv(0.00, 0.80, 0.48)}, - dFire= {hsv(0.04, 0.80, 0.34)}, - dOrange= {hsv(0.07, 0.80, 0.39)}, - dYellow= {hsv(0.12, 0.80, 0.37)}, - dLime= {hsv(0.20, 0.80, 0.26)}, - dJade= {hsv(0.29, 0.80, 0.27)}, - dGreen= {hsv(0.33, 0.80, 0.26)}, - dAqua= {hsv(0.46, 0.80, 0.24)}, - dCyan= {hsv(0.50, 0.80, 0.30)}, - dNavy= {hsv(0.58, 0.80, 0.42)}, - dSea= {hsv(0.64, 0.80, 0.40)}, - dBlue= {hsv(0.67, 0.80, 0.34)}, - dViolet= {hsv(0.71, 0.80, 0.35)}, - dPurple= {hsv(0.76, 0.80, 0.32)}, - dMagenta= {hsv(0.87, 0.80, 0.28)}, - dWine= {hsv(0.92, 0.80, 0.28)}, - - black= {hsv(0.04, 0.04, 0.14)}, - dGray= {hsv(0.02, 0.05, 0.44)}, - gray= {hsv(0.02, 0.05, 0.65)}, - lGray= {hsv(0.02, 0.06, 0.86)}, - white= {hsv(0.01, 0.02, 0.99)}, - - xGray= {hsv(0.00, 0.00, 0.35,.8)}, - lxGray= {hsv(0.00, 0.00, 0.62,.8)}, - dxGray= {hsv(0.00, 0.00, 0.16,.8)}, -} -for k,v in next,{ - R='red', F='fire', O='orange', Y='yellow', L='lime', J='jade', G='green', A='aqua', C='cyan', N='navy', S='sea', B='blue', V='violet', P='purple', M='magenta', W='wine', - lR='lRed',lF='lFire',lO='lOrange',lY='lYellow',lL='lLime',lJ='lJade',lG='lGreen',lA='lAqua',lC='lCyan',lN='lNavy',lS='lSea',lB='lBlue',lV='lViolet',lP='lPurple',lM='lMagenta',lW='lWine', - dR='dRed',dF='dFire',dO='dOrange',dY='dYellow',dL='dLime',dJ='dJade',dG='dGreen',dA='dAqua',dC='dCyan',dN='dNavy',dS='dSea',dB='dBlue',dV='dViolet',dP='dPurple',dM='dMagenta',dW='dWine', - D='black',dH='dGray',H='gray',lH='lGray',Z='white', - X='xGray',lX='lxGray',dX='dxGray', - --Remain letter: EIKQTUX -}do - COLOR[k]=COLOR[v] -end -setmetatable(COLOR,{__index=function(_,k) - error("No color: "..tostring(k)) -end}) - - -do--Random generators - local rnd=math.random - local list_norm={'red','fire','orange','yellow','lime','jade','green','aqua','cyan','navy','sea','blue','violet','purple','magenta','wine'} - local len_list_norm=#list_norm - function COLOR.random_norm() - return COLOR[list_norm[rnd(len_list_norm)]] - end - - local list_bright={'lRed','lFire','lOrange','lYellow','lLime','lJade','lGreen','lAqua','lCyan','lNavy','lSea','lBlue','lViolet','lPurple','lMagenta','lWine'} - local len_list_bright=#list_bright - function COLOR.random_bright() - return COLOR[list_bright[rnd(len_list_bright)]] - end - - local list_dark={'dRed','dFire','dOrange','dYellow','dLime','dJade','dGreen','dAqua','dCyan','dNavy','dSea','dBlue','dViolet','dPurple','dMagenta','dWine'} - local len_list_dark=#list_dark - function COLOR.random_dark() - return COLOR[list_dark[rnd(len_list_dark)]] - end -end - -do--Rainbow generators - local sin=math.sin - function COLOR.rainbow(phase,a) - return - sin(phase)*.4+.6, - sin(phase+2.0944)*.4+.6, - sin(phase-2.0944)*.4+.6, - a - end - function COLOR.rainbow_light(phase,a) - return - sin(phase)*.2+.7, - sin(phase+2.0944)*.2+.7, - sin(phase-2.0944)*.2+.7, - a - end - function COLOR.rainbow_dark(phase,a) - return - sin(phase)*.2+.4, - sin(phase+2.0944)*.2+.4, - sin(phase-2.0944)*.2+.4, - a - end - function COLOR.rainbow_gray(phase,a) - return - sin(phase)*.16+.5, - sin(phase+2.0944)*.16+.5, - sin(phase-2.0944)*.16+.5, - a - end -end - -return COLOR diff --git a/Zframework/file.lua b/Zframework/file.lua deleted file mode 100644 index 83b847c56..000000000 --- a/Zframework/file.lua +++ /dev/null @@ -1,105 +0,0 @@ -local fs=love.filesystem -local FILE={} -function FILE.load(name,args) - if not args then args=''end - if fs.getInfo(name)then - local F=fs.newFile(name) - assert(F:open'r','open error') - local s=F:read()F:close() - local mode= - STRING.sArg(args,'-luaon')and'luaon'or - STRING.sArg(args,'-lua')and'lua'or - STRING.sArg(args,'-json')and'json'or - STRING.sArg(args,'-string')and'string'or - s:sub(1,6)=='return{'and'luaon'or - (s:sub(1,1)=='['and s:sub(-1)==']'or s:sub(1,1)=='{'and s:sub(-1)=='}')and'json'or - 'string' - if mode=='luaon'then - local func,err_mes=loadstring(s) - if func then - setfenv(func,{}) - local res=func() - return assert(res,'decode error') - else - error('decode error: '..err_mes) - end - elseif mode=='lua'then - local func,err_mes=loadstring(s) - if func then - local res=func() - return assert(res,'run error') - else - error('compile error: '..err_mes) - end - elseif mode=='json'then - local res=JSON.decode(s) - if res then - return res - end - error('decode error') - elseif mode=='string'then - return s - else - error('unknown mode') - end - else - error('no file') - end -end -function FILE.save(data,name,args) - if not args then args=''end - if STRING.sArg(args,'-d')and fs.getInfo(name)then - error('duplicate') - end - - if type(data)=='table'then - if STRING.sArg(args,'-luaon')then - data=TABLE.dump(data) - if not data then - error('encode error') - end - else - data=JSON.encode(data) - if not data then - error('encode error') - end - end - else - data=tostring(data) - end - - local F=fs.newFile(name) - assert(F:open('w'),'open error') - F:write(data)F:flush()F:close() -end -function FILE.clear(path) - if fs.getRealDirectory(path)==SAVEDIR and fs.getInfo(path).type=='directory'then - for _,name in next,fs.getDirectoryItems(path)do - name=path..'/'..name - if fs.getRealDirectory(name)==SAVEDIR then - local t=fs.getInfo(name).type - if t=='file'then - fs.remove(name) - end - end - end - end -end -function FILE.clear_s(path) - if path==''or(fs.getRealDirectory(path)==SAVEDIR and fs.getInfo(path).type=='directory')then - for _,name in next,fs.getDirectoryItems(path)do - name=path..'/'..name - if fs.getRealDirectory(name)==SAVEDIR then - local t=fs.getInfo(name).type - if t=='file'then - fs.remove(name) - elseif t=='directory'then - FILE.clear_s(name) - fs.remove(name) - end - end - end - fs.remove(path) - end -end -return FILE diff --git a/Zframework/font.lua b/Zframework/font.lua deleted file mode 100644 index 78238bd6c..000000000 --- a/Zframework/font.lua +++ /dev/null @@ -1,60 +0,0 @@ -local gc=love.graphics -local set=gc.setFont -local fontFiles,fontCache={},{} -local defaultFont,defaultFallBack -local curFont=false--Current using font object - -local FONT={} -function FONT.setDefault(name)defaultFont=name end -function FONT.setFallback(name)defaultFallBack=name end -function FONT.rawget(s) - if not fontCache[s]then - fontCache[s]=gc.setNewFont(s,'light',gc.getDPIScale()*SCR.k*2) - end - return fontCache[s] -end -function FONT.rawset(s) - set(fontCache[s]or FONT.rawget(s)) -end -function FONT.load(fonts) - for name,path in next,fonts do - assert(love.filesystem.getInfo(path),STRING.repD("Font file $1($2) not exist!",name,path)) - fontFiles[name]=love.filesystem.newFile(path) - fontCache[name]={} - end - FONT.reset() -end -function FONT.get(size,name) - if not name then name=defaultFont end - local f=fontCache[name][size] - if not f then - f=gc.setNewFont(fontFiles[name],size,'light',gc.getDPIScale()*SCR.k*2) - if defaultFallBack and name~=defaultFallBack then - f:setFallbacks(FONT.get(size,defaultFallBack)) - end - fontCache[name][size]=f - end - return f -end -function FONT.set(size,name) - if not name then name=defaultFont end - - local f=fontCache[name][size] - if f~=curFont then - curFont=f or FONT.get(size,name) - set(curFont) - end -end -function FONT.reset() - for name,cache in next,fontCache do - if type(cache)=='table'then - for size in next,cache do - cache[size]=FONT.get(size,name) - end - else - fontCache[name]=FONT.rawget(name) - end - end -end - -return FONT diff --git a/Zframework/gcExtend.lua b/Zframework/gcExtend.lua deleted file mode 100644 index 57cea2b00..000000000 --- a/Zframework/gcExtend.lua +++ /dev/null @@ -1,164 +0,0 @@ -local gc=love.graphics -local setColor,printf,draw=gc.setColor,gc.printf,gc.draw -local GC={} -function GC.mStr(obj,x,y)printf(obj,x-626,y,1252,'center')end--Printf a string with 'center' -function GC.simpX(obj,x,y)draw(obj,x-obj:getWidth()*.5,y)end--Simply draw an obj with x=obj:getWidth()/2 -function GC.simpY(obj,x,y)draw(obj,x,y-obj:getHeight()*.5)end--Simply draw an obj with y=obj:getWidth()/2 -function GC.X(obj,x,y,a,k)draw(obj,x,y,a,k,nil,obj:getWidth()*.5,0)end--Draw an obj with x=obj:getWidth()/2 -function GC.Y(obj,x,y,a,k)draw(obj,x,y,a,k,nil,0,obj:getHeight()*.5)end--Draw an obj with y=obj:getWidth()/2 -function GC.draw(obj,x,y,a,k)draw(obj,x,y,a,k,nil,obj:getWidth()*.5,obj:getHeight()*.5)end--Draw an obj with both middle X & Y -function GC.outDraw(obj,div,x,y,a,k) - local w,h=obj:getWidth()*.5,obj:getHeight()*.5 - draw(obj,x-div,y-div,a,k,nil,w,h) - draw(obj,x-div,y+div,a,k,nil,w,h) - draw(obj,x+div,y-div,a,k,nil,w,h) - draw(obj,x+div,y+div,a,k,nil,w,h) -end -function GC.shadedPrint(str,x,y,mode,d,clr1,clr2) - local w=1280 - if mode=='center'then - x=x-w*.5 - elseif mode=='right'then - x=x-w - end - if not d then d=1 end - setColor(clr1 or COLOR.D) - printf(str,x-d,y-d,w,mode) - printf(str,x-d,y+d,w,mode) - printf(str,x+d,y-d,w,mode) - printf(str,x+d,y+d,w,mode) - setColor(clr2 or COLOR.Z) - printf(str,x,y,w,mode) -end -function GC.regularPolygon(mode,x,y,R,segments,r,phase) - local X,Y={},{} - local ang=phase or 0 - local angStep=6.283185307179586/segments - for i=1,segments do - X[i]=x+R*math.cos(ang) - Y[i]=y+R*math.sin(ang) - ang=ang+angStep - end - X[segments+1]=x+R*math.cos(ang) - Y[segments+1]=y+R*math.sin(ang) - local halfAng=6.283185307179586/segments/2 - local erasedLen=r*math.tan(halfAng) - if mode=='line'then - erasedLen=erasedLen+1--Fix 1px cover - for i=1,segments do - --Line - local x1,y1,x2,y2=X[i],Y[i],X[i+1],Y[i+1] - local dir=math.atan2(y2-y1,x2-x1) - gc.line(x1+erasedLen*math.cos(dir),y1+erasedLen*math.sin(dir),x2-erasedLen*math.cos(dir),y2-erasedLen*math.sin(dir)) - - --Arc - ang=ang+angStep - local R2=R-r/math.cos(halfAng) - local arcCX,arcCY=x+R2*math.cos(ang),y+R2*math.sin(ang) - gc.arc('line','open',arcCX,arcCY,r,ang-halfAng,ang+halfAng) - end - elseif mode=='fill'then - local L={} - for i=1,segments do - --Line - local x1,y1,x2,y2=X[i],Y[i],X[i+1],Y[i+1] - local dir=math.atan2(y2-y1,x2-x1) - table.insert(L,x1+erasedLen*math.cos(dir)) - table.insert(L,y1+erasedLen*math.sin(dir)) - table.insert(L,x2-erasedLen*math.cos(dir)) - table.insert(L,y2-erasedLen*math.sin(dir)) - - --Arc - ang=ang+angStep - local R2=R-r/math.cos(halfAng) - local arcCX,arcCY=x+R2*math.cos(ang),y+R2*math.sin(ang) - gc.arc('fill','open',arcCX,arcCY,r,ang-halfAng,ang+halfAng) - end - gc.polygon('fill',L) - else - error("Draw mode should be 'line' or 'fill'") - end -end -do--function GC.DO(L) - local cmds={ - origin="origin", - move="translate", - scale="scale", - rotate="rotate", - shear="shear", - clear="clear", - - setCL="setColor", - setCM="setColorMask", - setLW="setLineWidth", - setLS="setLineStyle", - setLJ="setLineJoin", - - print="print", - rawFT=function(...)FONT.rawset(...)end, - setFT=function(...)FONT.set(...)end, - mText=GC.mStr, - mDraw=GC.draw, - mDrawX=GC.X, - mDrawY=GC.Y, - mOutDraw=GC.outDraw, - - draw="draw", - line="line", - fRect=function(...)gc.rectangle('fill',...)end, - dRect=function(...)gc.rectangle('line',...)end, - fCirc=function(...)gc.circle('fill',...)end, - dCirc=function(...)gc.circle('line',...)end, - fElps=function(...)gc.ellipse('fill',...)end, - dElps=function(...)gc.ellipse('line',...)end, - fPoly=function(...)gc.polygon('fill',...)end, - dPoly=function(...)gc.polygon('line',...)end, - - dPie=function(...)gc.arc('line',...)end, - dArc=function(...)gc.arc('line','open',...)end, - dBow=function(...)gc.arc('line','closed',...)end, - fPie=function(...)gc.arc('fill',...)end, - fArc=function(...)gc.arc('fill','open',...)end, - fBow=function(...)gc.arc('fill','closed',...)end, - - fRPol=function(...)GC.regularPolygon('fill',...)end, - dRPol=function(...)GC.regularPolygon('line',...)end, - } - local sizeLimit=gc.getSystemLimits().texturesize - function GC.DO(L) - gc.push() - ::REPEAT_tryAgain:: - local success,canvas=pcall(gc.newCanvas,math.min(L[1],sizeLimit),math.min(L[2],sizeLimit)) - if not success then - sizeLimit=math.floor(sizeLimit*.8) - goto REPEAT_tryAgain - end - gc.setCanvas(canvas) - gc.origin() - gc.clear(1,1,1,0) - gc.setColor(1,1,1) - gc.setLineWidth(1) - for i=3,#L do - local cmd=L[i][1] - if type(cmd)=='boolean'and cmd then - table.remove(L[i],1) - cmd=L[i][1] - end - if type(cmd)=='string'then - local func=cmds[cmd] - if type(func)=='string'then - func=gc[func] - end - if func then - func(unpack(L[i],2)) - else - error("No gc command: "..cmd) - end - end - end - gc.setCanvas() - gc.pop() - return canvas - end -end -return GC diff --git a/Zframework/image.lua b/Zframework/image.lua deleted file mode 100644 index 7f5412300..000000000 --- a/Zframework/image.lua +++ /dev/null @@ -1,25 +0,0 @@ -local IMG={} -function IMG.init(list) - IMG.init=nil - - setmetatable(IMG,{__index=function(self,name) - if type(list[name])=='table'then - self[name]={} - for i=1,#list[name]do - self[name][i]=love.graphics.newImage(list[name][i]) - end - elseif type(list[name])=='string'then - self[name]=love.graphics.newImage(list[name]) - else - LOG("No IMG: "..name) - self[name]=PAPER - end - return self[name] - end}) - - function IMG.loadAll() - for k in next,list do local _=IMG[k]end - IMG.loadAll=nil - end -end -return IMG diff --git a/Zframework/init.lua b/Zframework/init.lua deleted file mode 100644 index 400a62631..000000000 --- a/Zframework/init.lua +++ /dev/null @@ -1,885 +0,0 @@ -NONE={}function NULL()end PAPER=love.graphics.newCanvas(1,1) -EDITING="" -LOADED=false - ---Pure lua modules (basic) -MATH= require'Zframework.mathExtend' -COLOR= require'Zframework.color' -TABLE= require'Zframework.tableExtend' -STRING= require'Zframework.stringExtend' -PROFILE= require'Zframework.profile' -JSON= require'Zframework.json' -TEST= require'Zframework.test' - -do--Add pcall & MES for JSON lib - local encode,decode=JSON.encode,JSON.decode - JSON.encode=function(val) - local a,b=pcall(encode,val) - if a then - return b - elseif MES then - MES.traceback() - end - end - JSON.decode=function(str) - local a,b=pcall(decode,str) - if a then - return b - elseif MES then - MES.traceback() - end - end -end - ---Pure lua modules (complex) -LOG= require'Zframework.log' -REQUIRE= require'Zframework.require' -TASK= require'Zframework.task' -WS= require'Zframework.websocket' -LANG= require'Zframework.languages' - ---Love-based modules (basic) -FILE= require'Zframework.file' -WHEELMOV= require'Zframework.wheelScroll' -SCR= require'Zframework.screen' -SCN= require'Zframework.scene' -LIGHT= require'Zframework.light' - ---Love-based modules (complex) -GC= require'Zframework.gcExtend' -FONT= require'Zframework.font' -TEXT= require'Zframework.text' -SYSFX= require'Zframework.sysFX' -MES= require'Zframework.message' -BG= require'Zframework.background' -WIDGET= require'Zframework.widget' -VIB= require'Zframework.vibrate' -SFX= require'Zframework.sfx' -IMG= require'Zframework.image' -BGM= require'Zframework.bgm' -VOC= require'Zframework.voice' - -local ms,kb=love.mouse,love.keyboard -local KBisDown=kb.isDown - -local gc=love.graphics -local gc_push,gc_pop,gc_clear,gc_discard=gc.push,gc.pop,gc.clear,gc.discard -local gc_replaceTransform,gc_present=gc.replaceTransform,gc.present -local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth -local gc_draw,gc_line,gc_circle,gc_print=gc.draw,gc.line,gc.circle,gc.print - -local WIDGET,SCR,SCN=WIDGET,SCR,SCN -local xOy=SCR.xOy -local ITP=xOy.inverseTransformPoint - -local max,min=math.max,math.min - -local devMode -local mx,my,mouseShow,cursorSpd=640,360,false,0 -local jsState={}--map, joystickID->axisStates: {axisName->axisVal} -local errData={}--list, each error create {mes={errMes strings},scene=sceneNameStr} - -local function drawCursor(_,x,y) - gc_setColor(1,1,1) - gc_setLineWidth(2) - gc_circle(ms.isDown(1)and'fill'or'line',x,y,6) -end -local showPowerInfo=true -local showClickFX=true -local discardCanvas=false -local frameMul=100 -local sleepInterval=1/60 -local onQuit=NULL - -local batteryImg=GC.DO{31,20, - {'fRect',1,0,26,2}, - {'fRect',1,18,26,2}, - {'fRect',0,1,2,18}, - {'fRect',26,1,2,18}, - {'fRect',29,3,2,14}, -} -local infoCanvas=gc.newCanvas(108,27) -local function updatePowerInfo() - local state,pow=love.system.getPowerInfo() - gc.setCanvas(infoCanvas) - gc_push('transform') - gc.origin() - gc_clear(0,0,0,.25) - if state~='unknown'then - gc_setLineWidth(4) - if state=='nobattery'then - gc_setColor(1,1,1) - gc_setLineWidth(2) - gc_line(74,5,100,22) - elseif pow then - if state=='charging'then gc_setColor(0,1,0) - elseif pow>50 then gc_setColor(1,1,1) - elseif pow>26 then gc_setColor(1,1,0) - elseif pow==26 then gc_setColor(.5,0,1) - else gc_setColor(1,0,0) - end - gc.rectangle('fill',76,6,pow*.22,14) - if pow<100 then - FONT.set(15) - gc.setColor(COLOR.D) - gc_print(pow,77,1) - gc_print(pow,77,3) - gc_print(pow,79,1) - gc_print(pow,79,3) - gc_setColor(COLOR.Z) - gc_print(pow,78,2) - end - end - gc_draw(batteryImg,73,3) - end - FONT.set(25) - gc_print(os.date("%H:%M"),3,-5) - gc_pop() - gc.setCanvas() -end -------------------------------------------------------------- -local lastX,lastY=0,0--Last click pos -local function _updateMousePos(x,y,dx,dy) - if SCN.swapping then return end - dx,dy=dx/SCR.k,dy/SCR.k - if SCN.mouseMove then SCN.mouseMove(x,y,dx,dy)end - if ms.isDown(1)then - WIDGET.drag(x,y,dx,dy) - else - WIDGET.cursorMove(x,y) - end -end -local function _triggerMouseDown(x,y,k) - if devMode==1 then - print(("(%d,%d)<-%d,%d ~~(%d,%d)<-%d,%d"):format( - x,y, - x-lastX,y-lastY, - math.floor(x/10)*10,math.floor(y/10)*10, - math.floor((x-lastX)/10)*10,math.floor((y-lastY)/10)*10 - )) - end - if SCN.swapping then return end - if SCN.mouseDown then SCN.mouseDown(x,y,k)end - WIDGET.press(x,y,k) - lastX,lastY=x,y - if showClickFX then SYSFX.newTap(3,x,y)end -end -local function mouse_update(dt) - if not KBisDown('lctrl','rctrl')and KBisDown('up','down','left','right')then - local dx,dy=0,0 - if KBisDown('up')then dy=dy-cursorSpd end - if KBisDown('down')then dy=dy+cursorSpd end - if KBisDown('left')then dx=dx-cursorSpd end - if KBisDown('right')then dx=dx+cursorSpd end - mx=max(min(mx+dx,1280),0) - my=max(min(my+dy,720),0) - if my==0 or my==720 then - WIDGET.sel=false - WIDGET.drag(0,0,0,-dy) - end - _updateMousePos(mx,my,dx,dy) - cursorSpd=min(cursorSpd+dt*26,12.6) - else - cursorSpd=6 - end -end -local function gp_update(js,dt) - local sx,sy=js._jsObj:getGamepadAxis('leftx'),js._jsObj:getGamepadAxis('lefty') - if math.abs(sx)>.1 or math.abs(sy)>.1 then - local dx,dy=0,0 - if sy<-.1 then dy=dy+2*sy*cursorSpd end - if sy>.1 then dy=dy+2*sy*cursorSpd end - if sx<-.1 then dx=dx+2*sx*cursorSpd end - if sx>.1 then dx=dx+2*sx*cursorSpd end - mx=max(min(mx+dx,1280),0) - my=max(min(my+dy,720),0) - if my==0 or my==720 then - WIDGET.sel=false - WIDGET.drag(0,0,0,-dy) - end - _updateMousePos(mx,my,dx,dy) - cursorSpd=min(cursorSpd+dt*26,12.6) - else - cursorSpd=6 - end -end -function love.mousepressed(x,y,k,touch) - if touch then return end - mouseShow=true - mx,my=ITP(xOy,x,y) - _triggerMouseDown(mx,my,k) -end -function love.mousemoved(x,y,dx,dy,touch) - if touch then return end - mouseShow=true - mx,my=ITP(xOy,x,y) - _updateMousePos(mx,my,dx,dy) -end -function love.mousereleased(x,y,k,touch) - if touch or SCN.swapping then return end - mx,my=ITP(xOy,x,y) - if SCN.mouseUp then SCN.mouseUp(mx,my,k)end - if WIDGET.sel then - WIDGET.release(mx,my) - else - if lastX and SCN.mouseClick and(mx-lastX)^2+(my-lastY)^2<62 then - SCN.mouseClick(mx,my,k) - end - end -end -function love.wheelmoved(x,y) - if SCN.swapping then return end - if SCN.wheelMoved then - SCN.wheelMoved(x,y) - else - WIDGET.unFocus() - WIDGET.drag(0,0,0,100*y) - end -end - -function love.touchpressed(id,x,y) - mouseShow=false - if SCN.swapping then return end - if not SCN.mainTouchID then - SCN.mainTouchID=id - WIDGET.unFocus(true) - love.touchmoved(id,x,y,0,0) - end - x,y=ITP(xOy,x,y) - lastX,lastY=x,y - WIDGET.cursorMove(x,y) - if SCN.touchDown then SCN.touchDown(x,y,id)end - if kb.hasTextInput()then kb.setTextInput(false)end -end -function love.touchmoved(id,x,y,dx,dy) - if SCN.swapping then return end - x,y=ITP(xOy,x,y) - if SCN.touchMove then SCN.touchMove(x,y,dx/SCR.k,dy/SCR.k,id)end - WIDGET.drag(x,y,dx/SCR.k,dy/SCR.k) -end -function love.touchreleased(id,x,y) - if SCN.swapping then return end - x,y=ITP(xOy,x,y) - if id==SCN.mainTouchID then - WIDGET.press(x,y,1) - WIDGET.release(x,y) - WIDGET.cursorMove(x,y) - WIDGET.unFocus() - SCN.mainTouchID=false - end - if SCN.touchUp then SCN.touchUp(x,y,id)end - if(x-lastX)^2+(y-lastY)^2<62 then - if SCN.touchClick then SCN.touchClick(x,y)end - if showClickFX then SYSFX.newTap(3,x,y)end - end -end - -local fnKey={NULL,NULL,NULL,NULL,NULL,NULL,NULL} -local function noDevkeyPressed(key) - if key=='f1'then fnKey[1]() - elseif key=='f2'then fnKey[2]() - elseif key=='f3'then fnKey[3]() - elseif key=='f4'then fnKey[4]() - elseif key=='f5'then fnKey[5]() - elseif key=='f6'then fnKey[6]() - elseif key=='f7'then fnKey[7]() - elseif key=='f8'then devMode=nil MES.new('info',"DEBUG OFF",.2) - elseif key=='f9'then devMode=1 MES.new('info',"DEBUG 1") - elseif key=='f10'then devMode=2 MES.new('info',"DEBUG 2") - elseif key=='f11'then devMode=3 MES.new('info',"DEBUG 3") - elseif key=='f12'then devMode=4 MES.new('info',"DEBUG 4") - elseif devMode==2 then - local W=WIDGET.sel - if W then - if key=='left'then W.x=W.x-10 - elseif key=='right'then W.x=W.x+10 - elseif key=='up'then W.y=W.y-10 - elseif key=='down'then W.y=W.y+10 - elseif key==','then W.w=W.w-10 - elseif key=='.'then W.w=W.w+10 - elseif key=='/'then W.h=W.h-10 - elseif key=='\''then W.h=W.h+10 - elseif key=='['then W.font=W.font-5 - elseif key==']'then W.font=W.font+5 - else return true - end - else - return true - end - else - return true - end -end -function love.keypressed(key,_,isRep) - mouseShow=false - if devMode and not noDevkeyPressed(key)then - return - elseif key=='f8'then - devMode=1 - MES.new('info',"DEBUG ON",.2) - elseif key=='f11'then - SETTING.fullscreen=not SETTING.fullscreen - applySettings() - saveSettings() - elseif not SCN.swapping then - if EDITING==""and(not SCN.keyDown or SCN.keyDown(key,isRep))then - local W=WIDGET.sel - if key=='escape'and not isRep then - SCN.back() - elseif key=='up'or key=='down'or key=='left'or key=='right'then - mouseShow=true - if KBisDown('lctrl','rctrl')then - if W and W.arrowKey then W:arrowKey(key)end - end - elseif key=='space'or key=='return'then - mouseShow=true - if not isRep then - if showClickFX then SYSFX.newTap(3,mx,my)end - _triggerMouseDown(mx,my,1) - end - else - if W and W.keypress then - W:keypress(key) - end - end - end - end -end -function love.keyreleased(i) - if SCN.swapping then return end - if SCN.keyUp then SCN.keyUp(i)end -end - -function love.textedited(texts) - EDITING=texts -end -function love.textinput(texts) - WIDGET.textinput(texts) -end - ---analog sticks: -1, 0, 1 for neg, neutral, pos ---triggers: 0 for released, 1 for pressed -local jsAxisEventName={ - leftx={'leftstick_left','leftstick_right'}, - lefty={'leftstick_up','leftstick_down'}, - rightx={'rightstick_left','rightstick_right'}, - righty={'rightstick_up','rightstick_down'}, - triggerleft='triggerleft', - triggerright='triggerright' -} -local gamePadKeys={'a','b','x','y','back','guide','start','leftstick','rightstick','leftshoulder','rightshoulder','dpup','dpdown','dpleft','dpright'} -local dPadToKey={ - dpup='up', - dpdown='down', - dpleft='left', - dpright='right', - start='return', - back='escape', -} -function love.joystickadded(JS) - table.insert(jsState,{ - _id=JS:getID(), - _jsObj=JS, - leftx=0,lefty=0, - rightx=0,righty=0, - triggerleft=0,triggerright=0 - }) - MES.new('info',"Joystick added") -end -function love.joystickremoved(JS) - for i=1,#jsState do - if jsState[i]._jsObj==JS then - for j=1,#gamePadKeys do - if JS:isGamepadDown(gamePadKeys[j])then - love.gamepadreleased(JS,gamePadKeys[j]) - end - end - love.gamepadaxis(JS,'leftx',0) - love.gamepadaxis(JS,'lefty',0) - love.gamepadaxis(JS,'rightx',0) - love.gamepadaxis(JS,'righty',0) - love.gamepadaxis(JS,'triggerleft',-1) - love.gamepadaxis(JS,'triggerright',-1) - MES.new('info',"Joystick removed") - table.remove(jsState,i) - break - end - end -end -function love.gamepadaxis(JS,axis,val) - if jsState[1]and JS==jsState[1]._jsObj then - local js=jsState[1] - if axis=='leftx'or axis=='lefty'or axis=='rightx'or axis=='righty'then - local newVal=--range: [0,1] - val>.4 and 1 or - val<-.4 and -1 or - 0 - if newVal~=js[axis]then - if js[axis]==-1 then - love.gamepadreleased(JS,jsAxisEventName[axis][1]) - elseif js[axis]~=0 then - love.gamepadreleased(JS,jsAxisEventName[axis][2]) - end - if newVal==-1 then - love.gamepadpressed(JS,jsAxisEventName[axis][1]) - elseif newVal==1 then - love.gamepadpressed(JS,jsAxisEventName[axis][2]) - end - js[axis]=newVal - end - elseif axis=='triggerleft'or axis=='triggerright'then - local newVal=val>.3 and 1 or 0--range: [0,1] - if newVal~=js[axis]then - if newVal==1 then - love.gamepadpressed(JS,jsAxisEventName[axis]) - else - love.gamepadreleased(JS,jsAxisEventName[axis]) - end - js[axis]=newVal - end - end - end -end -function love.gamepadpressed(_,key) - mouseShow=false - if not SCN.swapping then - local cursorCtrl - if SCN.gamepadDown then - cursorCtrl=SCN.gamepadDown(key) - elseif SCN.keyDown then - cursorCtrl=SCN.keyDown(dPadToKey[key]or key) - else - cursorCtrl=true - end - if cursorCtrl then - key=dPadToKey[key]or key - mouseShow=true - local W=WIDGET.sel - if key=='back'then - SCN.back() - elseif key=='up'or key=='down'or key=='left'or key=='right'then - mouseShow=true - if W and W.arrowKey then W:arrowKey(key)end - elseif key=='return'then - mouseShow=true - if showClickFX then SYSFX.newTap(3,mx,my)end - _triggerMouseDown(mx,my,1) - else - if W and W.keypress then - W:keypress(key) - end - end - end - end -end -function love.gamepadreleased(_,i) - if SCN.swapping then return end - if SCN.gamepadUp then SCN.gamepadUp(i)end -end - -function love.filedropped(file) - if SCN.fileDropped then SCN.fileDropped(file)end -end -function love.directorydropped(dir) - if SCN.directoryDropped then SCN.directoryDropped(dir)end -end -local autoGCcount=0 -function love.lowmemory() - collectgarbage() - if autoGCcount<3 then - autoGCcount=autoGCcount+1 - MES.new('check',"[auto GC] low MEM 设备内存过低") - end -end - -local onResize=NULL -function love.resize(w,h) - if SCR.w==w and SCR.h==h then return end - SCR.resize(w,h) - if BG.resize then BG.resize(w,h)end - if SCN.resize then SCN.resize(w,h)end - WIDGET.resize(w,h) - FONT.reset() - onResize(w,h) -end - -local onFocus=NULL -function love.focus(f)onFocus(f)end - -local yield=coroutine.yield -local function secondLoopThread() - local mainLoop=love.run() - repeat yield()until mainLoop() -end -function love.errorhandler(msg) - if type(msg)~='string'then - msg="Unknown error" - elseif msg:find("Invalid UTF-8")and text then - msg=text.tryAnotherBuild - end - - --Generate error message - local err={"Error:"..msg} - local c=2 - for l in debug.traceback("",2):gmatch("(.-)\n")do - if c>2 then - if not l:find("boot")then - err[c]=l:gsub("^\t*","") - c=c+1 - end - else - err[2]="Traceback" - c=3 - end - end - print(table.concat(err,"\n",1,c-2)) - - --Reset something - love.audio.stop() - gc.reset() - - if LOADED and #errData<3 then - BG.set('none') - local scn=SCN and SCN.cur or"NULL" - table.insert(errData,{mes=err,scene=scn}) - - --Write messages to log file - love.filesystem.append('conf/error.log', - os.date("%Y/%m/%d %A %H:%M:%S\n").. - #errData.." crash(es) "..love.system.getOS().."-"..VERSION.string.." scene: "..scn.."\n".. - table.concat(err,"\n",1,c-2).."\n\n" - ) - - --Get screencapture - gc.captureScreenshot(function(_)errData[#errData].shot=gc.newImage(_)end) - gc.present() - - --Create a new mainLoop thread to keep game alive - local status,resume=coroutine.status,coroutine.resume - local loopThread=coroutine.create(secondLoopThread) - local res,threadErr - repeat - res,threadErr=resume(loopThread) - until status(loopThread)=='dead' - if not res then - love.errorhandler(threadErr) - return - end - else - ms.setVisible(true) - - local errorMsg - errorMsg=LOADED and - "Too many errors or fatal error occured.\nPlease restart the game."or - "An error has occurred during loading.\nError info has been created, and you can send it to the author." - while true do - love.event.pump() - for E,a,b in love.event.poll()do - if E=='quit'or a=='escape'then - return true - elseif E=='resize'then - SCR.resize(a,b) - end - end - gc_clear(.3,.5,.9) - gc_push('transform') - gc_replaceTransform(SCR.xOy) - FONT.set(100)gc_print(":(",100,0,0,1.2) - FONT.set(40)gc.printf(errorMsg,100,160,SCR.w0-100) - FONT.set(20) - gc_print(love.system.getOS().."-"..VERSION.string.." scene:"..(SCN and SCN.cur or"NULL"),100,660) - gc.printf(err[1],100,360,1260-100) - gc_print("TRACEBACK",100,450) - for i=4,#err-2 do - gc_print(err[i],100,400+20*i) - end - gc_pop() - gc_present() - love.timer.sleep(.26) - end - end -end -love.threaderror=nil - -love.draw,love.update=nil--remove default draw/update - -local devColor={ - COLOR.Z, - COLOR.lM, - COLOR.lG, - COLOR.lB, -} -local WS=WS -local WSnames={'app','user','play','stream','chat','manage'} -local wsImg={}do - local L={78,18, - {'clear',1,1,1,0}, - {'setCL',1,1,1,.3}, - {'fRect',60,0,18,18}, - } - for i=0,59 do - table.insert(L,{'setCL',1,1,1,i*.005}) - table.insert(L,{'fRect',i,0,1,18}) - end - wsImg.bottom=GC.DO(L) - wsImg.dead=GC.DO{20,20, - {'rawFT',20}, - {'setCL',1,.3,.3}, - {'mText',"X",11,-1}, - } - wsImg.connecting=GC.DO{20,20, - {'rawFT',20}, - {'setLW',3}, - {'mText',"C",11,-1}, - } - wsImg.running=GC.DO{20,20, - {'rawFT',20}, - {'setCL',.5,1,0}, - {'mText',"R",11,-1}, - } -end - -local debugInfos={ - {"Cache",gcinfo}, -} -function love.run() - local love=love - - local BG=BG - local TEXT_update,TEXT_draw=TEXT.update,TEXT.draw - local MES_update,MES_draw=MES.update,MES.draw - local WS_update=WS.update - local TASK_update=TASK.update - local SYSFX_update,SYSFX_draw=SYSFX.update,SYSFX.draw - local WIDGET_update,WIDGET_draw=WIDGET.update,WIDGET.draw - local STEP,WAIT=love.timer.step,love.timer.sleep - local FPS,MINI=love.timer.getFPS,love.window.isMinimized - local PUMP,POLL=love.event.pump,love.event.poll - - local timer,VERSION=love.timer.getTime,VERSION - - local frameTimeList={} - local lastFrame=timer() - local lastFreshPow=lastFrame - local FCT=0--Framedraw counter, from 0~99 - - love.resize(gc.getWidth(),gc.getHeight()) - - --Scene Launch - while #SCN.stack>0 do SCN.pop()end - SCN.push('quit','slowFade') - SCN.init(#errData==0 and'load'or'error') - - return function() - local _ - - local time=timer() - local dt=time-lastFrame - lastFrame=time - - --EVENT - PUMP() - for N,a,b,c,d,e in POLL()do - if love[N]then - love[N](a,b,c,d,e) - elseif N=='quit'then - onQuit() - return a or true - end - end - - --UPDATE - STEP() - if mouseShow then mouse_update(dt)end - if next(jsState)then gp_update(jsState[1],dt)end - VOC.update() - BG.update(dt) - TEXT_update(dt) - MES_update(dt) - WS_update(dt) - TASK_update(dt) - SYSFX_update(dt) - if SCN.update then SCN.update(dt)end - if SCN.swapping then SCN.swapUpdate(dt)end - WIDGET_update(dt) - - --DRAW - if not MINI()then - FCT=FCT+frameMul - if FCT>=100 then - FCT=FCT-100 - - gc_replaceTransform(SCR.origin) - gc_setColor(1,1,1) - BG.draw() - gc_replaceTransform(SCR.xOy) - if SCN.draw then SCN.draw()end - WIDGET_draw() - SYSFX_draw() - TEXT_draw() - - --Draw cursor - if mouseShow then drawCursor(time,mx,my)end - gc_replaceTransform(SCR.xOy_ul) - MES_draw() - gc_replaceTransform(SCR.origin) - --Draw power info. - if showPowerInfo then - gc_setColor(1,1,1) - gc_draw(infoCanvas,SCR.safeX,0,0,SCR.k) - end - - --Draw scene swapping animation - if SCN.swapping then - gc_setColor(1,1,1) - _=SCN.stat - _.draw(_.time) - end - gc_replaceTransform(SCR.xOy_d) - --Draw Version string - gc_setColor(.9,.9,.9,.42) - FONT.set(20) - mStr(VERSION.string,0,-30) - gc_replaceTransform(SCR.xOy_dl) - local safeX=SCR.safeX/SCR.k - - --Draw FPS - FONT.set(15) - gc_setColor(1,1,1) - gc_print(FPS(),safeX+5,-20) - - --Debug info. - if devMode then - --Debug infos at left-down - gc_setColor(devColor[devMode]) - - --Text infos - for i=1,#debugInfos do - gc_print(debugInfos[i][1],safeX+5,-20-20*i) - gc_print(debugInfos[i][2](),safeX+62.6,-20-20*i) - end - - --Update & draw frame time - table.insert(frameTimeList,1,dt)table.remove(frameTimeList,126) - gc_setColor(1,1,1,.3) - for i=1,#frameTimeList do - gc.rectangle('fill',150+2*i,-20,2,-frameTimeList[i]*4000) - end - - --Cursor pos disp - gc_replaceTransform(SCR.origin) - local x,y=SCR.xOy:transformPoint(mx,my) - gc_setLineWidth(1) - gc_line(x,0,x,SCR.h) - gc_line(0,y,SCR.w,y) - local t=math.floor(mx+.5)..","..math.floor(my+.5) - gc.setColor(COLOR.D) - gc_print(t,x+1,y) - gc_print(t,x+1,y-1) - gc_print(t,x+2,y-1) - gc_setColor(COLOR.Z) - gc_print(t,x+2,y) - - gc_replaceTransform(SCR.xOy_dr) - --Websocket status - for i=1,6 do - local status=WS.status(WSnames[i]) - gc_setColor(1,1,1) - gc.draw(wsImg.bottom,-79,20*i-139) - if status=='dead'then - gc_draw(wsImg.dead,-20,20*i-140) - elseif status=='connecting'then - gc_setColor(1,1,1,.5+.3*math.sin(time*6.26)) - gc_draw(wsImg.connecting,-20,20*i-140) - elseif status=='running'then - gc_draw(wsImg.running,-20,20*i-140) - end - local t1,t2,t3=WS.getTimers(WSnames[i]) - gc_setColor(.9,.9,.9,t1)gc.rectangle('fill',-60,20*i-122,-16,-16) - gc_setColor(.3,1,.3,t2)gc.rectangle('fill',-42,20*i-122,-16,-16) - gc_setColor(1,.2,.2,t3)gc.rectangle('fill',-24,20*i-122,-16,-16) - end - end - gc_present() - - --SPEED UPUPUP! - if discardCanvas then gc_discard()end - end - end - - --Fresh power info. - if time-lastFreshPow>2.6 then - if showPowerInfo then - updatePowerInfo() - lastFreshPow=time - end - if gc.getWidth()~=SCR.w or gc.getHeight()~=SCR.h then - love.resize(gc.getWidth(),gc.getHeight()) - end - end - - --Slow devmode - if devMode then - if devMode==3 then - WAIT(.1) - elseif devMode==4 then - WAIT(.5) - end - end - - _=timer()-lastFrame - if _= math.huge then - error("unexpected number value '" .. tostring(val) .. "'") - end - return string.format("%.14g", val) -end - -local type_func_map = { - ['nil'] = encode_nil, - ['table'] = encode_table, - ['string'] = encode_string, - ['number'] = encode_number, - ['boolean'] = tostring -} - -_encode = function(val, stack) - local t = type(val) - local f = type_func_map[t] - if f then return f(val, stack) end - error("unexpected type '" .. t .. "'") -end - -json.encode=_encode - -------------------------------------------------------------------------------- --- Decode -------------------------------------------------------------------------------- - -local parse - -local function create_set(...) - local res = {} - for i = 1, select("#", ...) do res[select(i, ...)] = true end - return res -end - -local space_chars = create_set(" ", "\t", "\r", "\n") -local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") -local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") -local literals = create_set("true", "false", "null") - -local literal_map = {["true"] = true, ["false"] = false, ["null"] = nil} - -local function next_char(str, idx, set, negate) - for i = idx, #str do if set[str:sub(i, i)] ~= negate then return i end end - return #str + 1 -end - -local function decode_error(str, idx, msg) - local line_count = 1 - local col_count = 1 - for i = 1, idx - 1 do - col_count = col_count + 1 - if str:sub(i, i) == "\n" then - line_count = line_count + 1 - col_count = 1 - end - end - error(string.format("%s at line %d col %d", msg, line_count, col_count)) -end - -local function codepoint_to_utf8(n) - -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa - local f = bit.rshift - if n <= 0x7f then - return char(n) - elseif n <= 0x7ff then - return char(f(n, 6) + 192, n % 64 + 128) - elseif n <= 0xffff then - return char(f(n, 12) + 224, f(n % 4096, 6) + 128, n % 64 + 128) - elseif n <= 0x10ffff then - return char(f(n, 18) + 240, f(n % 262144, 12) + 128, f(n % 4096, 6) + 128, n % 64 + 128) - end - error(string.format("invalid unicode codepoint '%x'", n)) -end - -local function parse_unicode_escape(s) - local n1 = tonumber(s:sub(1, 4), 16) - local n2 = tonumber(s:sub(7, 10), 16) - -- Surrogate pair? - if n2 then - return - codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) - else - return codepoint_to_utf8(n1) - end -end - -local function parse_string(str, i) - local res = "" - local j = i + 1 - local k = j - - while j <= #str do - local x = str:byte(j) - - if x < 32 then - decode_error(str, j, "control character in string") - - elseif x == 92 then -- `\`: Escape - res = res .. str:sub(k, j - 1) - j = j + 1 - local c = str:sub(j, j) - if c == "u" then - local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1) or - str:match("^%x%x%x%x", j + 1) or - decode_error(str, j - 1, - "invalid unicode escape in string") - res = res .. parse_unicode_escape(hex) - j = j + #hex - else - if not escape_chars[c] then - decode_error(str, j - 1, - "invalid escape char '" .. c .. "' in string") - end - res = res .. escape_char_map_inv[c] - end - k = j + 1 - - elseif x == 34 then -- `"`: End of string - res = res .. str:sub(k, j - 1) - return res, j + 1 - end - - j = j + 1 - end - - decode_error(str, i, "expected closing quote for string") -end - -local function parse_number(str, i) - local x = next_char(str, i, delim_chars) - local s = str:sub(i, x - 1) - local n = tonumber(s) - if not n then decode_error(str, i, "invalid number '" .. s .. "'") end - return n, x -end - -local function parse_literal(str, i) - local x = next_char(str, i, delim_chars) - local word = str:sub(i, x - 1) - if not literals[word] then - decode_error(str, i, "invalid literal '" .. word .. "'") - end - return literal_map[word], x -end - -local function parse_array(str, i) - local res = {} - local n = 1 - i = i + 1 - while 1 do - local x - i = next_char(str, i, space_chars, true) - -- Empty / end of array? - if str:sub(i, i) == "]" then - i = i + 1 - break - end - -- Read token - x, i = parse(str, i) - res[n] = x - n = n + 1 - -- Next token - i = next_char(str, i, space_chars, true) - local chr = str:sub(i, i) - i = i + 1 - if chr == "]" then break end - if chr ~= "," then decode_error(str, i, "expected ']' or ','") end - end - return res, i -end - -local function parse_object(str, i) - local res = {} - i = i + 1 - while 1 do - local key, val - i = next_char(str, i, space_chars, true) - -- Empty / end of object? - if str:sub(i, i) == "}" then - i = i + 1 - break - end - -- Read key - if str:sub(i, i) ~= '"' then - decode_error(str, i, "expected string for key") - end - key, i = parse(str, i) - -- Read ':' delimiter - i = next_char(str, i, space_chars, true) - if str:sub(i, i) ~= ":" then - decode_error(str, i, "expected ':' after key") - end - i = next_char(str, i + 1, space_chars, true) - -- Read value - val, i = parse(str, i) - -- Set - res[key] = val - -- Next token - i = next_char(str, i, space_chars, true) - local chr = str:sub(i, i) - i = i + 1 - if chr == "}" then break end - if chr ~= "," then decode_error(str, i, "expected '}' or ','") end - end - return res, i -end - -local char_func_map = { - ['"'] = parse_string, - ["0"] = parse_number, - ["1"] = parse_number, - ["2"] = parse_number, - ["3"] = parse_number, - ["4"] = parse_number, - ["5"] = parse_number, - ["6"] = parse_number, - ["7"] = parse_number, - ["8"] = parse_number, - ["9"] = parse_number, - ["-"] = parse_number, - ["t"] = parse_literal, - ["f"] = parse_literal, - ["n"] = parse_literal, - ["["] = parse_array, - ["{"] = parse_object -} - -function parse(str, idx) - local chr = str:sub(idx, idx) - local f = char_func_map[chr] - if f then return f(str, idx) end - decode_error(str, idx, "unexpected character '" .. chr .. "'") -end - -function json.decode(str) - if type(str) ~= 'string' then - error("expected argument of type string, got " .. type(str)) - end - local res, idx = parse(str, next_char(str, 1, space_chars, true)) - idx = next_char(str, idx, space_chars, true) - if idx <= #str then decode_error(str, idx, "trailing garbage") end - return res -end -return json diff --git a/Zframework/languages.lua b/Zframework/languages.lua deleted file mode 100644 index ad40ce35e..000000000 --- a/Zframework/languages.lua +++ /dev/null @@ -1,57 +0,0 @@ -local LANG={} ---ONLY FIRST CALL MAKE SENSE ---Create LANG.get() and LANG.addScene() -function LANG.init(defaultLang,langList,publicText,pretreatFunc) - local function _langFallback(T0,T) - for k,v in next,T0 do - if type(v)=='table'and not v.refuseCopy then--refuseCopy: just copy pointer, not contents - if not T[k]then T[k]={}end - if type(T[k])=='table'then - _langFallback(v,T[k]) - end - elseif not T[k]then - T[k]=v - end - end - end - - --Set public text - if publicText then - for _,L in next,langList do - for key,list in next,publicText do L[key]=list end - end - end - - --Fallback to default language - for name,L in next,langList do - if name~=defaultLang then - _langFallback(langList[L.fallback or defaultLang],L) - end - end - - --Custom pretreatment for each language - if pretreatFunc then - for _,L in next,langList do - pretreatFunc(L) - end - end - - function LANG.get(l) - if not langList[l]then - LOG("Wrong language: "..tostring(l)) - l=defaultLang - end - return langList[l] - end - - function LANG.addScene(name) - for _,L in next,langList do - if L.WidgetText and not L.WidgetText[name]then - L.WidgetText[name]={} - end - end - end - - function LANG.init()end -end -return LANG diff --git a/Zframework/light/init.lua b/Zframework/light/init.lua deleted file mode 100644 index 712139692..000000000 --- a/Zframework/light/init.lua +++ /dev/null @@ -1,86 +0,0 @@ ---LIGHT MODULE (Optimized by MrZ, Original on github/LÖVE community/simple-love-lights) ---Heavily based on mattdesl's libGDX implementation: ---https://github.com/mattdesl/lwjgl-basics/wiki/2D-Pixel-Perfect-Shadows -local gc=love.graphics -local clear,gc_translate=gc.clear,gc.translate -local gc_setCanvas,gc_setShader=gc.setCanvas,gc.setShader -local gc_setColor,gc_draw=gc.setColor,gc.draw - -local shadowMapShader=gc.newShader('Zframework/light/shadowMap.glsl')--Shader for caculating the 1D shadow map. -local lightRenderShader=gc.newShader('Zframework/light/lightRender.glsl')--Shader for rendering blurred lights and shadows. -local Lights={}--Lightsource objects -local function move(L,x,y) - L.x,L.y=x,y -end -local function setPow(L,pow) - L.size=pow -end -local function drawLight(L) - local s=L.size - - --Initialization - gc_setCanvas(L.blackCanvas)clear() - gc_setCanvas(L.shadowCanvas)clear() - gc_setCanvas(L.renderCanvas)clear() - lightRenderShader:send('xresolution',s) - shadowMapShader:send('yresolution',s) - - --Get up-left of light - local X=L.x-s*.5 - local Y=L.y-s*.5 - - --Render solid - gc_translate(-X,-Y) - L.blackCanvas:renderTo(L.blackFn) - gc_translate(X,Y) - - --Render shade canvas by solid - gc_setShader(shadowMapShader) - gc_setCanvas(L.shadowCanvas) - gc_draw(L.blackCanvas) - - --Render light canvas by shade - gc_setShader(lightRenderShader) - gc_setCanvas(L.renderCanvas) - gc_draw(L.shadowCanvas,0,0,0,1,s) - - --Ready to final render - gc_setShader()gc_setCanvas()gc.setBlendMode('add') - - --Render to screen - gc_draw(L.renderCanvas,X,Y+s,0,1,-1) - - --Reset - gc.setBlendMode('alpha') -end - -local LIGHT={} -function LIGHT.draw() - gc_setColor(1,1,1) - for i=1,#Lights do - drawLight(Lights[i]) - end -end -function LIGHT.clear() - for i=1,#Lights do - Lights[i].blackCanvas:release() - Lights[i].shadowCanvas:release() - Lights[i].renderCanvas:release() - Lights[i]=nil - end -end -function LIGHT.add(x,y,radius,solidFunc) - local id=#Lights+1 - Lights[id]={ - id=id, - x=x,y=y,size=radius, - blackCanvas=gc.newCanvas(radius,radius),--Solid canvas - shadowCanvas=gc.newCanvas(radius,1),--1D vis-depth canvas - renderCanvas=gc.newCanvas(radius,radius),--Light canvas - blackFn=solidFunc,--Solid draw function - - move=move, - setPow=setPow, - } -end -return LIGHT diff --git a/Zframework/light/lightRender.glsl b/Zframework/light/lightRender.glsl deleted file mode 100644 index 7d3efe70d..000000000 --- a/Zframework/light/lightRender.glsl +++ /dev/null @@ -1,29 +0,0 @@ -#define PI 3.14159 -extern float xresolution; -// Sample from 1D vis-depth map -float samp(vec2 coord,float r,Image u_texture){ - return step(r,Texel(u_texture,coord).r); -} -vec4 effect(vec4 color,Image tex,vec2 tex_coords,vec2 screen_coords){ - // Cartesian to polar, y of 1D sample is always 0 - vec2 norm=tex_coords.st*2.-1.; - vec2 tc=vec2((atan(norm.y,norm.x)+PI)/(2.*PI),0.); - float r=length(norm); - - // Enlarge blur parameter by distance, light scattering simulation - float blur=(1./xresolution)*smoothstep(0.3,1.,r); - - // Simple Gaussian blur - float sum=// Brightness(0~1) - samp(vec2(tc.x-3.*blur,tc.y),r,tex)*0.1 - +samp(vec2(tc.x-2.*blur,tc.y),r,tex)*0.13 - +samp(vec2(tc.x-1.*blur,tc.y),r,tex)*0.17 - - +samp(tc,r,tex)*0.2// The center tex coord, which gives us hard shadows. - +samp(vec2(tc.x+1.*blur,tc.y),r,tex)*0.17 - +samp(vec2(tc.x+2.*blur,tc.y),r,tex)*0.13 - +samp(vec2(tc.x+3.*blur,tc.y),r,tex)*0.1; - - // Multiply the distance to get a soft fading - return vec4(vec3(1.),sum*smoothstep(1.,0.,r)); -} diff --git a/Zframework/light/shadowMap.glsl b/Zframework/light/shadowMap.glsl deleted file mode 100644 index 54809c799..000000000 --- a/Zframework/light/shadowMap.glsl +++ /dev/null @@ -1,20 +0,0 @@ -#define PI 3.14 -extern float yresolution; -vec4 effect(vec4 color,Image tex,vec2 tex_coords,vec2 screen_coords){ - // Iterate through the occluder map's y-axis. - for(float y=0.;y0.1 - )return vec4(vec3(y/yresolution),1.);// Collision check, alpha>0.1 means transparent - } - return vec4(1.);// Return max distance 1 -} diff --git a/Zframework/log.lua b/Zframework/log.lua deleted file mode 100644 index f1cec3cdb..000000000 --- a/Zframework/log.lua +++ /dev/null @@ -1,20 +0,0 @@ -local ins=table.insert - -local logs={os.date("Techmino logs %Y/%m/%d %A")} - -local function log(message) - ins(logs,os.date("[%H:%M:%S] ")..message) -end - -local LOG=setmetatable({logs=logs},{ - __call=function(_,message) - print(message) - log(message) - end -}) - -function LOG.read() - return table.concat(logs,"\n") -end - -return LOG diff --git a/Zframework/mathExtend.lua b/Zframework/mathExtend.lua deleted file mode 100644 index 5f3db7c39..000000000 --- a/Zframework/mathExtend.lua +++ /dev/null @@ -1,37 +0,0 @@ -local MATH={}for k,v in next,math do MATH[k]=v end - -local rnd=math.random - -MATH.tau=2*math.pi - -function MATH.sign(a) - return a>0 and 1 or a<0 and -1 or 0 -end - -function MATH.roll(chance) - return rnd()<(chance or .5) -end - -function MATH.coin(a,b) - if rnd()<.5 then - return a - else - return b - end -end - -function MATH.interval(v,low,high) - if v<=low then - return low - elseif v>=high then - return high - else - return v - end -end - -function MATH.expApproach(a,b,k) - return b+(a-b)*2.718281828459045^-k -end - -return MATH \ No newline at end of file diff --git a/Zframework/message.lua b/Zframework/message.lua deleted file mode 100644 index c2bbafa03..000000000 --- a/Zframework/message.lua +++ /dev/null @@ -1,148 +0,0 @@ -local gc=love.graphics -local gc_push,gc_pop=gc.push,gc.pop -local gc_translate,gc_setColor,gc_draw=gc.translate,gc.setColor,gc.draw - -local ins,rem=table.insert,table.remove -local max=math.max - -local mesList={} -local mesIcon={ - check=GC.DO{40,40, - {'setLW',10}, - {'setCL',0,0,0}, - {'line',4,19,15,30,36,9}, - {'setLW',6}, - {'setCL',.7,1,.6}, - {'line',5,20,15,30,35,10}, - }, - info=GC.DO{40,40, - {'setCL',.2,.25,.85}, - {'fCirc',20,20,15}, - {'setCL',1,1,1}, - {'setLW',2}, - {'dCirc',20,20,15}, - {'fRect',18,11,4,4}, - {'fRect',18,17,4,12}, - }, - broadcast=GC.DO{40,40, - {'setCL',1,1,1}, - {'fRect',2,4,36,26,3}, - {'fPoly',2,27,2,37,14,25}, - {'setCL',.5,.5,.5}, - {'fRect',6,11,4,4,1},{'fRect',14,11,19,4,1}, - {'fRect',6,19,4,4,1},{'fRect',14,19,19,4,1}, - }, - warn=GC.DO{40,40, - {'setCL',.95,.83,.4}, - {'fPoly',20.5,1,0,38,40,38}, - {'setCL',0,0,0}, - {'dPoly',20.5,1,0,38,40,38}, - {'fRect',17,10,7,18,2}, - {'fRect',17,29,7,7,2}, - {'setCL',1,1,1}, - {'fRect',18,11,5,16,2}, - {'fRect',18,30,5,5,2}, - }, - error=GC.DO{40,40, - {'setCL',.95,.3,.3}, - {'fCirc',20,20,19}, - {'setCL',0,0,0}, - {'dCirc',20,20,19}, - {'setLW',6}, - {'line',10.2,10.2,29.8,29.8}, - {'line',10.2,29.8,29.8,10.2}, - {'setLW',4}, - {'setCL',1,1,1}, - {'line',11,11,29,29}, - {'line',11,29,29,11}, - }, - music=GC.DO{40,40, - {'setLW',2}, - {'dRect',1,3,38,34,3}, - {'setLW',4}, - {'line',21,26,21,10,28,10}, - {'fElps',17,26,6,5}, - }, -} - -local MES={} -local backColors={ - check={.3,.6,.3,.7}, - broadcast={.3,.3,.6,.8}, - warn={.4,.4,.2,.9}, - error={.4,.2,.2,.9}, - music={.2,.4,.4,.9}, -} -function MES.new(icon,str,time) - local backColor={.5,.5,.5,.7} - if type(icon)=='string'then - backColor=backColors[icon]or backColor - icon=mesIcon[icon] - end - local t=gc.newText(FONT.get(30),str) - local w=math.max(t:getWidth()+(icon and 45 or 5),200)+15 - local h=math.max(t:getHeight(),46)+2 - local L={w,h, - {'clear',backColor}, - {'setCL',.7,.7,.7}, - {'setLW',2}, - {'dRect',1,1,w-2,h-2}, - {'setCL',1,1,1}, - } - if icon then - ins(L,{'draw',icon,4,4,nil,40/icon:getWidth(),40/icon:getHeight()}) - end - ins(L,{'mDrawY',t,icon and 50 or 10,h/2}) - - ins(mesList,{ - startTime=.5, - endTime=.5, - time=time or 3, - canvas=GC.DO(L), - width=w,height=h, - scale=h>400 and 1/math.min(h/400,2.6)or 1 - }) -end - -function MES.update(dt) - for i=#mesList,1,-1 do - local m=mesList[i] - if m.startTime>0 then - m.startTime=max(m.startTime-dt,0) - elseif m.time>0 then - m.time=max(m.time-dt,0) - elseif m.endTime>0 then - m.endTime=m.endTime-dt - else - rem(mesList,i) - end - end -end - -function MES.draw() - gc_push('transform') - if #mesList>0 then - gc_translate(SCR.safeX,30) - for i=1,#mesList do - local m=mesList[i] - gc_setColor(1,1,1,2*(m.endTime-m.startTime)) - gc_draw(m.canvas,40-80*(m.endTime+m.startTime),0,nil,m.scale) - gc_translate(0,m.height*m.scale+2) - end - end - gc_pop() -end - -function MES.traceback() - local mes= - debug.traceback('',1) - :gsub(': in function',', in') - :gsub(':',' ') - :gsub('\t','') - MES.new('error',mes:sub( - mes:find("\n",2)+1, - mes:find("\n%[C%], in 'xpcall'") - ),5) -end - -return MES diff --git a/Zframework/profile.lua b/Zframework/profile.lua deleted file mode 100644 index 65266f604..000000000 --- a/Zframework/profile.lua +++ /dev/null @@ -1,157 +0,0 @@ -local clock=os.clock - -local profile={} - -local _labeled={} -- function labels -local _defined={} -- function definitions -local _tcalled={} -- time of last call -local _telapsed={}-- total execution time -local _ncalls={} -- number of calls -local _internal={}-- list of internal profiler functions - -local getInfo=debug.getinfo -function profile.hooker(event,line,info) - info=info or getInfo(2,'fnS') - local f=info.func - if _internal[f]then return end-- ignore the profiler itself - if info.name then _labeled[f]=info.name end-- get the function name if available - -- find the line definition - if not _defined[f]then - _defined[f]=info.short_src..":"..info.linedefined - _ncalls[f]=0 - _telapsed[f]=0 - end - if _tcalled[f]then - local dt=clock()-_tcalled[f] - _telapsed[f]=_telapsed[f]+dt - _tcalled[f]=nil - end - if event=='tail call'then - local prev=getInfo(3,'fnS') - profile.hooker('return',line,prev) - profile.hooker('call',line,info) - elseif event=='call'then - _tcalled[f]=clock() - else - _ncalls[f]=_ncalls[f]+1 - end -end - ---- Starts collecting data. -function profile.start() - if jit then - jit.off() - jit.flush() - end - debug.sethook(profile.hooker,'cr') -end - ---- Stops collecting data. -function profile.stop() - debug.sethook() - for f in next,_tcalled do - local dt=clock()-_tcalled[f] - _telapsed[f]=_telapsed[f]+dt - _tcalled[f]=nil - end - -- merge closures - local lookup={} - for f,d in next,_defined do - local id=(_labeled[f]or"?")..d - local f2=lookup[id] - if f2 then - _ncalls[f2]=_ncalls[f2]+(_ncalls[f]or 0) - _telapsed[f2]=_telapsed[f2]+(_telapsed[f]or 0) - _defined[f],_labeled[f]=nil,nil - _ncalls[f],_telapsed[f]=nil,nil - else - lookup[id]=f - end - end - collectgarbage() -end - ---- Resets all collected data. -function profile.reset() - for f in next,_ncalls do - _ncalls[f]=0 - _telapsed[f]=0 - _tcalled[f]=nil - end - collectgarbage() -end - -local function _comp(a,b) - local dt=_telapsed[b]-_telapsed[a] - return dt==0 and _ncalls[b]<_ncalls[a]or dt<0 -end - ---- Iterates all functions that have been called since the profile was started. -function profile.query(limit) - local t={} - for f,n in next,_ncalls do - if n>0 then - t[#t+1]=f - end - end - table.sort(t,_comp) - - if limit then while #t>limit do table.remove(t)end end - - for i,f in ipairs(t)do - local dt=0 - if _tcalled[f]then - dt=clock()-_tcalled[f] - end - t[i]={i,_labeled[f]or"?",math.floor((_telapsed[f]+dt)*1e6)/1e6,_ncalls[f],_defined[f]} - end - return t -end - -local cols={3,20,8,6,32} -function profile.report(n) - local out={} - local report=profile.query(n) - for i,row in ipairs(report)do - for j=1,5 do - local s=tostring(row[j]) - local l1,l2=#s,cols[j] - if l1l2 then - s=s:sub(l1-l2+1,l1) - end - row[j]=s - end - out[i]=table.concat(row," | ") - end - - local row=" +-----+----------------------+----------+--------+----------------------------------+ \n" - local col=" | # | Function | Time | Calls | Code | \n" - local sz=row..col..row - if #out>0 then - sz=sz.." | "..table.concat(out," | \n | ").." | \n" - end - return "\n"..sz..row -end - -local switch=false -function profile.switch() - switch=not switch - if not switch then - profile.stop() - love.system.setClipboardText(profile.report()) - profile.reset() - return false - else - profile.start() - return true - end -end - --- store all internal profiler functions -for _,v in next,profile do - _internal[v]=type(v)=='function' -end - -return profile diff --git a/Zframework/require.lua b/Zframework/require.lua deleted file mode 100644 index d1b1afae7..000000000 --- a/Zframework/require.lua +++ /dev/null @@ -1,33 +0,0 @@ -package.cpath=package.cpath..';'..SAVEDIR..'/lib/lib?.so;'..'?.dylib' -local loaded={} -return function(libName) - local require=require - if love.system.getOS()=='OS X'then - require=package.loadlib(libName..'.dylib','luaopen_'..libName) - libname=nil - elseif love.system.getOS()=='Android'then - if not loaded[libName]then - local platform=(function() - local p=io.popen('uname -m') - local arch=p:read('*a'):lower() - p:close() - if arch:find('v8')or arch:find('64')then - return'arm64-v8a' - else - return'armeabi-v7a' - end - end)() - love.filesystem.write( - 'lib/libCCloader.so', - love.filesystem.read('data','libAndroid/'..platform..'/libCCloader.so') - ) - loaded[libName]=true - end - end - local success,res=pcall(require,libName) - if success and res then - return res - else - MES.new('error',"Cannot load "..libName..": "..res) - end -end diff --git a/Zframework/scene.lua b/Zframework/scene.lua deleted file mode 100644 index e990c71ba..000000000 --- a/Zframework/scene.lua +++ /dev/null @@ -1,210 +0,0 @@ -local gc=love.graphics -local abs=math.abs - -local scenes={} - -local SCN={ - mainTouchID=nil, --First touching ID(userdata) - cur='NULL', --Current scene name - swapping=false, --If Swapping - stat={ - tar=false, --Swapping target - style=false, --Swapping style - changeTime=false,--Loading point - time=false, --Full swap time - draw=false, --Swap draw func - }, - stack={},--Scene stack - prev=false, - args={},--Arguments from previous scene - - scenes=scenes, - - --Events - update=false, - draw=false, - mouseClick=false, - touchClick=false, - mouseDown=false, - mouseMove=false, - mouseUp=false, - wheelMoved=false, - touchDown=false, - touchUp=false, - touchMove=false, - keyDown=false, - keyUp=false, - gamepadDown=false, - gamepadUp=false, - fileDropped=false, - directoryDropped=false, - resize=false, - socketRead=false, -}--Scene datas, returned - -function SCN.add(name,scene) - scenes[name]=scene - if scene.widgetList then - setmetatable(scene.widgetList,WIDGET.indexMeta) - end -end - -function SCN.swapUpdate(dt) - local S=SCN.stat - S.time=S.time-dt - if S.time=S.changeTime then - --Scene swapped this frame - SCN.prev=SCN.cur - SCN.init(S.tar) - SCN.mainTouchID=nil - end - if S.time<0 then - SCN.swapping=false - end -end -function SCN.init(s) - love.keyboard.setTextInput(false) - - local S=scenes[s] - SCN.cur=s - - WIDGET.setScrollHeight(S.widgetScrollHeight) - WIDGET.setWidgetList(S.widgetList) - SCN.sceneInit=S.sceneInit - SCN.sceneBack=S.sceneBack - SCN.mouseDown=S.mouseDown - SCN.mouseMove=S.mouseMove - SCN.mouseUp=S.mouseUp - SCN.mouseClick=S.mouseClick - SCN.wheelMoved=S.wheelMoved - SCN.touchDown=S.touchDown - SCN.touchUp=S.touchUp - SCN.touchMove=S.touchMove - SCN.touchClick=S.touchClick - SCN.keyDown=S.keyDown - SCN.keyUp=S.keyUp - SCN.gamepadDown=S.gamepadDown - SCN.gamepadUp=S.gamepadUp - SCN.fileDropped=S.fileDropped - SCN.directoryDropped=S.directoryDropped - SCN.resize=S.resize - SCN.socketRead=S.socketRead - SCN.update=S.update - SCN.draw=S.draw - if S.sceneInit then - S.sceneInit() - end -end -function SCN.push(tar,style) - if not SCN.swapping then - local m=#SCN.stack - SCN.stack[m+1]=tar or SCN.cur - SCN.stack[m+2]=style or'fade' - end -end -function SCN.pop() - local s=SCN.stack - s[#s],s[#s-1]=nil -end - -local swap={ - none={ - duration=0,changeTime=0, - draw=function()end - }, - flash={ - duration=.16,changeTime=.08, - draw=function()gc.clear(1,1,1)end - }, - fade={ - duration=.5,changeTime=.25, - draw=function(t) - t=t>.25 and 2-t*4 or t*4 - gc.setColor(0,0,0,t) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - end - }, - fade_togame={ - duration=2,changeTime=.5, - draw=function(t) - t=t>.5 and(2-t)/1.5 or t*.5 - gc.setColor(0,0,0,t) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - end - }, - slowFade={ - duration=3,changeTime=1.5, - draw=function(t) - t=t>1.5 and (3-t)/1.5 or t/1.5 - gc.setColor(0,0,0,t) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - end - }, - swipeL={ - duration=.5,changeTime=.25, - draw=function(t) - t=t*2 - gc.setColor(.1,.1,.1,1-abs(t-.5)) - t=t*t*(3-2*t)*2-1 - gc.rectangle('fill',t*SCR.w,0,SCR.w,SCR.h) - end - }, - swipeR={ - duration=.5,changeTime=.25, - draw=function(t) - t=t*2 - gc.setColor(.1,.1,.1,1-abs(t-.5)) - t=t*t*(2*t-3)*2+1 - gc.rectangle('fill',t*SCR.w,0,SCR.w,SCR.h) - end - }, - swipeD={ - duration=.5,changeTime=.25, - draw=function(t) - t=t*2 - gc.setColor(.1,.1,.1,1-abs(t-.5)) - t=t*t*(2*t-3)*2+1 - gc.rectangle('fill',0,t*SCR.h,SCR.w,SCR.h) - end - }, -}--Scene swapping animations -function SCN.swapTo(tar,style,...)--Parallel scene swapping, cannot back - if scenes[tar]then - if not SCN.swapping and tar~=SCN.cur then - style=style or'fade' - SCN.swapping=true - SCN.args={...} - local S=SCN.stat - S.tar,S.style=tar,style - S.time=swap[style].duration - S.changeTime=swap[style].changeTime - S.draw=swap[style].draw - end - else - MES.new('warn',"No Scene: "..tar) - end -end -function SCN.go(tar,style,...)--Normal scene swapping, can back - if scenes[tar]then - SCN.push() - SCN.swapTo(tar,style,...) - else - MES.new('warn',"No Scene: "..tar) - end -end -function SCN.back(...) - if SCN.swapping then return end - - --Leave scene - if SCN.sceneBack then - SCN.sceneBack() - end - - --Poll&Back to previous Scene - local m=#SCN.stack - if m>0 then - SCN.swapTo(SCN.stack[m-1],SCN.stack[m],...) - SCN.stack[m],SCN.stack[m-1]=nil - end -end -return SCN diff --git a/Zframework/screen.lua b/Zframework/screen.lua deleted file mode 100644 index cf86cbd42..000000000 --- a/Zframework/screen.lua +++ /dev/null @@ -1,73 +0,0 @@ -local SCR={ - w0=1280,h0=720, --Default Screen Size - x=0,y=0, --Up-left Coord on screen - cx=0,cy=0, --Center Coord on screen (Center X/Y) - ex=0,ey=0, --Down-right Coord on screen (End X/Y) - w=0,h=0, --Fullscreen w/h for graphic functions - W=0,H=0, --Fullscreen w/h for shader - safeX=0,safeY=0,--Safe area - safeW=0,safeH=0,--Safe area - rad=0, --Radius - k=1, --Scale size - dpi=1, --DPI from gc.getDPIScale() - - --Screen transformation objects - origin=love.math.newTransform(), - xOy=love.math.newTransform(), - xOy_m=love.math.newTransform(), - xOy_ul=love.math.newTransform(), - xOy_u=love.math.newTransform(), - xOy_ur=love.math.newTransform(), - xOy_l=love.math.newTransform(), - xOy_r=love.math.newTransform(), - xOy_dl=love.math.newTransform(), - xOy_d=love.math.newTransform(), - xOy_dr=love.math.newTransform(), -} -function SCR.setSize(w,h) - SCR.w0,SCR.h0=w,h -end -function SCR.resize(w,h) - SCR.w,SCR.h,SCR.dpi=w,h,love.graphics.getDPIScale() - SCR.W,SCR.H=SCR.w*SCR.dpi,SCR.h*SCR.dpi - SCR.r=h/w - SCR.rad=(w^2+h^2)^.5 - - SCR.x,SCR.y=0,0 - if SCR.r>=SCR.h0/SCR.w0 then - SCR.k=w/SCR.w0 - SCR.y=(h-SCR.h0*SCR.k)/2 - else - SCR.k=h/SCR.h0 - SCR.x=(w-SCR.w0*SCR.k)/2 - end - SCR.cx,SCR.cy=SCR.w/2,SCR.h/2 - SCR.ex,SCR.ey=SCR.w-SCR.x,SCR.h-SCR.y - SCR.safeX,SCR.safeY,SCR.safeW,SCR.safeH=love.window.getSafeArea() - - SCR.origin:setTransformation(0,0) - SCR.xOy:setTransformation(SCR.x,SCR.y,0,SCR.k) - SCR.xOy_m:setTransformation(w/2,h/2,0,SCR.k) - SCR.xOy_ul:setTransformation(0,0,0,SCR.k) - SCR.xOy_u:setTransformation(w/2,0,0,SCR.k) - SCR.xOy_ur:setTransformation(w,0,0,SCR.k) - SCR.xOy_l:setTransformation(0,h/2,0,SCR.k) - SCR.xOy_r:setTransformation(w,h/2,0,SCR.k) - SCR.xOy_dl:setTransformation(0,h,0,SCR.k) - SCR.xOy_d:setTransformation(w/2,h,0,SCR.k) - SCR.xOy_dr:setTransformation(w,h,0,SCR.k) -end -function SCR.info() - return{ - ("w0,h0 : %d, %d"):format(SCR.w0,SCR.h0), - ("x,y : %d, %d"):format(SCR.x,SCR.y), - ("cx,cy : %d, %d"):format(SCR.cx,SCR.cy), - ("ex,ey : %d, %d"):format(SCR.ex,SCR.ey), - ("w,h : %d, %d"):format(SCR.w,SCR.h), - ("W,H : %d, %d"):format(SCR.W,SCR.H), - ("safeX,safeY : %d, %d"):format(SCR.safeX,SCR.safeY), - ("safeW,safeH : %d, %d"):format(SCR.safeW,SCR.safeH), - ("k,dpi,rad : %.2f, %d, %.2f"):format(SCR.k,SCR.dpi,SCR.rad), - } -end -return SCR diff --git a/Zframework/sfx.lua b/Zframework/sfx.lua deleted file mode 100644 index 8f5c5c20f..000000000 --- a/Zframework/sfx.lua +++ /dev/null @@ -1,170 +0,0 @@ -local type,rem=type,table.remove -local int,rnd=math.floor,math.random -local interval=MATH.interval - -local sfxList={} -local packSetting={} -local Sources={} -local volume=1 -local stereo=1 - -local noteVal={ - C=1,c=1, - D=3,d=3, - E=5,e=5, - F=6,f=6, - G=8,g=8, - A=10,a=10, - B=12,b=12, -} -local noteName={'C','C#','D','D#','E','F','F#','G','G#','A','A#','B'} -local function _getTuneHeight(tune) - local octave=tonumber(tune:sub(-1,-1)) - if octave then - local tuneHeight=noteVal[tune:sub(1,1)] - if tuneHeight then - tuneHeight=tuneHeight+(octave-1)*12 - local s=tune:sub(2,2) - if s=='s'or s=='#'then - tuneHeight=tuneHeight+1 - elseif s=='f'or s=='b'then - tuneHeight=tuneHeight-1 - end - return tuneHeight - end - end -end - -local SFX={} - -function SFX.init(list) - assert(type(list)=='table',"Initialize SFX lib with a list of filenames!") - for i=1,#list do table.insert(sfxList,list[i])end -end -function SFX.load(path) - local c=0 - local missing=0 - for i=1,#sfxList do - local fullPath=path..sfxList[i]..'.ogg' - if love.filesystem.getInfo(fullPath)then - if Sources[sfxList[i]]then - for j=1,#Sources[sfxList[i]]do - Sources[sfxList[i]][j]:release() - end - end - Sources[sfxList[i]]={love.audio.newSource(fullPath,'static')} - c=c+1 - else - LOG("No SFX: "..sfxList[i]..'.ogg',.1) - missing=missing+1 - end - end - LOG(c.."/"..#sfxList.." SFX files loaded") - LOG(missing.." SFX files missing") - if missing>0 then - MES.new('info',missing.." SFX files missing") - end - collectgarbage() -end -function SFX.loadSample(pack) - assert(type(pack)=='table',"Usage: SFX.loadsample([table])") - assert(pack.name,"No field: name") - assert(pack.path,"No field: path") - local num=1 - while love.filesystem.getInfo(pack.path..'/'..num..'.ogg')do - Sources[pack.name..num]={love.audio.newSource(pack.path..'/'..num..'.ogg','static')} - num=num+1 - end - local base=(_getTuneHeight(pack.base)or 37)-1 - local top=base+num-1 - packSetting[pack.name]={base=base,top=top} - LOG((num-1).." "..pack.name.." samples loaded") -end - -function SFX.getCount() - return #sfxList -end -function SFX.setVol(v) - assert(type(v)=='number'and v>=0 and v<=1,'Wrong volume') - volume=v -end -function SFX.setStereo(v) - assert(type(v)=='number'and v>=0 and v<=1,'Wrong stereo') - stereo=v -end - -function SFX.getNoteName(note) - if note<1 then - return'---' - else - note=note-1 - local octave=int(note/12)+1 - return noteName[note%12+1]..octave - end -end -function SFX.playSample(pack,...)--vol-1, sampSet1, vol-2, sampSet2 - if ... then - local arg={...} - local vol - for i=1,#arg do - local a=arg[i] - if type(a)=='number'and a<=1 then - vol=a - else - local base=packSetting[pack].base - local top=packSetting[pack].top - local tune=type(a)=='string'and _getTuneHeight(a)or a--Absolute tune in number - local playTune=tune+rnd(-2,2) - if playTune<=base then--Too low notes - playTune=base+1 - elseif playTune>top then--Too high notes - playTune=top - end - SFX.play(pack..playTune-base,vol,nil,tune-playTune) - end - end - end -end -local function _play(name,vol,pos,pitch) - if volume==0 or vol==0 then return end - local S=Sources[name]--Source list - if not S then return end - local n=1 - while S[n]:isPlaying()do - n=n+1 - if not S[n]then - S[n]=S[1]:clone() - S[n]:seek(0) - break - end - end - S=S[n]--AU_SRC - if S:getChannelCount()==1 then - if pos then - pos=interval(pos,-1,1)*stereo - S:setPosition(pos,1-pos^2,0) - else - S:setPosition(0,0,0) - end - end - S:setVolume(vol^1.626) - S:setPitch(pitch and 1.0594630943592953^pitch or 1) - S:play() -end -SFX.fplay=_play--Play sounds without apply module's volume setting -function SFX.play(name,vol,pos,pitch) - _play(name,(vol or 1)*volume,pos,pitch) -end -function SFX.reset() - for _,L in next,Sources do - if type(L)=='table'then - for i=#L,1,-1 do - if not L[i]:isPlaying()then - rem(L,i) - end - end - end - end -end - -return SFX diff --git a/Zframework/stringExtend.lua b/Zframework/stringExtend.lua deleted file mode 100644 index ca2ccdbd8..000000000 --- a/Zframework/stringExtend.lua +++ /dev/null @@ -1,231 +0,0 @@ -local data=love.data -local STRING={} -local assert,tostring,tonumber=assert,tostring,tonumber -local int,format=math.floor,string.format -local find,sub,gsub,upper=string.find,string.sub,string.gsub,string.upper -local char,byte=string.char,string.byte - ---"Replace dollars", replace all $n with ... -function STRING.repD(str,...) - local l={...} - for i=#l,1,-1 do - str=gsub(str,'$'..i,l[i]) - end - return str -end - ---"Scan arg", scan if str has the arg (format of str is like "-json -q", arg is like "-q") -function STRING.sArg(str,switch) - if find(str.." ",switch.." ")then - return true - end -end - -do--function STRING.shiftChar(c) - local shiftMap={ - ['1']='!',['2']='@',['3']='#',['4']='$',['5']='%', - ['6']='^',['7']='&',['8']='*',['9']='(',['0']=')', - ['`']='~',['-']='_',['=']='+', - ['[']='{',[']']='}',['\\']='|', - [';']=':',['\'']='"', - [',']='<',['.']='>',['/']='?', - } - function STRING.shiftChar(c) - return shiftMap[c]or upper(c) - end -end - -function STRING.trim(s) - if not s:find("%S")then return""end - s=s:sub((s:find("%S"))):reverse() - return s:sub((s:find("%S"))):reverse() -end - -function STRING.split(s,sep,regex) - local L={} - local p1,p2=1--start,target - if regex then - while p1<=#s do - p2=find(s,sep,p1)or #s+1 - L[#L+1]=sub(s,p1,p2-1) - p1=p2+#sep - end - else - while p1<=#s do - p2=find(s,sep,p1,true)or #s+1 - L[#L+1]=sub(s,p1,p2-1) - p1=p2+#sep - end - end - return L -end - -function STRING.simpEmailCheck(e) - e=STRING.split(e,"@") - if #e~=2 then return false end - if e[1]:sub(-1)=="."or e[2]:sub(-1)=="."then return false end - local e1,e2=STRING.split(e[1],"."),STRING.split(e[2],".") - if #e1*#e2==0 then return false end - for _,v in next,e1 do if #v==0 then return false end end - for _,v in next,e2 do if #v==0 then return false end end - return true -end - -function STRING.time_simp(t) - return format("%02d:%02d",int(t/60),int(t%60)) -end - -function STRING.time(t) - if t<60 then - return format("%.3f″",t) - elseif t<3600 then - return format("%d′%05.2f″",int(t/60),int(t%60*100)/100) - else - return format("%d:%.2d′%05.2f″",int(t/3600),int(t/60%60),int(t%60*100)/100) - end -end - -function STRING.UTF8(n)--Simple utf8 coding - assert(type(n)=='number',"Wrong type ("..type(n)..")") - assert(n>=0 and n<2^31,"Out of range ("..n..")") - if n<2^7 then return char(n) - elseif n<2^11 then return char(192+int(n/2^06),128+n%2^6) - elseif n<2^16 then return char(224+int(n/2^12),128+int(n/2^06)%2^6,128+n%2^6) - elseif n<2^21 then return char(240+int(n/2^18),128+int(n/2^12)%2^6,128+int(n/2^06)%2^6,128+n%2^6) - elseif n<2^26 then return char(248+int(n/2^24),128+int(n/2^18)%2^6,128+int(n/2^12)%2^6,128+int(n/2^06)%2^6,128+n%2^6) - elseif n<2^31 then return char(252+int(n/2^30),128+int(n/2^24)%2^6,128+int(n/2^18)%2^6,128+int(n/2^12)%2^6,128+int(n/2^06)%2^6,128+n%2^6) - end -end - -do--function STRING.bigInt(t) - local lg=math.log10 - local units={"","K","M","B","T","Qa","Qt","Sx","Sp","Oc","No"} - local preUnits={"","U","D","T","Qa","Qt","Sx","Sp","O","N"} - local secUnits={"Dc","Vg","Tg","Qd","Qi","Se","St","Og","Nn","Ce"}--Ce is next-level unit, but DcCe is not used so used here - for _,preU in next,preUnits do for _,secU in next,secUnits do table.insert(units,preU..secU)end end - function STRING.bigInt(t) - if t<1000 then - return tostring(t) - elseif t~=1e999 then - local e=int(lg(t)/3) - return(t/10^(e*3))..units[e+1] - else - return"INF" - end - end -end - -function STRING.hexColor(str)--[LOW PERFORMENCE] - assert(type(str)=='string') - if str:sub(1,1)=="#"then str=str:sub(2)end - assert(#str<=8) - local r=(tonumber(str:sub(1,2),16)or 0)/255 - local g=(tonumber(str:sub(3,4),16)or 0)/255 - local b=(tonumber(str:sub(5,6),16)or 0)/255 - local a=(tonumber(str:sub(7,8),16)or 255)/255 - return r,g,b,a -end - -do--function STRING.urlEncode(s) - local rshift=bit.rshift - local b16={[0]='0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'} - function STRING.urlEncode(s) - local out="" - for i=1,#s do - if s:sub(i,i):match("[a-zA-Z0-9]")then - out=out..s:sub(i,i) - else - local b=s:byte(i) - out=out.."%"..b16[rshift(b,4)]..b16[b%16] - end - end - return out - end -end - -function STRING.vcsEncrypt(text,key) - local keyLen=#key - local result="" - local buffer="" - for i=0,#text-1 do - buffer=buffer..char((byte(text,i+1)-32+byte(key,i%keyLen+1))%95+32) - if #buffer==26 then - result=result..buffer - buffer="" - end - end - return result..buffer -end -function STRING.vcsDecrypt(text,key) - local keyLen=#key - local result="" - local buffer="" - for i=0,#text-1 do - buffer=buffer..char((byte(text,i+1)-32-byte(key,i%keyLen+1))%95+32) - if #buffer==26 then - result=result..buffer - buffer="" - end - end - return result..buffer -end -function STRING.digezt(text)--Not powerful hash, just protect the original text - local out={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} - local seed=26 - for i=1,#text do - local c=byte(text,i) - seed=(seed+c)%26 - c=c+seed - local pos=c*i%16 - local step=(c+i)%4+1 - local times=2+(c%6) - for _=1,times do - out[pos+1]=(out[pos+1]+c)%256 - pos=(pos+step)%16 - end - end - local result="" - for i=1,16 do result=result..char(out[i])end - return result -end - -function STRING.readLine(str) - local p=str:find("\n") - if p then - return str:sub(1,p-1),str:sub(p+1) - else - return str,"" - end -end -function STRING.readChars(str,n) - return sub(str,1,n),sub(str,n+1) -end - -function STRING.packBin(s) - return data.encode('string','base64',data.compress('string','zlib',s)) -end -function STRING.unpackBin(str) - local res - res,str=pcall(data.decode,'string','base64',str) - if not res then return end - res,str=pcall(data.decompress,'string','zlib',str) - if res then return str end -end -function STRING.packText(s) - return data.encode('string','base64',data.compress('string','gzip',s)) -end -function STRING.unpackText(str) - local res - res,str=pcall(data.decode,'string','base64',str) - if not res then return end - res,str=pcall(data.decompress,'string','gzip',str) - if res then return str end -end -function STRING.packTable(t) - return STRING.packText(JSON.encode(t)) -end -function STRING.unpackTable(t) - return JSON.decode(STRING.unpackText(t)) -end - -return STRING diff --git a/Zframework/sysFX.lua b/Zframework/sysFX.lua deleted file mode 100644 index 07ddef2cb..000000000 --- a/Zframework/sysFX.lua +++ /dev/null @@ -1,205 +0,0 @@ -local gc=love.graphics -local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth -local gc_draw,gc_line=gc.draw,gc.line -local gc_rectangle,gc_circle=gc.rectangle,gc.circle - -local max,min=math.max,math.min -local rnd=math.random -local ins,rem=table.insert,table.remove - -local fx={} - -local function _normUpdate(S,dt) - S.t=S.t+dt*S.rate - return S.t>1 -end - -local FXupdate={} -function FXupdate.badge(S,dt) - S.t=S.t+dt - if S.t<.2 then - S.x,S.y=S.x1-14,S.y1-14 - elseif S.t<.8 then - local t=((S.t-.2)*1.6667) - t=(3-2*t)*t*t - S.x,S.y=S.x1*(1-t)+S.x2*t-14,S.y1*(1-t)+S.y2*t-14 - else - S.x,S.y=S.x2-14,S.y2-14 - end - return S.t>=1 -end -FXupdate.attack=_normUpdate -FXupdate.tap=_normUpdate -FXupdate.ripple=_normUpdate -FXupdate.rectRipple=_normUpdate -FXupdate.shade=_normUpdate -function FXupdate.cell(S,dt) - if S.vx then - S.x=S.x+S.vx*S.rate - S.y=S.y+S.vy*S.rate - if S.ax then - S.vx=S.vx+S.ax*S.rate - S.vy=S.vy+S.ay*S.rate - end - end - S.t=S.t+dt*S.rate - return S.t>1 -end -FXupdate.line=_normUpdate - -local FXdraw={} -function FXdraw.badge(S) - gc_setColor(1,1,1,S.t<.2 and S.t*.6 or S.t<.8 and 1 or(1-S.t)*.6) - gc_draw(IMG.badgeIcon,S.x,S.y) -end -function FXdraw.attack(S) - gc_setColor(S.r*2,S.g*2,S.b*2,S.a*min(4-S.t*4,1)) - - gc_setLineWidth(S.wid) - local t1,t2=max(5*S.t-4,0),min(S.t*4,1) - gc_line( - S.x1*(1-t1)+S.x2*t1, - S.y1*(1-t1)+S.y2*t1, - S.x1*(1-t2)+S.x2*t2, - S.y1*(1-t2)+S.y2*t2 - ) - - gc_setLineWidth(S.wid*.6) - t1,t2=max(4*S.t-3,0),min(S.t*5,1) - gc_line( - S.x1*(1-t1)+S.x2*t1, - S.y1*(1-t1)+S.y2*t1, - S.x1*(1-t2)+S.x2*t2, - S.y1*(1-t2)+S.y2*t2 - ) -end -function FXdraw.tap(S) - local t=S.t - gc_setColor(1,1,1,(1-t)*.4) - gc_circle('fill',S.x,S.y,30*(1-t)^.5) -end -function FXdraw.ripple(S) - local t=S.t - gc_setLineWidth(2) - gc_setColor(1,1,1,1-t) - gc_circle('line',S.x,S.y,t*(2-t)*S.r) -end -function FXdraw.rectRipple(S) - gc_setLineWidth(6) - gc_setColor(1,1,1,1-S.t) - local r=(10*S.t)^1.2 - gc_rectangle('line',S.x-r,S.y-r,S.w+2*r,S.h+2*r) -end -function FXdraw.shade(S) - gc_setColor(S.r,S.g,S.b,1-S.t) - gc_rectangle('fill',S.x,S.y,S.w,S.h,2) -end -function FXdraw.cell(S) - gc_setColor(1,1,1,1-S.t) - gc_draw(S.image,S.x,S.y,nil,S.size,nil,S.cx,S.cy) -end -function FXdraw.line(S) - gc_setColor(1,1,1,S.a*(1-S.t)) - gc_line(S.x1,S.y1,S.x2,S.y2) -end - -local SYSFX={} -function SYSFX.update(dt) - for i=#fx,1,-1 do - if fx[i]:update(dt)then - rem(fx,i) - end - end -end -function SYSFX.draw() - for i=1,#fx do - fx[i]:draw() - end -end - -function SYSFX.newBadge(x1,y1,x2,y2) - ins(fx,{ - update=FXupdate.badge, - draw=FXdraw.badge, - t=0, - x=x1,y=y1, - x1=x1,y1=y1, - x2=x2,y2=y2, - }) -end -function SYSFX.newAttack(rate,x1,y1,x2,y2,wid,r,g,b,a) - ins(fx,{ - update=FXupdate.attack, - draw=FXdraw.attack, - t=0, - rate=rate, - x1=x1,y1=y1,--Start pos - x2=x2,y2=y2,--End pos - wid=wid,--Line width - r=r,g=g,b=b,a=a, - }) -end -function SYSFX.newTap(rate,x,y) - local T= - { - update=FXupdate.tap, - draw=FXdraw.tap, - t=0, - rate=rate, - x=x,y=y, - } - ins(fx,T) -end -function SYSFX.newRipple(rate,x,y,r) - ins(fx,{ - update=FXupdate.ripple, - draw=FXdraw.ripple, - t=0, - rate=rate, - x=x,y=y,r=r, - }) -end -function SYSFX.newRectRipple(rate,x,y,w,h) - ins(fx,{ - update=FXupdate.rectRipple, - draw=FXdraw.rectRipple, - t=0, - rate=rate, - x=x,y=y,w=w,h=h, - }) -end -function SYSFX.newShade(rate,x,y,w,h,r,g,b) - ins(fx,{ - update=FXupdate.shade, - draw=FXdraw.shade, - t=0, - rate=rate, - x=x,y=y,w=w,h=h, - r=r or 1,g=g or 1,b=b or 1, - }) -end -function SYSFX.newCell(rate,image,size,x,y,vx,vy,ax,ay) - ins(fx,{ - update=FXupdate.cell, - draw=FXdraw.cell, - t=0, - rate=rate*(.9+rnd()*.2), - image=image,size=size, - cx=image:getWidth()*.5,cy=image:getHeight()*.5, - x=x,y=y, - vx=vx,vy=vy, - ax=ax,ay=ay, - }) -end -function SYSFX.newLine(rate,x1,y1,x2,y2,r,g,b,a) - ins(fx,{ - update=FXupdate.line, - draw=FXdraw.line, - t=0, - rate=rate, - x1=x1 or 0,y1=y1 or 0, - x2=x2 or x1 or 1280,y2=y2 or y1 or 720, - r=r or 1,g=g or 1,b=b or 1,a=a or 1, - }) -end -return SYSFX diff --git a/Zframework/tableExtend.lua b/Zframework/tableExtend.lua deleted file mode 100644 index 7b5c46c57..000000000 --- a/Zframework/tableExtend.lua +++ /dev/null @@ -1,255 +0,0 @@ -local find=string.find -local rem=table.remove -local next,type=next,type -local TABLE={} - ---Get a new filled table -function TABLE.new(val,count) - local L={} - for i=1,count do - L[i]=val - end - return L -end - ---Get a copy of [1~#] elements -function TABLE.shift(org,depth) - if not depth then depth=1e99 end - local L={} - for i=1,#org do - if type(org[i])=='table'and depth>0 then - L[i]=TABLE.shift(org[i],depth-1) - else - L[i]=org[i] - end - end - return L -end - ---Get a full copy of a table, depth = how many layers will be recreate, default to inf -function TABLE.copy(org,depth) - if not depth then depth=1e99 end - local L={} - for k,v in next,org do - if type(v)=='table'and depth>0 then - L[k]=TABLE.copy(v,depth-1) - else - L[k]=v - end - end - return L -end - ---For all things in new, push to old -function TABLE.cover(new,old) - for k,v in next,new do - old[k]=v - end -end - ---For all things in new, push to old -function TABLE.coverR(new,old) - for k,v in next,new do - if type(v)=='table'and type(old[k])=='table'then - TABLE.coverR(v,old[k]) - else - old[k]=v - end - end -end - - ---For all things in new if same type in old, push to old -function TABLE.update(new,old) - for k,v in next,new do - if type(v)==type(old[k])then - if type(v)=='table'then - TABLE.update(v,old[k]) - else - old[k]=v - end - end - end -end - ---For all things in new if no val in old, push to old -function TABLE.complete(new,old) - for k,v in next,new do - if type(v)=='table'then - if old[k]==nil then old[k]={}end - TABLE.complete(v,old[k]) - elseif old[k]==nil then - old[k]=v - end - end -end - ---Remove [1~#] of table -function TABLE.cut(G) - for i=1,#G do - G[i]=nil - end -end - ---Clear table -function TABLE.clear(G) - for k in next,G do - G[k]=nil - end -end - ---Remove duplicated value of [1~#] -function TABLE.trimDuplicate(org) - local cache={} - for i=1,#org,-1 do - if cache[org[i]]then - rem(org,i) - else - cache[org[i]]=true - end - end -end - ---Discard duplicated value -function TABLE.remDuplicate(org) - local cache={} - for k,v in next,org do - if cache[v]then - org[k]=nil - else - cache[v]=true - end - end -end - - ---Reverse [1~#] -function TABLE.reverse(org) - local l=#org - for i=1,math.floor(l/2)do - org[i],org[l+1-i]=org[l+1-i],org[i] - end -end - --------------------------- - ---Find value in [1~#] -function TABLE.find(t,val) - for i=1,#t do if t[i]==val then return i end end -end - ---Return next value of [1~#] (by value) -function TABLE.next(t,val) - for i=1,#t do if t[i]==val then return t[i%#t+1]end end -end - --------------------------- - ---Find value in whole table -function TABLE.search(t,val) - for k,v in next,t do if v==val then return k end end -end - ---Re-index string value of a table -function TABLE.reIndex(org) - for k,v in next,org do - if type(v)=='string'then - org[k]=org[v] - end - end -end - --------------------------- - ---Dump a simple lua table -do--function TABLE.dump(L,t) - local tabs={ - [0]="", - "\t", - "\t\t", - "\t\t\t", - "\t\t\t\t", - "\t\t\t\t\t", - } - local function dump(L,t) - local s - if t then - s="{\n" - else - s="return{\n" - t=1 - if type(L)~='table'then - return - end - end - local count=1 - for k,v in next,L do - local T=type(k) - if T=='number'then - if k==count then - k="" - count=count+1 - else - k="["..k.."]=" - end - elseif T=='string'then - if find(k,"[^0-9a-zA-Z_]")then - k="[\""..k.."\"]=" - else - k=k.."=" - end - elseif T=='boolean'then k="["..k.."]=" - else error("Error key type!") - end - T=type(v) - if T=='number'then v=tostring(v) - elseif T=='string'then v="\""..v.."\"" - elseif T=='table'then v=dump(v,t+1) - elseif T=='boolean'then v=tostring(v) - else error("Error data type!") - end - s=s..tabs[t]..k..v..",\n" - end - return s..tabs[t-1].."}" - end - TABLE.dump=dump -end - ---Dump a simple lua table (no whitespaces) -do--function TABLE.dumpDeflate(L,t) - local function dump(L) - local s="return{" - if type(L)~='table'then return end - local count=1 - for k,v in next,L do - local T=type(k) - if T=='number'then - if k==count then - k="" - count=count+1 - else - k="["..k.."]=" - end - elseif T=='string'then - if find(k,"[^0-9a-zA-Z_]")then - k="[\""..k.."\"]=" - else - k=k.."=" - end - elseif T=='boolean'then k="["..k.."]=" - else error("Error key type!") - end - T=type(v) - if T=='number'then v=tostring(v) - elseif T=='string'then v="\""..v.."\"" - elseif T=='table'then v=dump(v) - elseif T=='boolean'then v=tostring(v) - else error("Error data type!") - end - end - return s.."}" - end - TABLE.dumpDeflate=dump -end - -return TABLE diff --git a/Zframework/task.lua b/Zframework/task.lua deleted file mode 100644 index 6de252260..000000000 --- a/Zframework/task.lua +++ /dev/null @@ -1,56 +0,0 @@ -local rem=table.remove -local assert,resume,status=assert,coroutine.resume,coroutine.status -local tasks={} - -local TASK={} -function TASK.getCount() - return #tasks -end -local trigFrame=0 -function TASK.update(dt) - trigFrame=trigFrame+dt*60 - while trigFrame>=1 do - for i=#tasks,1,-1 do - local T=tasks[i] - if status(T.thread)=='dead'then - rem(tasks,i) - else - assert(resume(T.thread)) - end - end - trigFrame=trigFrame-1 - end -end -function TASK.new(code,...) - local thread=coroutine.create(code) - assert(resume(thread,...)) - if status(thread)~='dead'then - tasks[#tasks+1]={ - thread=thread, - code=code, - args={...}, - } - end -end -function TASK.removeTask_code(code) - for i=#tasks,1,-1 do - if tasks[i].code==code then - rem(tasks,i) - end - end -end -function TASK.removeTask_iterate(func,...) - for i=#tasks,1,-1 do - if func(tasks[i],...)then - rem(tasks,i) - end - end -end -function TASK.clear() - local i=#tasks - while i>0 do - tasks[i]=nil - i=i-1 - end -end -return TASK diff --git a/Zframework/test.lua b/Zframework/test.lua deleted file mode 100644 index 46be780cb..000000000 --- a/Zframework/test.lua +++ /dev/null @@ -1,12 +0,0 @@ -local TEST={} - ---Wait for the scene swapping animation to finish -function TEST.yieldUntilNextScene() - while SCN.swapping do YIELD()end -end - -function TEST.yieldN(frames) - for _=1,frames do YIELD()end -end - -return TEST diff --git a/Zframework/text.lua b/Zframework/text.lua deleted file mode 100644 index ddc464e50..000000000 --- a/Zframework/text.lua +++ /dev/null @@ -1,153 +0,0 @@ -local gc=love.graphics -local getColor,setColor=gc.getColor,gc.setColor - -local int,rnd=math.floor,math.random -local ins,rem=table.insert,table.remove -local draw=gc.draw - -local texts={} - -local textFX={} -function textFX.appear(t) - draw( - t.text,t.x,t.y, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.sudden(t) - setColor(1,1,1,1-t.c) - draw( - t.text,t.x,t.y, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.fly(t) - draw( - t.text,t.x+(t.c-.5)^3*300,t.y, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.stretch(t) - draw( - t.text,t.x,t.y, - nil, - t.c<.3 and(.3-t.c)*1.6+1 or 1,1, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.drive(t) - draw( - t.text,t.x,t.y, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5, - t.c<.3 and(.3-t.c)*2 or 0,0 - ) -end -function textFX.spin(t) - draw( - t.text,t.x,t.y, - t.c<.3 and(.3-t.c)^2*4 or t.c<.8 and 0 or(t.c-.8)^2*-4, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.flicker(t) - local _,_,_,T=getColor() - setColor(1,1,1,T*(rnd()+.5)) - draw( - t.text,t.x,t.y, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.zoomout(t) - draw( - t.text,t.x,t.y, - nil, - t.c^.5*.1+1,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.beat(t) - local k=t.c<.3 and 1.3-t.c^2/.3 or 1 - draw( - t.text,t.x,t.y, - nil, - k,k, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end -function textFX.score(t) - local _,_,_,T=getColor() - setColor(1,1,1,T*.5) - draw( - t.text,t.x,t.y-0-t.c^.2*50, - nil, - nil,nil, - t.text:getWidth()*.5,t.text:getHeight()*.5 - ) -end - -local TEXT={} -function TEXT.clear() - texts={} -end -function TEXT.show(text,x,y,font,style,spd,stop) - ins(texts,{ - c=0, --Timer - text=gc.newText(FONT.get(int(font/5)*5 or 40),text), --String - x=x or 0, --X - y=y or 0, --Y - spd=(spd or 1), --Timing speed(1=last 1 sec) - stop=stop, --Stop time(sustained text) - draw=assert(textFX[style or'appear'],"no text type:"..style),--Draw method - }) -end -function TEXT.getText(text,x,y,font,style,spd,stop)--Another version of TEXT.show(), but only return text object, need manual management - return{ - c=0, - text=gc.newText(FONT.get(int(font/5)*5 or 40),text), - x=x or 0, - y=y or 0, - spd=(spd or 1), - stop=stop, - draw=textFX[style or'appear']or error("unavailable type:"..style), - } -end -function TEXT.update(dt,list) - if not list then - list=texts - end - for i=#list,1,-1 do - local t=list[i] - t.c=t.c+t.spd*dt - if t.stop then - if t.c>t.stop then - t.c=t.stop - end - end - if t.c>1 then - rem(list,i) - end - end -end -function TEXT.draw(list) - if not list then - list=texts - end - for i=1,#list do - local t=list[i] - local p=t.c - setColor(1,1,1,p<.2 and p*5 or p<.8 and 1 or 5-p*5) - t:draw() - end -end -return TEXT diff --git a/Zframework/vibrate.lua b/Zframework/vibrate.lua deleted file mode 100644 index 9443b01b2..000000000 --- a/Zframework/vibrate.lua +++ /dev/null @@ -1,12 +0,0 @@ -local level={0,0,.01,.016,.023,.03,.04,.05,.06,.07,.08,.09,.12,.15} -local vib=love.system.vibrate -return love.system.getOS()=='iOS'and - function(t) - t=level[t] - if t then vib(t<=.03 and 1 or t<=.09 and 2 or 3)end - end -or - function(t) - t=level[t] - if t then vib(t)end - end \ No newline at end of file diff --git a/Zframework/voice.lua b/Zframework/voice.lua deleted file mode 100644 index 4963bc3d0..000000000 --- a/Zframework/voice.lua +++ /dev/null @@ -1,132 +0,0 @@ -local rnd=math.random -local volume=1 -local diversion=0 -local VOC={ - getCount=function()return 0 end, - getQueueCount=function()return 0 end, - load=function()error("Cannot load before init!")end, - getFreeChannel=NULL, - play=NULL, - update=NULL, -} -function VOC.setDiversion(n) - assert(type(n)=='number'and n>0 and n<12,'Wrong div') - diversion=n -end -function VOC.setVol(v) - assert(type(v)=='number'and v>=0 and v<=1,'Wrong volume') - volume=v -end -function VOC.init(list) - VOC.init=nil - local rem=table.remove - local voiceQueue={free=0} - local bank={}--{vocName1={SRC1s},vocName2={SRC2s},...} - local Source={} - - local count=#list function VOC.getCount()return count end - local function _loadVoiceFile(path,N,vocName) - local fullPath=path..vocName..'.ogg' - if love.filesystem.getInfo(fullPath)then - bank[vocName]={love.audio.newSource(fullPath,'stream')} - table.insert(Source[N],vocName) - return true - end - end - --Load voice with string - local function _getVoice(str) - local L=bank[str] - local n=1 - while L[n]:isPlaying()do - n=n+1 - if not L[n]then - L[n]=L[1]:clone() - L[n]:seek(0) - break - end - end - return L[n] - end - function VOC.load(path) - for i=1,count do - Source[list[i]]={} - - local n=0 - repeat n=n+1 until not _loadVoiceFile(path,list[i],list[i]..'_'..n) - - if n==1 then - if not _loadVoiceFile(path,list[i],list[i])then - LOG("No VOC: "..list[i],.1) - end - end - if not Source[list[i]][1]then - Source[list[i]]=nil - end - end - - function VOC.getQueueCount() - return #voiceQueue - end - function VOC.getFreeChannel() - local l=#voiceQueue - for i=1,l do - if #voiceQueue[i]==0 then return i end - end - voiceQueue[l+1]={s=0} - return l+1 - end - - function VOC.play(s,chn) - if volume>0 then - local _=Source[s] - if not _ then return end - if chn then - local L=voiceQueue[chn] - L[#L+1]=_[rnd(#_)] - L.s=1 - --Add to queue[chn] - else - voiceQueue[VOC.getFreeChannel()]={s=1,_[rnd(#_)]} - --Create new channel & play - end - end - end - function VOC.update() - for i=#voiceQueue,1,-1 do - local Q=voiceQueue[i] - if Q.s==0 then--Free channel, auto delete when >3 - if i>3 then - rem(voiceQueue,i) - end - elseif Q.s==1 then--Waiting load source - Q[1]=_getVoice(Q[1]) - Q[1]:setVolume(volume) - Q[1]:setPitch(1.0594630943592953^(diversion*(rnd()*2-1))) - Q[1]:play() - Q.s=Q[2]and 2 or 4 - elseif Q.s==2 then--Playing 1,ready 2 - if Q[1]:getDuration()-Q[1]:tell()<.08 then - Q[2]=_getVoice(Q[2]) - Q[2]:setVolume(volume) - Q[1]:setPitch(1.0594630943592953^(diversion*(rnd()*2-1))) - Q[2]:play() - Q.s=3 - end - elseif Q.s==3 then--Playing 12 same time - if not Q[1]:isPlaying()then - for j=1,#Q do - Q[j]=Q[j+1] - end - Q.s=Q[2]and 2 or 4 - end - elseif Q.s==4 then--Playing last - if not Q[1].isPlaying(Q[1])then - Q[1]=nil - Q.s=0 - end - end - end - end - end -end -return VOC diff --git a/Zframework/websocket.lua b/Zframework/websocket.lua deleted file mode 100644 index fca1e70c5..000000000 --- a/Zframework/websocket.lua +++ /dev/null @@ -1,191 +0,0 @@ -local host= - -- '127.0.0.1' - -- '192.168.114.102' - 'game.techmino.org' -local port='10026' -local path='/tech/socket/v1' - --- lua + LÖVE threading websocket client --- Original pure lua ver. by flaribbit and Particle_G --- Threading version by MrZ - -local type=type -local timer=love.timer.getTime -local CHN=love.thread.newChannel() -local CHN_getCount,CHN_push,CHN_pop=CHN.getCount,CHN.push,CHN.pop -local TRD=love.thread.newThread("\n") -local TRD_isRunning=TRD.isRunning - -local WS={} -local wsList=setmetatable({},{ - __index=function(l,k) - local ws={ - real=false, - status='dead', - lastPongTime=timer(), - sendTimer=0, - alertTimer=0, - pongTimer=0, - } - l[k]=ws - return ws - end -}) - -function WS.switchHost(_1,_2,_3) - for k in next,wsList do - WS.close(k) - end - host=_1 - port=_2 or port - path=_3 or path -end - -function WS.connect(name,subPath,body,timeout) - if wsList[name]and wsList[name].thread then - wsList[name].thread:release() - end - local ws={ - real=true, - thread=love.thread.newThread('Zframework/websocket_thread.lua'), - triggerCHN=love.thread.newChannel(), - sendCHN=love.thread.newChannel(), - readCHN=love.thread.newChannel(), - lastPingTime=0, - lastPongTime=timer(), - pingInterval=6, - status='connecting',--'connecting', 'running', 'dead' - sendTimer=0, - alertTimer=0, - pongTimer=0, - } - wsList[name]=ws - ws.thread:start(ws.triggerCHN,ws.sendCHN,ws.readCHN) - CHN_push(ws.sendCHN,host) - CHN_push(ws.sendCHN,port) - CHN_push(ws.sendCHN,path..subPath) - CHN_push(ws.sendCHN,body or"") - CHN_push(ws.sendCHN,timeout or 2.6) -end - -function WS.status(name) - local ws=wsList[name] - return ws.status or'dead' -end - -function WS.getTimers(name) - local ws=wsList[name] - return ws.pongTimer,ws.sendTimer,ws.alertTimer -end - -function WS.setPingInterval(name,time) - local ws=wsList[name] - ws.pingInterval=math.max(time or 2.6,2.6) -end - -function WS.alert(name) - local ws=wsList[name] - ws.alertTimer=2.6 -end - -local OPcode={ - continue=0, - text=1, - binary=2, - close=8, - ping=9, - pong=10, -} -local OPname={ - [0]='continue', - [1]='text', - [2]='binary', - [8]='close', - [9]='ping', - [10]='pong', -} -function WS.send(name,message,op) - if type(message)=='string'then - local ws=wsList[name] - if ws.real and ws.status=='running'then - CHN_push(ws.sendCHN,op and OPcode[op]or 2)--2=binary - CHN_push(ws.sendCHN,message) - ws.lastPingTime=timer() - ws.sendTimer=1 - end - else - MES.new('error',"Attempt to send non-string value!") - MES.traceback() - end -end - -function WS.read(name) - local ws=wsList[name] - if ws.real and ws.status~='connecting'and CHN_getCount(ws.readCHN)>=2 then - local op,message=CHN_pop(ws.readCHN),CHN_pop(ws.readCHN) - if op==8 then--8=close - ws.status='dead' - elseif op==9 then--9=ping - WS.send(name,message or"",'pong') - end - ws.lastPongTime=timer() - ws.pongTimer=1 - return message,OPname[op]or op - end -end - -function WS.close(name) - local ws=wsList[name] - if ws.real then - CHN_push(ws.sendCHN,8)--close - CHN_push(ws.sendCHN,"") - ws.status='dead' - end -end - -function WS.update(dt) - local time=timer() - for name,ws in next,wsList do - if ws.real and ws.status~='dead'then - if TRD_isRunning(ws.thread)then - if CHN_getCount(ws.triggerCHN)==0 then - CHN_push(ws.triggerCHN,0) - end - if ws.status=='connecting'then - local mes=CHN_pop(ws.readCHN) - if mes then - if mes=='success'then - ws.status='running' - ws.lastPingTime=time - ws.lastPongTime=time - ws.pongTimer=1 - else - ws.status='dead' - MES.new('warn',text.wsFailed..": "..(mes=="timeout"and text.netTimeout or mes)) - end - end - elseif ws.status=='running'then - if time-ws.lastPingTime>ws.pingInterval then - WS.send(name,"",'pong') - end - if time-ws.lastPongTime>6+2*ws.pingInterval then - WS.close(name) - end - end - if ws.sendTimer>0 then ws.sendTimer=ws.sendTimer-dt end - if ws.pongTimer>0 then ws.pongTimer=ws.pongTimer-dt end - if ws.alertTimer>0 then ws.alertTimer=ws.alertTimer-dt end - else - ws.status='dead' - local err=ws.thread:getError() - if err then - err=err:sub((err:find(":",(err:find(":")or 0)+1)or 0)+1,(err:find("\n")or 0)-1) - MES.new('warn',text.wsClose..err) - WS.alert(name) - end - end - end - end -end - -return WS diff --git a/Zframework/websocket_thread.lua b/Zframework/websocket_thread.lua deleted file mode 100644 index db4dc5488..000000000 --- a/Zframework/websocket_thread.lua +++ /dev/null @@ -1,191 +0,0 @@ -local triggerCHN,sendCHN,readCHN=... - -local CHN_demand,CHN_getCount=triggerCHN.demand,triggerCHN.getCount -local CHN_push,CHN_pop=triggerCHN.push,triggerCHN.pop - -local SOCK=require'socket'.tcp() -local JSON=require'Zframework.json' - -do--Connect - local host=CHN_demand(sendCHN) - local port=CHN_demand(sendCHN) - local path=CHN_demand(sendCHN) - local body=CHN_demand(sendCHN) - local timeout=CHN_demand(sendCHN) - - SOCK:settimeout(timeout) - local res,err=SOCK:connect(host,port) - assert(res,err) - - --WebSocket handshake - if not body then body=''end - SOCK:send( - 'GET '..path..' HTTP/1.1\r\n'.. - 'Host: '..host..':'..port..'\r\n'.. - 'Connection: Upgrade\r\n'.. - 'Upgrade: websocket\r\n'.. - 'Content-Type: application/json\r\n'.. - 'Content-Length: '..#body..'\r\n'.. - 'Sec-WebSocket-Version: 13\r\n'.. - 'Sec-WebSocket-Key: osT3F7mvlojIvf3/8uIsJQ==\r\n\r\n'..--secKey - body - ) - - --First line of HTTP - res,err=SOCK:receive('*l') - assert(res,err) - local code,ctLen - code=res:find(' ') - code=res:sub(code+1,code+3) - - --Get body length from headers and remove headers - repeat - res,err=SOCK:receive('*l') - assert(res,err) - if not ctLen and res:find('length')then - ctLen=tonumber(res:match('%d+')) - end - until res=='' - - --Result - if ctLen then - if code=='101'then - CHN_push(readCHN,'success') - else - res,err=SOCK:receive(ctLen) - res=JSON.decode(assert(res,err)) - error((code or"XXX")..":"..(res and res.reason or"Server Error")) - end - end - SOCK:settimeout(0) -end - -local YIELD=coroutine.yield -local byte,char=string.byte,string.char -local band,bor,bxor=bit.band,bit.bor,bit.bxor -local shl,shr=bit.lshift,bit.rshift - -local mask_key={1,14,5,14} -local mask_str=char(unpack(mask_key)) -local function _send(op,message) - --Message type - SOCK:send(char(bor(op,0x80))) - - if message then - --Length - local length=#message - if length>65535 then - SOCK:send(char(bor(127,0x80),0,0,0,0,band(shr(length,24),0xff),band(shr(length,16),0xff),band(shr(length,8),0xff),band(length,0xff))) - elseif length>125 then - SOCK:send(char(bor(126,0x80),band(shr(length,8),0xff),band(length,0xff))) - else - SOCK:send(char(bor(length,0x80))) - end - local msgbyte={byte(message,1,length)} - for i=1,length do - msgbyte[i]=bxor(msgbyte[i],mask_key[(i-1)%4+1]) - end - return SOCK:send(mask_str..char(unpack(msgbyte))) - else - SOCK:send('\128'..mask_str) - return 0 - end -end -local sendThread=coroutine.wrap(function() - while true do - while CHN_getCount(sendCHN)>=2 do - _send(CHN_pop(sendCHN),CHN_pop(sendCHN)) - end - YIELD() - end -end) - -local function _receive(sock,len) - local buffer="" - while true do - local r,e,p=sock:receive(len) - if r then - buffer=buffer..r - len=len-#r - elseif p then - buffer=buffer..p - len=len-#p - elseif e then - return nil,e - end - if len==0 then - return buffer - end - YIELD() - end -end -local readThread=coroutine.wrap(function() - local res,err - local op,fin - local lBuffer=""--Long multi-pack buffer - while true do - --Byte 0-1 - res,err=_receive(SOCK,2) - assert(res,err) - - op=band(byte(res,1),0x0f) - fin=band(byte(res,1),0x80)==0x80 - - --Calculating data length - local length=band(byte(res,2),0x7f) - if length==126 then - res,err=_receive(SOCK,2) - assert(res,err) - length=shl(byte(res,1),8)+byte(res,2) - elseif length==127 then - local lenData - lenData,err=_receive(SOCK,8) - assert(res,err) - local _,_,_,_,_5,_6,_7,_8=byte(lenData,1,8) - length=shl(_5,24)+shl(_6,16)+shl(_7,8)+_8 - end - res,err=_receive(SOCK,length) - assert(res,err) - - --React - if op==8 then--8=close - CHN_push(readCHN,8)--close - if type(res)=='string'then - CHN_push(readCHN,res:sub(3))--[Warning] 2 bytes close code at start so :sub(3) - else - CHN_push(readCHN,"WS closed") - end - return - elseif op==0 then--0=continue - lBuffer=lBuffer..res - if fin then - CHN_push(readCHN,lBuffer) - lBuffer="" - end - else - CHN_push(readCHN,op) - if fin then - CHN_push(readCHN,res) - lBuffer="" - else - lBuffer=res - end - end - YIELD() - end -end) - -local success,err - -while true do--Running - CHN_demand(triggerCHN) - success,err=pcall(sendThread) - if not success or err then break end - success,err=pcall(readThread) - if not success or err then break end -end - -SOCK:close() -CHN_push(readCHN,8)--close -CHN_push(readCHN,err or"Disconnected") -error() diff --git a/Zframework/wheelScroll.lua b/Zframework/wheelScroll.lua deleted file mode 100644 index 5e6024e8f..000000000 --- a/Zframework/wheelScroll.lua +++ /dev/null @@ -1,19 +0,0 @@ -local love=love -local max,min=math.max,math.min -local trigDist=0 -return function(y,key1,key2) - if y>0 then - trigDist=max(trigDist,0)+y^1.2 - elseif y<0 then - if trigDist>0 then trigDist=0 end - trigDist=min(trigDist,0)-(-y)^1.2 - end - while trigDist>=1 do - love.keypressed(key1 or'up') - trigDist=trigDist-1 - end - while trigDist<=-1 do - love.keypressed(key2 or'down') - trigDist=trigDist+1 - end -end diff --git a/Zframework/widget.lua b/Zframework/widget.lua deleted file mode 100644 index a22b5d252..000000000 --- a/Zframework/widget.lua +++ /dev/null @@ -1,1499 +0,0 @@ -local gc=love.graphics -local gc_origin=gc.origin -local gc_translate,gc_replaceTransform=gc.translate,gc.replaceTransform -local gc_stencil,gc_setStencilTest=gc.stencil,gc.setStencilTest -local gc_push,gc_pop=gc.push,gc.pop -local gc_setCanvas,gc_setBlendMode=gc.setCanvas,gc.setBlendMode -local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth -local gc_draw,gc_line=gc.draw,gc.line -local gc_rectangle=gc.rectangle -local gc_print,gc_printf=gc.print,gc.printf - -local kb=love.keyboard -local timer=love.timer.getTime - -local next=next -local int,ceil=math.floor,math.ceil -local max,min=math.max,math.min -local sub,ins,rem=string.sub,table.insert,table.remove -local xOy=SCR.xOy -local FONT=FONT -local mStr=GC.mStr -local approach=MATH.expApproach - -local downArrowIcon=GC.DO{40,25,{'fPoly',0,0,20,25,40,0}} -local upArrowIcon=GC.DO{40,25,{'fPoly',0,25,20,0,40,25}} -local clearIcon=GC.DO{40,40, - {'fRect',16,5,8,3}, - {'fRect',8,8,24,3}, - {'fRect',11,14,18,21}, -} -local sureIcon=GC.DO{40,40, - {'rawFT',35}, - {'mText',"?",20,0}, -} -local smallerThen=GC.DO{20,20, - {'setLW',5}, - {'line',18,2,1,10,18,18}, -} -local largerThen=GC.DO{20,20, - {'setLW',5}, - {'line',2,2,19,10,2,18}, -} - -local STW,STH--stencil-wid/hei -local function _rectangleStencil() - gc.rectangle('fill',1,1,STW-2,STH-2) -end - -local onChange=NULL - -local WIDGET={} - -function WIDGET.setOnChange(func)onChange=assert(type(func)=='function'and func,"WIDGET.setOnChange(func): func must be a function")end - -local widgetMetatable={ - __tostring=function(self) - return self:getInfo() - end, -} - -local text={ - type='text', - mustHaveText=true, - alpha=0, -} - -function text:reset()end -function text:update(dt) - if self.hideF and self.hideF()then - if self.alpha>0 then - self.alpha=max(self.alpha-dt*7.5,0) - end - elseif self.alpha<1 then - self.alpha=min(self.alpha+dt*7.5,1) - end -end -function text:draw() - if self.alpha>0 then - local c=self.color - gc_setColor(c[1],c[2],c[3],self.alpha) - local w=self.obj:getWidth() - local k=min(self.lim/self.obj:getWidth(),1) - if self.align=='M'then - gc_draw(self.obj,self.x,self.y,nil,k,1,w*.5,0) - elseif self.align=='L'then - gc_draw(self.obj,self.x,self.y,nil,k,1) - elseif self.align=='R'then - gc_draw(self.obj,self.x,self.y,nil,k,1,w,0) - end - end -end -function WIDGET.newText(D)--name,x,y[,lim][,fText][,color][,font=30][,fType][,align='M'][,hideF][,hide] - local _={ - name= D.name or"_", - x= D.x, - y= D.y, - lim= D.lim or 1e99, - - fText=D.fText, - color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, - font= D.font or 30, - fType=D.fType, - align=D.align or'M', - hideF=D.hideF, - } - for k,v in next,text do _[k]=v end - if not _.hideF then _.alpha=1 end - setmetatable(_,widgetMetatable) - return _ -end - -local image={ - type='image', -} -function image:reset() - if type(self.img)=='string'then - self.img=IMG[self.img] - end -end -function image:draw() - gc_setColor(1,1,1,self.alpha) - gc_draw(self.img,self.x,self.y,self.ang,self.k) -end -function WIDGET.newImage(D)--name[,img(name)],x,y[,ang][,k][,hideF][,hide] - local _={ - name= D.name or"_", - img= D.img or D.name or"_", - alpha=D.alpha, - x= D.x, - y= D.y, - ang= D.ang, - k= D.k, - hideF=D.hideF, - hide= D.hide, - } - for k,v in next,image do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local button={ - type='button', - mustHaveText=true, - ATV=0,--Activating time(0~8) -} -function button:reset() - self.ATV=0 -end -function button:setObject(obj) - if type(obj)=='string'or type(obj)=='number'then - self.obj=gc.newText(FONT.get(self.font,self.fType),obj) - elseif obj then - self.obj=obj - end -end -function button:isAbove(x,y) - local ATV=self.ATV - return - x>self.x-ATV and - y>self.y and - x0 then self.ATV=max(ATV-dt*30,0)end - end -end -function button:draw() - local x,y,w,h=self.x,self.y,self.w,self.h - local ATV=self.ATV - local c=self.color - local r,g,b=c[1],c[2],c[3] - - --Button - gc_setColor(.15+r*.7,.15+g*.7,.15+b*.7,.9) - gc_rectangle('fill',x-ATV,y,w+2*ATV,h,4) - gc_setLineWidth(2) - gc_setColor(.3+r*.7,.3+g*.7,.3+b*.7) - gc_rectangle('line',x-ATV,y,w+2*ATV,h,5) - if ATV>0 then - gc_setColor(.97,.97,.97,ATV*.125) - gc_rectangle('line',x-ATV,y,w+2*ATV,h,3) - end - - --Drawable - local obj=self.obj - local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5 - local y0=y+h*.5 - gc_setColor(1,1,1,.2+ATV*.05) - if self.align=='M'then - local x0=x+w*.5 - local kx=obj:type()=='Text'and min(w/ox/2,1)or 1 - gc_draw(obj,x0-1,y0-1,nil,kx,1,ox,oy) - gc_draw(obj,x0-1,y0+1,nil,kx,1,ox,oy) - gc_draw(obj,x0+1,y0-1,nil,kx,1,ox,oy) - gc_draw(obj,x0+1,y0+1,nil,kx,1,ox,oy) - gc_setColor(r*.55,g*.55,b*.55) - gc_draw(obj,x0,y0,nil,kx,1,ox,oy) - elseif self.align=='L'then - local edge=self.edge - gc_draw(obj,x+edge-1,y0-1-oy) - gc_draw(obj,x+edge-1,y0+1-oy) - gc_draw(obj,x+edge+1,y0-1-oy) - gc_draw(obj,x+edge+1,y0+1-oy) - gc_setColor(r*.55,g*.55,b*.55) - gc_draw(obj,x+edge,y0-oy) - elseif self.align=='R'then - local x0=x+w-self.edge-ox*2 - gc_draw(obj,x0-1,y0-1-oy) - gc_draw(obj,x0-1,y0+1-oy) - gc_draw(obj,x0+1,y0-1-oy) - gc_draw(obj,x0+1,y0+1-oy) - gc_setColor(r*.55,g*.55,b*.55) - gc_draw(obj,x0,y0-oy) - end -end -function button:getInfo() - return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font,self.fType) -end -function button:press(_,_,k) - self.code(k) - local ATV=self.ATV - SYSFX.newRectRipple( - 6, - self.x-ATV, - self.y-WIDGET.scrollPos, - self.w+2*ATV, - self.h - ) - if self.sound then - SFX.play(self.sound) - end -end -function WIDGET.newButton(D)--name,x,y,w[,h][,fText][,color][,font=30][,fType][,sound][,align='M'][,edge=0][,code][,hideF][,hide] - if not D.h then D.h=D.w end - local _={ - name= D.name or"_", - - x= D.x-D.w*.5, - y= D.y-D.h*.5, - w= D.w, - h= D.h, - - resCtr={ - D.x,D.y, - D.x-D.w*.35,D.y-D.h*.35, - D.x-D.w*.35,D.y+D.h*.35, - D.x+D.w*.35,D.y-D.h*.35, - D.x+D.w*.35,D.y+D.h*.35, - }, - - fText=D.fText, - color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, - font= D.font or 30, - fType=D.fType, - align=D.align or'M', - edge= D.edge or 0, - code= D.code or NULL, - hideF=D.hideF, - hide= D.hide, - } - if D.sound==false then - _.sound=false - elseif type(D.sound)=='string'then - _.sound=D.sound - else - _.sound='button' - end - - for k,v in next,button do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local key={ - type='key', - mustHaveText=true, - ATV=0,--Activating time(0~4) -} -function key:reset() - self.ATV=0 -end -function key:setObject(obj) - if type(obj)=='string'or type(obj)=='number'then - self.obj=gc.newText(FONT.get(self.font,self.fType),obj) - elseif obj then - self.obj=obj - end -end -function key:isAbove(x,y) - return - x>self.x and - y>self.y and - x0 then self.ATV=max(ATV-dt*30,0)end - end -end -function key:draw() - local x,y,w,h=self.x,self.y,self.w,self.h - local ATV=self.ATV - local c=self.color - local align=self.align - local r,g,b=c[1],c[2],c[3] - - --Fill - if self.fShade then - gc_setColor(r,g,b,ATV*.25) - if align=='M'then - gc_draw(self.fShade,x+w*.5-self.fShade:getWidth()*.5,y+h*.5-self.fShade:getHeight()*.5) - elseif align=='L'then - gc_draw(self.fShade,x+self.edge,y+h*.5-self.fShade:getHeight()*.5) - elseif align=='R'then - gc_draw(self.fShade,x+w-self.edge-self.fShade:getWidth(),y+h*.5-self.fShade:getHeight()*.5) - end - else - --Background - gc_setColor(0,0,0,.3) - gc_rectangle('fill',x,y,w,h,4) - - --Frame - gc_setColor(.2+r*.8,.2+g*.8,.2+b*.8,.7) - gc_setLineWidth(2) - gc_rectangle('line',x,y,w,h,3) - - --Shade - gc_setColor(1,1,1,ATV*.05) - gc_rectangle('fill',x,y,w,h,3) - end - - --Drawable - local obj=self.obj - local ox,oy=obj:getWidth()*.5,obj:getHeight()*.5 - gc_setColor(r,g,b) - if align=='M'then - local kx=obj:type()=='Text'and min(w/ox/2,1)or 1 - gc_draw(obj,x+w*.5,y+h*.5,nil,kx,1,ox,oy) - elseif align=='L'then - gc_draw(obj,x+self.edge,y-oy+h*.5) - elseif align=='R'then - gc_draw(obj,x+w-self.edge-ox*2,y-oy+h*.5) - end -end -function key:getInfo() - return("x=%d,y=%d,w=%d,h=%d,font=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h,self.font,self.fType) -end -function key:press(_,_,k) - self.code(k) - if self.sound then - SFX.play(self.sound) - end -end -function WIDGET.newKey(D)--name,x,y,w[,h][,fText][,fShade][,color][,font=30][,fType][,sound][,align='M'][,edge=0][,code][,hideF][,hide] - if not D.h then D.h=D.w end - local _={ - name= D.name or"_", - - x= D.x-D.w*.5, - y= D.y-D.h*.5, - w= D.w, - h= D.h, - - resCtr={ - D.x,D.y, - D.x-D.w*.35,D.y-D.h*.35, - D.x-D.w*.35,D.y+D.h*.35, - D.x+D.w*.35,D.y-D.h*.35, - D.x+D.w*.35,D.y+D.h*.35, - }, - - fText= D.fText, - fShade= D.fShade, - color= D.color and(COLOR[D.color]or D.color)or COLOR.Z, - font= D.font or 30, - fType= D.fType, - align= D.align or'M', - edge= D.edge or 0, - code= D.code or NULL, - hideF= D.hideF, - hide= D.hide, - } - if D.sound==false then - _.sound=false - elseif type(D.sound)=='string'then - _.sound=D.sound - else - _.sound='key' - end - for k,v in next,key do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local switch={ - type='switch', - mustHaveText=true, - ATV=0,--Activating time(0~8) - CHK=0,--Check alpha(0~6) -} -function switch:reset() - self.ATV=0 - self.CHK=0 -end -function switch:isAbove(x,y) - return x>self.x and xself.y-25 and y0 then self.ATV=max(ATV-dt*30,0)end - end - local chk=self.CHK - if self:disp()then - if chk<6 then self.CHK=min(chk+dt*60,6)end - else - if chk>0 then self.CHK=max(chk-dt*60,0)end - end -end -function switch:draw() - local x,y=self.x,self.y - local ATV=self.ATV - - --Background - gc_setColor(0,0,0,.3) - gc_rectangle('fill',x,y-25,50,50,4) - - --Frame - gc_setLineWidth(2) - gc_setColor(1,1,1,.6+ATV*.1) - gc_rectangle('line',x,y-25,50,50,3) - - --Checked - if ATV>0 then - gc_setColor(1,1,1,ATV*.06) - gc_rectangle('fill',x,y-25,50,50,3) - end - if self.CHK>0 then - gc_setColor(.9,1,.9,self.CHK/6) - gc_setLineWidth(5) - gc_line(x+5,y,x+18,y+13,x+45,y-14) - end - - --Drawable - local obj=self.obj - gc_setColor(self.color) - gc_draw(obj,x-12-ATV,y,nil,min(self.lim/obj:getWidth(),1),1,obj:getWidth(),obj:getHeight()*.5) -end -function switch:getInfo() - return("x=%d,y=%d,font=%d"):format(self.x,self.y,self.font,self.fType) -end -function switch:press() - self.code() - if self.sound then - SFX.play(self.disp()and'check'or'uncheck') - end -end -function WIDGET.newSwitch(D)--name,x,y[,lim][,fText][,color][,font=30][,fType][,sound=true][,disp][,code][,hideF][,hide] - local _={ - name= D.name or"_", - - x= D.x, - y= D.y, - lim= D.lim or 1e99, - - resCtr={ - D.x+25,D.y, - }, - - fText=D.fText, - color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, - font= D.font or 30, - fType=D.fType, - sound=D.sound~=false, - disp= D.disp, - code= D.code or NULL, - hideF=D.hideF, - hide= D.hide, - } - for k,v in next,switch do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local slider={ - type='slider', - ATV=0,--Activating time(0~8) - TAT=0,--Text activating time(0~180) - pos=0,--Position shown - lastTime=0,--Last value changing time -} -local sliderShowFunc={ - int=function(S) - return S.disp() - end, - float=function(S) - return int(S.disp()*100)*.01 - end, - percent=function(S) - return int(S.disp()*100).."%" - end, -} -function slider:reset() - self.ATV=0 - self.TAT=180 - self.pos=0 -end -function slider:isAbove(x,y) - return x>self.x-10 and xself.y-25 and y0 then - self.TAT=max(self.TAT-dt*60,0) - end - if WIDGET.sel==self then - if ATV<6 then self.ATV=min(ATV+dt*60,6)end - self.TAT=180 - else - if ATV>0 then self.ATV=max(ATV-dt*30,0)end - end - if not self.hide then - self.pos=approach(self.pos,self.disp(),dt*26) - end -end -function slider:draw() - local x,y=self.x,self.y - local ATV=self.ATV - local x2=x+self.w - - gc_setColor(1,1,1,.5+ATV*.06) - - --Units - if not self.smooth then - gc_setLineWidth(2) - for p=self.rangeL,self.rangeR,self.unit do - local X=x+(x2-x)*(p-self.rangeL)/(self.rangeR-self.rangeL) - gc_line(X,y+7,X,y-7) - end - end - - --Axis - gc_setLineWidth(4) - gc_line(x,y,x2,y) - - --Block - local cx=x+(x2-x)*(self.pos-self.rangeL)/(self.rangeR-self.rangeL) - local bx,by,bw,bh=cx-10-ATV*.5,y-16-ATV,20+ATV,32+2*ATV - gc_setColor(.8,.8,.8) - gc_rectangle('fill',bx,by,bw,bh,3) - - --Glow - if ATV>0 then - gc_setLineWidth(2) - gc_setColor(.97,.97,.97,ATV*.16) - gc_rectangle('line',bx+1,by+1,bw-2,bh-2,3) - end - - --Float text - if self.TAT>0 and self.show then - FONT.set(25) - gc_setColor(.97,.97,.97,self.TAT/180) - mStr(self:show(),cx,by-30) - end - - --Drawable - local obj=self.obj - if obj then - gc_setColor(self.color) - gc_draw(obj,x-12-ATV,y,nil,min(self.lim/obj:getWidth(),1),1,obj:getWidth(),obj:getHeight()*.5) - end -end -function slider:getInfo() - return("x=%d,y=%d,w=%d"):format(self.x,self.y,self.w) -end -function slider:press(x) - self:drag(x) -end -function slider:drag(x) - if not x then return end - x=x-self.x - local newPos=MATH.interval(x/self.w,0,1) - local newVal - if not self.unit then - newVal=(1-newPos)*self.rangeL+newPos*self.rangeR - else - newVal=newPos*(self.rangeR-self.rangeL) - newVal=self.rangeL+newVal-newVal%self.unit - end - if newVal~=self.disp()then - self.code(newVal) - end - if self.change and timer()-self.lastTime>.5 then - self.lastTime=timer() - self.change() - end -end -function slider:release(x) - self:drag(x) - self.lastTime=0 -end -function slider:scroll(n) - local p=self.disp() - local u=self.unit or .01 - local P=MATH.interval(p+u*n,self.rangeL,self.rangeR) - if p==P or not P then return end - self.code(P) - if self.change and timer()-self.lastTime>.18 then - self.lastTime=timer() - self.change() - end -end -function slider:arrowKey(k) - self:scroll((k=='left'or k=='up')and -1 or 1) -end -function WIDGET.newSlider(D)--name,x,y,w[,lim][,fText][,color][,axis][,smooth][,font=30][,fType][,change],disp[,show][,code],hide - if not D.axis then - D.axis={0,1,false} - D.smooth=true - elseif not D.axis[3]then - D.smooth=true - end - local _={ - name= D.name or"_", - - x= D.x, - y= D.y, - w= D.w, - lim= D.lim or 1e99, - - resCtr={ - D.x,D.y, - D.x+D.w*.25,D.y, - D.x+D.w*.5,D.y, - D.x+D.w*.75,D.y, - D.x+D.w,D.y, - }, - - fText= D.fText, - color= D.color and(COLOR[D.color]or D.color)or COLOR.Z, - rangeL=D.axis[1], - rangeR=D.axis[2], - unit= D.axis[3], - smooth=D.smooth, - font= D.font or 30, - fType= D.fType, - change=D.change, - disp= D.disp, - code= D.code or NULL, - hideF= D.hideF, - hide= D.hide, - show= false, - } - if D.show then - if type(D.show)=='function'then - _.show=D.show - else - _.show=sliderShowFunc[D.show] - end - elseif D.show~=false then--Use default if nil - if _.unit and _.unit%1==0 then - _.show=sliderShowFunc.int - else - _.show=sliderShowFunc.percent - end - end - for k,v in next,slider do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local selector={ - type='selector', - mustHaveText=true, - ATV=8,--Activating time(0~4) - select=false,--Selected item ID - selText=false,--Selected item name -} -function selector:reset() - self.ATV=0 - local V,L=self.disp(),self.list - for i=1,#L do - if L[i]==V then - self.select=i - self.selText=self.list[i] - return - end - end - self.select=0 - self.selText="" - MES.new('error',"Selector "..self.name.." dead, disp= "..tostring(V)) -end -function selector:isAbove(x,y) - return - x>self.x and - xself.y and - y0 then self.ATV=max(ATV-dt*30,0)end - end -end -function selector:draw() - local x,y=self.x,self.y - local w=self.w - local ATV=self.ATV - - --Background - gc_setColor(0,0,0,.3) - gc_rectangle('fill',x,y,w,60,4) - - --Frame - gc_setColor(1,1,1,.6+ATV*.1) - gc_setLineWidth(2) - gc_rectangle('line',x,y,w,60,3) - - --Arrow - gc_setColor(1,1,1,.2+ATV*.1) - local t=(timer()%.5)^.5 - if self.select>1 then - gc_draw(smallerThen,x+6,y+33) - if ATV>0 then - gc_setColor(1,1,1,ATV*.4*(.5-t)) - gc_draw(smallerThen,x+6-t*40,y+33) - gc_setColor(1,1,1,.2+ATV*.1) - end - end - if self.select<#self.list then - gc_draw(largerThen,x+w-26,y+33) - if ATV>0 then - gc_setColor(1,1,1,ATV*.4*(.5-t)) - gc_draw(largerThen,x+w-26+t*40,y+33) - end - end - - --Drawable - gc_setColor(self.color) - gc_draw(self.obj,x+w*.5,y-4,nil,min((w-20)/self.obj:getWidth(),1),1,self.obj:getWidth()*.5,0) - gc_setColor(1,1,1) - FONT.set(30) - mStr(self.selText,x+w*.5,y+22) -end -function selector:getInfo() - return("x=%d,y=%d,w=%d"):format(self.x+self.w*.5,self.y+30,self.w) -end -function selector:press(x) - if x then - local s=self.select - if x1 then - s=s-1 - SYSFX.newShade(3,self.x,self.y-WIDGET.scrollPos,self.w*.5,60) - end - else - if s<#self.list then - s=s+1 - SYSFX.newShade(3,self.x+self.w*.5,self.y-WIDGET.scrollPos,self.w*.5,60) - end - end - if self.select~=s then - self.code(self.list[s]) - self.select=s - self.selText=self.list[s] - if self.sound then - SFX.play('selector') - end - end - end -end -function selector:scroll(n) - local s=self.select - if n==-1 then - if s==1 then return end - s=s-1 - SYSFX.newShade(3,self.x,self.y-WIDGET.scrollPos,self.w*.5,60) - else - if s==#self.list then return end - s=s+1 - SYSFX.newShade(3,self.x+self.w*.5,self.y-WIDGET.scrollPos,self.w*.5,60) - end - self.code(self.list[s]) - self.select=s - self.selText=self.list[s] - if self.sound then - SFX.play('selector') - end -end -function selector:arrowKey(k) - self:scroll((k=='left'or k=='up')and -1 or 1) -end - -function WIDGET.newSelector(D)--name,x,y,w[,fText][,color][,sound=true],list,disp[,code],hide - local _={ - name= D.name or"_", - - x= D.x-D.w*.5, - y= D.y-30, - w= D.w, - - resCtr={ - D.x,D.y, - D.x+D.w*.25,D.y, - D.x+D.w*.5,D.y, - D.x+D.w*.75,D.y, - D.x+D.w,D.y, - }, - - fText=D.fText, - color=D.color and(COLOR[D.color]or D.color)or COLOR.Z, - sound=D.sound~=false, - font= 30, - list= D.list, - disp= D.disp, - code= D.code or NULL, - hideF=D.hideF, - hide= D.hide, - } - for k,v in next,selector do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local inputBox={ - type='inputBox', - keepFocus=true, - ATV=0,--Activating time(0~4) - value="",--Text contained -} -function inputBox:reset() - self.ATV=0 -end -function inputBox:hasText() - return #self.value>0 -end -function inputBox:getText() - return self.value -end -function inputBox:setText(str) - if type(str)=='string'then - self.value=str - end -end -function inputBox:addText(str) - if type(str)=='string'then - self.value=self.value..str - else - MES.new('error',"inputBox "..self.name.." dead, addText("..type(str)..")") - end -end -function inputBox:clear() - self.value="" -end -function inputBox:isAbove(x,y) - return - x>self.x and - y>self.y and - x0 then self.ATV=max(ATV-dt*15,0)end - end -end -function inputBox:draw() - local x,y,w,h=self.x,self.y,self.w,self.h - local ATV=self.ATV - - --Background - gc_setColor(0,0,0,.4) - gc_rectangle('fill',x,y,w,h,4) - - --Highlight - gc_setColor(1,1,1,ATV*.08*(math.sin(TIME()*4.2)*.2+.8)) - gc_rectangle('fill',x,y,w,h,4) - - --Frame - gc_setColor(1,1,1) - gc_setLineWidth(3) - gc_rectangle('line',x,y,w,h,3) - - --Drawable - local f=self.font - FONT.set(f,self.fType) - if self.obj then - gc_draw(self.obj,x-12-self.obj:getWidth(),y+h*.5-self.obj:getHeight()*.5) - end - if self.secret then - y=y+h*.5-f*.2 - for i=1,#self.value do - gc_rectangle("fill",x+f*.6*i,y,f*.4,f*.4) - end - else - gc_printf(self.value,x+10,y,self.w) - FONT.set(f-10) - if WIDGET.sel==self then - gc_print(EDITING,x+10,y+12-f*1.4) - end - end -end -function inputBox:getInfo() - return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h) -end -function inputBox:press() - if MOBILE then - local _,y1=xOy:transformPoint(0,self.y+self.h) - kb.setTextInput(true,0,y1,1,1) - end -end -function inputBox:keypress(k) - local t=self.value - if #t>0 and EDITING==""then - if k=='backspace'then - local p=#t - while t:byte(p)>=128 and t:byte(p)<192 do - p=p-1 - end - t=sub(t,1,p-1) - SFX.play('lock') - elseif k=='delete'then - t="" - SFX.play('hold') - end - self.value=t - end -end -function WIDGET.newInputBox(D)--name,x,y,w[,h][,font=30][,fType][,secret][,regex][,limit],hide - local _={ - name= D.name or"_", - - x= D.x, - y= D.y, - w= D.w, - h= D.h, - - resCtr={ - D.x+D.w*.2,D.y, - D.x+D.w*.5,D.y, - D.x+D.w*.8,D.y, - }, - - font= D.font or int(D.h/7-1)*5, - fType= D.fType, - secret=D.secret==true, - regex= D.regex, - limit= D.limit, - hideF= D.hideF, - hide= D.hide, - } - for k,v in next,inputBox do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local textBox={ - type='textBox', - scrollPos=0,--Scroll-down-distance - sure=0,--Sure-timer for clear history -} -function textBox:reset() - --haha nothing here, techmino is so fun! -end -function textBox:setTexts(t) - self.texts=t - self.scrollPos=0 -end -function textBox:clear() - self.texts={} - self.scrollPos=0 - SFX.play('fall') -end -function textBox:isAbove(x,y) - return - x>self.x and - y>self.y and - x0 then - self.sure=max(self.sure-dt,0) - end -end -function textBox:push(t) - ins(self.texts,t) - if self.scrollPos==(#self.texts-1-self.capacity)*self.lineH then--minus 1 for the new message - self.scrollPos=min(self.scrollPos+self.lineH,(#self.texts-self.capacity)*self.lineH) - end -end -function textBox:press(x,y) - if not(x and y)then return end - self:drag(0,0,0,0) - if not self.fix and x>self.x+self.w-40 and y0 then - self:clear() - self.sure=0 - else - self.sure=1 - end - end -end -function textBox:drag(_,_,_,dy) - self.scrollPos=max(0,min(self.scrollPos-dy,(#self.texts-self.capacity)*self.lineH)) -end -function textBox:scroll(dir) - if type(dir)=='string'then - if dir=="up"then - dir=-1 - elseif dir=="down"then - dir=1 - else - return - end - end - self:drag(nil,nil,nil,-dir*self.lineH) -end -function textBox:arrowKey(k) - if k=='up'then - self:scroll(-1) - elseif k=='down'then - self:scroll(-1) - end -end -function textBox:draw() - local x,y,w,h=self.x,self.y,self.w,self.h - local texts=self.texts - local scrollPos=self.scrollPos - local cap=self.capacity - local lineH=self.lineH - - --Background - gc_setColor(0,0,0,.3) - gc_rectangle('fill',x,y,w,h,4) - - --Frame - gc_setLineWidth(2) - gc_setColor(WIDGET.sel==self and COLOR.lN or COLOR.Z) - gc_rectangle('line',x,y,w,h,3) - - --Texts - FONT.set(self.font,self.fType) - gc_push('transform') - gc_translate(x,y) - - --Slider - gc_setColor(1,1,1) - if #texts>cap then - local len=h*h/(#texts*lineH) - gc_rectangle('fill',-15,(h-len)*scrollPos/((#texts-cap)*lineH),12,len,3) - end - - --Clear button - if not self.fix then - gc_rectangle('line',w-40,0,40,40,3) - gc_draw(self.sure==0 and clearIcon or sureIcon,w-40,0) - end - - gc_setStencilTest('equal',1) - STW,STH=w,h - gc_stencil(_rectangleStencil) - gc_translate(0,-(scrollPos%lineH)) - local pos=int(scrollPos/lineH) - for i=pos+1,min(pos+cap+1,#texts)do - gc_printf(texts[i],10,4,w-16) - gc_translate(0,lineH) - end - gc_setStencilTest() - gc_pop() -end -function textBox:getInfo() - return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h) -end -function WIDGET.newTextBox(D)--name,x,y,w,h[,font=30][,fType][,lineH][,fix],hide - local _={ - name= D.name or"_", - - resCtr={ - D.x+D.w*.5,D.y+D.h*.5, - D.x+D.w*.5,D.y, - D.x-D.w*.5,D.y, - D.x,D.y+D.h*.5, - D.x,D.y-D.h*.5, - D.x,D.y, - D.x+D.w,D.y, - D.x,D.y+D.h, - D.x+D.w,D.y+D.h, - }, - - x= D.x, - y= D.y, - w= D.w, - h= D.h, - - font= D.font or 30, - fType=D.fType, - fix= D.fix, - texts={}, - hideF=D.hideF, - hide= D.hide, - } - _.lineH=D.lineH or _.font*7/5 - _.capacity=ceil((D.h-10)/_.lineH) - - for k,v in next,textBox do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -local listBox={ - type='listBox', - keepFocus=true, - scrollPos=0,--Scroll-down-distance - selected=0,--Hidden wheel move value -} -function listBox:reset() - --haha nothing here too, techmino is really fun! -end -function listBox:clear() - self.list={} - self.scrollPos=0 -end -function listBox:setList(t) - self.list=t - self.selected=1 - self.scrollPos=0 -end -function listBox:getList() - return self.list -end -function listBox:getLen() - return #self.list -end -function listBox:getSel() - return self.list[self.selected] -end -function listBox:isAbove(x,y) - return - x>self.x and - y>self.y and - x0 then - rem(self.list) - listBox:drag(0,0,0,0) - end -end -function listBox:remove() - if self.selected then - rem(self.list,self.selected) - if not self.list[self.selected]then - self:arrowKey('up') - end - self:drag(0,0,0,0) - end -end -function listBox:press(x,y) - if not(x and y)then return end - x,y=x-self.x,y-self.y - if not(x and y and x>0 and y>0 and x<=self.w and y<=self.h)then return end - self:drag(0,0,0,0) - y=int((y+self.scrollPos)/self.lineH)+1 - if self.list[y]then - if self.selected~=y then - self.selected=y - SFX.play('selector',.8,0,12) - end - end -end -function listBox:drag(_,_,_,dy) - self.scrollPos=max(0,min(self.scrollPos-dy,(#self.list-self.capacity)*self.lineH)) -end -function listBox:scroll(n) - self:drag(nil,nil,nil,-n*self.lineH) -end -function listBox:arrowKey(dir) - if dir=="up"then - self.selected=max(self.selected-1,1) - if self.selectedint(self.scrollPos/self.lineH)+self.capacity-1 then - self:drag(nil,nil,nil,-self.lineH) - end - end -end -function listBox:select(i) - self.selected=i - if self.selectedint(self.scrollPos/self.lineH)+self.capacity-1 then - self:drag(nil,nil,nil,-1e99) - end -end -function listBox:draw() - local x,y,w,h=self.x,self.y,self.w,self.h - local list=self.list - local scrollPos=self.scrollPos - local cap=self.capacity - local lineH=self.lineH - - gc_push('transform') - gc_translate(x,y) - - --Background - gc_setColor(0,0,0,.4) - gc_rectangle('fill',0,0,w,h,4) - - --Frame - gc_setColor(WIDGET.sel==self and COLOR.lN or COLOR.Z) - gc_setLineWidth(2) - gc_rectangle('line',0,0,w,h,3) - - --Slider - if #list>cap then - gc_setColor(1,1,1) - local len=h*h/(#list*lineH) - gc_rectangle('fill',-15,(h-len)*scrollPos/((#list-cap)*lineH),12,len,3) - end - - --List - gc_setStencilTest('equal',1) - STW,STH=w,h - gc_stencil(_rectangleStencil) - local pos=int(scrollPos/lineH) - gc_translate(0,-(scrollPos%lineH)) - for i=pos+1,min(pos+cap+1,#list)do - self.drawF(list[i],i,i==self.selected) - gc_translate(0,lineH) - end - gc_setStencilTest() - gc_pop() -end -function listBox:getInfo() - return("x=%d,y=%d,w=%d,h=%d"):format(self.x+self.w*.5,self.y+self.h*.5,self.w,self.h) -end -function WIDGET.newListBox(D)--name,x,y,w,h,lineH,drawF[,hideF][,hide] - local _={ - name= D.name or"_", - - resCtr={ - D.x+D.w*.5,D.y+D.h*.5, - D.x+D.w*.5,D.y, - D.x-D.w*.5,D.y, - D.x,D.y+D.h*.5, - D.x,D.y-D.h*.5, - D.x,D.y, - D.x+D.w,D.y, - D.x,D.y+D.h, - D.x+D.w,D.y+D.h, - }, - - x= D.x, - y= D.y, - w= D.w, - h= D.h, - - list= {}, - lineH= D.lineH, - capacity=ceil(D.h/D.lineH), - drawF= D.drawF, - hideF= D.hideF, - hide= D.hide, - } - - for k,v in next,listBox do _[k]=v end - setmetatable(_,widgetMetatable) - return _ -end - -WIDGET.active={}--Table contains all active widgets -WIDGET.scrollHeight=0--Max drag height, not actual container height! -WIDGET.scrollPos=0--Current scroll position -WIDGET.sel=false--Selected widget -WIDGET.indexMeta={ - __index=function(L,k) - for i=1,#L do - if L[i].name==k then - return L[i] - end - end - end -} -function WIDGET.setWidgetList(list) - WIDGET.unFocus(true) - WIDGET.active=list or NONE - WIDGET.cursorMove(SCR.xOy:inverseTransformPoint(love.mouse.getPosition())) - - --Reset all widgets - if list then - for i=1,#list do - list[i]:reset() - end - onChange() - end -end -function WIDGET.setScrollHeight(height) - WIDGET.scrollHeight=height and height or 0 - WIDGET.scrollPos=0 -end -function WIDGET.setLang(widgetText) - for S,L in next,SCN.scenes do - if L.widgetList then - for _,W in next,L.widgetList do - local t=W.fText or widgetText[S][W.name] - if not t and W.mustHaveText then - t=W.name or"##" - W.color=COLOR.dV - end - if type(t)=='string'and W.font then - t=gc.newText(FONT.get(W.font),t) - end - W.obj=t - end - end - end -end -function WIDGET.getSelected() - return WIDGET.sel -end -function WIDGET.isFocus(W) - if W then - return W and WIDGET.sel==W - else - return WIDGET.sel~=false - end -end -function WIDGET.focus(W) - if WIDGET.sel==W then return end - if WIDGET.sel and WIDGET.sel.type=='inputBox'then - kb.setTextInput(false) - EDITING="" - end - WIDGET.sel=W - if W and W.type=='inputBox'then - local _,y1=xOy:transformPoint(0,W.y+W.h) - kb.setTextInput(true,0,y1,1,1) - end -end -function WIDGET.unFocus(force) - local W=WIDGET.sel - if W and(force or not W.keepFocus)then - if W.type=='inputBox'then - kb.setTextInput(false) - EDITING="" - end - WIDGET.sel=false - end -end - -function WIDGET.cursorMove(x,y) - for _,W in next,WIDGET.active do - if not W.hide and W.resCtr and W:isAbove(x,y+WIDGET.scrollPos)then - WIDGET.focus(W) - return - end - end - if WIDGET.sel and not WIDGET.sel.keepFocus then - WIDGET.unFocus() - end -end -function WIDGET.press(x,y,k) - local W=WIDGET.sel - if W then - W:press(x,y and y+WIDGET.scrollPos,k) - if W.hide then WIDGET.unFocus()end - end -end -function WIDGET.drag(x,y,dx,dy) - if WIDGET.sel then - local W=WIDGET.sel - if W.drag then - W:drag(x,y+WIDGET.scrollPos,dx,dy) - elseif not W:isAbove(x,y+WIDGET.scrollPos)then - WIDGET.unFocus(true) - end - else - WIDGET.scrollPos=max(min(WIDGET.scrollPos-dy,WIDGET.scrollHeight),0) - end -end -function WIDGET.release(x,y) - local W=WIDGET.sel - if W and W.release then - W:release(x,y+WIDGET.scrollPos) - end -end -function WIDGET.textinput(texts) - local W=WIDGET.sel - if W and W.type=='inputBox'then - if(not W.regex or texts:match(W.regex))and(not W.limit or #(WIDGET.sel.value..texts)<=W.limit)then - WIDGET.sel.value=WIDGET.sel.value..texts - SFX.play('touch') - else - SFX.play('drop_cancel') - end - end -end - -function WIDGET.update(dt) - for _,W in next,WIDGET.active do - if W.hideF then - W.hide=W.hideF() - if W.hide and W==WIDGET.sel then - WIDGET.unFocus(true) - end - end - if W.update then W:update(dt)end - end -end -local widgetCanvas -local widgetCover do - local L={1,360,{'fRect',0,30,1,300}} - for i=0,30 do - ins(L,{'setCL',1,1,1,i/30}) - ins(L,{'fRect',0,i,1,2}) - ins(L,{'fRect',0,360-i,1,2}) - end - widgetCover=GC.DO(L) -end -local scr_w,scr_h -function WIDGET.resize(w,h) - scr_w,scr_h=w,h - widgetCanvas=gc.newCanvas(w,h) -end -function WIDGET.draw() - gc_setCanvas({stencil=true},widgetCanvas) - gc_translate(0,-WIDGET.scrollPos) - for _,W in next,WIDGET.active do - if not W.hide then W:draw()end - end - gc_origin() - gc_setColor(1,1,1) - if WIDGET.scrollHeight>0 then - if WIDGET.scrollPos>0 then - gc_draw(upArrowIcon,scr_w*.5,10,0,SCR.k,nil,upArrowIcon:getWidth()*.5,0) - end - if WIDGET.scrollPos>'..k)print(debug.traceback():match("\n.-\n\t(.-): "))rawset(self,k,v)end}) +-- Var leak check +-- setmetatable(_G,{__newindex=function(self,k,v) print('>>'..k..string.rep(" ",26-#k),debug.traceback():match("\n.-\n\t(.-): "))rawset(self,k,v) end}) ---System Global Vars Declaration +-- System Global Vars Declaration local fs=love.filesystem VERSION=require"version" TIME=love.timer.getTime -YIELD=coroutine.yield -SYSTEM=love.system.getOS()if SYSTEM=='OS X'then SYSTEM='macOS'end -FNNS=SYSTEM:find'\79\83'--What does FNSF stand for? IDK so don't ask me lol -MOBILE=SYSTEM=='Android'or SYSTEM=='iOS' -SAVEDIR=fs.getSaveDirectory() ---Global Vars & Settings +-- Global Vars & Settings SFXPACKS={'chiptune'} -VOCPACKS={'miya',--[['mono',]]'xiaoya','miku'} +VOCPACKS={'miya','mono','xiaoya','flore','miku','zundamon'} FIRSTLAUNCH=false DAILYLAUNCH=false ---System setting +-- System setting math.randomseed(os.time()*626) love.setDeprecationOutput(false) love.keyboard.setKeyRepeat(true) love.keyboard.setTextInput(false) -if MOBILE then - local w,h,f=love.window.getMode() - f.resizable=false - love.window.setMode(w,h,f) -end local _LOADTIMELIST_={} local _LOADTIME_=TIME() ---Load modules +-- Load modules Z=require'Zframework' FONT.load{ - norm='parts/fonts/proportional.ttf', - mono='parts/fonts/monospaced.ttf', + norm='parts/fonts/proportional.otf', + mono='parts/fonts/monospaced.otf', } FONT.setDefault('norm') FONT.setFallback('norm') -SCR.setSize(1280,720)--Initialize Screen size +SCR.setSize(1280,720)-- Initialize Screen size BGM.setMaxSources(5) -BGM.setChange(function(name)MES.new('music',text.nowPlaying..name,5)end) VOC.setDiversion(.62) WIDGET.setOnChange(function() - if SCN.cur~='custom_field'then + if SCN.cur~='net_game' and SCN.cur~='custom_field' then local colorList=THEME.getThemeColor() - if not colorList then return end - local rnd=math.random - for _,W in next,SCN.scenes[SCN.cur].widgetList do - if W.color then - W.color=colorList[rnd(#colorList)] + if colorList then + for _,W in next,SCN.scenes[SCN.cur].widgetList do + if W.color then + W.color=colorList[math.random(#colorList)] + end end end end end) -table.insert(_LOADTIMELIST_,("Load Zframework: %.3fs"):format(TIME()-_LOADTIME_)) - ---Create shortcuts +-- Create shortcuts setFont=FONT.set getFont=FONT.get -mStr=GC.mStr mText=GC.simpX -mDraw=GC.draw +mDraw=GC.mDraw Snd=SFX.playSample string.repD=STRING.repD string.sArg=STRING.sArg string.split=STRING.split ---Delete all naked files (from too old version) +-- Delete all naked files (from ancient versions) FILE.clear('') ---Create directories -for _,v in next,{'conf','record','replay','cache','lib'}do +-- Create directories +for _,v in next,{'conf','record','replay','cache','lib'} do local info=fs.getInfo(v) if not info then fs.createDirectory(v) - elseif info.type~='directory'then + elseif info.type~='directory' then fs.remove(v) fs.createDirectory(v) end end -CHAR=require'parts.char' -require'parts.gameTables' -require'parts.gameFuncs' - ---Load shader files from SOURCE ONLY +-- Load shader files from SOURCE ONLY SHADER={} -for _,v in next,fs.getDirectoryItems('parts/shaders')do - if isSafeFile('parts/shaders/'..v)then +for _,v in next,fs.getDirectoryItems('parts/shaders') do + if FILE.isSafe('parts/shaders/'..v) then local name=v:sub(1,-6) SHADER[name]=love.graphics.newShader('parts/shaders/'..name..'.glsl') end end +-- Load modules +CHAR=require'parts.char' +require'parts.gameTables' +require'parts.gameFuncs' + THEME= require'parts.theme' LINE= require'parts.line' DATA= require'parts.data' @@ -125,7 +111,7 @@ USERS= require'parts.users' NET= require'parts.net' VK= require'parts.virtualKey' BOT= require'parts.bot' -RSlist= require'parts.RSlist'DSCP=RSlist.TRS.centerPos +RSlist= require'parts.RSlist'; DSCP=RSlist.TRS.centerPos PLY= require'parts.player' NETPLY= require'parts.netPlayer' MODES= require'parts.modes' @@ -136,10 +122,29 @@ setmetatable(TEXTURE,{__index=function(self,k) return self[k] end}) -table.insert(_LOADTIMELIST_,("Load Parts: %.3fs"):format(TIME()-_LOADTIME_)) +-- Load mode files +for i=1,#MODES do + local m=MODES[i]-- Mode template + if FILE.isSafe('parts/modes/'..m.name) then + TABLE.complete(require('parts.modes.'..m.name),MODES[i]) + MODES[m.name],MODES[i]=MODES[i] + end +end +for _,v in next,fs.getDirectoryItems('parts/modes') do + if FILE.isSafe('parts/modes/'..v) and not MODES[v:sub(1,-5)] then + local M={name=v:sub(1,-5)} + local modeData=require('parts.modes.'..M.name) + if modeData.env then + TABLE.complete(modeData,M) + MODES[M.name]=M + end + end +end + +table.insert(_LOADTIMELIST_,("Load Modules: %.3fs"):format(TIME()-_LOADTIME_)) ---Init Zframework -do--Z.setCursor +-- Initialize Zframework +do-- Z.setCursor local normImg=GC.DO{16,16, {'fCirc',8,8,4}, {'setCL',1,1,1,.7}, @@ -150,28 +155,26 @@ do--Z.setCursor {'dCirc',8,8,7}, {'fCirc',8,8,3}, } - local min,int,abs=math.min,math.floor,math.abs - local gc_setColor,gc_draw=love.graphics.setColor,love.graphics.draw - local ms=love.mouse + local _ Z.setCursor(function(time,x,y) if not SETTING.sysCursor then - local R=int((time+1)/2)%7+1 + local R=math.floor((time+1)/2)%7+1 _=BLOCK_COLORS[SETTING.skin[R]] - gc_setColor(_[1],_[2],_[3],min(abs(1-time%2),.3)) + GC.setColor(_[1],_[2],_[3],math.min(math.abs(1-time%2),.3)) _=DSCP[R][0] - gc_draw(TEXTURE.miniBlock[R],x,y,time%3.14159265359*4,16,16,_[2]+.5,#BLOCKS[R][0]-_[1]-.5) - gc_setColor(1,1,1) - gc_draw(ms.isDown(1)and holdImg or normImg,x,y,nil,nil,nil,8,8) + GC.draw(TEXTURE.miniBlock[R],x,y,time%math.pi*4,8,8,2*_[2]+1,2*(#BLOCKS[R][0]-_[1])-1) + GC.setColor(1,1,1) + GC.draw(love.mouse.isDown(1) and holdImg or normImg,x,y,nil,nil,nil,8,8) end end) end Z.setOnFnKeys({ - function()MES.new('check',PROFILE.switch()and"profile start!"or"profile report copied!")end, - function()MES.new('info',("System:%s[%s]\nluaVer:%s\njitVer:%s\njitVerNum:%s"):format(SYSTEM,jit.arch,_VERSION,jit.version,jit.version_num))end, - function()MES.new('error',"挂了")end, + function() MES.new('check',PROFILE.switch() and "profile start!" or "profile report copied!") end, + function() MES.new('info',("System:%s[%s]\nluaVer:%s\njitVer:%s\njitVerNum:%s"):format(SYSTEM,jit.arch,_VERSION,jit.version,jit.version_num)) end, + function() MES.new('error',"挂了") end, function() if GAME.playing and not GAME.net then - for _=1,8 do + for _=1,1 do if #PLY_ALIVE>1 then local P=PLY_ALIVE[math.random(2,#PLY_ALIVE)] P.lastRecv=PLAYERS[1] @@ -180,20 +183,25 @@ Z.setOnFnKeys({ end end end, - function()print(WIDGET.getSelected()or"no widget selected")end, - function()for k,v in next,_G do print(k,v)end end, - function()if love['_openConsole']then love['_openConsole']()end end, + function() print(BG.locked) end, + function() for k,v in next,_G do print(k,v) end end, + function() if love['_openConsole'] then love['_openConsole']() end end, }) +Z.setOnGlobalKey('f11',function() + if not MOBILE then + SETTING.fullscreen=not SETTING.fullscreen + applySettings() + saveSettings() + end +end) +Z.setVersionText(VERSION.string) Z.setDebugInfo{ {"Cache",gcinfo}, {"Tasks",TASK.getCount}, {"Voices",VOC.getQueueCount}, {"Audios",love.audio.getSourceCount}, } -Z.setOnResize(function(w,_) - SHADER.warning:send('w',w*SCR.dpi) -end) -do--Z.setOnFocus +do-- Z.setOnFocus local function task_autoSoundOff() while true do coroutine.yield() @@ -221,52 +229,28 @@ do--Z.setOnFocus TASK.new(task_autoSoundOn) end else - if SCN.cur=='game'and SETTING.autoPause then + if SCN.cur=='game' and SETTING.autoPause then pauseGame() end - if SETTING.autoMute then + if SETTING.autoMute and SCN.cur~='music' then TASK.removeTask_code(task_autoSoundOn) TASK.new(task_autoSoundOff) end end end) end -Z.setOnQuit(destroyPlayers) - ---Load settings and statistics -TABLE.cover (loadFile('conf/user','-canSkip')or{},USER) -TABLE.cover (loadFile('conf/unlock','-canSkip')or{},RANKS) -TABLE.update(loadFile('conf/settings','-canSkip')or{},SETTING) -TABLE.coverR(loadFile('conf/data','-canSkip')or{},STAT) -TABLE.cover (loadFile('conf/key','-canSkip')or{},KEY_MAP) -TABLE.cover (loadFile('conf/virtualkey','-json -canSkip')or{},VK_ORG) - ---Initialize fields, sequence, missions, gameEnv for cutsom game -local fieldData=loadFile('conf/customBoards','-string -canSkip') -if fieldData then - fieldData=STRING.split(fieldData,"!") - for i=1,#fieldData do - DATA.pasteBoard(fieldData[i],i) - end -else - FIELD[1]=DATA.newBoard() -end -local sequenceData=loadFile('conf/customSequence','-string -canSkip') -if sequenceData then - DATA.pasteSequence(sequenceData) -end -local missionData=loadFile('conf/customMissions','-string -canSkip') -if missionData then - DATA.pasteMission(missionData) -end -local customData=loadFile('conf/customEnv','-canSkip') -if customData and customData['version']==VERSION.code then - TABLE.complete(customData,CUSTOMENV) -end -TABLE.complete(require"parts.customEnv0",CUSTOMENV) - +Z.setOnBeforeQuit(function() + NET.ws_close() + TASK.new(function() + TEST.yieldT(.26) + love.event.quit() + end) +end) +Z.setOnQuit(function() + destroyPlayers() +end) ---Initialize image libs +-- Initialize image libs IMG.init{ lock='media/image/mess/lock.png', dialCircle='media/image/mess/dialCircle.png', @@ -274,7 +258,6 @@ IMG.init{ lifeIcon='media/image/mess/life.png', badgeIcon='media/image/mess/badge.png', ctrlSpeedLimit='media/image/mess/ctrlSpeedLimit.png', - speedLimit='media/image/mess/speedLimit.png',--Not used, for future C2-mode pay1='media/image/mess/pay1.png', pay2='media/image/mess/pay2.png', @@ -287,7 +270,18 @@ IMG.init{ monoCH='media/image/characters/mono.png', xiaoyaCH='media/image/characters/xiaoya.png', xiaoyaOmino='media/image/characters/xiaoya_Omino.png', + floreCH='media/image/characters/flore.png', mikuCH='media/image/characters/miku.png', + zundamonCH='media/image/characters/zundamon.png', + z={ + character='media/image/characters/z_character.png', + screen1='media/image/characters/z_screen1.png', + screen2='media/image/characters/z_screen2.png', + particle1='media/image/characters/z_particle1.png', + particle2='media/image/characters/z_particle2.png', + particle3='media/image/characters/z_particle3.png', + particle4='media/image/characters/z_particle4.png', + }, electric='media/image/characters/electric.png', hbm='media/image/characters/hbm.png', @@ -321,31 +315,35 @@ SKIN.load{ {name="yinyang_scf",path='media/image/skin/yinyang_scf.png'}, {name="cartooncup_earety",path='media/image/skin/cartooncup_earety.png'}, {name="jelly_miya",path='media/image/skin/jelly_miya.png'}, + {name="guidetris_xmiao_lusisi",path='media/image/skin/guidetris_xmiao_lusisi.png'}, {name="brick_notypey",path='media/image/skin/brick_notypey.png'}, {name="gem_notypey",path='media/image/skin/gem_notypey.png'}, {name="classic",path='media/image/skin/classic_unknown.png'}, {name="ball_shaw",path='media/image/skin/ball_shaw.png'}, {name="retro_notypey",path='media/image/skin/retro_notypey.png'}, {name="pixel_chno",path='media/image/skin/pixel_chno.png'}, + {name="pastel_chno",path='media/image/skin/pastel_chno.png'}, + {name="letters_chno",path='media/image/skin/letters_chno.png'}, + {name="kanji_chno",path='media/image/skin/kanji_chno.png'}, {name="textbone_mrz",path='media/image/skin/textbone_mrz.png'}, {name="coloredbone_mrz",path='media/image/skin/coloredbone_mrz.png'}, {name="wtf",path='media/image/skin/wtf_mrz.png'}, } ---Initialize sound libs +-- Initialize sound libs SFX.init((function()--[Warning] Not loading files here, just get the list of sound needed local L={} - for _,v in next,fs.getDirectoryItems('media/effect/chiptune/')do - if isSafeFile('media/effect/chiptune/'..v,"Dangerous file : %SAVE%/media/effect/chiptune/"..v)then + for _,v in next,fs.getDirectoryItems('media/effect/chiptune/') do + if FILE.isSafe('media/effect/chiptune/'..v) then table.insert(L,v:sub(1,-5)) end end return L end)()) -BGM.load((function() +BGM.init((function() local L={} - for _,v in next,fs.getDirectoryItems('media/music')do - if isSafeFile('media/music/'..v,"Dangerous file : %SAVE%/media/music/"..v)then + for _,v in next,fs.getDirectoryItems('media/music') do + if FILE.isSafe('media/music/'..v) then L[v:sub(1,-5)]='media/music/'..v end end @@ -353,7 +351,7 @@ BGM.load((function() end)()) VOC.init{ 'zspin','sspin','jspin','lspin','tspin','ospin','ispin','pspin','qspin','fspin','espin','uspin','vspin','wspin','xspin','rspin','yspin','nspin','hspin','cspin', - 'single','double','triple','techrash','pentacrash','hexacrash', + 'single','double','triple','techrash','pentacrash','hexacrash','heptacrash','octacrash','nonacrash','decacrash','undecacrash','dodecacrash','tridecacrash','tetradecacrash','pentadecacrash','hexadecacrash','heptadecacrash','octadecacrash','nonadecacrash','ultracrash','impossicrash', 'mini','b2b','b3b', 'perfect_clear','half_clear', 'win','lose','bye', @@ -361,235 +359,194 @@ VOC.init{ 'welcome', } ---Initialize language lib -LANG.init('zh', - { - zh=require'parts.language.lang_zh', - zh_trad=require'parts.language.lang_zh_trad', - zh_full=require'parts.language.lang_zh_full', - en=require'parts.language.lang_en', - fr=require'parts.language.lang_fr', - es=require'parts.language.lang_es', - pt=require'parts.language.lang_pt', - id=require'parts.language.lang_id', - ja=require'parts.language.lang_ja', - zh_grass=require'parts.language.lang_zh_grass', - symbol=require'parts.language.lang_symbol', - --1. Add language file to LANG folder; - --2. Require it; - --3. Add a button in parts/scenes/lang.lua; - }, - { - block=BLOCK_NAMES - }, - (function() - local tipMeta={__call=function(L)return L[math.random(#L)]end} - return function(L) - if type(rawget(L,'getTip'))=='table'then setmetatable(L.getTip,tipMeta)end - setmetatable(L,{__index=function(self,k) - local mes="No Text ("..SETTING.locale.."): "..k - LOG(mes) - MES.new('warn',mes) - self[k]=CHAR.zChan.thinking - return self[k] - end}) - end - end)() -) - -table.insert(_LOADTIMELIST_,("Initialize Parts: %.3fs"):format(TIME()-_LOADTIME_)) +table.insert(_LOADTIMELIST_,("Initialize Modules: %.3fs"):format(TIME()-_LOADTIME_)) + +-- Load settings and statistics +if + not ( + pcall(TABLE.cover, loadFile('conf/user', '-json -canSkip') or loadFile('conf/user', '-luaon -canSkip') or{},USER) and + pcall(TABLE.cover, loadFile('conf/unlock', '-json -canSkip') or loadFile('conf/unlock', '-luaon -canSkip') or{},RANKS) and + pcall(TABLE.update,loadFile('conf/settings', '-json -canSkip') or loadFile('conf/settings', '-luaon -canSkip') or{},SETTING) and + pcall(TABLE.coverR,loadFile('conf/data', '-json -canSkip') or loadFile('conf/data', '-luaon -canSkip') or{},STAT) and + pcall(TABLE.cover, loadFile('conf/key', '-json -canSkip') or loadFile('conf/key', '-luaon -canSkip') or{},KEY_MAP) and + pcall(TABLE.cover, loadFile('conf/virtualkey','-json -canSkip') or loadFile('conf/virtualkey','-luaon -canSkip') or{},VK_ORG) + ) +then + MES.new('error',"An error occured during loading, and some data was lost.") +end ---Load background files from SOURCE ONLY -for _,v in next,fs.getDirectoryItems('parts/backgrounds')do - if isSafeFile('parts/backgrounds/'..v)and v:sub(-3)=='lua'then - local name=v:sub(1,-5) - BG.add(name,require('parts.backgrounds.'..name)) +-- Initialize fields, sequence, missions, gameEnv for cutsom game +local fieldData=loadFile('conf/customBoards','-string -canSkip') +if fieldData then + fieldData=STRING.split(fieldData,"!") + for i=1,#fieldData do + DATA.pasteBoard(fieldData[i],i) end +else + FIELD[1]=DATA.newBoard() end -BG.remList('none')BG.remList('gray')BG.remList('custom') ---Load scene files from SOURCE ONLY -for _,v in next,fs.getDirectoryItems('parts/scenes')do - if isSafeFile('parts/scenes/'..v)then - local sceneName=v:sub(1,-5) - SCN.add(sceneName,require('parts.scenes.'..sceneName)) - LANG.addScene(sceneName) - end +local sequenceData=loadFile('conf/customSequence','-string -canSkip') +if sequenceData then + DATA.pasteSequence(sequenceData) end ---Load mode files -for i=1,#MODES do - local m=MODES[i]--Mode template - if isSafeFile('parts/modes/'..m.name)then - TABLE.complete(require('parts.modes.'..m.name),MODES[i]) - MODES[m.name],MODES[i]=MODES[i] - end +local missionData=loadFile('conf/customMissions','-string -canSkip') +if missionData then + DATA.pasteMission(missionData) end -for _,v in next,fs.getDirectoryItems('parts/modes')do - if isSafeFile('parts/modes/'..v)and not MODES[v:sub(1,-5)]then - local M={name=v:sub(1,-5)} - local modeData=require('parts.modes.'..M.name) - if modeData.env then - TABLE.complete(modeData,M) - MODES[M.name]=M - end - end +local customData=loadFile('conf/customEnv','-canSkip') +if customData and customData['version']==VERSION.code then + TABLE.complete(customData,CUSTOMENV) end +TABLE.complete(require"parts.customEnv0",CUSTOMENV) -table.insert(_LOADTIMELIST_,("Load Files: %.3fs"):format(TIME()-_LOADTIME_)) - ---Update data +-- Update data do - local needSave - - if not fs.getInfo('conf/data')then - needSave=true - end - if type(STAT.version)~='number'then + if type(STAT.version)~='number' then STAT.version=0 - needSave=true - end - if STAT.version<1500 then - FILE.clear_s('') - end - if STAT.version<1505 then - fs.remove('record/bigbang.rec') - fs.remove('conf/replay') - end - if STAT.version==1506 then - local temp1,temp2 - if fs.getInfo('record/master_l.rec')then - temp1=fs.read('record/master_l.rec') - end - if fs.getInfo('record/master_u.rec')then - temp2=fs.read('record/master_u.rec') - end - if temp1 then - fs.write('record/master_u.rec',temp1) - end - if temp2 then - fs.write('record/master_l.rec',temp2) - end - RANKS.master_l,RANKS.master_u=RANKS.master_u,RANKS.master_l - if RANKS.tsd_u then - RANKS.tsd_u=0 - end - end - if STAT.version==1601 then - RANKS.round_e=nil - RANKS.round_n=nil - RANKS.round_h=nil - RANKS.round_l=nil - RANKS.round_u=nil - fs.remove('record/round_e.rec') - fs.remove('record/round_n.rec') - fs.remove('record/round_h.rec') - fs.remove('record/round_l.rec') - fs.remove('record/round_u.rec') end if STAT.version<1700 and SETTING.dascut<5 then SETTING.dascut=SETTING.dascut+1 - needSave=true - end - if SETTING.vocPack=='mono'then - SETTING.vocPack='miya' end + if RANKS.stack_e then - RANKS.stack_e=nil - RANKS.stack_h=nil - RANKS.stack_u=nil - fs.remove('record/stack_e.rec') - fs.remove('record/stack_h.rec') - fs.remove('record/stack_u.rec') + RANKS.stack_e=nil; fs.remove('record/stack_e.rec') + RANKS.stack_h=nil; fs.remove('record/stack_h.rec') + RANKS.stack_u=nil; fs.remove('record/stack_u.rec') end if RANKS.stack_20l then - RANKS.stack_20l=nil - RANKS.stack_40l=nil - RANKS.stack_100l=nil - fs.remove('record/stack_20l.rec') - fs.remove('record/stack_40l.rec') - fs.remove('record/stack_100l.rec') + RANKS.stack_20l=nil; fs.remove('record/stack_20l.rec') + RANKS.stack_40l=nil; fs.remove('record/stack_40l.rec') + RANKS.stack_100l=nil; fs.remove('record/stack_100l.rec') end if RANKS.rhythm_e then - RANKS.rhythm_e=nil - RANKS.rhythm_h=nil - RANKS.rhythm_u=nil - fs.remove('record/rhythm_e.rec') - fs.remove('record/rhythm_h.rec') - fs.remove('record/rhythm_u.rec') - end - if RANKS.bigbang then - RANKS.clearRush,RANKS.bigbang=RANKS.bigbang - fs.remove('record/bigbang.rec') + RANKS.rhythm_e=nil; fs.remove('record/rhythm_e.rec') + RANKS.rhythm_h=nil; fs.remove('record/rhythm_h.rec') + RANKS.rhythm_u=nil; fs.remove('record/rhythm_u.rec') end + if RANKS.bigbang then fs.remove('record/bigbang.rec') end + if RANKS.clearRush then fs.remove('record/clearRush.rec') end + if STAT.version~=VERSION.code then for k,v in next,MODE_UPDATE_MAP do - if RANKS[k]then + if RANKS[k] then RANKS[v]=RANKS[k] RANKS[k]=nil end k='record/'..k - if fs.getInfo(k..'.dat')then + if fs.getInfo(k..'.dat') then fs.write('record/'..v..'.rec',fs.read(k..'.dat')) fs.remove(k..'.dat') end - if fs.getInfo(k..'.rec')then + if fs.getInfo(k..'.rec') then fs.write('record/'..v..'.rec',fs.read(k..'.rec')) fs.remove(k..'.rec') end end STAT.version=VERSION.code - needSave=true end - SETTING.appLock,SETTING.dataSaving,SETTING.swap=nil + SETTING.appLock,SETTING.dataSaving,SETTING.swap,SETTING.autoLogin=nil if not SETTING.VKSkin then SETTING.VKSkin=1 end for _,v in next,SETTING.skin do if v<1 or v>17 then v=17 end end - if not RSlist[SETTING.RS]then SETTING.RS='TRS'end - if SETTING.ghostType=='greyCell'then SETTING.ghostType='grayCell'end - if type(SETTING.skinSet)=='number'then SETTING.skinSet='crystal_scf'end - if not TABLE.find({8,10,13,17,22,29,37,47,62,80,100},SETTING.frameMul)then SETTING.frameMul=100 end + if not RSlist[SETTING.RS] then SETTING.RS='TRS' end + if SETTING.ghostType=='greyCell' then SETTING.ghostType='grayCell' end + if type(SETTING.skinSet)=='number' then SETTING.skinSet='crystal_scf' end + if not TABLE.find({8,10,13,17,22,29,37,47,62,80,100},SETTING.frameMul) then SETTING.frameMul=100 end if SETTING.cv then SETTING.vocPack,SETTING.cv=SETTING.cv end - if type(SETTING.bg)~='string'then SETTING.bg='on'end + if type(SETTING.bg)~='string' then SETTING.bg='on' end if SETTING.skin[18]==10 then SETTING.skin[18]=4 end if SETTING.reTime>3 or SETTING.reTime<.5 then SETTING.reTime=2 end + if SETTING.locale=='zh_full' then SETTING.locale='zh' end + if SETTING.vocPack=='rin' then SETTING.vocPack='miku' end if RANKS.infinite then RANKS.infinite=0 end if RANKS.infinite_dig then RANKS.infinite_dig=0 end if not RANKS.sprint_10l then RANKS.sprint_10l=0 end - if RANKS.master_l then RANKS.master_n,RANKS.master_l=RANKS.master_l needSave=true end - if RANKS.master_u then RANKS.master_h,RANKS.master_u=RANKS.master_u needSave=true end + if RANKS.master_l then RANKS.master_n,RANKS.master_l=RANKS.master_l end + if RANKS.master_u then RANKS.master_h,RANKS.master_u=RANKS.master_u end for _,v in next,VK_ORG do v.color=nil end for name,rank in next,RANKS do - if type(name)=='number'or type(rank)~='number'then + if type(name)=='number' or type(rank)~='number' then RANKS[name]=nil - needSave=true else local M=MODES[name] if M and M.unlock and rank>0 then for _,unlockName in next,M.unlock do - if not RANKS[unlockName]then + if not RANKS[unlockName] then RANKS[unlockName]=0 - needSave=true end end end - if not(M and M.x)then + if not (M and M.x) then RANKS[name]=nil - needSave=true end end end - if not MODES[STAT.lastPlay]then + if not MODES[STAT.lastPlay] then STAT.lastPlay='sprint_10l' - needSave=true end + fs.remove('conf/account') - if needSave then - saveStats() - saveProgress() - saveSettings() - love.event.quit('restart') + saveStats() + saveProgress() + saveSettings() +end + +-- Initialize language lib +LANG.init('zh', + { + zh=require'parts.language.lang_zh', + zh_trad=require'parts.language.lang_zh_trad', + en=require'parts.language.lang_en', + fr=require'parts.language.lang_fr', + es=require'parts.language.lang_es', + pt=require'parts.language.lang_pt', + id=require'parts.language.lang_id', + ja=require'parts.language.lang_ja', + symbol=require'parts.language.lang_symbol', + zh_code=require'parts.language.lang_zh_code', + vi=require'parts.language.lang_vi', + -- 1. Add language file to LANG folder; + -- 2. Require it; + -- 3. Add a button in parts/scenes/lang.lua; + }, + { + block=BLOCK_NAMES + }, + (function() + local tipMeta={__call=function(L) return L[math.random(#L)] end} + return function(L) + if type(rawget(L,'getTip'))=='table' then setmetatable(L.getTip,tipMeta) end + setmetatable(L,{__index=function(self,k) + local mes="No Text ("..SETTING.locale.."): "..k + LOG(mes) + MES.new('warn',mes) + self[k]="["..k.."]" + return self[k] + end}) + end + end)() +) + +-- Load background files from SOURCE ONLY +for _,v in next,fs.getDirectoryItems('parts/backgrounds') do + if FILE.isSafe('parts/backgrounds/'..v) and v:sub(-3)=='lua' then + local name=v:sub(1,-5) + BG.add(name,require('parts.backgrounds.'..name)) end end +BG.remList('none')BG.remList('gray')BG.remList('custom') ---First start +-- Load scene files from SOURCE ONLY +for _,v in next,fs.getDirectoryItems('parts/scenes') do + if FILE.isSafe('parts/scenes/'..v) then + local sceneName=v:sub(1,-5) + SCN.add(sceneName,require('parts.scenes.'..sceneName)) + LANG.addScene(sceneName) + end +end + +table.insert(_LOADTIMELIST_,("Load Files: %.3fs"):format(TIME()-_LOADTIME_)) + +-- First start FIRSTLAUNCH=STAT.run==0 if FIRSTLAUNCH and MOBILE then SETTING.VKSwitch=true @@ -597,21 +554,20 @@ if FIRSTLAUNCH and MOBILE then SETTING.cleanCanvas=true end ---Apply system setting +-- Apply system setting applySettings() ---Load replays -for _,fileName in next,fs.getDirectoryItems('replay')do - if fileName:sub(12,12):match("[a-zA-Z]")then +-- Load replays +for _,fileName in next,fs.getDirectoryItems('replay') do + if fileName:sub(12,12):match("[a-zA-Z]") then repeat local date,mode,version,player,seed,setting,mod - local fileData=fs.read('replay/'..fileName) + local success,fileData=true,fs.read('replay/'..fileName) date, fileData=STRING.readLine(fileData)date=date:gsub("[a-zA-Z]","") - mode, fileData=STRING.readLine(fileData)mode=MODE_UPDATE_MAP[mode]or mode + mode, fileData=STRING.readLine(fileData)mode=MODE_UPDATE_MAP[mode] or mode version,fileData=STRING.readLine(fileData) - player, fileData=STRING.readLine(fileData)if player=="Local Player"then player="Stacker"end - local success + player, fileData=STRING.readLine(fileData) if player=="Local Player" then player="Stacker" end success,fileData=pcall(love.data.decompress,'string','zlib',fileData) - if not success then goto BREAK_cannotParse end + if not success then break end seed, fileData=STRING.readLine(fileData) setting,fileData=STRING.readLine(fileData)setting=JSON.decode(setting) mod, fileData=STRING.readLine(fileData)mod=JSON.decode(mod) @@ -620,7 +576,7 @@ for _,fileName in next,fs.getDirectoryItems('replay')do not mod or not mode or #mode==0 - then goto BREAK_cannotParse end + then break end fs.remove('replay/'..fileName) local newName=fileName:sub(1,10)..fileName:sub(15) @@ -639,21 +595,26 @@ for _,fileName in next,fs.getDirectoryItems('replay')do ) ) fileName=newName - end - ::BREAK_cannotParse:: + until true end local rep=DATA.parseReplay('replay/'..fileName) table.insert(REPLAY,rep) end -table.sort(REPLAY,function(a,b)return a.fileName>b.fileName end) +table.sort(REPLAY,function(a,b) return a.fileName>b.fileName end) -table.insert(_LOADTIMELIST_,("Initialize Data: %.3fs"):format(TIME()-_LOADTIME_)) +AUTHURL="https://studio26f.org/oauth?product=techmino" +AUTHHOST="cafuuchino1.3322.org:8081" +WS.switchHost('cafuuchino1.3322.org','10026','/techmino/ws/v1') +HTTP.setHost("cafuuchino1.3322.org:10026") +HTTP.setThreadCount(1) -for i=1,#_LOADTIMELIST_ do LOG(_LOADTIMELIST_[i])end +table.insert(_LOADTIMELIST_,("Load Resources: %.3fs"):format(TIME()-_LOADTIME_)) ---Launch testing task if launch param received -if TABLE.find(arg,'--test')then +for i=1,#_LOADTIMELIST_ do LOG(_LOADTIMELIST_[i]) end + +-- Launch testing task if launch param received +if TABLE.find(arg,'-- test') then TASK.new(function() - while not LOADED do YIELD()end + while not LOADED do coroutine.yield() end LOG("\27[92m\27[1mAutomatic Test Started\27[0m") BGM.setVol(0)SFX.setVol(0) @@ -661,7 +622,7 @@ if TABLE.find(arg,'--test')then TEST.yieldUntilNextScene() for k,mode in next,MODES do - if k~='netBattle'then + if k~='netBattle' then LOG("Scanning mode: "..mode.name) loadGame(mode.name,true) TEST.yieldUntilNextScene() @@ -675,8 +636,8 @@ if TABLE.find(arg,'--test')then end) TASK.new(function() while true do - YIELD() - if Z.getErr(1)then break end + coroutine.yield() + if Z.getErr(1) then break end end LOG("\27[91m\27[1mAutomatic Test Failed :(\27[0m\nThe error message is:\n"..table.concat(Z.getErr(1).mes,"\n").."\27[91m\nAborting\27[0m") TEST.yieldN(60) diff --git a/media/effect/chiptune/achievement.ogg b/media/effect/chiptune/achievement.ogg new file mode 100644 index 000000000..1c3b8beb0 Binary files /dev/null and b/media/effect/chiptune/achievement.ogg differ diff --git a/media/effect/chiptune/back.ogg b/media/effect/chiptune/back.ogg index 63894675f..916199278 100644 Binary files a/media/effect/chiptune/back.ogg and b/media/effect/chiptune/back.ogg differ diff --git a/media/effect/chiptune/button.ogg b/media/effect/chiptune/button.ogg index ee9d75f11..11139e2b9 100644 Binary files a/media/effect/chiptune/button.ogg and b/media/effect/chiptune/button.ogg differ diff --git a/media/effect/chiptune/check.ogg b/media/effect/chiptune/check.ogg index 8d51c0ec5..564dffcf9 100644 Binary files a/media/effect/chiptune/check.ogg and b/media/effect/chiptune/check.ogg differ diff --git a/media/effect/chiptune/clear.ogg b/media/effect/chiptune/clear.ogg deleted file mode 100644 index ce32bf7a6..000000000 Binary files a/media/effect/chiptune/clear.ogg and /dev/null differ diff --git a/media/effect/chiptune/clear_1.ogg b/media/effect/chiptune/clear_1.ogg index 174b36b90..027b30a8e 100644 Binary files a/media/effect/chiptune/clear_1.ogg and b/media/effect/chiptune/clear_1.ogg differ diff --git a/media/effect/chiptune/clear_2.ogg b/media/effect/chiptune/clear_2.ogg index f8f870968..4b445e044 100644 Binary files a/media/effect/chiptune/clear_2.ogg and b/media/effect/chiptune/clear_2.ogg differ diff --git a/media/effect/chiptune/clear_3.ogg b/media/effect/chiptune/clear_3.ogg index 91ee47faa..29446bca3 100644 Binary files a/media/effect/chiptune/clear_3.ogg and b/media/effect/chiptune/clear_3.ogg differ diff --git a/media/effect/chiptune/clear_4.ogg b/media/effect/chiptune/clear_4.ogg index 971e541c1..b9cb3d1b7 100644 Binary files a/media/effect/chiptune/clear_4.ogg and b/media/effect/chiptune/clear_4.ogg differ diff --git a/media/effect/chiptune/clear_5.ogg b/media/effect/chiptune/clear_5.ogg index b3e31f54d..64559c801 100644 Binary files a/media/effect/chiptune/clear_5.ogg and b/media/effect/chiptune/clear_5.ogg differ diff --git a/media/effect/chiptune/clear_6.ogg b/media/effect/chiptune/clear_6.ogg index 9d6a8fa09..1763238a2 100644 Binary files a/media/effect/chiptune/clear_6.ogg and b/media/effect/chiptune/clear_6.ogg differ diff --git a/media/effect/chiptune/click.ogg b/media/effect/chiptune/click.ogg index 38de65e68..37b26d2d6 100644 Binary files a/media/effect/chiptune/click.ogg and b/media/effect/chiptune/click.ogg differ diff --git a/media/effect/chiptune/connect.ogg b/media/effect/chiptune/connect.ogg index 3af92aea5..0cec7d69c 100644 Binary files a/media/effect/chiptune/connect.ogg and b/media/effect/chiptune/connect.ogg differ diff --git a/media/effect/chiptune/connected.ogg b/media/effect/chiptune/connected.ogg index 05daaf083..af5ac7345 100644 Binary files a/media/effect/chiptune/connected.ogg and b/media/effect/chiptune/connected.ogg differ diff --git a/media/effect/chiptune/drop.ogg b/media/effect/chiptune/drop.ogg index ad5fa3f5f..4a7da0bac 100644 Binary files a/media/effect/chiptune/drop.ogg and b/media/effect/chiptune/drop.ogg differ diff --git a/media/effect/chiptune/drop_cancel.ogg b/media/effect/chiptune/drop_cancel.ogg index 10d930948..f8b2de178 100644 Binary files a/media/effect/chiptune/drop_cancel.ogg and b/media/effect/chiptune/drop_cancel.ogg differ diff --git a/media/effect/chiptune/emit.ogg b/media/effect/chiptune/emit.ogg index 67f0788e9..82e42635f 100644 Binary files a/media/effect/chiptune/emit.ogg and b/media/effect/chiptune/emit.ogg differ diff --git a/media/effect/chiptune/enter.ogg b/media/effect/chiptune/enter.ogg index cb830c5a9..d410c713f 100644 Binary files a/media/effect/chiptune/enter.ogg and b/media/effect/chiptune/enter.ogg differ diff --git a/media/effect/chiptune/error.ogg b/media/effect/chiptune/error.ogg index f4fa1cdc6..f04ff295b 100644 Binary files a/media/effect/chiptune/error.ogg and b/media/effect/chiptune/error.ogg differ diff --git a/media/effect/chiptune/fail.ogg b/media/effect/chiptune/fail.ogg index f99b60160..7882c2094 100644 Binary files a/media/effect/chiptune/fail.ogg and b/media/effect/chiptune/fail.ogg differ diff --git a/media/effect/chiptune/fall.ogg b/media/effect/chiptune/fall.ogg index 290c88273..675257a41 100644 Binary files a/media/effect/chiptune/fall.ogg and b/media/effect/chiptune/fall.ogg differ diff --git a/media/effect/chiptune/finesseError.ogg b/media/effect/chiptune/finesseError.ogg index 302931564..4db7dea9c 100644 Binary files a/media/effect/chiptune/finesseError.ogg and b/media/effect/chiptune/finesseError.ogg differ diff --git a/media/effect/chiptune/finesseError_long.ogg b/media/effect/chiptune/finesseError_long.ogg index cb915c35a..d9c6c4d3d 100644 Binary files a/media/effect/chiptune/finesseError_long.ogg and b/media/effect/chiptune/finesseError_long.ogg differ diff --git a/media/effect/chiptune/hold.ogg b/media/effect/chiptune/hold.ogg index 831b2116c..0d526d185 100644 Binary files a/media/effect/chiptune/hold.ogg and b/media/effect/chiptune/hold.ogg differ diff --git a/media/effect/chiptune/key.ogg b/media/effect/chiptune/key.ogg index 58aa769a1..4f60e682d 100644 Binary files a/media/effect/chiptune/key.ogg and b/media/effect/chiptune/key.ogg differ diff --git a/media/effect/chiptune/lock.ogg b/media/effect/chiptune/lock.ogg index 9268e98eb..2e6f8e632 100644 Binary files a/media/effect/chiptune/lock.ogg and b/media/effect/chiptune/lock.ogg differ diff --git a/media/effect/chiptune/prehold.ogg b/media/effect/chiptune/prehold.ogg index 605d7ac03..73e5357c9 100644 Binary files a/media/effect/chiptune/prehold.ogg and b/media/effect/chiptune/prehold.ogg differ diff --git a/media/effect/chiptune/prerotate.ogg b/media/effect/chiptune/prerotate.ogg index 9dfe91bf7..53f5f25e4 100644 Binary files a/media/effect/chiptune/prerotate.ogg and b/media/effect/chiptune/prerotate.ogg differ diff --git a/media/effect/chiptune/reach.ogg b/media/effect/chiptune/reach.ogg index 9b57e9ad2..904d06dad 100644 Binary files a/media/effect/chiptune/reach.ogg and b/media/effect/chiptune/reach.ogg differ diff --git a/media/effect/chiptune/ren_mega.ogg b/media/effect/chiptune/ren_mega.ogg index 19691cef7..c7e91411c 100644 Binary files a/media/effect/chiptune/ren_mega.ogg and b/media/effect/chiptune/ren_mega.ogg differ diff --git a/media/effect/chiptune/rotate.ogg b/media/effect/chiptune/rotate.ogg index e9d4fa003..5460c038d 100644 Binary files a/media/effect/chiptune/rotate.ogg and b/media/effect/chiptune/rotate.ogg differ diff --git a/media/effect/chiptune/rotatekick.ogg b/media/effect/chiptune/rotatekick.ogg index acea4a683..842c7fb76 100644 Binary files a/media/effect/chiptune/rotatekick.ogg and b/media/effect/chiptune/rotatekick.ogg differ diff --git a/media/effect/chiptune/selector.ogg b/media/effect/chiptune/selector.ogg index f4e6a0d8c..fe75311a4 100644 Binary files a/media/effect/chiptune/selector.ogg and b/media/effect/chiptune/selector.ogg differ diff --git a/media/effect/chiptune/spin_0.ogg b/media/effect/chiptune/spin_0.ogg index 2530c75fc..09937b6e8 100644 Binary files a/media/effect/chiptune/spin_0.ogg and b/media/effect/chiptune/spin_0.ogg differ diff --git a/media/effect/chiptune/spin_1.ogg b/media/effect/chiptune/spin_1.ogg index 28388d5db..9b9b3b557 100644 Binary files a/media/effect/chiptune/spin_1.ogg and b/media/effect/chiptune/spin_1.ogg differ diff --git a/media/effect/chiptune/spin_2.ogg b/media/effect/chiptune/spin_2.ogg index 4e5e335b2..a8f019892 100644 Binary files a/media/effect/chiptune/spin_2.ogg and b/media/effect/chiptune/spin_2.ogg differ diff --git a/media/effect/chiptune/spin_3.ogg b/media/effect/chiptune/spin_3.ogg index 238924b4a..ecd9de42f 100644 Binary files a/media/effect/chiptune/spin_3.ogg and b/media/effect/chiptune/spin_3.ogg differ diff --git a/media/effect/chiptune/swipe.ogg b/media/effect/chiptune/swipe.ogg index b7f07127b..a297b340a 100644 Binary files a/media/effect/chiptune/swipe.ogg and b/media/effect/chiptune/swipe.ogg differ diff --git a/media/effect/chiptune/touch.ogg b/media/effect/chiptune/touch.ogg index d4841bc8c..67b46448f 100644 Binary files a/media/effect/chiptune/touch.ogg and b/media/effect/chiptune/touch.ogg differ diff --git a/media/effect/chiptune/uncheck .ogg b/media/effect/chiptune/uncheck .ogg index 740d0d88f..6665d8bb1 100644 Binary files a/media/effect/chiptune/uncheck .ogg and b/media/effect/chiptune/uncheck .ogg differ diff --git a/media/effect/chiptune/uncheck.ogg b/media/effect/chiptune/uncheck.ogg index 5a7a8dc04..c79af7867 100644 Binary files a/media/effect/chiptune/uncheck.ogg and b/media/effect/chiptune/uncheck.ogg differ diff --git a/media/effect/chiptune/virtualKey.ogg b/media/effect/chiptune/virtualKey.ogg index 1571ac50a..87d80bb53 100644 Binary files a/media/effect/chiptune/virtualKey.ogg and b/media/effect/chiptune/virtualKey.ogg differ diff --git a/media/effect/chiptune/warn_1.ogg b/media/effect/chiptune/warn_1.ogg index 9c8cdc640..a0bb0489c 100644 Binary files a/media/effect/chiptune/warn_1.ogg and b/media/effect/chiptune/warn_1.ogg differ diff --git a/media/effect/chiptune/warn_2.ogg b/media/effect/chiptune/warn_2.ogg index 8d0f21f3a..bb2f33dc5 100644 Binary files a/media/effect/chiptune/warn_2.ogg and b/media/effect/chiptune/warn_2.ogg differ diff --git a/media/effect/chiptune/warn_beep.ogg b/media/effect/chiptune/warn_beep.ogg index 8c6cc2858..8615f1047 100644 Binary files a/media/effect/chiptune/warn_beep.ogg and b/media/effect/chiptune/warn_beep.ogg differ diff --git a/media/effect/chiptune/win.ogg b/media/effect/chiptune/win.ogg index c3d56b468..66724db27 100644 Binary files a/media/effect/chiptune/win.ogg and b/media/effect/chiptune/win.ogg differ diff --git a/media/image/characters/flore.png b/media/image/characters/flore.png new file mode 100644 index 000000000..923c330f8 Binary files /dev/null and b/media/image/characters/flore.png differ diff --git a/media/image/characters/miku.png b/media/image/characters/miku.png index e1fa2c1f9..f1238afb9 100644 Binary files a/media/image/characters/miku.png and b/media/image/characters/miku.png differ diff --git a/media/image/characters/mono.png b/media/image/characters/mono.png index 72cd319dc..874cba48a 100644 Binary files a/media/image/characters/mono.png and b/media/image/characters/mono.png differ diff --git a/media/image/characters/z_character.png b/media/image/characters/z_character.png new file mode 100644 index 000000000..87320213f Binary files /dev/null and b/media/image/characters/z_character.png differ diff --git a/media/image/characters/z_particle1.png b/media/image/characters/z_particle1.png new file mode 100644 index 000000000..58148fe7f Binary files /dev/null and b/media/image/characters/z_particle1.png differ diff --git a/media/image/characters/z_particle2.png b/media/image/characters/z_particle2.png new file mode 100644 index 000000000..280b31be3 Binary files /dev/null and b/media/image/characters/z_particle2.png differ diff --git a/media/image/characters/z_particle3.png b/media/image/characters/z_particle3.png new file mode 100644 index 000000000..25de7e0e8 Binary files /dev/null and b/media/image/characters/z_particle3.png differ diff --git a/media/image/characters/z_particle4.png b/media/image/characters/z_particle4.png new file mode 100644 index 000000000..a1c07638b Binary files /dev/null and b/media/image/characters/z_particle4.png differ diff --git a/media/image/characters/z_screen1.png b/media/image/characters/z_screen1.png new file mode 100644 index 000000000..4d5227ced Binary files /dev/null and b/media/image/characters/z_screen1.png differ diff --git a/media/image/characters/z_screen2.png b/media/image/characters/z_screen2.png new file mode 100644 index 000000000..d6b77e5bb Binary files /dev/null and b/media/image/characters/z_screen2.png differ diff --git a/media/image/characters/zundamon.png b/media/image/characters/zundamon.png new file mode 100644 index 000000000..1f4a06965 Binary files /dev/null and b/media/image/characters/zundamon.png differ diff --git a/media/image/mess/speedLimit.png b/media/image/mess/speedLimit.png deleted file mode 100644 index ceb602b54..000000000 Binary files a/media/image/mess/speedLimit.png and /dev/null differ diff --git a/media/image/modeicon/big.png b/media/image/modeicon/big.png new file mode 100644 index 000000000..3a6a234d0 Binary files /dev/null and b/media/image/modeicon/big.png differ diff --git a/media/image/modeicon/dig_eff.png b/media/image/modeicon/dig_eff.png new file mode 100644 index 000000000..00d72223a Binary files /dev/null and b/media/image/modeicon/dig_eff.png differ diff --git a/media/image/modeicon/secret_grade.png b/media/image/modeicon/secret_grade.png new file mode 100644 index 000000000..bb3d7ec21 Binary files /dev/null and b/media/image/modeicon/secret_grade.png differ diff --git a/media/image/modeicon/sprint_pento.png b/media/image/modeicon/sprint_pento.png new file mode 100644 index 000000000..aea62da5a Binary files /dev/null and b/media/image/modeicon/sprint_pento.png differ diff --git a/media/image/modeicon/sprint_tri.png b/media/image/modeicon/sprint_tri.png new file mode 100644 index 000000000..6203e946f Binary files /dev/null and b/media/image/modeicon/sprint_tri.png differ diff --git a/media/image/skin/guidetris_xmiao_lusisi.png b/media/image/skin/guidetris_xmiao_lusisi.png new file mode 100644 index 000000000..72daacc45 Binary files /dev/null and b/media/image/skin/guidetris_xmiao_lusisi.png differ diff --git a/media/image/skin/kanji_chno.png b/media/image/skin/kanji_chno.png new file mode 100644 index 000000000..63d5c88db Binary files /dev/null and b/media/image/skin/kanji_chno.png differ diff --git a/media/image/skin/letters_chno.png b/media/image/skin/letters_chno.png new file mode 100644 index 000000000..61847b649 Binary files /dev/null and b/media/image/skin/letters_chno.png differ diff --git a/media/image/skin/minoes_scf.png b/media/image/skin/minoes_scf.png index 769ce164a..5fe5a3b60 100644 Binary files a/media/image/skin/minoes_scf.png and b/media/image/skin/minoes_scf.png differ diff --git a/media/image/skin/pastel_chno.png b/media/image/skin/pastel_chno.png new file mode 100644 index 000000000..9b7cca1c3 Binary files /dev/null and b/media/image/skin/pastel_chno.png differ diff --git a/media/image/virtualkey.png b/media/image/virtualkey.png index eb6a6f69c..71e1cc6b6 100644 Binary files a/media/image/virtualkey.png and b/media/image/virtualkey.png differ diff --git a/media/music/antispace.ogg b/media/music/antispace.ogg new file mode 100644 index 000000000..f2b8d2384 Binary files /dev/null and b/media/music/antispace.ogg differ diff --git a/media/music/empty.ogg b/media/music/empty.ogg index 249cc8088..8b1cdc6ac 100644 Binary files a/media/music/empty.ogg and b/media/music/empty.ogg differ diff --git a/media/music/way.ogg b/media/music/way.ogg index d501b7cbc..b70240264 100644 Binary files a/media/music/way.ogg and b/media/music/way.ogg differ diff --git a/media/vocal/flore/b2b_1.ogg b/media/vocal/flore/b2b_1.ogg new file mode 100644 index 000000000..397710011 Binary files /dev/null and b/media/vocal/flore/b2b_1.ogg differ diff --git a/media/vocal/flore/b2b_2.ogg b/media/vocal/flore/b2b_2.ogg new file mode 100644 index 000000000..37e79559e Binary files /dev/null and b/media/vocal/flore/b2b_2.ogg differ diff --git a/media/vocal/flore/b2b_3.ogg b/media/vocal/flore/b2b_3.ogg new file mode 100644 index 000000000..b8682b78f Binary files /dev/null and b/media/vocal/flore/b2b_3.ogg differ diff --git a/media/vocal/flore/b3b_1.ogg b/media/vocal/flore/b3b_1.ogg new file mode 100644 index 000000000..cb2d7758c Binary files /dev/null and b/media/vocal/flore/b3b_1.ogg differ diff --git a/media/vocal/flore/b3b_2.ogg b/media/vocal/flore/b3b_2.ogg new file mode 100644 index 000000000..24ef6a62b Binary files /dev/null and b/media/vocal/flore/b3b_2.ogg differ diff --git a/media/vocal/flore/b3b_3.ogg b/media/vocal/flore/b3b_3.ogg new file mode 100644 index 000000000..24d80be76 Binary files /dev/null and b/media/vocal/flore/b3b_3.ogg differ diff --git a/media/vocal/flore/bye_1.ogg b/media/vocal/flore/bye_1.ogg new file mode 100644 index 000000000..17234bffd Binary files /dev/null and b/media/vocal/flore/bye_1.ogg differ diff --git a/media/vocal/flore/bye_2.ogg b/media/vocal/flore/bye_2.ogg new file mode 100644 index 000000000..44608266a Binary files /dev/null and b/media/vocal/flore/bye_2.ogg differ diff --git a/media/vocal/flore/bye_3.ogg b/media/vocal/flore/bye_3.ogg new file mode 100644 index 000000000..c55ad2ff2 Binary files /dev/null and b/media/vocal/flore/bye_3.ogg differ diff --git a/media/vocal/flore/bye_4.ogg b/media/vocal/flore/bye_4.ogg new file mode 100644 index 000000000..8bd4d2e3f Binary files /dev/null and b/media/vocal/flore/bye_4.ogg differ diff --git a/media/vocal/flore/bye_5.ogg b/media/vocal/flore/bye_5.ogg new file mode 100644 index 000000000..f7dde5656 Binary files /dev/null and b/media/vocal/flore/bye_5.ogg differ diff --git a/media/vocal/flore/bye_6.ogg b/media/vocal/flore/bye_6.ogg new file mode 100644 index 000000000..96ce043fc Binary files /dev/null and b/media/vocal/flore/bye_6.ogg differ diff --git a/media/vocal/flore/cspin.ogg b/media/vocal/flore/cspin.ogg new file mode 100644 index 000000000..a0618211f Binary files /dev/null and b/media/vocal/flore/cspin.ogg differ diff --git a/media/vocal/flore/decacrash_1.ogg b/media/vocal/flore/decacrash_1.ogg new file mode 100644 index 000000000..a57b83324 Binary files /dev/null and b/media/vocal/flore/decacrash_1.ogg differ diff --git a/media/vocal/flore/decacrash_2.ogg b/media/vocal/flore/decacrash_2.ogg new file mode 100644 index 000000000..abb739252 Binary files /dev/null and b/media/vocal/flore/decacrash_2.ogg differ diff --git a/media/vocal/flore/dodecacrash_1.ogg b/media/vocal/flore/dodecacrash_1.ogg new file mode 100644 index 000000000..ba192c29e Binary files /dev/null and b/media/vocal/flore/dodecacrash_1.ogg differ diff --git a/media/vocal/flore/double_1.ogg b/media/vocal/flore/double_1.ogg new file mode 100644 index 000000000..f7c33ffc8 Binary files /dev/null and b/media/vocal/flore/double_1.ogg differ diff --git a/media/vocal/flore/double_2.ogg b/media/vocal/flore/double_2.ogg new file mode 100644 index 000000000..9817a2beb Binary files /dev/null and b/media/vocal/flore/double_2.ogg differ diff --git a/media/vocal/flore/double_3.ogg b/media/vocal/flore/double_3.ogg new file mode 100644 index 000000000..dbe251eb9 Binary files /dev/null and b/media/vocal/flore/double_3.ogg differ diff --git a/media/vocal/flore/doubt_1.ogg b/media/vocal/flore/doubt_1.ogg new file mode 100644 index 000000000..9453f8601 Binary files /dev/null and b/media/vocal/flore/doubt_1.ogg differ diff --git a/media/vocal/flore/doubt_2.ogg b/media/vocal/flore/doubt_2.ogg new file mode 100644 index 000000000..c615a5212 Binary files /dev/null and b/media/vocal/flore/doubt_2.ogg differ diff --git a/media/vocal/flore/doubt_3.ogg b/media/vocal/flore/doubt_3.ogg new file mode 100644 index 000000000..bb67115b3 Binary files /dev/null and b/media/vocal/flore/doubt_3.ogg differ diff --git a/media/vocal/flore/espin.ogg b/media/vocal/flore/espin.ogg new file mode 100644 index 000000000..34ea1fe6b Binary files /dev/null and b/media/vocal/flore/espin.ogg differ diff --git a/media/vocal/flore/fspin.ogg b/media/vocal/flore/fspin.ogg new file mode 100644 index 000000000..e4647701e Binary files /dev/null and b/media/vocal/flore/fspin.ogg differ diff --git a/media/vocal/flore/half_clear_1.ogg b/media/vocal/flore/half_clear_1.ogg new file mode 100644 index 000000000..7ba62f7bb Binary files /dev/null and b/media/vocal/flore/half_clear_1.ogg differ diff --git a/media/vocal/flore/half_clear_2.ogg b/media/vocal/flore/half_clear_2.ogg new file mode 100644 index 000000000..00dbd0c5a Binary files /dev/null and b/media/vocal/flore/half_clear_2.ogg differ diff --git a/media/vocal/flore/happy_1.ogg b/media/vocal/flore/happy_1.ogg new file mode 100644 index 000000000..925aa3f24 Binary files /dev/null and b/media/vocal/flore/happy_1.ogg differ diff --git a/media/vocal/flore/happy_2.ogg b/media/vocal/flore/happy_2.ogg new file mode 100644 index 000000000..aa283dacb Binary files /dev/null and b/media/vocal/flore/happy_2.ogg differ diff --git a/media/vocal/flore/happy_3.ogg b/media/vocal/flore/happy_3.ogg new file mode 100644 index 000000000..bf653259f Binary files /dev/null and b/media/vocal/flore/happy_3.ogg differ diff --git a/media/vocal/flore/heptacrash_1.ogg b/media/vocal/flore/heptacrash_1.ogg new file mode 100644 index 000000000..8895a1da2 Binary files /dev/null and b/media/vocal/flore/heptacrash_1.ogg differ diff --git a/media/vocal/flore/heptacrash_2.ogg b/media/vocal/flore/heptacrash_2.ogg new file mode 100644 index 000000000..e8dea3b0e Binary files /dev/null and b/media/vocal/flore/heptacrash_2.ogg differ diff --git a/media/vocal/flore/heptadecacrash_1.ogg b/media/vocal/flore/heptadecacrash_1.ogg new file mode 100644 index 000000000..4e350a2ac Binary files /dev/null and b/media/vocal/flore/heptadecacrash_1.ogg differ diff --git a/media/vocal/flore/hexacrash_1.ogg b/media/vocal/flore/hexacrash_1.ogg new file mode 100644 index 000000000..184074fcc Binary files /dev/null and b/media/vocal/flore/hexacrash_1.ogg differ diff --git a/media/vocal/flore/hexacrash_2.ogg b/media/vocal/flore/hexacrash_2.ogg new file mode 100644 index 000000000..761057bfd Binary files /dev/null and b/media/vocal/flore/hexacrash_2.ogg differ diff --git a/media/vocal/flore/hexacrash_3.ogg b/media/vocal/flore/hexacrash_3.ogg new file mode 100644 index 000000000..a5dfbb61d Binary files /dev/null and b/media/vocal/flore/hexacrash_3.ogg differ diff --git a/media/vocal/flore/hexadecacrash_1.ogg b/media/vocal/flore/hexadecacrash_1.ogg new file mode 100644 index 000000000..34e1be53c Binary files /dev/null and b/media/vocal/flore/hexadecacrash_1.ogg differ diff --git a/media/vocal/flore/hspin.ogg b/media/vocal/flore/hspin.ogg new file mode 100644 index 000000000..49d212da7 Binary files /dev/null and b/media/vocal/flore/hspin.ogg differ diff --git a/media/vocal/flore/impossicrash_1.ogg b/media/vocal/flore/impossicrash_1.ogg new file mode 100644 index 000000000..ae159a37a Binary files /dev/null and b/media/vocal/flore/impossicrash_1.ogg differ diff --git a/media/vocal/flore/ispin_1.ogg b/media/vocal/flore/ispin_1.ogg new file mode 100644 index 000000000..003f7f532 Binary files /dev/null and b/media/vocal/flore/ispin_1.ogg differ diff --git a/media/vocal/flore/ispin_2.ogg b/media/vocal/flore/ispin_2.ogg new file mode 100644 index 000000000..fd0ca1b8c Binary files /dev/null and b/media/vocal/flore/ispin_2.ogg differ diff --git a/media/vocal/flore/jspin_1.ogg b/media/vocal/flore/jspin_1.ogg new file mode 100644 index 000000000..1b37611ec Binary files /dev/null and b/media/vocal/flore/jspin_1.ogg differ diff --git a/media/vocal/flore/jspin_2.ogg b/media/vocal/flore/jspin_2.ogg new file mode 100644 index 000000000..197c61c1e Binary files /dev/null and b/media/vocal/flore/jspin_2.ogg differ diff --git a/media/vocal/flore/lose_1.ogg b/media/vocal/flore/lose_1.ogg new file mode 100644 index 000000000..0032572d6 Binary files /dev/null and b/media/vocal/flore/lose_1.ogg differ diff --git a/media/vocal/flore/lose_2.ogg b/media/vocal/flore/lose_2.ogg new file mode 100644 index 000000000..80d86e2bf Binary files /dev/null and b/media/vocal/flore/lose_2.ogg differ diff --git a/media/vocal/flore/lose_3.ogg b/media/vocal/flore/lose_3.ogg new file mode 100644 index 000000000..1fa9164ef Binary files /dev/null and b/media/vocal/flore/lose_3.ogg differ diff --git a/media/vocal/flore/lose_4.ogg b/media/vocal/flore/lose_4.ogg new file mode 100644 index 000000000..06b8f33af Binary files /dev/null and b/media/vocal/flore/lose_4.ogg differ diff --git a/media/vocal/flore/lose_5.ogg b/media/vocal/flore/lose_5.ogg new file mode 100644 index 000000000..427ed6b65 Binary files /dev/null and b/media/vocal/flore/lose_5.ogg differ diff --git a/media/vocal/flore/lose_6.ogg b/media/vocal/flore/lose_6.ogg new file mode 100644 index 000000000..cb1340013 Binary files /dev/null and b/media/vocal/flore/lose_6.ogg differ diff --git a/media/vocal/flore/lspin_1.ogg b/media/vocal/flore/lspin_1.ogg new file mode 100644 index 000000000..fdb09d7d3 Binary files /dev/null and b/media/vocal/flore/lspin_1.ogg differ diff --git a/media/vocal/flore/lspin_2.ogg b/media/vocal/flore/lspin_2.ogg new file mode 100644 index 000000000..e949a8f63 Binary files /dev/null and b/media/vocal/flore/lspin_2.ogg differ diff --git a/media/vocal/flore/mini_1.ogg b/media/vocal/flore/mini_1.ogg new file mode 100644 index 000000000..00c0fae27 Binary files /dev/null and b/media/vocal/flore/mini_1.ogg differ diff --git a/media/vocal/flore/mini_2.ogg b/media/vocal/flore/mini_2.ogg new file mode 100644 index 000000000..e416a5661 Binary files /dev/null and b/media/vocal/flore/mini_2.ogg differ diff --git a/media/vocal/flore/mini_3.ogg b/media/vocal/flore/mini_3.ogg new file mode 100644 index 000000000..36d827d7f Binary files /dev/null and b/media/vocal/flore/mini_3.ogg differ diff --git a/media/vocal/flore/nonacrash_1.ogg b/media/vocal/flore/nonacrash_1.ogg new file mode 100644 index 000000000..2f9e8a52a Binary files /dev/null and b/media/vocal/flore/nonacrash_1.ogg differ diff --git a/media/vocal/flore/nonacrash_2.ogg b/media/vocal/flore/nonacrash_2.ogg new file mode 100644 index 000000000..6f2c159d3 Binary files /dev/null and b/media/vocal/flore/nonacrash_2.ogg differ diff --git a/media/vocal/flore/nonadecacrash_1.ogg b/media/vocal/flore/nonadecacrash_1.ogg new file mode 100644 index 000000000..5e2f5cc96 Binary files /dev/null and b/media/vocal/flore/nonadecacrash_1.ogg differ diff --git a/media/vocal/flore/nspin.ogg b/media/vocal/flore/nspin.ogg new file mode 100644 index 000000000..11b7f6fa5 Binary files /dev/null and b/media/vocal/flore/nspin.ogg differ diff --git a/media/vocal/flore/octacrash_1.ogg b/media/vocal/flore/octacrash_1.ogg new file mode 100644 index 000000000..a41ae17cc Binary files /dev/null and b/media/vocal/flore/octacrash_1.ogg differ diff --git a/media/vocal/flore/octacrash_2.ogg b/media/vocal/flore/octacrash_2.ogg new file mode 100644 index 000000000..97d357c06 Binary files /dev/null and b/media/vocal/flore/octacrash_2.ogg differ diff --git a/media/vocal/flore/octadecacrash_1.ogg b/media/vocal/flore/octadecacrash_1.ogg new file mode 100644 index 000000000..da9273b5b Binary files /dev/null and b/media/vocal/flore/octadecacrash_1.ogg differ diff --git a/media/vocal/flore/ospin.ogg b/media/vocal/flore/ospin.ogg new file mode 100644 index 000000000..437a1a892 Binary files /dev/null and b/media/vocal/flore/ospin.ogg differ diff --git a/media/vocal/flore/ospin_1.ogg b/media/vocal/flore/ospin_1.ogg new file mode 100644 index 000000000..042de6a22 Binary files /dev/null and b/media/vocal/flore/ospin_1.ogg differ diff --git a/media/vocal/flore/pentacrash_1.ogg b/media/vocal/flore/pentacrash_1.ogg new file mode 100644 index 000000000..45b96ce78 Binary files /dev/null and b/media/vocal/flore/pentacrash_1.ogg differ diff --git a/media/vocal/flore/pentacrash_2.ogg b/media/vocal/flore/pentacrash_2.ogg new file mode 100644 index 000000000..71c94804a Binary files /dev/null and b/media/vocal/flore/pentacrash_2.ogg differ diff --git a/media/vocal/flore/pentacrash_3.ogg b/media/vocal/flore/pentacrash_3.ogg new file mode 100644 index 000000000..c16f7918c Binary files /dev/null and b/media/vocal/flore/pentacrash_3.ogg differ diff --git a/media/vocal/flore/pentadecacrash_1.ogg b/media/vocal/flore/pentadecacrash_1.ogg new file mode 100644 index 000000000..187af33f4 Binary files /dev/null and b/media/vocal/flore/pentadecacrash_1.ogg differ diff --git a/media/vocal/flore/perfect_clear_1.ogg b/media/vocal/flore/perfect_clear_1.ogg new file mode 100644 index 000000000..769c66af1 Binary files /dev/null and b/media/vocal/flore/perfect_clear_1.ogg differ diff --git a/media/vocal/flore/perfect_clear_2.ogg b/media/vocal/flore/perfect_clear_2.ogg new file mode 100644 index 000000000..5aafb828b Binary files /dev/null and b/media/vocal/flore/perfect_clear_2.ogg differ diff --git a/media/vocal/flore/pspin.ogg b/media/vocal/flore/pspin.ogg new file mode 100644 index 000000000..0995e5075 Binary files /dev/null and b/media/vocal/flore/pspin.ogg differ diff --git a/media/vocal/flore/qspin.ogg b/media/vocal/flore/qspin.ogg new file mode 100644 index 000000000..1a2b466b1 Binary files /dev/null and b/media/vocal/flore/qspin.ogg differ diff --git a/media/vocal/flore/rspin.ogg b/media/vocal/flore/rspin.ogg new file mode 100644 index 000000000..0d4c65c2e Binary files /dev/null and b/media/vocal/flore/rspin.ogg differ diff --git a/media/vocal/flore/single_1.ogg b/media/vocal/flore/single_1.ogg new file mode 100644 index 000000000..392b5a89f Binary files /dev/null and b/media/vocal/flore/single_1.ogg differ diff --git a/media/vocal/flore/single_2.ogg b/media/vocal/flore/single_2.ogg new file mode 100644 index 000000000..eb8554f0a Binary files /dev/null and b/media/vocal/flore/single_2.ogg differ diff --git a/media/vocal/flore/single_3.ogg b/media/vocal/flore/single_3.ogg new file mode 100644 index 000000000..048f871fa Binary files /dev/null and b/media/vocal/flore/single_3.ogg differ diff --git a/media/vocal/flore/sspin_1.ogg b/media/vocal/flore/sspin_1.ogg new file mode 100644 index 000000000..670e30474 Binary files /dev/null and b/media/vocal/flore/sspin_1.ogg differ diff --git a/media/vocal/flore/sspin_2.ogg b/media/vocal/flore/sspin_2.ogg new file mode 100644 index 000000000..61125ae6a Binary files /dev/null and b/media/vocal/flore/sspin_2.ogg differ diff --git a/media/vocal/flore/techrash_1.ogg b/media/vocal/flore/techrash_1.ogg new file mode 100644 index 000000000..2cfe9e43f Binary files /dev/null and b/media/vocal/flore/techrash_1.ogg differ diff --git a/media/vocal/flore/techrash_2.ogg b/media/vocal/flore/techrash_2.ogg new file mode 100644 index 000000000..c760b6d19 Binary files /dev/null and b/media/vocal/flore/techrash_2.ogg differ diff --git a/media/vocal/flore/techrash_3.ogg b/media/vocal/flore/techrash_3.ogg new file mode 100644 index 000000000..6c74f9381 Binary files /dev/null and b/media/vocal/flore/techrash_3.ogg differ diff --git a/media/vocal/flore/test_1.ogg b/media/vocal/flore/test_1.ogg new file mode 100644 index 000000000..37fb7073a Binary files /dev/null and b/media/vocal/flore/test_1.ogg differ diff --git a/media/vocal/flore/test_2.ogg b/media/vocal/flore/test_2.ogg new file mode 100644 index 000000000..9d608c756 Binary files /dev/null and b/media/vocal/flore/test_2.ogg differ diff --git a/media/vocal/flore/test_3.ogg b/media/vocal/flore/test_3.ogg new file mode 100644 index 000000000..966a4b8bb Binary files /dev/null and b/media/vocal/flore/test_3.ogg differ diff --git a/media/vocal/flore/test_4.ogg b/media/vocal/flore/test_4.ogg new file mode 100644 index 000000000..31d4f4206 Binary files /dev/null and b/media/vocal/flore/test_4.ogg differ diff --git a/media/vocal/flore/tetradecacrash_1.ogg b/media/vocal/flore/tetradecacrash_1.ogg new file mode 100644 index 000000000..23a0cf123 Binary files /dev/null and b/media/vocal/flore/tetradecacrash_1.ogg differ diff --git a/media/vocal/flore/tridecacrash_1.ogg b/media/vocal/flore/tridecacrash_1.ogg new file mode 100644 index 000000000..8dd702d5f Binary files /dev/null and b/media/vocal/flore/tridecacrash_1.ogg differ diff --git a/media/vocal/flore/triple_1.ogg b/media/vocal/flore/triple_1.ogg new file mode 100644 index 000000000..d8c99d6fc Binary files /dev/null and b/media/vocal/flore/triple_1.ogg differ diff --git a/media/vocal/flore/triple_2.ogg b/media/vocal/flore/triple_2.ogg new file mode 100644 index 000000000..45b349e1c Binary files /dev/null and b/media/vocal/flore/triple_2.ogg differ diff --git a/media/vocal/flore/triple_3.ogg b/media/vocal/flore/triple_3.ogg new file mode 100644 index 000000000..42756d34f Binary files /dev/null and b/media/vocal/flore/triple_3.ogg differ diff --git a/media/vocal/flore/tspin_1.ogg b/media/vocal/flore/tspin_1.ogg new file mode 100644 index 000000000..95f65ce47 Binary files /dev/null and b/media/vocal/flore/tspin_1.ogg differ diff --git a/media/vocal/flore/tspin_2.ogg b/media/vocal/flore/tspin_2.ogg new file mode 100644 index 000000000..d2a9919e3 Binary files /dev/null and b/media/vocal/flore/tspin_2.ogg differ diff --git a/media/vocal/flore/ultracrash_1.ogg b/media/vocal/flore/ultracrash_1.ogg new file mode 100644 index 000000000..172163432 Binary files /dev/null and b/media/vocal/flore/ultracrash_1.ogg differ diff --git a/media/vocal/flore/undecacrash_1.ogg b/media/vocal/flore/undecacrash_1.ogg new file mode 100644 index 000000000..9d7aab013 Binary files /dev/null and b/media/vocal/flore/undecacrash_1.ogg differ diff --git a/media/vocal/flore/uspin.ogg b/media/vocal/flore/uspin.ogg new file mode 100644 index 000000000..cea69dd96 Binary files /dev/null and b/media/vocal/flore/uspin.ogg differ diff --git a/media/vocal/flore/vspin.ogg b/media/vocal/flore/vspin.ogg new file mode 100644 index 000000000..f20235df1 Binary files /dev/null and b/media/vocal/flore/vspin.ogg differ diff --git a/media/vocal/flore/welcome_1.ogg b/media/vocal/flore/welcome_1.ogg new file mode 100644 index 000000000..28dd481a5 Binary files /dev/null and b/media/vocal/flore/welcome_1.ogg differ diff --git a/media/vocal/flore/welcome_2.ogg b/media/vocal/flore/welcome_2.ogg new file mode 100644 index 000000000..a1eec9b6e Binary files /dev/null and b/media/vocal/flore/welcome_2.ogg differ diff --git a/media/vocal/flore/welcome_3.ogg b/media/vocal/flore/welcome_3.ogg new file mode 100644 index 000000000..9093d4787 Binary files /dev/null and b/media/vocal/flore/welcome_3.ogg differ diff --git a/media/vocal/flore/welcome_4.ogg b/media/vocal/flore/welcome_4.ogg new file mode 100644 index 000000000..4da82cd5b Binary files /dev/null and b/media/vocal/flore/welcome_4.ogg differ diff --git a/media/vocal/flore/welcome_5.ogg b/media/vocal/flore/welcome_5.ogg new file mode 100644 index 000000000..795c3b034 Binary files /dev/null and b/media/vocal/flore/welcome_5.ogg differ diff --git a/media/vocal/flore/welcome_6.ogg b/media/vocal/flore/welcome_6.ogg new file mode 100644 index 000000000..90921af24 Binary files /dev/null and b/media/vocal/flore/welcome_6.ogg differ diff --git a/media/vocal/flore/win_1.ogg b/media/vocal/flore/win_1.ogg new file mode 100644 index 000000000..574f33a3f Binary files /dev/null and b/media/vocal/flore/win_1.ogg differ diff --git a/media/vocal/flore/win_2.ogg b/media/vocal/flore/win_2.ogg new file mode 100644 index 000000000..aa2c8a0fd Binary files /dev/null and b/media/vocal/flore/win_2.ogg differ diff --git a/media/vocal/flore/win_3.ogg b/media/vocal/flore/win_3.ogg new file mode 100644 index 000000000..336e321a3 Binary files /dev/null and b/media/vocal/flore/win_3.ogg differ diff --git a/media/vocal/flore/win_4.ogg b/media/vocal/flore/win_4.ogg new file mode 100644 index 000000000..5c4db48b1 Binary files /dev/null and b/media/vocal/flore/win_4.ogg differ diff --git a/media/vocal/flore/win_5.ogg b/media/vocal/flore/win_5.ogg new file mode 100644 index 000000000..c5be6be1a Binary files /dev/null and b/media/vocal/flore/win_5.ogg differ diff --git a/media/vocal/flore/win_6.ogg b/media/vocal/flore/win_6.ogg new file mode 100644 index 000000000..d58806c45 Binary files /dev/null and b/media/vocal/flore/win_6.ogg differ diff --git a/media/vocal/flore/wspin.ogg b/media/vocal/flore/wspin.ogg new file mode 100644 index 000000000..ccf3a7505 Binary files /dev/null and b/media/vocal/flore/wspin.ogg differ diff --git a/media/vocal/flore/xspin.ogg b/media/vocal/flore/xspin.ogg new file mode 100644 index 000000000..c3ef14e8e Binary files /dev/null and b/media/vocal/flore/xspin.ogg differ diff --git a/media/vocal/flore/yspin.ogg b/media/vocal/flore/yspin.ogg new file mode 100644 index 000000000..11e0c91f6 Binary files /dev/null and b/media/vocal/flore/yspin.ogg differ diff --git a/media/vocal/flore/zspin_1.ogg b/media/vocal/flore/zspin_1.ogg new file mode 100644 index 000000000..8c75a5414 Binary files /dev/null and b/media/vocal/flore/zspin_1.ogg differ diff --git a/media/vocal/flore/zspin_2.ogg b/media/vocal/flore/zspin_2.ogg new file mode 100644 index 000000000..90ed0f6d7 Binary files /dev/null and b/media/vocal/flore/zspin_2.ogg differ diff --git a/media/vocal/miya/angry_1.ogg b/media/vocal/miya/angry_1.ogg new file mode 100644 index 000000000..d07a20de0 Binary files /dev/null and b/media/vocal/miya/angry_1.ogg differ diff --git a/media/vocal/miya/b2b_1.ogg b/media/vocal/miya/b2b_1.ogg index 9825507a8..5e8219dc4 100644 Binary files a/media/vocal/miya/b2b_1.ogg and b/media/vocal/miya/b2b_1.ogg differ diff --git a/media/vocal/miya/b2b_2.ogg b/media/vocal/miya/b2b_2.ogg index fe4c83b87..982de8373 100644 Binary files a/media/vocal/miya/b2b_2.ogg and b/media/vocal/miya/b2b_2.ogg differ diff --git a/media/vocal/miya/b2b_3.ogg b/media/vocal/miya/b2b_3.ogg index dca284549..4f44531c9 100644 Binary files a/media/vocal/miya/b2b_3.ogg and b/media/vocal/miya/b2b_3.ogg differ diff --git a/media/vocal/miya/b3b_1.ogg b/media/vocal/miya/b3b_1.ogg index 533febbe8..323d40bbd 100644 Binary files a/media/vocal/miya/b3b_1.ogg and b/media/vocal/miya/b3b_1.ogg differ diff --git a/media/vocal/miya/b3b_2.ogg b/media/vocal/miya/b3b_2.ogg index 0dc6bcc6c..714979420 100644 Binary files a/media/vocal/miya/b3b_2.ogg and b/media/vocal/miya/b3b_2.ogg differ diff --git a/media/vocal/miya/b3b_3.ogg b/media/vocal/miya/b3b_3.ogg new file mode 100644 index 000000000..5d9aff5e9 Binary files /dev/null and b/media/vocal/miya/b3b_3.ogg differ diff --git a/media/vocal/miya/bye_1.ogg b/media/vocal/miya/bye_1.ogg index 13366f0c3..20d1d9353 100644 Binary files a/media/vocal/miya/bye_1.ogg and b/media/vocal/miya/bye_1.ogg differ diff --git a/media/vocal/miya/bye_2.ogg b/media/vocal/miya/bye_2.ogg index 045a26f85..5a77ac21c 100644 Binary files a/media/vocal/miya/bye_2.ogg and b/media/vocal/miya/bye_2.ogg differ diff --git a/media/vocal/miya/bye_3.ogg b/media/vocal/miya/bye_3.ogg new file mode 100644 index 000000000..f20572a47 Binary files /dev/null and b/media/vocal/miya/bye_3.ogg differ diff --git a/media/vocal/miya/bye_4.ogg b/media/vocal/miya/bye_4.ogg new file mode 100644 index 000000000..4445d7494 Binary files /dev/null and b/media/vocal/miya/bye_4.ogg differ diff --git a/media/vocal/miya/bye_5.ogg b/media/vocal/miya/bye_5.ogg new file mode 100644 index 000000000..419c8d60d Binary files /dev/null and b/media/vocal/miya/bye_5.ogg differ diff --git a/media/vocal/miya/clear_1.ogg b/media/vocal/miya/clear_1.ogg deleted file mode 100644 index 3c3ad0758..000000000 Binary files a/media/vocal/miya/clear_1.ogg and /dev/null differ diff --git a/media/vocal/miya/clear_2.ogg b/media/vocal/miya/clear_2.ogg deleted file mode 100644 index 84cc57fa8..000000000 Binary files a/media/vocal/miya/clear_2.ogg and /dev/null differ diff --git a/media/vocal/miya/double_1.ogg b/media/vocal/miya/double_1.ogg index af2b2c634..e76f0f3df 100644 Binary files a/media/vocal/miya/double_1.ogg and b/media/vocal/miya/double_1.ogg differ diff --git a/media/vocal/miya/double_2.ogg b/media/vocal/miya/double_2.ogg index ca10bc118..627183de7 100644 Binary files a/media/vocal/miya/double_2.ogg and b/media/vocal/miya/double_2.ogg differ diff --git a/media/vocal/miya/double_3.ogg b/media/vocal/miya/double_3.ogg index 5e647be72..fb29529db 100644 Binary files a/media/vocal/miya/double_3.ogg and b/media/vocal/miya/double_3.ogg differ diff --git a/media/vocal/miya/double_4.ogg b/media/vocal/miya/double_4.ogg deleted file mode 100644 index 6e2b9b63a..000000000 Binary files a/media/vocal/miya/double_4.ogg and /dev/null differ diff --git a/media/vocal/miya/double_5.ogg b/media/vocal/miya/double_5.ogg deleted file mode 100644 index 950bb06d6..000000000 Binary files a/media/vocal/miya/double_5.ogg and /dev/null differ diff --git a/media/vocal/miya/doubt_1.ogg b/media/vocal/miya/doubt_1.ogg index e0d94c5f4..12af3f355 100644 Binary files a/media/vocal/miya/doubt_1.ogg and b/media/vocal/miya/doubt_1.ogg differ diff --git a/media/vocal/miya/doubt_2.ogg b/media/vocal/miya/doubt_2.ogg index cd7ee9bdc..230e51e85 100644 Binary files a/media/vocal/miya/doubt_2.ogg and b/media/vocal/miya/doubt_2.ogg differ diff --git a/media/vocal/miya/doubt_3.ogg b/media/vocal/miya/doubt_3.ogg new file mode 100644 index 000000000..6895441e0 Binary files /dev/null and b/media/vocal/miya/doubt_3.ogg differ diff --git a/media/vocal/miya/doubt_4.ogg b/media/vocal/miya/doubt_4.ogg new file mode 100644 index 000000000..e3b3d6c2b Binary files /dev/null and b/media/vocal/miya/doubt_4.ogg differ diff --git a/media/vocal/miya/espin_1.ogg b/media/vocal/miya/espin_1.ogg new file mode 100644 index 000000000..ad3f5ba02 Binary files /dev/null and b/media/vocal/miya/espin_1.ogg differ diff --git a/media/vocal/miya/fspin_1.ogg b/media/vocal/miya/fspin_1.ogg new file mode 100644 index 000000000..34d813845 Binary files /dev/null and b/media/vocal/miya/fspin_1.ogg differ diff --git a/media/vocal/miya/half_clear_1.ogg b/media/vocal/miya/half_clear_1.ogg index 43bb3b7fe..5d5f9cd68 100644 Binary files a/media/vocal/miya/half_clear_1.ogg and b/media/vocal/miya/half_clear_1.ogg differ diff --git a/media/vocal/miya/half_clear_2.ogg b/media/vocal/miya/half_clear_2.ogg index ee1476e83..97262b0f8 100644 Binary files a/media/vocal/miya/half_clear_2.ogg and b/media/vocal/miya/half_clear_2.ogg differ diff --git a/media/vocal/miya/happy_1.ogg b/media/vocal/miya/happy_1.ogg index 8b10ba459..8975f100e 100644 Binary files a/media/vocal/miya/happy_1.ogg and b/media/vocal/miya/happy_1.ogg differ diff --git a/media/vocal/miya/happy_2.ogg b/media/vocal/miya/happy_2.ogg index 913ca1188..f16f84cb4 100644 Binary files a/media/vocal/miya/happy_2.ogg and b/media/vocal/miya/happy_2.ogg differ diff --git a/media/vocal/miya/happy_3.ogg b/media/vocal/miya/happy_3.ogg index f9f534965..6114b5ed5 100644 Binary files a/media/vocal/miya/happy_3.ogg and b/media/vocal/miya/happy_3.ogg differ diff --git a/media/vocal/miya/happy_4.ogg b/media/vocal/miya/happy_4.ogg index e1faf5055..38d4b96de 100644 Binary files a/media/vocal/miya/happy_4.ogg and b/media/vocal/miya/happy_4.ogg differ diff --git a/media/vocal/miya/happy_5.ogg b/media/vocal/miya/happy_5.ogg new file mode 100644 index 000000000..bdaebf74c Binary files /dev/null and b/media/vocal/miya/happy_5.ogg differ diff --git a/media/vocal/miya/happy_6.ogg b/media/vocal/miya/happy_6.ogg new file mode 100644 index 000000000..b1c09ef0e Binary files /dev/null and b/media/vocal/miya/happy_6.ogg differ diff --git a/media/vocal/miya/happy_7.ogg b/media/vocal/miya/happy_7.ogg new file mode 100644 index 000000000..63afff9c3 Binary files /dev/null and b/media/vocal/miya/happy_7.ogg differ diff --git a/media/vocal/miya/hspin_1.ogg b/media/vocal/miya/hspin_1.ogg new file mode 100644 index 000000000..3279d8946 Binary files /dev/null and b/media/vocal/miya/hspin_1.ogg differ diff --git a/media/vocal/miya/ispin_1.ogg b/media/vocal/miya/ispin_1.ogg index 25a5539f6..55e2ef080 100644 Binary files a/media/vocal/miya/ispin_1.ogg and b/media/vocal/miya/ispin_1.ogg differ diff --git a/media/vocal/miya/ispin_2.ogg b/media/vocal/miya/ispin_2.ogg index 661ea38be..a337b8aa2 100644 Binary files a/media/vocal/miya/ispin_2.ogg and b/media/vocal/miya/ispin_2.ogg differ diff --git a/media/vocal/miya/ispin_3.ogg b/media/vocal/miya/ispin_3.ogg deleted file mode 100644 index b0233fa7c..000000000 Binary files a/media/vocal/miya/ispin_3.ogg and /dev/null differ diff --git a/media/vocal/miya/jspin_1.ogg b/media/vocal/miya/jspin_1.ogg index efe109356..6d0c7a410 100644 Binary files a/media/vocal/miya/jspin_1.ogg and b/media/vocal/miya/jspin_1.ogg differ diff --git a/media/vocal/miya/jspin_2.ogg b/media/vocal/miya/jspin_2.ogg index 81abf3bc9..6b362600a 100644 Binary files a/media/vocal/miya/jspin_2.ogg and b/media/vocal/miya/jspin_2.ogg differ diff --git a/media/vocal/miya/jspin_3.ogg b/media/vocal/miya/jspin_3.ogg deleted file mode 100644 index cb9c44e87..000000000 Binary files a/media/vocal/miya/jspin_3.ogg and /dev/null differ diff --git a/media/vocal/miya/jspin_4.ogg b/media/vocal/miya/jspin_4.ogg deleted file mode 100644 index 3b6eb33c0..000000000 Binary files a/media/vocal/miya/jspin_4.ogg and /dev/null differ diff --git a/media/vocal/miya/lose_1.ogg b/media/vocal/miya/lose_1.ogg index 0d6c2e70c..baaa6d8a0 100644 Binary files a/media/vocal/miya/lose_1.ogg and b/media/vocal/miya/lose_1.ogg differ diff --git a/media/vocal/miya/lose_2.ogg b/media/vocal/miya/lose_2.ogg index 29ebd17b1..6b97a663d 100644 Binary files a/media/vocal/miya/lose_2.ogg and b/media/vocal/miya/lose_2.ogg differ diff --git a/media/vocal/miya/lose_3.ogg b/media/vocal/miya/lose_3.ogg index da48ed4bb..a590b5799 100644 Binary files a/media/vocal/miya/lose_3.ogg and b/media/vocal/miya/lose_3.ogg differ diff --git a/media/vocal/miya/lose_4.ogg b/media/vocal/miya/lose_4.ogg new file mode 100644 index 000000000..bb724ee72 Binary files /dev/null and b/media/vocal/miya/lose_4.ogg differ diff --git a/media/vocal/miya/lose_5.ogg b/media/vocal/miya/lose_5.ogg new file mode 100644 index 000000000..2f7394ee5 Binary files /dev/null and b/media/vocal/miya/lose_5.ogg differ diff --git a/media/vocal/miya/lose_6.ogg b/media/vocal/miya/lose_6.ogg new file mode 100644 index 000000000..cf5dacb81 Binary files /dev/null and b/media/vocal/miya/lose_6.ogg differ diff --git a/media/vocal/miya/lspin_1.ogg b/media/vocal/miya/lspin_1.ogg index ff0342f25..5af71baac 100644 Binary files a/media/vocal/miya/lspin_1.ogg and b/media/vocal/miya/lspin_1.ogg differ diff --git a/media/vocal/miya/lspin_2.ogg b/media/vocal/miya/lspin_2.ogg deleted file mode 100644 index 102abe279..000000000 Binary files a/media/vocal/miya/lspin_2.ogg and /dev/null differ diff --git a/media/vocal/miya/mini_1.ogg b/media/vocal/miya/mini_1.ogg index 8678bc2eb..f4586fbc6 100644 Binary files a/media/vocal/miya/mini_1.ogg and b/media/vocal/miya/mini_1.ogg differ diff --git a/media/vocal/miya/mini_2.ogg b/media/vocal/miya/mini_2.ogg index 4b1230a4e..4953c597b 100644 Binary files a/media/vocal/miya/mini_2.ogg and b/media/vocal/miya/mini_2.ogg differ diff --git a/media/vocal/miya/mini_3.ogg b/media/vocal/miya/mini_3.ogg index cf10f2291..bde5b757d 100644 Binary files a/media/vocal/miya/mini_3.ogg and b/media/vocal/miya/mini_3.ogg differ diff --git a/media/vocal/miya/mini_4.ogg b/media/vocal/miya/mini_4.ogg new file mode 100644 index 000000000..c68945bc5 Binary files /dev/null and b/media/vocal/miya/mini_4.ogg differ diff --git a/media/vocal/miya/mini_5.ogg b/media/vocal/miya/mini_5.ogg new file mode 100644 index 000000000..2d3037502 Binary files /dev/null and b/media/vocal/miya/mini_5.ogg differ diff --git a/media/vocal/miya/nspin_1.ogg b/media/vocal/miya/nspin_1.ogg new file mode 100644 index 000000000..cacb9d011 Binary files /dev/null and b/media/vocal/miya/nspin_1.ogg differ diff --git a/media/vocal/miya/nya_1.ogg b/media/vocal/miya/nya_1.ogg deleted file mode 100644 index c51b00c5e..000000000 Binary files a/media/vocal/miya/nya_1.ogg and /dev/null differ diff --git a/media/vocal/miya/nya_2.ogg b/media/vocal/miya/nya_2.ogg deleted file mode 100644 index e278ffffa..000000000 Binary files a/media/vocal/miya/nya_2.ogg and /dev/null differ diff --git a/media/vocal/miya/nya_3.ogg b/media/vocal/miya/nya_3.ogg deleted file mode 100644 index 0ed6aad7e..000000000 Binary files a/media/vocal/miya/nya_3.ogg and /dev/null differ diff --git a/media/vocal/miya/nya_4.ogg b/media/vocal/miya/nya_4.ogg deleted file mode 100644 index 9a7307c86..000000000 Binary files a/media/vocal/miya/nya_4.ogg and /dev/null differ diff --git a/media/vocal/miya/nya_doubt_1.ogg b/media/vocal/miya/nya_doubt_1.ogg deleted file mode 100644 index e0d94c5f4..000000000 Binary files a/media/vocal/miya/nya_doubt_1.ogg and /dev/null differ diff --git a/media/vocal/miya/nya_doubt_2.ogg b/media/vocal/miya/nya_doubt_2.ogg deleted file mode 100644 index cd7ee9bdc..000000000 Binary files a/media/vocal/miya/nya_doubt_2.ogg and /dev/null differ diff --git a/media/vocal/miya/nya_happy_1.ogg b/media/vocal/miya/nya_happy_1.ogg deleted file mode 100644 index 8b10ba459..000000000 Binary files a/media/vocal/miya/nya_happy_1.ogg and /dev/null differ diff --git a/media/vocal/miya/nya_happy_2.ogg b/media/vocal/miya/nya_happy_2.ogg deleted file mode 100644 index 913ca1188..000000000 Binary files a/media/vocal/miya/nya_happy_2.ogg and /dev/null differ diff --git a/media/vocal/miya/nya_happy_3.ogg b/media/vocal/miya/nya_happy_3.ogg deleted file mode 100644 index f9f534965..000000000 Binary files a/media/vocal/miya/nya_happy_3.ogg and /dev/null differ diff --git a/media/vocal/miya/nya_happy_4.ogg b/media/vocal/miya/nya_happy_4.ogg deleted file mode 100644 index e1faf5055..000000000 Binary files a/media/vocal/miya/nya_happy_4.ogg and /dev/null differ diff --git a/media/vocal/miya/nya_sad_1.ogg b/media/vocal/miya/nya_sad_1.ogg deleted file mode 100644 index 4270f18ca..000000000 Binary files a/media/vocal/miya/nya_sad_1.ogg and /dev/null differ diff --git a/media/vocal/miya/ospin_1.ogg b/media/vocal/miya/ospin_1.ogg index 1d0651ed3..26ad0e6ef 100644 Binary files a/media/vocal/miya/ospin_1.ogg and b/media/vocal/miya/ospin_1.ogg differ diff --git a/media/vocal/miya/ospin_2.ogg b/media/vocal/miya/ospin_2.ogg index a70f0e173..4fa006ab9 100644 Binary files a/media/vocal/miya/ospin_2.ogg and b/media/vocal/miya/ospin_2.ogg differ diff --git a/media/vocal/miya/ospin_3.ogg b/media/vocal/miya/ospin_3.ogg deleted file mode 100644 index b8523892b..000000000 Binary files a/media/vocal/miya/ospin_3.ogg and /dev/null differ diff --git a/media/vocal/miya/perfect_clear_1.ogg b/media/vocal/miya/perfect_clear_1.ogg index 3c3ad0758..aaf235f32 100644 Binary files a/media/vocal/miya/perfect_clear_1.ogg and b/media/vocal/miya/perfect_clear_1.ogg differ diff --git a/media/vocal/miya/perfect_clear_2.ogg b/media/vocal/miya/perfect_clear_2.ogg index 84cc57fa8..9efdadfaa 100644 Binary files a/media/vocal/miya/perfect_clear_2.ogg and b/media/vocal/miya/perfect_clear_2.ogg differ diff --git a/media/vocal/miya/perfect_clear_3.ogg b/media/vocal/miya/perfect_clear_3.ogg new file mode 100644 index 000000000..68b610f0a Binary files /dev/null and b/media/vocal/miya/perfect_clear_3.ogg differ diff --git a/media/vocal/miya/perfect_clear_4.ogg b/media/vocal/miya/perfect_clear_4.ogg new file mode 100644 index 000000000..0a165b671 Binary files /dev/null and b/media/vocal/miya/perfect_clear_4.ogg differ diff --git a/media/vocal/miya/perfect_clear_5.ogg b/media/vocal/miya/perfect_clear_5.ogg new file mode 100644 index 000000000..91579e50f Binary files /dev/null and b/media/vocal/miya/perfect_clear_5.ogg differ diff --git a/media/vocal/miya/pspin_1.ogg b/media/vocal/miya/pspin_1.ogg new file mode 100644 index 000000000..10bb18108 Binary files /dev/null and b/media/vocal/miya/pspin_1.ogg differ diff --git a/media/vocal/miya/qspin_1.ogg b/media/vocal/miya/qspin_1.ogg new file mode 100644 index 000000000..7acff5135 Binary files /dev/null and b/media/vocal/miya/qspin_1.ogg differ diff --git a/media/vocal/miya/rspin_1.ogg b/media/vocal/miya/rspin_1.ogg new file mode 100644 index 000000000..69cddb03a Binary files /dev/null and b/media/vocal/miya/rspin_1.ogg differ diff --git a/media/vocal/miya/sad_1.ogg b/media/vocal/miya/sad_1.ogg new file mode 100644 index 000000000..9654ff7b1 Binary files /dev/null and b/media/vocal/miya/sad_1.ogg differ diff --git a/media/vocal/miya/single_1.ogg b/media/vocal/miya/single_1.ogg index 41ec27983..41f9411d0 100644 Binary files a/media/vocal/miya/single_1.ogg and b/media/vocal/miya/single_1.ogg differ diff --git a/media/vocal/miya/single_2.ogg b/media/vocal/miya/single_2.ogg index e74c71030..cf32a878f 100644 Binary files a/media/vocal/miya/single_2.ogg and b/media/vocal/miya/single_2.ogg differ diff --git a/media/vocal/miya/single_3.ogg b/media/vocal/miya/single_3.ogg deleted file mode 100644 index b90251aff..000000000 Binary files a/media/vocal/miya/single_3.ogg and /dev/null differ diff --git a/media/vocal/miya/single_4.ogg b/media/vocal/miya/single_4.ogg deleted file mode 100644 index d66efcf7e..000000000 Binary files a/media/vocal/miya/single_4.ogg and /dev/null differ diff --git a/media/vocal/miya/single_5.ogg b/media/vocal/miya/single_5.ogg deleted file mode 100644 index 43c718659..000000000 Binary files a/media/vocal/miya/single_5.ogg and /dev/null differ diff --git a/media/vocal/miya/single_6.ogg b/media/vocal/miya/single_6.ogg deleted file mode 100644 index edf427ad4..000000000 Binary files a/media/vocal/miya/single_6.ogg and /dev/null differ diff --git a/media/vocal/miya/single_7.ogg b/media/vocal/miya/single_7.ogg deleted file mode 100644 index f173c2dfc..000000000 Binary files a/media/vocal/miya/single_7.ogg and /dev/null differ diff --git a/media/vocal/miya/sspin_1.ogg b/media/vocal/miya/sspin_1.ogg index b620a7e0d..34347314c 100644 Binary files a/media/vocal/miya/sspin_1.ogg and b/media/vocal/miya/sspin_1.ogg differ diff --git a/media/vocal/miya/sspin_2.ogg b/media/vocal/miya/sspin_2.ogg index e32904b5f..565df4836 100644 Binary files a/media/vocal/miya/sspin_2.ogg and b/media/vocal/miya/sspin_2.ogg differ diff --git a/media/vocal/miya/sspin_3.ogg b/media/vocal/miya/sspin_3.ogg index e6cb63311..49baebd8b 100644 Binary files a/media/vocal/miya/sspin_3.ogg and b/media/vocal/miya/sspin_3.ogg differ diff --git a/media/vocal/miya/sspin_4.ogg b/media/vocal/miya/sspin_4.ogg index a1f184688..93ad383f3 100644 Binary files a/media/vocal/miya/sspin_4.ogg and b/media/vocal/miya/sspin_4.ogg differ diff --git a/media/vocal/miya/sspin_5.ogg b/media/vocal/miya/sspin_5.ogg deleted file mode 100644 index 2494d3bb5..000000000 Binary files a/media/vocal/miya/sspin_5.ogg and /dev/null differ diff --git a/media/vocal/miya/sspin_6.ogg b/media/vocal/miya/sspin_6.ogg deleted file mode 100644 index e2690ea5c..000000000 Binary files a/media/vocal/miya/sspin_6.ogg and /dev/null differ diff --git a/media/vocal/miya/techrash_1.ogg b/media/vocal/miya/techrash_1.ogg index 4c4b6f146..32347e031 100644 Binary files a/media/vocal/miya/techrash_1.ogg and b/media/vocal/miya/techrash_1.ogg differ diff --git a/media/vocal/miya/techrash_2.ogg b/media/vocal/miya/techrash_2.ogg index c56a01f1b..b45e0783b 100644 Binary files a/media/vocal/miya/techrash_2.ogg and b/media/vocal/miya/techrash_2.ogg differ diff --git a/media/vocal/miya/techrash_3.ogg b/media/vocal/miya/techrash_3.ogg deleted file mode 100644 index 49bc7ab0f..000000000 Binary files a/media/vocal/miya/techrash_3.ogg and /dev/null differ diff --git a/media/vocal/miya/techrash_4.ogg b/media/vocal/miya/techrash_4.ogg deleted file mode 100644 index c001c793f..000000000 Binary files a/media/vocal/miya/techrash_4.ogg and /dev/null differ diff --git a/media/vocal/miya/test_1.ogg b/media/vocal/miya/test_1.ogg index c51b00c5e..68724ef42 100644 Binary files a/media/vocal/miya/test_1.ogg and b/media/vocal/miya/test_1.ogg differ diff --git a/media/vocal/miya/test_2.ogg b/media/vocal/miya/test_2.ogg index e278ffffa..6484f0c9a 100644 Binary files a/media/vocal/miya/test_2.ogg and b/media/vocal/miya/test_2.ogg differ diff --git a/media/vocal/miya/test_3.ogg b/media/vocal/miya/test_3.ogg index 0ed6aad7e..f0d6d41a1 100644 Binary files a/media/vocal/miya/test_3.ogg and b/media/vocal/miya/test_3.ogg differ diff --git a/media/vocal/miya/test_4.ogg b/media/vocal/miya/test_4.ogg index 9a7307c86..e33d10c77 100644 Binary files a/media/vocal/miya/test_4.ogg and b/media/vocal/miya/test_4.ogg differ diff --git a/media/vocal/miya/triple_1.ogg b/media/vocal/miya/triple_1.ogg index 7d564188b..aaf713710 100644 Binary files a/media/vocal/miya/triple_1.ogg and b/media/vocal/miya/triple_1.ogg differ diff --git a/media/vocal/miya/triple_2.ogg b/media/vocal/miya/triple_2.ogg index 58518f144..7285cb6af 100644 Binary files a/media/vocal/miya/triple_2.ogg and b/media/vocal/miya/triple_2.ogg differ diff --git a/media/vocal/miya/triple_3.ogg b/media/vocal/miya/triple_3.ogg index eb9daf3b9..19a697966 100644 Binary files a/media/vocal/miya/triple_3.ogg and b/media/vocal/miya/triple_3.ogg differ diff --git a/media/vocal/miya/triple_4.ogg b/media/vocal/miya/triple_4.ogg index cea64b4ab..6d10a504f 100644 Binary files a/media/vocal/miya/triple_4.ogg and b/media/vocal/miya/triple_4.ogg differ diff --git a/media/vocal/miya/triple_5.ogg b/media/vocal/miya/triple_5.ogg deleted file mode 100644 index b19062fc0..000000000 Binary files a/media/vocal/miya/triple_5.ogg and /dev/null differ diff --git a/media/vocal/miya/triple_6.ogg b/media/vocal/miya/triple_6.ogg deleted file mode 100644 index 0221d8437..000000000 Binary files a/media/vocal/miya/triple_6.ogg and /dev/null differ diff --git a/media/vocal/miya/triple_7.ogg b/media/vocal/miya/triple_7.ogg deleted file mode 100644 index 4dedec5b9..000000000 Binary files a/media/vocal/miya/triple_7.ogg and /dev/null differ diff --git a/media/vocal/miya/tspin_1.ogg b/media/vocal/miya/tspin_1.ogg index 982712b17..c70038844 100644 Binary files a/media/vocal/miya/tspin_1.ogg and b/media/vocal/miya/tspin_1.ogg differ diff --git a/media/vocal/miya/tspin_2.ogg b/media/vocal/miya/tspin_2.ogg index f597536ad..87640b3a6 100644 Binary files a/media/vocal/miya/tspin_2.ogg and b/media/vocal/miya/tspin_2.ogg differ diff --git a/media/vocal/miya/tspin_3.ogg b/media/vocal/miya/tspin_3.ogg index d15c53480..6a1a8a422 100644 Binary files a/media/vocal/miya/tspin_3.ogg and b/media/vocal/miya/tspin_3.ogg differ diff --git a/media/vocal/miya/tspin_4.ogg b/media/vocal/miya/tspin_4.ogg deleted file mode 100644 index 3747c6eb8..000000000 Binary files a/media/vocal/miya/tspin_4.ogg and /dev/null differ diff --git a/media/vocal/miya/tspin_5.ogg b/media/vocal/miya/tspin_5.ogg deleted file mode 100644 index af2487ea0..000000000 Binary files a/media/vocal/miya/tspin_5.ogg and /dev/null differ diff --git a/media/vocal/miya/tspin_6.ogg b/media/vocal/miya/tspin_6.ogg deleted file mode 100644 index 0b569d33e..000000000 Binary files a/media/vocal/miya/tspin_6.ogg and /dev/null differ diff --git a/media/vocal/miya/uspin_1.ogg b/media/vocal/miya/uspin_1.ogg new file mode 100644 index 000000000..3ed149243 Binary files /dev/null and b/media/vocal/miya/uspin_1.ogg differ diff --git a/media/vocal/miya/vspin_1.ogg b/media/vocal/miya/vspin_1.ogg new file mode 100644 index 000000000..2b1c5f2bf Binary files /dev/null and b/media/vocal/miya/vspin_1.ogg differ diff --git a/media/vocal/miya/welcome.ogg b/media/vocal/miya/welcome.ogg deleted file mode 100644 index 908560473..000000000 Binary files a/media/vocal/miya/welcome.ogg and /dev/null differ diff --git a/media/vocal/miya/welcome_1.ogg b/media/vocal/miya/welcome_1.ogg new file mode 100644 index 000000000..11e74486c Binary files /dev/null and b/media/vocal/miya/welcome_1.ogg differ diff --git a/media/vocal/miya/welcome_2.ogg b/media/vocal/miya/welcome_2.ogg new file mode 100644 index 000000000..daf001cce Binary files /dev/null and b/media/vocal/miya/welcome_2.ogg differ diff --git a/media/vocal/miya/welcome_3.ogg b/media/vocal/miya/welcome_3.ogg new file mode 100644 index 000000000..1b8b77499 Binary files /dev/null and b/media/vocal/miya/welcome_3.ogg differ diff --git a/media/vocal/miya/welcome_4.ogg b/media/vocal/miya/welcome_4.ogg new file mode 100644 index 000000000..33df5771e Binary files /dev/null and b/media/vocal/miya/welcome_4.ogg differ diff --git a/media/vocal/miya/welcome_5.ogg b/media/vocal/miya/welcome_5.ogg new file mode 100644 index 000000000..5f85a97b2 Binary files /dev/null and b/media/vocal/miya/welcome_5.ogg differ diff --git a/media/vocal/miya/welcome_6.ogg b/media/vocal/miya/welcome_6.ogg new file mode 100644 index 000000000..46706bfb3 Binary files /dev/null and b/media/vocal/miya/welcome_6.ogg differ diff --git a/media/vocal/miya/win_1.ogg b/media/vocal/miya/win_1.ogg index 502d5d22b..0811560a3 100644 Binary files a/media/vocal/miya/win_1.ogg and b/media/vocal/miya/win_1.ogg differ diff --git a/media/vocal/miya/win_2.ogg b/media/vocal/miya/win_2.ogg index 543ca30ac..18d2912b6 100644 Binary files a/media/vocal/miya/win_2.ogg and b/media/vocal/miya/win_2.ogg differ diff --git a/media/vocal/miya/win_3.ogg b/media/vocal/miya/win_3.ogg index f50557127..86861684d 100644 Binary files a/media/vocal/miya/win_3.ogg and b/media/vocal/miya/win_3.ogg differ diff --git a/media/vocal/miya/win_4.ogg b/media/vocal/miya/win_4.ogg index 7528d3929..bb55c76b6 100644 Binary files a/media/vocal/miya/win_4.ogg and b/media/vocal/miya/win_4.ogg differ diff --git a/media/vocal/miya/win_5.ogg b/media/vocal/miya/win_5.ogg index c0e14db01..8210e03c1 100644 Binary files a/media/vocal/miya/win_5.ogg and b/media/vocal/miya/win_5.ogg differ diff --git a/media/vocal/miya/win_6.ogg b/media/vocal/miya/win_6.ogg index 99f681c41..1fe6416be 100644 Binary files a/media/vocal/miya/win_6.ogg and b/media/vocal/miya/win_6.ogg differ diff --git a/media/vocal/miya/win_7.ogg b/media/vocal/miya/win_7.ogg deleted file mode 100644 index fa5fa03be..000000000 Binary files a/media/vocal/miya/win_7.ogg and /dev/null differ diff --git a/media/vocal/miya/win_8.ogg b/media/vocal/miya/win_8.ogg deleted file mode 100644 index bcf18792d..000000000 Binary files a/media/vocal/miya/win_8.ogg and /dev/null differ diff --git a/media/vocal/miya/wspin_1.ogg b/media/vocal/miya/wspin_1.ogg new file mode 100644 index 000000000..3e2d490a5 Binary files /dev/null and b/media/vocal/miya/wspin_1.ogg differ diff --git a/media/vocal/miya/xspin_1.ogg b/media/vocal/miya/xspin_1.ogg new file mode 100644 index 000000000..823707d99 Binary files /dev/null and b/media/vocal/miya/xspin_1.ogg differ diff --git a/media/vocal/miya/yspin_1.ogg b/media/vocal/miya/yspin_1.ogg new file mode 100644 index 000000000..82af8c26d Binary files /dev/null and b/media/vocal/miya/yspin_1.ogg differ diff --git a/media/vocal/miya/zspin_1.ogg b/media/vocal/miya/zspin_1.ogg index 8da82c520..7e9698975 100644 Binary files a/media/vocal/miya/zspin_1.ogg and b/media/vocal/miya/zspin_1.ogg differ diff --git a/media/vocal/miya/zspin_2.ogg b/media/vocal/miya/zspin_2.ogg index 776e51933..42736c160 100644 Binary files a/media/vocal/miya/zspin_2.ogg and b/media/vocal/miya/zspin_2.ogg differ diff --git a/media/vocal/miya/zspin_3.ogg b/media/vocal/miya/zspin_3.ogg index 91bd6caa8..c43fdad05 100644 Binary files a/media/vocal/miya/zspin_3.ogg and b/media/vocal/miya/zspin_3.ogg differ diff --git a/media/vocal/mono/bye_1.ogg b/media/vocal/mono/bye_1.ogg new file mode 100644 index 000000000..973a7fbdc Binary files /dev/null and b/media/vocal/mono/bye_1.ogg differ diff --git a/media/vocal/mono/bye_2.ogg b/media/vocal/mono/bye_2.ogg new file mode 100644 index 000000000..65073d7c3 Binary files /dev/null and b/media/vocal/mono/bye_2.ogg differ diff --git a/media/vocal/mono/bye_3.ogg b/media/vocal/mono/bye_3.ogg new file mode 100644 index 000000000..70c9e3761 Binary files /dev/null and b/media/vocal/mono/bye_3.ogg differ diff --git a/media/vocal/mono/bye_4.ogg b/media/vocal/mono/bye_4.ogg new file mode 100644 index 000000000..24b94a561 Binary files /dev/null and b/media/vocal/mono/bye_4.ogg differ diff --git a/media/vocal/mono/clear_1.ogg b/media/vocal/mono/clear_1.ogg new file mode 100644 index 000000000..9d6714a3c Binary files /dev/null and b/media/vocal/mono/clear_1.ogg differ diff --git a/media/vocal/mono/clear_2.ogg b/media/vocal/mono/clear_2.ogg new file mode 100644 index 000000000..1542fe6e7 Binary files /dev/null and b/media/vocal/mono/clear_2.ogg differ diff --git a/media/vocal/mono/clear_3.ogg b/media/vocal/mono/clear_3.ogg new file mode 100644 index 000000000..fc0bf401c Binary files /dev/null and b/media/vocal/mono/clear_3.ogg differ diff --git a/media/vocal/mono/clear_4.ogg b/media/vocal/mono/clear_4.ogg new file mode 100644 index 000000000..e128d9fc4 Binary files /dev/null and b/media/vocal/mono/clear_4.ogg differ diff --git a/media/vocal/mono/double.ogg b/media/vocal/mono/double.ogg deleted file mode 100644 index 8617370df..000000000 Binary files a/media/vocal/mono/double.ogg and /dev/null differ diff --git a/media/vocal/mono/double_1.ogg b/media/vocal/mono/double_1.ogg new file mode 100644 index 000000000..8469bf0a0 Binary files /dev/null and b/media/vocal/mono/double_1.ogg differ diff --git a/media/vocal/mono/double_2.ogg b/media/vocal/mono/double_2.ogg new file mode 100644 index 000000000..77bbd7009 Binary files /dev/null and b/media/vocal/mono/double_2.ogg differ diff --git a/media/vocal/mono/double_3.ogg b/media/vocal/mono/double_3.ogg new file mode 100644 index 000000000..f13dc6535 Binary files /dev/null and b/media/vocal/mono/double_3.ogg differ diff --git a/media/vocal/mono/double_4.ogg b/media/vocal/mono/double_4.ogg new file mode 100644 index 000000000..e68d0d3af Binary files /dev/null and b/media/vocal/mono/double_4.ogg differ diff --git a/media/vocal/mono/doubt_1.ogg b/media/vocal/mono/doubt_1.ogg new file mode 100644 index 000000000..7cf249862 Binary files /dev/null and b/media/vocal/mono/doubt_1.ogg differ diff --git a/media/vocal/mono/doubt_2.ogg b/media/vocal/mono/doubt_2.ogg new file mode 100644 index 000000000..626a63aea Binary files /dev/null and b/media/vocal/mono/doubt_2.ogg differ diff --git a/media/vocal/mono/doubt_3.ogg b/media/vocal/mono/doubt_3.ogg new file mode 100644 index 000000000..63a37d62b Binary files /dev/null and b/media/vocal/mono/doubt_3.ogg differ diff --git a/media/vocal/mono/doubt_4.ogg b/media/vocal/mono/doubt_4.ogg new file mode 100644 index 000000000..c48cfec60 Binary files /dev/null and b/media/vocal/mono/doubt_4.ogg differ diff --git a/media/vocal/mono/half_clear_1.ogg b/media/vocal/mono/half_clear.ogg similarity index 100% rename from media/vocal/mono/half_clear_1.ogg rename to media/vocal/mono/half_clear.ogg diff --git a/media/vocal/mono/happy_1.ogg b/media/vocal/mono/happy_1.ogg new file mode 100644 index 000000000..55013860b Binary files /dev/null and b/media/vocal/mono/happy_1.ogg differ diff --git a/media/vocal/mono/happy_2.ogg b/media/vocal/mono/happy_2.ogg new file mode 100644 index 000000000..71445d813 Binary files /dev/null and b/media/vocal/mono/happy_2.ogg differ diff --git a/media/vocal/mono/happy_3.ogg b/media/vocal/mono/happy_3.ogg new file mode 100644 index 000000000..b98941221 Binary files /dev/null and b/media/vocal/mono/happy_3.ogg differ diff --git a/media/vocal/mono/happy_4.ogg b/media/vocal/mono/happy_4.ogg new file mode 100644 index 000000000..e076edbb7 Binary files /dev/null and b/media/vocal/mono/happy_4.ogg differ diff --git a/media/vocal/mono/hexacrash_1.ogg b/media/vocal/mono/hexacrash_1.ogg new file mode 100644 index 000000000..8bdf767cb Binary files /dev/null and b/media/vocal/mono/hexacrash_1.ogg differ diff --git a/media/vocal/mono/hexacrash_2.ogg b/media/vocal/mono/hexacrash_2.ogg new file mode 100644 index 000000000..3183fc80e Binary files /dev/null and b/media/vocal/mono/hexacrash_2.ogg differ diff --git a/media/vocal/mono/hexacrash_3.ogg b/media/vocal/mono/hexacrash_3.ogg new file mode 100644 index 000000000..702c2b205 Binary files /dev/null and b/media/vocal/mono/hexacrash_3.ogg differ diff --git a/media/vocal/mono/hexacrash_4.ogg b/media/vocal/mono/hexacrash_4.ogg new file mode 100644 index 000000000..c9b7d7945 Binary files /dev/null and b/media/vocal/mono/hexacrash_4.ogg differ diff --git a/media/vocal/mono/ispin.ogg b/media/vocal/mono/ispin.ogg new file mode 100644 index 000000000..07ef4f09b Binary files /dev/null and b/media/vocal/mono/ispin.ogg differ diff --git a/media/vocal/mono/ispin0.ogg b/media/vocal/mono/ispin0.ogg new file mode 100644 index 000000000..5a9fcea46 Binary files /dev/null and b/media/vocal/mono/ispin0.ogg differ diff --git a/media/vocal/mono/ispin_1.ogg b/media/vocal/mono/ispin_1.ogg deleted file mode 100644 index b269f77c1..000000000 Binary files a/media/vocal/mono/ispin_1.ogg and /dev/null differ diff --git a/media/vocal/mono/ispin_2.ogg b/media/vocal/mono/ispin_2.ogg deleted file mode 100644 index 63e40ee35..000000000 Binary files a/media/vocal/mono/ispin_2.ogg and /dev/null differ diff --git a/media/vocal/mono/ispin_3.ogg b/media/vocal/mono/ispin_3.ogg deleted file mode 100644 index 310ed5791..000000000 Binary files a/media/vocal/mono/ispin_3.ogg and /dev/null differ diff --git a/media/vocal/mono/ispin_4.ogg b/media/vocal/mono/ispin_4.ogg deleted file mode 100644 index bf506a045..000000000 Binary files a/media/vocal/mono/ispin_4.ogg and /dev/null differ diff --git a/media/vocal/mono/jspin.ogg b/media/vocal/mono/jspin.ogg new file mode 100644 index 000000000..579eddd65 Binary files /dev/null and b/media/vocal/mono/jspin.ogg differ diff --git a/media/vocal/mono/jspin0.ogg b/media/vocal/mono/jspin0.ogg new file mode 100644 index 000000000..35d7dda15 Binary files /dev/null and b/media/vocal/mono/jspin0.ogg differ diff --git a/media/vocal/mono/jspin_1.ogg b/media/vocal/mono/jspin_1.ogg deleted file mode 100644 index 420eb5f34..000000000 Binary files a/media/vocal/mono/jspin_1.ogg and /dev/null differ diff --git a/media/vocal/mono/jspin_2.ogg b/media/vocal/mono/jspin_2.ogg deleted file mode 100644 index 68fb6f3dd..000000000 Binary files a/media/vocal/mono/jspin_2.ogg and /dev/null differ diff --git a/media/vocal/mono/jspin_3.ogg b/media/vocal/mono/jspin_3.ogg deleted file mode 100644 index 407052326..000000000 Binary files a/media/vocal/mono/jspin_3.ogg and /dev/null differ diff --git a/media/vocal/mono/jspin_4.ogg b/media/vocal/mono/jspin_4.ogg deleted file mode 100644 index 322556027..000000000 Binary files a/media/vocal/mono/jspin_4.ogg and /dev/null differ diff --git a/media/vocal/mono/lose_1.ogg b/media/vocal/mono/lose_1.ogg index 7cd53e1bb..9b645c3d4 100644 Binary files a/media/vocal/mono/lose_1.ogg and b/media/vocal/mono/lose_1.ogg differ diff --git a/media/vocal/mono/lose_2.ogg b/media/vocal/mono/lose_2.ogg index 58c0f5b38..94fe5124c 100644 Binary files a/media/vocal/mono/lose_2.ogg and b/media/vocal/mono/lose_2.ogg differ diff --git a/media/vocal/mono/lose_3.ogg b/media/vocal/mono/lose_3.ogg index fbab21e72..8ede047a3 100644 Binary files a/media/vocal/mono/lose_3.ogg and b/media/vocal/mono/lose_3.ogg differ diff --git a/media/vocal/mono/lose_4.ogg b/media/vocal/mono/lose_4.ogg new file mode 100644 index 000000000..2832ab42d Binary files /dev/null and b/media/vocal/mono/lose_4.ogg differ diff --git a/media/vocal/mono/lose_5.ogg b/media/vocal/mono/lose_5.ogg new file mode 100644 index 000000000..1b3a2171b Binary files /dev/null and b/media/vocal/mono/lose_5.ogg differ diff --git a/media/vocal/mono/lose_6.ogg b/media/vocal/mono/lose_6.ogg new file mode 100644 index 000000000..181497731 Binary files /dev/null and b/media/vocal/mono/lose_6.ogg differ diff --git a/media/vocal/mono/lspin.ogg b/media/vocal/mono/lspin.ogg new file mode 100644 index 000000000..83097cbc7 Binary files /dev/null and b/media/vocal/mono/lspin.ogg differ diff --git a/media/vocal/mono/lspin0.ogg b/media/vocal/mono/lspin0.ogg new file mode 100644 index 000000000..9ae4cc605 Binary files /dev/null and b/media/vocal/mono/lspin0.ogg differ diff --git a/media/vocal/mono/lspin_1.ogg b/media/vocal/mono/lspin_1.ogg deleted file mode 100644 index ccd114b18..000000000 Binary files a/media/vocal/mono/lspin_1.ogg and /dev/null differ diff --git a/media/vocal/mono/lspin_2.ogg b/media/vocal/mono/lspin_2.ogg deleted file mode 100644 index ac44b0045..000000000 Binary files a/media/vocal/mono/lspin_2.ogg and /dev/null differ diff --git a/media/vocal/mono/lspin_3.ogg b/media/vocal/mono/lspin_3.ogg deleted file mode 100644 index 72995edb7..000000000 Binary files a/media/vocal/mono/lspin_3.ogg and /dev/null differ diff --git a/media/vocal/mono/mini_1.ogg b/media/vocal/mono/mini_1.ogg deleted file mode 100644 index 4a5e4a2e2..000000000 Binary files a/media/vocal/mono/mini_1.ogg and /dev/null differ diff --git a/media/vocal/mono/mini_2.ogg b/media/vocal/mono/mini_2.ogg deleted file mode 100644 index 1245e8a2a..000000000 Binary files a/media/vocal/mono/mini_2.ogg and /dev/null differ diff --git a/media/vocal/mono/mini_3.ogg b/media/vocal/mono/mini_3.ogg deleted file mode 100644 index 18888005d..000000000 Binary files a/media/vocal/mono/mini_3.ogg and /dev/null differ diff --git a/media/vocal/mono/ospin.ogg b/media/vocal/mono/ospin.ogg new file mode 100644 index 000000000..20d0a9d24 Binary files /dev/null and b/media/vocal/mono/ospin.ogg differ diff --git a/media/vocal/mono/ospin0.ogg b/media/vocal/mono/ospin0.ogg new file mode 100644 index 000000000..c55725476 Binary files /dev/null and b/media/vocal/mono/ospin0.ogg differ diff --git a/media/vocal/mono/ospin_1.ogg b/media/vocal/mono/ospin_1.ogg deleted file mode 100644 index 3016ed39a..000000000 Binary files a/media/vocal/mono/ospin_1.ogg and /dev/null differ diff --git a/media/vocal/mono/ospin_2.ogg b/media/vocal/mono/ospin_2.ogg deleted file mode 100644 index 83695304a..000000000 Binary files a/media/vocal/mono/ospin_2.ogg and /dev/null differ diff --git a/media/vocal/mono/ospin_3.ogg b/media/vocal/mono/ospin_3.ogg deleted file mode 100644 index 185f43892..000000000 Binary files a/media/vocal/mono/ospin_3.ogg and /dev/null differ diff --git a/media/vocal/mono/pentacrash_1.ogg b/media/vocal/mono/pentacrash_1.ogg new file mode 100644 index 000000000..948aa8f5d Binary files /dev/null and b/media/vocal/mono/pentacrash_1.ogg differ diff --git a/media/vocal/mono/pentacrash_2.ogg b/media/vocal/mono/pentacrash_2.ogg new file mode 100644 index 000000000..41db171f0 Binary files /dev/null and b/media/vocal/mono/pentacrash_2.ogg differ diff --git a/media/vocal/mono/pentacrash_3.ogg b/media/vocal/mono/pentacrash_3.ogg new file mode 100644 index 000000000..a41017d61 Binary files /dev/null and b/media/vocal/mono/pentacrash_3.ogg differ diff --git a/media/vocal/mono/pentacrash_4.ogg b/media/vocal/mono/pentacrash_4.ogg new file mode 100644 index 000000000..b79348f7e Binary files /dev/null and b/media/vocal/mono/pentacrash_4.ogg differ diff --git a/media/vocal/mono/perfect_clear.ogg b/media/vocal/mono/perfect_clear.ogg deleted file mode 100644 index 9634a49f2..000000000 Binary files a/media/vocal/mono/perfect_clear.ogg and /dev/null differ diff --git a/media/vocal/mono/perfect_clear_1.ogg b/media/vocal/mono/perfect_clear_1.ogg new file mode 100644 index 000000000..7edf99d1b Binary files /dev/null and b/media/vocal/mono/perfect_clear_1.ogg differ diff --git a/media/vocal/mono/perfect_clear_2.ogg b/media/vocal/mono/perfect_clear_2.ogg new file mode 100644 index 000000000..550726c97 Binary files /dev/null and b/media/vocal/mono/perfect_clear_2.ogg differ diff --git a/media/vocal/mono/perfect_clear_3.ogg b/media/vocal/mono/perfect_clear_3.ogg new file mode 100644 index 000000000..7ea10fcfc Binary files /dev/null and b/media/vocal/mono/perfect_clear_3.ogg differ diff --git a/media/vocal/mono/perfect_clear_4.ogg b/media/vocal/mono/perfect_clear_4.ogg new file mode 100644 index 000000000..279d03801 Binary files /dev/null and b/media/vocal/mono/perfect_clear_4.ogg differ diff --git a/media/vocal/mono/single_1.ogg b/media/vocal/mono/single_1.ogg index 6591a2de1..83f3b062b 100644 Binary files a/media/vocal/mono/single_1.ogg and b/media/vocal/mono/single_1.ogg differ diff --git a/media/vocal/mono/single_2.ogg b/media/vocal/mono/single_2.ogg index 3e930847d..1c282225d 100644 Binary files a/media/vocal/mono/single_2.ogg and b/media/vocal/mono/single_2.ogg differ diff --git a/media/vocal/mono/single_3.ogg b/media/vocal/mono/single_3.ogg new file mode 100644 index 000000000..f5fafda9d Binary files /dev/null and b/media/vocal/mono/single_3.ogg differ diff --git a/media/vocal/mono/single_4.ogg b/media/vocal/mono/single_4.ogg new file mode 100644 index 000000000..26a42b968 Binary files /dev/null and b/media/vocal/mono/single_4.ogg differ diff --git a/media/vocal/mono/sspin.ogg b/media/vocal/mono/sspin.ogg new file mode 100644 index 000000000..05569f799 Binary files /dev/null and b/media/vocal/mono/sspin.ogg differ diff --git a/media/vocal/mono/sspin0.ogg b/media/vocal/mono/sspin0.ogg new file mode 100644 index 000000000..c8ba8dc2e Binary files /dev/null and b/media/vocal/mono/sspin0.ogg differ diff --git a/media/vocal/mono/sspin_1.ogg b/media/vocal/mono/sspin_1.ogg deleted file mode 100644 index 97ae12a9d..000000000 Binary files a/media/vocal/mono/sspin_1.ogg and /dev/null differ diff --git a/media/vocal/mono/sspin_2.ogg b/media/vocal/mono/sspin_2.ogg deleted file mode 100644 index 50b1f8bda..000000000 Binary files a/media/vocal/mono/sspin_2.ogg and /dev/null differ diff --git a/media/vocal/mono/sspin_3.ogg b/media/vocal/mono/sspin_3.ogg deleted file mode 100644 index e3c444236..000000000 Binary files a/media/vocal/mono/sspin_3.ogg and /dev/null differ diff --git a/media/vocal/mono/techrash_1.ogg b/media/vocal/mono/techrash_1.ogg index 77d1dbbde..181a350e4 100644 Binary files a/media/vocal/mono/techrash_1.ogg and b/media/vocal/mono/techrash_1.ogg differ diff --git a/media/vocal/mono/techrash_2.ogg b/media/vocal/mono/techrash_2.ogg index 4b9578377..06a44db02 100644 Binary files a/media/vocal/mono/techrash_2.ogg and b/media/vocal/mono/techrash_2.ogg differ diff --git a/media/vocal/mono/techrash_3.ogg b/media/vocal/mono/techrash_3.ogg new file mode 100644 index 000000000..11a699d4b Binary files /dev/null and b/media/vocal/mono/techrash_3.ogg differ diff --git a/media/vocal/mono/techrash_4.ogg b/media/vocal/mono/techrash_4.ogg new file mode 100644 index 000000000..4491bb7d5 Binary files /dev/null and b/media/vocal/mono/techrash_4.ogg differ diff --git a/media/vocal/mono/test_1.ogg b/media/vocal/mono/test_1.ogg index ce261bdb8..78b66cb7e 100644 Binary files a/media/vocal/mono/test_1.ogg and b/media/vocal/mono/test_1.ogg differ diff --git a/media/vocal/mono/test_2.ogg b/media/vocal/mono/test_2.ogg index 4720a201f..3bc1f4f09 100644 Binary files a/media/vocal/mono/test_2.ogg and b/media/vocal/mono/test_2.ogg differ diff --git a/media/vocal/mono/test_3.ogg b/media/vocal/mono/test_3.ogg new file mode 100644 index 000000000..6cbbb6d11 Binary files /dev/null and b/media/vocal/mono/test_3.ogg differ diff --git a/media/vocal/mono/test_4.ogg b/media/vocal/mono/test_4.ogg new file mode 100644 index 000000000..71a95645a Binary files /dev/null and b/media/vocal/mono/test_4.ogg differ diff --git a/media/vocal/mono/triple.ogg b/media/vocal/mono/triple.ogg deleted file mode 100644 index dade3b06e..000000000 Binary files a/media/vocal/mono/triple.ogg and /dev/null differ diff --git a/media/vocal/mono/triple_1.ogg b/media/vocal/mono/triple_1.ogg index 562475dc7..8eb3de1ca 100644 Binary files a/media/vocal/mono/triple_1.ogg and b/media/vocal/mono/triple_1.ogg differ diff --git a/media/vocal/mono/triple_2.ogg b/media/vocal/mono/triple_2.ogg new file mode 100644 index 000000000..11880edf7 Binary files /dev/null and b/media/vocal/mono/triple_2.ogg differ diff --git a/media/vocal/mono/triple_3.ogg b/media/vocal/mono/triple_3.ogg new file mode 100644 index 000000000..216786262 Binary files /dev/null and b/media/vocal/mono/triple_3.ogg differ diff --git a/media/vocal/mono/triple_4.ogg b/media/vocal/mono/triple_4.ogg new file mode 100644 index 000000000..d3af588bb Binary files /dev/null and b/media/vocal/mono/triple_4.ogg differ diff --git a/media/vocal/mono/tspin.ogg b/media/vocal/mono/tspin.ogg new file mode 100644 index 000000000..8be45f917 Binary files /dev/null and b/media/vocal/mono/tspin.ogg differ diff --git a/media/vocal/mono/tspin0.ogg b/media/vocal/mono/tspin0.ogg new file mode 100644 index 000000000..dfc91b687 Binary files /dev/null and b/media/vocal/mono/tspin0.ogg differ diff --git a/media/vocal/mono/tspin_1.ogg b/media/vocal/mono/tspin_1.ogg deleted file mode 100644 index 1d2dc3abd..000000000 Binary files a/media/vocal/mono/tspin_1.ogg and /dev/null differ diff --git a/media/vocal/mono/tspin_2.ogg b/media/vocal/mono/tspin_2.ogg deleted file mode 100644 index a7fecadf8..000000000 Binary files a/media/vocal/mono/tspin_2.ogg and /dev/null differ diff --git a/media/vocal/mono/tspin_3.ogg b/media/vocal/mono/tspin_3.ogg deleted file mode 100644 index f0dad5a33..000000000 Binary files a/media/vocal/mono/tspin_3.ogg and /dev/null differ diff --git a/media/vocal/mono/welcome_1.ogg b/media/vocal/mono/welcome_1.ogg index d8f56e004..34008c076 100644 Binary files a/media/vocal/mono/welcome_1.ogg and b/media/vocal/mono/welcome_1.ogg differ diff --git a/media/vocal/mono/welcome_2.ogg b/media/vocal/mono/welcome_2.ogg index d7ba3b372..04b636e5a 100644 Binary files a/media/vocal/mono/welcome_2.ogg and b/media/vocal/mono/welcome_2.ogg differ diff --git a/media/vocal/mono/welcome_3.ogg b/media/vocal/mono/welcome_3.ogg index db690c620..97e1e500d 100644 Binary files a/media/vocal/mono/welcome_3.ogg and b/media/vocal/mono/welcome_3.ogg differ diff --git a/media/vocal/mono/welcome_4.ogg b/media/vocal/mono/welcome_4.ogg new file mode 100644 index 000000000..b6eeb8b0f Binary files /dev/null and b/media/vocal/mono/welcome_4.ogg differ diff --git a/media/vocal/mono/welcome_5.ogg b/media/vocal/mono/welcome_5.ogg new file mode 100644 index 000000000..c88e9ae9a Binary files /dev/null and b/media/vocal/mono/welcome_5.ogg differ diff --git a/media/vocal/mono/win_1.ogg b/media/vocal/mono/win_1.ogg index 1a733e9f2..dc4f023b0 100644 Binary files a/media/vocal/mono/win_1.ogg and b/media/vocal/mono/win_1.ogg differ diff --git a/media/vocal/mono/win_2.ogg b/media/vocal/mono/win_2.ogg index 94e80c8bf..bfab69057 100644 Binary files a/media/vocal/mono/win_2.ogg and b/media/vocal/mono/win_2.ogg differ diff --git a/media/vocal/mono/win_3.ogg b/media/vocal/mono/win_3.ogg index 04e8a1335..c159100a8 100644 Binary files a/media/vocal/mono/win_3.ogg and b/media/vocal/mono/win_3.ogg differ diff --git a/media/vocal/mono/win_4.ogg b/media/vocal/mono/win_4.ogg new file mode 100644 index 000000000..b49f3e755 Binary files /dev/null and b/media/vocal/mono/win_4.ogg differ diff --git a/media/vocal/mono/win_5.ogg b/media/vocal/mono/win_5.ogg new file mode 100644 index 000000000..dbfcb85ae Binary files /dev/null and b/media/vocal/mono/win_5.ogg differ diff --git a/media/vocal/mono/zspin.ogg b/media/vocal/mono/zspin.ogg new file mode 100644 index 000000000..358de5c9e Binary files /dev/null and b/media/vocal/mono/zspin.ogg differ diff --git a/media/vocal/mono/zspin0.ogg b/media/vocal/mono/zspin0.ogg new file mode 100644 index 000000000..46c2b96d7 Binary files /dev/null and b/media/vocal/mono/zspin0.ogg differ diff --git a/media/vocal/mono/zspin_1.ogg b/media/vocal/mono/zspin_1.ogg deleted file mode 100644 index 65508f39b..000000000 Binary files a/media/vocal/mono/zspin_1.ogg and /dev/null differ diff --git a/media/vocal/mono/zspin_2.ogg b/media/vocal/mono/zspin_2.ogg deleted file mode 100644 index a7b77163d..000000000 Binary files a/media/vocal/mono/zspin_2.ogg and /dev/null differ diff --git a/media/vocal/mono/zspin_3.ogg b/media/vocal/mono/zspin_3.ogg deleted file mode 100644 index 91c6157bb..000000000 Binary files a/media/vocal/mono/zspin_3.ogg and /dev/null differ diff --git a/media/vocal/zundamon/air.ogg b/media/vocal/zundamon/air.ogg new file mode 100644 index 000000000..b18c02649 Binary files /dev/null and b/media/vocal/zundamon/air.ogg differ diff --git a/media/vocal/zundamon/b2b.ogg b/media/vocal/zundamon/b2b.ogg new file mode 100644 index 000000000..608b25b2d Binary files /dev/null and b/media/vocal/zundamon/b2b.ogg differ diff --git a/media/vocal/zundamon/b3b.ogg b/media/vocal/zundamon/b3b.ogg new file mode 100644 index 000000000..1b4f3c761 Binary files /dev/null and b/media/vocal/zundamon/b3b.ogg differ diff --git a/media/vocal/zundamon/bye.ogg b/media/vocal/zundamon/bye.ogg new file mode 100644 index 000000000..51b03349c Binary files /dev/null and b/media/vocal/zundamon/bye.ogg differ diff --git a/media/vocal/zundamon/color.ogg b/media/vocal/zundamon/color.ogg new file mode 100644 index 000000000..983ff29f8 Binary files /dev/null and b/media/vocal/zundamon/color.ogg differ diff --git a/media/vocal/zundamon/cspin.ogg b/media/vocal/zundamon/cspin.ogg new file mode 100644 index 000000000..6e2dc58fa Binary files /dev/null and b/media/vocal/zundamon/cspin.ogg differ diff --git a/media/vocal/zundamon/cspin0.ogg b/media/vocal/zundamon/cspin0.ogg new file mode 100644 index 000000000..e5c99caee Binary files /dev/null and b/media/vocal/zundamon/cspin0.ogg differ diff --git a/media/vocal/zundamon/decacrash.ogg b/media/vocal/zundamon/decacrash.ogg new file mode 100644 index 000000000..902c1a7ef Binary files /dev/null and b/media/vocal/zundamon/decacrash.ogg differ diff --git a/media/vocal/zundamon/deep.ogg b/media/vocal/zundamon/deep.ogg new file mode 100644 index 000000000..e447e63bc Binary files /dev/null and b/media/vocal/zundamon/deep.ogg differ diff --git a/media/vocal/zundamon/dodecacrash.ogg b/media/vocal/zundamon/dodecacrash.ogg new file mode 100644 index 000000000..96664eede Binary files /dev/null and b/media/vocal/zundamon/dodecacrash.ogg differ diff --git a/media/vocal/zundamon/double.ogg b/media/vocal/zundamon/double.ogg new file mode 100644 index 000000000..3cd5e9538 Binary files /dev/null and b/media/vocal/zundamon/double.ogg differ diff --git a/media/vocal/zundamon/doubt.ogg b/media/vocal/zundamon/doubt.ogg new file mode 100644 index 000000000..ce6664ed8 Binary files /dev/null and b/media/vocal/zundamon/doubt.ogg differ diff --git a/media/vocal/zundamon/espin.ogg b/media/vocal/zundamon/espin.ogg new file mode 100644 index 000000000..805d352ad Binary files /dev/null and b/media/vocal/zundamon/espin.ogg differ diff --git a/media/vocal/zundamon/espin0.ogg b/media/vocal/zundamon/espin0.ogg new file mode 100644 index 000000000..14cceddc8 Binary files /dev/null and b/media/vocal/zundamon/espin0.ogg differ diff --git a/media/vocal/zundamon/fspin.ogg b/media/vocal/zundamon/fspin.ogg new file mode 100644 index 000000000..9cc49d3f4 Binary files /dev/null and b/media/vocal/zundamon/fspin.ogg differ diff --git a/media/vocal/zundamon/fspin0.ogg b/media/vocal/zundamon/fspin0.ogg new file mode 100644 index 000000000..891c4bca6 Binary files /dev/null and b/media/vocal/zundamon/fspin0.ogg differ diff --git a/media/vocal/zundamon/half_clear_1.ogg b/media/vocal/zundamon/half_clear_1.ogg new file mode 100644 index 000000000..39b15e2d2 Binary files /dev/null and b/media/vocal/zundamon/half_clear_1.ogg differ diff --git a/media/vocal/zundamon/half_clear_2.ogg b/media/vocal/zundamon/half_clear_2.ogg new file mode 100644 index 000000000..cd0a1932d Binary files /dev/null and b/media/vocal/zundamon/half_clear_2.ogg differ diff --git a/media/vocal/zundamon/happy.ogg b/media/vocal/zundamon/happy.ogg new file mode 100644 index 000000000..5c472c13c Binary files /dev/null and b/media/vocal/zundamon/happy.ogg differ diff --git a/media/vocal/zundamon/heptacrash.ogg b/media/vocal/zundamon/heptacrash.ogg new file mode 100644 index 000000000..75a059927 Binary files /dev/null and b/media/vocal/zundamon/heptacrash.ogg differ diff --git a/media/vocal/zundamon/heptadecacrash.ogg b/media/vocal/zundamon/heptadecacrash.ogg new file mode 100644 index 000000000..3a69ac96a Binary files /dev/null and b/media/vocal/zundamon/heptadecacrash.ogg differ diff --git a/media/vocal/zundamon/hexacrash.ogg b/media/vocal/zundamon/hexacrash.ogg new file mode 100644 index 000000000..09d6bae8f Binary files /dev/null and b/media/vocal/zundamon/hexacrash.ogg differ diff --git a/media/vocal/zundamon/hexadecacrash.ogg b/media/vocal/zundamon/hexadecacrash.ogg new file mode 100644 index 000000000..fcb30b0c5 Binary files /dev/null and b/media/vocal/zundamon/hexadecacrash.ogg differ diff --git a/media/vocal/zundamon/hspin.ogg b/media/vocal/zundamon/hspin.ogg new file mode 100644 index 000000000..2e8ba80e1 Binary files /dev/null and b/media/vocal/zundamon/hspin.ogg differ diff --git a/media/vocal/zundamon/hspin0.ogg b/media/vocal/zundamon/hspin0.ogg new file mode 100644 index 000000000..2bfbd5ba3 Binary files /dev/null and b/media/vocal/zundamon/hspin0.ogg differ diff --git a/media/vocal/zundamon/impossicrash.ogg b/media/vocal/zundamon/impossicrash.ogg new file mode 100644 index 000000000..6ad866ba1 Binary files /dev/null and b/media/vocal/zundamon/impossicrash.ogg differ diff --git a/media/vocal/zundamon/ispin.ogg b/media/vocal/zundamon/ispin.ogg new file mode 100644 index 000000000..41bba14e7 Binary files /dev/null and b/media/vocal/zundamon/ispin.ogg differ diff --git a/media/vocal/zundamon/ispin0.ogg b/media/vocal/zundamon/ispin0.ogg new file mode 100644 index 000000000..2d1c226d2 Binary files /dev/null and b/media/vocal/zundamon/ispin0.ogg differ diff --git a/media/vocal/zundamon/jspin.ogg b/media/vocal/zundamon/jspin.ogg new file mode 100644 index 000000000..02fad4414 Binary files /dev/null and b/media/vocal/zundamon/jspin.ogg differ diff --git a/media/vocal/zundamon/jspin0.ogg b/media/vocal/zundamon/jspin0.ogg new file mode 100644 index 000000000..31c238211 Binary files /dev/null and b/media/vocal/zundamon/jspin0.ogg differ diff --git a/media/vocal/zundamon/lose_1.ogg b/media/vocal/zundamon/lose_1.ogg new file mode 100644 index 000000000..e1a30e9e1 Binary files /dev/null and b/media/vocal/zundamon/lose_1.ogg differ diff --git a/media/vocal/zundamon/lose_2.ogg b/media/vocal/zundamon/lose_2.ogg new file mode 100644 index 000000000..a0b37f328 Binary files /dev/null and b/media/vocal/zundamon/lose_2.ogg differ diff --git a/media/vocal/zundamon/lspin.ogg b/media/vocal/zundamon/lspin.ogg new file mode 100644 index 000000000..3d25fe108 Binary files /dev/null and b/media/vocal/zundamon/lspin.ogg differ diff --git a/media/vocal/zundamon/lspin0.ogg b/media/vocal/zundamon/lspin0.ogg new file mode 100644 index 000000000..3c5caa617 Binary files /dev/null and b/media/vocal/zundamon/lspin0.ogg differ diff --git a/media/vocal/zundamon/mini.ogg b/media/vocal/zundamon/mini.ogg new file mode 100644 index 000000000..5218c0b71 Binary files /dev/null and b/media/vocal/zundamon/mini.ogg differ diff --git a/media/vocal/zundamon/mis.ogg b/media/vocal/zundamon/mis.ogg new file mode 100644 index 000000000..df2b82915 Binary files /dev/null and b/media/vocal/zundamon/mis.ogg differ diff --git a/media/vocal/zundamon/nonacrash.ogg b/media/vocal/zundamon/nonacrash.ogg new file mode 100644 index 000000000..90decaf84 Binary files /dev/null and b/media/vocal/zundamon/nonacrash.ogg differ diff --git a/media/vocal/zundamon/nonadecacrash.ogg b/media/vocal/zundamon/nonadecacrash.ogg new file mode 100644 index 000000000..a46c8aa69 Binary files /dev/null and b/media/vocal/zundamon/nonadecacrash.ogg differ diff --git a/media/vocal/zundamon/nspin.ogg b/media/vocal/zundamon/nspin.ogg new file mode 100644 index 000000000..8b6dc63e1 Binary files /dev/null and b/media/vocal/zundamon/nspin.ogg differ diff --git a/media/vocal/zundamon/nspin0.ogg b/media/vocal/zundamon/nspin0.ogg new file mode 100644 index 000000000..2f84118c3 Binary files /dev/null and b/media/vocal/zundamon/nspin0.ogg differ diff --git a/media/vocal/zundamon/octacrash.ogg b/media/vocal/zundamon/octacrash.ogg new file mode 100644 index 000000000..1b458d28f Binary files /dev/null and b/media/vocal/zundamon/octacrash.ogg differ diff --git a/media/vocal/zundamon/octadecacrash.ogg b/media/vocal/zundamon/octadecacrash.ogg new file mode 100644 index 000000000..31aa8d461 Binary files /dev/null and b/media/vocal/zundamon/octadecacrash.ogg differ diff --git a/media/vocal/zundamon/ospin.ogg b/media/vocal/zundamon/ospin.ogg new file mode 100644 index 000000000..21354bf81 Binary files /dev/null and b/media/vocal/zundamon/ospin.ogg differ diff --git a/media/vocal/zundamon/ospin0.ogg b/media/vocal/zundamon/ospin0.ogg new file mode 100644 index 000000000..8166b62fb Binary files /dev/null and b/media/vocal/zundamon/ospin0.ogg differ diff --git a/media/vocal/zundamon/pentacrash.ogg b/media/vocal/zundamon/pentacrash.ogg new file mode 100644 index 000000000..7aadf737e Binary files /dev/null and b/media/vocal/zundamon/pentacrash.ogg differ diff --git a/media/vocal/zundamon/pentadecacrash.ogg b/media/vocal/zundamon/pentadecacrash.ogg new file mode 100644 index 000000000..3c1f0b791 Binary files /dev/null and b/media/vocal/zundamon/pentadecacrash.ogg differ diff --git a/media/vocal/zundamon/perfect_clear_1.ogg b/media/vocal/zundamon/perfect_clear_1.ogg new file mode 100644 index 000000000..e5bfd37dc Binary files /dev/null and b/media/vocal/zundamon/perfect_clear_1.ogg differ diff --git a/media/vocal/zundamon/perfect_clear_2.ogg b/media/vocal/zundamon/perfect_clear_2.ogg new file mode 100644 index 000000000..f2ba74878 Binary files /dev/null and b/media/vocal/zundamon/perfect_clear_2.ogg differ diff --git a/media/vocal/zundamon/pspin.ogg b/media/vocal/zundamon/pspin.ogg new file mode 100644 index 000000000..8e376b55c Binary files /dev/null and b/media/vocal/zundamon/pspin.ogg differ diff --git a/media/vocal/zundamon/pspin0.ogg b/media/vocal/zundamon/pspin0.ogg new file mode 100644 index 000000000..d7d604f1d Binary files /dev/null and b/media/vocal/zundamon/pspin0.ogg differ diff --git a/media/vocal/zundamon/qspin.ogg b/media/vocal/zundamon/qspin.ogg new file mode 100644 index 000000000..ee668e195 Binary files /dev/null and b/media/vocal/zundamon/qspin.ogg differ diff --git a/media/vocal/zundamon/qspin0.ogg b/media/vocal/zundamon/qspin0.ogg new file mode 100644 index 000000000..092a2bb0d Binary files /dev/null and b/media/vocal/zundamon/qspin0.ogg differ diff --git a/media/vocal/zundamon/rspin.ogg b/media/vocal/zundamon/rspin.ogg new file mode 100644 index 000000000..59692ec68 Binary files /dev/null and b/media/vocal/zundamon/rspin.ogg differ diff --git a/media/vocal/zundamon/rspin0.ogg b/media/vocal/zundamon/rspin0.ogg new file mode 100644 index 000000000..3ead7c168 Binary files /dev/null and b/media/vocal/zundamon/rspin0.ogg differ diff --git a/media/vocal/zundamon/single.ogg b/media/vocal/zundamon/single.ogg new file mode 100644 index 000000000..ca8823617 Binary files /dev/null and b/media/vocal/zundamon/single.ogg differ diff --git a/media/vocal/zundamon/split.ogg b/media/vocal/zundamon/split.ogg new file mode 100644 index 000000000..03a9aa954 Binary files /dev/null and b/media/vocal/zundamon/split.ogg differ diff --git a/media/vocal/zundamon/sspin.ogg b/media/vocal/zundamon/sspin.ogg new file mode 100644 index 000000000..020a63471 Binary files /dev/null and b/media/vocal/zundamon/sspin.ogg differ diff --git a/media/vocal/zundamon/sspin0.ogg b/media/vocal/zundamon/sspin0.ogg new file mode 100644 index 000000000..04507c6c4 Binary files /dev/null and b/media/vocal/zundamon/sspin0.ogg differ diff --git a/media/vocal/zundamon/techrash.ogg b/media/vocal/zundamon/techrash.ogg new file mode 100644 index 000000000..7610bded0 Binary files /dev/null and b/media/vocal/zundamon/techrash.ogg differ diff --git a/media/vocal/zundamon/test.ogg b/media/vocal/zundamon/test.ogg new file mode 100644 index 000000000..f1a028460 Binary files /dev/null and b/media/vocal/zundamon/test.ogg differ diff --git a/media/vocal/zundamon/tetradecacrash.ogg b/media/vocal/zundamon/tetradecacrash.ogg new file mode 100644 index 000000000..20fe2a690 Binary files /dev/null and b/media/vocal/zundamon/tetradecacrash.ogg differ diff --git a/media/vocal/zundamon/tridecacrash.ogg b/media/vocal/zundamon/tridecacrash.ogg new file mode 100644 index 000000000..779e35ec4 Binary files /dev/null and b/media/vocal/zundamon/tridecacrash.ogg differ diff --git a/media/vocal/zundamon/triple.ogg b/media/vocal/zundamon/triple.ogg new file mode 100644 index 000000000..97e0c0c8a Binary files /dev/null and b/media/vocal/zundamon/triple.ogg differ diff --git a/media/vocal/zundamon/tspin.ogg b/media/vocal/zundamon/tspin.ogg new file mode 100644 index 000000000..c2fed4e45 Binary files /dev/null and b/media/vocal/zundamon/tspin.ogg differ diff --git a/media/vocal/zundamon/tspin0.ogg b/media/vocal/zundamon/tspin0.ogg new file mode 100644 index 000000000..7ffede935 Binary files /dev/null and b/media/vocal/zundamon/tspin0.ogg differ diff --git a/media/vocal/zundamon/ultracrash.ogg b/media/vocal/zundamon/ultracrash.ogg new file mode 100644 index 000000000..a4aaf7e58 Binary files /dev/null and b/media/vocal/zundamon/ultracrash.ogg differ diff --git a/media/vocal/zundamon/undecacrash.ogg b/media/vocal/zundamon/undecacrash.ogg new file mode 100644 index 000000000..d2bf95040 Binary files /dev/null and b/media/vocal/zundamon/undecacrash.ogg differ diff --git a/media/vocal/zundamon/uspin.ogg b/media/vocal/zundamon/uspin.ogg new file mode 100644 index 000000000..4e06a7c62 Binary files /dev/null and b/media/vocal/zundamon/uspin.ogg differ diff --git a/media/vocal/zundamon/uspin0.ogg b/media/vocal/zundamon/uspin0.ogg new file mode 100644 index 000000000..d9795ba87 Binary files /dev/null and b/media/vocal/zundamon/uspin0.ogg differ diff --git a/media/vocal/zundamon/vspin.ogg b/media/vocal/zundamon/vspin.ogg new file mode 100644 index 000000000..00de8914a Binary files /dev/null and b/media/vocal/zundamon/vspin.ogg differ diff --git a/media/vocal/zundamon/vspin0.ogg b/media/vocal/zundamon/vspin0.ogg new file mode 100644 index 000000000..04f8be13a Binary files /dev/null and b/media/vocal/zundamon/vspin0.ogg differ diff --git a/media/vocal/zundamon/welcome_1.ogg b/media/vocal/zundamon/welcome_1.ogg new file mode 100644 index 000000000..4dec925e3 Binary files /dev/null and b/media/vocal/zundamon/welcome_1.ogg differ diff --git a/media/vocal/zundamon/welcome_2.ogg b/media/vocal/zundamon/welcome_2.ogg new file mode 100644 index 000000000..06005923c Binary files /dev/null and b/media/vocal/zundamon/welcome_2.ogg differ diff --git a/media/vocal/zundamon/win_1.ogg b/media/vocal/zundamon/win_1.ogg new file mode 100644 index 000000000..a675f27e5 Binary files /dev/null and b/media/vocal/zundamon/win_1.ogg differ diff --git a/media/vocal/zundamon/win_2.ogg b/media/vocal/zundamon/win_2.ogg new file mode 100644 index 000000000..4b7cb0f7d Binary files /dev/null and b/media/vocal/zundamon/win_2.ogg differ diff --git a/media/vocal/zundamon/wspin.ogg b/media/vocal/zundamon/wspin.ogg new file mode 100644 index 000000000..8812ccd10 Binary files /dev/null and b/media/vocal/zundamon/wspin.ogg differ diff --git a/media/vocal/zundamon/wspin0.ogg b/media/vocal/zundamon/wspin0.ogg new file mode 100644 index 000000000..656c51ccc Binary files /dev/null and b/media/vocal/zundamon/wspin0.ogg differ diff --git a/media/vocal/zundamon/xspin.ogg b/media/vocal/zundamon/xspin.ogg new file mode 100644 index 000000000..fdfc779d2 Binary files /dev/null and b/media/vocal/zundamon/xspin.ogg differ diff --git a/media/vocal/zundamon/xspin0.ogg b/media/vocal/zundamon/xspin0.ogg new file mode 100644 index 000000000..3314cb452 Binary files /dev/null and b/media/vocal/zundamon/xspin0.ogg differ diff --git a/media/vocal/zundamon/yspin.ogg b/media/vocal/zundamon/yspin.ogg new file mode 100644 index 000000000..da2e0ae54 Binary files /dev/null and b/media/vocal/zundamon/yspin.ogg differ diff --git a/media/vocal/zundamon/yspin0.ogg b/media/vocal/zundamon/yspin0.ogg new file mode 100644 index 000000000..4362b18e8 Binary files /dev/null and b/media/vocal/zundamon/yspin0.ogg differ diff --git a/media/vocal/zundamon/zspin.ogg b/media/vocal/zundamon/zspin.ogg new file mode 100644 index 000000000..5dc2ecbc7 Binary files /dev/null and b/media/vocal/zundamon/zspin.ogg differ diff --git a/media/vocal/zundamon/zspin0.ogg b/media/vocal/zundamon/zspin0.ogg new file mode 100644 index 000000000..543951dde Binary files /dev/null and b/media/vocal/zundamon/zspin0.ogg differ diff --git a/parts/RSlist.lua b/parts/RSlist.lua index 661adcfa1..1da080033 100644 --- a/parts/RSlist.lua +++ b/parts/RSlist.lua @@ -1,43 +1,43 @@ -local defaultCenterTex=GC.DO{1,1}--No texture -local defaultCenterPos={--For SRS-like RSs - --Tetromino - {[0]={0,1},{1,0},{1,1},{1,1}},--Z - {[0]={0,1},{1,0},{1,1},{1,1}},--S - {[0]={0,1},{1,0},{1,1},{1,1}},--J - {[0]={0,1},{1,0},{1,1},{1,1}},--L - {[0]={0,1},{1,0},{1,1},{1,1}},--T - {[0]={.5,.5},{.5,.5},{.5,.5},{.5,.5}},--O - {[0]={-.5,1.5},{1.5,-.5},{.5,1.5},{1.5,.5}},--I +local defaultCenterTex=GC.DO{1,1}-- No texture +local defaultCenterPos={-- For SRS-like RSs + -- Tetromino + {[0]={0,1},{1,0},{1,1},{1,1}},-- Z + {[0]={0,1},{1,0},{1,1},{1,1}},-- S + {[0]={0,1},{1,0},{1,1},{1,1}},-- J + {[0]={0,1},{1,0},{1,1},{1,1}},-- L + {[0]={0,1},{1,0},{1,1},{1,1}},-- T + {[0]={.5,.5},{.5,.5},{.5,.5},{.5,.5}},-- O + {[0]={-.5,1.5},{1.5,-.5},{.5,1.5},{1.5,.5}},-- I - --Pentomino - {[0]={1,1},{1,1},{1,1},{1,1}},--Z5 - {[0]={1,1},{1,1},{1,1},{1,1}},--S5 - {[0]={0,1},{1,0},{1,1},{1,1}},--P - {[0]={0,1},{1,0},{1,1},{1,1}},--Q - {[0]={1,1},{1,1},{1,1},{1,1}},--F - {[0]={1,1},{1,1},{1,1},{1,1}},--E - {[0]={1,1},{1,1},{1,1},{1,1}},--T5 - {[0]={0,1},{1,0},{1,1},{1,1}},--U - {[0]={.5,1.5},{.5,.5},{1.5,.5},{1.5,1.5}},--V - {[0]={1,1},{1,1},{1,1},{1,1}},--W - {[0]={1,1},{1,1},{1,1},{1,1}},--X - {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},--J5 - {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},--L5 - {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},--R - {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},--Y - {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},--N - {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},--H - {[0]={0,2},{2,0},{0,2},{2,0}},--I5 + -- Pentomino + {[0]={1,1},{1,1},{1,1},{1,1}},-- Z5 + {[0]={1,1},{1,1},{1,1},{1,1}},-- S5 + {[0]={0,1},{1,0},{1,1},{1,1}},-- P + {[0]={0,1},{1,0},{1,1},{1,1}},-- Q + {[0]={1,1},{1,1},{1,1},{1,1}},-- F + {[0]={1,1},{1,1},{1,1},{1,1}},-- E + {[0]={1,1},{1,1},{1,1},{1,1}},-- T5 + {[0]={0,1},{1,0},{1,1},{1,1}},-- U + {[0]={.5,1.5},{.5,.5},{1.5,.5},{1.5,1.5}},-- V + {[0]={1,1},{1,1},{1,1},{1,1}},-- W + {[0]={1,1},{1,1},{1,1},{1,1}},-- X + {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},-- J5 + {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},-- L5 + {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},-- R + {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},-- Y + {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},-- N + {[0]={.5,1.5},{1.5,.5},{.5,1.5},{1.5,.5}},-- H + {[0]={0,2},{2,0},{0,2},{2,0}},-- I5 - --Trimino - {[0]={0,1},{1,0},{0,1},{1,0}},--I3 - {[0]={.5,.5},{.5,.5},{.5,.5},{.5,.5}},--C + -- Trimino + {[0]={0,1},{1,0},{0,1},{1,0}},-- I3 + {[0]={.5,.5},{.5,.5},{.5,.5},{.5,.5}},-- C - --Domino - {[0]={-.5,.5},{.5,-.5},{.5,.5},{.5,.5}},--I2 + -- Domino + {[0]={-.5,.5},{.5,-.5},{.5,.5},{.5,.5}},-- I2 - --Dot - {[0]={0,0},{0,0},{0,0},{0,0}},--O1 + -- Dot + {[0]={0,0},{0,0},{0,0},{0,0}},-- O1 } local noKickSet,noKickSet_180 do @@ -52,14 +52,14 @@ local function _strToVec(list) return list end ---Use this if the block is centrosymmetry, *PTR!!! +-- Use this if the block is centrosymmetry, *PTR!!! local function _centroSymSet(L) L[23]=L[01]L[32]=L[10] L[21]=L[03]L[12]=L[30] L[20]=L[02]L[31]=L[13] end ---Use this to copy a symmetry set +-- Use this to copy a symmetry set local function _flipList(O) if not O then return @@ -72,7 +72,7 @@ local function _flipList(O) end local function _reflect(a) - return{ + return { [03]=_flipList(a[01]), [01]=_flipList(a[03]), [30]=_flipList(a[10]), @@ -91,21 +91,21 @@ end local TRS do local OspinList={ - {111,5,2, 0,-1,0},{111,5,2,-1,-1,0},{111,5,0,-1, 0,0},--T - {333,5,2,-1,-1,0},{333,5,2, 0,-1,0},{333,5,0, 0, 0,0},--T - {313,1,2,-1, 0,0},{313,1,2, 0,-1,0},{313,1,2, 0, 0,0},--Z - {131,2,2, 0, 0,0},{131,2,2,-1,-1,0},{131,2,2,-1, 0,0},--S - {131,1,2,-1, 0,0},{131,1,2, 0,-1,0},{131,1,2, 0, 0,0},--Z(misOrder) - {313,2,2, 0, 0,0},{313,2,2,-1,-1,0},{313,2,2,-1, 0,0},--S(misOrder) - {331,3,2, 0,-1,1},--J(farDown) - {113,4,2,-1,-1,1},--L(farDown) - {113,3,2,-1,-1,0},{113,3,0, 0, 0,0},--J - {331,4,2, 0,-1,0},{331,4,0,-1, 0,0},--L - {222,7,0,-1, 1,1},{222,7,0,-2, 1,1},{222,7,0, 0, 1,1},--I(high) - {222,7,2,-1, 0,2},{222,7,2,-2, 0,2},{222,7,2, 0, 0,2},--I(low) - {121,6,0, 1,-1,2},{112,6,0, 2,-1,2},{122,6,0, 1,-2,2},--O - {323,6,0,-1,-1,2},{332,6,0,-2,-1,2},{322,6,0,-1,-2,2},--O - }--{keys, ID, dir, dx, dy, freeLevel (0=immovable, 1=U/D-immovable, 2=free)} + {111,5,2, 0,-1,0},{111,5,2,-1,-1,0},{111,5,0,-1, 0,0},-- T + {333,5,2,-1,-1,0},{333,5,2, 0,-1,0},{333,5,0, 0, 0,0},-- T + {313,1,2,-1, 0,0},{313,1,2, 0,-1,0},{313,1,2, 0, 0,0},-- Z + {131,2,2, 0, 0,0},{131,2,2,-1,-1,0},{131,2,2,-1, 0,0},-- S + {131,1,2,-1, 0,0},{131,1,2, 0,-1,0},{131,1,2, 0, 0,0},-- Z(misOrder) + {313,2,2, 0, 0,0},{313,2,2,-1,-1,0},{313,2,2,-1, 0,0},-- S(misOrder) + {331,3,2, 0,-1,0},-- J(farDown) + {113,4,2,-1,-1,0},-- L(farDown) + {113,3,2,-1,-1,0},{113,3,0, 0, 0,0},-- J + {331,4,2, 0,-1,0},{331,4,0,-1, 0,0},-- L + {222,7,0,-1, 1,1},{222,7,0,-2, 1,1},{222,7,0, 0, 1,1},-- I(high) + {222,7,2,-1, 0,2},{222,7,2,-2, 0,2},{222,7,2, 0, 0,2},-- I(low) + {121,6,0, 1,-1,2},{112,6,0, 2,-1,2},{122,6,0, 1,-2,2},-- O + {323,6,0,-1,-1,2},{332,6,0,-2,-1,2},{322,6,0,-1,-2,2},-- O + }-- {keys, ID, dir, dx, dy, freeLevel (0=immovable, 1=U/D-immovable, 2=free)} local XspinList={ {{ 1,-1},{ 1, 0},{ 1, 1},{ 1,-2},{ 1, 2}}, {{ 0,-1},{ 0,-2},{ 0, 1},{ 0,-2},{ 0, 2}}, @@ -126,7 +126,7 @@ do kickTable={ { [01]={'+0+0','-1+0','-1+1','+0-2','-1+2','+0+1'}, - [10]={'+0+0','+1+0','+1-1','+0+2','+1-2','+1-2'}, + [10]={'+0+0','+1+0','+1-1','+0+2','+1-2','+0-1'}, [03]={'+0+0','+1+0','+1+1','+0-2','+1-1','+1-2'}, [30]={'+0+0','-1+0','-1-1','+0+2','-1+2','+0-1'}, [12]={'+0+0','+1+0','+1-1','+0+2','+1+2','+1+1'}, @@ -137,8 +137,8 @@ do [20]={'+0+0','-1+0','+1+0','+0+1','+0-1'}, [13]={'+0+0','+0-1','+0+1','+0-2'}, [31]={'+0+0','+0+1','+0-1','+0+2'}, - },--Z - false,--S + },-- Z + false,-- S { [01]={'+0+0','-1+0','-1+1','+0-2','+1+1','+0+1','+0-1'}, [10]={'+0+0','+1+0','+1-1','+0+2','-1-1','+0-1','+0+1'}, @@ -152,22 +152,22 @@ do [20]={'+0+0','+1+0','-1+0','+0+1','+0-1'}, [13]={'+0+0','+0-1','+0+1','+1+0'}, [31]={'+0+0','+0+1','+0-1','-1+0'}, - },--J - false,--L + },-- J + false,-- L { [01]={'+0+0','-1+0','-1+1','+0-2','-1-2','+0+1'}, - [10]={'+0+0','+1+0','+1-1','+0+2','+1+2','+0-1'}, + [10]={'+0+0','+1+0','+1-1','+0+2','+1+2','+0+1','+0-1'}, [03]={'+0+0','+1+0','+1+1','+0-2','+1-2','+0+1'}, - [30]={'+0+0','-1+0','-1-1','+0+2','-1+2','+0-1'}, + [30]={'+0+0','-1+0','-1-1','+0+2','-1+2','+0+1','+0-1'}, [12]={'+0+0','+1+0','+1-1','+0-1','-1-1','+0+2','+1+2','+1+1'}, - [21]={'+0+0','-1+0','+0-2','-1-2','-1-1','+1+1'}, + [21]={'+0+0','-1+0','+0-2','-1-2','-1-1','+0-1','+1+1'}, [32]={'+0+0','-1+0','-1-1','+0-1','+1-1','+0+2','-1+2','-1+1'}, - [23]={'+0+0','+1+0','+0-2','+1-2','+1-1','-1+1'}, + [23]={'+0+0','+1+0','+0-2','+1-2','+1-1','+0-1','-1+1'}, [02]={'+0+0','-1+0','+1+0','+0+1'}, [20]={'+0+0','+1+0','-1+0','+0-1'}, [13]={'+0+0','+0-1','+0+1','+1+0','+0-2','+0+2'}, [31]={'+0+0','+0-1','+0+1','-1+0','+0-2','+0+2'}, - },--T + },-- T function(P,d) if P.gameEnv.easyFresh then P:freshBlock('fresh') @@ -175,7 +175,7 @@ do if P.gameEnv.ospin then local x,y=P.curX,P.curY local C=P.cur - if y==P.ghoY and((P:solid(x-1,y)or P:solid(x-1,y+1)))and(P:solid(x+2,y)or P:solid(x+2,y+1))then + if y==P.ghoY and ((P:solid(x-1,y) or P:solid(x-1,y+1))) and (P:solid(x+2,y) or P:solid(x+2,y+1)) then if P.sound then SFX.play('rotatekick',nil,P:getCenterX()*.15) end @@ -186,15 +186,15 @@ do return end for i=1,#OspinList do local L=OspinList[i] - if C.spinSeq==L[1]then + if C.spinSeq==L[1] then local id,dir=L[2],L[3] local bk=BLOCKS[id][dir] x,y=P.curX+L[4],P.curY+L[5] if - not P:ifoverlap(bk,x,y)and( - L[6]>0 or(P:ifoverlap(bk,x-1,y)and P:ifoverlap(bk,x+1,y)) - )and( - L[6]==2 or(P:ifoverlap(bk,x,y-1)and P:ifoverlap(bk,x,y+1)) + not P:ifoverlap(bk,x,y) and ( + L[6]>0 or (P:ifoverlap(bk,x-1,y) and P:ifoverlap(bk,x+1,y)) + ) and ( + L[6]==2 or (P:ifoverlap(bk,x,y-1) and P:ifoverlap(bk,x,y+1)) ) then C.id=id @@ -220,7 +220,7 @@ do SFX.play('rotate',nil,P:getCenterX()*.15) end end - end,--O + end,-- O { [01]={'+0+0','+0+1','+1+0','-2+0','-2-1','+1+2'}, [10]={'+0+0','+2+0','-1+0','-1-2','+2+1','+0+1'}, @@ -234,14 +234,14 @@ do [20]={'+0+0','+1+0','-1+0','+0+1','+0-1'}, [13]={'+0+0','+0-1','-1+0','+1+0','+0+1'}, [31]={'+0+0','+0-1','+1+0','-1+0','+0+1'}, - },--I + },-- I { [01]={'+0+0','+0+1','+1+1','-1+0','+0-3','+0+2','+0-2','+0+3','-1+2'}, [10]={'+0+0','+0-1','-1-1','+1+0','+0-3','+0+2','+0-2','+0+3','+1-2'}, [03]={'+0+0','+1+0','+0-3','+0-1','+0+1','+0-2','+0+2','+0+3','+1+2'}, [30]={'+0+0','-1+0','+0-1','+0+1','+0-2','+0-3','+0+2','+0+3','-1-2'}, - },--Z5 - false,--S5 + },-- Z5 + false,-- S5 { [01]={'+0+0','-1+0','-1+1','+0-2','-1-2','-1-1','+0+1'}, [10]={'+0+0','+1+0','+1-1','+0+2','+1+2','+0-1','+1+1'}, @@ -255,8 +255,8 @@ do [20]={'+0+0','+1+0','+0+1','+0-1'}, [13]={'+0+0','+1+0','+0+1','-1+0'}, [31]={'+0+0','-1+0','+0-1','+1+0'}, - },--P - false,--Q + },-- P + false,-- Q { [01]={'+0+0','-1+0','+1+0','-1+1','+0-2','+0-3'}, [10]={'+0+0','+1+0','+1-1','-1+0','+0+2','+0+3'}, @@ -270,8 +270,8 @@ do [20]={'+0+0','-1+0','+1+0','+1+1'}, [13]={'+0+0','+0-1','-1+1','+0+1'}, [31]={'+0+0','+0-1','+1-1','+0+1'}, - },--F - false,--E + },-- F + false,-- E { [01]={'+0+0','+0-1','-1-1','+1+0','+1+1','+0-3','-1+0','+0+2','-1+2'}, [10]={'+0+0','+1+0','+0-1','-1-1','+0-2','-1+1','+0-3','+1-2','+0+1'}, @@ -285,7 +285,7 @@ do [20]={'+0+0','+0-1','+0+1','+0-2'}, [13]={'+0+0','+1+0','-1+1','-2+0'}, [31]={'+0+0','-1+0','+1+1','+2+0'}, - },--T5 + },-- T5 { [01]={'+0+0','-1+0','-1+1','+0-2','-1-2'}, [10]={'+0+0','+1+0','+1-1','+0+2','+1+2'}, @@ -299,21 +299,21 @@ do [20]={'+0+0','+0-1'}, [13]={'+0+0','+0-1','+0+1','+1+0'}, [31]={'+0+0','+0-1','+0+1','-1+0'}, - },--U + },-- U { [01]={'+0+0','+0+1','-1+0','+0-2','-1-2'}, [10]={'+0+0','+0+1','+1+0','+0-2','+1-2'}, [03]={'+0+0','+0-1','+0+1','+0+2'}, [30]={'+0+0','+0-1','+0+1','+0-2'}, [12]={'+0+0','+0-1','+0+1','+0+2'}, - [21]={'+0+0','+0-1','+0-2','+0-2'}, + [21]={'+0+0','+0-1','+0+1','+0-2'}, [32]={'+0+0','+1+0','-1+0'}, [23]={'+0+0','-1+0','+1+0'}, [02]={'+0+0','-1+1','+1-1'}, [20]={'+0+0','+1-1','-1+1'}, [13]={'+0+0','+1+1','-1-1'}, [31]={'+0+0','-1-1','+1+1'}, - },--V + },-- V { [01]={'+0+0','+0-1','-1+0','+1+0','+1-1','+0+2'}, [10]={'+0+0','+0-1','-1-1','+0+1','+0-2','+1-2','+0+2'}, @@ -327,15 +327,15 @@ do [20]={'+0+0','+0+1','+1+0'}, [13]={'+0+0','+0+1','-1+0'}, [31]={'+0+0','+0-1','+1+0'}, - },--W + },-- W function(P,d) - if P.type=='human'then + if P.type=='human' then SFX.play('rotate',nil,P:getCenterX()*.15) end local kickData=XspinList[d] for test=1,#kickData do local x,y=P.curX+kickData[test][1],P.curY+kickData[test][2] - if not P:ifoverlap(P.cur.bk,x,y)then + if not P:ifoverlap(P.cur.bk,x,y) then P.curX,P.curY=x,y P.spinLast=1 P:freshBlock('move') @@ -344,7 +344,7 @@ do end end P:freshBlock('fresh') - end,--X + end,-- X { [01]={'+0+0','-1+0','-1+1','+0-3','-1+1','-1+2','+0+1'}, [10]={'+0+0','-1+0','+1-1','+0+3','+1-1','+1-2','+0+1'}, @@ -358,8 +358,8 @@ do [20]={'+0+0','+0+1','+1+1','-1+1','+1+0','-2+1'}, [13]={'+0+0','-1+0','-1-1','+0+1','-1-2'}, [31]={'+0+0','+1+0','+1+1','+0-1','+1+2'}, - },--J5 - false,--L5 + },-- J5 + false,-- L5 { [01]={'+0+0','-1+0','-1+1','+1+0','-1+2','-1-1','+0-3','+0+1'}, [10]={'+0+0','-1+0','+1+0','+1-1','+1-2','+1+1','+0+3','+0+1'}, @@ -373,8 +373,8 @@ do [20]={'+0+0','+0+1','-1+1','+1+0','-2+1','+0-1'}, [13]={'+0+0','-1+0','-1-1','+0+1','-1-2'}, [31]={'+0+0','+1+0','+1+1','+0-1','+1+2'}, - },--R - false,--Y + },-- R + false,-- Y { [01]={'+0+0','-1+0','-1+1','+0+1','+1+0','+1+1','-1+2','-2+0','+0-2'}, [10]={'+0+0','+1+0','-1+0','+0-1','-1-1','+1-1','+1-2','+2+0','+0+2'}, @@ -388,20 +388,20 @@ do [20]={'+0+0','+1+0','+0-2','+0+1'}, [13]={'+0+0','-1+0','-1-1','+0+1','+1+2'}, [31]={'+0+0','+1+0','+1+1','+0-1','-1-2'}, - },--N - false,--H + },-- N + false,-- H { [01]={'+0+0','+1-1','+1+0','+1+1','+0+1','-1+1','-1+0','-1-1','+0-1','+0-2','-2-1','-2-2','+2+0','+2-1','+2-2','+1+2','+2+2','-1+2','-2+2'}, [10]={'+0+0','-1+0','-1-1','+0-1','+1-1','-2-2','-2-1','-2+0','-1-2','+0-2','+1-2','+2-2','-1+1','-2+1','-2+2','+1+0','+2+0','+2-1','+0+1','+1-1','+2-2'}, - [03]={'+0+0','-1-1','-1+0','-1+1','-0+1','+1+1','+1+0','+1-1','-0-1','-0-2','+2-1','+2-2','-2+0','-2-1','-2-2','-1+2','-2+2','+1+2','+2+2'}, - [30]={'+0+0','+1+0','+1-1','-0-1','-1-1','+2-2','+2-1','+2+0','+1-2','-0-2','-1-2','-2-2','+1+1','+2+1','+2+2','-1+0','-2+0','-2-1','+0+1','-1-1','-2-2'}, - },--I5 + [03]={'+0+0','-1-1','-1+0','-1+1','+0+1','+1+1','+1+0','+1-1','+0-1','+0-2','+2-1','+2-2','-2+0','-2-1','-2-2','-1+2','-2+2','+1+2','+2+2'}, + [30]={'+0+0','+1+0','+1-1','+0-1','-1-1','+2-2','+2-1','+2+0','+1-2','+0-2','-1-2','-2-2','+1+1','+2+1','+2+2','-1+0','-2+0','-2-1','+0+1','-1-1','-2-2'}, + },-- I5 { [01]={'+0+0','-1+0','-1-1','+1+1','-1+1'}, [10]={'+0+0','-1+0','+1+0','-1-1','+1+1'}, [03]={'+0+0','+1+0','+1-1','-1+1','+1+1'}, [30]={'+0+0','+1+0','-1+0','+1-1','-1+1'}, - },--I3 + },-- I3 { [01]={'+0+0','-1+0','+1+0'}, [10]={'+0+0','+1+0','-1+0'}, @@ -415,7 +415,7 @@ do [20]={'+0+0','+0+1','-1+1','+1+1'}, [13]={'+0+0','+0-1','-1-1','+1-1'}, [31]={'+0+0','+0+1','+1+1','-1+1'}, - },--C + },-- C { [01]={'+0+0','-1+0','+0+1'}, [10]={'+0+0','+1+0','+0+1'}, @@ -429,22 +429,22 @@ do [20]={'+0+0','+0+1','+0-1'}, [13]={'+0+0','-1+0','+1+0'}, [31]={'+0+0','+1+0','-1+0'}, - },--I2 - nil,--O1 + },-- I2 + nil,-- O1 } } TRS.centerDisp[6]=false TRS.centerDisp[18]=false - TRS.kickTable[2]= _reflect(TRS.kickTable[1])--SZ - TRS.kickTable[4]= _reflect(TRS.kickTable[3])--LJ - TRS.kickTable[9]= _reflect(TRS.kickTable[8])--S5Z5 - TRS.kickTable[11]=_reflect(TRS.kickTable[10])--PQ - TRS.kickTable[13]=_reflect(TRS.kickTable[12])--FE - TRS.kickTable[20]=_reflect(TRS.kickTable[19])--L5J5 - TRS.kickTable[22]=_reflect(TRS.kickTable[21])--RY - TRS.kickTable[24]=_reflect(TRS.kickTable[23])--NH - _centroSymSet(TRS.kickTable[8])_centroSymSet(TRS.kickTable[9])--S5Z5 - _centroSymSet(TRS.kickTable[25])_centroSymSet(TRS.kickTable[26])--I5I3 + TRS.kickTable[2]= _reflect(TRS.kickTable[1])-- SZ + TRS.kickTable[4]= _reflect(TRS.kickTable[3])-- LJ + TRS.kickTable[9]= _reflect(TRS.kickTable[8])-- S5Z5 + TRS.kickTable[11]=_reflect(TRS.kickTable[10])-- PQ + TRS.kickTable[13]=_reflect(TRS.kickTable[12])-- FE + TRS.kickTable[20]=_reflect(TRS.kickTable[19])-- L5J5 + TRS.kickTable[22]=_reflect(TRS.kickTable[21])-- RY + TRS.kickTable[24]=_reflect(TRS.kickTable[23])-- NH + _centroSymSet(TRS.kickTable[8])_centroSymSet(TRS.kickTable[9])-- S5Z5 + _centroSymSet(TRS.kickTable[25])_centroSymSet(TRS.kickTable[26])-- I5I3 end local SRS @@ -469,12 +469,12 @@ do [32]={'+0+0','-1+0','-1-1','+0+2','-1+2'}, [23]={'+0+0','+1+0','+1+1','+0-2','+1-2'}, [02]={'+0+0'},[20]={'+0+0'},[13]={'+0+0'},[31]={'+0+0'}, - },--Z - false,--S - false,--J - false,--L - false,--T - noKickSet,--O + },-- Z + false,-- S + false,-- J + false,-- L + false,-- T + noKickSet,-- O { [01]={'+0+0','-2+0','+1+0','-2-1','+1+2'}, [10]={'+0+0','+2+0','-1+0','+2+1','-1-2'}, @@ -485,11 +485,11 @@ do [30]={'+0+0','+1+0','-2+0','+1-2','-2+1'}, [03]={'+0+0','-1+0','+2+0','-1+2','+2-1'}, [02]={'+0+0'},[20]={'+0+0'},[13]={'+0+0'},[31]={'+0+0'}, - }--I + }-- I } } - for i=2,5 do SRS.kickTable[i]=SRS.kickTable[1]end - for i=8,29 do SRS.kickTable[i]=SRS.kickTable[1]end + for i=2,5 do SRS.kickTable[i]=SRS.kickTable[1] end + for i=8,29 do SRS.kickTable[i]=SRS.kickTable[1] end end local SRS_plus @@ -519,30 +519,30 @@ do [20]={'+0+0','+1+0','-1+0','+0-1','+0+1'}, [13]={'+0+0','+0-1','-1+0','+1+0','+0+1'}, [31]={'+0+0','+0-1','-1+0','+1+0','+0+1'}, - },--Z - false,--S - false,--J - false,--L - false,--T - noKickSet,--O + },-- Z + false,-- S + false,-- J + false,-- L + false,-- T + noKickSet,-- O { - [01]={'+0+0','-2+0','+1+0','-2-1','+1+2'}, - [10]={'+0+0','+2+0','-1+0','+2+1','-1-2'}, + [01]={'+0+0','+1+0','-2+0','+1+2','-2-1'}, + [10]={'+0+0','-1+0','+2+0','-1-2','+2+1'}, + [03]={'+0+0','-1+0','+2+0','-1+2','+2-1'}, + [30]={'+0+0','+1+0','-2+0','+1-2','-2+1'}, [12]={'+0+0','-1+0','+2+0','-1+2','+2-1'}, [21]={'+0+0','+1+0','-2+0','+1-2','-2+1'}, - [23]={'+0+0','+2+0','-1+0','+2+1','-1-2'}, - [32]={'+0+0','-2+0','+1+0','-2-1','+1+2'}, - [30]={'+0+0','+1+0','-2+0','+1-2','-2+1'}, - [03]={'+0+0','-1+0','+2+0','-1+2','+2-1'}, + [32]={'+0+0','+1+0','-2+0','+1+2','-2-1'}, + [23]={'+0+0','-1+0','+2+0','-1-2','+2+1'}, [02]={'+0+0','-1+0','+1+0','+0-1','+0+1'}, [20]={'+0+0','+1+0','-1+0','+0+1','+0-1'}, [13]={'+0+0','+0-1','-1+0','+1+0','+0+1'}, [31]={'+0+0','+0-1','+1+0','-1+0','+0+1'}, - }--I + }-- I } } - for i=2,5 do SRS_plus.kickTable[i]=SRS_plus.kickTable[1]end - for i=8,29 do SRS_plus.kickTable[i]=SRS_plus.kickTable[1]end + for i=2,5 do SRS_plus.kickTable[i]=SRS_plus.kickTable[1] end + for i=8,29 do SRS_plus.kickTable[i]=SRS_plus.kickTable[1] end end local SRS_X @@ -570,19 +570,19 @@ do [20]={'+0+0','+1+0','-1+0','+0-1','+0+1'}, [13]={'+0+0','+0-1','-1+0','+1+0','+0+1'}, [31]={'+0+0','+0-1','-1+0','+1+0','+0+1'}, - },--Z - false,--S - false,--J - false,--L - false,--T - noKickSet,--O - false,--I + },-- Z + false,-- S + false,-- J + false,-- L + false,-- T + noKickSet,-- O + false,-- I } } - for i=2,5 do SRS_X.kickTable[i]=SRS_X.kickTable[1]end - for i=7,29 do SRS_X.kickTable[i]=TRS.kickTable[i]end - SRS_X.kickTable[10]=SRS_X.kickTable[1]--P - SRS_X.kickTable[11]=SRS_X.kickTable[1]--Q + for i=2,5 do SRS_X.kickTable[i]=SRS_X.kickTable[1] end + for i=7,29 do SRS_X.kickTable[i]=TRS.kickTable[i] end + SRS_X.kickTable[10]=SRS_X.kickTable[1]-- P + SRS_X.kickTable[11]=SRS_X.kickTable[1]-- Q end local BiRS @@ -591,45 +591,45 @@ do local L=_strToVec{'+0+0','+1+0','+1-1','+0-1','+1+1','-1-1','-1+0','+0+1','-1+1','+0+2','+1+2','-1+2','+2+0','-2+0'} local F=_strToVec{'+0+0','+0-1','+0+1','+0+2'} local list={ - {[02]=L,[20]=R,[13]=R,[31]=L},--Z - {[02]=R,[20]=L,[13]=L,[31]=R},--S - {[02]=L,[20]=R,[13]=L,[31]=R},--J - {[02]=R,[20]=L,[13]=L,[31]=R},--L - {[02]=F,[20]=F,[13]=L,[31]=R},--T - {[02]=F,[20]=F,[13]=F,[31]=F},--O - {[02]=F,[20]=F,[13]=R,[31]=L},--I + {[02]=L,[20]=R,[13]=R,[31]=L},-- Z + {[02]=R,[20]=L,[13]=L,[31]=R},-- S + {[02]=L,[20]=R,[13]=L,[31]=R},-- J + {[02]=R,[20]=L,[13]=L,[31]=R},-- L + {[02]=F,[20]=F,[13]=L,[31]=R},-- T + {[02]=F,[20]=F,[13]=F,[31]=F},-- O + {[02]=F,[20]=F,[13]=R,[31]=L},-- I - {[02]=L,[20]=L,[13]=R,[31]=R},--Z5 - {[02]=R,[20]=R,[13]=L,[31]=L},--S5 - {[02]=L,[20]=R,[13]=L,[31]=R},--P - {[02]=R,[20]=L,[13]=R,[31]=L},--Q - {[02]=R,[20]=L,[13]=L,[31]=R},--F - {[02]=L,[20]=R,[13]=R,[31]=L},--E - {[02]=F,[20]=F,[13]=L,[31]=R},--T5 - {[02]=F,[20]=F,[13]=L,[31]=R},--U - {[02]=R,[20]=L,[13]=L,[31]=R},--V - {[02]=R,[20]=L,[13]=L,[31]=R},--W - {[02]=F,[20]=F,[13]=F,[31]=F},--X - {[02]=L,[20]=R,[13]=R,[31]=L},--J5 - {[02]=R,[20]=L,[13]=L,[31]=R},--L5 - {[02]=L,[20]=R,[13]=R,[31]=L},--R - {[02]=R,[20]=L,[13]=L,[31]=R},--Y - {[02]=L,[20]=R,[13]=R,[31]=L},--N - {[02]=R,[20]=L,[13]=L,[31]=R},--H - {[02]=F,[20]=F,[13]=F,[31]=F},--I5 + {[02]=L,[20]=L,[13]=R,[31]=R},-- Z5 + {[02]=R,[20]=R,[13]=L,[31]=L},-- S5 + {[02]=L,[20]=R,[13]=L,[31]=R},-- P + {[02]=R,[20]=L,[13]=R,[31]=L},-- Q + {[02]=R,[20]=L,[13]=L,[31]=R},-- F + {[02]=L,[20]=R,[13]=R,[31]=L},-- E + {[02]=F,[20]=F,[13]=L,[31]=R},-- T5 + {[02]=F,[20]=F,[13]=L,[31]=R},-- U + {[02]=R,[20]=L,[13]=L,[31]=R},-- V + {[02]=R,[20]=L,[13]=L,[31]=R},-- W + {[02]=F,[20]=F,[13]=F,[31]=F},-- X + {[02]=L,[20]=R,[13]=R,[31]=L},-- J5 + {[02]=R,[20]=L,[13]=L,[31]=R},-- L5 + {[02]=L,[20]=R,[13]=R,[31]=L},-- R + {[02]=R,[20]=L,[13]=L,[31]=R},-- Y + {[02]=L,[20]=R,[13]=R,[31]=L},-- N + {[02]=R,[20]=L,[13]=L,[31]=R},-- H + {[02]=F,[20]=F,[13]=F,[31]=F},-- I5 - {[02]=F,[20]=F,[13]=F,[31]=F},--I3 - {[02]=R,[20]=L,[13]=L,[31]=R},--C - {[02]=F,[20]=F,[13]=R,[31]=L},--I2 - {[02]=F,[20]=F,[13]=F,[31]=F},--O1 + {[02]=F,[20]=F,[13]=F,[31]=F},-- I3 + {[02]=R,[20]=L,[13]=L,[31]=R},-- C + {[02]=F,[20]=F,[13]=R,[31]=L},-- I2 + {[02]=F,[20]=F,[13]=F,[31]=F},-- O1 } for i=1,29 do local a,b=R,L if i==6 or i==18 then a,b=b,a end - list[i][01]=a;list[i][10]=b;list[i][03]=b;list[i][30]=a - list[i][12]=a;list[i][21]=b;list[i][32]=b;list[i][23]=a + list[i][01]=a; list[i][10]=b; list[i][03]=b; list[i][30]=a + list[i][12]=a; list[i][21]=b; list[i][32]=b; list[i][23]=a end BiRS={ centerTex=GC.DO{10,10, @@ -653,9 +653,9 @@ do end local dx,dy=0,0 do local pressing=P.keyPressing - if pressing[1]and P:ifoverlap(C.bk,P.curX-1,P.curY)then dx=dx-1 end - if pressing[2]and P:ifoverlap(C.bk,P.curX+1,P.curY)then dx=dx+1 end - if pressing[7]and P:ifoverlap(C.bk,P.curX,P.curY-1)then dy= -1 end + if pressing[1] and P:ifoverlap(C.bk,P.curX-1,P.curY) then dx=dx-1 end + if pressing[2] and P:ifoverlap(C.bk,P.curX+1,P.curY) then dx=dx+1 end + if pressing[7] and P:ifoverlap(C.bk,P.curX,P.curY-1) then dy= -1 end end while true do for test=1,#kickList do @@ -666,7 +666,7 @@ do (P.freshTime>0 or fdy<=0) then local x,y=ix+fdx,iy+fdy - if not P:ifoverlap(icb,x,y)then + if not P:ifoverlap(icb,x,y) then if P.gameEnv.moveFX and P.gameEnv.block then P:createMoveFX() end @@ -685,7 +685,7 @@ do local sfx if ifpre then sfx='prerotate' - elseif P:ifoverlap(icb,x,y+1)and P:ifoverlap(icb,x-1,y)and P:ifoverlap(icb,x+1,y)then + elseif P:ifoverlap(icb,x,y+1) and P:ifoverlap(icb,x-1,y) and P:ifoverlap(icb,x+1,y) then sfx='rotatekick' P:_rotateField(d) else @@ -700,7 +700,7 @@ do end end - --Try release left/right, then softdrop, failed to rotate otherwise + -- Try release left/right, then softdrop, failed to rotate otherwise if dx~=0 then dx=0 elseif dy~=0 then @@ -728,24 +728,24 @@ do [02]=upOnly,[20]=upOnly,[13]=upOnly,[31]=upOnly, } local centerPos=TABLE.copy(defaultCenterPos) - centerPos[1]={[0]={1,1},{1,0},{1,1},{1,0}}--Z - centerPos[2]={[0]={1,1},{1,1},{1,1},{1,1}}--S - centerPos[3]={[0]={1,1},{1,0},{1,1},{1,1}}--L - centerPos[4]={[0]={1,1},{1,0},{1,1},{1,1}}--J - centerPos[5]={[0]={1,1},{1,0},{1,1},{1,1}}--T - centerPos[7]={[0]={0,2},{2,0},{0,2},{2,0}}--I - centerPos[10]={[0]={1,1},{1,0},{1,1},{1,0}}--P - centerPos[11]={[0]={1,1},{1,1},{1,1},{1,1}}--Q - centerPos[15]={[0]={1,1},{1,0},{1,1},{1,1}}--U - centerPos[16]={[0]={1,1},{1,1},{1,1},{1,1}}--V - centerPos[19]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--J5 - centerPos[20]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--L5 - centerPos[21]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--R - centerPos[22]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--Y - centerPos[23]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--N - centerPos[24]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--H - centerPos[26]={[0]={0,1},{0,0},{0,1},{0,0}}--I3 - centerPos[28]={[0]={0,1},{0,0},{0,1},{0,0}}--I2 + centerPos[1]={[0]={1,1},{1,0},{1,1},{1,0}}-- Z + centerPos[2]={[0]={1,1},{1,1},{1,1},{1,1}}-- S + centerPos[3]={[0]={1,1},{1,0},{1,1},{1,1}}-- L + centerPos[4]={[0]={1,1},{1,0},{1,1},{1,1}}-- J + centerPos[5]={[0]={1,1},{1,0},{1,1},{1,1}}-- T + centerPos[7]={[0]={0,2},{2,0},{0,2},{2,0}}-- I + centerPos[10]={[0]={1,1},{1,0},{1,1},{1,0}}-- P + centerPos[11]={[0]={1,1},{1,1},{1,1},{1,1}}-- Q + centerPos[15]={[0]={1,1},{1,0},{1,1},{1,1}}-- U + centerPos[16]={[0]={1,1},{1,1},{1,1},{1,1}}-- V + centerPos[19]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- J5 + centerPos[20]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- L5 + centerPos[21]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- R + centerPos[22]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- Y + centerPos[23]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- N + centerPos[24]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- H + centerPos[26]={[0]={0,1},{0,0},{0,1},{0,0}}-- I3 + centerPos[28]={[0]={0,1},{0,0},{0,1},{0,0}}-- I2 ARS_Z={ centerTex=GC.DO{10,10, @@ -765,24 +765,24 @@ end local DRS_weak do local centerPos=TABLE.copy(defaultCenterPos) - centerPos[1]={[0]={1,1},{1,0},{1,1},{1,1}}--Z - centerPos[2]={[0]={1,1},{1,0},{1,1},{1,1}}--S - centerPos[3]={[0]={1,1},{1,0},{1,1},{1,1}}--L - centerPos[4]={[0]={1,1},{1,0},{1,1},{1,1}}--J - centerPos[5]={[0]={1,1},{1,0},{1,1},{1,1}}--T - centerPos[7]={[0]={.5,1.5},{1.5,-.5},{.5,1.5},{1.5,.5}}--I - centerPos[10]={[0]={1,1},{1,0},{1,1},{1,0}}--P - centerPos[11]={[0]={1,1},{1,1},{1,1},{1,1}}--Q - centerPos[15]={[0]={1,1},{1,0},{1,1},{1,1}}--U - centerPos[16]={[0]={1,1},{1,1},{1,1},{1,1}}--V - centerPos[19]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--J5 - centerPos[20]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--L5 - centerPos[21]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--R - centerPos[22]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--Y - centerPos[23]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--N - centerPos[24]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}--H - centerPos[26]={[0]={0,1},{0,0},{0,1},{0,0}}--I3 - centerPos[28]={[0]={0,1},{0,0},{0,1},{0,0}}--I2 + centerPos[1]={[0]={1,1},{1,0},{1,1},{1,1}}-- Z + centerPos[2]={[0]={1,1},{1,0},{1,1},{1,1}}-- S + centerPos[3]={[0]={1,1},{1,0},{1,1},{1,1}}-- L + centerPos[4]={[0]={1,1},{1,0},{1,1},{1,1}}-- J + centerPos[5]={[0]={1,1},{1,0},{1,1},{1,1}}-- T + centerPos[7]={[0]={.5,1.5},{1.5,-.5},{.5,1.5},{1.5,.5}}-- I + centerPos[10]={[0]={1,1},{1,0},{1,1},{1,0}}-- P + centerPos[11]={[0]={1,1},{1,1},{1,1},{1,1}}-- Q + centerPos[15]={[0]={1,1},{1,0},{1,1},{1,1}}-- U + centerPos[16]={[0]={1,1},{1,1},{1,1},{1,1}}-- V + centerPos[19]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- J5 + centerPos[20]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- L5 + centerPos[21]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- R + centerPos[22]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- Y + centerPos[23]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- N + centerPos[24]={[0]={1.5,1.5},{1.5,0.5},{1.5,1.5},{1.5,0.5}}-- H + centerPos[26]={[0]={0,1},{0,0},{0,1},{0,0}}-- I3 + centerPos[28]={[0]={0,1},{0,0},{0,1},{0,0}}-- I2 local L={'+0+0','-1+0','+1+0','+0-1','-1-1','+1-1'} local R={'+0+0','+1+0','-1+0','+0-1','+1-1','-1-1'} @@ -802,24 +802,24 @@ do }, centerPos=centerPos, kickTable={ - Z,S,--Z,S - Z,S,--J,L - Z,--T - noKickSet,--O - Z,--I + Z,S,-- Z,S + Z,S,-- J,L + Z,-- T + noKickSet,-- O + Z,-- I - Z,S,--Z5,S5 - Z,S,--P,Q - Z,S,--F,E - Z,Z,Z,Z,--T5,U,V,W - noKickSet,--X - Z,S,--J5,L5 - Z,S,--R,Y - Z,S,--N,H - Z,--I5 + Z,S,-- Z5,S5 + Z,S,-- P,Q + Z,S,-- F,E + Z,Z,Z,Z,-- T5,U,V,W + noKickSet,-- X + Z,S,-- J5,L5 + Z,S,-- R,Y + Z,S,-- N,H + Z,-- I5 - Z,Z,--I3,C - Z,Z,--I2,O1 + Z,Z,-- I3,C + Z,Z,-- I2,O1 } } end @@ -830,8 +830,19 @@ do local R=_flipList(L) local F={'+0+0'} local centerPos=TABLE.copy(defaultCenterPos) - centerPos[6]={[0]={0,0},{1,0},{1,1},{0,1}} - centerPos[7]={[0]={0,1},{2,0},{0,2},{1,0}} + centerPos[6]={[0]={0,0},{1,0},{1,1},{0,1}}-- O + centerPos[7]={[0]={0,1},{2,0},{0,2},{1,0}}-- I + centerPos[14]={[0]={0,1},{1,0},{2,1},{1,2}}-- T5 + centerPos[16]={[0]={1,1},{1,1},{1,1},{1,1}}-- V + centerPos[19]={[0]={0,1},{2,0},{1,2},{1,1}}-- J5 + centerPos[20]={[0]={0,2},{1,0},{1,1},{2,1}}-- L5 + centerPos[21]={[0]={0,2},{1,0},{1,1},{2,1}}-- R + centerPos[22]={[0]={0,1},{2,0},{1,2},{1,1}}-- Y + centerPos[23]={[0]={0,1},{2,0},{1,2},{1,1}}-- N + centerPos[24]={[0]={0,2},{1,0},{1,1},{2,1}}-- H + centerPos[27]={[0]={0,1},{0,0},{1,0},{1,1}}-- C + centerPos[28]={[0]={0,1},{0,0},{0,0},{1,0}}-- I2 + ASC={ centerTex=GC.DO{10,10, {'setLW',2}, @@ -857,7 +868,7 @@ do local L={'+0+0','+1+0','+0-1','+1-1','+0-2','+1-2','+2+0','+2-1','+2-2','-1+0','-1-1','+0+1','+1+1','+2+1','-1-2','-2+0','+0+2','+1+2','+2+2','-2-1','-2-2'} local R=_flipList(L) local F={'+0+0','-1+0','+1+0','+0-1','-1-1','+1-1','+0-2','-1-2','+1-2','-2+0','+2+0','-2-1','+2-1','-2+1','+2+1','+0+2','-1+2','+1+2'} - local centerPos=TABLE.copy(defaultCenterPos) + local centerPos=TABLE.copy(ASC.centerPos) centerPos[6]={[0]={0,0},{1,0},{1,1},{0,1}} centerPos[7]={[0]={0,1},{2,0},{0,2},{1,0}} ASC_plus={ @@ -916,28 +927,62 @@ do {'fRect',3,3,4,4}, }, kickTable={ - Z,S,--Z,S - Z,S,--J,L - Z,--T - noKickSet,--O - Z,--I + Z,S,-- Z,S + Z,S,-- J,L + Z,-- T + noKickSet,-- O + Z,-- I - Z,S,--Z5,S5 - Z,S,--P,Q - Z,S,--F,E - Z,Z,Z,Z,--T5,U,V,W - noKickSet,--X - Z,S,--J5,L5 - Z,S,--R,Y - Z,S,--N,H - Z,--I5 + Z,S,-- Z5,S5 + Z,S,-- P,Q + Z,S,-- F,E + Z,Z,Z,Z,-- T5,U,V,W + noKickSet,-- X + Z,S,-- J5,L5 + Z,S,-- R,Y + Z,S,-- N,H + Z,-- I5 - Z,Z,--I3,C - Z,Z,--I2,O1 + Z,Z,-- I3,C + Z,Z,-- I2,O1 } } end +local N64 +do + local R={'+0+0','+0-1','+1+0','-1+0','+0+1'} + local L={'+0+0','+0-1','-1+0','+1+0','+0+1'} + N64={ + centerTex=GC.DO{10,10, + {'setLW',2}, + {'line',2,9,2,1,8,9,8,1}, + }, + kickTable=TABLE.new({ + [01]=R,[10]=L,[12]=R,[21]=L, + [23]=R,[32]=L,[30]=R,[03]=L, + },29) + } +end + +local N64_plus +do + local R={'+0+0','+0-1','+1+0','-1+0','+0+1'} + local L={'+0+0','+0-1','-1+0','+1+0','+0+1'} + local F={'+0+0','+0-1','+0+1'} + N64_plus={ + centerTex=GC.DO{10,10, + {'setLW',2}, + {'line',4,9,2,9,2,1,8,9,8,1,6,1}, + }, + kickTable=TABLE.new({ + [01]=R,[10]=L,[12]=R,[21]=L, + [23]=R,[32]=L,[30]=R,[03]=L, + [02]=F,[20]=F,[13]=F,[31]=F, + },29) + } +end + local Classic do local centerPos=TABLE.copy(defaultCenterPos) centerPos[1]={[0]={1,1},{1,0},{1,1},{1,0}} @@ -978,7 +1023,7 @@ local None={ {'setLW',2}, {'line',2,2,6,6}, }, - kickTable=TABLE.new(noKickSet_180,29) + kickTable=TABLE.new(noKickSet,29) } local None_plus={ @@ -987,7 +1032,7 @@ local None_plus={ {'line',1,1,7,7}, {'fRect',2,2,4,4}, }, - kickTable=TABLE.new(noKickSet,29) + kickTable=TABLE.new(noKickSet_180,29) } local RSlist={ @@ -1002,6 +1047,8 @@ local RSlist={ ASC_plus=ASC_plus, C2=C2, C2_sym=C2_sym, + N64=N64, + N64_plus=N64_plus, Classic=Classic, Classic_plus=Classic_plus, None=None, @@ -1009,15 +1056,15 @@ local RSlist={ } for _,rs in next,RSlist do - if not rs.centerDisp then rs.centerDisp=TABLE.new(true,29)end + if not rs.centerDisp then rs.centerDisp=TABLE.new(true,29) end if not rs.centerPos then rs.centerPos=defaultCenterPos end if not rs.centerTex then rs.centerTex=defaultCenterTex end - --Make all string vec to the same table vec + -- Make all string vec to the same table vec for _,set in next,rs.kickTable do - if type(set)=='table'then + if type(set)=='table' then for _,list in next,set do - if type(list[1])=='string'then + if type(list[1])=='string' then _strToVec(list) end end diff --git a/parts/backgrounds/aura.lua b/parts/backgrounds/aura.lua index 3927c8b29..eaea505a6 100644 --- a/parts/backgrounds/aura.lua +++ b/parts/backgrounds/aura.lua @@ -1,25 +1,19 @@ ---Cool liquid background -local gc=love.graphics +-- Cool liquid background local back={} local shader=SHADER.aura local t function back.init() t=math.random()*2600 - BG.resize(SCR.w,SCR.h) -end -function back.resize(_,h) - shader:send('w',SCR.W) - shader:send('h',h*SCR.dpi) end function back.update(dt) - t=t+dt + t=(t+dt)%6200 end function back.draw() - gc.clear(.08,.08,.084) - shader:send('t',t) - gc.setShader(shader) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - gc.setShader() + GC.clear(.08,.08,.084) + shader:send('phase',t) + GC.setShader(shader) + GC.rectangle('fill',0,0,SCR.w,SCR.h) + GC.setShader() end return back diff --git a/parts/backgrounds/bg1.lua b/parts/backgrounds/bg1.lua index a08ce3039..a5bb9f42c 100644 --- a/parts/backgrounds/bg1.lua +++ b/parts/backgrounds/bg1.lua @@ -1,24 +1,19 @@ ---Horizonal red-blue gradient -local gc=love.graphics +-- Horizonal red-blue gradient local back={} local shader=SHADER.grad1 local t function back.init() t=math.random()*2600 - back.resize() -end -function back.resize() - shader:send('w',SCR.W) end function back.update(dt) - t=t+dt + t=(t+dt)%6200 end function back.draw() - gc.clear(.08,.08,.084) - shader:send('t',t) - gc.setShader(shader) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - gc.setShader() + GC.clear(.08,.08,.084) + shader:send('phase',t) + GC.setShader(shader) + GC.rectangle('fill',0,0,SCR.w,SCR.h) + GC.setShader() end return back diff --git a/parts/backgrounds/bg2.lua b/parts/backgrounds/bg2.lua index 7a2952a12..b7af6541c 100644 --- a/parts/backgrounds/bg2.lua +++ b/parts/backgrounds/bg2.lua @@ -1,24 +1,19 @@ ---Vertical red-green gradient -local gc=love.graphics +-- Vertical red-green gradient local back={} local shader=SHADER.grad2 local t function back.init() t=math.random()*2600 - BG.resize(nil,SCR.h) -end -function back.resize(_,h) - shader:send('h',h*SCR.dpi) end function back.update(dt) - t=t+dt + t=(t+dt)%6200 end function back.draw() - gc.clear(.08,.08,.084) - shader:send('t',t) - gc.setShader(shader) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - gc.setShader() + GC.clear(.08,.08,.084) + shader:send('phase',t) + GC.setShader(shader) + GC.rectangle('fill',0,0,SCR.w,SCR.h) + GC.setShader() end return back diff --git a/parts/backgrounds/blockfall.lua b/parts/backgrounds/blockfall.lua index 4ecb0a74f..bce4c32b1 100644 --- a/parts/backgrounds/blockfall.lua +++ b/parts/backgrounds/blockfall.lua @@ -1,4 +1,4 @@ ---Large falling tetrominoes +-- Large falling tetrominoes local gc=love.graphics local gc_clear=gc.clear local gc_setColor,gc_draw=gc.setColor,gc.draw @@ -43,8 +43,8 @@ function back.draw() local M=mino[i] local b=M.block for y=1,#b do - for x=1,#b[1]do - if b[y][x]then + for x=1,#b[1] do + if b[y][x] then gc_draw(M.texture,M.x+(x-1)*30*M.k,M.y-y*30*M.k,nil,M.k) end end diff --git a/parts/backgrounds/blockhole.lua b/parts/backgrounds/blockhole.lua index 8f14f2ac2..f759b5182 100644 --- a/parts/backgrounds/blockhole.lua +++ b/parts/backgrounds/blockhole.lua @@ -1,4 +1,4 @@ ---blockhole +-- blockhole local gc=love.graphics local gc_clear,gc_replaceTransform=gc.clear,gc.replaceTransform local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth @@ -44,14 +44,14 @@ function back.draw() gc_clear(.1,.1,.1) gc_replaceTransform(SCR.xOy_m) - --Squares + -- Squares gc_setColor(1,1,1,.2) for i=1,#squares do local S=squares[i] gc_draw(S.texture,S.d*cos(S.ang),S.d*sin(S.ang),S.rotate,S.size*.026,nil,15,15) end - --blockhole + -- blockhole gc_setColor(.07,.07,.07) gc_circle('fill',0,0,157) gc_setLineWidth(6) diff --git a/parts/backgrounds/blockrain.lua b/parts/backgrounds/blockrain.lua index c26abcb49..fc2eba5a8 100644 --- a/parts/backgrounds/blockrain.lua +++ b/parts/backgrounds/blockrain.lua @@ -1,4 +1,4 @@ ---Block rain +-- Block rain local gc=love.graphics local rnd=math.random local ins,rem=table.insert,table.remove @@ -20,7 +20,7 @@ function back.update() color=BLOCK_COLORS[SETTING.skin[r]], x=SCR.w*rnd(), y=SCR.h*-.05, - k=SCR.rad/100, + k=SCR.rad/200, ang=rnd()*6.2832, vy=.5+rnd()*.4, vx=rnd()*.4-.2, diff --git a/parts/backgrounds/blockspace.lua b/parts/backgrounds/blockspace.lua index 092ff180e..ff5ce285c 100644 --- a/parts/backgrounds/blockspace.lua +++ b/parts/backgrounds/blockspace.lua @@ -1,4 +1,4 @@ ---Space but tetrominoes +-- Space but tetrominoes local gc=love.graphics local gc_clear,gc_translate=gc.clear,gc.translate local gc_setColor,gc_draw=gc.setColor,gc.draw @@ -47,7 +47,7 @@ function back.draw() local M=mino[i] local c=M.color gc_setColor(c[1],c[2],c[3],.2) - gc_draw(M.block,M.d*cos(M.ang),M.d*sin(M.ang),M.rotate,(18*M.d/SCR.rad)^1.6,nil,M.block:getWidth()/2,M.block:getHeight()/2) + gc_draw(M.block,M.d*cos(M.ang),M.d*sin(M.ang),M.rotate,(12*M.d/SCR.rad)^1.6,nil,M.block:getWidth()/2,M.block:getHeight()/2) end gc_translate(-SCR.cx,-SCR.cy) end diff --git a/parts/backgrounds/cubes.lua b/parts/backgrounds/cubes.lua index 84442a1fb..bbf9724c9 100644 --- a/parts/backgrounds/cubes.lua +++ b/parts/backgrounds/cubes.lua @@ -1,4 +1,4 @@ ---Flying cubes +-- Flying cubes local gc=love.graphics local gc_clear=gc.clear local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth diff --git a/parts/backgrounds/custom.lua b/parts/backgrounds/custom.lua index 0d098cfae..06afbe503 100644 --- a/parts/backgrounds/custom.lua +++ b/parts/backgrounds/custom.lua @@ -1,4 +1,4 @@ ---Secret custom background +-- Custom background local gc_clear,gc_setColor=love.graphics.clear,love.graphics.setColor local back={} diff --git a/parts/backgrounds/fan.lua b/parts/backgrounds/fan.lua index aaa46fc32..2938fe1a5 100644 --- a/parts/backgrounds/fan.lua +++ b/parts/backgrounds/fan.lua @@ -1,4 +1,4 @@ ---Yuyuko's fan +-- Yuyuko's fan local gc=love.graphics local gc_clear,gc_origin,gc_replaceTransform=gc.clear,gc.origin,gc.replaceTransform local gc_translate=gc.translate @@ -61,7 +61,7 @@ function back.draw() gc_setLineWidth(6) gc_setColor(.8,.9,1,.3) - for i=1,#SVG_TITLE_FAN do gc_polygon('line',SVG_TITLE_FAN[i])end + for i=1,#SVG_TITLE_FAN do gc_polygon('line',SVG_TITLE_FAN[i]) end gc_setLineWidth(2) gc_setColor(1,.5,.7,.3) diff --git a/parts/backgrounds/firework.lua b/parts/backgrounds/firework.lua index 33c5ae709..0ba9be889 100644 --- a/parts/backgrounds/firework.lua +++ b/parts/backgrounds/firework.lua @@ -1,4 +1,4 @@ ---Firework +-- Firework local gc=love.graphics local gc_clear=gc.clear local gc_setColor,gc_setLineWidth=gc.setColor,gc.setLineWidth @@ -37,7 +37,7 @@ function back.update(dt) local x,y,color=F.x,F.y,F.color if F.big then SFX.play('fall',.5) - for _=1,rnd(62,126)do + for _=1,rnd(62,126) do ins(particle,{ x=x,y=y, color=color, @@ -48,7 +48,7 @@ function back.update(dt) end else SFX.play('clear_1',.4) - for _=1,rnd(16,26)do + for _=1,rnd(16,26) do ins(particle,{ x=x,y=y, color=color, diff --git a/parts/backgrounds/fixColor.lua b/parts/backgrounds/fixColor.lua new file mode 100644 index 000000000..7bc8b9aaa --- /dev/null +++ b/parts/backgrounds/fixColor.lua @@ -0,0 +1,10 @@ +-- Customizable grey background +local back={} +local r,g,b=.26,.26,.26 +function back.draw() + GC.clear(r,g,b) +end +function back.event(_r,_g,_b) + r,g,b=_r,_g,_b +end +return back diff --git a/parts/backgrounds/flink.lua b/parts/backgrounds/flink.lua index 39b74e663..73112c254 100644 --- a/parts/backgrounds/flink.lua +++ b/parts/backgrounds/flink.lua @@ -1,5 +1,4 @@ ---Flash after random time -local gc=love.graphics +-- Flash after random time local back={} local t @@ -11,8 +10,8 @@ function back.update(dt) end function back.draw() local t1=.13-t%3%1.9 - if t1<.2 then gc.clear(t1,t1,t1) - else gc.clear(0,0,0) + if t1<.2 then GC.clear(t1,t1,t1) + else GC.clear(0,0,0) end end return back diff --git a/parts/backgrounds/galaxy.lua b/parts/backgrounds/galaxy.lua new file mode 100644 index 000000000..bab729197 --- /dev/null +++ b/parts/backgrounds/galaxy.lua @@ -0,0 +1,41 @@ +--Space with stars +local gc=love.graphics +local circle,setColor,hsv=gc.circle,gc.setColor,COLOR.hsv +local sin,cos=math.sin,math.cos +local back={} + +local sDist,sRev={},{} -- star data in SoA [distance from center, revolution progress, color] + +function back.init() + if sDist[1] then return end + local max + for i=0,20 do + max=16*(i+1) + for j=1,max do + sDist[#sDist+1]=i+math.random() + sRev[#sRev+1]=MATH.tau*j/max+MATH.tau*math.random()/max + end + end +end +function back.update(dt) + for i=1,#sDist do + sRev[i]=(sRev[i]+dt/(sDist[i]+1))%MATH.tau + end +end +function back.draw() + gc.clear() + gc.translate(SCR.cx,SCR.cy) + gc.scale(SCR.k) + gc.rotate(1) + for i=1,#sDist do + local d,r=sDist[i],sRev[i] + if d<5 then + setColor(hsv(.088,(d-2)/7,1,.2)) + else + setColor(hsv(.572,d/70+.1,(22-d)/12,.2)) + end + circle('fill',8*d*cos(r),24*d*sin(r),5) + end +end + +return back diff --git a/parts/backgrounds/glow.lua b/parts/backgrounds/glow.lua index 792a5a9b7..42e4a8ad5 100644 --- a/parts/backgrounds/glow.lua +++ b/parts/backgrounds/glow.lua @@ -1,5 +1,4 @@ ---Light-dark -local gc=love.graphics +-- Light-dark local sin=math.sin local back={} @@ -12,6 +11,6 @@ function back.update(dt) end function back.draw() local t1=(sin(t*.5)+sin(t*.7)+sin(t*.9+1)+sin(t*1.5)+sin(t*2+10))*.08 - gc.clear(t1,t1,t1) + GC.clear(t1,t1,t1) end return back diff --git a/parts/backgrounds/gray.lua b/parts/backgrounds/gray.lua deleted file mode 100644 index c9ce3ffb2..000000000 --- a/parts/backgrounds/gray.lua +++ /dev/null @@ -1,11 +0,0 @@ ---Customizable grey background -local gc=love.graphics -local back={} -local brightness=.26 -function back.draw() - gc.clear(brightness,brightness,brightness) -end -function back.event(b) - brightness=b -end -return back diff --git a/parts/backgrounds/lanterns.lua b/parts/backgrounds/lanterns.lua index 63d606812..2a507f1d6 100644 --- a/parts/backgrounds/lanterns.lua +++ b/parts/backgrounds/lanterns.lua @@ -1,5 +1,4 @@ ---A lantern background which is full of festive atmosphere. Lantern image by ScF -local gc=love.graphics +-- A lantern background which is full of festive atmosphere. Lantern image by ScF local int,rnd=math.floor,math.random local ins,rem=table.insert,table.remove local mDraw=mDraw @@ -37,8 +36,8 @@ function back.update(dt) end end function back.draw() - gc.clear(.08,.08,.084) - gc.setColor(1,1,1,.2) + GC.clear(.08,.08,.084) + GC.setColor(1,1,1,.2) local img=IMG.lanterns for i=1,#lanterns do local L=lanterns[i] diff --git a/parts/backgrounds/league.lua b/parts/backgrounds/league.lua index a940207ab..265082338 100644 --- a/parts/backgrounds/league.lua +++ b/parts/backgrounds/league.lua @@ -1,5 +1,4 @@ ---Space with stars -local gc=love.graphics +-- Space with stars local back={} local upCover do @@ -29,8 +28,8 @@ end function back.update() end function back.draw() - gc.clear(.08,.08,.084) - gc.draw(upCover,0,0,0,W,H*.3/64) - gc.draw(downCover,0,H*.7,0,W,H*.3/64) + GC.clear(.08,.08,.084) + GC.draw(upCover,0,0,0,W,H*.3/64) + GC.draw(downCover,0,H*.7,0,W,H*.3/64) end return back diff --git a/parts/backgrounds/lightning.lua b/parts/backgrounds/lightning.lua index 7bac2b457..0ae685844 100644 --- a/parts/backgrounds/lightning.lua +++ b/parts/backgrounds/lightning.lua @@ -1,5 +1,4 @@ ---Lightning -local gc=love.graphics +-- Lightning local back={} local t @@ -11,8 +10,8 @@ function back.update(dt) end function back.draw() local t1=2.5-t%20%6%2.5 - if t1<.3 then gc.clear(t1,t1,t1) - else gc.clear(0,0,0) + if t1<.3 then GC.clear(t1,t1,t1) + else GC.clear(0,0,0) end end return back diff --git a/parts/backgrounds/lightning2.lua b/parts/backgrounds/lightning2.lua index 68aba3c97..1d8fd08b0 100644 --- a/parts/backgrounds/lightning2.lua +++ b/parts/backgrounds/lightning2.lua @@ -1,12 +1,10 @@ ---Fast lightning + spining tetromino -local gc=love.graphics +-- Fast lightning + spining tetromino local int,rnd=math.floor,math.random local back={} local t local colorLib=BLOCK_COLORS local blocks=BLOCKS -local scs=RSlist.TRS.centerPos function back.init() t=rnd()*2600 end @@ -16,11 +14,11 @@ end function back.draw() local R=7-int(t*.5%7) local T=1.2-t%15%6%1.8 - if T<.26 then gc.clear(T,T,T) - else gc.clear(0,0,0) + if T<.26 then GC.clear(T,T,T) + else GC.clear(0,0,0) end local _=colorLib[SETTING.skin[R]] - gc.setColor(_[1],_[2],_[3],.12) - gc.draw(TEXTURE.miniBlock[R],SCR.cx,SCR.cy,t%3.1416*6,400*SCR.k,nil,scs[R][0][2]+.5,#blocks[R][0]-scs[R][0][1]-.5) + GC.setColor(_[1],_[2],_[3],.12) + GC.draw(TEXTURE.miniBlock[R],SCR.cx,SCR.cy,t%3.1416*6,200*SCR.k,nil,2*DSCP[R][0][2]+1,2*(#blocks[R][0]-DSCP[R][0][1])-1) end return back diff --git a/parts/backgrounds/matrix.lua b/parts/backgrounds/matrix.lua index d487d801c..e1d413d47 100644 --- a/parts/backgrounds/matrix.lua +++ b/parts/backgrounds/matrix.lua @@ -1,4 +1,4 @@ ---Black-White grid +-- Black-White grid local gc=love.graphics local gc_clear,gc_scale=gc.clear,gc.scale local gc_setColor=gc.setColor @@ -9,7 +9,7 @@ local ceil=math.ceil local back={} local t -local matrixT={}for i=1,50 do matrixT[i]={}for j=1,50 do matrixT[i][j]=love.math.noise(i,j)+2 end end +local matrixT={} for i=1,50 do matrixT[i]={} for j=1,50 do matrixT[i][j]=love.math.noise(i,j)+2 end end function back.init() t=math.random()*2600 end @@ -21,7 +21,7 @@ function back.draw() local k=SCR.k gc_scale(k) local Y=ceil(SCR.h/80/k) - for x=1,ceil(SCR.w/80/k)do + for x=1,ceil(SCR.w/80/k) do for y=1,Y do gc_setColor(1,1,1,sin(x+matrixT[x][y]*t)*.04+.04) gc_rectangle('fill',80*x,80*y,-80,-80) diff --git a/parts/backgrounds/quarks.lua b/parts/backgrounds/quarks.lua new file mode 100644 index 000000000..2159d6779 --- /dev/null +++ b/parts/backgrounds/quarks.lua @@ -0,0 +1,145 @@ +local gc=love.graphics +local hsv=COLOR.hsv +local circle,push,pop,rot,translate,setColor=gc.circle,gc.push,gc.pop,gc.rotate,gc.translate,gc.setColor +local rnd,sin,cos,log=math.random,math.sin,math.cos,math.log +local back={} + +local qX,qY,qdX,qdY={},{},{},{} -- quark data in SoA [size, X, Y, dx, dy, color] + +local ptcclr={{1,0,0,.5},{0,1,0,.5},{0,0,1,.5}} +local apcclr={{0,1,1,.5},{1,0,1,.5},{1,1,0,.5}} + +local blasts={} -- data about annihilation blasts from particles and antiparticles colliding +local ptc={} -- particle-antiparticle data (antiparticle is a mirror of particle) +local nextpair + +local W,H,size +local quarkCount=400 + +local function spawnQuarkRandom(i) + qX[i]=rnd(W)-10 -- X + qY[i]=rnd(H)-10 -- Y + local theta=rnd()*MATH.tau + qdX[i]=cos(theta)*300 -- dx + qdY[i]=sin(theta)*300 -- dy +end +local function spawnQuarkEdge(i) + local side=rnd(4) + if side==1 then -- Up edge of screen + qX[i]=rnd(SCR.x-10,SCR.ex+10) + qY[i]=SCR.y-10 + elseif side==2 then -- Right edge of screen + qX[i]=SCR.ex+10 + qY[i]=rnd(SCR.y-10,SCR.ey+10) + elseif side==3 then -- Down edge of screen + qX[i]=rnd(SCR.x-10,SCR.ex+10) + qY[i]=SCR.ey+10 + elseif side==4 then -- Left edge of screen + qX[i]=SCR.x-10 + qY[i]=rnd(SCR.y-10,SCR.ey+10) + end + local theta=rnd()*MATH.tau + qdX[i]=cos(theta)*300 -- dx + qdY[i]=sin(theta)*300 -- dy +end +local function spawnParticlePair() + ptc[#ptc+1]={ + x=rnd(W)-10, + y=rnd(H)-10, + dist=0, + theta=rnd()*MATH.tau, + v=500, + c=rnd(3), + } +end +local function spawnBlast(_x,_y) + blasts[#blasts+1]={x=_x,y=_y,t=0} +end + +function back.init() + qX,qY,qdX,qdY={},{},{},{} + blasts={} + ptc={} + nextpair=0 + BG.resize(SCR.w,SCR.h) +end +function back.resize(w,h) + W,H=w+20,h+20 + for i=1,quarkCount do spawnQuarkRandom(i) end + size=2.6*SCR.k +end +function back.update(dt) + -- Move far-away quarks + for i=1,quarkCount do + qX[i]=qX[i]+qdX[i]*dt + qY[i]=qY[i]+qdY[i]*dt + if qX[i]SCR.ex+26 or qY[i]SCR.ey+26 then + spawnQuarkEdge(i) + end + end + + -- Particle pair attraction & destruction + for i=#ptc,1,-1 do + local p=ptc[i] + if p then + p.dist=p.dist+p.v*dt + p.v=p.v-p.dist^2*dt + + -- Destroy colliding particle pairs + if p.dist<=10 and p.v<=0 then + spawnBlast(p.x,p.y) + table.remove(ptc,i) + end + end + end + + -- Age blasts, delete old blasts + for i=#blasts,1,-1 do + if blasts[i] then + blasts[i].t=blasts[i].t+dt + if blasts[i].t>=1 then + table.remove(blasts,i) + end + end + end + + -- Spawn particle pairs + nextpair=nextpair-dt + if nextpair<=0 then + spawnParticlePair() + nextpair=rnd()*4 + end +end +function back.draw() + gc.clear(.08,.04,.01) + translate(-10,-10) + + -- Draw quarks in R/G/B + setColor(1,0,0,.5) for i=1, math.floor(quarkCount/3) do circle('fill',qX[i],qY[i],size) end + setColor(0,1,0,.5) for i=math.floor(quarkCount/3)+1, math.floor(quarkCount*2/3) do circle('fill',qX[i],qY[i],size) end + setColor(0,0,1,.5) for i=math.floor(quarkCount*2/3)+1,quarkCount do circle('fill',qX[i],qY[i],size) end + + for i=1,#ptc do + local p=ptc[i] + push() + translate(p.x,p.y) + rot(p.theta) + + setColor(ptcclr[p.c]) + circle('fill', p.dist,0,4*size) + setColor(apcclr[p.c]) + circle('fill',-p.dist,0,4*size) + pop() + end + for i=1,#blasts do + local t=blasts[i].t + setColor(hsv(-80*t,1-1.7*log(5*t,10),1,1-t)) + circle('fill',blasts[i].x,blasts[i].y,62*t^.3) + end +end +function back.discard() + qX,qY,qdX,qdY,qC=nil + ptc,blasts=nil + collectgarbage() +end +return back diff --git a/parts/backgrounds/rainbow.lua b/parts/backgrounds/rainbow.lua index b0a5d4fc6..ab82699f6 100644 --- a/parts/backgrounds/rainbow.lua +++ b/parts/backgrounds/rainbow.lua @@ -1,25 +1,19 @@ ---Colorful RGB -local gc=love.graphics +-- Colorful RGB local back={} local shader=SHADER.rgb1 local t function back.init() t=math.random()*2600 - BG.resize(SCR.w,SCR.h) -end -function back.resize(_,h) - shader:send('w',SCR.W) - shader:send('h',h*SCR.dpi) end function back.update(dt) - t=t+dt + t=(t+dt)%6200 end function back.draw() - gc.clear(.08,.08,.084) - shader:send('t',t) - gc.setShader(shader) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - gc.setShader() + GC.clear(.08,.08,.084) + shader:send('phase',t) + GC.setShader(shader) + GC.rectangle('fill',0,0,SCR.w,SCR.h) + GC.setShader() end return back diff --git a/parts/backgrounds/rainbow2.lua b/parts/backgrounds/rainbow2.lua index ef8d56454..6fae525d1 100644 --- a/parts/backgrounds/rainbow2.lua +++ b/parts/backgrounds/rainbow2.lua @@ -1,25 +1,19 @@ ---Blue RGB -local gc=love.graphics +-- Blue RGB local back={} local shader=SHADER.rgb2 local t function back.init() t=math.random()*2600 - BG.resize(SCR.w,SCR.h) -end -function back.resize(_,h) - shader:send('w',SCR.W) - shader:send('h',h*SCR.dpi) end function back.update(dt) - t=t+dt + t=(t+dt)%6200 end function back.draw() - gc.clear(.08,.08,.084) - shader:send('t',t) - gc.setShader(shader) - gc.rectangle('fill',0,0,SCR.w,SCR.h) - gc.setShader() + GC.clear(.08,.08,.084) + shader:send('phase',t) + GC.setShader(shader) + GC.rectangle('fill',0,0,SCR.w,SCR.h) + GC.setShader() end return back diff --git a/parts/backgrounds/rgb.lua b/parts/backgrounds/rgb.lua index 1983464c0..2951e46c4 100644 --- a/parts/backgrounds/rgb.lua +++ b/parts/backgrounds/rgb.lua @@ -1,5 +1,4 @@ ---Changing pure color -local gc=love.graphics +-- Changing pure color local sin=math.sin local back={} @@ -11,7 +10,7 @@ function back.update(dt) t=t+dt end function back.draw() - gc.clear( + GC.clear( sin(t*1.2)*.06+.08, sin(t*1.5)*.06+.08, sin(t*1.9)*.06+.08 diff --git a/parts/backgrounds/snow.lua b/parts/backgrounds/snow.lua index d3a658037..d377a9262 100644 --- a/parts/backgrounds/snow.lua +++ b/parts/backgrounds/snow.lua @@ -1,4 +1,4 @@ ---Snow +-- Snow local gc=love.graphics local ellipse=gc.ellipse local rnd=math.random diff --git a/parts/backgrounds/space.lua b/parts/backgrounds/space.lua index 48be71ad8..4d2f32fe8 100644 --- a/parts/backgrounds/space.lua +++ b/parts/backgrounds/space.lua @@ -1,4 +1,4 @@ ---Space with stars +-- Space with stars local gc=love.graphics local rectangle=gc.rectangle local rnd=math.random @@ -15,16 +15,16 @@ function back.resize(w,h) local S=stars for i=1,1260,5 do local s=rnd(26,40)*.1 - S[i]=s*SCR.k --Size - S[i+1]=rnd(W)-10 --X - S[i+2]=rnd(H)-10 --Y - S[i+3]=(rnd()-.5)*.01*s--Vx - S[i+4]=(rnd()-.5)*.01*s--Vy + S[i]=s*SCR.k -- Size + S[i+1]=rnd(W)-10 -- X + S[i+2]=rnd(H)-10 -- Y + S[i+3]=(rnd()-.5)*.01*s-- Vx + S[i+4]=(rnd()-.5)*.01*s-- Vy end end function back.update(dt) local S=stars - --Star moving + -- Star moving for i=1,1260,5 do S[i+1]=(S[i+1]+S[i+3]*dt*60)%W S[i+2]=(S[i+2]+S[i+4]*dt*60)%H @@ -32,7 +32,7 @@ function back.update(dt) end function back.draw() gc.clear(.08,.08,.084) - if not stars[1]then return end + if not stars[1] then return end gc.translate(-10,-10) gc.setColor(1,1,1,.6) for i=1,1260,5 do diff --git a/parts/backgrounds/tunnel.lua b/parts/backgrounds/tunnel.lua index 103de65df..5391a25ae 100644 --- a/parts/backgrounds/tunnel.lua +++ b/parts/backgrounds/tunnel.lua @@ -1,5 +1,4 @@ ---Cool Tunnel -local gc=love.graphics +-- Cool Tunnel local rnd=math.random local ins,rem=table.insert,table.remove local back={} @@ -29,12 +28,12 @@ function back.update(dt) end end function back.draw() - gc.clear(.08,.08,.084) - gc.setColor(1,1,1,.1) + GC.clear(.08,.08,.084) + GC.setColor(1,1,1,.1) for i=1,#ring do local r=ring[i]^2/12 - gc.setLineWidth(30-15/(r+.5)) - gc.rectangle('line',W*.5-W*r/2,H*.5-H*r/2,W*r,H*r) + GC.setLineWidth(30-15/(r+.5)) + GC.rectangle('line',W*.5-W*r/2,H*.5-H*r/2,W*r,H*r) end end function back.discard() diff --git a/parts/backgrounds/welcome.lua b/parts/backgrounds/welcome.lua index 15c030fe9..09a95755c 100644 --- a/parts/backgrounds/welcome.lua +++ b/parts/backgrounds/welcome.lua @@ -1,5 +1,4 @@ ---Welcome to Techmino -local gc=love.graphics +-- Welcome to Techmino local sin=math.sin local back={} @@ -7,33 +6,33 @@ local t local textObj function back.init() t=math.random()*2600 - textObj=gc.newText(getFont(80),"Welcome To Techmino") + textObj=GC.newText(getFont(80),"Welcome To Techmino") end function back.update(dt) t=t+dt end function back.draw() if -t%13.55<.1283 then - gc.clear(.2+.1*sin(t),.2+.1*sin(1.26*t),.2+.1*sin(1.626*t)) + GC.clear(.2+.1*sin(t),.2+.1*sin(1.26*t),.2+.1*sin(1.626*t)) else - gc.clear(.08,.08,.084) + GC.clear(.08,.08,.084) end - gc.push('transform') - gc.translate(SCR.cx,SCR.cy+20*sin(t*.02)) - gc.scale(SCR.k) - gc.scale(1.26,1.36) + GC.push('transform') + GC.replaceTransform(SCR.xOy_m) + GC.translate(0,20*sin(t*.02)) + GC.scale(1.26,1.36) if -t%6.26<.1355 then - gc.translate(60*sin(t*.26),100*sin(t*.626)) + GC.translate(60*sin(t*.26),100*sin(t*.626)) end if -t%12.6<.1626 then - gc.rotate(t+5*sin(.26*t)+5*sin(.626*t)) + GC.rotate(t+5*sin(.26*t)+5*sin(.626*t)) end - gc.setColor(.4,.6,1,.3) + GC.setColor(.4,.6,1,.3) mDraw(textObj,4*sin(t*.7942),4*sin(t*.7355)) - gc.setColor(.5,.7,1,.4) + GC.setColor(.5,.7,1,.4) mDraw(textObj,2*sin(t*.77023),2*sin(t*.7026)) - gc.setColor(1,1,1,.5) + GC.setColor(1,1,1,.5) mDraw(textObj,3*sin(t*.7283),3*sin(t*.7626)) - gc.pop() + GC.pop() end return back diff --git a/parts/backgrounds/wing.lua b/parts/backgrounds/wing.lua index b36ffa7f1..822812fb3 100644 --- a/parts/backgrounds/wing.lua +++ b/parts/backgrounds/wing.lua @@ -1,6 +1,4 @@ ---Flandre's wing -local gc=love.graphics -local rnd=math.random +-- Flandre's wing local back={} local crystal_img,crystals local wingColor={ @@ -46,31 +44,31 @@ function back.update() end end function back.draw() - gc.clear(.06,.06,.06) - gc.setColor(.12,.10,.08) - gc.setLineJoin('bevel') - gc.setLineWidth(14*SCR.k) + GC.clear(.06,.06,.06) + GC.setColor(.12,.10,.08) + GC.setLineJoin('bevel') + GC.setLineWidth(14*SCR.k) local W,H=SCR.w,SCR.h - gc.line(.018*W,.567*H,.101*W,.512*H,.202*W,.369*H,.260*W,.212*H) - gc.line(.247*W,.257*H,.307*W,.383*H,.352*W,.436*H,.401*W,.309*H) - gc.line(.982*W,.567*H,.899*W,.512*H,.798*W,.369*H,.740*W,.212*H) - gc.line(.753*W,.257*H,.693*W,.383*H,.648*W,.436*H,.599*W,.309*H) + GC.line(.018*W,.567*H,.101*W,.512*H,.202*W,.369*H,.260*W,.212*H) + GC.line(.247*W,.257*H,.307*W,.383*H,.352*W,.436*H,.401*W,.309*H) + GC.line(.982*W,.567*H,.899*W,.512*H,.798*W,.369*H,.740*W,.212*H) + GC.line(.753*W,.257*H,.693*W,.383*H,.648*W,.436*H,.599*W,.309*H) local k=SCR.k for i=1,8 do - gc.setColor(wingColor[i]) + GC.setColor(wingColor[i]) local B=crystals[i] - gc.draw(crystal_img,B.x,B.y,B.a,k,k,21,0) + GC.draw(crystal_img,B.x,B.y,B.a,k,k,21,0) B=crystals[8+i] - gc.draw(crystal_img,B.x,B.y,B.a,-k,k,21,0) + GC.draw(crystal_img,B.x,B.y,B.a,-k,k,21,0) end end function back.event(level) for i=1,8 do local B=crystals[i] - B.va=B.va+.001*level*(1+rnd()) + B.va=B.va+.001*level*(1+math.random()) B=crystals[17-i] - B.va=B.va-.001*level*(1+rnd()) + B.va=B.va-.001*level*(1+math.random()) end end function back.discard() diff --git a/parts/bot/bot_9s.lua b/parts/bot/bot_9s.lua index b14b9b7d6..5f91e2cc4 100644 --- a/parts/bot/bot_9s.lua +++ b/parts/bot/bot_9s.lua @@ -38,8 +38,8 @@ local FCL={ local LclearScore={[0]=0,-200,-150,-100,200} local HclearScore={[0]=0,100,140,200,500} local function _ifoverlapAI(f,bk,x,y) - for i=1,#bk do for j=1,#bk[1]do - if f[y+i-1]and bk[i][j]and f[y+i-1][x+j-1]>0 then + for i=1,#bk do for j=1,#bk[1] do + if f[y+i-1] and bk[i][j] and f[y+i-1][x+j-1]>0 then return true end end end @@ -65,16 +65,21 @@ local function _getScore(field,cb,cy) local hole=0 for i=cy+#cb-1,cy,-1 do + local full=true for j=1,10 do if field[i][j]==0 then - goto CONTINUE_notFull + -- goto CONTINUE_notFull + full=false + break end end - discardRow(rem(field,i)) - clear=clear+1 - ::CONTINUE_notFull:: + if full then + -- ::CONTINUE_notFull:: + discardRow(rem(field,i)) + clear=clear+1 + end end - if #field==0 then--PC + if #field==0 then-- PC return 1e99 end for x=1,10 do @@ -116,10 +121,10 @@ local function _getScore(field,cb,cy) -#field*30 -#cb*15 +(#field>10 and - HclearScore[clear]--Clearing - -hole*70--Hole - -cy*50--Height - -sdh--Sum of DeltaH + HclearScore[clear]-- Clearing + -hole*70-- Hole + -cy*50-- Height + -sdh-- Sum of DeltaH or LclearScore[clear] -hole*100 @@ -139,10 +144,10 @@ local bot_9s={} function bot_9s.thread(bot) local P,data,keys=bot.P,bot.data,bot.keys while true do - --Thinking + -- Thinking yield() - local Tfield={}--Test field - local best={x=1,dir=0,hold=false,score=-1e99}--Best method + local Tfield={}-- Test field + local best={x=1,dir=0,hold=false,score=-1e99}-- Best method local field_org=P.field for i=1,#field_org do Tfield[i]=getRow(0) @@ -152,33 +157,33 @@ function bot_9s.thread(bot) end for ifhold=0,data.hold and P.gameEnv.holdCount>0 and 1 or 0 do - --Get block id + -- Get block id local bn if ifhold==0 then bn=P.cur and P.cur.id else - bn=P.holdQueue[1]and P.holdQueue[1].id or P.nextQueue[1]and P.nextQueue[1].id + bn=P.holdQueue[1] and P.holdQueue[1].id or P.nextQueue[1] and P.nextQueue[1].id end if bn then - for dir=0,dirCount[bn]do--Each dir + for dir=0,dirCount[bn] do-- Each dir local cb=BLOCKS[bn][dir] - for cx=1,11-#cb[1]do--Each pos + for cx=1,11-#cb[1] do-- Each pos local cy=#Tfield+1 - --Move to bottom - while cy>1 and not _ifoverlapAI(Tfield,cb,cx,cy-1)do + -- Move to bottom + while cy>1 and not _ifoverlapAI(Tfield,cb,cx,cy-1) do cy=cy-1 end - --Simulate lock + -- Simulate lock for i=1,#cb do local y=cy+i-1 - if not Tfield[y]then + if not Tfield[y] then Tfield[y]=getRow(0) end local L=Tfield[y] - for j=1,#cb[1]do - if cb[i][j]then + for j=1,#cb[1] do + if cb[i][j] then L[cx+j-1]=1 end end @@ -194,7 +199,7 @@ function bot_9s.thread(bot) end if not best.bn then return 1 end - --Release cache + -- Release cache while #Tfield>0 do discardRow(rem(Tfield,1)) end @@ -207,7 +212,7 @@ function bot_9s.thread(bot) end ins(keys,6) - --Check if time to change target + -- Check if time to change target yield() if P.aiRND:random()<.00126 then P:changeAtkMode(P.aiRND:random()<.85 and 1 or #P.atker>3 and 4 or P.aiRND:random()<.3 and 2 or 3) diff --git a/parts/bot/bot_cc.lua b/parts/bot/bot_cc.lua index ec2c615c0..bc4e4ede2 100644 --- a/parts/bot/bot_cc.lua +++ b/parts/bot/bot_cc.lua @@ -7,40 +7,58 @@ local pcall=pcall local ins,rem=table.insert,table.remove local yield=coroutine.yield local bot_cc={} -function bot_cc:checkDest() +function bot_cc:checkDest(b2b,atk,exblock,yomi) local dest=self.P.destFX if not dest then return end + if not (dest.b2b==b2b and dest.attack==atk and dest.extra==exblock) then + -- print(('hope: %s %s %s'):format(dest.b2b,dest.attack,dest.extra)) + -- print(('real: %s %s %s'):format(b2b,atk,exblock)) + -- print(yomi) + self:lockWrongPlace() + self.P.destFX=nil + return + end local CB=self.P.cur.bk for k=1,#dest,2 do local r=CB[dest[k+1]-self.P.curY+2] - if not r or not r[dest[k]-self.P.curX+2]then + if not r or not r[dest[k]-self.P.curX+2] then + -- print('wrong place') self:lockWrongPlace() self.P.destFX=nil return end end + local should_spawn = self.P:getNextSpawn() - 1 + if dest.spawn ~= should_spawn then + assert(dest.spawn > should_spawn) + -- print('wrong spawn: should be '..dest.spawn..' but '..should_spawn) + -- print('-- should only happen when camera is going down') + self:lockWrongPlace() + self.P.destFX=nil + return + end end function bot_cc:revive() TABLE.cut(self.P.holdQueue) self.P:loadAI(self.data) end function bot_cc:pushNewNext(id) - self.ccBot:addNext(rem(self.bufferedNexts,1)) ins(self.bufferedNexts,id) + self.ccBot:addNext(rem(self.bufferedNexts,1)) end function bot_cc:thread() local P,keys=self.P,self.keys local ccBot=self.ccBot while true do - --Start thinking + -- Start thinking yield() ccBot:think() - --Poll keys - local success,result,dest,hold,move + -- Poll keys + local success,result,dest,hold,move,b2b,attack,extra,spawn repeat yield() - success,result,dest,hold,move=pcall(ccBot.getMove,ccBot) + success,result,dest,hold,move,b2b,attack,extra,spawn=pcall(ccBot.getMove,ccBot) until not success or result==0 or result==2 if not success then break end if result==2 then @@ -50,14 +68,20 @@ function bot_cc:thread() dest[7],dest[8]=dest[2][1],dest[2][2] dest[1],dest[2]=dest[3][1],dest[3][2] dest[3],dest[4]=dest[4][1],dest[4][2] + dest.b2b = b2b + dest.attack = attack + dest.extra = extra + dest.spawn = spawn P.destFX=dest - if hold then--Hold + if hold then-- Hold keys[1]=8 end - while move[1]do + while move[1] do local m=rem(move,1) if m<4 then ins(keys,m+1) + elseif m==5 then + ins(keys, 5) elseif not self.data._20G then ins(keys,13) end @@ -65,7 +89,7 @@ function bot_cc:thread() ins(keys,6) end - --Check if time to change target + -- Check if time to change target yield() if P.aiRND:random()<.00126 then P:changeAtkMode(P.aiRND:random()<.85 and 1 or #P.atker>3 and 4 or P.aiRND:random()<.3 and 2 or 3) @@ -80,8 +104,16 @@ function bot_cc:updateField() F[i],i=F0[y][x]>0,i+1 end end while i<=400 do F[i],i=false,i+1 end - if not pcall(self.ccBot.reset,self.ccBot,F,P.b2b>=100,P.combo)then + local y = P:getNextSpawn()-1 + if not pcall(self.ccBot.reset,self.ccBot,F,P.b2b,P.combo,P.stat.pc,P.stat.row,y) then print("CC is dead ("..P.id..")","error") + for y=#F0,1,-1 do + local s="" + for x=1,10 do + s=s..(F[(y-1)*10+x] and "[]" or "..") + end + print(s) + end end end function bot_cc:switch20G() diff --git a/parts/bot/init.lua b/parts/bot/init.lua index 4df42abfa..aed19b239 100644 --- a/parts/bot/init.lua +++ b/parts/bot/init.lua @@ -14,9 +14,9 @@ function baseBot.update(bot) local keys=bot.keys if P.control and P.cur then bot.delay=bot.delay-1 - if not keys[1]then + if not keys[1] then if bot.runningThread then - if not pcall(bot.runningThread)then + if not pcall(bot.runningThread) then bot.runningThread=false end else @@ -49,7 +49,7 @@ local botMeta={__index=_undefMethod} local BOT={} -local AISpeed={60,50,40,30,20,14,10,6,4,3} +local AISpeed={60,50,42,34,27,21,16,12,9,6} --[[ arg={ next: number of nexts @@ -61,18 +61,18 @@ local AISpeed={60,50,40,30,20,14,10,6,4,3} } ]] function BOT.template(arg) - if arg.type=='CC'then - return{ + if arg.type=='CC' then + return { type='CC', next=arg.next, hold=arg.hold, delay=AISpeed[arg.speedLV], node=arg.node, - bag=(arg.randomizer or'bag')=='bag', + bag=(arg.randomizer or 'bag')=='bag', _20G=arg._20G, } - elseif arg.type=='9S'then - return{ + elseif arg.type=='9S' then + return { type='9S', delay=math.floor(AISpeed[arg.speedLV]), hold=arg.hold, @@ -82,8 +82,8 @@ end function BOT.new(P,data) local bot={P=P,data=data} - if data.type=="CC"then - P:setRS('SRS') + if data.type=="CC" then + P:setRS('TRS') bot.keys={} bot.bufferedNexts={} bot.delay=data.delay @@ -92,7 +92,7 @@ function BOT.new(P,data) P:setHold(1) end - local cc=cc or REQUIRE"CCloader" + local cc=REQUIRE"CCloader" if not cc then data.type=false return BOT.new(P,data) @@ -107,8 +107,8 @@ function BOT.new(P,data) local cc_lua=require"parts.bot.bot_cc" setmetatable(bot,{__index=function(self,k) return - self.ccBot[k]and function(_,...)self.ccBot[k](self.ccBot,...)end or - cc_lua[k]and function(_,...)cc_lua[k](self,...)end or + self.ccBot[k] and function(_,...)self.ccBot[k](self.ccBot,...) end or + cc_lua[k] and function(_,...)cc_lua[k](self,...) end or assert(baseBot[k],"No CC action called "..k) end}) @@ -127,7 +127,7 @@ function BOT.new(P,data) end bot.runningThread=coroutine.wrap(cc_lua.thread) bot.runningThread(bot) - else--if data.type=="9S"then--9s or else + else-- if data.type=="9S" then-- 9s or else TABLE.cover(baseBot,bot) TABLE.cover(require"parts.bot.bot_9s",bot) P:setRS('TRS') diff --git a/parts/char.lua b/parts/char.lua index e6b57aef9..1f39bc6de 100644 --- a/parts/char.lua +++ b/parts/char.lua @@ -1,5 +1,5 @@ local L={ - zChan={--F0000~F003F + zChan={-- F0000~F003F none= 0xF0000, normal= 0xF0001, full= 0xF0002, @@ -24,7 +24,7 @@ local L={ thinking= 0xF0015, spark= 0xF0016, }, - mino={--F0040~F007F + mino={-- F0040~F007F Z=0xF0040, S=0xF0041, J=0xF0042, @@ -57,7 +57,7 @@ local L={ I2=0xF005B, O1=0xF005C, }, - icon={--F0080~F00FF + icon={-- F0080~F00FF menu= 0xF0080, music= 0xF0081, language= 0xF0082, @@ -130,8 +130,14 @@ local L={ bomb= 0xF00C5, garbage= 0xF00C6, copy= 0xF00C7, + tas= 0xF00C8, + pencil= 0xF00C9, + magGlass= 0xF00CA, + zoomIn= 0xF00CB, + zoomOut= 0xF00CC, + zoomDefault= 0xF00CD, }, - key={--F0100~F017F + key={-- F0100~F017F macCmd= 0xF0100, macOpt= 0xF0101, macCtrl= 0xF0102, @@ -172,7 +178,7 @@ local L={ macPgdnAlt= 0xF0125, iecPower= 0xF0126, }, - controller={--F0100~F017F + controller={-- F0180~F01FF xbox= 0xF0180, lt= 0xF0181, rt= 0xF0182, @@ -186,12 +192,12 @@ local L={ joystickR= 0xF018A, jsLU= 0xF018B, jsLD= 0xF018C, - jsLL= 0xF018D, - jsLR= 0xF018E, + jsLR= 0xF018D, + jsLL= 0xF018E, jsRU= 0xF018F, jsRD= 0xF0190, - jsRL= 0xF0191, - jsRR= 0xF0192, + jsRR= 0xF0191, + jsRL= 0xF0192, jsLPress= 0xF0193, jsRPress= 0xF0194, dpad= 0xF0195, @@ -211,6 +217,94 @@ local L={ psMute= 0xF01A3, psCreate= 0xF01A4, psOption= 0xF01A5, + }, + mahjong={-- F0200~F027F + m1= 0xF0200, + m2= 0xF0201, + m3= 0xF0202, + m4= 0xF0203, + m5= 0xF0204, + m6= 0xF0205, + m7= 0xF0206, + m8= 0xF0207, + m9= 0xF0208, + s1= 0xF0209, + s2= 0xF020A, + s3= 0xF020B, + s4= 0xF020C, + s5= 0xF020D, + s6= 0xF020E, + s7= 0xF020F, + s8= 0xF0210, + s9= 0xF0211, + p1= 0xF0212, + p2= 0xF0213, + p3= 0xF0214, + p4= 0xF0215, + p5= 0xF0216, + p6= 0xF0217, + p7= 0xF0218, + p8= 0xF0219, + p9= 0xF021A, + ton= 0xF021B, + nan= 0xF021C, + sha= 0xF021D, + pe= 0xF021E, + chun= 0xF021F, + hatsu= 0xF0220, + haku= 0xF0221, + hatsuAlt= 0xF0222, + hakuAlt= 0xF0223, + haru= 0xF0224, + natsu= 0xF0225, + aki= 0xF0226, + fuyu= 0xF0227, + ume= 0xF0228, + ran= 0xF0229, + kiku= 0xF022A, + take= 0xF022B, + m5Red= 0xF022C, + s5Red= 0xF022D, + p5Red= 0xF022E, + m1Base= 0xF022F, + m2Base= 0xF0230, + m3Base= 0xF0231, + m4Base= 0xF0232, + m5Base= 0xF0233, + m6Base= 0xF0234, + m7Base= 0xF0235, + m8Base= 0xF0236, + m9Base= 0xF0237, + mComb= 0xF0238, + s1Base= 0xF0239, + s1Comb= 0xF023A, + s5Base= 0xF023B, + s5Comb= 0xF023C, + s7Base= 0xF023D, + s7Comb= 0xF023E, + s9Base= 0xF023F, + s9Comb= 0xF0240, + p2Base= 0xF0241, + p2Comb= 0xF0242, + p3Base= 0xF0243, + p3Comb1= 0xF0244, + p3Comb2= 0xF0245, + p4Base= 0xF0246, + p4Comb= 0xF0247, + p5Base= 0xF0248, + p5Comb1= 0xF0249, + p5Comb2= 0xF024A, + p6Base= 0xF024B, + p6Comb= 0xF024C, + p7Base= 0xF024D, + p7Comb= 0xF024E, + p9Base= 0xF024F, + p9Comb1= 0xF0250, + p9Comb2= 0xF0251, + frameComb= 0xF0252, + s1j= 0xF0253, + s1jBase= 0xF0254, + s1jComb= 0xF0255, } } diff --git a/parts/customEnv0.lua b/parts/customEnv0.lua index 075304d0f..5b6629257 100644 --- a/parts/customEnv0.lua +++ b/parts/customEnv0.lua @@ -1,7 +1,7 @@ -return{ +return { version=VERSION.code, - --Basic + -- Basic drop=1e99, lock=1e99, wait=0, @@ -9,17 +9,17 @@ return{ hang=5, hurry=1e99, - --Control + -- Control nextCount=6, holdMode='hold', holdCount=1, infHold=true, phyHold=false, - --Visual + -- Visual bone=false, - --Rule + -- Rule sequence='bag', lockout=false, fieldH=20, @@ -40,7 +40,7 @@ return{ garbageSpeed=1, missionKill=false, - --Else + -- Else bg='blockrain', bgm='hang out', diff --git a/parts/data.lua b/parts/data.lua index 33c25864f..bd8ff4cef 100644 --- a/parts/data.lua +++ b/parts/data.lua @@ -5,8 +5,8 @@ local ins=table.insert local BAG,FIELD,MISSION,CUSTOMENV,GAME=BAG,FIELD,MISSION,CUSTOMENV,GAME local DATA={} ---Sep symbol: 33 (!) ---Safe char: 34~126 +-- Sep symbol: 33 (!) +-- Safe char: 34~126 --[[ Count: 34~96 Block: 97~125 @@ -18,7 +18,7 @@ function DATA.copySequence() local count=1 for i=1,#BAG+1 do - if BAG[i+1]~=BAG[i]or count==64 then + if BAG[i+1]~=BAG[i] or count==64 then str=str..char(96+BAG[i]) if count>1 then str=str..char(32+count) @@ -66,14 +66,14 @@ local fieldMeta={__index=function(self,h) end return self[h] end} -function DATA.newBoard(f)--Generate a new board - return setmetatable(f and TABLE.shift(f)or{},fieldMeta) +function DATA.newBoard(f)-- Generate a new board + return setmetatable(f and TABLE.shift(f) or{},fieldMeta) end -function DATA.copyBoard(page)--Copy the [page] board +function DATA.copyBoard(page)-- Copy the [page] board local F=FIELD[page or 1] local str="" - --Encode field + -- Encode field for y=1,#F do local S="" local L=F[y] @@ -91,25 +91,25 @@ function DATA.copyBoards() end return table.concat(out,"!") end -function DATA.pasteBoard(str,page)--Paste [str] data to [page] board +function DATA.pasteBoard(str,page)-- Paste [str] data to [page] board if not page then page=1 end - if not FIELD[page]then + if not FIELD[page] then FIELD[page]=DATA.newBoard() end local F=FIELD[page] - --Decode + -- Decode str=STRING.unpackBin(str) if not str then return end - local fX,fY=1,1--*ptr for Field(r*10+(c-1)) + local fX,fY=1,1-- *ptr for Field(r*10+(c-1)) local p=1 while true do - local b=byte(str,p)--1byte + local b=byte(str,p)-- 1byte - --Str end + -- Str end if not b then if fX~=1 then return @@ -118,16 +118,16 @@ function DATA.pasteBoard(str,page)--Paste [str] data to [page] board end end - local id=b%32-1--Block id - if id>26 then return end--Illegal blockid - b=int(b/32)--Mode id + local id=b%32-1-- Block id + if id>26 then return end-- Illegal blockid + b=int(b/32)-- Mode id F[fY][fX]=id if fX<10 then fX=fX+1 else fY=fY+1 - if fY>20 then break end + if fY>60 then break end fX=1 end p=p+1 @@ -158,7 +158,7 @@ function DATA.copyMission() local count=1 for i=1,#MISSION+1 do - if MISSION[i+1]~=MISSION[i]or count==13 then + if MISSION[i+1]~=MISSION[i] or count==13 then _=33+MISSION[i] str=str..char(_) if count>1 then @@ -186,7 +186,7 @@ function DATA.pasteMission(str) end else if b>=34 and b<=114 then - if ENUM_MISSION[reg]then + if ENUM_MISSION[reg] then ins(MISSION,reg) reg=b-33 else @@ -211,8 +211,8 @@ function DATA.copyQuestArgs() local ENV=CUSTOMENV local str="".. ENV.holdCount.. - (ENV.ospin and"O"or"Z").. - (ENV.missionKill and"M"or"Z").. + (ENV.ospin and "O" or "Z").. + (ENV.missionKill and "M" or "Z").. ENV.sequence return str end @@ -252,15 +252,15 @@ function DATA.dumpRecording(list,ptr) local out="" local buffer,buffer2="" if not ptr then ptr=1 end - local prevFrm=list[ptr-2]or 0 - while list[ptr]do - --Flush buffer + local prevFrm=list[ptr-2] or 0 + while list[ptr] do + -- Flush buffer if #buffer>10 then out=out..buffer buffer="" end - --Encode time + -- Encode time local t=list[ptr]-prevFrm prevFrm=list[ptr] if t>=128 then @@ -275,7 +275,7 @@ function DATA.dumpRecording(list,ptr) buffer=buffer..char(t) end - --Encode event + -- Encode event t=list[ptr+1] if t>=128 then buffer2=char(t%128) @@ -289,7 +289,7 @@ function DATA.dumpRecording(list,ptr) buffer=buffer..char(t) end - --Step + -- Step ptr=ptr+2 end return out..buffer,ptr @@ -298,10 +298,10 @@ function DATA.pumpRecording(str,L) local len=#str local p=1 - local curFrm=L[#L-1]or 0 + local curFrm=L[#L-1] or 0 local code while p<=len do - --Read delta time + -- Read delta time code=0 local b=byte(str,p) while b>=128 do @@ -324,7 +324,7 @@ function DATA.pumpRecording(str,L) p=p+1 end end -do--function DATA.saveReplay() +do-- function DATA.saveReplay() local noRecList={"custom","solo","round","techmino"} local function _getModList() local res={} @@ -336,17 +336,17 @@ do--function DATA.saveReplay() return res end function DATA.saveReplay() - --Filtering modes that cannot be saved + -- Filtering modes that cannot be saved for _,v in next,noRecList do - if GAME.curModeName:find(v)then + if GAME.curModeName:find(v) then MES.new('error',"Cannot save recording of this mode now!") return end end - --Write file + -- Write file local fileName=os.date("replay/%Y_%m_%d_%H%M%S.rep") - if not love.filesystem.getInfo(fileName)then + if not love.filesystem.getInfo(fileName) then love.filesystem.write(fileName, love.data.compress('string','zlib', JSON.encode{ @@ -371,29 +371,33 @@ do--function DATA.saveReplay() end function DATA.parseReplay(fileName,ifFull) local fileData - --Read file + -- Read file fileData=love.filesystem.read(fileName) return DATA.parseReplayData(fileName,fileData,ifFull) end function DATA.parseReplayData(fileName,fileData,ifFull) - local success,metaData,rep + local success,metaData + local rep={-- unavailable replay object + fileName=fileName, + available=false, + } - if not(fileData and #fileData>0)then goto BREAK_cannotParse end + if not (fileData and #fileData>0) then return rep end-- goto BREAK_cannotParse - --Decompress file + -- Decompress file success,fileData=pcall(love.data.decompress,'string','zlib',fileData) - if not success then goto BREAK_cannotParse end + if not success then return rep end-- goto BREAK_cannotParse - --Load metadata + -- Load metadata metaData,fileData=STRING.readLine(fileData) metaData=JSON.decode(metaData) - if not metaData then goto BREAK_cannotParse end + if not metaData then return rep end-- goto BREAK_cannotParse - --Convert ancient replays - metaData.mode=MODE_UPDATE_MAP[metaData.mode]or metaData.mode - if not MODES[metaData.mode]then goto BREAK_cannotParse end + -- Convert ancient replays + metaData.mode=MODE_UPDATE_MAP[metaData.mode] or metaData.mode + if not MODES[metaData.mode] then return rep end-- goto BREAK_cannotParse - --Create replay object + -- Create replay object rep={ fileName=fileName, available=true, @@ -409,13 +413,6 @@ function DATA.parseReplayData(fileName,fileData,ifFull) tasUsed=metaData.tasUsed, } if ifFull then rep.data=fileData end - do return rep end - - --Create unavailable replay object - ::BREAK_cannotParse:: - return{ - fileName=fileName, - available=false, - } + return rep end return DATA diff --git a/parts/eventsets/attacker_h.lua b/parts/eventsets/attacker_h.lua index 06c88544a..fa2efa3fd 100644 --- a/parts/eventsets/attacker_h.lua +++ b/parts/eventsets/attacker_h.lua @@ -1,25 +1,25 @@ -return{ +return { mesDisp=function(P) setFont(55) - mStr(P.modeData.wave,63,200) - mStr("22",63,320) + GC.mStr(P.modeData.wave,63,200) + GC.mStr("22",63,320) mText(TEXTOBJ.wave,63,260) mText(TEXTOBJ.nextWave,63,380) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control and P.atkBufferSum==0 then local D=P.modeData if D.wave==50 then P:win('finish') else if D.wave<20 then - local t=1500-30*D.wave--1500~900 + local t=1500-30*D.wave-- 1500~900 table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(4,7)),amount=12,countdown=t,cd0=t,time=0,sent=false,lv=3}) table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(3,8)),amount=10,countdown=t,cd0=t,time=0,sent=false,lv=4}) else - local t=900-10*(D.wave-20)--900~600 + local t=900-10*(D.wave-20)-- 900~600 table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(10)),amount=14,countdown=t,cd0=t,time=0,sent=false,lv=4}) table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(4,7)),amount=8,countdown=t,cd0=t,time=0,sent=false,lv=5}) end diff --git a/parts/eventsets/attacker_u.lua b/parts/eventsets/attacker_u.lua index b59da766b..307ba42aa 100644 --- a/parts/eventsets/attacker_u.lua +++ b/parts/eventsets/attacker_u.lua @@ -1,21 +1,21 @@ -return{ +return { mesDisp=function(P) setFont(55) - mStr(P.modeData.wave,63,200) - mStr(20+4*math.min(math.floor(P.modeData.wave/10),2),63,320) + GC.mStr(P.modeData.wave,63,200) + GC.mStr(20+4*math.min(math.floor(P.modeData.wave/10),2),63,320) mText(TEXTOBJ.wave,63,260) mText(TEXTOBJ.nextWave,63,380) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control and P.atkBufferSum<4 then local D=P.modeData if D.wave==50 then P:win('finish') else local s - local t=800-10*D.wave--800~700~600~500 + local t=800-10*D.wave-- 800~700~600~500 if D.wave<10 then table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(5,6)),amount=9,countdown=t,cd0=t,time=0,sent=false,lv=3}) table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(4,7)),amount=11,countdown=t,cd0=t+62,time=0,sent=false,lv=4}) diff --git a/parts/eventsets/backfire_0.lua b/parts/eventsets/backfire_0.lua index 8c4a012cc..621df23d9 100644 --- a/parts/eventsets/backfire_0.lua +++ b/parts/eventsets/backfire_0.lua @@ -1,4 +1,4 @@ -return{ +return { hook_drop=function(P) if P.lastPiece.atk>0 then P:receive(nil,P.lastPiece.atk,0,generateLine(P.holeRND:random(10))) diff --git a/parts/eventsets/backfire_120.lua b/parts/eventsets/backfire_120.lua index 4a284a48a..639cf3b70 100644 --- a/parts/eventsets/backfire_120.lua +++ b/parts/eventsets/backfire_120.lua @@ -1,4 +1,4 @@ -return{ +return { hook_drop=function(P) if P.lastPiece.atk>0 then P:receive(nil,P.lastPiece.atk,120,generateLine(P.holeRND:random(10))) diff --git a/parts/eventsets/backfire_30.lua b/parts/eventsets/backfire_30.lua index bb949c4af..4ae0feb81 100644 --- a/parts/eventsets/backfire_30.lua +++ b/parts/eventsets/backfire_30.lua @@ -1,4 +1,4 @@ -return{ +return { hook_drop=function(P) if P.lastPiece.atk>0 then P:receive(nil,P.lastPiece.atk,30,generateLine(P.holeRND:random(10))) diff --git a/parts/eventsets/backfire_60.lua b/parts/eventsets/backfire_60.lua index 22e7ff042..617fd6243 100644 --- a/parts/eventsets/backfire_60.lua +++ b/parts/eventsets/backfire_60.lua @@ -1,4 +1,4 @@ -return{ +return { hook_drop=function(P) if P.lastPiece.atk>0 then P:receive(nil,P.lastPiece.atk,60,generateLine(P.holeRND:random(10))) diff --git a/parts/eventsets/bigWallGen.lua b/parts/eventsets/bigWallGen.lua index 072406732..a70051117 100644 --- a/parts/eventsets/bigWallGen.lua +++ b/parts/eventsets/bigWallGen.lua @@ -1,4 +1,4 @@ -return{ +return { hook_drop=function(P) if P.lastPiece.row>0 then for _=1,#P.clearedRow do diff --git a/parts/eventsets/blindMesDisp.lua b/parts/eventsets/blindMesDisp.lua index 2dae20072..ecde9fc0c 100644 --- a/parts/eventsets/blindMesDisp.lua +++ b/parts/eventsets/blindMesDisp.lua @@ -1,13 +1,11 @@ -local gc=love.graphics - -return{ +return { mesDisp=function(P) mText(TEXTOBJ.techrash,63,420) setFont(75) - mStr(P.stat.clears[4],63,340) + GC.mStr(P.stat.clears[4],63,340) PLY.draw.applyField(P) - gc.setColor(1,1,1,.1) - gc.draw(IMG.electric,0,106,0,2.6) - PLY.draw.cancelField(P) + GC.setColor(1,1,1,.1) + GC.draw(IMG.electric,0,106,0,2.6) + PLY.draw.cancelField() end, } diff --git a/parts/eventsets/c4wBase.lua b/parts/eventsets/c4wBase.lua index 15fa311a3..3d88cab06 100644 --- a/parts/eventsets/c4wBase.lua +++ b/parts/eventsets/c4wBase.lua @@ -1,10 +1,10 @@ local rem=table.remove -return{ +return { mesDisp=function(P) setFont(45) - mStr(P.combo,63,310) - mStr(P.modeData.maxCombo,63,400) + GC.mStr(P.combo,63,310) + GC.mStr(P.modeData.maxCombo,63,400) mText(TEXTOBJ.combo,63,358) mText(TEXTOBJ.maxcmb,63,450) end, diff --git a/parts/eventsets/c4wCheck_easy.lua b/parts/eventsets/c4wCheck_easy.lua index 5f81dd243..2058cf8d2 100644 --- a/parts/eventsets/c4wCheck_easy.lua +++ b/parts/eventsets/c4wCheck_easy.lua @@ -1,4 +1,4 @@ -return{ +return { hook_drop=function(P) if P.lastPiece.row>0 then for _=1,#P.clearedRow do diff --git a/parts/eventsets/c4wCheck_hard.lua b/parts/eventsets/c4wCheck_hard.lua index e2ecc4d88..ac31d3e8c 100644 --- a/parts/eventsets/c4wCheck_hard.lua +++ b/parts/eventsets/c4wCheck_hard.lua @@ -1,4 +1,4 @@ -return{ +return { hook_drop=function(P) if P.lastPiece.row==0 then P:lose() diff --git a/parts/eventsets/checkAttack_100.lua b/parts/eventsets/checkAttack_100.lua index e112a2c7d..4c7c789a5 100644 --- a/parts/eventsets/checkAttack_100.lua +++ b/parts/eventsets/checkAttack_100.lua @@ -1,8 +1,8 @@ -return{ +return { mesDisp=function(P) setFont(45) - mStr(("%.1f"):format(P.stat.atk),63,190) - mStr(("%.2f"):format(P.stat.atk/P.stat.row),63,310) + GC.mStr(("%d"):format(P.stat.atk),63,190) + GC.mStr(("%.2f"):format(P.stat.atk/P.stat.row),63,310) mText(TEXTOBJ.atk,63,243) mText(TEXTOBJ.eff,63,363) end, diff --git a/parts/eventsets/checkClearBoard.lua b/parts/eventsets/checkClearBoard.lua index ea51a2c98..a6016c77d 100644 --- a/parts/eventsets/checkClearBoard.lua +++ b/parts/eventsets/checkClearBoard.lua @@ -1,9 +1,9 @@ -return{ +return { hook_drop=function(P) if P.garbageBeneath==0 then local D=P.modeData D.finished=D.finished+1 - if FIELD[D.finished+1]then + if FIELD[D.finished+1] then P.waiting=26 for i=#P.field,1,-1 do P.field[i],P.visTime[i]=nil diff --git a/parts/eventsets/checkLine_10.lua b/parts/eventsets/checkLine_10.lua index 02edb80a0..06dc16757 100644 --- a/parts/eventsets/checkLine_10.lua +++ b/parts/eventsets/checkLine_10.lua @@ -1,9 +1,9 @@ -return{ +return { mesDisp=function(P) setFont(55) local r=10-P.stat.row if r<0 then r=0 end - mStr(r,63,265) + GC.mStr(r,63,265) PLY.draw.drawTargetLine(P,r) end, hook_drop=function(P) diff --git a/parts/eventsets/checkLine_100.lua b/parts/eventsets/checkLine_100.lua index 2c6bef5cc..61e4e63bf 100644 --- a/parts/eventsets/checkLine_100.lua +++ b/parts/eventsets/checkLine_100.lua @@ -1,9 +1,9 @@ -return{ +return { mesDisp=function(P) setFont(55) local r=100-P.stat.row if r<0 then r=0 end - mStr(r,63,265) + GC.mStr(r,63,265) PLY.draw.drawTargetLine(P,r) end, hook_drop=function(P) diff --git a/parts/eventsets/checkLine_1000.lua b/parts/eventsets/checkLine_1000.lua index c1321251b..8a515f783 100644 --- a/parts/eventsets/checkLine_1000.lua +++ b/parts/eventsets/checkLine_1000.lua @@ -1,9 +1,9 @@ -return{ +return { mesDisp=function(P) setFont(55) local r=1000-P.stat.row if r<0 then r=0 end - mStr(r,63,265) + GC.mStr(r,63,265) PLY.draw.drawTargetLine(P,r) end, hook_drop=function(P) diff --git a/parts/eventsets/checkLine_20.lua b/parts/eventsets/checkLine_20.lua index d901ec8d2..a135bc40b 100644 --- a/parts/eventsets/checkLine_20.lua +++ b/parts/eventsets/checkLine_20.lua @@ -1,9 +1,9 @@ -return{ +return { mesDisp=function(P) setFont(55) local r=20-P.stat.row if r<0 then r=0 end - mStr(r,63,265) + GC.mStr(r,63,265) PLY.draw.drawTargetLine(P,r) end, hook_drop=function(P) diff --git a/parts/eventsets/checkLine_200.lua b/parts/eventsets/checkLine_200.lua index e75128970..8edb41c57 100644 --- a/parts/eventsets/checkLine_200.lua +++ b/parts/eventsets/checkLine_200.lua @@ -1,9 +1,9 @@ -return{ +return { mesDisp=function(P) setFont(55) local r=200-P.stat.row if r<0 then r=0 end - mStr(r,63,265) + GC.mStr(r,63,265) PLY.draw.drawTargetLine(P,r) end, hook_drop=function(P) diff --git a/parts/eventsets/checkLine_40.lua b/parts/eventsets/checkLine_40.lua index bd8f2956a..a5a62e4bc 100644 --- a/parts/eventsets/checkLine_40.lua +++ b/parts/eventsets/checkLine_40.lua @@ -1,9 +1,9 @@ -return{ +return { mesDisp=function(P) setFont(55) local r=40-P.stat.row if r<0 then r=0 end - mStr(r,63,265) + GC.mStr(r,63,265) PLY.draw.drawTargetLine(P,r) end, hook_drop=function(P) diff --git a/parts/eventsets/checkLine_400.lua b/parts/eventsets/checkLine_400.lua index 3457f3c56..852c69b92 100644 --- a/parts/eventsets/checkLine_400.lua +++ b/parts/eventsets/checkLine_400.lua @@ -1,9 +1,9 @@ -return{ +return { mesDisp=function(P) setFont(55) local r=400-P.stat.row if r<0 then r=0 end - mStr(r,63,265) + GC.mStr(r,63,265) PLY.draw.drawTargetLine(P,r) end, hook_drop=function(P) diff --git a/parts/eventsets/checkTurn_1.lua b/parts/eventsets/checkTurn_1.lua index c0ca5c3f0..8f96769b6 100644 --- a/parts/eventsets/checkTurn_1.lua +++ b/parts/eventsets/checkTurn_1.lua @@ -1,4 +1,4 @@ -return{ +return { hook_drop=function(P) if #PLY_ALIVE>1 then P.control=false @@ -13,7 +13,7 @@ return{ end end for i=1,#PLY_ALIVE do - if PLY_ALIVE[i].sid==(minMaxID==1e99 and minID or minMaxID)then + if PLY_ALIVE[i].sid==(minMaxID==1e99 and minID or minMaxID) then PLY_ALIVE[i].control=true return end diff --git a/parts/eventsets/checkTurn_7.lua b/parts/eventsets/checkTurn_7.lua index bf0ce2d75..d44d326fd 100644 --- a/parts/eventsets/checkTurn_7.lua +++ b/parts/eventsets/checkTurn_7.lua @@ -1,4 +1,4 @@ -return{ +return { hook_drop=function(P) if P.stat.piece%7==0 and #PLY_ALIVE>1 then P.control=false @@ -13,7 +13,7 @@ return{ end end for i=1,#PLY_ALIVE do - if PLY_ALIVE[i].sid==(minMaxID==1e99 and minID or minMaxID)then + if PLY_ALIVE[i].sid==(minMaxID==1e99 and minID or minMaxID) then PLY_ALIVE[i].control=true return end diff --git a/parts/eventsets/classic_e.lua b/parts/eventsets/classic_e.lua index 483149bad..fc45ff67f 100644 --- a/parts/eventsets/classic_e.lua +++ b/parts/eventsets/classic_e.lua @@ -1,5 +1,29 @@ -local gc_setColor=love.graphics.setColor -return{ +local function GetLevelStr(lvl) + local list={"01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","00","0A","14","1E","28","32","3C","46","50","5A","64","6E","78","82","8C","96","A0","AA","B4","BE","C6","20","E6","20","06","21","26","21","46","21","66","21","86","21","A6","21","C6","21","E6","21","06","22","26","22","46","22","66","22","86","22","A6","22","C6","22","E6","22","06","23","26","23","85","A8","29","F0","4A","4A","4A","4A","8D","07","20","A5","A8","29","0F","8D","07","20","60","A6","49","E0","15","10","53","BD","D6","96","A8","8A","0A","AA","E8","BD","EA","96","8D","06","20","CA","A5","BE","C9","01","F0","1E","A5","B9","C9","05","F0","0C","BD","EA","96","38","E9","02","8D","06","20","4C","67","97","BD","EA","96","18","69","0C","8D","06","20","4C","67","97","BD","EA","96","18","69","06","8D","06","20","A2","0A","B1","B8","8D","07","20","C8","CA","D0","F7","E6","49","A5","49","C9","14","30","04","A9","20","85","49","60","A5","B1","29","03","D0","78","A9","00","85","AA","A6","AA","B5","4A","F0","5C","0A","A8","B9","EA","96","85","A8","A5","BE","C9","01","D0","0A","A5","A8","18","69","06","85","A8","4C","BD","97","A5","B9","C9","04","D0","0A","A5","A8","38","E9","02","85","A8","4C","BD","97","A5","A8"} + list[0]="00" + lvl=lvl%256 + return list[lvl] +end +local function GetGravity(lvl) + lvl=lvl%256 + return + lvl==0 and 48 or + lvl==1 and 43 or + lvl==2 and 38 or + lvl==3 and 33 or + lvl==4 and 28 or + lvl==5 and 23 or + lvl==6 and 18 or + lvl==7 and 13 or + lvl==8 and 8 or + lvl==9 and 6 or + lvl<13 and 5 or + lvl<16 and 4 or + lvl<19 and 3 or + lvl<29 and 2 or + 1 +end +return { das=16,arr=6, sddas=6,sdarr=6, irs=false,ims=false, @@ -15,44 +39,38 @@ return{ keyCancel={5,6}, mesDisp=function(P) setFont(75) - local r=P.modeData.target/10 - mStr(r<10 and 9 or r<30 and r or("%02x"):format(r*10-300),63,210) + GC.mStr(GetLevelStr(P.modeData.lvl),63,210) mText(TEXTOBJ.speedLV,63,290) PLY.draw.drawProgress(P.stat.row,P.modeData.target) if P.modeData.drought>7 then if P.modeData.drought<=14 then - gc_setColor(1,1,1,P.modeData.drought/7-1) + GC.setColor(1,1,1,P.modeData.drought/7-1) else local gb=P.modeData.drought<=21 and 2-P.modeData.drought/14 or .5 - gc_setColor(1,gb,gb) + GC.setColor(1,gb,gb) end setFont(50) - mStr(P.modeData.drought,63,130) + GC.mStr(P.modeData.drought,63,130) mDraw(MODES.drought_l.icon,63,200,nil,.5) end end, task=function(P) + P.modeData.lvl=9 P.modeData.target=10 end, hook_drop=function(P) local D=P.modeData D.drought=P.lastPiece.id==7 and 0 or D.drought+1 if P.stat.row>=D.target then - if D.target==110 then - P.gameEnv.drop,P.gameEnv.lock=5,5 - P.gameEnv.sddas,P.gameEnv.sdarr=5,5 - SFX.play('warn_2',.7) - elseif D.target==140 then - P.gameEnv.drop,P.gameEnv.lock=4,4 - P.gameEnv.sddas,P.gameEnv.sdarr=4,4 - SFX.play('warn_2',.7) - elseif D.target==170 then - P.gameEnv.drop,P.gameEnv.lock=3,3 - P.gameEnv.sddas,P.gameEnv.sdarr=3,3 + if D.target>=100 then + D.lvl=D.lvl+1 + end + local dropSpd=GetGravity(D.lvl) + if D.target==200 then P:win('finish') return + elseif dropSpd~=P.gameEnv.drop then + P.gameEnv.drop,P.gameEnv.lock=dropSpd,dropSpd + P.gameEnv.sddas,P.gameEnv.sdarr=dropSpd,dropSpd SFX.play('warn_2',.7) - elseif D.target==200 then - P:win('finish') - return else SFX.play('reach') end diff --git a/parts/eventsets/classic_h.lua b/parts/eventsets/classic_h.lua index a4157e95a..be1ebb52f 100644 --- a/parts/eventsets/classic_h.lua +++ b/parts/eventsets/classic_h.lua @@ -1,5 +1,29 @@ -local gc_setColor=love.graphics.setColor -return{ +local function GetLevelStr(lvl) + local list={"01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","00","0A","14","1E","28","32","3C","46","50","5A","64","6E","78","82","8C","96","A0","AA","B4","BE","C6","20","E6","20","06","21","26","21","46","21","66","21","86","21","A6","21","C6","21","E6","21","06","22","26","22","46","22","66","22","86","22","A6","22","C6","22","E6","22","06","23","26","23","85","A8","29","F0","4A","4A","4A","4A","8D","07","20","A5","A8","29","0F","8D","07","20","60","A6","49","E0","15","10","53","BD","D6","96","A8","8A","0A","AA","E8","BD","EA","96","8D","06","20","CA","A5","BE","C9","01","F0","1E","A5","B9","C9","05","F0","0C","BD","EA","96","38","E9","02","8D","06","20","4C","67","97","BD","EA","96","18","69","0C","8D","06","20","4C","67","97","BD","EA","96","18","69","06","8D","06","20","A2","0A","B1","B8","8D","07","20","C8","CA","D0","F7","E6","49","A5","49","C9","14","30","04","A9","20","85","49","60","A5","B1","29","03","D0","78","A9","00","85","AA","A6","AA","B5","4A","F0","5C","0A","A8","B9","EA","96","85","A8","A5","BE","C9","01","D0","0A","A5","A8","18","69","06","85","A8","4C","BD","97","A5","B9","C9","04","D0","0A","A5","A8","38","E9","02","85","A8","4C","BD","97","A5","A8"} + list[0]="00" + lvl=lvl%256 + return list[lvl] +end +local function GetGravity(lvl) + lvl=lvl%256 + return + lvl==0 and 48 or + lvl==1 and 43 or + lvl==2 and 38 or + lvl==3 and 33 or + lvl==4 and 28 or + lvl==5 and 23 or + lvl==6 and 18 or + lvl==7 and 13 or + lvl==8 and 8 or + lvl==9 and 6 or + lvl<13 and 5 or + lvl<16 and 4 or + lvl<19 and 3 or + lvl<29 and 2 or + 1 +end +return { das=16,arr=6, sddas=3,sdarr=3, irs=false,ims=false, @@ -15,36 +39,38 @@ return{ keyCancel={5,6}, mesDisp=function(P) setFont(75) - local r=P.modeData.target/10 - mStr(r<11 and 18 or r<22 and r+8 or("%02x"):format(r*10-220),63,210) + GC.mStr(GetLevelStr(P.modeData.lvl),63,210) mText(TEXTOBJ.speedLV,63,290) PLY.draw.drawProgress(P.stat.row,P.modeData.target) if P.modeData.drought>7 then if P.modeData.drought<=14 then - gc_setColor(1,1,1,P.modeData.drought/7-1) + GC.setColor(1,1,1,P.modeData.drought/7-1) else local gb=P.modeData.drought<=21 and 2-P.modeData.drought/14 or .5 - gc_setColor(1,gb,gb) + GC.setColor(1,gb,gb) end setFont(50) - mStr(P.modeData.drought,63,130) + GC.mStr(P.modeData.drought,63,130) mDraw(MODES.drought_l.icon,63,200,nil,.5) end end, task=function(P) + P.modeData.lvl=18 P.modeData.target=10 end, hook_drop=function(P) local D=P.modeData D.drought=P.lastPiece.id==7 and 0 or D.drought+1 if P.stat.row>=D.target then - if D.target==110 then - P.gameEnv.drop,P.gameEnv.lock=2,2 - P.gameEnv.sddas,P.gameEnv.sdarr=2,2 + if D.target>=100 then + D.lvl=D.lvl+1 + end + local dropSpd=GetGravity(D.lvl) + if D.target==200 then P:win('finish') return + elseif dropSpd~=P.gameEnv.drop then + P.gameEnv.drop,P.gameEnv.lock=dropSpd,dropSpd + P.gameEnv.sddas,P.gameEnv.sdarr=dropSpd,dropSpd SFX.play('warn_1') - elseif D.target==200 then - P:win('finish') - return else SFX.play('reach') end diff --git a/parts/eventsets/classic_l.lua b/parts/eventsets/classic_l.lua new file mode 100644 index 000000000..a2d2f1767 --- /dev/null +++ b/parts/eventsets/classic_l.lua @@ -0,0 +1,79 @@ +local function GetLevelStr(lvl) + local list={"01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","00","0A","14","1E","28","32","3C","46","50","5A","64","6E","78","82","8C","96","A0","AA","B4","BE","C6","20","E6","20","06","21","26","21","46","21","66","21","86","21","A6","21","C6","21","E6","21","06","22","26","22","46","22","66","22","86","22","A6","22","C6","22","E6","22","06","23","26","23","85","A8","29","F0","4A","4A","4A","4A","8D","07","20","A5","A8","29","0F","8D","07","20","60","A6","49","E0","15","10","53","BD","D6","96","A8","8A","0A","AA","E8","BD","EA","96","8D","06","20","CA","A5","BE","C9","01","F0","1E","A5","B9","C9","05","F0","0C","BD","EA","96","38","E9","02","8D","06","20","4C","67","97","BD","EA","96","18","69","0C","8D","06","20","4C","67","97","BD","EA","96","18","69","06","8D","06","20","A2","0A","B1","B8","8D","07","20","C8","CA","D0","F7","E6","49","A5","49","C9","14","30","04","A9","20","85","49","60","A5","B1","29","03","D0","78","A9","00","85","AA","A6","AA","B5","4A","F0","5C","0A","A8","B9","EA","96","85","A8","A5","BE","C9","01","D0","0A","A5","A8","18","69","06","85","A8","4C","BD","97","A5","B9","C9","04","D0","0A","A5","A8","38","E9","02","85","A8","4C","BD","97","A5","A8"} + list[0]="00" + lvl=lvl%256 + return list[lvl] +end +local function GetGravity(lvl) + lvl=lvl%256 + return + lvl==0 and 48 or + lvl==1 and 43 or + lvl==2 and 38 or + lvl==3 and 33 or + lvl==4 and 28 or + lvl==5 and 23 or + lvl==6 and 18 or + lvl==7 and 13 or + lvl==8 and 8 or + lvl==9 and 6 or + lvl<13 and 5 or + lvl<16 and 4 or + lvl<19 and 3 or + lvl<29 and 2 or + 1 +end +return { + das=16,arr=6, + sddas=2,sdarr=2, + irs=false,ims=false, + drop=2,lock=2, + wait=10,fall=25, + freshLimit=0, + fieldH=19, + nextCount=1, + holdCount=0, + RS='Classic', + sequence='rnd', + noTele=true, + keyCancel={5,6}, + mesDisp=function(P) + setFont(75) + GC.mStr(GetLevelStr(P.modeData.lvl),63,210) + mText(TEXTOBJ.speedLV,63,290) + PLY.draw.drawProgress(P.stat.row,P.modeData.target) + if P.modeData.drought>7 then + if P.modeData.drought<=14 then + GC.setColor(1,1,1,P.modeData.drought/7-1) + else + local gb=P.modeData.drought<=21 and 2-P.modeData.drought/14 or .5 + GC.setColor(1,gb,gb) + end + setFont(50) + GC.mStr(P.modeData.drought,63,130) + mDraw(MODES.drought_l.icon,63,200,nil,.5) + end + end, + task=function(P) + P.modeData.lvl=19 + P.modeData.target=10 + end, + hook_drop=function(P) + local D=P.modeData + D.drought=P.lastPiece.id==7 and 0 or D.drought+1 + if P.stat.row>=D.target then + if D.target>=100 then + D.lvl=D.lvl+1 + end + local dropSpd=GetGravity(D.lvl) + if dropSpd~=P.gameEnv.drop then + P.gameEnv.drop,P.gameEnv.lock=dropSpd,dropSpd + P.gameEnv.sddas,P.gameEnv.sdarr=dropSpd,dropSpd + SFX.play('warn_1') + else + SFX.play('reach') + end + D.target=D.target+10 + end + end +} diff --git a/parts/eventsets/classic_u.lua b/parts/eventsets/classic_u.lua index 31edc74f3..f6c9d14e8 100644 --- a/parts/eventsets/classic_u.lua +++ b/parts/eventsets/classic_u.lua @@ -1,5 +1,10 @@ -local gc_setColor=love.graphics.setColor -return{ +local function GetLevelStr(lvl) + local list={"01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","00","0A","14","1E","28","32","3C","46","50","5A","64","6E","78","82","8C","96","A0","AA","B4","BE","C6","20","E6","20","06","21","26","21","46","21","66","21","86","21","A6","21","C6","21","E6","21","06","22","26","22","46","22","66","22","86","22","A6","22","C6","22","E6","22","06","23","26","23","85","A8","29","F0","4A","4A","4A","4A","8D","07","20","A5","A8","29","0F","8D","07","20","60","A6","49","E0","15","10","53","BD","D6","96","A8","8A","0A","AA","E8","BD","EA","96","8D","06","20","CA","A5","BE","C9","01","F0","1E","A5","B9","C9","05","F0","0C","BD","EA","96","38","E9","02","8D","06","20","4C","67","97","BD","EA","96","18","69","0C","8D","06","20","4C","67","97","BD","EA","96","18","69","06","8D","06","20","A2","0A","B1","B8","8D","07","20","C8","CA","D0","F7","E6","49","A5","49","C9","14","30","04","A9","20","85","49","60","A5","B1","29","03","D0","78","A9","00","85","AA","A6","AA","B5","4A","F0","5C","0A","A8","B9","EA","96","85","A8","A5","BE","C9","01","D0","0A","A5","A8","18","69","06","85","A8","4C","BD","97","A5","B9","C9","04","D0","0A","A5","A8","38","E9","02","85","A8","4C","BD","97","A5","A8"} + list[0]="00" + lvl=lvl%256 + return list[lvl] +end +return { das=16,arr=6, sddas=1,sdarr=1, irs=false,ims=false, @@ -15,35 +20,33 @@ return{ keyCancel={5,6}, mesDisp=function(P) setFont(75) - local r=P.modeData.target/10 - mStr(r==1 and 29 or("%02x"):format(r*10-20),63,210) + GC.mStr(GetLevelStr(P.modeData.lvl),63,210) mText(TEXTOBJ.speedLV,63,290) PLY.draw.drawProgress(P.stat.row,P.modeData.target) if P.modeData.drought>7 then if P.modeData.drought<=14 then - gc_setColor(1,1,1,P.modeData.drought/7-1) + GC.setColor(1,1,1,P.modeData.drought/7-1) else local gb=P.modeData.drought<=21 and 2-P.modeData.drought/14 or .5 - gc_setColor(1,gb,gb) + GC.setColor(1,gb,gb) end setFont(50) - mStr(P.modeData.drought,63,130) + GC.mStr(P.modeData.drought,63,130) mDraw(MODES.drought_l.icon,63,200,nil,.5) end end, task=function(P) + P.modeData.lvl=29 P.modeData.target=10 end, hook_drop=function(P) local D=P.modeData D.drought=P.lastPiece.id==7 and 0 or D.drought+1 if P.stat.row>=D.target then - if D.target==100 then - P:win('finish') - return - end - D.target=D.target+10 + if D.target>=200 then P:win('finish') return end SFX.play('reach') + D.lvl=D.lvl+1 + D.target=D.target+10 end end, } diff --git a/parts/eventsets/clearRush.lua b/parts/eventsets/clearRush.lua deleted file mode 100644 index 21ce0dfba..000000000 --- a/parts/eventsets/clearRush.lua +++ /dev/null @@ -1,36 +0,0 @@ -local function task_newBoard(P,init) - local targetLine - local F,L={},{1} - --TODO - P:pushNextList(L) - - P.control=false - if not init then for _=1,26 do YIELD()end end - P.control=true - - P.gameEnv.heightLimit=targetLine or #F - P:pushLineList(F) -end -local function _check(P) - P.gameEnv.heightLimit=P.gameEnv.heightLimit-P.lastPiece.row - if P.gameEnv.heightLimit==0 then - P.modeData.stage=P.modeData.stage+1 - if P.modeData.stage>=100 then - P:win('finish') - else - P:newTask(task_newBoard) - end - end -end -return{ - sequence='none', - RS="TRS", - pushSpeed=5, - mesDisp=function(P) - setFont(60) - mStr(P.modeData.stage,63,280) - mText(TEXTOBJ.wave,63,350) - end, - hook_drop=_check, - task=function(P)task_newBoard(P,true)P.fieldBeneath=0 end,--Just run one time at first to start first level -} diff --git a/parts/eventsets/defender_l.lua b/parts/eventsets/defender_l.lua index a27b537de..061f00e2b 100644 --- a/parts/eventsets/defender_l.lua +++ b/parts/eventsets/defender_l.lua @@ -1,46 +1,48 @@ -return{ +return { drop=5,lock=60, fall=6, mesDisp=function(P) setFont(55) - mStr(P.modeData.wave,63,200) - mStr(P.modeData.rpm,63,320) + GC.mStr(P.modeData.wave,63,200) + GC.mStr(P.modeData.rpm,63,320) mText(TEXTOBJ.wave,63,260) mText(TEXTOBJ.rpm,63,380) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control then local D=P.modeData - D.counter=D.counter+1 - local t= - D.wave<=60 and 240-2*D.wave or - D.wave<=120 and 120-(D.wave-60)or - D.wave<=180 and math.floor(60-(D.wave-120)*.5)or - 30 - if D.counter>=t then - D.counter=0 - for _=1,4 do - table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(10)),amount=1,countdown=5*t,cd0=5*t,time=0,sent=false,lv=2}) + D.timer=D.timer+1 + if P.atkBufferSum<30 then + local t= + D.wave<=60 and 240-2*D.wave or + D.wave<=120 and 120-(D.wave-60) or + D.wave<=180 and math.floor(60-(D.wave-120)*.5) or + 30 + if D.timer>=t then + D.timer=0 + for _=1,4 do + table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(10)),amount=1,countdown=5*t,cd0=5*t,time=0,sent=false,lv=2}) + end + P.atkBufferSum=P.atkBufferSum+4 + P.stat.recv=P.stat.recv+4 + D.wave=D.wave+1 + D.rpm=math.floor(144e3/t)*.1 + if D.wave==60 then + P:_showText(text.great,0,-140,100,'appear',.6) + P.gameEnv.pushSpeed=3 + P.dropDelay,P.gameEnv.drop=4,4 + elseif D.wave==120 then + P:_showText(text.awesome,0,-140,100,'appear',.6) + P.gameEnv.pushSpeed=4 + P.dropDelay,P.gameEnv.drop=3,3 + elseif D.wave==180 then + P:_showText(text.maxspeed,0,-140,100,'appear',.6) + P.dropDelay,P.gameEnv.drop=2,2 + end + P:shakeField(3) end - P.atkBufferSum=P.atkBufferSum+4 - P.stat.recv=P.stat.recv+4 - D.wave=D.wave+1 - D.rpm=math.floor(144e3/t)*.1 - if D.wave==60 then - P:_showText(text.great,0,-140,100,'appear',.6) - P.gameEnv.pushSpeed=3 - P.dropDelay,P.gameEnv.drop=4,4 - elseif D.wave==120 then - P:_showText(text.awesome,0,-140,100,'appear',.6) - P.gameEnv.pushSpeed=4 - P.dropDelay,P.gameEnv.drop=3,3 - elseif D.wave==180 then - P:_showText(text.maxspeed,0,-140,100,'appear',.6) - P.dropDelay,P.gameEnv.drop=2,2 - end - P:shakeField(3) end end end diff --git a/parts/eventsets/defender_n.lua b/parts/eventsets/defender_n.lua index 7d89786e9..a4a984e08 100644 --- a/parts/eventsets/defender_n.lua +++ b/parts/eventsets/defender_n.lua @@ -1,46 +1,48 @@ -return{ +return { drop=30,lock=60, fall=10, mesDisp=function(P) setFont(55) - mStr(P.modeData.wave,63,200) - mStr(P.modeData.rpm,63,320) + GC.mStr(P.modeData.wave,63,200) + GC.mStr(P.modeData.rpm,63,320) mText(TEXTOBJ.wave,63,260) mText(TEXTOBJ.rpm,63,380) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control then local D=P.modeData - D.counter=D.counter+1 - local t= - D.wave<=60 and 360-D.wave*3 or - D.wave<=120 and 180-(D.wave-60)*2 or - D.wave<=180 and 120-(D.wave-120)or - 60 - if D.counter>=t then - D.counter=0 - for _=1,3 do - table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(10)),amount=1,countdown=2*t,cd0=2*t,time=0,sent=false,lv=1}) + D.timer=D.timer+1 + if P.atkBufferSum<20 then + local t= + D.wave<=40 and 360-D.wave*4 or + D.wave<=80 and 200-(D.wave-40)*2 or + D.wave<=140 and 120-(D.wave-80) or + 60 + if D.timer>=t then + D.timer=0 + for _=1,3 do + table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(10)),amount=1,countdown=2*t,cd0=2*t,time=0,sent=false,lv=1}) + end + P.atkBufferSum=P.atkBufferSum+3 + P.stat.recv=P.stat.recv+3 + D.wave=D.wave+1 + D.rpm=math.floor(108e3/t)*.1 + if D.wave==60 then + P:_showText(text.great,0,-140,100,'appear',.6) + P.gameEnv.pushSpeed=2 + P.dropDelay,P.gameEnv.drop=20,20 + elseif D.wave==120 then + P:_showText(text.awesome,0,-140,100,'appear',.6) + P.gameEnv.pushSpeed=3 + P.dropDelay,P.gameEnv.drop=10,10 + elseif D.wave==180 then + P.dropDelay,P.gameEnv.drop=5,5 + P:_showText(text.maxspeed,0,-140,100,'appear',.6) + end + P:shakeField(3) end - P.atkBufferSum=P.atkBufferSum+3 - P.stat.recv=P.stat.recv+3 - D.wave=D.wave+1 - D.rpm=math.floor(108e3/t)*.1 - if D.wave==60 then - P:_showText(text.great,0,-140,100,'appear',.6) - P.gameEnv.pushSpeed=2 - P.dropDelay,P.gameEnv.drop=20,20 - elseif D.wave==120 then - P:_showText(text.awesome,0,-140,100,'appear',.6) - P.gameEnv.pushSpeed=3 - P.dropDelay,P.gameEnv.drop=10,10 - elseif D.wave==180 then - P.dropDelay,P.gameEnv.drop=5,5 - P:_showText(text.maxspeed,0,-140,100,'appear',.6) - end - P:shakeField(3) end end end diff --git a/parts/eventsets/dig_100l.lua b/parts/eventsets/dig_100l.lua index 5c2299ac4..9ec7f3b71 100644 --- a/parts/eventsets/dig_100l.lua +++ b/parts/eventsets/dig_100l.lua @@ -1,7 +1,7 @@ -return{ +return { mesDisp=function(P) setFont(55) - mStr(100-P.stat.dig,63,265) + GC.mStr(100-P.stat.dig,63,265) end, hook_drop=function(P) for _=1,math.min(10,100-P.stat.dig)-P.garbageBeneath do diff --git a/parts/eventsets/dig_10l.lua b/parts/eventsets/dig_10l.lua index eccb98545..c5aed4d88 100644 --- a/parts/eventsets/dig_10l.lua +++ b/parts/eventsets/dig_10l.lua @@ -1,7 +1,7 @@ -return{ +return { mesDisp=function(P) setFont(55) - mStr(10-P.stat.dig,63,265) + GC.mStr(10-P.stat.dig,63,265) end, hook_drop=function(P) if P.stat.dig==10 then diff --git a/parts/eventsets/dig_400l.lua b/parts/eventsets/dig_400l.lua index 1a56310df..23eb1cbc8 100644 --- a/parts/eventsets/dig_400l.lua +++ b/parts/eventsets/dig_400l.lua @@ -1,7 +1,7 @@ -return{ +return { mesDisp=function(P) setFont(55) - mStr(400-P.stat.dig,63,265) + GC.mStr(400-P.stat.dig,63,265) end, hook_drop=function(P) for _=1,math.min(10,400-P.stat.dig)-P.garbageBeneath do diff --git a/parts/eventsets/dig_40l.lua b/parts/eventsets/dig_40l.lua index 11c240408..8233b7575 100644 --- a/parts/eventsets/dig_40l.lua +++ b/parts/eventsets/dig_40l.lua @@ -1,7 +1,7 @@ -return{ +return { mesDisp=function(P) setFont(55) - mStr(40-P.stat.dig,63,265) + GC.mStr(40-P.stat.dig,63,265) end, hook_drop=function(P) for _=1,math.min(10,40-P.stat.dig)-P.garbageBeneath do diff --git a/parts/eventsets/dig_h.lua b/parts/eventsets/dig_h.lua index e040b141a..45cc0f674 100644 --- a/parts/eventsets/dig_h.lua +++ b/parts/eventsets/dig_h.lua @@ -1,16 +1,16 @@ -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.wave,63,310) + GC.mStr(P.modeData.wave,63,310) mText(TEXTOBJ.wave,63,375) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control then local D=P.modeData D.timer=D.timer+1 - if D.timer>=math.max(90,180-D.wave)then + if D.timer>=math.max(90,180-D.wave) then P:garbageRise(21,1,P:getHolePos()) P.stat.recv=P.stat.recv+1 D.timer=0 diff --git a/parts/eventsets/dig_u.lua b/parts/eventsets/dig_u.lua index 35bb49dbd..ac357a532 100644 --- a/parts/eventsets/dig_u.lua +++ b/parts/eventsets/dig_u.lua @@ -1,16 +1,16 @@ -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.wave,63,310) + GC.mStr(P.modeData.wave,63,310) mText(TEXTOBJ.wave,63,375) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control then local D=P.modeData D.timer=D.timer+1 - if D.timer>=math.max(30,80-.3*D.wave)then + if D.timer>=math.max(30,80-.3*D.wave) then P:garbageRise(20+D.wave%5,1,P:getHolePos()) P.stat.recv=P.stat.recv+1 D.timer=0 diff --git a/parts/eventsets/marathon_bfmax.lua b/parts/eventsets/marathon_bfmax.lua index 078c5b3fa..2873abbad 100644 --- a/parts/eventsets/marathon_bfmax.lua +++ b/parts/eventsets/marathon_bfmax.lua @@ -1,6 +1,6 @@ local dropSpeed={50,40,30,25,20,15,12,9,7,5,4,3,2,1,1,.5,.5,.25,.25} -return{ +return { drop=60, wait=8, fall=20, @@ -14,11 +14,11 @@ return{ hook_drop=function(P) local flag local l=P.lastPiece - if P.combo>1 then flag=true;P:showText("2x",0,-220,40,'flicker',.3)end - if l.spin then flag=true;P:showText("spin",0,-180,40,'flicker',.3)end - if l.row>1 then flag=true;P:showText("1+",0,-140,40,'flicker',.3)end - if l.hpc then flag=true;P:showText("HPC",0,-100,40,'flicker',.3)end - if l.pc then P:showText("PC",0,-90,100,'beat',.5)end + if P.combo>1 then flag=true;P:showText("2x",0,-220,40,'flicker',.3) end + if l.spin then flag=true;P:showText("spin",0,-180,40,'flicker',.3) end + if l.row>1 then flag=true;P:showText("1+",0,-140,40,'flicker',.3) end + if l.hpc then flag=true;P:showText("HPC",0,-100,40,'flicker',.3) end + if l.pc then P:showText("PC",0,-90,100,'beat',.5) end if flag then P:lose() else diff --git a/parts/eventsets/marathon_inf.lua b/parts/eventsets/marathon_inf.lua index 80e8fa129..d9f88cfb1 100644 --- a/parts/eventsets/marathon_inf.lua +++ b/parts/eventsets/marathon_inf.lua @@ -2,7 +2,7 @@ local dropSpeed={ 50,42,35,30,25,20,16,13,11,10, 9,8,7,6,5,5,4,4,3,3, 3,2,2,2,2,1,1,1,1,1, - .5,.5,.5,.5,.25,.25,.25,.125,.125,--Total 39 numbers, switch to 20G when reach 400 lines + .5,.5,.5,.5,.25,.25,.25,.125,.125,-- Total 39 numbers, switch to 20G when reach 400 lines } local lockDelay={ 57,54,51,48,46,44,42,40,38,36, @@ -17,7 +17,7 @@ local lockDelay={ 4,4,4,4,4,4,4,4,4,4, 3,3,3,3,3,3,3,3,3,3, 2,2,2,2,2,2,2,2,2,2, - 1,1,1,1,1,1,1,1,1,--Finish at 1700 + 1,1,1,1,1,1,1,1,1,-- Finish at 1700 } return diff --git a/parts/eventsets/master_ex.lua b/parts/eventsets/master_ex.lua index c3845c1b3..16f024571 100644 --- a/parts/eventsets/master_ex.lua +++ b/parts/eventsets/master_ex.lua @@ -1,8 +1,16 @@ -local gc=love.graphics local sectionName={"D","C","B","A","A+","S-","S","S+","S+","SS","SS","U","U","X","X+"} local passPoint=16 -return{ +local function getRollGoal(P) + -- get amount of grades needed for X+ + local rem=12.4-P.modeData.rankPoint/10 + if rem<=0 then return 0 end + local goal=math.floor(rem)*4 + rem=rem%1 + return goal+(rem>0.3 and 4 or rem*10) +end + +return { drop=0,lock=15, wait=15,fall=6, noTele=true, @@ -15,26 +23,27 @@ return{ mesDisp=function(P) local h=(3600-P.stat.frame)/10 if h>0 then - gc.setColor(1,1,1,.12) - gc.rectangle('fill',0,475-h,125,h,4) - gc.setColor(COLOR.Z) + GC.setColor(1,1,1,.12) + GC.rectangle('fill',0,475-h,125,h,4) + GC.setColor(COLOR.Z) end mText(TEXTOBJ.line,63,310) mText(TEXTOBJ.techrash,63,420) mText(TEXTOBJ.grade,63,180) setFont(20) - mStr(("%.1f"):format(P.modeData.rankPoint/10),63,208) + GC.mStr(("%.1f"):format(P.modeData.rankPoint/10),63,208) setFont(55) - mStr(P.modeData.rankName,63,125) + GC.mStr(P.modeData.rankName,63,125) setFont(75) - mStr(P.stat.row,63,230) - mStr(P.stat.clears[4],63,340) + GC.mStr(P.stat.row,63,230) + GC.mStr(P.stat.clears[4],63,340) + PLY.draw.drawTargetLine(P,getRollGoal(P)) end, hook_drop=function(P) - if P.modeData.rankPoint<140-passPoint then--If Less then X + if P.modeData.rankPoint<140-passPoint then-- If Less then X local R=#P.clearedRow if R>0 then - if R==4 then R=10 end--Techrash +10 + if R==4 then R=10 end-- Techrash +10 P.modeData.rankPoint=math.min(P.modeData.rankPoint+R,140-passPoint) P.modeData.rankName=sectionName[math.floor(P.modeData.rankPoint/10)+1] end @@ -44,7 +53,7 @@ return{ P.modeData.rankPoint=0 P.modeData.rankName=sectionName[1] while true do - YIELD() + coroutine.yield() if P.stat.frame>=3600 then P.modeData.rankPoint=math.min(P.modeData.rankPoint+passPoint,140) P.modeData.rankName=sectionName[math.floor(P.modeData.rankPoint/10)+1] diff --git a/parts/eventsets/master_final.lua b/parts/eventsets/master_final.lua index b6ad08a79..b8fdbbd6f 100644 --- a/parts/eventsets/master_final.lua +++ b/parts/eventsets/master_final.lua @@ -1,4 +1,4 @@ -return{ +return { drop=0,lock=12, wait=10,fall=10, noTele=true, @@ -21,18 +21,18 @@ return{ if D.pt%100==99 then SFX.play('warn_1') - elseif D.pt>=D.target then--Level up! - s=D.target/100--range from 1 to 9 + elseif D.pt>=D.target then-- Level up! + s=D.target/100-- range from 1 to 9 local E=P.gameEnv if s<4 then P:stageComplete(s) - --First 300 + -- First 300 if s~=1 then E.lock=E.lock-1 end if s~=2 then E.wait=E.wait-1 end if s~=3 then E.fall=E.fall-1 end D.target=D.target+100 elseif s<10 then - if s==5 then BGM.play('distortion')end + if s==5 then BGM.play('distortion') end P:stageComplete(s) if s==4 or s==7 then E.das=E.das-1 end if s%3==0 then E.lock=E.lock-1 diff --git a/parts/eventsets/master_g.lua b/parts/eventsets/master_g.lua new file mode 100644 index 000000000..9b711325c --- /dev/null +++ b/parts/eventsets/master_g.lua @@ -0,0 +1,344 @@ +local regretDelay=-1 +local int_grade=0 +local grade_points=0 +local int_grade_boosts={0,1,2,3,4,5,5,6,6,7,7,7,8,8,8,9,9,9,10,11,12,12,12,13,13,14,14,15,15,16,16,17,17,18,18,19,19,20,20,21,21,22,22,23,23,24,24,25,25,26} +local coolList={false,false,false,false,false,false,false,false,false} +local regretList={false,false,false,false,false,false,false,false,false,false} +local gradeList={ + "9","8","7","6","5","4","3","2","1", + "S1","S2","S3","S4","S5","S6","S7","S8","S9", + "m1","m2","m3","m4","m5","m6","m7","m8","m9", + "M","MK","MV","MO","MM-","MM","MM+","GM-","GM","GM+","TM-","TM","TM+" +} +local spd_lvl=0 +local cools=0 +local regrets=0 +local prevSectTime=0 +local isInRoll=false +local rollGrades=0 +local cool_time={3120,3120,2940,2700,2700,2520,2520,2280,2280,0} +local reg_time= {5400,4500,4500,4080,3600,3600,3000,3000,3000,3000} +local prevDrop70=false -- determines if previous piece has level less than __70 +local nextSpeedUp=false -- determines if the next section speed should be boosted by 100 +local isInRollTrans=false +local function getGrav(l) + return + l<30 and 64 or + l<35 and 43 or + l<40 and 32 or + l<50 and 26 or + l<60 and 21 or + l<70 and 16 or + l<80 and 8 or + l<90 and 6 or + l<120 and 4 or + l<160 and 3 or + l<200 and 2 or + l<220 and 64 or + l<230 and 8 or + l<233 and 4 or + l<236 and 3 or + l<243 and 2 or + l<300 and 1 or + l<360 and 0.5 or + l<450 and 0.25 or + 0 +end +local function getLock(l) + return + l<900 and 30 or + l<1100 and 19 or + 15 +end +local function getWait(l) + return + l<700 and 23 or + l<800 and 16 or + l<1000 and 12 or + l<1100 and 7 or + 6 +end +local function getFall(l) + return + l<500 and 25 or + l<600 and 18 or + l<700 and 12 or + l<800 and 8 or + 4 +end +local function getDas(l) + return + l<500 and 10 or + l<900 and 8 or + 6 +end +local function getGrade() + if int_grade==nil then int_grade=0 end + if rollGrades==nil then rollGrades=0 end + return gradeList[math.max(math.min(math.floor(int_grade_boosts[math.min(int_grade+1,#int_grade_boosts)]+rollGrades+cools+1-regrets),#gradeList),1)] +end +local function addGrade(row, cmb, lvl) -- IGS = internal grade system + if row<1 then return end + local pts=0 + local cmb_mult=1.0 + local lvl_mult=math.floor(lvl/250)+1 + + if row==1 then + pts=int_grade<5 and 10 or int_grade<10 and 5 or 2 + cmb_mult=1.0 + elseif row==2 then + pts=int_grade<3 and 20 or int_grade<6 and 15 or int_grade<10 and 10 or 12 + cmb_mult=cmb==1 and 1 or cmb<4 and 1.2 or cmb<8 and 1.4 or cmb<10 and 1.5 or 2.0 + elseif row==3 then + pts=int_grade==0 and 40 or int_grade<4 and 30 or int_grade<7 and 20 or int_grade<10 and 15 or 13 + cmb_mult=cmb==1 and 1 or cmb<10 and 1+(cmb+2)*0.1 or 2 + else + pts=int_grade==0 and 50 or int_grade<5 and 40 or 30 + cmb_mult=cmb==1 and 1 or cmb==2 and 1.5 or cmb<6 and (0.2*cmb)+1.2 or cmb<10 and (0.1*cmb)+1.7 or 3 + end + + grade_points=grade_points+(pts*cmb_mult*lvl_mult) + if grade_points>=100 then + grade_points=0 + int_grade=int_grade+1 + end +end +local function getRollGoal() + -- get amount of grades needed for TM+ + local rem=#gradeList-(int_grade_boosts[math.min(int_grade+1,#int_grade_boosts)]+rollGrades+cools+1-regrets) + if rem<=0 then return 0 end + local goal=0 + if cools>8 then + goal=math.floor(rem)*4 + rem=rem%1 + return goal+(rem>0.3 and 4 or rem*10) + else + goal=math.floor(rem/0.26)*4 + rem=rem%0.26 + return goal+(rem>0.12 and 4 or rem*25) + end +end + +return { + drop=64, + lock=30, + wait=23, + fall=25, + keyCancel={10,11,12,14,15,16,17,18,19,20}, + das=16,arr=1, + minsdarr=1, + ihs=true,irs=true,ims=false, + mesDisp=function(P) + GC.setColor(1,1,1,1) + setFont(45) + mText(TEXTOBJ.grade,63,180) + setFont(60) + GC.mStr(getGrade(),63,110) -- draw grade + for i=1,10 do -- draw cool/regret history + if not (coolList[i] or regretList[i]) then -- neither cool nor regret + GC.setColor(0.6,0.6,0.6,P.modeData.pt<(i-1)*100 and 0.25 or 0.6) + else + GC.setColor(regretList[i] and 1 or 0, coolList[i] and 1 or 0, 0, 1) + end + GC.circle('fill',-10,150+i*25,10) + GC.setColor(1,1,1,1) + end + if isInRoll then + setFont(20) + GC.mStr(("%.1f"):format(rollGrades),63,208) -- draw roll grades + GC.setLineWidth(2) + GC.setColor(.98,.98,.98,.8) + GC.rectangle('line',0,240,126,80,4) + GC.setColor(.98,.98,.98,.4) + GC.rectangle('fill',0+2,240+2,126-4,80-4,2) -- draw time box + setFont(45) + local t=(P.stat.frame-prevSectTime)/60 + local T=("%.1f"):format(60-t) + GC.setColor(COLOR.dH) + GC.mStr(T,65,250) -- draw time + t=t/60 + GC.setColor(1.7*t,2.3-2*t,.3) + GC.mStr(T,63,248) + PLY.draw.drawTargetLine(P,getRollGoal()) + else + -- draw level counter + setFont(20) + GC.mStr(grade_points,63,208) + setFont(45) + if coolList[math.ceil(P.modeData.pt/100+0.01)] then + GC.setColor(0,1,0,1) + elseif P.stat.frame-prevSectTime > cool_time[math.ceil(P.modeData.pt/100+0.01)] then + GC.setColor(0.7,0.7,0.7,1) + end + if coolList[math.ceil(P.modeData.pt/100+0.01)] and regretList[math.ceil(P.modeData.pt/100+0.01)] then + GC.setColor(1,1,0,1) + elseif regretList[math.ceil(P.modeData.pt/100+0.01)] then + GC.setColor(1,0,0,1) + end + PLY.draw.drawProgress(P.modeData.pt,P.modeData.target) + end + end, + hook_drop=function(P) + local D=P.modeData + + local c=#P.clearedRow + + if cools>8 and isInRoll then + rollGrades=rollGrades+(c==4 and 1 or 0.1*c) + return + elseif isInRoll then + rollGrades=rollGrades+(c==4 and 0.26 or 0.04*c) + return + end + + if c==0 and D.pt+1>=D.target then return end + local s=c<3 and c+1 or c==3 and 5 or 7 + if P.combo>7 then s=s+2 + elseif P.combo>3 then s=s+1 + end + + addGrade(c,P.combo,D.pt) + + D.pt=D.pt+s + spd_lvl=spd_lvl+1 + + P.gameEnv.drop=getGrav(spd_lvl) + + if (P.gameEnv.drop==0) then + P:set20G(true) + end + + if D.pt%100>70 and not prevDrop70 then + if P.stat.frame-prevSectTime < cool_time[math.ceil(D.pt/100)] then + cools=cools+1 + coolList[math.ceil(D.pt/100)]=true + P:_showText("COOL!",0,-120,80,'fly',.8) + nextSpeedUp=true + end + prevDrop70=true + end + + if D.pt+1==D.target then + SFX.play('warn_1') + elseif D.pt>=D.target then-- Level up! + spd_lvl=nextSpeedUp and spd_lvl+100 or spd_lvl + nextSpeedUp=false + prevDrop70=false + s=D.target/100 + local E=P.gameEnv + E.lock=getLock(spd_lvl) + E.wait=getWait(spd_lvl) + E.fall=getFall(spd_lvl) + E.das=getDas(spd_lvl) + + if P.stat.frame-prevSectTime > reg_time[math.ceil(s)] then + regrets=regrets+1 + regretDelay=60 + end + prevSectTime=P.stat.frame + if s==2 then + BG.set('rainbow') + elseif s==4 then + BG.set('rainbow2') + elseif s==5 then + if P.stat.frame>420*60 then + D.pt=500 + P:win('finish') + return + else + BG.set('glow') + BGM.play('secret7th remix') + end + elseif s==6 then + BG.set('lightning') + elseif s>9 then + if cools>8 then + if E.lockFX and E.lockFX>1 then E.lockFX=1 end + P:setInvisible(5) + else + P:setInvisible(300) + end + D.pt=999 + P.waiting=240 + BGM.stop() + isInRollTrans=true + return + end + D.target=D.target<900 and D.target+100 or 999 + P:stageComplete(s) + SFX.play('reach') + end + end, + task=function(P) + regretDelay=-1 + P.modeData.pt=0 + P.modeData.target=100 + int_grade=0 + grade_points=0 + rollGrades=0 + spd_lvl=0 + cools=0 + regrets=0 + prevSectTime=0 + isInRoll=false + isInRollTrans=false + prevDrop70=false + nextSpeedUp=false + coolList={false,false,false,false,false,false,false,false,false} + regretList={false,false,false,false,false,false,false,false,false,false} + local decayRate={125,80,80,50,45,45,45,40,40,40,40,40,30,30,30,20,20,20,20,20,15,15,15,15,15,15,15,15,15,15,10,10,10,9,9,9,8,8,8,7,7,7,6} + local decayTimer=0 + while true do + coroutine.yield() + P.modeData.grade=getGrade() + P.modeData.gradePts=math.max(math.min(math.floor(int_grade_boosts[math.min(int_grade+1,#int_grade_boosts)]+rollGrades+cools+1-regrets),#gradeList),1) + if P.stat.frame-prevSectTime > reg_time[math.ceil(P.modeData.pt/100+0.01)] and not (isInRoll or isInRollTrans) then + regretList[math.ceil(P.modeData.pt/100)]=true + end + if regretDelay>-1 then + regretDelay=regretDelay-1 + if regretDelay==-1 then P:_showText("REGRET!!",0,-120,80,'beat',.8) end + end + if isInRollTrans then + if P.waiting>=220 then + -- Make field invisible + for y=1,#P.field do for x=1,10 do + P.visTime[y][x]=P.waiting-220 + end end + elseif P.waiting==190 then + TABLE.cut(P.field) + TABLE.cut(P.visTime) + elseif P.waiting==180 then + playReadySFX(3,3) + P:_showText("3",0,-120,120,'fly',1) + elseif P.waiting==120 then + playReadySFX(2,1) + P:_showText("2",0,-120,120,'fly',1) + elseif P.waiting==60 then + playReadySFX(1,1) + P:_showText("1",0,-120,120,'fly',1) + elseif P.waiting==1 then + playReadySFX(0,1) + isInRollTrans=false + isInRoll=true + BGM.play('hope') + BG.set('blockspace') + prevSectTime=P.stat.frame + end + end + if P.waiting<=0 and grade_points>0 and not isInRoll then + decayTimer=decayTimer+1 + if decayTimer>=decayRate[math.min(int_grade+1,#decayRate)] then + decayTimer=0 + grade_points=grade_points-1 + end + elseif isInRoll and P.stat.frame>=prevSectTime+3599 then + rollGrades=rollGrades+(cools>8 and 1.6 or 0.5) + P.modeData.grade=getGrade() + P.modeData.gradePts=math.min(math.floor(int_grade_boosts[math.min(int_grade+1,#int_grade_boosts)]+rollGrades+cools+1-regrets),#gradeList) + coroutine.yield() + P:win('finish') + end + end + end, +} diff --git a/parts/eventsets/master_h.lua b/parts/eventsets/master_h.lua index 8934830a0..d141f8dc0 100644 --- a/parts/eventsets/master_h.lua +++ b/parts/eventsets/master_h.lua @@ -2,7 +2,7 @@ local death_lock={12,11,10,9,8, 8,8,7,7,6} local death_wait={10,9, 8, 7,6, 7,6,6,5,5} local death_fall={10,9, 8, 7,6, 7,6,5,5,5} -return{ +return { drop=0, lock=death_lock[1], wait=death_wait[1], @@ -25,7 +25,7 @@ return{ if D.pt%100==99 then SFX.play('warn_1') - elseif D.pt>=D.target then--Level up! + elseif D.pt>=D.target then-- Level up! s=D.target/100 local E=P.gameEnv E.lock=death_lock[s] diff --git a/parts/eventsets/master_instinct.lua b/parts/eventsets/master_instinct.lua index d0588c2c5..053e786ce 100644 --- a/parts/eventsets/master_instinct.lua +++ b/parts/eventsets/master_instinct.lua @@ -5,7 +5,7 @@ local inv_hide={20,17,14,11, 8, 5, 3, 2, 1, 0} local hidetimer=0 local held=false -return{ +return { drop=0, lock=inv_lock[1], wait=inv_wait[1], @@ -20,7 +20,13 @@ return{ local D=P.modeData local c=#P.clearedRow - if c==0 and D.pt%100==99 then return end + if c==0 and D.pt%100==99 then + if D.pt<1000 then + hidetimer=0-inv_wait[(P.modeData.pt/100-(P.modeData.pt%100)/100)+1] + if c>0 then hidetimer=hidetimer-inv_fall[(P.modeData.pt/100-(P.modeData.pt%100)/100)+1] end + end + return + end local s=c<3 and c+1 or c==3 and 5 or 7 if P.combo>7 then s=s+2 elseif P.combo>3 then s=s+1 @@ -29,12 +35,12 @@ return{ held=false if D.pt<1000 then hidetimer=0-inv_wait[(P.modeData.pt/100-(P.modeData.pt%100)/100)+1] - if c>0 then hidetimer=hidetimer-inv_fall[(P.modeData.pt/100-(P.modeData.pt%100)/100)+1]end + if c>0 then hidetimer=hidetimer-inv_fall[(P.modeData.pt/100-(P.modeData.pt%100)/100)+1] end end if D.pt%100==99 then SFX.play('warn_1') - elseif D.pt>=D.target then--Level up! + elseif D.pt>=D.target then-- Level up! s=D.target/100 local E=P.gameEnv E.lock=inv_lock[s] @@ -50,6 +56,8 @@ return{ elseif s==7 then E.das=6 BGM.play('far') + elseif s==8 then + BG.set('none') elseif s==10 then D.pt=1000 P:win('finish') @@ -64,13 +72,13 @@ return{ P.modeData.pt=0 P.modeData.target=100 while true do - YIELD() + coroutine.yield() if P.holdTime==0 and P.waiting<=0 and not held then hidetimer=0 held=true end hidetimer=hidetimer+1 - if hidetimer>inv_hide[(P.modeData.pt/100-(P.modeData.pt%100)/100)+1]then + if hidetimer>inv_hide[(P.modeData.pt/100-(P.modeData.pt%100)/100)+1] then P.gameEnv.block=false else P.gameEnv.block=true diff --git a/parts/eventsets/master_n.lua b/parts/eventsets/master_n.lua index ef573852c..3379f52c3 100644 --- a/parts/eventsets/master_n.lua +++ b/parts/eventsets/master_n.lua @@ -2,7 +2,7 @@ local rush_lock={20,18,16,15,14, 14,13,12,11,11} local rush_wait={12,11,11,10,10, 10,10, 9, 9, 9} local rush_fall={18,16,14,13,12, 12,11,11,10,10} -return{ +return { drop=0, lock=rush_lock[1], wait=rush_wait[1], @@ -25,7 +25,7 @@ return{ if D.pt%100==99 then SFX.play('warn_1') - elseif D.pt>=D.target then--Level up! + elseif D.pt>=D.target then-- Level up! s=D.target/100 local E=P.gameEnv E.lock=rush_lock[s] diff --git a/parts/eventsets/master_ph.lua b/parts/eventsets/master_ph.lua index 917259290..0fc304f0a 100644 --- a/parts/eventsets/master_ph.lua +++ b/parts/eventsets/master_ph.lua @@ -18,9 +18,9 @@ return if p>=P.modeData.target then local ENV=P.gameEnv local T=P.modeData.target - --Stage 1: clear 3 techrash - if T==12 then--Stage 2: swap color of S/Z & J/L - P:stageComplete(2) + -- Stage 1: clear 3 techrash + if T==12 then-- Stage 2: swap color of S/Z & J/L + P:stageComplete(1) P.waiting=30 P.curMission=false @@ -34,9 +34,9 @@ return P.modeData.target=26 SFX.play('reach') - elseif T==26 then--Stage 3: dig to bottom - P:stageComplete(3) - if not P.holdQueue[1]then--1 up if ban hold + elseif T==26 then-- Stage 3: dig to bottom + P:stageComplete(2) + if not P.holdQueue[1] then-- 1 up if ban hold P.life=P.life+1 end P.waiting=45 @@ -44,7 +44,7 @@ return ENV.skin[3],ENV.skin[4]=ENV.skin[4],ENV.skin[3] for i=1,10 do - if P.field[i]then + if P.field[i] then for j=1,10 do if P.field[i][j]>0 then P.field[i][j]=17 @@ -79,9 +79,9 @@ return P.modeData.target=42 SFX.play('reach') - elseif T==42 then--Stage 4: survive in high speed + elseif T==42 then-- Stage 4: survive in high speed if P.garbageBeneath==0 then - P:stageComplete(4) + P:stageComplete(3) P.waiting=30 ENV.lock=11 P:setNext(6) @@ -93,8 +93,8 @@ return else p=41 end - elseif T==62 then--Stage 5: survive without easy-fresh rule - P:stageComplete(5) + elseif T==62 then-- Stage 5: survive without easy-fresh rule + P:stageComplete(4) P.life=P.life+1 ENV.lock=13 ENV.wait=5 @@ -104,8 +104,8 @@ return P.modeData.target=126 SFX.play('reach') - elseif T==126 then--Stage 6: speed up - P:stageComplete(6) + elseif T==126 then-- Stage 6: speed up + P:stageComplete(5) P.life=P.life+1 ENV.lock=11 @@ -114,8 +114,8 @@ return P.modeData.target=162 SFX.play('reach') - elseif T==162 then--Stage 7: speed up+++ - P:stageComplete(7) + elseif T==162 then-- Stage 7: speed up+++ + P:stageComplete(6) P.life=P.life+1 ENV.lock=10 @@ -125,8 +125,8 @@ return P.modeData.target=226 SFX.play('reach') - elseif T==226 then--Stage 8: final invisible - P:stageComplete(8) + elseif T==226 then-- Stage 8: final invisible + P:stageComplete(7) P.life=P.life+1 ENV.bone=false @@ -134,10 +134,10 @@ return P.modeData.target=259 SFX.play('reach') - elseif T==259 then--Stage 9: ending - P:stageComplete(9) + elseif T==259 then-- Stage 9: ending + P:stageComplete(8) P.life=P.life+1 - for i=1,7 do ENV.skin[i]=P.holeRND:random(16)end + for i=1,7 do ENV.skin[i]=P.holeRND:random(16) end P:setInvisible(40) ENV.lock=15 diff --git a/parts/eventsets/pc_inf.lua b/parts/eventsets/pc_inf.lua index 78b8f07ae..e5bef0112 100644 --- a/parts/eventsets/pc_inf.lua +++ b/parts/eventsets/pc_inf.lua @@ -1,12 +1,12 @@ -return{ +return { heightLimit=4, mesDisp=function(P) setFont(60) - mStr(P.stat.pc,63,340) + GC.mStr(P.stat.pc,63,340) mText(TEXTOBJ.pc,63,410) end, hook_drop=function(P) - if P.lastPiece.pc and P.stat.row%4==0 then + if P.lastPiece.pc then P.gameEnv.heightLimit=4 if P.stat.pc%5==0 then P.gameEnv.drop=math.max(P.gameEnv.drop-1,1) diff --git a/parts/eventsets/pctrain_l.lua b/parts/eventsets/pctrain_l.lua index 2e83cf720..871999341 100644 --- a/parts/eventsets/pctrain_l.lua +++ b/parts/eventsets/pctrain_l.lua @@ -11,7 +11,7 @@ local function task_PC(P) P:pushNextList(L,symmetry) P.control=false - if P.frameRun>180 then for _=1,26 do YIELD()end end + if P.frameRun>180 then for _=1,26 do coroutine.yield() end end P.control=true local base=PCbase[difficulty] @@ -31,9 +31,9 @@ local function _check(P) if P.stat.pc%4==0 and P.stat.pc>0 and P.stat.pc<=40 then local s=P.stat.pc/4 - P.gameEnv.drop=pc_drop[s]or 10 - P.gameEnv.lock=pc_lock[s]or 25 - P.gameEnv.fall=pc_fall[s]or 4 + P.gameEnv.drop=pc_drop[s] or 10 + P.gameEnv.lock=pc_lock[s] or 25 + P.gameEnv.fall=pc_fall[s] or 4 if s==10 then P:_showText(text.maxspeed,0,-140,100,'appear',.6) end @@ -41,14 +41,14 @@ local function _check(P) end end end -return{ +return { sequence='none', RS="SRS", mesDisp=function(P) setFont(60) - mStr(P.stat.pc,63,260) + GC.mStr(P.stat.pc,63,260) mText(TEXTOBJ.pc,63,330) end, hook_drop=_check, - task=_check,--Just run one time at first to start first level + task=_check,-- Just run one time at first to start first level } diff --git a/parts/eventsets/pctrain_n.lua b/parts/eventsets/pctrain_n.lua index a925725ba..cfeac90e0 100644 --- a/parts/eventsets/pctrain_n.lua +++ b/parts/eventsets/pctrain_n.lua @@ -8,13 +8,13 @@ local PCtype={ 1,2,3, } local function task_PC(P) - local difficulty=PCtype[P.stat.pc+1]or 3 + local difficulty=PCtype[P.stat.pc+1] or 3 local L=PClist[difficulty][P.holeRND:random(#PClist[difficulty])] local symmetry=P.holeRND:random()>.5 P:pushNextList(L,symmetry) P.control=false - if P.frameRun>180 then for _=1,26 do YIELD()end end + if P.frameRun>180 then for _=1,26 do coroutine.yield() end end P.control=true local base=PCbase[difficulty] @@ -34,14 +34,14 @@ local function _check(P) end end end -return{ +return { sequence='none', RS="SRS", mesDisp=function(P) setFont(60) - mStr(P.stat.pc,63,260) + GC.mStr(P.stat.pc,63,260) mText(TEXTOBJ.pc,63,330) end, hook_drop=_check, - task=_check,--Just run one time at first to start first level + task=_check,-- Just run one time at first to start first level } diff --git a/parts/eventsets/royale.lua b/parts/eventsets/royale.lua index fae53599c..71922b573 100644 --- a/parts/eventsets/royale.lua +++ b/parts/eventsets/royale.lua @@ -1,10 +1,4 @@ -local gc=love.graphics -local gc_draw,gc_print,gc_setColor=gc.draw,gc.print,gc.setColor -local setFont=setFont - -local PLAYERS,PLY_ALIVE=PLAYERS,PLY_ALIVE - -return{ +return { layout='royale', fkey1=function(P) P:changeAtkMode(P.atkMode<3 and P.atkMode+2 or 5-P.atkMode) @@ -12,20 +6,20 @@ return{ end, mesDisp=function(P) setFont(35) - mStr(#PLY_ALIVE.."/"..#PLAYERS,63,175) - mStr(P.modeData.ko,80,215) - gc_draw(TEXTOBJ.ko,60-TEXTOBJ.ko:getWidth(),222) + GC.mStr(#PLY_ALIVE.."/"..#PLAYERS,63,175) + GC.mStr(P.modeData.ko,80,215) + GC.draw(TEXTOBJ.ko,60-TEXTOBJ.ko:getWidth(),222) setFont(20) - gc_setColor(1,.5,0,.6) - gc_print(P.badge,103,227) - gc_setColor(.97,.97,.97) + GC.setColor(1,.5,0,.6) + GC.print(P.badge,103,227) + GC.setColor(.97,.97,.97) setFont(25) - mStr(text.powerUp[P.strength],63,290) - gc_setColor(1,1,1) + GC.mStr(text.powerUp[P.strength],63,290) + GC.setColor(1,1,1) for i=1,P.strength do - gc_draw(IMG.badgeIcon,16*i+6,260) + GC.draw(IMG.badgeIcon,16*i+6,260) end end, } diff --git a/parts/eventsets/secret_grade.lua b/parts/eventsets/secret_grade.lua new file mode 100644 index 000000000..b93f44fcb --- /dev/null +++ b/parts/eventsets/secret_grade.lua @@ -0,0 +1,92 @@ +local gc_setColor,gc_draw=love.graphics.setColor,love.graphics.draw +local ply_applyField=PLY.draw.applyField +local function getOpenHole(num) + return -math.abs(((num-1) % 18)-9)+10 +end +local F={} + +-- local ranks={"10","9","8","7","6","5","4","3","2","1","S1","S2","S3","S4","S5","S6","S7","S8","S9","GM","GM+","TM","TM+","TM+₂","TM+₃", "TM+₄","TM+₅"} +-- lines: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 + +local function getSmallNum(num) + local smalldigit={[0]="₀","₁","₂","₃","₄","₅","₆","₇","₈","₉"} + local str=tostring(num) + local out="" + for i=1,#str do + out=out..smalldigit[tonumber(string.sub(str,i,i))] + end + return out +end + +local function getRank(index) + if index<11 then -- rank 10 - 1 + return tostring(11-index) + elseif index<20 then -- S1 - S9 ranks + return "S"..index-10 + elseif index<24 then -- GM, GM+, TM, TM+ ranks + local r={"GM","GM+","TM","TM+"} + return r[index-19] + else + return "TM+"..getSmallNum(index-22) + end +end + +local function generateGuide(num) + local l=#F + if l>num then + return + end + for i=l,num do + F[i] = {} + local h=getOpenHole(i) + for j=1,10 do + F[i][j]=h==j and -1 or 21 + end + end +end + +return { + fkey1=function(P) P.modeData.showGuide=not P.modeData.showGuide end, + mesDisp=function(P) + mText(TEXTOBJ.grade,63,190) + mText(TEXTOBJ.line,63,310) + setFont(55) + GC.mStr(getRank(P.modeData.rankPts),63,125) + GC.mStr(P.modeData.rankPts-1,63,245) + ply_applyField(P) + local mark=TEXTURE.puzzleMark + gc_setColor(1,1,1) + if P.modeData.showGuide then + for y=1,P.modeData.rankPts+1 do for x=1,10 do + local T=F[y][x] + if T~=0 then + gc_draw(mark[T],30*x-30,600-30*y) + end + end end + end + PLY.draw.cancelField() + end, + task=function(P) + P.modeData.rankPts=1 + P.modeData.showGuide=true + generateGuide(10) + end, + hook_drop=function(P) + local D=P.modeData + D.rankPts=1 + for i=1,#P.field do + local h=getOpenHole(i) + local flag + for j=1,10 do + if P.field[i][j]>0 and h==j then flag=true break end-- goto post_pts_calc + if P.field[i][j]==0 and h~=j then flag=true break end-- goto post_pts_calc + end + if flag then break end + if i==#P.field then break end-- goto post_pts_calc + if P.field[i+1][h]==0 then break end-- goto post_pts_calc + D.rankPts=D.rankPts+1 + end + -- ::post_pts_calc:: + generateGuide(D.rankPts+20) + end +} diff --git a/parts/eventsets/sprintEff_40.lua b/parts/eventsets/sprintEff_40.lua index 09d76a226..412e8e6e2 100644 --- a/parts/eventsets/sprintEff_40.lua +++ b/parts/eventsets/sprintEff_40.lua @@ -1,15 +1,15 @@ -return{ +return { mesDisp=function(P) setFont(45) - mStr(("%.1f"):format(P.stat.atk),63,270) + GC.mStr(("%d"):format(P.stat.atk),63,270) mText(TEXTOBJ.atk,63,323) - mStr(("%.2f"):format(P.stat.atk/P.stat.row),63,370) + GC.mStr(("%.2f"):format(P.stat.atk/P.stat.row),63,370) mText(TEXTOBJ.eff,63,423) setFont(55) local r=40-P.stat.row if r<0 then r=0 end - mStr(r,63,170) + GC.mStr(r,63,170) PLY.draw.drawTargetLine(P,r) end, hook_drop=function(P) diff --git a/parts/eventsets/sprintMD.lua b/parts/eventsets/sprintMD.lua index 0c18a7e1a..55793cebc 100644 --- a/parts/eventsets/sprintMD.lua +++ b/parts/eventsets/sprintMD.lua @@ -1,24 +1,24 @@ -return{ +return { mesDisp=function(P) setFont(55) local r=40-P.stat.row if r<0 then r=0 end - mStr(r,63,265) + GC.mStr(r,63,265) PLY.draw.drawTargetLine(P,r) end, task=function(P) - YIELD() + coroutine.yield() while true do - for _=1,P.holeRND:random(40,200)do YIELD()end + for _=1,P.holeRND:random(40,200) do coroutine.yield() end local r=P.holeRND:random(7) if r==1 then - if P.cur and not P:ifoverlap(P.cur.bk,P.curX-1,P.curY)then + if P.cur and not P:ifoverlap(P.cur.bk,P.curX-1,P.curY) then P:createMoveFX('left') P.curX=P.curX-1 P:freshBlock('move') end elseif r==2 then - if P.cur and not P:ifoverlap(P.cur.bk,P.curX-1,P.curY)then + if P.cur and not P:ifoverlap(P.cur.bk,P.curX-1,P.curY) then P:createMoveFX('left') P.curX=P.curX-1 P:freshBlock('move') diff --git a/parts/eventsets/sprintSym.lua b/parts/eventsets/sprintSym.lua index 2457a189a..afe90dfc4 100644 --- a/parts/eventsets/sprintSym.lua +++ b/parts/eventsets/sprintSym.lua @@ -1,7 +1,7 @@ local oppo={ [1]=7,[7]=1,[11]=3,[3]=11,[14]=14,[4]=4,[9]=9, } -return{ +return { skin={ 1,7,11,3,14,4,9, 1,7,2,6,10,2,13,5,9,15,10,11,3,12,2,16,8,4, @@ -11,7 +11,7 @@ return{ setFont(55) local r=40-P.stat.row if r<0 then r=0 end - mStr(r,63,265) + GC.mStr(r,63,265) PLY.draw.drawTargetLine(P,r) end, hook_drop=function(P) @@ -19,7 +19,7 @@ return{ for y=1,#F do local l=F[y] for x=1,5 do - if l[x]>0 and l[11-x]>0 and oppo[l[x]]~=l[11-x]then + if l[x]>0 and l[11-x]>0 and oppo[l[x]]~=l[11-x] then P:lose() return end diff --git a/parts/eventsets/stack_e.lua b/parts/eventsets/stack_e.lua index a7ceed5e4..155a71db9 100644 --- a/parts/eventsets/stack_e.lua +++ b/parts/eventsets/stack_e.lua @@ -1,22 +1,32 @@ -return{ +return { fieldH=20, fillClear=false, mesDisp=function(P) setFont(60) - mStr(P.stat.row,63,280) + GC.mStr(P.stat.row,63,280) mText(TEXTOBJ.line,63,350) PLY.draw.drawMarkLine(P,20,.3,1,1,TIME()%.42<.21 and .95 or .6) end, hook_die=function(P) local cc=P:clearFilledLines(P.garbageBeneath+1,#P.field-P.garbageBeneath) if cc>0 then - local h=20-cc-P.garbageBeneath - if h>0 then - P:garbageRise(21,h,2e10-1) + local clearH=cc+P.garbageBeneath + if clearH<20 then + P:garbageRise(21,20-clearH,2e10-1) if P.garbageBeneath>=20 then P:lose() end + elseif P.garbageBeneath>0 and clearH>20 then + local bonus=math.min(P.garbageBeneath,clearH-20) + if bonus>0 then + for _=1,bonus do + LINE.discard(table.remove(P.field,1)) + LINE.discard(table.remove(P.visTime,1)) + end + P.garbageBeneath=P.garbageBeneath-bonus + end end + P:freshBlock('push') end end, } \ No newline at end of file diff --git a/parts/eventsets/stack_u.lua b/parts/eventsets/stack_u.lua index 7f08bd9df..c04a389f1 100644 --- a/parts/eventsets/stack_u.lua +++ b/parts/eventsets/stack_u.lua @@ -1,22 +1,32 @@ -return{ +return { fieldH=21, fillClear=false, mesDisp=function(P) setFont(60) - mStr(P.stat.row,63,280) + GC.mStr(P.stat.row,63,280) mText(TEXTOBJ.line,63,350) PLY.draw.drawMarkLine(P,17,.3,1,1,TIME()%.42<.21 and .95 or .6) end, hook_die=function(P) local cc=P:clearFilledLines(P.garbageBeneath+1,#P.field-P.garbageBeneath) if cc>0 then - local h=20-cc-P.garbageBeneath-3 - if h>0 then - P:garbageRise(21,h,2e10-1) - if P.garbageBeneath>=20 then + local clearH=cc+P.garbageBeneath + if clearH<17 then + P:garbageRise(21,17-clearH,2e10-1) + if P.garbageBeneath>=17 then P:lose() end + elseif P.garbageBeneath>0 and clearH>17 then + local bonus=math.min(P.garbageBeneath,clearH-17) + if bonus>0 then + for _=1,bonus do + LINE.discard(table.remove(P.field,1)) + LINE.discard(table.remove(P.visTime,1)) + end + P.garbageBeneath=P.garbageBeneath-bonus + end end + P:freshBlock('push') end end, } \ No newline at end of file diff --git a/parts/eventsets/survivor_e.lua b/parts/eventsets/survivor_e.lua index 0abdad615..ec098e09e 100644 --- a/parts/eventsets/survivor_e.lua +++ b/parts/eventsets/survivor_e.lua @@ -1,16 +1,16 @@ -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.wave,63,310) + GC.mStr(P.modeData.wave,63,310) mText(TEXTOBJ.wave,63,375) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control then local D=P.modeData D.timer=D.timer+1 - if D.timer>=math.max(60,150-2*D.wave)and P.atkBufferSum<4 then + if D.timer>=math.max(60,150-2*D.wave) and P.atkBufferSum<4 then if D.wave==100 then P:win('finish') else diff --git a/parts/eventsets/survivor_h.lua b/parts/eventsets/survivor_h.lua index fce75feff..9e078c2f1 100644 --- a/parts/eventsets/survivor_h.lua +++ b/parts/eventsets/survivor_h.lua @@ -1,16 +1,16 @@ -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.wave,63,310) + GC.mStr(P.modeData.wave,63,310) mText(TEXTOBJ.wave,63,375) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control then local D=P.modeData D.timer=D.timer+1 - if D.timer>=math.max(60,180-2*D.wave)and P.atkBufferSum<15 then + if D.timer>=math.max(60,180-2*D.wave) and P.atkBufferSum<15 then if D.wave==90 then P:win('finish') else diff --git a/parts/eventsets/survivor_l.lua b/parts/eventsets/survivor_l.lua index ab0a951f5..e0999f933 100644 --- a/parts/eventsets/survivor_l.lua +++ b/parts/eventsets/survivor_l.lua @@ -1,16 +1,16 @@ -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.wave,63,310) + GC.mStr(P.modeData.wave,63,310) mText(TEXTOBJ.wave,63,375) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control then local D=P.modeData D.timer=D.timer+1 - if D.timer>=math.max(60,150-D.wave)and P.atkBufferSum<20 then + if D.timer>=math.max(60,150-D.wave) and P.atkBufferSum<20 then if D.wave==110 then P:win('finish') else @@ -18,7 +18,7 @@ return{ table.insert(P.atkBuffer,{line=generateLine(P.holeRND:random(10)),amount=4,countdown=t,cd0=t,time=0,sent=false,lv=3}) P.atkBufferSum=P.atkBufferSum+4 P.stat.recv=P.stat.recv+4 - if D.wave==60 then + if D.wave==90 then P:_showText(text.maxspeed,0,-140,100,'appear',.6) end P:shakeField(3) diff --git a/parts/eventsets/survivor_n.lua b/parts/eventsets/survivor_n.lua index 80ac120fe..82393088e 100644 --- a/parts/eventsets/survivor_n.lua +++ b/parts/eventsets/survivor_n.lua @@ -1,24 +1,24 @@ -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.wave,63,310) + GC.mStr(P.modeData.wave,63,310) mText(TEXTOBJ.wave,63,375) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control then local D=P.modeData D.timer=D.timer+1 - if D.timer>=math.max(90,180-2*D.wave)and P.atkBufferSum<8 then + if D.timer>=math.max(90,180-2*D.wave) and P.atkBufferSum<8 then if D.wave==80 then P:win('finish') else local d=D.wave+1 table.insert(P.atkBuffer, - d%4==0 and{line=generateLine(P.holeRND:random(10)),amount=1,countdown=60,cd0=60,time=0,sent=false,lv=1}or - d%4==1 and{line=generateLine(P.holeRND:random(10)),amount=2,countdown=70,cd0=70,time=0,sent=false,lv=1}or - d%4==2 and{line=generateLine(P.holeRND:random(10)),amount=3,countdown=80,cd0=80,time=0,sent=false,lv=2}or + d%4==0 and{line=generateLine(P.holeRND:random(10)),amount=1,countdown=60,cd0=60,time=0,sent=false,lv=1} or + d%4==1 and{line=generateLine(P.holeRND:random(10)),amount=2,countdown=70,cd0=70,time=0,sent=false,lv=1} or + d%4==2 and{line=generateLine(P.holeRND:random(10)),amount=3,countdown=80,cd0=80,time=0,sent=false,lv=2} or d%4==3 and{line=generateLine(P.holeRND:random(10)),amount=4,countdown=90,cd0=90,time=0,sent=false,lv=3} ) P.atkBufferSum=P.atkBufferSum+d%4+1 diff --git a/parts/eventsets/survivor_u.lua b/parts/eventsets/survivor_u.lua index 161446189..0ab93cbff 100644 --- a/parts/eventsets/survivor_u.lua +++ b/parts/eventsets/survivor_u.lua @@ -1,16 +1,16 @@ -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.wave,63,310) + GC.mStr(P.modeData.wave,63,310) mText(TEXTOBJ.wave,63,375) end, task=function(P) while true do - YIELD() + coroutine.yield() if P.control then local D=P.modeData D.timer=D.timer+1 - if D.timer>=math.max(300,600-10*D.wave)and P.atkBufferSum<20 then + if D.timer>=math.max(300,600-10*D.wave) and P.atkBufferSum<20 then if D.wave==35 then P:win('finish') else diff --git a/parts/eventsets/techrash_n.lua b/parts/eventsets/techrash_n.lua index f92000069..b78fdb0a5 100644 --- a/parts/eventsets/techrash_n.lua +++ b/parts/eventsets/techrash_n.lua @@ -1,7 +1,7 @@ -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.stat.clear[7][4],63,250) + GC.mStr(P.stat.clear[7][4],63,250) mText(TEXTOBJ.techrash,63,315) end, hook_drop=function(P) diff --git a/parts/eventsets/techrash_u.lua b/parts/eventsets/techrash_u.lua index b32e99be6..70c3d28f7 100644 --- a/parts/eventsets/techrash_u.lua +++ b/parts/eventsets/techrash_u.lua @@ -1,23 +1,21 @@ -local gc=love.graphics - -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.techrash,63,250) + GC.mStr(P.modeData.techrash,63,250) mText(TEXTOBJ.techrash,63,315) PLY.draw.applyField(P) local L=P.modeData.history for i=1,#L do - gc.setColor(1,.3,.3,.5-i*.04) - gc.rectangle('fill',30*L[i]-30,0,30,600) + GC.setColor(1,.3,.3,.5-i*.04) + GC.rectangle('fill',30*L[i]-30,0,30,600) end - PLY.draw.cancelField(P) + PLY.draw.cancelField() end, hook_drop=function(P) local C=P.lastPiece if C.row>0 then if C.row==4 then - if TABLE.find(P.modeData.history,C.curX)then + if TABLE.find(P.modeData.history,C.curX) then P:showText("STACK",0,-140,40,'flicker',.3) P:lose() else diff --git a/parts/eventsets/tsd_e.lua b/parts/eventsets/tsd_e.lua index cc6e450a9..b8583db4d 100644 --- a/parts/eventsets/tsd_e.lua +++ b/parts/eventsets/tsd_e.lua @@ -1,7 +1,7 @@ -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.tsd,63,250) + GC.mStr(P.modeData.tsd,63,250) mText(TEXTOBJ.tsd,63,315) end, hook_drop=function(P) diff --git a/parts/eventsets/tsd_h.lua b/parts/eventsets/tsd_h.lua index d028b00fc..3f8c816d9 100644 --- a/parts/eventsets/tsd_h.lua +++ b/parts/eventsets/tsd_h.lua @@ -1,16 +1,14 @@ -local gc=love.graphics - -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.tsd,63,250) + GC.mStr(P.modeData.tsd,63,250) mText(TEXTOBJ.tsd,63,315) local L=P.modeData.history - if L[1]and L[1]==L[2]and L[1]==L[3]then + if L[1] and L[1]==L[2] and L[1]==L[3] then PLY.draw.applyField(P) - gc.setColor(1,.3,.3,.2) - gc.rectangle('fill',30*L[1]-30,0,30,600) - PLY.draw.cancelField(P) + GC.setColor(1,.3,.3,.2) + GC.rectangle('fill',30*L[1]-30,0,30,600) + PLY.draw.cancelField() end end, hook_drop=function(P) @@ -18,7 +16,7 @@ return{ if C.row>0 then if C.id==5 and C.row==2 and C.spin then local L=P.modeData.history - if L[1]==C.centX and L[1]==L[2]and L[1]==L[3]then + if L[1]==C.centX and L[1]==L[2] and L[1]==L[3] then P:showText("STACK",0,-140,40,'flicker',.3) P:lose() else diff --git a/parts/eventsets/tsd_u.lua b/parts/eventsets/tsd_u.lua index 09f95d282..c2e6d9c67 100644 --- a/parts/eventsets/tsd_u.lua +++ b/parts/eventsets/tsd_u.lua @@ -1,23 +1,21 @@ -local gc=love.graphics - -return{ +return { mesDisp=function(P) setFont(60) - mStr(P.modeData.tsd,63,250) + GC.mStr(P.modeData.tsd,63,250) mText(TEXTOBJ.tsd,63,315) PLY.draw.applyField(P) local L=P.modeData.history for i=1,#L do - gc.setColor(1,.3,.3,.4-i*.05) - gc.rectangle('fill',30*L[i]-30,0,30,600) + GC.setColor(1,.3,.3,.4-i*.05) + GC.rectangle('fill',30*L[i]-30,0,30,600) end - PLY.draw.cancelField(P) + PLY.draw.cancelField() end, hook_drop=function(P) local C=P.lastPiece if C.row>0 then if C.id==5 and C.row==2 and C.spin then - if TABLE.find(P.modeData.history,C.centX)then + if TABLE.find(P.modeData.history,C.centX) then P:showText("STACK",0,-140,40,'flicker',.3) P:lose() else diff --git a/parts/eventsets/ultra.lua b/parts/eventsets/ultra.lua index 1f19b6a74..cd085dd12 100644 --- a/parts/eventsets/ultra.lua +++ b/parts/eventsets/ultra.lua @@ -1,29 +1,28 @@ -local gc=love.graphics local warnTime={60,90,105,115,116,117,118,119,120} for i=1,#warnTime do warnTime[i]=warnTime[i]*60 end -return{ +return { mesDisp=function(P) - gc.setLineWidth(2) - gc.setColor(.98,.98,.98,.8) - gc.rectangle('line',0,260,126,80,4) - gc.setColor(.98,.98,.98,.4) - gc.rectangle('fill',0+2,260+2,126-4,80-4,2) + GC.setLineWidth(2) + GC.setColor(.98,.98,.98,.8) + GC.rectangle('line',0,260,126,80,4) + GC.setColor(.98,.98,.98,.4) + GC.rectangle('fill',0+2,260+2,126-4,80-4,2) setFont(45) local t=P.stat.frame/60 local T=("%.1f"):format(120-t) - gc.setColor(COLOR.dH) - mStr(T,65,270) + GC.setColor(COLOR.dH) + GC.mStr(T,65,270) t=t/120 - gc.setColor(1.7*t,2.3-2*t,.3) - mStr(T,63,268) + GC.setColor(1.7*t,2.3-2*t,.3) + GC.mStr(T,63,268) end, task=function(P) - BGM.seek(0) + BGM.set('all','seek',0) P.modeData.section=1 while true do - YIELD() - while P.stat.frame>=warnTime[P.modeData.section]do + coroutine.yield() + while P.stat.frame>=warnTime[P.modeData.section] do if P.modeData.section<9 then P.modeData.section=P.modeData.section+1 playReadySFX(3,.7+P.modeData.section*.03) diff --git a/parts/fonts/monospaced.otf b/parts/fonts/monospaced.otf new file mode 100644 index 000000000..6d562d164 Binary files /dev/null and b/parts/fonts/monospaced.otf differ diff --git a/parts/fonts/monospaced.ttf b/parts/fonts/monospaced.ttf deleted file mode 100644 index b915a953f..000000000 Binary files a/parts/fonts/monospaced.ttf and /dev/null differ diff --git a/parts/fonts/proportional.otf b/parts/fonts/proportional.otf new file mode 100644 index 000000000..20ab61810 Binary files /dev/null and b/parts/fonts/proportional.otf differ diff --git a/parts/fonts/proportional.ttf b/parts/fonts/proportional.ttf deleted file mode 100644 index ae127acca..000000000 Binary files a/parts/fonts/proportional.ttf and /dev/null differ diff --git a/parts/gameFuncs.lua b/parts/gameFuncs.lua index 2606af0d6..aefff5f60 100644 --- a/parts/gameFuncs.lua +++ b/parts/gameFuncs.lua @@ -1,9 +1,8 @@ -local gc=love.graphics -local gc_push,gc_pop=gc.push,gc.pop -local gc_origin,gc_replaceTransform=gc.origin,gc.replaceTransform -local gc_setLineWidth,gc_setColor=gc.setLineWidth,gc.setColor -local gc_setShader=gc.setShader -local gc_draw,gc_rectangle,gc_line,gc_printf=gc.draw,gc.rectangle,gc.line,gc.printf +local gc_push,gc_pop=GC.push,GC.pop +local gc_origin,gc_replaceTransform=GC.origin,GC.replaceTransform +local gc_setLineWidth,gc_setColor=GC.setLineWidth,GC.setColor +local gc_setShader=GC.setShader +local gc_draw,gc_rectangle,gc_printf=GC.draw,GC.rectangle,GC.printf local ins,rem=table.insert,table.remove local int,rnd=math.floor,math.random @@ -11,12 +10,11 @@ local approach=MATH.expApproach local SETTING,GAME,SCR=SETTING,GAME,SCR local PLAYERS=PLAYERS -local playSFX=SFX.play ---System -do--function tryBack() +-- System +do-- function tryBack() local sureTime=-1e99 function tryBack() if TIME()-sureTime<1 then @@ -28,7 +26,7 @@ do--function tryBack() end end end -do--function tryReset() +do-- function tryReset() local sureTime=-1e99 function tryReset() if TIME()-sureTime<1 then @@ -40,7 +38,7 @@ do--function tryReset() end end end -do--function tryDelete() +do-- function tryDelete() local sureTime=-1e99 function tryDelete() if TIME()-sureTime<1 then @@ -52,21 +50,21 @@ do--function tryDelete() end end end -do--function loadFile(name,args), function saveFile(data,name,args) - local t=setmetatable({},{__index=function()return"'$1' loading failed: $2"end}) +do-- function loadFile(name,args), function saveFile(data,name,args) + local t=setmetatable({},{__index=function() return "'$1' loading failed: $2" end}) function loadFile(name,args) local text=text or t - if not args then args=''end + if not args then args='' end local res,mes=pcall(FILE.load,name,args) if res then return mes else - if mes:find'open error'then + if mes:find'open error' then MES.new('error',text.loadError_open:repD(name,"")) - elseif mes:find'unknown mode'then + elseif mes:find'unknown mode' then MES.new('error',text.loadError_errorMode:repD(name,args)) - elseif mes:find'no file'then - if not args:sArg'-canSkip'then + elseif mes:find'no file' then + if not args:sArg'-canSkip' then MES.new('error',text.loadError_noFile:repD(name,"")) end elseif mes then @@ -83,24 +81,17 @@ do--function loadFile(name,args), function saveFile(data,name,args) return true else MES.new('error', - mes:find'duplicate'and - text.saveError_duplicate:repD(name)or - mes:find'encode error'and - text.saveError_encode:repD(name)or + mes:find'duplicate' and + text.saveError_duplicate:repD(name) or + mes:find'encode error' and + text.saveError_encode:repD(name) or mes and - text.saveError_other:repD(name,mes)or + text.saveError_other:repD(name,mes) or text.saveError_unknown:repD(name) ) end end end -function isSafeFile(file,mes) - if love.filesystem.getRealDirectory(file)~=SAVEDIR then - return true - elseif mes then - MES.new('warn',mes) - end -end function saveStats() return saveFile(STAT,'conf/data') end @@ -108,9 +99,15 @@ function saveProgress() return saveFile(RANKS,'conf/unlock') end function saveSettings() + if WS.status('game')=='running' then + NET.player_updateConf() + end return saveFile(SETTING,'conf/settings') end -do--function applySettings() +function saveUser() + return saveFile(USER.__data,'conf/user') +end +do-- function applySettings() local saturateValues={ normal={0,1}, soft={.2,.7}, @@ -119,87 +116,94 @@ do--function applySettings() color={-.2,1.2}, } function applySettings() - --Apply fullscreen + -- Apply language + text=LANG.get(SETTING.locale) + WIDGET.setLang(text.WidgetText) + for k,v in next,TEXTOBJ do + if rawget(text,k) then + v:set(text[k]) + end + end + + -- Apply cursor + love.mouse.setVisible(SETTING.sysCursor) + + -- Apply fullscreen love.window.setFullscreen(SETTING.fullscreen) - love.resize(gc.getWidth(),gc.getHeight()) + love.resize(GC.getWidth(),GC.getHeight()) - --Apply Zframework setting + -- Apply Zframework setting Z.setClickFX(SETTING.clickFX) Z.setFrameMul(SETTING.frameMul) Z.setPowerInfo(SETTING.powerInfo) Z.setCleanCanvas(SETTING.cleanCanvas) - --Apply VK shape + -- Apply VK shape VK.setShape(SETTING.VKSkin) - --Apply sound + -- Apply sound love.audio.setVolume(SETTING.mainVol) BGM.setVol(SETTING.bgm) SFX.setVol(SETTING.sfx) VOC.setVol(SETTING.voc) - --Apply saturs + -- Apply saturs local m - m=saturateValues[SETTING.blockSatur]or saturateValues.normal + m=saturateValues[SETTING.blockSatur] or saturateValues.normal SHADER.blockSatur:send('b',m[1]) SHADER.blockSatur:send('k',m[2]) - m=saturateValues[SETTING.fieldSatur]or saturateValues.normal + m=saturateValues[SETTING.fieldSatur] or saturateValues.normal SHADER.fieldSatur:send('b',m[1]) SHADER.fieldSatur:send('k',m[2]) - --Apply language - text=LANG.get(SETTING.locale) - WIDGET.setLang(text.WidgetText) - for k,v in next,TEXTOBJ do - if rawget(text,k)then - v:set(text[k]) - end - end - - --Apply cursor - love.mouse.setVisible(SETTING.sysCursor) - - --Apply BG - if SETTING.bg=='on'then + -- Apply BG + if SETTING.bg=='on' then BG.unlock() BG.set() - elseif SETTING.bg=='off'then + elseif SETTING.bg=='off' then BG.unlock() - BG.set('gray') - BG.send(SETTING.bgAlpha) + BG.set('fixColor',SETTING.bgAlpha,SETTING.bgAlpha,SETTING.bgAlpha) BG.lock() - elseif SETTING.bg=='custom'then - if love.filesystem.getInfo('conf/customBG')then - local res,image=pcall(gc.newImage,love.filesystem.newFile('conf/customBG')) + elseif SETTING.bg=='custom' then + if love.filesystem.getInfo('conf/customBG') then + local res,image=pcall(GC.newImage,love.filesystem.newFile('conf/customBG')) if res then BG.unlock() - BG.set('custom') - gc.setDefaultFilter('linear','linear') - BG.send(SETTING.bgAlpha,image) - gc.setDefaultFilter('nearest','nearest') + GC.setDefaultFilter('linear','linear') + BG.set('custom',SETTING.bgAlpha,image) + GC.setDefaultFilter('nearest','nearest') BG.lock() else MES.new('error',text.customBGloadFailed) end - else--Switch off when custom BG not found + else-- Switch off when custom BG not found SETTING.bg='off' BG.unlock() - BG.set('gray') - BG.send(SETTING.bgAlpha) + BG.set('fixColor',SETTING.bgAlpha,SETTING.bgAlpha,SETTING.bgAlpha) BG.lock() end end end end ---Royale mode -function randomTarget(P)--Return a random opponent for P - if #PLY_ALIVE>1 then - local R - repeat - R=PLY_ALIVE[rnd(#PLY_ALIVE)] - until R~=P - return R +-- Royale mode +function randomTarget(P)-- Return a random opponent for P + local l=TABLE.shift(PLY_ALIVE,0) + local count=0 + for i=1,#l do + if P.group==0 and l[i]~=P or P.group~=l[i].group then + count=count+1 + end + end + if count==0 then return end + count=rnd(count) + for i=1,#l do + if P.group==0 and l[i]~=P or P.group~=l[i].group then + count=count-1 + if count==0 then + return l[i] + end + end end end function freshMostDangerous() @@ -246,7 +250,7 @@ end function royaleLevelup() GAME.stage=GAME.stage+1 local spd - TEXT.show(text.royale_remain:gsub("$1",#PLY_ALIVE),640,200,40,'beat',.3) + TEXT.show(text.royale_remain:repD(#PLY_ALIVE),640,200,40,'beat',.3) if GAME.stage==2 then spd=30 elseif GAME.stage==3 then @@ -276,7 +280,7 @@ function royaleLevelup() for _,P in next,PLY_ALIVE do P.gameEnv.drop=spd end - if GAME.curMode.name:find("_u")then + if GAME.curMode.name:find("_u") then for i=1,#PLY_ALIVE do local P=PLY_ALIVE[i] P.gameEnv.drop=int(P.gameEnv.drop*.4) @@ -288,29 +292,29 @@ function royaleLevelup() end end ---Sound shortcuts +-- Sound shortcuts function playClearSFX(cc) if cc<=0 or cc%1~=0 then return end if cc<=4 then - playSFX('clear_'..cc) + SFX.play('clear_'..cc) elseif cc<=6 then - playSFX('clear_4') + SFX.play('clear_4') elseif cc<=12 then - playSFX('clear_4',.8) + SFX.play('clear_4',.8) if cc<=9 then Snd('bass','A3','E4') else Snd('bass','A3','E4','A4') end elseif cc<=16 then - playSFX('clear_5',.7) + SFX.play('clear_5',.7) if cc<=14 then Snd('bass',.8,'A3','E4')Snd('lead','A4','E5') else Snd('bass',.8,'A3','G4')Snd('lead','B4','G5') end else - playSFX('clear_6',.6) + SFX.play('clear_6',.6) if cc==17 then Snd('bass',.8,'A3','A4')Snd('lead','E5','G5') elseif cc==18 then Snd('bass',.7,'A4')Snd('lead',.8,'C4','G5')Snd('bell','D5') elseif cc==19 then Snd('bass',.7,'A4')Snd('lead',.8,'A4','E5')Snd('bell','B5') @@ -340,7 +344,7 @@ function playReadySFX(i,vol) end ---Game +-- Game function getItem(itemName,amount) STAT.item[itemName]=STAT.item[itemName]+(amount or 1) end @@ -358,7 +362,7 @@ function setField(P,page) local F=FIELD[page] local height=0 for y=#F,1,-1 do - if notEmptyLine(F[y])then + if notEmptyLine(F[y]) then height=y break end @@ -385,16 +389,16 @@ function freshDate(args) STAT.date=date STAT.todayTime=0 getItem('zTicket',1) - if not args:find'q'then + if not args:find'q' then MES.new('info',text.newDay) end saveStats() return true end end -function legalGameTime()--Check if today's playtime is legal +function legalGameTime()-- Check if today's playtime is legal if - SETTING.locale:find'zh'and + SETTING.locale:find'zh' and RANKS.sprint_10l<4 and (not RANKS.sprint_40l or RANKS.sprint_40l<3) then @@ -410,7 +414,7 @@ function legalGameTime()--Check if today's playtime is legal end return true end -do--function trySettingWarn() +do-- function trySettingWarn() local lastWarnTime=0 function trySettingWarn() if TIME()-lastWarnTime>2.6 then @@ -420,20 +424,20 @@ do--function trySettingWarn() end end -function mergeStat(stat,delta)--Merge delta stat. to global stat. +function mergeStat(stat,delta)-- Merge delta stat. to global stat. for k,v in next,delta do - if type(v)=='table'then - if type(stat[k])=='table'then + if type(v)=='table' then + if type(stat[k])=='table' then mergeStat(stat[k],v) end else - if stat[k]then + if stat[k] then stat[k]=stat[k]+v end end end end -function scoreValid()--Check if any unranked mods are activated +function scoreValid()-- Check if any unranked mods are activated for _,M in next,GAME.mod do if M.unranked then return false @@ -444,13 +448,13 @@ function scoreValid()--Check if any unranked mods are activated end return true end -function destroyPlayers()--Destroy all player objects, restore freerows and free CCs +function destroyPlayers()-- Destroy all player objects, restore freerows and free CCs for i=#PLAYERS,1,-1 do local P=PLAYERS[i] if P.canvas then P.canvas:release() end - while P.field[1]do + while P.field[1] do rem(P.field) rem(P.visTime) end @@ -464,7 +468,7 @@ function pauseGame() for i=1,#PLAYERS do local l=PLAYERS[i].keyPressing for j=1,#l do - if l[j]then + if l[j] then PLAYERS[i]:releaseKey(j) end end @@ -473,31 +477,31 @@ function pauseGame() for i=1,20 do VK.release(i) end - if not(GAME.result or GAME.replaying)then + if not (GAME.result or GAME.replaying) then GAME.pauseCount=GAME.pauseCount+1 end SCN.swapTo('pause','none') end end -function applyCustomGame()--Apply CUSTOMENV, BAG, MISSION +function applyCustomGame()-- Apply CUSTOMENV, BAG, MISSION for k,v in next,CUSTOMENV do GAME.modeEnv[k]=v end - if BAG[1]then + if BAG[1] then GAME.modeEnv.seqData=BAG else GAME.modeEnv.seqData=nil end - if MISSION[1]then + if MISSION[1] then GAME.modeEnv.mission=MISSION else GAME.modeEnv.mission=nil end end -function loadGame(mode,ifQuickPlay,ifNet)--Load a mode and go to game scene +function loadGame(mode,ifQuickPlay,ifNet)-- Load a mode and go to game scene freshDate() - if legalGameTime()then - if not MODES[mode]and love.filesystem.getRealDirectory('parts/modes/'..mode)~=SAVEDIR then + if legalGameTime() then + if not MODES[mode] and FILE.isSafe('parts/modes/'..mode) then MODES[mode]=require('parts.modes.'..mode) MODES[mode].name=mode end @@ -514,14 +518,14 @@ function loadGame(mode,ifQuickPlay,ifNet)--Load a mode and go to game scene if ifNet then SCN.go('net_game','swipeD') else - local modeText=text.modes[mode]or{"["..MODES[mode].name.."]",""} + local modeText=text.modes[mode] or{"["..MODES[mode].name.."]",""} TEXTOBJ.modeName:set(modeText[1].." "..modeText[2]) - SCN.go('game',ifQuickPlay and'swipeD'or'fade_togame') - playSFX('enter') + SCN.go('game',ifQuickPlay and 'swipeD' or 'fade_togame') + SFX.play('enter') end end end -function gameOver()--Save record +function gameOver()-- Save record if GAME.replaying then local R=GAME.curMode.getRank if R then @@ -537,15 +541,15 @@ function gameOver()--Save record local R=M.getRank if R then local P=PLAYERS[1] - R=R(P)--New rank + R=R(P)-- New rank if R then if R>0 then GAME.rank=R end - if not GAME.replaying and M.score and scoreValid()then - if RANKS[M.name]then--Old rank exist + if not GAME.replaying and M.score and scoreValid() then + if RANKS[M.name] then-- Old rank exist local needSave - if R>RANKS[M.name]then + if R>RANKS[M.name] then RANKS[M.name]=R needSave=true end @@ -554,7 +558,7 @@ function gameOver()--Save record for i=1,#M.unlock do local m=M.unlock[i] local n=MODES[m].name - if not RANKS[n]then + if not RANKS[n] then if MODES[m].x then RANKS[n]=0 end @@ -569,9 +573,9 @@ function gameOver()--Save record end local D=M.score(P) local L=M.records - local p=#L--Rank-1 + local p=#L-- Rank-1 if p>0 then - while M.comp(D,L[p])do--If higher rank + while M.comp(D,L[p]) do-- If higher rank p=p-1 if p==0 then break end end @@ -579,15 +583,15 @@ function gameOver()--Save record if p<10 then if p==0 then P:_showText(text.newRecord,0,-100,100,'beat',.5) - if SETTING.autoSave and DATA.saveReplay()then + if SETTING.autoSave and DATA.saveReplay() then GAME.saved=true - playSFX('connected') + SFX.play('connected') MES.new('check',text.saveDone) end end D.date=os.date("%Y/%m/%d %H:%M") ins(L,p+1,D) - if L[11]then L[11]=nil end + if L[11] then L[11]=nil end saveFile(L,('record/%s.rec'):format(M.name),'-luaon') end end @@ -595,7 +599,7 @@ function gameOver()--Save record end end function trySave() - if not GAME.statSaved and PLAYERS[1]and PLAYERS[1].type=='human'and(PLAYERS[1].frameRun>300 or GAME.result)then + if not GAME.statSaved and PLAYERS[1] and PLAYERS[1].type=='human' and (PLAYERS[1].frameRun>300 or GAME.result) then GAME.statSaved=true STAT.game=STAT.game+1 mergeStat(STAT,PLAYERS[1].stat) @@ -603,86 +607,314 @@ function trySave() saveStats() end end -do--function freshPlayerPosition(sudden) - local posLists={ - --1~5 - { - {340,75,1}, - {965,390,.5}, - {965,30,.5}, - {20,390,.5}, - {20,30,.5}, +do-- function freshPlayerPosition(sudden) + local posLists=setmetatable({ + alive={ + [1]={main={340,75,1}}, + [3]={main={340,75,1}, + {25,210,.5}, + {955,210,.5}, + }, + [4]={main={340,75,1}, + {25,210,.5}, + {970,90,.45},{970,410,.45}, + }, + [5]={main={340,75,1}, + {40,90,.45},{40,410,.45}, + {970,90,.45},{970,410,.45}, + }, + [6]={main={340,75,1}, + {40,90,.45},{40,410,.45}, + {1010,80,.305},{1010,290,.305},{1010,500,.305}, + }, + [7]={main={340,75,1}, + {100,80,.305},{100,290,.305},{100,500,.305}, + {1010,80,.305},{1010,290,.305},{1010,500,.305}, + }, + [10]={main={340,75,1}, + {100,80,.305},{100,290,.305},{100,500,.305}, + {935,90,.275},{935,300,.275},{935,510,.275}, + {1105,90,.275},{1105,300,.275},{1105,510,.275}, + }, + [13]={main={340,75,1}, + {10,90,.275},{10,300,.275},{10,510,.275}, + {180,90,.275},{180,300,.275},{180,510,.275}, + {935,90,.275},{935,300,.275},{935,510,.275}, + {1105,90,.275},{1105,300,.275},{1105,510,.275}, + }, + [14]={main={340,75,1}, + {10,90,.275},{10,300,.275},{10,510,.275}, + {180,90,.275},{180,300,.275},{180,510,.275}, + {935,90,.275},{935,300,.275},{935,510,.275}, + {1120,80,.225},{1120,240,.225},{1120,400,.225},{1120,560,.225}, + }, + [15]={main={340,75,1}, + {10,90,.275},{10,300,.275},{10,510,.275}, + {180,90,.275},{180,300,.275},{180,510,.275}, + {960,80,.225},{960,240,.225},{960,400,.225},{960,560,.225}, + {1120,80,.225},{1120,240,.225},{1120,400,.225},{1120,560,.225}, + }, + [16]={main={340,75,1}, + {10,90,.275},{10,300,.275},{10,510,.275}, + {190,80,.225},{190,240,.225},{190,400,.225},{190,560,.225}, + {960,80,.225},{960,240,.225},{960,400,.225},{960,560,.225}, + {1120,80,.225},{1120,240,.225},{1120,400,.225},{1120,560,.225}, + }, + [17]={main={340,75,1}, + {30,80,.225},{30,240,.225},{30,400,.225},{30,560,.225}, + {190,80,.225},{190,240,.225},{190,400,.225},{190,560,.225}, + {960,80,.225},{960,240,.225},{960,400,.225},{960,560,.225}, + {1120,80,.225},{1120,240,.225},{1120,400,.225},{1120,560,.225}, + }, + [24]={main={340,75,1}, + {30,80,.225},{30,240,.225},{30,400,.225},{30,560,.225}, + {190,80,.225},{190,240,.225},{190,400,.225},{190,560,.225}, + {940,80,.175},{940,205,.175},{940,330,.175},{940,455,.175},{940,580,.175}, + {1050,80,.175},{1050,205,.175},{1050,330,.175},{1050,455,.175},{1050,580,.175}, + {1160,80,.175},{1160,205,.175},{1160,330,.175},{1160,455,.175},{1160,580,.175}, + }, + [31]={main={340,75,1}, + {10,80,.175},{10,205,.175},{10,330,.175},{10,455,.175},{10,580,.175}, + {120,80,.175},{120,205,.175},{120,330,.175},{120,455,.175},{120,580,.175}, + {230,80,.175},{230,205,.175},{230,330,.175},{230,455,.175},{230,580,.175}, + {940,80,.175},{940,205,.175},{940,330,.175},{940,455,.175},{940,580,.175}, + {1050,80,.175},{1050,205,.175},{1050,330,.175},{1050,455,.175},{1050,580,.175}, + {1160,80,.175},{1160,205,.175},{1160,330,.175},{1160,455,.175},{1160,580,.175}, + }, + [33]=(function() + local l={main={340,75,1}} + for y=-1.5,1.5 do for x=0,3 do + table.insert(l,{265-85*x,310+160*y,.125}) + table.insert(l,{940+85*x,310+160*y,.125}) + end end + return l + end)(), + [51]=(function() + local l={main={340,75,1}} + for y=-2,2 do for x=0,4 do + table.insert(l,{275-65*x,315+125*y,.1}) + table.insert(l,{945+65*x,315+125*y,.1}) + end end + return l + end)(), + [75]=(function() + local l={main={340,75,1}} + for y=-2,2 do for x=0,4 do + table.insert(l,{275-65*x,310+125*y,.1}) + end end + for y=-3,3 do for x=0,6 do + table.insert(l,{940+47*x,340+92*y,.075}) + end end + return l + end)(), + [99]=(function() + local l={main={340,75,1}} + for y=-3,3 do for x=0,6 do + table.insert(l,{290-47*x,340+92*y,.075}) + table.insert(l,{940+47*x,340+92*y,.075}) + end end + return l + end)(), + [MATH.inf]={main={340,75,1}}, }, - --6~17 - (function() - local L={{340,75,1}} - for i=1,4 do ins(L,{15,-160+180*i,.25})end - for i=1,4 do ins(L,{180,-160+180*i,.25})end - for i=1,4 do ins(L,{950,-160+180*i,.25})end - for i=1,4 do ins(L,{1120,-160+180*i,.25})end - return L - end)(), - --18~31 - (function() - local L={{340,75,1}} - for i=1,5 do ins(L,{10, -100+135*i,.18})end - for i=1,5 do ins(L,{120, -100+135*i,.18})end - for i=1,5 do ins(L,{230, -100+135*i,.18})end - for i=1,5 do ins(L,{940, -100+135*i,.18})end - for i=1,5 do ins(L,{1050,-100+135*i,.18})end - for i=1,5 do ins(L,{1160,-100+135*i,.18})end - return L - end)(), - --32~49 - (function() - local L={{340,75,1}} - for i=1,4 do for j=1,6 do ins(L,{78*i-54,115*j-98,.09})end end - for i=9,12 do for j=1,6 do ins(L,{78*i+267,115*j-98,.09})end end - return L - end)(), - --50~99 - (function() - local L={{340,75,1}} - for i=1,7 do for j=1,7 do ins(L,{46*i-36,97*j-72,.068})end end - for i=15,21 do for j=1,7 do ins(L,{46*i+264,97*j-72,.068})end end - return L - end)(), - } - function freshPlayerPosition(sudden)--Set initial position for every player + dead={ + [1]={{340,75,1}}, + [2]={ + {50,130,.925},{670,130,.925}, + }, + [3]={ + {25,160,.675},{440,160,.675},{855,160,.675}, + }, + [4]={ + {13,200,.525},{328,200,.525},{643,200,.525},{948,200,.525}, + }, + [5]={ + {8,230,.425},{260,230,.425},{512,230,.425},{764,230,.425},{1016,230,.425}, + }, + [10]={ + {8,110,.425},{260,110,.425},{512,110,.425},{764,110,.425},{1016,110,.425}, + {8,410,.425},{260,410,.425},{512,410,.425},{764,410,.425},{1016,410,.425}, + }, + [12]={ + {10,120,.35},{220,120,.35},{430,120,.35},{640,120,.35},{850,120,.35},{1060,120,.35}, + {10,400,.35},{220,400,.35},{430,400,.35},{640,400,.35},{850,400,.35},{1060,400,.35}, + }, + [18]={ + {10,90,.305},{220,90,.305},{430,90,.305},{640,90,.305},{850,90,.305},{1060,90,.305}, + {10,300,.305},{220,300,.305},{430,300,.305},{640,300,.305},{850,300,.305},{1060,300,.305}, + {10,510,.305},{220,510,.305},{430,510,.305},{640,510,.305},{850,510,.305},{1060,510,.305}, + }, + [21]={ + {10,90,.295},{190,90,.295},{370,90,.295},{550,90,.295},{730,90,.295},{910,90,.295},{1090,90,.295}, + {10,300,.295},{190,300,.295},{370,300,.295},{550,300,.295},{730,300,.295},{910,300,.295},{1090,300,.295}, + {10,510,.295},{190,510,.295},{370,510,.295},{550,510,.295},{730,510,.295},{910,510,.295},{1090,510,.295}, + }, + [24]={ + {20,100,.25},{175,100,.25},{330,100,.25},{485,100,.25},{640,100,.25},{795,100,.25},{950,100,.25},{1105,100,.25}, + {20,300,.25},{175,300,.25},{330,300,.25},{485,300,.25},{640,300,.25},{795,300,.25},{950,300,.25},{1105,300,.25}, + {20,500,.25},{175,500,.25},{330,500,.25},{485,500,.25},{640,500,.25},{795,500,.25},{950,500,.25},{1105,500,.25}, + }, + [27]={ + {10,100,.225},{150,100,.225},{290,100,.225},{430,100,.225},{570,100,.225},{710,100,.225},{850,100,.225},{990,100,.225},{1130,100,.225}, + {10,300,.225},{150,300,.225},{290,300,.225},{430,300,.225},{570,300,.225},{710,300,.225},{850,300,.225},{990,300,.225},{1130,300,.225}, + {10,500,.225},{150,500,.225},{290,500,.225},{430,500,.225},{570,500,.225},{710,500,.225},{850,500,.225},{990,500,.225},{1130,500,.225}, + }, + [36]={ + {10,90,.225},{150,90,.225},{290,90,.225},{430,90,.225},{570,90,.225},{710,90,.225},{850,90,.225},{990,90,.225},{1130,90,.225}, + {10,245,.225},{150,245,.225},{290,245,.225},{430,245,.225},{570,245,.225},{710,245,.225},{850,245,.225},{990,245,.225},{1130,245,.225}, + {10,400,.225},{150,400,.225},{290,400,.225},{430,400,.225},{570,400,.225},{710,400,.225},{850,400,.225},{990,400,.225},{1130,400,.225}, + {10,555,.225},{150,555,.225},{290,555,.225},{430,555,.225},{570,555,.225},{710,555,.225},{850,555,.225},{990,555,.225},{1130,555,.225}, + }, + [39]=(function() + local l={} + for y=0,2 do for x=0,12 do + table.insert(l,{13+97*x,110+190*y,.15}) + end end + return l + end)(), + [42]=(function() + local l={} + for y=0,2 do for x=0,13 do + table.insert(l,{15+90*x,120+190*y,.135}) + end end + return l + end)(), + [45]=(function() + local l={} + for y=0,2 do for x=0,14 do + table.insert(l,{8+85*x,120+190*y,.125}) + end end + return l + end)(), + [60]=(function() + local l={} + for y=0,3 do for x=0,14 do + table.insert(l,{8+85*x,85+155*y,.125}) + end end + return l + end)(), + [64]=(function() + local l={} + for y=0,3 do for x=0,15 do + table.insert(l,{13+79*x,85+155*y,.115}) + end end + return l + end)(), + [68]=(function() + local l={} + for y=0,3 do for x=0,16 do + table.insert(l,{6+75*x,85+155*y,.115}) + end end + return l + end)(), + [72]=(function() + local l={} + for y=0,3 do for x=0,17 do + table.insert(l,{15+70*x,95+155*y,.1}) + end end + return l + end)(), + [90]=(function() + local l={} + for y=0,4 do for x=0,17 do + table.insert(l,{15+70*x,82+127*y,.1}) + end end + return l + end)(), + [95]=(function() + local l={} + for y=0,4 do for x=0,18 do + table.insert(l,{15+66*x,82+127*y,.1}) + end end + return l + end)(), + [100]=(function() + local l={} + for y=0,4 do for x=0,19 do + table.insert(l,{12+63*x,82+127*y,.1}) + end end + return l + end)(), + [MATH.inf]={}, + }, + }, { + __call=function(self,alive,count) + local lastTested=MATH.inf + for k in next,self[alive and 'alive' or 'dead'] do + if k=count then + lastTested=k + end + end + return self[alive and 'alive' or 'dead'][lastTested] + end, + }) + + function freshPlayerPosition(mode)-- Set initial position for every player, mode: 'normal'|'quick'|'update' + assert(mode=='normal' or mode=='quick' or mode=='update',"Wrong freshPlyPos mode") local L=PLY_ALIVE - if not sudden then + if mode~='update' then for i=1,#L do L[i]:setPosition(640,#L<=5 and 360 or -62,0) end end - local posList - if #L<=5 then posList=posLists[1] - elseif #L<=17 then posList=posLists[2] - elseif #L<=31 then posList=posLists[3] - elseif #L<=49 then posList=posLists[4] - elseif #L<=99 then posList=posLists[5] - else error("TOO MANY PLAYERS!") + local alive=PLAYERS[1].alive + + if mode=='update' then + if alive then + if #L<=31 then + for i=2,#L do + L[i].miniMode=false + L[i].draw=require"parts.player.draw".norm + end + end + else + if #L<=36 then + for i=1,#L do + L[i].miniMode=false + L[i].draw=require"parts.player.draw".norm + end + end + end + end + + local posList=posLists(alive,#L) + local method=mode=='normal' and 'setPosition' or 'movePosition' + + if alive then + for i=1,#L do + if i==1 then + if SETTING.portrait then-- WARNING: Brutly scaling up to 2x only for 1P, will cause many other visual issues. + L[i][method](L[i],36,-260,2) + else + L[i][method](L[i],unpack(posList['main'])) + end + else + L[i][method](L[i],unpack(posList[i-1])) + end + end + else + for i=1,#L do + L[i][method](L[i],unpack(posList[i])) + end end - local method=sudden and'setPosition'or'movePosition' - for i=1,#L do L[i][method](L[i],unpack(posList[i]))end end end -do--function dumpBasicConfig() +do-- function dumpBasicConfig() local gameSetting={ - --Tuning + -- Tuning 'das','arr','dascut','dropcut','sddas','sdarr', 'ihs','irs','ims','RS', - --System + -- System 'skin','face', - --Graphic + -- Graphic 'ghostType','block','ghost','center','bagLine', 'dropFX','moveFX','shakeFX', 'text','highCam','nextPos', - --Unnecessary graphic + -- Unnecessary graphic -- 'grid','smooth', -- 'lockFX','clearFX','splashFX','atkFX', -- 'score', @@ -695,11 +927,11 @@ do--function dumpBasicConfig() return JSON.encode(S) end end -do--function resetGameData(args) +do-- function resetGameData(args) local function task_showMods() local time=0 while true do - YIELD() + coroutine.yield() time=time+1 if time%20==0 then local M=GAME.mod[time/20] @@ -712,14 +944,14 @@ do--function resetGameData(args) end end local gameSetting={ - --Tuning + -- Tuning 'das','arr','dascut','dropcut','sddas','sdarr', - 'ihs','irs','ims','RS','FTLock', + 'ihs','irs','ims','RS', - --System + -- System 'skin','face', - --Graphic + -- Graphic 'block','ghost','center','smooth','grid','bagLine', 'lockFX','dropFX','moveFX','clearFX','splashFX','shakeFX','atkFX', 'text','score','warn','highCam','nextPos', @@ -727,7 +959,7 @@ do--function resetGameData(args) local function _copyGameSetting() local S={} for _,key in next,gameSetting do - if type(SETTING[key])=='table'then + if type(SETTING[key])=='table' then S[key]=TABLE.shift(SETTING[key]) else S[key]=SETTING[key] @@ -736,20 +968,20 @@ do--function resetGameData(args) return S end function resetGameData(args,seed) - if not args then args=""end + if not args then args="" end trySave() GAME.result=false GAME.rank=0 GAME.warnLVL0=0 GAME.warnLVL=0 - if args:find'r'then + if args:find'r' then GAME.frameStart=0 GAME.recording=false GAME.replaying=true else - GAME.frameStart=args:find'n'and 0 or 180-SETTING.reTime*60 - GAME.seed=seed or math.random(1046101471,2662622626) + GAME.frameStart=args:find'n' and 0 or 180-SETTING.reTime*60 + GAME.seed=seed or math.random(1046101471) GAME.pauseTime=0 GAME.pauseCount=0 GAME.saved=false @@ -768,16 +1000,16 @@ do--function resetGameData(args) else PLY.newPlayer(1) end - freshPlayerPosition(args:find'q') + freshPlayerPosition((args:find'q') and 'quick' or 'normal') VK.restore() local bg=GAME.modeEnv.bg - BG.set(type(bg)=='string'and bg or type(bg)=='table'and bg[math.random(#bg)]) + BG.set(type(bg)=='string' and bg or type(bg)=='table' and bg[math.random(#bg)]) local bgm=GAME.modeEnv.bgm - BGM.play(type(bgm)=='string'and bgm or type(bgm)=='table'and bgm[math.random(#bgm)]) + BGM.play(type(bgm)=='string' and bgm or type(bgm)=='table' and bgm[math.random(#bgm)]) TEXT.clear() - if GAME.modeEnv.eventSet=='royale'then + if GAME.modeEnv.eventSet=='royale' then for i=1,#PLAYERS do PLAYERS[i]:changeAtk(randomTarget(PLAYERS[i])) end @@ -796,14 +1028,13 @@ do--function resetGameData(args) collectgarbage() end end -do--function checkWarning() +do-- function checkWarning(P,dt) local max=math.max - function checkWarning(dt) - local P1=PLAYERS[1] - if P1.alive then - if P1.frameRun%26==0 then - local F=P1.field - local height=0--Max height of row 4~7 + function checkWarning(P,dt) + if P.alive then + if P.frameRun%26==0 then + local F=P.field + local height=0-- Max height of row 4~7 for x=4,7 do for y=#F,1,-1 do if F[y][x]>0 then @@ -814,7 +1045,7 @@ do--function checkWarning() end end end - GAME.warnLVL0=math.log(height-(P1.gameEnv.fieldH-5)+P1.atkBufferSum*.8) + GAME.warnLVL0=math.log(height-(P.gameEnv.fieldH-5)+P.atkBufferSum*.8) end local _=GAME.warnLVL if _1.126 and P1.frameRun%30==0 then + if GAME.warnLVL>1.126 and P.frameRun%30==0 then SFX.fplay('warn_beep',SETTING.sfx_warn) end elseif GAME.warnLVL>0 then @@ -834,54 +1065,31 @@ end ---Game draw -do--function drawSelfProfile() - local lvColor={COLOR.J,COLOR.A,COLOR.C,COLOR.N,COLOR.S,COLOR.V,COLOR.P,COLOR.M,COLOR.W,COLOR.R,COLOR.O,COLOR.Y} - local lvIcon=setmetatable({},{__index=function(self,lv) - local c=lvColor[int((lv-1)/26)+1]or COLOR.Z - - local img=GC.DO{25,25, - {"clear",0,0,0,0}, - {"setLW",2}, - {"setCL",c[1],c[2],c[3],.6}, - {"fRect",2,2,21,21,2}, - {"setCL",c}, - {"dRect",2,2,21,21,2}, - {"setCL",COLOR.Z}, - {"mText",(lv-1)%26+1,13,-1}, - } - rawset(self,lv,img) - return img - end}) +-- Game draw +do-- function drawSelfProfile() local name local textObj,scaleK,width,offY function drawSelfProfile() - local selfAvatar=USERS.getAvatar(USER.uid) gc_push('transform') gc_replaceTransform(SCR.xOy_ur) - --Draw avatar + -- Draw avatar gc_setLineWidth(2) gc_setColor(COLOR.X)gc_rectangle('fill',0,0,-300,80) gc_setColor(1,1,1)gc_rectangle('line',-300,0,300,80,5) gc_rectangle('line',-73,7,66,66,2) - gc_draw(selfAvatar,-72,8,nil,.5) + gc_draw(USERS.getAvatar(USER.uid),-72,8,nil,.5) - --Draw username - if name~=USERS.getUsername(USER.uid)then + -- Draw username + if name~=USERS.getUsername(USER.uid) then name=USERS.getUsername(USER.uid) - textObj=gc.newText(getFont(30),name) + textObj=GC.newText(getFont(30),name) width=textObj:getWidth() scaleK=210/math.max(width,210) offY=textObj:getHeight()/2 end gc_draw(textObj,-82,26,nil,scaleK,nil,width,offY) - --Draw lv. & xp. - gc_draw(lvIcon[USER.lv],-295,50) - gc_line(-270,55,-80,55,-80,70,-270,70) - gc_rectangle('fill',-210,55,150*USER.xp/USER.lv/USER.lv,15) - gc_pop() end end @@ -890,7 +1098,7 @@ function drawOnlinePlayerCount() gc_setColor(1,1,1) gc_push('transform') gc_replaceTransform(SCR.xOy_ur) - gc_printf(("%s: %s/%s/%s"):format(text.onlinePlayerCount,NET.UserCount,NET.PlayCount,NET.StreamCount),-600,80,594,'right') + gc_printf(text.onlinePlayerCount:repD(NET.onlineCount),-600,80,594,'right') gc_pop() end function drawWarning() @@ -907,53 +1115,53 @@ end ---Widget function shortcuts -function backScene()SCN.back()end -do--function goScene(name,style) +-- Widget function shortcuts +function backScene() SCN.back() end +do-- function goScene(name,style) local cache={} function goScene(name,style) local hash=style and name..style or name - if not cache[hash]then - cache[hash]=function()SCN.go(name,style)end + if not cache[hash] then + cache[hash]=function() SCN.go(name,style) end end return cache[hash] end end -do--function swapScene(name,style) +do-- function swapScene(name,style) local cache={} function swapScene(name,style) local hash=style and name..style or name - if not cache[hash]then - cache[hash]=function()SCN.swapTo(name,style)end + if not cache[hash] then + cache[hash]=function() SCN.swapTo(name,style) end end return cache[hash] end end -do--function pressKey(k) +do-- function pressKey(k) local cache={} function pressKey(k) - if not cache[k]then - cache[k]=function()love.keypressed(k)end + if not cache[k] then + cache[k]=function() love.keypressed(k) end end return cache[k] end end -do--CUS/SETXXX(k) +do-- CUS/SETXXX(k) local CUSTOMENV=CUSTOMENV local warnList={ 'das','arr','dascut','dropcut','sddas','sdarr', 'ihs','irs','ims','RS', - 'FTLock','frameMul','highCam', + 'frameMul','highCam', 'VKSwitch','VKIcon','VKTrack','VKDodge', 'simpMode', } - function CUSval(k)return function()return CUSTOMENV[k]end end - function ROOMval(k)return function()return ROOMENV[k]end end - function SETval(k)return function()return SETTING[k]end end - function CUSrev(k)return function()CUSTOMENV[k]=not CUSTOMENV[k]end end - function ROOMrev(k)return function()ROOMENV[k]=not ROOMENV[k]end end - function SETrev(k)return function()if TABLE.find(warnList,k)then trySettingWarn()end SETTING[k]=not SETTING[k]end end - function CUSsto(k)return function(i)CUSTOMENV[k]=i end end - function ROOMsto(k)return function(i)ROOMENV[k]=i end end - function SETsto(k)return function(i)if TABLE.find(warnList,k)then trySettingWarn()end SETTING[k]=i end end + function CUSval(k) return function() return CUSTOMENV[k] end end + function ROOMval(k) return function() return ROOMENV[k] end end + function SETval(k) return function() return SETTING[k] end end + function CUSrev(k) return function() CUSTOMENV[k]=not CUSTOMENV[k] end end + function ROOMrev(k) return function() ROOMENV[k]=not ROOMENV[k] end end + function SETrev(k) return function() if TABLE.find(warnList,k) then trySettingWarn() end SETTING[k]=not SETTING[k] end end + function CUSsto(k) return function(i) CUSTOMENV[k]=i end end + function ROOMsto(k) return function(i) ROOMENV[k]=i end end + function SETsto(k) return function(i) if TABLE.find(warnList,k) then trySettingWarn() end SETTING[k]=i end end end diff --git a/parts/gameTables.lua b/parts/gameTables.lua index 97af692b9..d1eee3b2b 100644 --- a/parts/gameTables.lua +++ b/parts/gameTables.lua @@ -1,4 +1,4 @@ ---Static data tables +-- Static data tables BLOCK_NAMES={ 'Z','S','J','L','T','O','I', 'Z5','S5','P','Q','F','E', @@ -6,13 +6,13 @@ BLOCK_NAMES={ 'J5','L5','R','Y','N','H','I5', 'I3','C','I2','O1' } -BLOCK_CHARS={}for i=1,#BLOCK_NAMES do BLOCK_CHARS[i]=CHAR.mino[BLOCK_NAMES[i]]end +BLOCK_CHARS={} for i=1,#BLOCK_NAMES do BLOCK_CHARS[i]=CHAR.mino[BLOCK_NAMES[i]] end BLOCK_COLORS={ COLOR.R,COLOR.F,COLOR.O,COLOR.Y,COLOR.L,COLOR.J,COLOR.G,COLOR.A, COLOR.C,COLOR.N,COLOR.S,COLOR.B,COLOR.V,COLOR.P,COLOR.M,COLOR.W, COLOR.dH,COLOR.D,COLOR.lY,COLOR.H,COLOR.lH,COLOR.dV,COLOR.dR,COLOR.dG, } -RANK_CHARS={'B','A','S','U','X'}for i=1,#RANK_CHARS do RANK_CHARS[i]=CHAR.icon['rank'..RANK_CHARS[i]]end +RANK_CHARS={'B','A','S','U','X'} for i=1,#RANK_CHARS do RANK_CHARS[i]=CHAR.icon['rank'..RANK_CHARS[i]] end RANK_COLORS={ {.8,.86,.9}, {.6,.9,.7}, @@ -20,7 +20,17 @@ RANK_COLORS={ {1,.5,.4}, {.95,.5,.95}, } -do--SVG_TITLE_FILL, SVG_TITLE_LINE +GROUP_COLORS={ + [0]=COLOR.Z, + [1]={STRING.hexColor'e57373'}, + [2]={STRING.hexColor"4caf50"}, + [3]={STRING.hexColor'5c6bc0'}, + [4]={STRING.hexColor'ffe082'}, + [5]={STRING.hexColor'ba68c8'}, + [6]={STRING.hexColor'80deea'}, +} + +do-- SVG_TITLE_FILL, SVG_TITLE_LINE SVG_TITLE_FILL={ { 0,0, @@ -131,24 +141,24 @@ do--SVG_TITLE_FILL, SVG_TITLE_LINE SVG_TITLE_LINE=TABLE.shift(SVG_TITLE_FILL) SVG_TITLE_LINE[8],SVG_TITLE_LINE[9]={},{} - for j=1,16 do SVG_TITLE_LINE[8][j]=SVG_TITLE_FILL[8][j]end - for j=19,#SVG_TITLE_FILL[8]-2 do SVG_TITLE_LINE[9][j-18]=SVG_TITLE_FILL[8][j]end + for j=1,16 do SVG_TITLE_LINE[8][j]=SVG_TITLE_FILL[8][j] end + for j=19,#SVG_TITLE_FILL[8]-2 do SVG_TITLE_LINE[9][j-18]=SVG_TITLE_FILL[8][j] end end -do--SVG_TITLE_FAN +do-- SVG_TITLE_FAN SVG_TITLE_FAN={} local sin,cos=math.sin,math.cos for i=1,9 do local L=TABLE.copy(SVG_TITLE_LINE[i]) SVG_TITLE_FAN[i]=L for j=1,#L,2 do - local x,y=L[j],L[j+1]--0