├── .github └── workflows │ └── gradle.yml ├── .gitignore ├── DB.mwb ├── README.md ├── build.gradle.kts ├── conf.pro ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── nms ├── build.gradle.kts ├── shared │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ ├── NMSUtils.java │ │ ├── OldNmsUtils.java │ │ └── jukebox │ │ └── IJukebox.java ├── src │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── JukeboxFactory.java └── versions │ ├── 12 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V12.java │ ├── 17 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V17.java │ ├── 18 │ ├── build.gradle │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V18.java │ ├── 21 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V21.java │ ├── 13-16 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V13_16.java │ ├── 19_2 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V19_2.java │ ├── 19_3 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V19_3.java │ ├── 19_4 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V19_4.java │ ├── 20_1 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V20_1.java │ ├── 20_2 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V20_2.java │ ├── 20_3 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V20_3.java │ ├── 20_5 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V20_5.java │ ├── 21_2 │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── java │ │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ └── minecraft │ │ └── nms │ │ └── jukebox │ │ └── versions │ │ └── V21_2.java │ └── build.gradle ├── plugin ├── build.gradle.kts └── src │ └── main │ ├── java │ └── ru │ │ └── spliterash │ │ └── musicbox │ │ ├── Handler.java │ │ ├── Lang.java │ │ ├── MusicBox.java │ │ ├── MusicBoxConfig.java │ │ ├── commands │ │ ├── MusicBoxExecutor.java │ │ ├── SubCommand.java │ │ └── subcommands │ │ │ ├── AbstractSelect.java │ │ │ ├── GiveExecutor.java │ │ │ ├── GiveSingleExecutor.java │ │ │ ├── PlayExecutor.java │ │ │ ├── PlaylistExecutor.java │ │ │ ├── ReloadExecutor.java │ │ │ ├── ShopExecutor.java │ │ │ ├── ShutUp.java │ │ │ └── SilentExecutor.java │ │ ├── customPlayers │ │ ├── abstracts │ │ │ └── AbstractBlockPlayer.java │ │ ├── interfaces │ │ │ ├── IPlayList.java │ │ │ ├── MusicBoxSongPlayer.java │ │ │ ├── PlayerSongPlayer.java │ │ │ └── PositionPlayer.java │ │ ├── models │ │ │ ├── MusicBoxSongPlayerModel.java │ │ │ ├── PlayerPlayerModel.java │ │ │ ├── PositionPlayerModel.java │ │ │ └── RangePlayerModel.java │ │ ├── objects │ │ │ ├── RadioPlayer.java │ │ │ ├── SignPlayer.java │ │ │ ├── SpeakerPlayer.java │ │ │ └── jukebox │ │ │ │ ├── JukeboxPlayer.java │ │ │ │ ├── JukeboxPlaylistImpl.java │ │ │ │ └── JukeboxPlaylistInitException.java │ │ └── playlist │ │ │ ├── ListPlaylist.java │ │ │ └── SingletonPlayList.java │ │ ├── db │ │ ├── AbstractBase.java │ │ ├── DatabaseLoader.java │ │ ├── model │ │ │ └── PlayerPlayListModel.java │ │ ├── types │ │ │ └── SQLite.java │ │ └── utils │ │ │ ├── NamedParamStatement.java │ │ │ └── ResultSetRow.java │ │ ├── events │ │ └── SourcedBlockRedstoneEvent.java │ │ ├── gui │ │ ├── GUIActions.java │ │ ├── playlist │ │ │ ├── PlayListEditorGUI.java │ │ │ └── PlayListListGUI.java │ │ └── song │ │ │ ├── SPControlGUI.java │ │ │ └── SongContainerGUI.java │ │ ├── minecraft │ │ ├── gui │ │ │ ├── GUI.java │ │ │ ├── InventoryAction.java │ │ │ └── actions │ │ │ │ ├── ClickAction.java │ │ │ │ └── PlayerClickAction.java │ │ └── nms │ │ │ └── versionutils │ │ │ ├── NewVersion.java │ │ │ ├── OldVersion.java │ │ │ ├── VersionUtils.java │ │ │ └── VersionUtilsFactory.java │ │ ├── players │ │ └── PlayerWrapper.java │ │ ├── song │ │ ├── MusicBoxSong.java │ │ ├── MusicBoxSongContainer.java │ │ ├── MusicBoxSongManager.java │ │ ├── SongNullException.java │ │ └── songContainers │ │ │ ├── SongContainerFactory.java │ │ │ ├── containers │ │ │ └── SingletonContainer.java │ │ │ ├── factory │ │ │ ├── FolderContainerFactory.java │ │ │ ├── ListContainerFactory.java │ │ │ └── SingletonContainerFactory.java │ │ │ └── types │ │ │ ├── FullSongContainer.java │ │ │ ├── SongContainer.java │ │ │ └── SubSongContainer.java │ │ └── utils │ │ ├── ArrayUtils.java │ │ ├── BukkitUtils.java │ │ ├── ComponentUtils.java │ │ ├── EconomyUtils.java │ │ ├── FaceUtils.java │ │ ├── FileUtils.java │ │ ├── ItemUtils.java │ │ ├── JavaUtils.java │ │ ├── RedstoneUtils.java │ │ ├── SignUtils.java │ │ ├── SongUtils.java │ │ ├── StringUtils.java │ │ ├── YamlSupportUtils.java │ │ ├── classes │ │ ├── Pair.java │ │ └── PeekList.java │ │ └── nbt │ │ ├── BukkitNbtHandler.java │ │ ├── NBTFactory.java │ │ ├── NBTHandler.java │ │ ├── NbtConstants.java │ │ └── NbtEditorHandler.java │ └── resources │ ├── config.yml │ ├── db │ └── SQLite.sql │ ├── help.txt │ └── songs │ ├── &aM&2e&am&2e&as │ ├── AMOGUS.nbs │ ├── All stars.nbs │ ├── Astronomia.nbs │ ├── DJ Got Us Fallin' in Love.nbs │ ├── DotA - Basshunter.nbs │ ├── Never gonna give you up.nbs │ └── info.txt │ ├── &dBest &cm&6u&es&ai&bc │ ├── Bad Apple.nbs │ ├── Blinding Lights.nbs │ ├── Croatian Rhapsody.nbs │ ├── Dancing Queen.nbs │ ├── Godfather.nbs │ ├── MK.nbs │ ├── Take on me.nbs │ ├── Taxi.nbs │ ├── The Final Countdown.nbs │ ├── Through the Fire and the Flames.nbs │ └── info.txt │ ├── Classic │ ├── Can Can.nbs │ ├── Edvard Grieg.nbs │ ├── Eine kleine Nachtmusik.nbs │ ├── Russian Dance.nbs │ ├── Serenade No.13.nbs │ ├── Turkish March.nbs │ └── info.txt │ ├── Games │ ├── Cuphead │ │ ├── Floral Fury.nbs │ │ ├── Inkwell Isle One.nbs │ │ ├── Introduction.nbs │ │ ├── Murine Corps.nbs │ │ ├── Threatin' Zeppelin.nbs │ │ └── info.txt │ ├── GreenHill.nbs │ ├── Guile's Theme.nbs │ ├── Tetris A.nbs │ ├── TobyFox │ │ ├── Asgore.nbs │ │ ├── Can You Really Call This A Hotel I Didn't Receive A Mint On My Pillow.nbs │ │ ├── Field of Hopes and Dreams.nbs │ │ ├── Finale.nbs │ │ ├── Hopes And Dream.nbs │ │ ├── Last Goodbye.nbs │ │ ├── Megalovania.nbs │ │ ├── Scarlet Forest.nbs │ │ ├── Spear of Justice.nbs │ │ └── info.txt │ └── info.txt │ ├── Other │ ├── Deja Vu' from Initial D.nbs │ ├── Hightway to Hell.nbs │ ├── James Bond.nbs │ ├── Running in the 90s.nbs │ └── info.txt │ └── Русская музыка │ ├── info.txt │ ├── Деревня дураков.nbs │ ├── Едем в соседнее село.nbs │ ├── Мобильник из бумера.nbs │ └── Юность в сапогах.nbs └── settings.gradle /.github/workflows/gradle.yml: -------------------------------------------------------------------------------- 1 | name: Build and Release 2 | on: 3 | push: 4 | tags: [ '*' ] # Запуск при создании тега 5 | 6 | jobs: 7 | build: 8 | runs-on: ubuntu-latest 9 | steps: 10 | - uses: actions/checkout@v2 11 | - name: Set up JDK 11 12 | uses: actions/setup-java@v2 13 | with: 14 | java-version: '11' 15 | distribution: 'temurin' 16 | - name: Build with Gradle 17 | uses: gradle/gradle-build-action@937999e9cc2425eddc7fd62d1053baf041147db7 18 | with: 19 | arguments: build 20 | - name: Upload Build Artifact 21 | uses: actions/upload-artifact@v4 22 | with: 23 | name: musicbox 24 | path: | 25 | build/libs/MusicBox*-all.jar 26 | 27 | release: 28 | needs: build 29 | runs-on: ubuntu-latest 30 | steps: 31 | - name: Checkout code 32 | uses: actions/checkout@v2 33 | - name: Download Build Artifact 34 | uses: actions/download-artifact@v4 35 | with: 36 | name: musicbox 37 | path: build/libs/ 38 | - name: Get Artifact Filename 39 | id: get_filename 40 | run: echo "FILENAME=$(basename build/libs/MusicBox*-all.jar)" >> $GITHUB_ENV 41 | - name: Create GitHub Release 42 | id: create_release 43 | uses: actions/create-release@v1 44 | env: 45 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 46 | with: 47 | tag_name: ${{ github.ref }} 48 | release_name: Release ${{ github.ref }} 49 | draft: false 50 | prerelease: false 51 | - name: Upload Release Asset 52 | uses: actions/upload-release-asset@v1 53 | env: 54 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 55 | with: 56 | upload_url: ${{ steps.create_release.outputs.upload_url }} 57 | asset_path: build/libs/${{ env.FILENAME }} 58 | asset_name: ${{ env.FILENAME }} 59 | asset_content_type: application/java-archive -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/ 3 | 4 | *.iml 5 | *.ipr 6 | *.iws 7 | 8 | # IntelliJ 9 | out/ 10 | # mpeltonen/sbt-idea plugin 11 | .idea_modules/ 12 | 13 | # JIRA plugin 14 | atlassian-ide-plugin.xml 15 | 16 | # Compiled class file 17 | *.class 18 | 19 | # Log file 20 | *.log 21 | 22 | # BlueJ files 23 | *.ctxt 24 | 25 | # Package Files # 26 | *.jar 27 | *.war 28 | *.nar 29 | *.ear 30 | *.zip 31 | *.tar.gz 32 | *.rar 33 | 34 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 35 | hs_err_pid* 36 | 37 | *~ 38 | 39 | # temporary files which can be created if a process still has a handle open of a deleted file 40 | .fuse_hidden* 41 | 42 | # KDE directory preferences 43 | .directory 44 | 45 | # Linux trash folder which might appear on any partition or disk 46 | .Trash-* 47 | 48 | # .nfs files are created when an open file is removed but is still being accessed 49 | .nfs* 50 | 51 | # General 52 | .DS_Store 53 | .AppleDouble 54 | .LSOverride 55 | 56 | # Icon must end with two \r 57 | Icon 58 | 59 | # Thumbnails 60 | ._* 61 | 62 | # Files that might appear in the root of a volume 63 | .DocumentRevisions-V100 64 | .fseventsd 65 | .Spotlight-V100 66 | .TemporaryItems 67 | .Trashes 68 | .VolumeIcon.icns 69 | .com.apple.timemachine.donotpresent 70 | 71 | # Directories potentially created on remote AFP share 72 | .AppleDB 73 | .AppleDesktop 74 | Network Trash Folder 75 | Temporary Items 76 | .apdisk 77 | 78 | # Windows thumbnail cache files 79 | Thumbs.db 80 | Thumbs.db:encryptable 81 | ehthumbs.db 82 | ehthumbs_vista.db 83 | 84 | # Dump file 85 | *.stackdump 86 | 87 | # Folder config file 88 | [Dd]esktop.ini 89 | 90 | # Recycle Bin used on file shares 91 | $RECYCLE.BIN/ 92 | 93 | # Windows Installer files 94 | *.cab 95 | *.msi 96 | *.msix 97 | *.msm 98 | *.msp 99 | 100 | # Windows shortcuts 101 | *.lnk 102 | 103 | .gradle 104 | build/ 105 | 106 | # Ignore Gradle GUI config 107 | gradle-app.setting 108 | 109 | # Cache of project 110 | .gradletasknamecache 111 | 112 | **/build/ 113 | 114 | # Common working directory 115 | run/ 116 | 117 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 118 | !gradle-wrapper.jar 119 | 120 | /libs 121 | 122 | lombok.config -------------------------------------------------------------------------------- /DB.mwb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/DB.mwb -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MusicBox 2 | Этот плагин добавляет на сервер новые пластинки, таблички, и много чего другого. Полное описание можно посмотреть на spigot 3 | 4 | Сюда добавлю лишь видео обзор 5 | 6 | [![](http://img.youtube.com/vi/uwygwHRrvkA/0.jpg)](http://www.youtube.com/watch?v=uwygwHRrvkA "") 7 | 8 | [Ссылка на spigot](https://www.spigotmc.org/resources/musicbox-music-on-discs.67949/) -------------------------------------------------------------------------------- /build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | `java-library` 3 | id("io.github.goooler.shadow") version "8.1.7" 4 | id("io.freefair.lombok") version "8.6" 5 | id("net.minecrell.plugin-yml.bukkit") version "0.6.0" 6 | id("io.papermc.paperweight.userdev") version "1.7.1" apply false 7 | } 8 | 9 | bukkit { 10 | name = "MusicBox" 11 | main = "ru.spliterash.musicbox.MusicBox" 12 | apiVersion = "1.13" 13 | authors = listOf("Spliterash") 14 | depend = listOf("NoteBlockAPI") 15 | softDepend = listOf("Vault") 16 | commands { 17 | register("musicbox") 18 | } 19 | } 20 | 21 | group = "ru.spliterash" 22 | 23 | allprojects { 24 | apply(plugin = "java-library"); 25 | apply(plugin = "io.freefair.lombok") 26 | 27 | version = "2.1.4" 28 | 29 | repositories { 30 | mavenCentral() 31 | mavenLocal() 32 | 33 | maven("https://jitpack.io") 34 | maven("https://repo.codemc.org/repository/maven-public") 35 | maven("https://hub.spigotmc.org/nexus/content/repositories/snapshots/") 36 | maven("https://oss.sonatype.org/content/groups/public/") 37 | maven("https://repo.clojars.org/") 38 | } 39 | 40 | dependencies { 41 | compileOnly("org.jetbrains:annotations:24.0.1") 42 | } 43 | } 44 | 45 | 46 | val startPath = "ru.spliterash.musicbox.shadow." 47 | tasks.shadowJar { 48 | relocate("com.cryptomorin.xseries", startPath + "xseries") 49 | relocate("org.bstats", startPath + "bstats") 50 | relocate("io.github.bananapuncher714.nbteditor", startPath + "nbteditor") 51 | } 52 | 53 | tasks.assemble { dependsOn(tasks.shadowJar) } 54 | 55 | dependencies { 56 | api(project(":plugin")) 57 | api(project(":nms")) 58 | api(project(":nms:shared")) 59 | api(project(":nms:versions:12")) 60 | api(project(":nms:versions:13-16")) 61 | api(project(":nms:versions:17")) 62 | api(project(":nms:versions:18")) 63 | api(project(":nms:versions:19_2", "reobf")) 64 | api(project(":nms:versions:19_3", "reobf")) 65 | api(project(":nms:versions:19_4", "reobf")) 66 | api(project(":nms:versions:20_1", "reobf")) 67 | api(project(":nms:versions:20_2", "reobf")) 68 | api(project(":nms:versions:20_3", "reobf")) 69 | api(project(":nms:versions:20_5", "reobf")) 70 | api(project(":nms:versions:21", "reobf")) 71 | api(project(":nms:versions:21_2", "reobf")) 72 | } 73 | -------------------------------------------------------------------------------- /conf.pro: -------------------------------------------------------------------------------- 1 | -libraryjars /jmods 2 | -keepattributes *Annotation*,SourceFile,LineNumberTable,Signature 3 | #-dontnote 4 | -dontwarn org.slf4j.** 5 | -dontwarn javax.** 6 | -dontwarn ru.spliterash.musicbox.shadow.** 7 | -dontwarn org.apache.** 8 | -optimizationpasses 5 9 | -overloadaggressively 10 | -dontobfuscate 11 | -allowaccessmodification 12 | -dontnote 13 | 14 | # Мои лаунчеры 15 | -keep class * extends org.bukkit.plugin.java.JavaPlugin 16 | # Сохраняем всё моё, разрешая запутывание 17 | -keepclassmembers,allowobfuscation class ru.spliterash.** { *; } 18 | 19 | 20 | -keep class sun.misc.Unsafe { *; } 21 | 22 | # Сохраняем имена енумоф 23 | -keepclassmembernames enum * { 24 | ; 25 | public static **[] values(); 26 | public static ** valueOf(java.lang.String); 27 | } 28 | # Ещё раз на всякий случай 29 | -keepclassmembers class * extends java.lang.Enum { 30 | ; 31 | public static **[] values(); 32 | public static ** valueOf(java.lang.String); 33 | } 34 | 35 | # Сериализацию да тоже надо 36 | -keepclassmembernames class * extends java.io.Serializable { 37 | static final long serialVersionUID; 38 | static final java.io.ObjectStreamField[] serialPersistentFields; 39 | private void writeObject(java.io.ObjectOutputStream); 40 | private void readObject(java.io.ObjectInputStream); 41 | java.lang.Object writeReplace(); 42 | java.lang.Object readResolve(); 43 | } 44 | 45 | # Нативные методы само собой 46 | -keepclasseswithmembers,includedescriptorclasses,allowshrinking class * { 47 | native ; 48 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs='-Dfile.encoding=UTF-8' -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /nms/build.gradle.kts: -------------------------------------------------------------------------------- 1 | java { 2 | targetCompatibility = JavaVersion.VERSION_1_8 3 | sourceCompatibility = JavaVersion.VERSION_1_8 4 | } 5 | 6 | dependencies { 7 | compileOnly("org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT") 8 | 9 | api(project("shared")) 10 | } -------------------------------------------------------------------------------- /nms/shared/build.gradle.kts: -------------------------------------------------------------------------------- 1 | java { 2 | targetCompatibility = JavaVersion.VERSION_1_8 3 | sourceCompatibility = JavaVersion.VERSION_1_8 4 | } 5 | 6 | dependencies{ 7 | compileOnly("org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT") 8 | } -------------------------------------------------------------------------------- /nms/shared/src/main/java/ru/spliterash/musicbox/minecraft/nms/NMSUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms; 2 | 3 | import org.bukkit.Bukkit; 4 | 5 | public class NMSUtils { 6 | 7 | public static int parseMajorVersion(String raw) { 8 | int firstDotIndex = raw.indexOf("."); 9 | 10 | raw = raw.substring(firstDotIndex + 1); 11 | 12 | int secondDotIndex = raw.indexOf("."); 13 | 14 | if (secondDotIndex != -1) 15 | raw = raw.substring(0, secondDotIndex); 16 | 17 | return Integer.parseInt(raw); 18 | } 19 | 20 | public static String getRawVersion() { 21 | String strVersion = Bukkit.getVersion(); 22 | 23 | int start = strVersion.indexOf("(MC: ") + 5; 24 | 25 | strVersion = strVersion.substring(start); 26 | 27 | int end = strVersion.indexOf(")"); 28 | 29 | strVersion = strVersion.substring(0, end); 30 | 31 | return strVersion; 32 | } 33 | 34 | public static int getVersion() { 35 | return parseMajorVersion(getRawVersion()); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /nms/shared/src/main/java/ru/spliterash/musicbox/minecraft/nms/OldNmsUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import org.bukkit.Bukkit; 5 | 6 | @UtilityClass 7 | public class OldNmsUtils { 8 | public Class getNMSClass(String first, String nmsClassString) throws ClassNotFoundException { 9 | String name = first + "." + getOldNmsPackage() + "." + nmsClassString; 10 | return Class.forName(name); 11 | } 12 | 13 | public static String getOldNmsPackage() { 14 | return Bukkit.getServer().getClass().getPackage().getName().split("\\.")[3]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /nms/shared/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/IJukebox.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox; 2 | 3 | import org.bukkit.Material; 4 | import org.bukkit.inventory.ItemStack; 5 | 6 | import java.lang.reflect.Method; 7 | 8 | public interface IJukebox { 9 | default boolean isEmpty() { 10 | ItemStack item = getJukebox(); 11 | return item == null || item.getType().equals(Material.AIR); 12 | } 13 | 14 | void setJukebox(ItemStack item); 15 | 16 | ItemStack getJukebox(); 17 | } 18 | -------------------------------------------------------------------------------- /nms/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/JukeboxFactory.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox; 2 | 3 | import org.bukkit.block.Jukebox; 4 | import ru.spliterash.musicbox.minecraft.nms.NMSUtils; 5 | 6 | import java.lang.reflect.InvocationTargetException; 7 | 8 | public class JukeboxFactory { 9 | private static final String START_PATH = "ru.spliterash.musicbox.minecraft.nms.jukebox.versions."; 10 | private static final Class clazz; 11 | 12 | static { 13 | String raw = NMSUtils.getRawVersion(); 14 | int iV = NMSUtils.parseMajorVersion(raw); 15 | 16 | String className; 17 | if (iV == 21) { 18 | switch (raw) { 19 | case "1.21": 20 | case "1.21.1": 21 | className = START_PATH + "V21"; 22 | break; 23 | case "1.21.2": 24 | case "1.21.3": 25 | className = START_PATH + "V21_2"; 26 | break; 27 | default: 28 | className = null; 29 | break; 30 | } 31 | } else if (iV == 20) { 32 | switch (raw) { 33 | case "1.20": 34 | case "1.20.1": 35 | className = START_PATH + "V20_1"; 36 | break; 37 | case "1.20.2": 38 | className = START_PATH + "V20_2"; 39 | break; 40 | case "1.20.3": 41 | case "1.20.4": 42 | className = START_PATH + "V20_3"; 43 | break; 44 | case "1.20.5": 45 | case "1.20.6": 46 | default: 47 | className = START_PATH + "V20_5"; 48 | break; 49 | } 50 | } else if (iV == 19) { 51 | switch (raw) { 52 | case "1.19.2": 53 | className = START_PATH + "V19_2"; 54 | break; 55 | case "1.19.3": 56 | className = START_PATH + "V19_3"; 57 | break; 58 | case "1.19.4": 59 | className = START_PATH + "V19_4"; 60 | break; 61 | default: 62 | className = null; 63 | break; 64 | } 65 | } else if (iV == 18) 66 | className = START_PATH + "V18"; 67 | else if (iV == 17) 68 | className = START_PATH + "V17"; 69 | else if (iV >= 13) 70 | className = START_PATH + "V13_16"; 71 | else if (iV == 12) 72 | className = START_PATH + "V12"; 73 | else 74 | className = null; 75 | 76 | if (className == null) 77 | throw new IllegalArgumentException("Unsupported version: " + raw); 78 | Class tmpClass = null; 79 | try { 80 | //noinspection unchecked 81 | tmpClass = (Class) Class.forName(className); 82 | } catch (ClassNotFoundException e) { 83 | throw new RuntimeException(e); 84 | } finally { 85 | clazz = tmpClass; 86 | } 87 | } 88 | 89 | public static boolean jukeboxAvailable() { 90 | return clazz != null; 91 | } 92 | 93 | public static IJukebox getJukebox(Jukebox jukebox) { 94 | try { 95 | return clazz.getConstructor(Jukebox.class).newInstance(jukebox); 96 | } catch (InstantiationException | IllegalAccessException | InvocationTargetException | 97 | NoSuchMethodException e) { 98 | throw new RuntimeException(e); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /nms/versions/12/build.gradle.kts: -------------------------------------------------------------------------------- 1 | java{ 2 | sourceCompatibility = JavaVersion.VERSION_1_8 3 | targetCompatibility = JavaVersion.VERSION_1_8 4 | } 5 | dependencies { 6 | compileOnly("org.spigotmc:spigot-api:1.12.2-R0.1-SNAPSHOT") 7 | } -------------------------------------------------------------------------------- /nms/versions/12/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V12.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import org.bukkit.block.Jukebox; 4 | import org.bukkit.inventory.ItemStack; 5 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 6 | import ru.spliterash.musicbox.minecraft.nms.OldNmsUtils; 7 | 8 | import java.lang.reflect.Method; 9 | 10 | public class V12 implements IJukebox { 11 | 12 | private final Object tile_entity; 13 | 14 | public V12(Jukebox box) throws Exception { 15 | Method m = OldNmsUtils.getNMSClass("org.bukkit.craftbukkit", "block.CraftBlockEntityState").getDeclaredMethod("getTileEntity"); 16 | m.setAccessible(true); 17 | this.tile_entity = m.invoke(box); 18 | } 19 | 20 | public Object toCraft(ItemStack item) throws Exception { 21 | Method toVanilaItem = OldNmsUtils.getNMSClass( 22 | "org.bukkit.craftbukkit", 23 | "inventory.CraftItemStack") 24 | .getMethod("asNMSCopy", ItemStack.class); 25 | return toVanilaItem.invoke(null, item); 26 | } 27 | 28 | public ItemStack fromCraft(Object vanilaItem) throws Exception { 29 | Method toBukkitItem = OldNmsUtils.getNMSClass( 30 | "org.bukkit.craftbukkit", 31 | "inventory.CraftItemStack") 32 | .getMethod("asBukkitCopy", OldNmsUtils.getNMSClass("net.minecraft.server", "ItemStack")); 33 | return (ItemStack) toBukkitItem.invoke(null, vanilaItem); 34 | } 35 | 36 | @Override 37 | public void setJukebox(ItemStack item) { 38 | try { 39 | Object vanilaItem = this.toCraft(item); 40 | Method m = this.tile_entity.getClass().getMethod("setRecord", vanilaItem.getClass()); 41 | m.invoke(this.tile_entity, vanilaItem); 42 | } catch (Exception ex) { 43 | ex.printStackTrace(); 44 | } 45 | } 46 | 47 | @Override 48 | public ItemStack getJukebox() { 49 | try { 50 | Method m = tile_entity.getClass().getMethod("getRecord"); 51 | Object vanilaItem = m.invoke(this.tile_entity); 52 | return fromCraft(vanilaItem); 53 | } catch (Exception e) { 54 | e.printStackTrace(); 55 | return null; 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /nms/versions/13-16/build.gradle.kts: -------------------------------------------------------------------------------- 1 | java{ 2 | sourceCompatibility = JavaVersion.VERSION_1_8 3 | targetCompatibility = JavaVersion.VERSION_1_8 4 | } 5 | dependencies { 6 | compileOnly("org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT") 7 | } -------------------------------------------------------------------------------- /nms/versions/13-16/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V13_16.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import org.bukkit.block.Jukebox; 4 | import org.bukkit.inventory.ItemStack; 5 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 6 | import ru.spliterash.musicbox.minecraft.nms.OldNmsUtils; 7 | 8 | import java.lang.reflect.Field; 9 | import java.lang.reflect.Method; 10 | 11 | public class V13_16 implements IJukebox { 12 | private final Object tile_entity; 13 | 14 | public V13_16(Jukebox box) throws Exception { 15 | Field f = OldNmsUtils.getNMSClass("org.bukkit.craftbukkit", "block.CraftBlockEntityState").getDeclaredField("tileEntity"); 16 | f.setAccessible(true); 17 | this.tile_entity = f.get(box); 18 | } 19 | 20 | public Object toCraft(ItemStack item) throws Exception { 21 | Method toVanilaItem = OldNmsUtils.getNMSClass( 22 | "org.bukkit.craftbukkit", 23 | "inventory.CraftItemStack") 24 | .getMethod("asNMSCopy", ItemStack.class); 25 | return toVanilaItem.invoke(null, item); 26 | } 27 | 28 | public ItemStack fromCraft(Object vanilaItem) throws Exception { 29 | Method toBukkitItem = OldNmsUtils.getNMSClass( 30 | "org.bukkit.craftbukkit", 31 | "inventory.CraftItemStack") 32 | .getMethod("asBukkitCopy", OldNmsUtils.getNMSClass("net.minecraft.server", "ItemStack")); 33 | return (ItemStack) toBukkitItem.invoke(null, vanilaItem); 34 | } 35 | 36 | public void setJukebox(ItemStack item) { 37 | try { 38 | Object vanilaItem = this.toCraft(item); 39 | Method m = this.tile_entity.getClass().getMethod("setRecord", vanilaItem.getClass()); 40 | m.invoke(this.tile_entity, vanilaItem); 41 | } catch (Exception var4) { 42 | var4.printStackTrace(); 43 | } 44 | 45 | } 46 | 47 | public ItemStack getJukebox() { 48 | try { 49 | Method m = this.tile_entity.getClass().getMethod("getRecord"); 50 | Object vanilaItem = m.invoke(this.tile_entity); 51 | return this.fromCraft(vanilaItem); 52 | } catch (Exception var3) { 53 | var3.printStackTrace(); 54 | return null; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /nms/versions/17/build.gradle.kts: -------------------------------------------------------------------------------- 1 | java{ 2 | sourceCompatibility = JavaVersion.VERSION_1_8 3 | targetCompatibility = JavaVersion.VERSION_1_8 4 | } 5 | dependencies { 6 | compileOnly("org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT") 7 | } -------------------------------------------------------------------------------- /nms/versions/17/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V17.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import org.bukkit.block.Jukebox; 4 | import org.bukkit.inventory.ItemStack; 5 | import ru.spliterash.musicbox.minecraft.nms.OldNmsUtils; 6 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 7 | 8 | import java.lang.reflect.Field; 9 | import java.lang.reflect.Method; 10 | 11 | public class V17 implements IJukebox { 12 | 13 | private final Object tile_entity; 14 | 15 | public V17(Jukebox jukebox) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { 16 | Field f = OldNmsUtils.getNMSClass("org.bukkit.craftbukkit", "block.CraftBlockEntityState").getDeclaredField("tileEntity"); 17 | f.setAccessible(true); 18 | this.tile_entity = f.get(jukebox); 19 | } 20 | 21 | 22 | public Object toCraft(ItemStack item) throws Exception { 23 | Method toVanilaItem = OldNmsUtils.getNMSClass( 24 | "org.bukkit.craftbukkit", 25 | "inventory.CraftItemStack") 26 | .getMethod("asNMSCopy", ItemStack.class); 27 | return toVanilaItem.invoke(null, item); 28 | } 29 | 30 | public ItemStack fromCraft(Object vanilaItem) throws Exception { 31 | Method toBukkitItem = OldNmsUtils.getNMSClass( 32 | "org.bukkit.craftbukkit", 33 | "inventory.CraftItemStack") 34 | .getMethod("asBukkitCopy", Class.forName("net.minecraft.world.item.ItemStack")); 35 | return (ItemStack) toBukkitItem.invoke(null, vanilaItem); 36 | } 37 | 38 | public void setJukebox(ItemStack item) { 39 | try { 40 | Object vanilaItem = this.toCraft(item); 41 | Method m = this.tile_entity.getClass().getMethod("setRecord", vanilaItem.getClass()); 42 | m.invoke(this.tile_entity, vanilaItem); 43 | } catch (Exception var4) { 44 | var4.printStackTrace(); 45 | } 46 | 47 | } 48 | 49 | public ItemStack getJukebox() { 50 | try { 51 | Method m = this.tile_entity.getClass().getMethod("getRecord"); 52 | Object vanilaItem = m.invoke(this.tile_entity); 53 | return this.fromCraft(vanilaItem); 54 | } catch (Exception var3) { 55 | var3.printStackTrace(); 56 | return null; 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /nms/versions/18/build.gradle: -------------------------------------------------------------------------------- 1 | java { 2 | sourceCompatibility = JavaVersion.VERSION_1_8 3 | targetCompatibility = JavaVersion.VERSION_1_8 4 | } 5 | dependencies { 6 | compileOnly("org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT") 7 | } -------------------------------------------------------------------------------- /nms/versions/18/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V18.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import org.bukkit.block.Jukebox; 4 | import org.bukkit.inventory.CraftingInventory; 5 | import org.bukkit.inventory.ItemStack; 6 | import ru.spliterash.musicbox.minecraft.nms.OldNmsUtils; 7 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 8 | 9 | import java.lang.reflect.Field; 10 | import java.lang.reflect.Method; 11 | 12 | public class V18 implements IJukebox { 13 | 14 | private final Object tile_entity; 15 | 16 | public V18(Jukebox jukebox) throws ClassNotFoundException, IllegalAccessException, NoSuchFieldException { 17 | Field f = OldNmsUtils.getNMSClass("org.bukkit.craftbukkit", "block.CraftBlockEntityState").getDeclaredField("tileEntity"); 18 | f.setAccessible(true); 19 | this.tile_entity = f.get(jukebox); 20 | } 21 | 22 | 23 | public Object toCraft(ItemStack item) throws Exception { 24 | Method toVanilaItem = OldNmsUtils.getNMSClass( 25 | "org.bukkit.craftbukkit", 26 | "inventory.CraftItemStack") 27 | .getMethod("asNMSCopy", ItemStack.class); 28 | return toVanilaItem.invoke(null, item); 29 | } 30 | 31 | public ItemStack fromCraft(Object vanilaItem) throws Exception { 32 | Method toBukkitItem = OldNmsUtils.getNMSClass( 33 | "org.bukkit.craftbukkit", 34 | "inventory.CraftItemStack") 35 | .getMethod("asBukkitCopy", Class.forName("net.minecraft.world.item.ItemStack")); 36 | return (ItemStack) toBukkitItem.invoke(null, vanilaItem); 37 | } 38 | 39 | public void setJukebox(ItemStack item) { 40 | try { 41 | Object vanilaItem = this.toCraft(item); 42 | Method m = this.tile_entity.getClass().getMethod("a", vanilaItem.getClass()); 43 | m.invoke(this.tile_entity, vanilaItem); 44 | } catch (Exception var4) { 45 | var4.printStackTrace(); 46 | } 47 | 48 | } 49 | 50 | public ItemStack getJukebox() { 51 | try { 52 | Method m = this.tile_entity.getClass().getMethod("c"); 53 | Object vanilaItem = m.invoke(this.tile_entity); 54 | return this.fromCraft(vanilaItem); 55 | } catch (Exception var3) { 56 | var3.printStackTrace(); 57 | return null; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /nms/versions/19_2/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("io.papermc.paperweight.userdev") 3 | } 4 | java { 5 | toolchain.languageVersion.set(JavaLanguageVersion.of(17)) 6 | } 7 | dependencies { 8 | paperweight.paperDevBundle("1.19.2-R0.1-SNAPSHOT") 9 | } -------------------------------------------------------------------------------- /nms/versions/19_2/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V19_2.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import net.minecraft.world.level.block.entity.JukeboxBlockEntity; 4 | import org.bukkit.block.Jukebox; 5 | import org.bukkit.craftbukkit.v1_19_R1.block.CraftJukebox; 6 | import org.bukkit.craftbukkit.v1_19_R1.inventory.CraftItemStack; 7 | import org.bukkit.inventory.ItemStack; 8 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 9 | 10 | public class V19_2 implements IJukebox { 11 | private final JukeboxBlockEntity tileEntity; 12 | 13 | public V19_2(Jukebox jukebox) { 14 | CraftJukebox craft = (CraftJukebox) jukebox; 15 | tileEntity = craft.getTileEntity(); 16 | } 17 | 18 | public void setJukebox(ItemStack item) { 19 | net.minecraft.world.item.ItemStack converted = CraftItemStack.asNMSCopy(item); 20 | tileEntity.setRecord(converted); 21 | 22 | } 23 | 24 | public ItemStack getJukebox() { 25 | net.minecraft.world.item.ItemStack nmsItem = tileEntity.getRecord(); 26 | if (nmsItem.isEmpty()) 27 | return null; 28 | 29 | return CraftItemStack.asBukkitCopy(nmsItem); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /nms/versions/19_3/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("io.papermc.paperweight.userdev") 3 | } 4 | java { 5 | toolchain.languageVersion.set(JavaLanguageVersion.of(17)) 6 | } 7 | dependencies { 8 | paperweight.paperDevBundle("1.19.3-R0.1-SNAPSHOT") 9 | } -------------------------------------------------------------------------------- /nms/versions/19_3/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V19_3.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import net.minecraft.world.level.block.entity.JukeboxBlockEntity; 4 | import org.bukkit.block.Jukebox; 5 | import org.bukkit.craftbukkit.v1_19_R2.block.CraftJukebox; 6 | import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack; 7 | import org.bukkit.inventory.ItemStack; 8 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 9 | 10 | public class V19_3 implements IJukebox { 11 | private final JukeboxBlockEntity tileEntity; 12 | 13 | public V19_3(Jukebox jukebox) { 14 | CraftJukebox craft = (CraftJukebox) jukebox; 15 | tileEntity = craft.getTileEntity(); 16 | } 17 | 18 | public void setJukebox(ItemStack item) { 19 | net.minecraft.world.item.ItemStack converted = CraftItemStack.asNMSCopy(item); 20 | tileEntity.setRecord(converted); 21 | 22 | } 23 | 24 | public ItemStack getJukebox() { 25 | net.minecraft.world.item.ItemStack nmsItem = tileEntity.getRecord(); 26 | if (nmsItem.isEmpty()) 27 | return null; 28 | 29 | return CraftItemStack.asBukkitCopy(nmsItem); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /nms/versions/19_4/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("io.papermc.paperweight.userdev") 3 | } 4 | java { 5 | toolchain.languageVersion.set(JavaLanguageVersion.of(17)) 6 | } 7 | dependencies { 8 | paperweight.paperDevBundle("1.19.4-R0.1-SNAPSHOT") 9 | } -------------------------------------------------------------------------------- /nms/versions/19_4/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V19_4.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import net.minecraft.world.level.block.entity.JukeboxBlockEntity; 4 | import org.bukkit.block.Jukebox; 5 | import org.bukkit.craftbukkit.v1_19_R3.block.CraftJukebox; 6 | import org.bukkit.craftbukkit.v1_19_R3.inventory.CraftItemStack; 7 | import org.bukkit.inventory.ItemStack; 8 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 9 | 10 | public class V19_4 implements IJukebox { 11 | private final JukeboxBlockEntity tileEntity; 12 | 13 | public V19_4(Jukebox jukebox) { 14 | CraftJukebox craft = (CraftJukebox) jukebox; 15 | tileEntity = craft.getTileEntity(); 16 | } 17 | 18 | public void setJukebox(ItemStack item) { 19 | net.minecraft.world.item.ItemStack converted = CraftItemStack.asNMSCopy(item); 20 | tileEntity.setRecordWithoutPlaying(converted); 21 | 22 | } 23 | 24 | public ItemStack getJukebox() { 25 | net.minecraft.world.item.ItemStack nmsItem = tileEntity.getItem(0); 26 | if (nmsItem.isEmpty()) 27 | return null; 28 | 29 | return CraftItemStack.asBukkitCopy(nmsItem); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /nms/versions/20_1/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("io.papermc.paperweight.userdev") 3 | } 4 | java { 5 | toolchain.languageVersion.set(JavaLanguageVersion.of(17)) 6 | } 7 | dependencies { 8 | paperweight.paperDevBundle("1.20.1-R0.1-SNAPSHOT") 9 | } -------------------------------------------------------------------------------- /nms/versions/20_1/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V20_1.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import net.minecraft.world.level.block.entity.JukeboxBlockEntity; 4 | import org.bukkit.block.Jukebox; 5 | import org.bukkit.craftbukkit.v1_20_R1.block.CraftJukebox; 6 | import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; 7 | import org.bukkit.inventory.ItemStack; 8 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 9 | 10 | public class V20_1 implements IJukebox { 11 | private final JukeboxBlockEntity tileEntity; 12 | 13 | public V20_1(Jukebox jukebox) { 14 | CraftJukebox craft = (CraftJukebox) jukebox; 15 | tileEntity = craft.getTileEntity(); 16 | } 17 | 18 | public void setJukebox(ItemStack item) { 19 | net.minecraft.world.item.ItemStack converted = CraftItemStack.asNMSCopy(item); 20 | tileEntity.setRecordWithoutPlaying(converted); 21 | 22 | } 23 | 24 | public ItemStack getJukebox() { 25 | net.minecraft.world.item.ItemStack nmsItem = tileEntity.getItem(0); 26 | if (nmsItem.isEmpty()) 27 | return null; 28 | 29 | return CraftItemStack.asBukkitCopy(nmsItem); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /nms/versions/20_2/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("io.papermc.paperweight.userdev") 3 | } 4 | java { 5 | toolchain.languageVersion.set(JavaLanguageVersion.of(17)) 6 | } 7 | dependencies { 8 | paperweight.paperDevBundle("1.20.2-R0.1-SNAPSHOT") 9 | } -------------------------------------------------------------------------------- /nms/versions/20_2/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V20_2.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import net.minecraft.world.level.block.entity.JukeboxBlockEntity; 4 | import org.bukkit.block.Jukebox; 5 | import org.bukkit.craftbukkit.v1_20_R2.block.CraftJukebox; 6 | import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack; 7 | import org.bukkit.inventory.ItemStack; 8 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 9 | 10 | public class V20_2 implements IJukebox { 11 | private final JukeboxBlockEntity tileEntity; 12 | 13 | public V20_2(Jukebox jukebox) { 14 | CraftJukebox craft = (CraftJukebox) jukebox; 15 | tileEntity = craft.getTileEntity(); 16 | } 17 | 18 | public void setJukebox(ItemStack item) { 19 | net.minecraft.world.item.ItemStack converted = CraftItemStack.asNMSCopy(item); 20 | tileEntity.setRecordWithoutPlaying(converted); 21 | 22 | } 23 | 24 | public ItemStack getJukebox() { 25 | net.minecraft.world.item.ItemStack nmsItem = tileEntity.getItem(0); 26 | if (nmsItem.isEmpty()) 27 | return null; 28 | 29 | return CraftItemStack.asBukkitCopy(nmsItem); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /nms/versions/20_3/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("io.papermc.paperweight.userdev") 3 | } 4 | java { 5 | toolchain.languageVersion.set(JavaLanguageVersion.of(17)) 6 | } 7 | dependencies { 8 | paperweight.paperDevBundle("1.20.3-R0.1-SNAPSHOT") 9 | } -------------------------------------------------------------------------------- /nms/versions/20_3/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V20_3.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import net.minecraft.world.level.block.entity.JukeboxBlockEntity; 4 | import org.bukkit.block.Jukebox; 5 | import org.bukkit.craftbukkit.v1_20_R3.block.CraftJukebox; 6 | import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack; 7 | import org.bukkit.inventory.ItemStack; 8 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 9 | 10 | public class V20_3 implements IJukebox { 11 | private final JukeboxBlockEntity tileEntity; 12 | 13 | public V20_3(Jukebox jukebox) { 14 | CraftJukebox craft = (CraftJukebox) jukebox; 15 | tileEntity = craft.getTileEntity(); 16 | } 17 | 18 | public void setJukebox(ItemStack item) { 19 | net.minecraft.world.item.ItemStack converted = CraftItemStack.asNMSCopy(item); 20 | tileEntity.setRecordWithoutPlaying(converted); 21 | 22 | } 23 | 24 | public ItemStack getJukebox() { 25 | net.minecraft.world.item.ItemStack nmsItem = tileEntity.getItem(0); 26 | if (nmsItem.isEmpty()) 27 | return null; 28 | 29 | return CraftItemStack.asBukkitCopy(nmsItem); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /nms/versions/20_5/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("io.papermc.paperweight.userdev") 3 | } 4 | java { 5 | toolchain.languageVersion.set(JavaLanguageVersion.of(21)) 6 | } 7 | repositories { 8 | maven("https://repo.minebench.de") //kiory fix 9 | } 10 | dependencies { 11 | paperweight.paperDevBundle("1.20.5-R0.1-SNAPSHOT") 12 | } -------------------------------------------------------------------------------- /nms/versions/20_5/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V20_5.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import net.minecraft.world.level.block.entity.JukeboxBlockEntity; 4 | import org.bukkit.block.Jukebox; 5 | import org.bukkit.craftbukkit.block.CraftJukebox; 6 | import org.bukkit.craftbukkit.inventory.CraftItemStack; 7 | import org.bukkit.inventory.ItemStack; 8 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 9 | 10 | public class V20_5 implements IJukebox { 11 | private final JukeboxBlockEntity tileEntity; 12 | 13 | public V20_5(Jukebox jukebox) { 14 | CraftJukebox craft = (CraftJukebox) jukebox; 15 | tileEntity = craft.getTileEntity(); 16 | } 17 | 18 | public void setJukebox(ItemStack item) { 19 | net.minecraft.world.item.ItemStack converted = CraftItemStack.asNMSCopy(item); 20 | tileEntity.setRecordWithoutPlaying(converted); 21 | 22 | } 23 | 24 | public ItemStack getJukebox() { 25 | net.minecraft.world.item.ItemStack nmsItem = tileEntity.getItem(0); 26 | if (nmsItem.isEmpty()) 27 | return null; 28 | 29 | return CraftItemStack.asBukkitCopy(nmsItem); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /nms/versions/21/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("io.papermc.paperweight.userdev") 3 | } 4 | java { 5 | toolchain.languageVersion.set(JavaLanguageVersion.of(21)) 6 | } 7 | dependencies { 8 | paperweight.paperDevBundle("1.21-R0.1-SNAPSHOT") 9 | } -------------------------------------------------------------------------------- /nms/versions/21/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V21.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import net.minecraft.world.level.block.entity.JukeboxBlockEntity; 4 | import org.bukkit.block.Jukebox; 5 | import org.bukkit.craftbukkit.block.CraftJukebox; 6 | import org.bukkit.craftbukkit.inventory.CraftItemStack; 7 | import org.bukkit.inventory.ItemStack; 8 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 9 | 10 | public class V21 implements IJukebox { 11 | private final JukeboxBlockEntity tileEntity; 12 | 13 | public V21(Jukebox jukebox) { 14 | CraftJukebox craft = (CraftJukebox) jukebox; 15 | tileEntity = craft.getTileEntity(); 16 | } 17 | 18 | public void setJukebox(ItemStack item) { 19 | net.minecraft.world.item.ItemStack converted = CraftItemStack.asNMSCopy(item); 20 | tileEntity.setSongItemWithoutPlaying(converted, 0); 21 | 22 | } 23 | 24 | public ItemStack getJukebox() { 25 | net.minecraft.world.item.ItemStack nmsItem = tileEntity.getItem(0); 26 | if (nmsItem.isEmpty()) 27 | return null; 28 | 29 | return CraftItemStack.asBukkitCopy(nmsItem); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /nms/versions/21_2/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("io.papermc.paperweight.userdev") 3 | } 4 | java { 5 | toolchain.languageVersion.set(JavaLanguageVersion.of(21)) 6 | } 7 | dependencies { 8 | // 1.21.2 нет, но нарушать порядок версий у себя я не хочу, так что давайте представим что тут 1.21.2 9 | paperweight.paperDevBundle("1.21.3-R0.1-SNAPSHOT") 10 | } -------------------------------------------------------------------------------- /nms/versions/21_2/src/main/java/ru/spliterash/musicbox/minecraft/nms/jukebox/versions/V21_2.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.jukebox.versions; 2 | 3 | import net.minecraft.world.level.block.entity.JukeboxBlockEntity; 4 | import org.bukkit.block.Jukebox; 5 | import org.bukkit.craftbukkit.block.CraftJukebox; 6 | import org.bukkit.craftbukkit.inventory.CraftItemStack; 7 | import org.bukkit.inventory.ItemStack; 8 | import ru.spliterash.musicbox.minecraft.nms.jukebox.IJukebox; 9 | 10 | public class V21_2 implements IJukebox { 11 | private final JukeboxBlockEntity tileEntity; 12 | 13 | public V21_2(Jukebox jukebox) { 14 | CraftJukebox craft = (CraftJukebox) jukebox; 15 | tileEntity = craft.getTileEntity(); 16 | } 17 | 18 | public void setJukebox(ItemStack item) { 19 | net.minecraft.world.item.ItemStack converted = CraftItemStack.asNMSCopy(item); 20 | tileEntity.setSongItemWithoutPlaying(converted, 0); 21 | 22 | } 23 | 24 | public ItemStack getJukebox() { 25 | net.minecraft.world.item.ItemStack nmsItem = tileEntity.getItem(0); 26 | if (nmsItem.isEmpty()) 27 | return null; 28 | 29 | return CraftItemStack.asBukkitCopy(nmsItem); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /nms/versions/build.gradle: -------------------------------------------------------------------------------- 1 | subprojects { 2 | dependencies { 3 | compileOnly project(":nms:shared") 4 | } 5 | } -------------------------------------------------------------------------------- /plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | java { 2 | targetCompatibility = JavaVersion.VERSION_1_8 3 | sourceCompatibility = JavaVersion.VERSION_1_8 4 | } 5 | dependencies { 6 | compileOnly("org.spigotmc:spigot-api:1.13.2-R0.1-SNAPSHOT") 7 | compileOnly("com.github.MilkBowl:VaultAPI:1.7") 8 | compileOnly("com.github.koca2000:NoteBlockAPI:1.6.1") 9 | 10 | api("com.github.cryptomorin:XSeries:11.0.0") 11 | api("io.github.bananapuncher714:nbteditor:7.19.0") 12 | api("org.bstats:bstats-bukkit:3.0.2") 13 | 14 | api(project(":nms")) 15 | 16 | compileOnly("org.yaml:snakeyaml:2.0") 17 | 18 | } -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/MusicBox.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox; 2 | 3 | import lombok.Getter; 4 | import org.bstats.bukkit.Metrics; 5 | import org.bstats.charts.SingleLineChart; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.Location; 8 | import org.bukkit.command.PluginCommand; 9 | import org.bukkit.command.TabExecutor; 10 | import org.bukkit.entity.Player; 11 | import org.bukkit.inventory.ItemStack; 12 | import org.bukkit.plugin.java.JavaPlugin; 13 | import ru.spliterash.musicbox.commands.MusicBoxExecutor; 14 | import ru.spliterash.musicbox.customPlayers.abstracts.AbstractBlockPlayer; 15 | import ru.spliterash.musicbox.customPlayers.models.MusicBoxSongPlayerModel; 16 | import ru.spliterash.musicbox.customPlayers.objects.SignPlayer; 17 | import ru.spliterash.musicbox.db.DatabaseLoader; 18 | import ru.spliterash.musicbox.gui.GUIActions; 19 | import ru.spliterash.musicbox.players.PlayerWrapper; 20 | import ru.spliterash.musicbox.song.MusicBoxSongManager; 21 | 22 | import java.io.File; 23 | import java.io.FileInputStream; 24 | import java.io.FileNotFoundException; 25 | import java.util.Enumeration; 26 | import java.util.List; 27 | import java.util.jar.JarEntry; 28 | import java.util.stream.Collectors; 29 | 30 | @Getter 31 | public final class MusicBox extends JavaPlugin { 32 | @Getter 33 | private static MusicBox instance; 34 | private MusicBoxConfig configObject; 35 | private boolean loaded = false; 36 | private Metrics bStats; 37 | 38 | @Override 39 | public void onEnable() { 40 | instance = this; 41 | saveDefaultValues(); 42 | registerCommand("musicbox", new MusicBoxExecutor()); 43 | Bukkit.getPluginManager().registerEvents(new Handler(), this); 44 | Bukkit.getScheduler().runTaskAsynchronously(this, this::reloadPlugin); 45 | } 46 | 47 | public void sendMessage(String pex, String noPexMessage, String message) { 48 | for (Player player : Bukkit.getOnlinePlayers()) { 49 | if (player.hasPermission(pex)) 50 | player.sendMessage(message); 51 | else 52 | player.sendMessage(noPexMessage); 53 | } 54 | } 55 | 56 | private void saveDefaultValues() { 57 | boolean firstRun = !getDataFolder().isDirectory(); 58 | saveDefaultConfig(); 59 | if (firstRun) 60 | saveMyMusic(); 61 | } 62 | 63 | @SuppressWarnings("SameParameterValue") 64 | private void registerCommand(String command, TabExecutor executor) { 65 | PluginCommand cmd = getCommand(command); 66 | //noinspection ConstantConditions 67 | cmd.setExecutor(executor); 68 | cmd.setTabCompleter(executor); 69 | } 70 | 71 | public void reloadPlugin() { 72 | loaded = false; 73 | destroyAllPlayers(); 74 | try { 75 | configObject = MusicBoxConfig.parseConfig(new FileInputStream(new File(getDataFolder(), "config.yml"))); 76 | } catch (FileNotFoundException e) { 77 | throw new RuntimeException(e); 78 | } 79 | DatabaseLoader.reload(); 80 | Lang.reload(new File(getDataFolder(), "lang"), configObject.getLang()); 81 | PlayerWrapper.clearAll(); 82 | MusicBoxSongManager.reload(new File(getDataFolder(), "songs")); 83 | GUIActions.reloadGUI(); 84 | ItemStack stack; 85 | 86 | 87 | if (configObject.isBStats() && bStats == null) { 88 | bStats = new Metrics(this, 8766); 89 | bStats.addCustomChart( 90 | new SingleLineChart( 91 | "song_count", 92 | () -> MusicBoxSongManager.getAllSongs().size()) 93 | ); 94 | } 95 | loaded = true; 96 | SignPlayer.restorePreventedPlayers(); 97 | } 98 | 99 | public void destroyAllPlayers() { 100 | MusicBoxSongPlayerModel.destroyAll(); 101 | PlayerWrapper.clearAll(); 102 | } 103 | 104 | @Override 105 | public void onDisable() { 106 | List signLocations = SignPlayer 107 | .getPreventedPlayers() 108 | .stream() 109 | .map(AbstractBlockPlayer::getLocation) 110 | .collect(Collectors.toList()); 111 | if (signLocations.size() > 0) 112 | DatabaseLoader.getBase().savePreventedSigns(signLocations); 113 | destroyAllPlayers(); 114 | } 115 | 116 | private void saveMyMusic() { 117 | try { 118 | java.util.jar.JarFile jar = new java.util.jar.JarFile(getFile()); 119 | Enumeration enumEntries = jar.entries(); 120 | while (enumEntries.hasMoreElements()) { 121 | JarEntry entry = enumEntries.nextElement(); 122 | File realFile = new File(getDataFolder(), entry.getName()); 123 | if (!entry.getName().startsWith("songs/")) 124 | continue; 125 | if (entry.isDirectory()) { // if its a directory, create it 126 | //noinspection ResultOfMethodCallIgnored 127 | realFile.mkdir(); 128 | continue; 129 | } 130 | // get the input stream 131 | 132 | try (java.io.InputStream in = jar.getInputStream(entry); java.io.FileOutputStream out = new java.io.FileOutputStream(realFile)) { 133 | byte[] buffer = new byte[4096]; 134 | int n; 135 | while (-1 != (n = in.read(buffer))) { 136 | out.write(buffer, 0, n); 137 | } 138 | } 139 | } 140 | jar.close(); 141 | } catch (Exception ex) { 142 | ex.printStackTrace(); 143 | 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/MusicBoxConfig.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox; 2 | 3 | import lombok.AccessLevel; 4 | import lombok.Getter; 5 | import lombok.NoArgsConstructor; 6 | import org.yaml.snakeyaml.Yaml; 7 | import org.yaml.snakeyaml.introspector.BeanAccess; 8 | import ru.spliterash.musicbox.utils.YamlSupportUtils; 9 | 10 | import java.io.InputStream; 11 | 12 | @SuppressWarnings("unused") 13 | @Getter 14 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 15 | public class MusicBoxConfig { 16 | public static MusicBoxConfig parseConfig(InputStream yamlStream) { 17 | Yaml yaml = new Yaml(YamlSupportUtils.createCustomClassLoaderConstructor()); 18 | yaml.setBeanAccess(BeanAccess.FIELD); 19 | return yaml.loadAs(yamlStream, MusicBoxConfig.class); 20 | } 21 | 22 | private boolean printNewInstrument; 23 | private EconomySetting economy; 24 | private BossBarSetting bossbar; 25 | private int speakerRadius; 26 | private int jukeboxRadius; 27 | private String lang; 28 | private int autoDestroy; 29 | private boolean bStats; 30 | private boolean hearPermissionsCheck; 31 | private boolean enable10octave; 32 | @Getter 33 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 34 | public static class BossBarSetting { 35 | private boolean enable; 36 | private String color; 37 | private String style; 38 | 39 | } 40 | 41 | @Getter 42 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 43 | public static class EconomySetting { 44 | private boolean enable; 45 | private double price; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/MusicBoxExecutor.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands; 2 | 3 | import org.bukkit.ChatColor; 4 | import org.bukkit.command.Command; 5 | import org.bukkit.command.CommandSender; 6 | import org.bukkit.command.TabExecutor; 7 | import org.bukkit.entity.Player; 8 | import ru.spliterash.musicbox.Lang; 9 | import ru.spliterash.musicbox.MusicBox; 10 | import ru.spliterash.musicbox.commands.subcommands.*; 11 | import ru.spliterash.musicbox.gui.GUIActions; 12 | import ru.spliterash.musicbox.players.PlayerWrapper; 13 | import ru.spliterash.musicbox.utils.ArrayUtils; 14 | 15 | import java.util.*; 16 | import java.util.stream.Collectors; 17 | 18 | public class MusicBoxExecutor implements TabExecutor { 19 | private final Map subs = new HashMap<>(); 20 | 21 | public MusicBoxExecutor() { 22 | 23 | subs.put("shop", new ShopExecutor()); 24 | subs.put("give", new GiveExecutor()); 25 | subs.put("give_single", new GiveSingleExecutor()); 26 | subs.put("playlist", new PlaylistExecutor()); 27 | subs.put("play", new PlayExecutor()); 28 | subs.put("shutup", new ShutUp(this)); 29 | subs.put("reload", new ReloadExecutor()); 30 | subs.put("silent", new SilentExecutor()); 31 | } 32 | 33 | @Override 34 | public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { 35 | if (!MusicBox.getInstance().isLoaded()) { 36 | sender.sendMessage(ChatColor.RED + "Plugin not loaded, please wait or check console if wait too long"); 37 | return true; 38 | } 39 | 40 | if (!sender.hasPermission("musicbox.use")) { 41 | sender.sendMessage(Lang.NO_PEX.toString()); 42 | return true; 43 | } 44 | 45 | if (args.length == 0) { 46 | if (sender instanceof Player) 47 | GUIActions.openDefaultInventory(PlayerWrapper.getInstance((Player) sender)); 48 | else 49 | sendHelp(sender); 50 | return true; 51 | } 52 | SubCommand executor = subs.get(args[0]); 53 | if (executor == null) { 54 | sendHelp(sender); 55 | return true; 56 | } 57 | if (executor.canExecute(sender)) { 58 | executor.execute(sender, ArrayUtils.removeFirst(String.class, args)); 59 | } else { 60 | sender.sendMessage(Lang.NO_PEX.toString()); 61 | } 62 | return true; 63 | } 64 | 65 | public void sendHelp(CommandSender sender) { 66 | sender.sendMessage(Lang.COMMAND_HELP.toArray()); 67 | if (sender.hasPermission("musicbox.shop")) { 68 | sender.sendMessage(Lang.COMMAND_HELP_SHOP.toString()); 69 | } 70 | if (sender.hasPermission("musicbox.give")) { 71 | sender.sendMessage(Lang.COMMAND_HELP_GIVE.toString()); 72 | } 73 | if (sender.hasPermission("musicbox.admin")) { 74 | sender.sendMessage(Lang.ADMIN_HELP.toArray()); 75 | } 76 | } 77 | 78 | @Override 79 | public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { 80 | if (args.length <= 1) { 81 | List tabComplete = new LinkedList<>(); 82 | if (sender.hasPermission("musicbox.use")) { 83 | tabComplete.add("play"); 84 | tabComplete.add("silent"); 85 | if (sender instanceof Player) 86 | tabComplete.add("playlist"); 87 | } 88 | if (sender.hasPermission("musicbox.shop")) 89 | tabComplete.add("shop"); 90 | if (sender.hasPermission("musicbox.give")) 91 | tabComplete.add("give"); 92 | if (sender.hasPermission("musicbox.admin")) { 93 | tabComplete.add("give_single"); 94 | tabComplete.add("shutup"); 95 | tabComplete.add("reload"); 96 | } 97 | if (args.length == 1) 98 | return tabComplete 99 | .stream() 100 | .filter(s -> s.startsWith(args[0])) 101 | .collect(Collectors.toList()); 102 | else 103 | return tabComplete; 104 | } else { 105 | SubCommand executor = subs.get(args[0].toLowerCase()); 106 | if (executor != null) { 107 | if (executor.canExecute(sender)) 108 | return executor.tabComplete(sender, ArrayUtils.removeFirst(String.class, args)); 109 | } 110 | } 111 | return Collections.emptyList(); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/SubCommand.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands; 2 | 3 | import org.bukkit.command.CommandSender; 4 | 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | public interface SubCommand { 9 | void execute(CommandSender sender, String[] args); 10 | 11 | default boolean canExecute(CommandSender sender) { 12 | return sender.hasPermission("musicbox.use"); 13 | } 14 | 15 | default List tabComplete(CommandSender player, String[] args) { 16 | return Collections.emptyList(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/subcommands/AbstractSelect.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands.subcommands; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.command.CommandSender; 5 | import org.bukkit.entity.HumanEntity; 6 | import org.bukkit.entity.Player; 7 | import ru.spliterash.musicbox.Lang; 8 | import ru.spliterash.musicbox.commands.SubCommand; 9 | import ru.spliterash.musicbox.song.MusicBoxSong; 10 | import ru.spliterash.musicbox.song.MusicBoxSongManager; 11 | import ru.spliterash.musicbox.utils.StringUtils; 12 | 13 | import java.util.Collections; 14 | import java.util.List; 15 | import java.util.stream.Stream; 16 | 17 | public abstract class AbstractSelect implements SubCommand { 18 | 19 | private final String pex; 20 | 21 | public AbstractSelect(String pex) { 22 | this.pex = pex; 23 | } 24 | @Override 25 | public boolean canExecute(CommandSender sender) { 26 | return sender.hasPermission(pex); 27 | } 28 | 29 | @Override 30 | public void execute(CommandSender sender, String[] args) { 31 | if (args.length == 0) { 32 | if (sender instanceof Player) 33 | noArgs(sender, (Player) sender); 34 | else 35 | sender.sendMessage(Lang.SPECIFY_PLAYER.toString()); 36 | return; 37 | } else if (args.length == 1) { 38 | if (!sender.hasPermission("musicbox.admin")) { 39 | sender.sendMessage(Lang.NO_PEX.toString()); 40 | return; 41 | } 42 | Player target = Bukkit.getPlayer(args[0]); 43 | if (target == null) { 44 | sender.sendMessage(Lang.PLAYER_OFLLINE.toString("{player}", args[0])); 45 | return; 46 | } 47 | 48 | noArgs(sender, target); 49 | return; 50 | } 51 | 52 | String songName = args[1].replace('_', ' '); 53 | MusicBoxSong song = MusicBoxSongManager.findByName(songName).orElse(null); 54 | if (song == null) { 55 | sender.sendMessage(Lang.SONG_NOT_FOUND.toString()); 56 | return; 57 | } 58 | Player target; 59 | if (!sender.hasPermission("musicbox.admin")) { 60 | sender.sendMessage(Lang.NO_PEX.toString()); 61 | return; 62 | } 63 | 64 | String playerName = args[0]; 65 | target = Bukkit.getPlayer(playerName); 66 | if (target == null) { 67 | sender.sendMessage(Lang.PLAYER_OFLLINE.toString("{player}", playerName)); 68 | return; 69 | } 70 | 71 | processSong(sender, target, song, args); 72 | } 73 | 74 | 75 | protected abstract void noArgs(CommandSender sender, Player player); 76 | 77 | protected abstract void processSong(CommandSender sender, Player target, MusicBoxSong song, String[] args); 78 | 79 | @Override 80 | public List tabComplete(CommandSender sender, String[] args) { 81 | if (!sender.hasPermission("musicbox.admin")) return Collections.emptyList(); 82 | 83 | if (args.length <= 1) 84 | return StringUtils.tabCompletePrepare(args, Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName)); 85 | else if (args.length <= 2) { 86 | Stream stream = MusicBoxSongManager 87 | .getRootContainer() 88 | .getAllSongs() 89 | .stream() 90 | .map(MusicBoxSong::getName) 91 | .map(s -> s.replace(' ', '_')); 92 | return StringUtils.tabCompletePrepare(args, 2, stream); 93 | } else 94 | return Collections.emptyList(); 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/subcommands/GiveExecutor.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands.subcommands; 2 | 3 | import org.bukkit.command.CommandSender; 4 | import org.bukkit.entity.Player; 5 | import ru.spliterash.musicbox.gui.GUIActions; 6 | import ru.spliterash.musicbox.players.PlayerWrapper; 7 | import ru.spliterash.musicbox.song.MusicBoxSong; 8 | 9 | public class GiveExecutor extends AbstractSelect { 10 | public GiveExecutor() { 11 | super("musicbox.give"); 12 | } 13 | @Override 14 | protected void noArgs(CommandSender sender, Player player) { 15 | GUIActions.openGiveInventoryMany(PlayerWrapper.getInstance(player)); 16 | } 17 | @Override 18 | protected void processSong(CommandSender sender, Player target, MusicBoxSong song, String[] args) { 19 | GUIActions.giveDisc(PlayerWrapper.getInstance(target), song); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/subcommands/GiveSingleExecutor.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands.subcommands; 2 | 3 | import org.bukkit.command.CommandSender; 4 | import org.bukkit.entity.Player; 5 | import ru.spliterash.musicbox.gui.GUIActions; 6 | import ru.spliterash.musicbox.players.PlayerWrapper; 7 | import ru.spliterash.musicbox.song.MusicBoxSong; 8 | 9 | public class GiveSingleExecutor extends AbstractSelect { 10 | public GiveSingleExecutor() { 11 | super("musicbox.give"); 12 | } 13 | 14 | @Override 15 | protected void noArgs(CommandSender sender, Player player) { 16 | GUIActions.openGiveInventorySingle(PlayerWrapper.getInstance(player)); 17 | } 18 | 19 | @Override 20 | protected void processSong(CommandSender sender, Player target, MusicBoxSong song, String[] args) { 21 | // Who cares....... 22 | GUIActions.giveDisc(PlayerWrapper.getInstance(target), song); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/subcommands/PlayExecutor.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands.subcommands; 2 | 3 | import org.bukkit.command.CommandSender; 4 | import org.bukkit.entity.Player; 5 | import ru.spliterash.musicbox.commands.MusicBoxExecutor; 6 | import ru.spliterash.musicbox.gui.GUIActions; 7 | import ru.spliterash.musicbox.players.PlayerWrapper; 8 | import ru.spliterash.musicbox.song.MusicBoxSong; 9 | 10 | public class PlayExecutor extends AbstractSelect { 11 | public PlayExecutor() { 12 | super("musicbox.use"); 13 | } 14 | 15 | @Override 16 | protected void noArgs(CommandSender sender, Player player) { 17 | GUIActions.openDefaultInventory(PlayerWrapper.getInstance(player)); 18 | } 19 | 20 | @Override 21 | protected void processSong(CommandSender sender, Player target, MusicBoxSong song, String[] args) { 22 | PlayerWrapper.getInstance(target).play(song); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/subcommands/PlaylistExecutor.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands.subcommands; 2 | 3 | import org.bukkit.command.CommandSender; 4 | import org.bukkit.entity.Player; 5 | import ru.spliterash.musicbox.Lang; 6 | import ru.spliterash.musicbox.commands.SubCommand; 7 | import ru.spliterash.musicbox.db.model.PlayerPlayListModel; 8 | import ru.spliterash.musicbox.gui.GUIActions; 9 | import ru.spliterash.musicbox.players.PlayerWrapper; 10 | import ru.spliterash.musicbox.utils.StringUtils; 11 | 12 | public class PlaylistExecutor implements SubCommand { 13 | @Override 14 | public void execute(CommandSender sender, String[] args) { 15 | if (!(sender instanceof Player)) { 16 | sender.sendMessage(Lang.ONLY_PLAYERS.toString()); 17 | return; 18 | } 19 | Player player = (Player) sender; 20 | if (args.length == 0) { 21 | GUIActions.openPlaylistListEditor(PlayerWrapper.getInstance(player)); 22 | return; 23 | } 24 | createPlaylist(player, args); 25 | } 26 | 27 | private void createPlaylist(Player player, String[] args) { 28 | if (args.length <= 0) { 29 | player.sendMessage(Lang.INPUT_NAME.toString()); 30 | return; 31 | } 32 | String name = StringUtils.t(String.join(" ", args)); 33 | GUIActions.openPlaylistEditor( 34 | PlayerWrapper.getInstance(player), 35 | new PlayerPlayListModel(-1, player.getUniqueId(), name) 36 | ); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/subcommands/ReloadExecutor.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands.subcommands; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.ChatColor; 5 | import org.bukkit.command.CommandSender; 6 | import ru.spliterash.musicbox.MusicBox; 7 | import ru.spliterash.musicbox.commands.SubCommand; 8 | 9 | public class ReloadExecutor implements SubCommand { 10 | @Override 11 | public void execute(CommandSender sender, String[] args) { 12 | Bukkit.getScheduler().runTaskAsynchronously(MusicBox.getInstance(), () -> { 13 | MusicBox.getInstance().reloadPlugin(); 14 | sender.sendMessage(ChatColor.GREEN + "Reloaded"); 15 | }); 16 | 17 | } 18 | 19 | @Override 20 | public boolean canExecute(CommandSender sender) { 21 | return sender.hasPermission("musicbox.admin"); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/subcommands/ShopExecutor.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands.subcommands; 2 | 3 | import org.bukkit.command.CommandSender; 4 | import org.bukkit.entity.Player; 5 | import ru.spliterash.musicbox.gui.GUIActions; 6 | import ru.spliterash.musicbox.players.PlayerWrapper; 7 | import ru.spliterash.musicbox.song.MusicBoxSong; 8 | 9 | public class ShopExecutor extends AbstractSelect { 10 | public ShopExecutor() { 11 | super("musicbox.shop"); 12 | } 13 | 14 | @Override 15 | protected void noArgs(CommandSender sender, Player player) { 16 | GUIActions.openShopInventory(PlayerWrapper.getInstance(player)); 17 | } 18 | 19 | @Override 20 | protected void processSong(CommandSender sender, Player player, MusicBoxSong song, String[] args) { 21 | GUIActions.playerBuyMusic(PlayerWrapper.getInstance(player), song); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/subcommands/ShutUp.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands.subcommands; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.command.CommandSender; 5 | import org.bukkit.entity.HumanEntity; 6 | import org.bukkit.entity.Player; 7 | import ru.spliterash.musicbox.Lang; 8 | import ru.spliterash.musicbox.commands.MusicBoxExecutor; 9 | import ru.spliterash.musicbox.commands.SubCommand; 10 | import ru.spliterash.musicbox.players.PlayerWrapper; 11 | import ru.spliterash.musicbox.utils.StringUtils; 12 | 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | public class ShutUp implements SubCommand { 17 | private final MusicBoxExecutor parent; 18 | 19 | public ShutUp(MusicBoxExecutor parent) { 20 | this.parent = parent; 21 | } 22 | 23 | @Override 24 | public void execute(CommandSender sender, String[] args) { 25 | if (args.length == 0) { 26 | parent.sendHelp(sender); 27 | return; 28 | } 29 | 30 | shutUp(sender, args); 31 | } 32 | 33 | @Override 34 | public boolean canExecute(CommandSender sender) { 35 | return sender.hasPermission("musicbox.shutup"); 36 | } 37 | 38 | @Override 39 | public List tabComplete(CommandSender sender, String[] args) { 40 | if (args.length <= 1) { 41 | return StringUtils.tabCompletePrepare(args, Bukkit 42 | .getOnlinePlayers() 43 | .stream() 44 | .map(HumanEntity::getName)); 45 | } else 46 | return Collections.emptyList(); 47 | } 48 | 49 | public void shutUp(CommandSender sender, String[] args) { 50 | Player p = Bukkit.getPlayer(args[0]); 51 | if (p == null) { 52 | sender.sendMessage(Lang.PLAYER_OFLLINE.toString("{player}", args[0])); 53 | return; 54 | } 55 | PlayerWrapper 56 | .getInstanceOptional(p) 57 | .ifPresent(PlayerWrapper::destroyActivePlayer); 58 | 59 | sender.sendMessage(Lang.SHUT_UPPED.toString("{player}", p.getName())); 60 | 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/commands/subcommands/SilentExecutor.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.commands.subcommands; 2 | 3 | import org.bukkit.Bukkit; 4 | import org.bukkit.command.CommandSender; 5 | import org.bukkit.entity.HumanEntity; 6 | import org.bukkit.entity.Player; 7 | import ru.spliterash.musicbox.Lang; 8 | import ru.spliterash.musicbox.commands.SubCommand; 9 | import ru.spliterash.musicbox.players.PlayerWrapper; 10 | import ru.spliterash.musicbox.utils.StringUtils; 11 | 12 | import java.util.Collections; 13 | import java.util.List; 14 | import java.util.stream.Stream; 15 | 16 | public class SilentExecutor implements SubCommand { 17 | @Override 18 | public void execute(CommandSender sender, String[] args) { 19 | Player target; 20 | if (args.length >= 2) { 21 | if (!sender.hasPermission("musicbox.admin")) { 22 | sender.sendMessage(Lang.NO_PEX.toString()); 23 | return; 24 | } 25 | target = Bukkit.getPlayer(args[1]); 26 | if (target == null) { 27 | sender.sendMessage(Lang.PLAYER_OFLLINE.toString("{player}", args[1])); 28 | return; 29 | } 30 | } else if (sender instanceof Player) { 31 | target = (Player) sender; 32 | } else { 33 | sender.sendMessage(Lang.SPECIFY_PLAYER.toString()); 34 | return; 35 | } 36 | PlayerWrapper wrapper = PlayerWrapper.getInstance(target); 37 | 38 | if (args.length == 0) { 39 | wrapper.setSilent(!wrapper.isSilent()); 40 | return; 41 | } 42 | 43 | if (args[0].equalsIgnoreCase("on")) 44 | wrapper.setSilent(true); 45 | else if (args[0].equalsIgnoreCase("off")) 46 | wrapper.setSilent(false); 47 | else if (args[0].equalsIgnoreCase("switch")) 48 | wrapper.setSilent(!wrapper.isSilent()); 49 | else { 50 | sender.sendMessage("Unknown type"); 51 | } 52 | 53 | if (sender != target) 54 | sender.sendMessage(Lang.SILENT_MODE_RESPONSE.toString( 55 | "{player}", target.getName(), 56 | "{state}", wrapper.isSilent() ? Lang.ENABLE.toString() : Lang.DISABLE.toString()) 57 | ); 58 | } 59 | 60 | @Override 61 | public List tabComplete(CommandSender sender, String[] args) { 62 | if (args.length <= 1) 63 | return StringUtils.tabCompletePrepare(args, Stream.of("off", "on")); 64 | else if (args.length <= 2) 65 | return StringUtils.tabCompletePrepare( 66 | args, 67 | 1, 68 | Bukkit.getOnlinePlayers().stream().map(HumanEntity::getName) 69 | ); 70 | else 71 | return Collections.emptyList(); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/abstracts/AbstractBlockPlayer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.abstracts; 2 | 3 | import com.xxmicloxx.NoteBlockAPI.songplayer.PositionSongPlayer; 4 | import lombok.Getter; 5 | import org.bukkit.Location; 6 | import org.bukkit.World; 7 | import org.bukkit.plugin.IllegalPluginAccessException; 8 | import org.bukkit.scheduler.BukkitRunnable; 9 | import ru.spliterash.musicbox.MusicBox; 10 | import ru.spliterash.musicbox.customPlayers.interfaces.IPlayList; 11 | import ru.spliterash.musicbox.customPlayers.interfaces.MusicBoxSongPlayer; 12 | import ru.spliterash.musicbox.customPlayers.interfaces.PositionPlayer; 13 | import ru.spliterash.musicbox.customPlayers.models.MusicBoxSongPlayerModel; 14 | import ru.spliterash.musicbox.customPlayers.models.RangePlayerModel; 15 | import ru.spliterash.musicbox.utils.BukkitUtils; 16 | import ru.spliterash.musicbox.utils.SignUtils; 17 | 18 | import java.util.*; 19 | import java.util.stream.Collectors; 20 | 21 | @Getter 22 | public abstract class AbstractBlockPlayer extends PositionSongPlayer implements PositionPlayer { 23 | private final static Map players = new HashMap<>(); 24 | @Getter 25 | private final static Collection all = Collections.unmodifiableCollection(players.values()); 26 | private final MusicBoxSongPlayerModel musicBoxModel; 27 | private final RangePlayerModel rangePlayerModel; 28 | private final Location location; 29 | 30 | public AbstractBlockPlayer(IPlayList list, Location location, int range) { 31 | super(list.getCurrent().getSong()); 32 | this.location = BukkitUtils.centerBlock(location); 33 | setRange(range); 34 | setTargetLocation(BukkitUtils.centerBlock(location)); 35 | AbstractBlockPlayer oldBlock = players.put(getTargetLocation(), this); 36 | if (oldBlock != null) 37 | oldBlock.destroy(); 38 | this.musicBoxModel = new MusicBoxSongPlayerModel(this, list, this::runNextSong); 39 | this.rangePlayerModel = new RangePlayerModel(musicBoxModel); 40 | musicBoxModel.runPlayer(); 41 | new BukkitRunnable() { 42 | @Override 43 | public void run() { 44 | while (!isDestroyed()) { 45 | rangePlayerModel.tick(); 46 | every100MillisAsync(); 47 | try { 48 | //noinspection BusyWait 49 | Thread.sleep(100); 50 | } catch (InterruptedException e) { 51 | e.printStackTrace(); 52 | break; 53 | } 54 | } 55 | } 56 | }.runTaskAsynchronously(MusicBox.getInstance()); 57 | } 58 | 59 | public static T findByLocation(Location location) { 60 | //noinspection unchecked 61 | return (T) players.get(BukkitUtils.centerBlock(location)); 62 | } 63 | 64 | public static Set findByChunk(World world, int x, int z) { 65 | return getAll() 66 | .stream() 67 | .filter(e -> BukkitUtils.inChunk(e.getLocation(), world, x, z)) 68 | .collect(Collectors.toSet()); 69 | 70 | } 71 | 72 | protected abstract Location getInfoSign(); 73 | 74 | 75 | protected abstract void every100MillisAsync(); 76 | 77 | protected abstract MusicBoxSongPlayer runNextSong(IPlayList list); 78 | 79 | public static Optional findByInfoSign(Location location) { 80 | //noinspection unchecked 81 | return players 82 | .values() 83 | .stream() 84 | .filter(i -> i.getInfoSign() != null && i.getInfoSign().equals(location)) 85 | .findFirst() 86 | .map(a -> (T) a); 87 | } 88 | 89 | @Override 90 | public Location getLocation() { 91 | return getTargetLocation(); 92 | } 93 | 94 | @Override 95 | public int getRange() { 96 | return getDistance(); 97 | } 98 | 99 | @Override 100 | public void setRange(int range) { 101 | setDistance(range); 102 | } 103 | 104 | @Override 105 | public boolean isDestroyed() { 106 | return destroyed; 107 | } 108 | 109 | @Override 110 | public void destroy() { 111 | if (!isDestroyed()) { 112 | try { 113 | super.destroy(); 114 | } catch (IllegalPluginAccessException ex) { 115 | // ПОФИК 116 | } 117 | players.values().remove(this); 118 | boolean normalEnd = musicBoxModel.isSongEndNormal(); 119 | if (normalEnd) 120 | songEnd(); 121 | Location infoSign = getInfoSign(); 122 | if (infoSign != null) { 123 | BukkitUtils.runSyncTask(() -> { 124 | if (!musicBoxModel.isNextCreated()) 125 | SignUtils.setPlayerOff(infoSign); 126 | }); 127 | } 128 | rangePlayerModel.destroy(); 129 | musicBoxModel.destroy(); 130 | } 131 | } 132 | 133 | /** 134 | * Вызывается в случае нормального завершения музыки 135 | */ 136 | protected abstract void songEnd(); 137 | } 138 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/interfaces/IPlayList.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.interfaces; 2 | 3 | import ru.spliterash.musicbox.song.MusicBoxSong; 4 | 5 | import java.util.List; 6 | 7 | @SuppressWarnings({"BooleanMethodIsAlwaysInverted", "unused"}) 8 | public interface IPlayList { 9 | /** 10 | * Перемещает счётчик вперёд 11 | */ 12 | void next(); 13 | 14 | /** 15 | * Список следуюших song'ов 16 | * 17 | * @param count Количество 18 | */ 19 | List getNextSongs(int count); 20 | 21 | /** 22 | * Список предыдуших song'ов 23 | * 24 | * @param count Количество 25 | */ 26 | List getPrevSongs(int count); 27 | 28 | /** 29 | * Есть ли следующая песня 30 | */ 31 | boolean hasNext(); 32 | 33 | /** 34 | * Есть ли предыдущая песня 35 | */ 36 | boolean hasPrev(); 37 | 38 | default boolean isSingleList() { 39 | return !hasNext() && !hasPrev(); 40 | } 41 | 42 | MusicBoxSong getCurrent(); 43 | 44 | void back(int count); 45 | 46 | int getSongNum(MusicBoxSong song); 47 | 48 | 49 | default boolean tryNext() { 50 | if (hasNext()) { 51 | next(); 52 | return true; 53 | } else 54 | return false; 55 | } 56 | 57 | /** 58 | * Перемотать к этой музыке (если есть) 59 | * 60 | * @param song Собственно к чему надо перематывать 61 | */ 62 | void setSong(MusicBoxSong song); 63 | } 64 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/interfaces/MusicBoxSongPlayer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.interfaces; 2 | 3 | import com.xxmicloxx.NoteBlockAPI.songplayer.SongPlayer; 4 | import ru.spliterash.musicbox.customPlayers.models.MusicBoxSongPlayerModel; 5 | import ru.spliterash.musicbox.gui.song.SPControlGUI; 6 | import ru.spliterash.musicbox.song.MusicBoxSong; 7 | 8 | import java.util.Set; 9 | import java.util.UUID; 10 | 11 | /** 12 | * Все проигрыватели созданные этим плагином 13 | */ 14 | public interface MusicBoxSongPlayer { 15 | 16 | default SPControlGUI getControl() { 17 | return getMusicBoxModel().getControlGUI(); 18 | } 19 | 20 | /** 21 | * Получить музыку которая сейчас играет 22 | */ 23 | default MusicBoxSong getMusicBoxSong() { 24 | return getMusicBoxModel().getCurrentSong(); 25 | } 26 | 27 | MusicBoxSongPlayerModel getMusicBoxModel(); 28 | 29 | /** 30 | * Для сокращения кода 31 | */ 32 | default SongPlayer getApiPlayer() { 33 | return (SongPlayer) this; 34 | } 35 | 36 | /** 37 | * Получить тик который играет в данный момент 38 | */ 39 | short getTick(); 40 | 41 | default IPlayList getPlayList() { 42 | return getMusicBoxModel().getPlayList(); 43 | } 44 | 45 | boolean isDestroyed(); 46 | 47 | default Set getPlayers() { 48 | return getApiPlayer().getPlayerUUIDs(); 49 | } 50 | 51 | /** 52 | * Вызывается event'ом когда музыка реально закончилась 53 | */ 54 | default void onSongEnd() { 55 | getMusicBoxModel().pingSongEnded(); 56 | getMusicBoxModel().onSongEnd(); 57 | } 58 | 59 | /** 60 | * Просто сокращение 61 | * Полностью убивает SongPlayer 62 | */ 63 | default void destroy() { 64 | getApiPlayer().destroy(); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/interfaces/PlayerSongPlayer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.interfaces; 2 | 3 | import ru.spliterash.musicbox.customPlayers.models.PlayerPlayerModel; 4 | 5 | /** 6 | * Название идиотское, согласен 7 | * На русском - Проигрыватель звука игрока 8 | * Помечается на все проигрыватели, так или иначе связанные с игроком 9 | */ 10 | public interface PlayerSongPlayer extends MusicBoxSongPlayer { 11 | PlayerPlayerModel getModel(); 12 | } 13 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/interfaces/PositionPlayer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.interfaces; 2 | 3 | import org.bukkit.Location; 4 | 5 | public interface PositionPlayer extends MusicBoxSongPlayer { 6 | Location getLocation(); 7 | 8 | int getRange(); 9 | 10 | void setRange(int range); 11 | } 12 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/models/MusicBoxSongPlayerModel.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.models; 2 | 3 | import com.xxmicloxx.NoteBlockAPI.songplayer.SongPlayer; 4 | import lombok.Getter; 5 | import ru.spliterash.musicbox.MusicBox; 6 | import ru.spliterash.musicbox.customPlayers.interfaces.IPlayList; 7 | import ru.spliterash.musicbox.customPlayers.interfaces.MusicBoxSongPlayer; 8 | import ru.spliterash.musicbox.gui.song.SPControlGUI; 9 | import ru.spliterash.musicbox.song.MusicBoxSong; 10 | 11 | import java.lang.reflect.Field; 12 | import java.util.*; 13 | import java.util.concurrent.locks.Lock; 14 | import java.util.function.Function; 15 | 16 | @Getter 17 | public class MusicBoxSongPlayerModel { 18 | private final static Set all = Collections.newSetFromMap(new WeakHashMap<>()); 19 | private final MusicBoxSongPlayer musicBoxSongPlayer; 20 | private final IPlayList playList; 21 | private final Function nextSongRunnable; 22 | private boolean run = false; 23 | 24 | /** 25 | * @param songPlayer плеер который связан с этой моделью 26 | * @param playList плейлист который сейчас играет 27 | * @param nextSongRunnable как ставить следующую музыку из плейлиста 28 | */ 29 | public MusicBoxSongPlayerModel(MusicBoxSongPlayer songPlayer, IPlayList playList, Function nextSongRunnable) { 30 | all.add(this); 31 | this.musicBoxSongPlayer = songPlayer; 32 | this.playList = playList; 33 | this.nextSongRunnable = nextSongRunnable; 34 | } 35 | 36 | public static void destroyAll() { 37 | all.forEach(a -> a.getMusicBoxSongPlayer().destroy()); 38 | all.clear(); 39 | } 40 | 41 | public MusicBoxSong getCurrentSong() { 42 | return playList.getCurrent(); 43 | } 44 | 45 | public void runPlayer() { 46 | if (!run) { 47 | SongPlayer songPlayer = this.musicBoxSongPlayer.getApiPlayer(); 48 | if (MusicBox.getInstance().getConfigObject().isEnable10octave()) { 49 | songPlayer.setEnable10Octave(true); 50 | } 51 | songPlayer.setPlaying(true); 52 | run = true; 53 | } 54 | } 55 | 56 | /** 57 | * Вызывается при вызове {@link SongPlayer#destroy()} 58 | */ 59 | public void destroy() { 60 | if (controlGUI != null) 61 | controlGUI.close(); 62 | } 63 | 64 | private SPControlGUI controlGUI; 65 | 66 | /** 67 | * Создаёт GUI для настройки этого SongPlayer'а 68 | */ 69 | public SPControlGUI getControlGUI() { 70 | if (controlGUI == null) 71 | controlGUI = new SPControlGUI(this); 72 | return controlGUI; 73 | } 74 | // Немного чернухи 75 | 76 | private static final Field lockField; 77 | 78 | private static final Field playersField; 79 | 80 | static { 81 | try { 82 | playersField = SongPlayer.class.getDeclaredField("playerList"); 83 | lockField = SongPlayer.class.getDeclaredField("lock"); 84 | playersField.setAccessible(true); 85 | lockField.setAccessible(true); 86 | } catch (NoSuchFieldException e) { 87 | throw new RuntimeException(e); 88 | } 89 | } 90 | 91 | private Lock getLock() throws IllegalAccessException { 92 | return (Lock) lockField.get(musicBoxSongPlayer); 93 | } 94 | 95 | private Map getPlayers() throws IllegalAccessException { 96 | //noinspection unchecked 97 | return (Map) playersField.get(musicBoxSongPlayer); 98 | } 99 | 100 | public void setPlayers(Collection players) { 101 | try { 102 | Map map = getPlayers(); 103 | if (map.keySet().containsAll(players) && !players.isEmpty()) 104 | return; 105 | Lock lock = getLock(); 106 | lock.lock(); 107 | try { 108 | map.clear(); 109 | players.forEach(p -> map.put(p, true)); 110 | } finally { 111 | lock.unlock(); 112 | } 113 | } catch (IllegalAccessException e) { 114 | throw new RuntimeException(e); 115 | } 116 | } 117 | 118 | /** 119 | * Применяет следующий плейлист 120 | */ 121 | private void acceptNext() { 122 | MusicBoxSongPlayer nextPlayer = nextSongRunnable.apply(playList); 123 | if (nextPlayer != null && controlGUI != null) 124 | controlGUI.openNext(nextPlayer.getMusicBoxModel()); 125 | } 126 | 127 | /** 128 | * Вызывается из event'a 129 | */ 130 | public void onSongEnd() { 131 | startNext(); 132 | } 133 | 134 | private boolean nextCreated = false; 135 | 136 | public void createNextPlayer() { 137 | nextCreated = true; 138 | getMusicBoxSongPlayer().destroy(); 139 | acceptNext(); 140 | } 141 | 142 | /** 143 | * Завершилась ли музыка сама по себе, или её destroy() 144 | */ 145 | private boolean songEndNormal = false; 146 | 147 | /** 148 | * Возможно костыль, но сначало нужно destroy SongPlayer а потом его модель 149 | */ 150 | public void pingSongEnded() { 151 | songEndNormal = true; 152 | } 153 | 154 | public void startNext() { 155 | if (playList.tryNext()) { 156 | createNextPlayer(); 157 | } else 158 | getMusicBoxSongPlayer().destroy(); 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/models/PlayerPlayerModel.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.models; 2 | 3 | import com.xxmicloxx.NoteBlockAPI.songplayer.SongPlayer; 4 | import lombok.Getter; 5 | import ru.spliterash.musicbox.Lang; 6 | import ru.spliterash.musicbox.players.PlayerWrapper; 7 | 8 | /** 9 | * Небольшая модель 10 | * Которая применима ко всем проигрывателям игроков 11 | */ 12 | @Getter 13 | public class PlayerPlayerModel { 14 | 15 | private final PlayerWrapper wrapper; 16 | private final MusicBoxSongPlayerModel model; 17 | 18 | public PlayerPlayerModel(PlayerWrapper wrapper, MusicBoxSongPlayerModel model) { 19 | this.wrapper = wrapper; 20 | this.model = model; 21 | wrapper.setBarProgress(0); 22 | wrapper.setBarVisible(true); 23 | wrapper.setBarTitle(Lang.CURRENT_PLAYNING.toString("{song}", model.getCurrentSong().getName())); 24 | SongPlayer songPlay = model.getMusicBoxSongPlayer().getApiPlayer(); 25 | songPlay.addPlayer(wrapper.getPlayer()); 26 | } 27 | 28 | /** 29 | * Вызывается до воспроизведения следующего тика 30 | * 31 | * @param all Кол-во тиков в мелодии 32 | * @param current Текущий тик 33 | */ 34 | public void nextTick(int all, int current) { 35 | if (current == -1) { 36 | return; 37 | } 38 | double progress = (double) current / (double) all; 39 | if (progress >= 0 && progress <= 1) { 40 | wrapper.setBarProgress(progress); 41 | } 42 | } 43 | 44 | public void destroy() { 45 | wrapper.nullActivePlayer(getModel().getMusicBoxSongPlayer()); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/models/PositionPlayerModel.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.models; 2 | 3 | import lombok.Getter; 4 | import ru.spliterash.musicbox.customPlayers.interfaces.PositionPlayer; 5 | import ru.spliterash.musicbox.song.MusicBoxSong; 6 | 7 | @Getter 8 | public class PositionPlayerModel { 9 | private final PositionPlayer positionPlayer; 10 | private final MusicBoxSong song; 11 | 12 | public PositionPlayerModel(PositionPlayer positionPlayer, MusicBoxSong song) { 13 | this.positionPlayer = positionPlayer; 14 | this.song = song; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/models/RangePlayerModel.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.models; 2 | 3 | import lombok.Getter; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.entity.Entity; 6 | import ru.spliterash.musicbox.MusicBox; 7 | import ru.spliterash.musicbox.customPlayers.interfaces.MusicBoxSongPlayer; 8 | import ru.spliterash.musicbox.customPlayers.interfaces.PositionPlayer; 9 | import ru.spliterash.musicbox.customPlayers.objects.SpeakerPlayer; 10 | import ru.spliterash.musicbox.players.PlayerWrapper; 11 | 12 | import java.util.HashSet; 13 | import java.util.Set; 14 | import java.util.UUID; 15 | import java.util.stream.Collectors; 16 | import java.util.stream.Stream; 17 | 18 | @Getter 19 | public class RangePlayerModel { 20 | private final MusicBoxSongPlayerModel musicBoxModel; 21 | private final Set players = new HashSet<>(); 22 | private int destroyMillis; 23 | private int emptyMillis = 0; 24 | 25 | public RangePlayerModel(MusicBoxSongPlayerModel musicBoxModel) { 26 | this.musicBoxModel = musicBoxModel; 27 | destroyMillis = MusicBox.getInstance().getConfigObject().getAutoDestroy() * 1000; 28 | players.addAll(getSongPlayer().getPlayers()); 29 | } 30 | 31 | /** 32 | * Устанавливает новое значение после которого SP будет уничтожен 33 | */ 34 | public void setAutoDestroyMillis(int millis) { 35 | this.destroyMillis = millis; 36 | emptyMillis = 0; 37 | } 38 | 39 | public PositionPlayer getSongPlayer() { 40 | return (PositionPlayer) musicBoxModel.getMusicBoxSongPlayer(); 41 | } 42 | 43 | public void destroy() { 44 | // Потом может быть 45 | } 46 | 47 | /** 48 | * Обновление игроков 49 | * Вызывается в асинхронне каждые 100 милисов 50 | */ 51 | public void tick() { 52 | Stream ownerStream; 53 | MusicBoxSongPlayer sp = musicBoxModel.getMusicBoxSongPlayer(); 54 | if (sp instanceof SpeakerPlayer) 55 | ownerStream = Stream.of(((SpeakerPlayer) sp).getOwner().getPlayer()).map(Entity::getUniqueId); 56 | else 57 | ownerStream = Stream.empty(); 58 | 59 | Set canHear = Stream.concat(Bukkit 60 | .getOnlinePlayers() 61 | .stream() 62 | .filter(p -> PlayerWrapper.getInstance(p).canHearMusic()) 63 | .filter(p -> p.getWorld().equals(getSongPlayer().getLocation().getWorld())) 64 | .filter(p -> p.getLocation().distanceSquared(getSongPlayer().getLocation()) < Math.pow(getSongPlayer().getRange() + 10, 2)) 65 | .map(Entity::getUniqueId), ownerStream) 66 | .collect(Collectors.toSet()); 67 | if (destroyMillis > 0 && canHear.size() == 0) { 68 | if (emptyMillis >= destroyMillis) { 69 | getSongPlayer().destroy(); 70 | return; 71 | } 72 | emptyMillis += 100; 73 | } else 74 | emptyMillis = 0; 75 | getMusicBoxModel().setPlayers(canHear); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/objects/RadioPlayer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.objects; 2 | 3 | import com.xxmicloxx.NoteBlockAPI.songplayer.RadioSongPlayer; 4 | import lombok.Getter; 5 | import org.bukkit.entity.Player; 6 | import org.bukkit.plugin.IllegalPluginAccessException; 7 | import ru.spliterash.musicbox.customPlayers.interfaces.IPlayList; 8 | import ru.spliterash.musicbox.customPlayers.interfaces.PlayerSongPlayer; 9 | import ru.spliterash.musicbox.customPlayers.models.MusicBoxSongPlayerModel; 10 | import ru.spliterash.musicbox.customPlayers.models.PlayerPlayerModel; 11 | import ru.spliterash.musicbox.players.PlayerWrapper; 12 | import ru.spliterash.musicbox.utils.SongUtils; 13 | 14 | /** 15 | * Проигрыватель для игрока 16 | * Если игрок захочет послушать музыку никого не напрягая 17 | */ 18 | @Getter 19 | public class RadioPlayer extends RadioSongPlayer implements PlayerSongPlayer { 20 | private final PlayerPlayerModel model; 21 | private final MusicBoxSongPlayerModel musicBoxModel; 22 | 23 | 24 | public RadioPlayer(IPlayList list, PlayerWrapper wrapper) { 25 | super(list.getCurrent().getSong()); 26 | this.musicBoxModel = new MusicBoxSongPlayerModel(this, list, SongUtils.nextPlayerSong(wrapper)); 27 | this.model = new PlayerPlayerModel(wrapper, musicBoxModel); 28 | musicBoxModel.runPlayer(); 29 | 30 | } 31 | 32 | 33 | @Override 34 | public void destroy() { 35 | if (!isDestroyed()) { 36 | try { 37 | super.destroy(); 38 | } catch (IllegalPluginAccessException ex) { 39 | // ПОФИК 40 | } 41 | model.destroy(); 42 | musicBoxModel.destroy(); 43 | } 44 | } 45 | 46 | @Override 47 | public boolean isDestroyed() { 48 | return destroyed; 49 | } 50 | 51 | @Override 52 | public void playTick(Player player, int tick) { 53 | super.playTick(player, tick); 54 | if (player.equals(model.getWrapper().getPlayer())) { 55 | model.nextTick(getSong().getLength(), tick); 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/objects/SpeakerPlayer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.objects; 2 | 3 | import com.xxmicloxx.NoteBlockAPI.songplayer.EntitySongPlayer; 4 | import lombok.Getter; 5 | import org.bukkit.Location; 6 | import org.bukkit.Particle; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.plugin.IllegalPluginAccessException; 9 | import org.bukkit.scheduler.BukkitRunnable; 10 | import org.bukkit.scheduler.BukkitTask; 11 | import ru.spliterash.musicbox.MusicBox; 12 | import ru.spliterash.musicbox.customPlayers.interfaces.IPlayList; 13 | import ru.spliterash.musicbox.customPlayers.interfaces.PlayerSongPlayer; 14 | import ru.spliterash.musicbox.customPlayers.interfaces.PositionPlayer; 15 | import ru.spliterash.musicbox.customPlayers.models.MusicBoxSongPlayerModel; 16 | import ru.spliterash.musicbox.customPlayers.models.PlayerPlayerModel; 17 | import ru.spliterash.musicbox.customPlayers.models.RangePlayerModel; 18 | import ru.spliterash.musicbox.players.PlayerWrapper; 19 | import ru.spliterash.musicbox.utils.SongUtils; 20 | 21 | /** 22 | * Проигрыватель для игрока 23 | * Но его слышат все вокруг 24 | */ 25 | @Getter 26 | public class SpeakerPlayer extends EntitySongPlayer implements PlayerSongPlayer, PositionPlayer { 27 | 28 | private final MusicBoxSongPlayerModel musicBoxModel; 29 | private final PlayerPlayerModel model; 30 | private final RangePlayerModel rangeModel; 31 | private final BukkitTask task; 32 | private final PlayerWrapper owner; 33 | 34 | public SpeakerPlayer(IPlayList list, PlayerWrapper wrapper) { 35 | super(list.getCurrent().getSong()); 36 | this.musicBoxModel = new MusicBoxSongPlayerModel(this, list, SongUtils.nextPlayerSong(wrapper)); 37 | this.model = new PlayerPlayerModel(wrapper, musicBoxModel); 38 | this.rangeModel = new RangePlayerModel(musicBoxModel); 39 | this.owner = wrapper; 40 | setEntity(wrapper.getPlayer()); 41 | setRange(MusicBox.getInstance().getConfigObject().getSpeakerRadius()); 42 | 43 | musicBoxModel.runPlayer(); 44 | task = new BukkitRunnable() { 45 | @Override 46 | public void run() { 47 | while (!isDestroyed()) { 48 | rangeModel.tick(); 49 | try { 50 | //noinspection BusyWait 51 | Thread.sleep(100); 52 | } catch (InterruptedException e) { 53 | e.printStackTrace(); 54 | break; 55 | } 56 | } 57 | } 58 | }.runTaskAsynchronously(MusicBox.getInstance()); 59 | } 60 | 61 | @Override 62 | public void destroy() { 63 | if (!isDestroyed()) { 64 | try { 65 | super.destroy(); 66 | } catch (IllegalPluginAccessException ex) { 67 | // ПОФИК 68 | } 69 | rangeModel.destroy(); 70 | model.destroy(); 71 | musicBoxModel.destroy(); 72 | } 73 | } 74 | 75 | @Override 76 | public boolean isDestroyed() { 77 | return destroyed; 78 | } 79 | 80 | @Override 81 | public void playTick(Player player, int tick) { 82 | super.playTick(player, tick); 83 | if (player.equals(model.getWrapper().getPlayer())) { 84 | model.nextTick(getSong().getLength(), tick); 85 | spawnNote(tick, player); 86 | } 87 | } 88 | 89 | private void spawnNote(int tick, Player player) { 90 | //Если это не пустой тик то 91 | if (song 92 | .getLayerHashMap() 93 | .values() 94 | .stream() 95 | .anyMatch(l -> l.getNote(tick) != null) 96 | ) { 97 | Location spawnLocation = player.getLocation().add(0, 2.3, 0); 98 | player.getWorld().spawnParticle(Particle.NOTE, spawnLocation, 1); 99 | } 100 | } 101 | 102 | @Override 103 | public Location getLocation() { 104 | return model.getWrapper().getPlayer().getLocation(); 105 | } 106 | 107 | @Override 108 | public int getRange() { 109 | return super.getDistance(); 110 | } 111 | 112 | @Override 113 | public void setRange(int range) { 114 | super.setDistance(range); 115 | } 116 | 117 | 118 | } 119 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/objects/jukebox/JukeboxPlayer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.objects.jukebox; 2 | 3 | import lombok.Getter; 4 | import org.bukkit.Location; 5 | import org.bukkit.block.Block; 6 | import org.bukkit.block.BlockState; 7 | import org.bukkit.block.Jukebox; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.event.player.PlayerInteractEvent; 10 | import org.bukkit.inventory.ItemStack; 11 | import org.jetbrains.annotations.NotNull; 12 | import ru.spliterash.musicbox.Lang; 13 | import ru.spliterash.musicbox.MusicBox; 14 | import ru.spliterash.musicbox.customPlayers.abstracts.AbstractBlockPlayer; 15 | import ru.spliterash.musicbox.customPlayers.interfaces.IPlayList; 16 | import ru.spliterash.musicbox.minecraft.nms.jukebox.JukeboxFactory; 17 | import ru.spliterash.musicbox.song.MusicBoxSong; 18 | import ru.spliterash.musicbox.song.MusicBoxSongManager; 19 | import ru.spliterash.musicbox.utils.BukkitUtils; 20 | import ru.spliterash.musicbox.utils.SignUtils; 21 | 22 | @Getter 23 | public class JukeboxPlayer extends AbstractBlockPlayer { 24 | private Location infoSign; 25 | 26 | private JukeboxPlayer(IPlayList list, int range, Jukebox box) { 27 | super(list, box.getLocation(), range); 28 | SignUtils 29 | .findSign(box.getLocation()) 30 | .ifPresent(s -> { 31 | infoSign = s.getLocation(); 32 | SignUtils.setPlayListInfo(infoSign, list); 33 | }); 34 | } 35 | 36 | public static void onJukeboxClick(Jukebox jukebox, ItemStack clickedItem, PlayerInteractEvent e) { 37 | JukeboxPlayer sp = AbstractBlockPlayer.findByLocation(jukebox.getLocation()); 38 | if (clickedItem == null && sp == null) 39 | return; 40 | if (sp != null) { 41 | sp.destroy(); 42 | } 43 | if (clickedItem == null) 44 | return; 45 | MusicBoxSong song = MusicBoxSongManager.findByItem(clickedItem).orElse(null); 46 | if (song == null) { 47 | return; 48 | } 49 | if (JukeboxFactory.jukeboxAvailable()) { 50 | e.setCancelled(true); 51 | e.getPlayer().getInventory().setItemInMainHand(null); 52 | JukeboxFactory.getJukebox(jukebox).setJukebox(clickedItem); 53 | 54 | createNew(jukebox); 55 | } else { 56 | e.getPlayer().sendMessage(Lang.JUKEBOX_NOT_SUPPORTED.toString()); 57 | } 58 | } 59 | 60 | private static void createNew(Jukebox jukebox) { 61 | try { 62 | JukeboxPlaylistImpl playlist = new JukeboxPlaylistImpl(jukebox.getLocation()); 63 | new JukeboxPlayer(playlist, MusicBox.getInstance().getConfigObject().getJukeboxRadius(), jukebox); 64 | } catch (JukeboxPlaylistInitException e) { 65 | // NOTHING 66 | } 67 | } 68 | 69 | /** 70 | * Вызывается когда игрок кликает с зажатым шифтом 71 | */ 72 | public static void onSneakingClick(Jukebox jukebox, Player player) { 73 | JukeboxPlayer songPlayer = AbstractBlockPlayer.findByLocation(jukebox.getLocation()); 74 | if (songPlayer != null) { 75 | songPlayer.getControl().open(player); 76 | } 77 | } 78 | 79 | /** 80 | * Вызывается когда редстоун тычет 81 | * 82 | * @param box Проигрыватель 83 | * @param source Откуда пришёл сигнал 84 | * @param power Сила сигнала 85 | */ 86 | public static void onRedstone(Jukebox box, Block source, int power) { 87 | if (power > 0) { 88 | JukeboxPlayer player = AbstractBlockPlayer.findByLocation(box.getLocation()); 89 | if (player != null) { 90 | player.getMusicBoxModel().startNext(); 91 | } else if (JukeboxFactory.jukeboxAvailable()) 92 | createNew(box); 93 | } 94 | } 95 | 96 | @Override 97 | protected void every100MillisAsync() { 98 | BukkitUtils.runSyncTask(() -> { 99 | Block b = getTargetLocation().getBlock(); 100 | if (!(b.getState() instanceof Jukebox)) 101 | destroy(); 102 | }); 103 | } 104 | 105 | @Override 106 | protected JukeboxPlayer runNextSong(IPlayList list) { 107 | @NotNull BlockState state = getTargetLocation().getBlock().getState(); 108 | if (state instanceof Jukebox) { 109 | return new JukeboxPlayer(list, getRange(), (Jukebox) state); 110 | } else 111 | return null; 112 | } 113 | 114 | @Override 115 | protected void songEnd() { 116 | // NOTHING 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/objects/jukebox/JukeboxPlaylistInitException.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.objects.jukebox; 2 | 3 | public class JukeboxPlaylistInitException extends Exception { 4 | public JukeboxPlaylistInitException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/playlist/ListPlaylist.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.playlist; 2 | 3 | import ru.spliterash.musicbox.customPlayers.interfaces.IPlayList; 4 | import ru.spliterash.musicbox.song.MusicBoxSong; 5 | import ru.spliterash.musicbox.utils.classes.PeekList; 6 | import ru.spliterash.musicbox.song.songContainers.types.SongContainer; 7 | 8 | import java.util.List; 9 | 10 | public class ListPlaylist implements IPlayList { 11 | private final PeekList peekList; 12 | 13 | public ListPlaylist(List songs) { 14 | this(songs, false); 15 | } 16 | 17 | /** 18 | * Создаёт PlayList из списка 19 | * 20 | * @param songs Список музыки 21 | * @param hasEnd Если false то лист крутится без остановки 22 | */ 23 | public ListPlaylist(List songs, boolean hasEnd) { 24 | if (songs.size() == 0) 25 | throw new RuntimeException("List can't be 0 size"); 26 | this.peekList = new PeekList<>(songs, hasEnd); 27 | } 28 | 29 | public static ListPlaylist fromContainer(SongContainer container, boolean rand, boolean hasEnd) { 30 | return new ListPlaylist(rand ? container.getSongsShuffle() : container.getAllSongs(), hasEnd); 31 | } 32 | 33 | @Override 34 | public void next() { 35 | peekList.next(); 36 | } 37 | 38 | @Override 39 | public List getNextSongs(int count) { 40 | return peekList.getNextElements(count); 41 | } 42 | 43 | 44 | @Override 45 | public boolean hasNext() { 46 | return peekList.hasNext(); 47 | } 48 | 49 | @Override 50 | public boolean hasPrev() { 51 | return peekList.hasPrev(); 52 | } 53 | 54 | @Override 55 | public List getPrevSongs(int count) { 56 | return peekList.getPrevElements(count); 57 | } 58 | 59 | @Override 60 | public MusicBoxSong getCurrent() { 61 | return peekList.current(); 62 | } 63 | 64 | @Override 65 | public void back(int count) { 66 | for (int i = 0; i < count; i++) { 67 | peekList.prev(); 68 | } 69 | } 70 | 71 | @Override 72 | public int getSongNum(MusicBoxSong song) { 73 | return peekList.getIndexOf(song); 74 | } 75 | 76 | @Override 77 | public void setSong(MusicBoxSong song) { 78 | peekList.moveTo(song); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/customPlayers/playlist/SingletonPlayList.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.customPlayers.playlist; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import ru.spliterash.musicbox.customPlayers.interfaces.IPlayList; 5 | import ru.spliterash.musicbox.song.MusicBoxSong; 6 | 7 | import java.util.Collections; 8 | import java.util.List; 9 | 10 | /** 11 | * Небольшая имплементация плейлиста 12 | * Содерижит только одну музыку и то, отдаст её только один раз 13 | */ 14 | @RequiredArgsConstructor 15 | public class SingletonPlayList implements IPlayList { 16 | private final MusicBoxSong song; 17 | 18 | @Override 19 | public void next() { 20 | // Тоже нет 21 | } 22 | 23 | @Override 24 | public List getNextSongs(int a) { 25 | return Collections.emptyList(); 26 | 27 | } 28 | 29 | @Override 30 | public boolean hasNext() { 31 | return false; 32 | } 33 | 34 | @Override 35 | public boolean hasPrev() { 36 | return false; 37 | } 38 | 39 | @Override 40 | public boolean isSingleList() { 41 | return true; 42 | } 43 | 44 | @Override 45 | public List getPrevSongs(int count) { 46 | return Collections.emptyList(); 47 | } 48 | 49 | @Override 50 | public MusicBoxSong getCurrent() { 51 | return song; 52 | } 53 | 54 | @Override 55 | public void back(int count) { 56 | // NO 57 | } 58 | 59 | @Override 60 | public int getSongNum(MusicBoxSong song) { 61 | return 0; 62 | } 63 | 64 | @Override 65 | public void setSong(MusicBoxSong song) { 66 | // НЕА 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/db/DatabaseLoader.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.db; 2 | 3 | 4 | import ru.spliterash.musicbox.MusicBox; 5 | import ru.spliterash.musicbox.db.types.SQLite; 6 | 7 | import java.io.File; 8 | 9 | 10 | public class DatabaseLoader { 11 | private static DatabaseLoader instance; 12 | private final AbstractBase base; 13 | 14 | public static void reload() { 15 | instance = new DatabaseLoader(); 16 | } 17 | 18 | public static AbstractBase getBase() { 19 | return instance.base; 20 | } 21 | 22 | private DatabaseLoader() { 23 | try { 24 | base = new SQLite(new File(MusicBox.getInstance().getDataFolder(), "base.db")); 25 | 26 | } catch (Exception ex) { 27 | throw new RuntimeException("Can't connect to db", ex); 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/db/model/PlayerPlayListModel.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.db.model; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | import lombok.Setter; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.entity.Player; 8 | import ru.spliterash.musicbox.db.DatabaseLoader; 9 | import ru.spliterash.musicbox.players.PlayerWrapper; 10 | import ru.spliterash.musicbox.song.MusicBoxSong; 11 | import ru.spliterash.musicbox.song.songContainers.types.SongContainer; 12 | import ru.spliterash.musicbox.song.songContainers.factory.ListContainerFactory; 13 | 14 | import java.util.LinkedList; 15 | import java.util.List; 16 | import java.util.Optional; 17 | import java.util.UUID; 18 | 19 | @Getter 20 | @Setter 21 | @AllArgsConstructor 22 | public class PlayerPlayListModel implements SongContainer { 23 | private int id; 24 | private final UUID owner; 25 | private String name; 26 | private final List songs = new LinkedList<>(); 27 | 28 | /** 29 | * Возращает владельца если тот в сети 30 | */ 31 | public Optional getOwnerWrapper() { 32 | Player player = Bukkit.getPlayer(owner); 33 | if (player == null) 34 | return Optional.empty(); 35 | else 36 | return Optional.of(PlayerWrapper.getInstance(player)); 37 | } 38 | 39 | public void save() { 40 | DatabaseLoader.getBase().savePlayList(this); 41 | } 42 | 43 | public void delete() { 44 | DatabaseLoader.getBase().deleteMe(this); 45 | } 46 | 47 | @Override 48 | public String getNameId() { 49 | return ListContainerFactory.NAME + ":" + id; 50 | } 51 | 52 | } 53 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/db/types/SQLite.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.db.types; 2 | 3 | import ru.spliterash.musicbox.db.AbstractBase; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.lang.reflect.InvocationHandler; 8 | import java.lang.reflect.Proxy; 9 | import java.sql.Connection; 10 | import java.sql.DriverManager; 11 | import java.sql.SQLException; 12 | 13 | public class SQLite extends AbstractBase { 14 | private final File file; 15 | 16 | public SQLite(File file) { 17 | super("SQLite"); 18 | this.file = file; 19 | if (!file.exists()) { 20 | try { 21 | //noinspection ResultOfMethodCallIgnored 22 | file.createNewFile(); 23 | } catch (IOException e) { 24 | throw new IllegalArgumentException("File write error: " + file); 25 | } 26 | } 27 | try { 28 | Class.forName("org.sqlite.JDBC"); 29 | } catch (ClassNotFoundException ex) { 30 | throw new IllegalArgumentException("jdbc driver unavailable!"); 31 | } 32 | afterInit(); 33 | } 34 | 35 | 36 | @Override 37 | protected Connection getConnection() throws SQLException { 38 | return DriverManager.getConnection("jdbc:sqlite:" + file); 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/db/utils/NamedParamStatement.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.db.utils; 2 | 3 | import org.intellij.lang.annotations.Language; 4 | import ru.spliterash.musicbox.db.AbstractBase; 5 | 6 | import java.sql.Connection; 7 | import java.sql.PreparedStatement; 8 | import java.sql.ResultSet; 9 | import java.sql.SQLException; 10 | import java.util.*; 11 | import java.util.regex.Matcher; 12 | import java.util.regex.Pattern; 13 | import java.util.stream.Collectors; 14 | 15 | public class NamedParamStatement { 16 | private static final Pattern findParametersPattern = Pattern.compile("(?> map = new HashMap<>(); 19 | 20 | public NamedParamStatement(@Language("SQL") String query) { 21 | this.query = query; 22 | } 23 | 24 | private PreparedStatement prepareStatement(Connection connection) throws SQLException { 25 | Matcher matcher = findParametersPattern.matcher(query); 26 | final String finalQuery; 27 | List result = new ArrayList<>(map.size()); 28 | StringBuilder queryBuilder = new StringBuilder(); 29 | int oldEnd = 0; 30 | while (matcher.find()) { 31 | queryBuilder.append(query, oldEnd, matcher.start()); 32 | oldEnd = matcher.end(); 33 | String key = matcher.group().substring(1); 34 | Collection set = map.get(key); 35 | StringBuilder replaceTo = new StringBuilder(); 36 | if (set != null && set.size() > 0) { 37 | result.addAll(set); 38 | for (int i = 0; i < set.size(); i++) { 39 | replaceTo.append('?'); 40 | if (i < set.size() - 1) 41 | replaceTo.append(','); 42 | } 43 | } else { 44 | replaceTo.append('?'); 45 | result.add(null); 46 | } 47 | queryBuilder.append(replaceTo); 48 | } 49 | // Если не было ничо 50 | if (oldEnd == 0) 51 | finalQuery = query; 52 | else 53 | finalQuery = queryBuilder.append(query, oldEnd, query.length()).toString(); 54 | PreparedStatement statement = connection.prepareStatement(finalQuery); 55 | for (int i = 0; i < result.size(); i++) { 56 | AbstractBase.setValue(statement, i, result.get(i)); 57 | } 58 | reset(); 59 | return statement; 60 | } 61 | 62 | public ResultSet executeQuery(Connection connection) throws SQLException { 63 | return prepareStatement(connection).executeQuery(); 64 | } 65 | 66 | public int executeUpdate(Connection connection) throws SQLException { 67 | return prepareStatement(connection).executeUpdate(); 68 | } 69 | 70 | /** 71 | * Очищает карту и можно пихать следующие данные 72 | */ 73 | public void reset() { 74 | map.clear(); 75 | } 76 | 77 | public void setValue(String key, Object value) { 78 | map.put(key, Collections.singleton(value)); 79 | } 80 | 81 | 82 | public void setValues(String key, Collection values) { 83 | map.put(key, values); 84 | } 85 | 86 | public void setValues(String key, T[] values) { 87 | Set set = Arrays.stream(values).collect(Collectors.toSet()); 88 | map.put(key, set); 89 | } 90 | } -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/db/utils/ResultSetRow.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.db.utils; 2 | 3 | import lombok.Builder; 4 | import lombok.Singular; 5 | 6 | import java.util.Map; 7 | 8 | @Builder 9 | public class ResultSetRow { 10 | @Singular("addResultRow") 11 | private final Map result; 12 | 13 | public Integer getInt(String key) { 14 | return (Integer) result.get(key); 15 | } 16 | 17 | public String getString(String key) { 18 | return result.get(key).toString(); 19 | } 20 | 21 | public Integer getInt(int i) { 22 | int k = -1; 23 | for (Map.Entry entry : result.entrySet()) { 24 | if (++k == i) { 25 | return (Integer) entry.getValue(); 26 | } 27 | } 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/events/SourcedBlockRedstoneEvent.java: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | /* 3 | * Copyright (C) 2010, 2011 sk89q 4 | * 5 | * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public 6 | * License as published by the Free 7 | * Software Foundation, either version 3 of the License, or (at your option) any later version. 8 | * 9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied 10 | * warranty of MERCHANTABILITY or 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. 12 | * 13 | * You should have received a copy of the GNU General Public License along with this program. If not, 14 | * see . 15 | */ 16 | 17 | package ru.spliterash.musicbox.events; 18 | 19 | import org.bukkit.block.Block; 20 | import org.bukkit.event.HandlerList; 21 | import org.bukkit.event.block.BlockRedstoneEvent; 22 | 23 | /** 24 | * A variation of the redstone event with a source block. 25 | */ 26 | public class SourcedBlockRedstoneEvent extends BlockRedstoneEvent { 27 | 28 | protected final Block source; 29 | private static final HandlerList handlers = new HandlerList(); 30 | 31 | public SourcedBlockRedstoneEvent(Block source, Block block, int old, int n) { 32 | 33 | super(block, old, n); 34 | this.source = source; 35 | } 36 | 37 | public Block getSource() { 38 | 39 | return source; 40 | } 41 | 42 | public boolean hasChanged() { 43 | 44 | return getOldCurrent() != getNewCurrent(); 45 | } 46 | 47 | public boolean isMinor() { 48 | 49 | return !hasChanged() || wasOn() == isOn(); 50 | } 51 | 52 | public boolean isOn() { 53 | 54 | return getNewCurrent() > 0; 55 | } 56 | 57 | public boolean wasOn() { 58 | 59 | return getOldCurrent() > 0; 60 | } 61 | 62 | @Override 63 | public HandlerList getHandlers() { 64 | return handlers; 65 | } 66 | 67 | public static HandlerList getHandlerList() { 68 | return handlers; 69 | } 70 | } -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/gui/playlist/PlayListListGUI.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.gui.playlist; 2 | 3 | import com.cryptomorin.xseries.XMaterial; 4 | import org.bukkit.entity.Player; 5 | import org.bukkit.inventory.ItemStack; 6 | import ru.spliterash.musicbox.Lang; 7 | import ru.spliterash.musicbox.db.DatabaseLoader; 8 | import ru.spliterash.musicbox.db.model.PlayerPlayListModel; 9 | import ru.spliterash.musicbox.minecraft.gui.GUI; 10 | import ru.spliterash.musicbox.minecraft.gui.InventoryAction; 11 | import ru.spliterash.musicbox.minecraft.gui.actions.ClickAction; 12 | import ru.spliterash.musicbox.players.PlayerWrapper; 13 | import ru.spliterash.musicbox.song.MusicBoxSong; 14 | import ru.spliterash.musicbox.song.MusicBoxSongManager; 15 | import ru.spliterash.musicbox.utils.ItemUtils; 16 | import ru.spliterash.musicbox.utils.StringUtils; 17 | import ru.spliterash.musicbox.song.songContainers.types.SongContainer; 18 | 19 | import java.util.List; 20 | import java.util.function.Function; 21 | 22 | /** 23 | * Класс для создания инвентаря со списком плейлистов 24 | */ 25 | public class PlayListListGUI { 26 | private final List list; 27 | private final PlayerWrapper wrapper; 28 | 29 | public PlayListListGUI(PlayerWrapper wrapper) { 30 | this.wrapper = wrapper; 31 | this.list = DatabaseLoader.getBase().getPlayLists(wrapper.getPlayer().getUniqueId()); 32 | } 33 | 34 | /** 35 | * Собсна открывает игроку инвентарь 36 | * 37 | * @param onSelect - Что делать с выбранном плейлистом(если null то это master плейлист) 38 | */ 39 | public void openPage(int page, Function onSelect, Function> extraLore) { 40 | int offset = page * 45; 41 | int lastPage = getLastPage(); 42 | GUI gui = new GUI(Lang.PLAYLIST_LIST_TITLE.toString( 43 | "{page}", String.valueOf(page + 1), 44 | "{last_page}", String.valueOf(lastPage) 45 | )); 46 | gui.open(wrapper.getPlayer()); 47 | for (int i = 0; i < 45; i++) { 48 | int listIndex = offset + i; 49 | if (listIndex >= list.size()) 50 | break; 51 | PlayerPlayListModel element = list.get(listIndex); 52 | List lore = Lang.PLAYLIST_LORE.toList( 53 | "{count}", String.valueOf(element.getSongs().size()), 54 | "{duration}", StringUtils.toHumanTime(element 55 | .getSongs() 56 | .stream() 57 | .mapToInt(MusicBoxSong::getDuration) 58 | .sum()) 59 | ); 60 | if (extraLore != null) 61 | lore.addAll(extraLore.apply(element)); 62 | ItemStack stack = ItemUtils.createStack( 63 | XMaterial.PAPER, 64 | Lang.PLAYLIST_NAME.toString("{name}", element.getName()), 65 | lore); 66 | gui.addItem(i, stack, onSelect.apply(element)); 67 | } 68 | // Создать новый плейлист 69 | gui.addItem( 70 | 49, 71 | ItemUtils.createStack(XMaterial.SUGAR, Lang.CREATE_NEW_PLAYLIST.toString(), null), 72 | new ClickAction(() -> { 73 | Player p = wrapper.getPlayer(); 74 | p.closeInventory(); 75 | p.sendMessage(Lang.NEW_PLAYLIST_MESSAGE.toString()); 76 | }) 77 | ); 78 | // Главный плейлист 79 | gui.addItem( 80 | 46, 81 | ItemUtils.createStack(XMaterial.DIAMOND, Lang.MASTER_PLAYLIST.toString(), Lang.MASTER_PLAYLIST_LORE.toList()), 82 | onSelect.apply(MusicBoxSongManager.getMasterContainer()) 83 | ); 84 | // Пагинация 85 | if (page > 0) 86 | gui.addItem( 87 | 45, 88 | ItemUtils.createStack(XMaterial.MAGMA_CREAM, Lang.BACK.toString(), null), 89 | new ClickAction(() -> openPage(page - 1, onSelect, extraLore))); 90 | if ((lastPage - 1) > page) 91 | gui.addItem( 92 | 53, 93 | ItemUtils.createStack(XMaterial.MAGMA_CREAM, Lang.NEXT.toString(), null), 94 | new ClickAction(() -> openPage( 95 | page + 1, onSelect, extraLore))); 96 | } 97 | 98 | private int getLastPage() { 99 | return (int) Math.ceil(list.size() / 45D); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/minecraft/gui/GUI.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.gui; 2 | 3 | 4 | import com.cryptomorin.xseries.XSound; 5 | import lombok.Getter; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.entity.Player; 8 | import org.bukkit.event.EventHandler; 9 | import org.bukkit.event.Listener; 10 | import org.bukkit.event.inventory.InventoryClickEvent; 11 | import org.bukkit.inventory.Inventory; 12 | import org.bukkit.inventory.InventoryHolder; 13 | import org.bukkit.inventory.ItemStack; 14 | import ru.spliterash.musicbox.MusicBox; 15 | import ru.spliterash.musicbox.utils.BukkitUtils; 16 | 17 | import java.util.HashMap; 18 | import java.util.Map; 19 | import java.util.concurrent.ExecutionException; 20 | 21 | @SuppressWarnings("unused") 22 | public class GUI implements InventoryHolder { 23 | 24 | static { 25 | Bukkit.getPluginManager().registerEvents(new Listener() { 26 | @EventHandler 27 | public void onClick(InventoryClickEvent e) { 28 | if (e.getInventory().getHolder() instanceof GUI) { 29 | ((GUI) e.getInventory().getHolder()).onInventoryClick(e); 30 | } 31 | } 32 | 33 | }, MusicBox.getInstance()); 34 | } 35 | 36 | @Getter 37 | private Inventory inventory; 38 | private final Map runnableMap = new HashMap<>(); 39 | 40 | public GUI(String title, int rows) { 41 | createInventory(title, rows); 42 | } 43 | 44 | private void createInventory(String title, int rows) { 45 | if (Bukkit.isPrimaryThread()) 46 | inventory = Bukkit.createInventory(this, 9 * rows, title); 47 | else { 48 | try { 49 | inventory = Bukkit 50 | .getScheduler() 51 | .callSyncMethod( 52 | MusicBox.getInstance(), 53 | () -> Bukkit.createInventory(GUI.this, 9 * rows, title)) 54 | .get(); 55 | } catch (InterruptedException | ExecutionException e) { 56 | throw new RuntimeException(e); 57 | } 58 | } 59 | } 60 | 61 | public GUI(String title) { 62 | this(title, 6); 63 | } 64 | 65 | public void open(Player player) { 66 | BukkitUtils.runSyncTask(() -> player.openInventory(getInventory())); 67 | } 68 | 69 | public void clear() { 70 | inventory.clear(); 71 | runnableMap.clear(); 72 | } 73 | 74 | public void addItem(int slot, ItemStack item, InventoryAction runnable) { 75 | inventory.setItem(slot, item); 76 | runnableMap.put(slot, runnable); 77 | } 78 | 79 | public void removeItem(int slot) { 80 | inventory.clear(slot); 81 | runnableMap.remove(slot); 82 | } 83 | 84 | public void onInventoryClick(InventoryClickEvent e) { 85 | e.setCancelled(true); 86 | if (e.getClickedInventory() == null || e.getClickedInventory().getHolder() != this) 87 | return; 88 | InventoryAction action = runnableMap.get(e.getSlot()); 89 | if (action == null) 90 | return; 91 | XSound.UI_BUTTON_CLICK.play(e.getWhoClicked()); 92 | action.onEvent(e); 93 | } 94 | 95 | /** 96 | * Поскольку у созданого инвентаря нельзя сменить титл, то только так 97 | * 98 | * @param title Новый титл 99 | * @return Новый GUI с новым титлом 100 | */ 101 | public GUI cloneWithNewTitle(String title) { 102 | ItemStack[] content = inventory.getContents(); 103 | GUI gui = new GUI(title, content.length); 104 | gui.runnableMap.putAll(runnableMap); 105 | gui.inventory.setContents(content); 106 | return gui; 107 | } 108 | 109 | } -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/minecraft/gui/InventoryAction.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.gui; 2 | 3 | import org.bukkit.event.inventory.InventoryClickEvent; 4 | 5 | public interface InventoryAction { 6 | void onEvent(InventoryClickEvent e); 7 | } 8 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/minecraft/gui/actions/ClickAction.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.gui.actions; 2 | 3 | import org.bukkit.event.inventory.InventoryClickEvent; 4 | import ru.spliterash.musicbox.minecraft.gui.InventoryAction; 5 | 6 | import java.util.Optional; 7 | 8 | @SuppressWarnings("OptionalUsedAsFieldOrParameterType") 9 | public class ClickAction implements InventoryAction { 10 | private final Optional left; 11 | private final Optional right; 12 | 13 | public ClickAction(Runnable left, Runnable right) { 14 | this.left = Optional.ofNullable(left); 15 | this.right = Optional.ofNullable(right); 16 | } 17 | 18 | public ClickAction(Runnable left) { 19 | this(left, null); 20 | } 21 | 22 | 23 | @Override 24 | final public void onEvent(InventoryClickEvent e) { 25 | switch (e.getClick()) { 26 | case LEFT: 27 | left.ifPresent(Runnable::run); 28 | break; 29 | case RIGHT: 30 | right.ifPresent(Runnable::run); 31 | break; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/minecraft/gui/actions/PlayerClickAction.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.gui.actions; 2 | 3 | import org.bukkit.entity.Player; 4 | import org.bukkit.event.inventory.InventoryClickEvent; 5 | import ru.spliterash.musicbox.minecraft.gui.InventoryAction; 6 | 7 | import java.util.Optional; 8 | import java.util.function.Consumer; 9 | 10 | @SuppressWarnings("OptionalUsedAsFieldOrParameterType") 11 | public class PlayerClickAction implements InventoryAction { 12 | private final Optional> left; 13 | private final Optional> right; 14 | 15 | public PlayerClickAction(Consumer onLeftClick, Consumer onRightClick) { 16 | this.left = Optional.ofNullable(onLeftClick); 17 | this.right = Optional.ofNullable(onRightClick); 18 | } 19 | 20 | public PlayerClickAction(Consumer onLeftClick) { 21 | this(onLeftClick, null); 22 | } 23 | 24 | @Override 25 | final public void onEvent(InventoryClickEvent e) { 26 | Player p = (Player) e.getWhoClicked(); 27 | switch (e.getClick()) { 28 | case LEFT: 29 | left.ifPresent(c -> c.accept(p)); 30 | break; 31 | case RIGHT: 32 | right.ifPresent(r -> r.accept(p)); 33 | break; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/minecraft/nms/versionutils/NewVersion.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.versionutils; 2 | 3 | import org.bukkit.block.Block; 4 | import org.bukkit.block.BlockFace; 5 | import org.bukkit.block.data.BlockData; 6 | import org.bukkit.block.data.Directional; 7 | import org.bukkit.block.data.Powerable; 8 | import org.bukkit.block.data.Rotatable; 9 | 10 | public class NewVersion implements VersionUtils { 11 | @Override 12 | public BlockFace getRotation(Block block) { 13 | MyRotate rotate = MyRotate.by(block.getBlockData()); 14 | 15 | if (rotate == null) 16 | return BlockFace.SELF; 17 | return rotate.getRotate(); 18 | 19 | } 20 | 21 | @Override 22 | public void setRotation(Block block, BlockFace face) { 23 | MyRotate rotate = MyRotate.by(block.getBlockData()); 24 | 25 | if (rotate == null) 26 | return; 27 | 28 | rotate.setRotate(face); 29 | block.setBlockData(rotate.getData(), false); 30 | } 31 | 32 | @Override 33 | public void setLever(Block block, boolean powered) { 34 | if (block.getBlockData() instanceof Powerable) { 35 | Powerable data = (Powerable) block.getBlockData(); 36 | data.setPowered(powered); 37 | block.setBlockData(data, true); 38 | } 39 | } 40 | 41 | private interface MyRotate { 42 | void setRotate(BlockFace rotate); 43 | 44 | BlockFace getRotate(); 45 | 46 | static MyRotate by(BlockData data) { 47 | if (data instanceof Directional) 48 | return new BlockFaceRotate((Directional) data); 49 | else if (data instanceof Rotatable) 50 | return new RotatableRotate((Rotatable) data); 51 | else 52 | return null; 53 | } 54 | 55 | BlockData getData(); 56 | } 57 | 58 | private static class BlockFaceRotate implements MyRotate { 59 | 60 | private final Directional directional; 61 | 62 | private BlockFaceRotate(Directional directional) { 63 | this.directional = directional; 64 | } 65 | 66 | @Override 67 | public void setRotate(BlockFace rotate) { 68 | directional.setFacing(rotate); 69 | } 70 | 71 | @Override 72 | public BlockFace getRotate() { 73 | return directional.getFacing(); 74 | } 75 | 76 | @Override 77 | public BlockData getData() { 78 | return directional; 79 | } 80 | } 81 | 82 | private static class RotatableRotate implements MyRotate { 83 | private final Rotatable rotatable; 84 | 85 | private RotatableRotate(Rotatable rotatable) { 86 | this.rotatable = rotatable; 87 | } 88 | 89 | @Override 90 | public void setRotate(BlockFace rotate) { 91 | this.rotatable.setRotation(rotate); 92 | } 93 | 94 | @Override 95 | public BlockFace getRotate() { 96 | return this.rotatable.getRotation(); 97 | } 98 | 99 | @Override 100 | public BlockData getData() { 101 | return rotatable; 102 | } 103 | } 104 | } 105 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/minecraft/nms/versionutils/OldVersion.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.versionutils; 2 | 3 | import org.bukkit.block.Block; 4 | import org.bukkit.block.BlockFace; 5 | import org.bukkit.block.BlockState; 6 | import org.bukkit.material.Directional; 7 | import org.bukkit.material.Lever; 8 | import org.bukkit.material.MaterialData; 9 | 10 | @SuppressWarnings("deprecation") 11 | public class OldVersion implements VersionUtils { 12 | 13 | @Override 14 | public BlockFace getRotation(Block block) { 15 | BlockState state = block.getState(); 16 | MaterialData data = state.getData(); 17 | if (data instanceof org.bukkit.material.Directional) 18 | return ((org.bukkit.material.Directional) data).getFacing(); 19 | else 20 | return null; 21 | } 22 | 23 | @Override 24 | public void setRotation(Block block, BlockFace face) { 25 | BlockState state = block.getState(); 26 | MaterialData data = state.getData(); 27 | if (data instanceof org.bukkit.material.Directional) { 28 | ((Directional) data).setFacingDirection(face); 29 | state.setData(data); 30 | state.update(true, true); 31 | } 32 | } 33 | 34 | @Override 35 | public void setLever(Block block, boolean powered) { 36 | BlockState state = block.getState(); 37 | MaterialData data = state.getData(); 38 | if (data instanceof Lever) { 39 | Lever lever = (Lever) data; 40 | lever.setPowered(powered); 41 | state.setData(lever); 42 | state.update(true, true); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/minecraft/nms/versionutils/VersionUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.versionutils; 2 | 3 | import org.bukkit.block.Block; 4 | import org.bukkit.block.BlockFace; 5 | 6 | public interface VersionUtils { 7 | 8 | BlockFace getRotation(Block block); 9 | 10 | void setRotation(Block block, BlockFace face); 11 | 12 | void setLever(Block block, boolean powered); 13 | } 14 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/minecraft/nms/versionutils/VersionUtilsFactory.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.minecraft.nms.versionutils; 2 | 3 | import lombok.Getter; 4 | import ru.spliterash.musicbox.minecraft.nms.NMSUtils; 5 | 6 | public class VersionUtilsFactory { 7 | @Getter 8 | private static final VersionUtils instance; 9 | 10 | static { 11 | int iV = NMSUtils.getVersion(); 12 | if (iV >= 13) { 13 | instance = new NewVersion(); 14 | } else { 15 | instance = new OldVersion(); 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/MusicBoxSong.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song; 2 | 3 | import com.cryptomorin.xseries.XMaterial; 4 | import com.xxmicloxx.NoteBlockAPI.model.Song; 5 | import com.xxmicloxx.NoteBlockAPI.utils.NBSDecoder; 6 | import lombok.Getter; 7 | import org.bukkit.inventory.ItemStack; 8 | import org.bukkit.inventory.meta.ItemMeta; 9 | import ru.spliterash.musicbox.Lang; 10 | import ru.spliterash.musicbox.utils.*; 11 | import ru.spliterash.musicbox.utils.nbt.NBTFactory; 12 | import ru.spliterash.musicbox.utils.nbt.NbtConstants; 13 | 14 | import java.io.File; 15 | import java.lang.ref.WeakReference; 16 | import java.util.Collections; 17 | import java.util.HashMap; 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | @Getter 22 | public class MusicBoxSong { 23 | 24 | private final File file; 25 | private final String name; 26 | private final Map hoverMap = new HashMap<>(); 27 | private final MusicBoxSongContainer container; 28 | private final short length; 29 | private final float speed; 30 | private transient WeakReference songReference; 31 | private final int hash; 32 | 33 | MusicBoxSong(File songFile, MusicBoxSongContainer container) { 34 | this.file = songFile; 35 | this.container = container; 36 | Song song = getSong(); 37 | this.name = StringUtils.t(StringUtils.getOrEmpty(song.getTitle(), () -> FileUtils.getFilename(file.getName()))); 38 | this.length = song.getLength(); 39 | this.speed = song.getSpeed(); 40 | this.hash = file.getPath().hashCode(); 41 | String time = StringUtils.toHumanTime(getDuration()); 42 | hoverMap.put("{length}", time); 43 | hoverMap.put("{author}", song.getAuthor()); 44 | hoverMap.put("{original_author}", song.getOriginalAuthor()); 45 | hoverMap.put("{name}", getName()); 46 | } 47 | 48 | public int getDuration() { 49 | return (int) Math.floor(length / speed); 50 | } 51 | 52 | public ItemStack getSongStack(XMaterial material) { 53 | return getSongStack(material, Collections.emptyList(), false); 54 | } 55 | 56 | public ItemStack getSongStack(XMaterial material, List extraLines, boolean glow) { 57 | return getSongStack(material, Lang.SONG_NAME.toString("{song}", getName()), extraLines, glow); 58 | } 59 | 60 | /** 61 | * @param material Какой материал использовать 62 | * @return Айтем с этим материалом 63 | */ 64 | public ItemStack getSongStack(XMaterial material, String itemName, List extraLines, boolean glow) { 65 | ItemStack stack = material.parseItem(); 66 | ItemMeta meta = stack.getItemMeta(); 67 | meta.setDisplayName(itemName); 68 | List list = ArrayUtils.replaceOrRemove(Lang.SONG_LORE.toList(), hoverMap); 69 | list.addAll(extraLines); 70 | meta.setLore(list); 71 | stack.setItemMeta(meta); 72 | stack = NBTFactory.NBT_HANDLER.setNbt(stack, NbtConstants.NBT_NAME, getHash()); 73 | if (glow) 74 | stack = ItemUtils.glow(stack); 75 | return stack; 76 | } 77 | 78 | /** 79 | * Смотрит есть ли Song в референсе 80 | * И если нету, то отдаёт загруженный с диска файл 81 | *

82 | * Немного подвиснет сервак кнч, но зато оперативка чистая 83 | */ 84 | public Song getSong() throws SongNullException { 85 | if (songReference == null || songReference.get() == null) { 86 | Song song = loadFromDisc(); 87 | if (song == null) { 88 | throw new SongNullException("Song can't be loaded"); 89 | } 90 | songReference = new WeakReference<>(song); 91 | return song; 92 | } else 93 | return songReference.get(); 94 | } 95 | 96 | /** 97 | * Загружает инстанц прямо с диска 98 | * То есть, создаёт новый объект 99 | */ 100 | private Song loadFromDisc() { 101 | return NBSDecoder.parse(file); 102 | } 103 | 104 | public ItemStack getSongStack() { 105 | return getSongStack(BukkitUtils.getRandomDisc()); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/MusicBoxSongContainer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song; 2 | 3 | import com.cryptomorin.xseries.XMaterial; 4 | import lombok.Getter; 5 | import org.bukkit.ChatColor; 6 | import org.bukkit.inventory.ItemStack; 7 | import org.bukkit.inventory.meta.ItemMeta; 8 | import ru.spliterash.musicbox.Lang; 9 | import ru.spliterash.musicbox.MusicBox; 10 | import ru.spliterash.musicbox.gui.song.SongContainerGUI; 11 | import ru.spliterash.musicbox.players.PlayerWrapper; 12 | import ru.spliterash.musicbox.song.songContainers.factory.FolderContainerFactory; 13 | import ru.spliterash.musicbox.song.songContainers.types.FullSongContainer; 14 | import ru.spliterash.musicbox.song.songContainers.types.SubSongContainer; 15 | import ru.spliterash.musicbox.utils.FileUtils; 16 | import ru.spliterash.musicbox.utils.JavaUtils; 17 | import ru.spliterash.musicbox.utils.StringUtils; 18 | 19 | import java.io.File; 20 | import java.io.IOException; 21 | import java.util.*; 22 | import java.util.function.Function; 23 | 24 | @Getter 25 | public class MusicBoxSongContainer implements SubSongContainer, FullSongContainer { 26 | private final MusicBoxSongContainer parent; 27 | private List subContainers; 28 | private List songs; 29 | private final String name; 30 | private final List lore; 31 | private final int hash; 32 | 33 | public MusicBoxSongContainer(File folder, MusicBoxSongContainer parent) { 34 | this(folder, parent, true); 35 | } 36 | 37 | public MusicBoxSongContainer(File folder, MusicBoxSongContainer parent, boolean keepFolderName) { 38 | if (!folder.isDirectory()) { 39 | throw new RuntimeException("File is not folder"); 40 | } 41 | this.parent = parent; 42 | if (keepFolderName) 43 | name = StringUtils.t(folder.getName()); 44 | else 45 | name = ""; 46 | File infoFile = new File(folder, "info.txt"); 47 | if (infoFile.isFile()) { 48 | List tempLore; 49 | try { 50 | tempLore = FileUtils.readFileToList(infoFile); 51 | 52 | } catch (IOException ex) { 53 | tempLore = JavaUtils.stackTraceToList(ex.getStackTrace()); 54 | } 55 | lore = Collections.unmodifiableList(StringUtils.t(tempLore)); 56 | } else { 57 | lore = Collections.emptyList(); 58 | } 59 | hash = folder.getPath().hashCode(); 60 | loadSongs(Objects.requireNonNull(folder.listFiles(f -> f.getName().endsWith(".nbs")))); 61 | loadSubContainers(Objects.requireNonNull(folder.listFiles(File::isDirectory))); 62 | } 63 | 64 | /** 65 | * Загружает папки 66 | */ 67 | private void loadSubContainers(File[] folders) { 68 | ArrayList subContainersTemp = new ArrayList<>(folders.length); 69 | for (File folder : folders) { 70 | MusicBoxSongContainer container = new MusicBoxSongContainer(folder, this); 71 | subContainersTemp.add(container); 72 | } 73 | subContainersTemp.sort(Comparator.comparing(container -> ChatColor.stripColor(container.getName()))); 74 | 75 | subContainers = Collections.unmodifiableList(subContainersTemp); 76 | } 77 | 78 | /** 79 | * Загружает музыку из текущей папки 80 | */ 81 | private void loadSongs(File[] songFiles) { 82 | ArrayList songsTemp = new ArrayList<>(songFiles.length); 83 | for (File file : songFiles) { 84 | try { 85 | MusicBoxSong song = new MusicBoxSong(file, this); 86 | songsTemp.add(song); 87 | } catch (SongNullException e) { 88 | MusicBox.getInstance().getLogger().warning("Can't load " + file); 89 | } 90 | } 91 | 92 | songsTemp.sort(Comparator.comparing(song -> ChatColor.stripColor(song.getName()))); 93 | 94 | songs = Collections.unmodifiableList(songsTemp); 95 | } 96 | 97 | /** 98 | * Создать GUI для этого контейнера 99 | */ 100 | public SongContainerGUI createGUI(PlayerWrapper player) { 101 | return new SongContainerGUI(this, player); 102 | } 103 | 104 | public ItemStack getItemStack() { 105 | return getItemStack(Collections.emptyList()); 106 | } 107 | 108 | public ItemStack getItemStack(List extraLines) { 109 | ItemStack chest = XMaterial.CHEST.parseItem(); 110 | ItemMeta meta = chest.getItemMeta(); 111 | meta.setDisplayName(Lang.FOLDER_FORMAT.toString("{folder}", getName())); 112 | List tempLore; 113 | if (extraLines.size() > 0) { 114 | tempLore = new ArrayList<>(lore); 115 | tempLore.addAll(extraLines); 116 | } else 117 | tempLore = lore; 118 | meta.setLore(tempLore); 119 | chest.setItemMeta(meta); 120 | return chest; 121 | } 122 | 123 | public MusicBoxSongContainer findById(int id) { 124 | if (getHash() == id) 125 | return this; 126 | for (MusicBoxSongContainer container : subContainers) { 127 | MusicBoxSongContainer c = container.findById(id); 128 | if (c != null) 129 | return c; 130 | } 131 | return null; 132 | } 133 | 134 | @Override 135 | public String getNameId() { 136 | return FolderContainerFactory.NAME + ":" + getHash(); 137 | } 138 | 139 | @Override 140 | public List getSubContainers() { 141 | return subContainers; 142 | } 143 | 144 | @Override 145 | public SubSongContainer getParentContainer() { 146 | return getParent(); 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/MusicBoxSongManager.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song; 2 | 3 | import lombok.Getter; 4 | import lombok.experimental.UtilityClass; 5 | import org.bukkit.inventory.ItemStack; 6 | import ru.spliterash.musicbox.song.songContainers.SongContainerFactory; 7 | import ru.spliterash.musicbox.song.songContainers.factory.FolderContainerFactory; 8 | import ru.spliterash.musicbox.song.songContainers.factory.ListContainerFactory; 9 | import ru.spliterash.musicbox.song.songContainers.factory.SingletonContainerFactory; 10 | import ru.spliterash.musicbox.song.songContainers.types.SongContainer; 11 | import ru.spliterash.musicbox.utils.nbt.NBTFactory; 12 | import ru.spliterash.musicbox.utils.nbt.NbtConstants; 13 | 14 | import java.io.File; 15 | import java.util.*; 16 | 17 | @SuppressWarnings("unused") 18 | @UtilityClass 19 | 20 | public class MusicBoxSongManager { 21 | public final String MASTER_CONTAINER = "MASTER"; 22 | private final Set> factorySet = new HashSet<>(); 23 | @Getter 24 | private final SongContainer masterContainer = new MasterContainer(); 25 | // Для быстрого поиска 26 | @Getter 27 | private List allSongs; 28 | @Getter 29 | private MusicBoxSongContainer rootContainer; 30 | 31 | static { 32 | factorySet.add(new FolderContainerFactory()); 33 | factorySet.add(new SingletonContainerFactory()); 34 | factorySet.add(new ListContainerFactory()); 35 | } 36 | 37 | public Optional getContainerById(String str) { 38 | if (str.equals(MASTER_CONTAINER)) 39 | return Optional.of(masterContainer); 40 | String[] split = str.split(":"); 41 | if (split.length != 2) 42 | return Optional.empty(); 43 | int id; 44 | try { 45 | id = Integer.parseInt(split[1]); 46 | } catch (Exception ex) { 47 | return Optional.empty(); 48 | } 49 | return factorySet 50 | .stream() 51 | .filter(c -> c.getKey().equalsIgnoreCase(split[0])) 52 | .findFirst() 53 | .map(f -> f.parseContainer(id)); 54 | 55 | } 56 | 57 | public void reload(File rootFolder) { 58 | rootContainer = new MusicBoxSongContainer(rootFolder, null, false); 59 | // ArrayList так как по нему быстрее искать элементы 60 | allSongs = Collections.unmodifiableList(new ArrayList<>(rootContainer.getAllSongs())); 61 | } 62 | 63 | public Optional findByName(String name) { 64 | return allSongs 65 | .stream() 66 | .filter(s -> s.getName().equals(name)) 67 | .findFirst(); 68 | } 69 | 70 | public Optional findSongByHash(int hash) { 71 | return allSongs 72 | .stream() 73 | .filter(s -> s.getHash() == hash) 74 | .findFirst(); 75 | } 76 | 77 | public Optional findByItem(ItemStack stack) { 78 | if (stack == null) 79 | return Optional.empty(); 80 | int hash = NBTFactory.NBT_HANDLER.getNbt(stack, NbtConstants.NBT_NAME); 81 | if (hash != 0) 82 | return findSongByHash(hash); 83 | else 84 | return Optional.empty(); 85 | } 86 | 87 | public Optional findContainerById(int id) { 88 | return Optional.of(rootContainer.findById(id)); 89 | } 90 | 91 | /** 92 | * Имплементация контейнера, содержащая всё что только есть 93 | */ 94 | @SuppressWarnings("RedundantModifiersUtilityClassLombok") 95 | private static class MasterContainer implements SongContainer { 96 | 97 | @Override 98 | public String getNameId() { 99 | return MASTER_CONTAINER; 100 | } 101 | 102 | @Override 103 | public List getSongs() { 104 | ArrayList list = new ArrayList<>(allSongs); 105 | Collections.shuffle(list); 106 | return list; 107 | } 108 | 109 | @Override 110 | public List getSongsShuffle() { 111 | return getSongs(); 112 | } 113 | } 114 | 115 | } 116 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/SongNullException.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song; 2 | 3 | public class SongNullException extends RuntimeException { 4 | public SongNullException(String s) { 5 | super(s); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/songContainers/SongContainerFactory.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song.songContainers; 2 | 3 | import ru.spliterash.musicbox.song.songContainers.types.SongContainer; 4 | 5 | public interface SongContainerFactory { 6 | String getKey(); 7 | 8 | T parseContainer(int id); 9 | } 10 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/songContainers/containers/SingletonContainer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song.songContainers.containers; 2 | 3 | import lombok.RequiredArgsConstructor; 4 | import ru.spliterash.musicbox.song.songContainers.types.SongContainer; 5 | import ru.spliterash.musicbox.song.MusicBoxSong; 6 | import ru.spliterash.musicbox.song.songContainers.factory.SingletonContainerFactory; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | /** 12 | * По названию можно и догадаться, содержит в себе 1 единственную музыку 13 | */ 14 | @RequiredArgsConstructor 15 | public class SingletonContainer implements SongContainer { 16 | 17 | private final MusicBoxSong song; 18 | 19 | @Override 20 | public String getNameId() { 21 | return SingletonContainerFactory.NAME+":" + song.getHash(); 22 | } 23 | 24 | @Override 25 | public List getSongs() { 26 | return Collections.singletonList(song); 27 | } 28 | 29 | @Override 30 | public List getSongsShuffle() { 31 | return getSongs(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/songContainers/factory/FolderContainerFactory.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song.songContainers.factory; 2 | 3 | import ru.spliterash.musicbox.song.MusicBoxSongContainer; 4 | import ru.spliterash.musicbox.song.MusicBoxSongManager; 5 | import ru.spliterash.musicbox.song.songContainers.SongContainerFactory; 6 | 7 | public class FolderContainerFactory implements SongContainerFactory { 8 | public static final String NAME = "CHEST"; 9 | 10 | @Override 11 | public String getKey() { 12 | return NAME; 13 | } 14 | 15 | @Override 16 | public MusicBoxSongContainer parseContainer(int id) { 17 | return MusicBoxSongManager 18 | .findContainerById(id) 19 | .orElse(null); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/songContainers/factory/ListContainerFactory.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song.songContainers.factory; 2 | 3 | import ru.spliterash.musicbox.db.DatabaseLoader; 4 | import ru.spliterash.musicbox.db.model.PlayerPlayListModel; 5 | import ru.spliterash.musicbox.song.songContainers.SongContainerFactory; 6 | 7 | public class ListContainerFactory implements SongContainerFactory { 8 | public static String NAME = "LIST"; 9 | 10 | @Override 11 | public String getKey() { 12 | return NAME; 13 | } 14 | 15 | @Override 16 | public PlayerPlayListModel parseContainer(int id) { 17 | return DatabaseLoader.getBase().getPlayListById(id); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/songContainers/factory/SingletonContainerFactory.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song.songContainers.factory; 2 | 3 | import ru.spliterash.musicbox.song.MusicBoxSongManager; 4 | import ru.spliterash.musicbox.song.songContainers.SongContainerFactory; 5 | import ru.spliterash.musicbox.song.songContainers.containers.SingletonContainer; 6 | 7 | public class SingletonContainerFactory implements SongContainerFactory { 8 | public static String NAME = "ID"; 9 | 10 | @Override 11 | public String getKey() { 12 | return NAME; 13 | } 14 | 15 | @Override 16 | public SingletonContainer parseContainer(int id) { 17 | return MusicBoxSongManager 18 | .findSongByHash(id) 19 | .map(SingletonContainer::new) 20 | .orElse(null); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/songContainers/types/FullSongContainer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song.songContainers.types; 2 | 3 | import org.bukkit.inventory.ItemStack; 4 | 5 | import java.util.Collections; 6 | import java.util.List; 7 | 8 | public interface FullSongContainer extends SubSongContainer { 9 | default ItemStack getItemStack() { 10 | return getItemStack(Collections.emptyList()); 11 | } 12 | 13 | ItemStack getItemStack(List extraLines); 14 | 15 | String getName(); 16 | } 17 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/songContainers/types/SongContainer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song.songContainers.types; 2 | 3 | import ru.spliterash.musicbox.song.MusicBoxSong; 4 | 5 | import java.util.ArrayList; 6 | import java.util.Collections; 7 | import java.util.List; 8 | 9 | public interface SongContainer { 10 | String getNameId(); 11 | 12 | List getSongs(); 13 | 14 | default List getSongsShuffle() { 15 | List list = new ArrayList<>(getSongs()); 16 | Collections.shuffle(list); 17 | return list; 18 | } 19 | 20 | default List getSongsRand(boolean rand) { 21 | return rand ? getSongsShuffle() : getSongs(); 22 | } 23 | 24 | default List getAllSongs() { 25 | return getSongs(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/song/songContainers/types/SubSongContainer.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.song.songContainers.types; 2 | 3 | import ru.spliterash.musicbox.song.MusicBoxSong; 4 | import ru.spliterash.musicbox.song.MusicBoxSongContainer; 5 | 6 | import java.util.LinkedList; 7 | import java.util.List; 8 | 9 | public interface SubSongContainer extends SongContainer { 10 | List getSubContainers(); 11 | 12 | SubSongContainer getParentContainer(); 13 | 14 | /** 15 | * Возращает всю музыку с учётом саб контейнеров и в них и в них 16 | * Рекурсивная крч фигня 17 | */ 18 | @Override 19 | default List getAllSongs() { 20 | // Так как мы будем очень часто добавлять в него переменные 21 | List list = new LinkedList<>(getSongs()); 22 | for (SongContainer container : getSubContainers()) { 23 | list.addAll(container.getAllSongs()); 24 | } 25 | return list; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/ArrayUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import com.cryptomorin.xseries.XMaterial; 4 | import lombok.experimental.UtilityClass; 5 | 6 | import java.lang.reflect.Array; 7 | import java.util.List; 8 | import java.util.Map; 9 | import java.util.Random; 10 | 11 | @UtilityClass 12 | public class ArrayUtils { 13 | public void replaceOrRemove(List list, String key, String value) { 14 | for (int i = 0; i < list.size(); i++) { 15 | String element = list.get(i); 16 | if (!element.contains(key)) 17 | continue; 18 | if (value != null && !value.isEmpty()) { 19 | list.set(i, element.replace(key, value)); 20 | } else { 21 | list.remove(i); 22 | i--; 23 | } 24 | 25 | } 26 | } 27 | 28 | public T[] removeFirst(Class clazz, T[] source) { 29 | if (source.length == 0) 30 | return source; 31 | //noinspection unchecked 32 | T[] result = (T[]) Array.newInstance(clazz, source.length - 1); 33 | System.arraycopy(source, 1, result, 0, source.length - 1); 34 | return result; 35 | } 36 | 37 | 38 | /** 39 | * Заменяет элементы в мапе 40 | * Если элемент не найден, то удаляет строку 41 | * 42 | * @param list Лист в котором надо заменить 43 | * @param replaceMap Карта замены 44 | * @return тот же лист 45 | */ 46 | public List replaceOrRemove(List list, Map replaceMap) { 47 | for (int i = 0; i < list.size(); i++) { 48 | String element = list.get(i); 49 | boolean found = false; 50 | String newString = element; 51 | boolean contains = false; 52 | for (Map.Entry entry : replaceMap.entrySet()) { 53 | String key = entry.getKey(); 54 | //Есть ли в этой строке вообще плейсхолдеры 55 | if (!element.contains(key)) 56 | continue; 57 | String value = entry.getValue(); 58 | contains = true; 59 | if (value == null || value.isEmpty()) { 60 | newString = newString.replace(entry.getKey(), ""); 61 | continue; 62 | } 63 | //Уже не удаляем 64 | found = true; 65 | newString = newString.replace(entry.getKey(), entry.getValue()); 66 | } 67 | if (!contains) 68 | continue; 69 | if (!found) { 70 | list.remove(i); 71 | i--; 72 | } else { 73 | list.set(i, newString); 74 | } 75 | 76 | } 77 | return list; 78 | } 79 | 80 | public T getRandom(List list) { 81 | Random rand = new Random(); 82 | return list.get(rand.nextInt(list.size())); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/BukkitUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import com.cryptomorin.xseries.XMaterial; 4 | import lombok.experimental.UtilityClass; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.Location; 7 | import org.bukkit.World; 8 | import org.bukkit.entity.Player; 9 | import org.bukkit.inventory.Inventory; 10 | import org.bukkit.inventory.InventoryHolder; 11 | import org.bukkit.metadata.MetadataValue; 12 | import org.bukkit.metadata.Metadatable; 13 | import org.jetbrains.annotations.Nullable; 14 | import ru.spliterash.musicbox.MusicBox; 15 | 16 | import java.util.Arrays; 17 | import java.util.Collections; 18 | import java.util.List; 19 | import java.util.Set; 20 | import java.util.stream.Collectors; 21 | 22 | @UtilityClass 23 | public class BukkitUtils { 24 | public final List DISCS = Collections.unmodifiableList( 25 | Arrays.asList( 26 | XMaterial.MUSIC_DISC_13, 27 | XMaterial.MUSIC_DISC_BLOCKS, 28 | XMaterial.MUSIC_DISC_CAT, 29 | XMaterial.MUSIC_DISC_CHIRP, 30 | XMaterial.MUSIC_DISC_FAR, 31 | XMaterial.MUSIC_DISC_MALL, 32 | XMaterial.MUSIC_DISC_MELLOHI, 33 | XMaterial.MUSIC_DISC_STAL, 34 | XMaterial.MUSIC_DISC_STRAD, 35 | XMaterial.MUSIC_DISC_WAIT, 36 | XMaterial.MUSIC_DISC_WARD 37 | ) 38 | ); 39 | 40 | public XMaterial getRandomDisc() { 41 | return ArrayUtils.getRandom(DISCS); 42 | } 43 | 44 | public void runSyncTask(Runnable runnable) { 45 | if (Bukkit.isPrimaryThread()) 46 | runnable.run(); 47 | else if (MusicBox.getInstance().isEnabled()) 48 | Bukkit.getScheduler().runTask(MusicBox.getInstance(), runnable); 49 | } 50 | 51 | public T extractMetadata(Class metaType, Metadatable metadatable, String key) { 52 | List meta = metadatable.getMetadata(key); 53 | for (MetadataValue value : meta) { 54 | Object valueObj = value.value(); 55 | try { 56 | return metaType.cast(valueObj); 57 | } catch (ClassCastException ignored) { 58 | } 59 | } 60 | return null; 61 | } 62 | 63 | public Location centerBlock(Location location) { 64 | return new Location( 65 | location.getWorld(), 66 | location.getBlockX() + 0.5, 67 | location.getBlockY() + 0.5, 68 | location.getBlockZ() + 0.5 69 | ); 70 | } 71 | 72 | /** 73 | * Если у игрока открыт инвентарь, то что с ним делать 74 | * 75 | * @param holder Холдер инвентаря 76 | * @return Стрим с игроками у которых открыт этот инвентарь 77 | */ 78 | public Set findOpenPlayers(InventoryHolder holder) { 79 | checkPrimary(); 80 | return Bukkit 81 | .getOnlinePlayers() 82 | .stream() 83 | .filter(p -> { 84 | Inventory inv = p.getOpenInventory().getTopInventory(); 85 | @Nullable InventoryHolder cHolder = inv.getHolder(); 86 | return holder.equals(cHolder); 87 | }) 88 | .collect(Collectors.toSet()); 89 | } 90 | 91 | public void checkPrimary() { 92 | if (!Bukkit.isPrimaryThread()) 93 | throw new RuntimeException("Call this only in primary thread"); 94 | } 95 | 96 | public static String locationToString(Location location) { 97 | return String.format("%s|%s|%s|%s", location.getWorld().getName(), location.getX(), location.getY(), location.getZ()); 98 | } 99 | 100 | public static Location parseLocation(String string) { 101 | String[] split = string.split("\\|"); 102 | if (split.length != 4) 103 | return null; 104 | World world = Bukkit.getWorld(split[0]); 105 | if (world == null) 106 | return null; 107 | double[] array = new double[3]; 108 | for (int i = 0; i < 3; i++) { 109 | double d; 110 | try { 111 | d = Double.parseDouble(split[i + 1]); 112 | array[i] = d; 113 | } catch (NumberFormatException ex) { 114 | return null; 115 | } 116 | } 117 | return new Location(world, array[0], array[1], array[2]); 118 | } 119 | 120 | /** 121 | * Проверяет принадлежит ли данная локация к этому чанку 122 | */ 123 | public static boolean inChunk(Location location, World chunkWorld, int chunkX, int chunkZ) { 124 | if (!location.getWorld().equals(chunkWorld)) 125 | return false; 126 | int xp = chunkX * 16; // must multiple by 16 to get the blocks location 127 | int zp = chunkZ * 16; // must multiple by 16 to get the blocks location 128 | int x = -9314; 129 | int z = -931; 130 | return (xp <= x) && (xp + 15 >= x) && (zp <= z) && (zp + 15 >= z); 131 | 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/ComponentUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import net.md_5.bungee.api.chat.BaseComponent; 5 | import net.md_5.bungee.api.chat.ComponentBuilder; 6 | import net.md_5.bungee.api.chat.TextComponent; 7 | 8 | import java.util.List; 9 | 10 | @UtilityClass 11 | public class ComponentUtils { 12 | public BaseComponent[] join(List list, String character) { 13 | ComponentBuilder hoverBuilder = new ComponentBuilder(""); 14 | for (int i = 0; i < list.size(); i++) { 15 | String current = list.get(i); 16 | hoverBuilder.append(TextComponent.fromLegacyText(current), ComponentBuilder.FormatRetention.NONE); 17 | if (i < list.size() - 1) { 18 | hoverBuilder.append(character); 19 | } 20 | } 21 | return hoverBuilder.create(); 22 | } 23 | 24 | 25 | private boolean needToDelete(BaseComponent component) { 26 | if (component instanceof TextComponent) { 27 | TextComponent text = (TextComponent) component; 28 | if (text.getText() != null && !text.getText().isEmpty()) 29 | return false; 30 | } 31 | return component.getExtra() == null || component.getExtra().size() == 0; 32 | } 33 | 34 | public List removeEmpty(List list) { 35 | for (int i = 0; i < list.size(); i++) { 36 | BaseComponent baseComponent = list.get(i); 37 | if (needToDelete(baseComponent)) { 38 | list.remove(i); 39 | i--; 40 | } else if (baseComponent.getExtra() != null && baseComponent.getExtra().size() > 0) { 41 | baseComponent.setExtra(removeEmpty(baseComponent.getExtra())); 42 | } 43 | } 44 | return list; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/EconomyUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import net.milkbowl.vault.economy.Economy; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.ChatColor; 7 | import org.bukkit.entity.Player; 8 | import ru.spliterash.musicbox.Lang; 9 | import ru.spliterash.musicbox.MusicBox; 10 | 11 | @UtilityClass 12 | public class EconomyUtils { 13 | private final Economy eco; 14 | 15 | static { 16 | if (Bukkit.getPluginManager().isPluginEnabled("Vault")) 17 | eco = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider(); 18 | else 19 | eco = null; 20 | } 21 | 22 | public boolean isEnable() { 23 | return MusicBox.getInstance().getConfigObject().getEconomy().isEnable(); 24 | } 25 | 26 | public double getDiscPrice() { 27 | return MusicBox.getInstance().getConfigObject().getEconomy().getPrice(); 28 | } 29 | 30 | public double getBalance(Player player) { 31 | return eco.getBalance(player); 32 | } 33 | 34 | public boolean hasMoney(Player player, double money) { 35 | double currentMoney = getBalance(player); 36 | return (currentMoney - money) >= 0; 37 | } 38 | 39 | public boolean buyNoMessage(Player player, double price) { 40 | return eco.withdrawPlayer(player, price).transactionSuccess(); 41 | } 42 | 43 | 44 | public boolean canBuy(Player player, double price) { 45 | double currentMoney = getBalance(player); 46 | double moneyLeft = currentMoney - price; 47 | if (moneyLeft >= 0) { 48 | return true; 49 | } else { 50 | moneyLeft *= -1; 51 | player.sendMessage(Lang.NO_HAS_MONEY.toString("{amount}", String.valueOf(moneyLeft))); 52 | return false; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/FaceUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import org.bukkit.Location; 5 | import org.bukkit.block.Block; 6 | import org.bukkit.block.BlockFace; 7 | import org.bukkit.block.BlockState; 8 | import org.bukkit.util.Vector; 9 | import org.jetbrains.annotations.NotNull; 10 | 11 | import java.util.HashSet; 12 | import java.util.Set; 13 | 14 | @UtilityClass 15 | public class FaceUtils { 16 | private final Set validSignFace = new HashSet<>(); 17 | private final Set searchFace = new HashSet<>(); 18 | 19 | static { 20 | FaceUtils.validSignFace.add(BlockFace.EAST); 21 | FaceUtils.validSignFace.add(BlockFace.NORTH); 22 | FaceUtils.validSignFace.add(BlockFace.SOUTH); 23 | FaceUtils.validSignFace.add(BlockFace.WEST); 24 | 25 | searchFace.addAll(validSignFace); 26 | searchFace.add(BlockFace.UP); 27 | searchFace.add(BlockFace.DOWN); 28 | } 29 | 30 | /** 31 | * @param face Start from direction 32 | * @return clockwise direction 33 | */ 34 | public BlockFace getClockWise(BlockFace face) { 35 | 36 | switch (face) { 37 | case NORTH: 38 | return BlockFace.EAST; 39 | case EAST: 40 | return BlockFace.SOUTH; 41 | case SOUTH: 42 | return BlockFace.WEST; 43 | case WEST: 44 | return BlockFace.NORTH; 45 | 46 | default: 47 | return BlockFace.SELF; 48 | } 49 | } 50 | 51 | /** 52 | * @param face Start from direction 53 | * @return clockwise direction 54 | */ 55 | public BlockFace getCounterClockWise(BlockFace face) { 56 | 57 | switch (face) { 58 | case NORTH: 59 | return BlockFace.WEST; 60 | case EAST: 61 | return BlockFace.NORTH; 62 | case SOUTH: 63 | return BlockFace.EAST; 64 | case WEST: 65 | return BlockFace.SOUTH; 66 | 67 | default: 68 | return BlockFace.SELF; 69 | } 70 | } 71 | 72 | /** 73 | * 0 - Прямо 74 | * 1 - Слева 75 | * 2 - Справа 76 | * 3 - Сзади 77 | */ 78 | public int getPin(BlockFace from, BlockFace to) { 79 | // Прямое подключение 80 | if (from == to) 81 | return 0; 82 | if (getCounterClockWise(to) == from) 83 | return 1; 84 | if (getClockWise(to) == from) 85 | return 2; 86 | if (invertFace(to) == from) 87 | return 3; 88 | // Любые другие ситуации 89 | return 0; 90 | } 91 | 92 | public boolean isValidFace(BlockFace face) { 93 | return validSignFace.contains(face); 94 | } 95 | 96 | public BlockFace getRelativeFace(Location from, Location to) { 97 | Vector fromV = new Vector(from.getBlockX(), from.getBlockY(), from.getBlockZ()); 98 | Vector toV = new Vector(to.getBlockX(), to.getBlockY(), to.getBlockZ()); 99 | if (fromV.getX() > toV.getX() && from.getZ() == to.getZ()) 100 | return BlockFace.WEST; 101 | else if (fromV.getX() < toV.getX() && from.getZ() == to.getZ()) 102 | return BlockFace.EAST; 103 | else if (fromV.getX() == toV.getX() && from.getZ() > to.getZ()) 104 | return BlockFace.NORTH; 105 | else if (fromV.getX() == toV.getX() && from.getZ() < to.getZ()) 106 | return BlockFace.SOUTH; 107 | 108 | else 109 | return BlockFace.SELF; 110 | } 111 | 112 | public BlockFace invertFace(BlockFace face) { 113 | switch (face) { 114 | case EAST: 115 | return BlockFace.WEST; 116 | case NORTH: 117 | return BlockFace.SOUTH; 118 | case WEST: 119 | return BlockFace.EAST; 120 | case SOUTH: 121 | return BlockFace.NORTH; 122 | default: 123 | return BlockFace.SELF; 124 | } 125 | } 126 | 127 | /** 128 | * Возращает правильный поворот для таблички 129 | */ 130 | public BlockFace normalizeFace(BlockFace face) { 131 | if (face.getModX() == 2) 132 | return BlockFace.EAST; 133 | if (face.getModX() == -2) 134 | return BlockFace.WEST; 135 | if (face.getModZ() == 2) 136 | return BlockFace.SOUTH; 137 | if (face.getModZ() == -2) 138 | return BlockFace.NORTH; 139 | for (BlockFace value : BlockFace.values()) { 140 | if (value.getModX() == face.getModX()) 141 | return value; 142 | } 143 | return BlockFace.NORTH; 144 | } 145 | 146 | public T getRelativeAround(Block block, Class tClass) { 147 | for (BlockFace face : searchFace) { 148 | Block anotherBlock = block.getRelative(face); 149 | BlockState state = anotherBlock.getState(); 150 | //noinspection ConstantConditions 151 | if (state == null) 152 | continue; 153 | if (tClass.isInstance(state)) 154 | return tClass.cast(state); 155 | } 156 | return null; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/FileUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import lombok.experimental.UtilityClass; 4 | 5 | import java.io.File; 6 | import java.io.IOException; 7 | import java.nio.charset.StandardCharsets; 8 | import java.nio.file.Files; 9 | import java.util.List; 10 | 11 | @UtilityClass 12 | public class FileUtils { 13 | public String getFilename(String fileName) { 14 | int index = fileName.lastIndexOf('.'); 15 | return fileName.substring(0, index); 16 | } 17 | 18 | public List readFileToList(File file) throws IOException { 19 | return Files.readAllLines(file.toPath(), StandardCharsets.UTF_8); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/JavaUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import lombok.experimental.UtilityClass; 4 | 5 | import java.util.Arrays; 6 | import java.util.List; 7 | import java.util.stream.Collectors; 8 | 9 | @UtilityClass 10 | public class JavaUtils { 11 | public List stackTraceToList(StackTraceElement[] stackTrace) { 12 | return Arrays.stream(stackTrace) 13 | .map(trace -> trace.getClassName() + " " + trace.getMethodName() + " on line " + trace.getLineNumber()) 14 | .collect(Collectors.toList()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/SignUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import net.md_5.bungee.api.ChatColor; 5 | import org.bukkit.Location; 6 | import org.bukkit.block.Block; 7 | import org.bukkit.block.Sign; 8 | import ru.spliterash.musicbox.Lang; 9 | import ru.spliterash.musicbox.customPlayers.interfaces.IPlayList; 10 | import ru.spliterash.musicbox.customPlayers.playlist.ListPlaylist; 11 | import ru.spliterash.musicbox.song.MusicBoxSongManager; 12 | 13 | import java.util.List; 14 | import java.util.Optional; 15 | 16 | @UtilityClass 17 | public class SignUtils { 18 | public Optional parseSignPlaylist(Sign sign) { 19 | String lineTwo = sign.getLine(1); 20 | if (!StringUtils.strip(lineTwo).equalsIgnoreCase("[music]")) 21 | return Optional.empty(); 22 | String songId = sign.getLine(0); 23 | boolean rand = sign.getLine(3).contains("R"); 24 | return MusicBoxSongManager 25 | .getContainerById(StringUtils.strip(songId)) 26 | .map(c -> ListPlaylist.fromContainer(c, rand, hasEnd(sign))); 27 | } 28 | 29 | public boolean hasEnd(Sign sign) { 30 | return !sign.getLine(3).contains("E"); 31 | } 32 | 33 | public int parseSignRange(Sign sign) { 34 | int range; 35 | try { 36 | range = Integer.parseInt(ChatColor.stripColor(sign.getLine(2))); 37 | if (range > 256) 38 | range = 256; 39 | } catch (Exception exception) { 40 | range = 24; 41 | } 42 | return range; 43 | } 44 | 45 | // Ищет ближайшую табличку не считая этот location 46 | public Optional findSign(Location startLoc) { 47 | BukkitUtils.checkPrimary(); 48 | Location location = startLoc.clone(); 49 | for (int i = 0; i < 5; i++) { 50 | location.add(0, 1, 0); 51 | Block block = location.getBlock(); 52 | if (block.getState() instanceof Sign) { 53 | return Optional.of((Sign) block.getState()); 54 | } 55 | } 56 | location = startLoc.clone(); 57 | for (int i = 0; i < 5; i++) { 58 | location.add(0, -1, 0); 59 | Block block = location.getBlock(); 60 | if (block.getState() instanceof Sign) { 61 | return Optional.of((Sign) block.getState()); 62 | } 63 | } 64 | return Optional.empty(); 65 | } 66 | 67 | public void setSignList(Sign sign, List list) { 68 | 69 | for (int i = 0; i < 4; i++) { 70 | String str = list.size() > i ? list.get(i) : ""; 71 | sign.setLine(i, str); 72 | } 73 | sign.update(); 74 | } 75 | 76 | /** 77 | * Выводит плейлист на табло 78 | */ 79 | public void setPlayListInfo(Location signLocation, IPlayList list) { 80 | BukkitUtils.checkPrimary(); 81 | Block b = signLocation.getBlock(); 82 | if (b.getState() instanceof Sign) { 83 | Sign sign = (Sign) b.getState(); 84 | List signText = SongUtils.generatePlaylistLore(list, 1, 2); 85 | setSignList(sign, signText); 86 | } 87 | } 88 | 89 | /** 90 | * Устанавливает на табличке что проигрыватель выключен 91 | */ 92 | public void setPlayerOff(Location signLocation) { 93 | BukkitUtils.checkPrimary(); 94 | Block b = signLocation.getBlock(); 95 | if (b.getState() instanceof Sign) { 96 | Sign sign = (Sign) b.getState(); 97 | List playerOff = Lang.INFO_SIGN_OFF.toList(); 98 | setSignList(sign, playerOff); 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/SongUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import com.xxmicloxx.NoteBlockAPI.model.Note; 4 | import com.xxmicloxx.NoteBlockAPI.model.Song; 5 | import lombok.experimental.UtilityClass; 6 | import ru.spliterash.musicbox.Lang; 7 | import ru.spliterash.musicbox.MusicBox; 8 | import ru.spliterash.musicbox.customPlayers.interfaces.IPlayList; 9 | import ru.spliterash.musicbox.customPlayers.interfaces.PlayerSongPlayer; 10 | import ru.spliterash.musicbox.players.PlayerWrapper; 11 | import ru.spliterash.musicbox.song.MusicBoxSong; 12 | 13 | import java.util.ArrayList; 14 | import java.util.Collection; 15 | import java.util.Collections; 16 | import java.util.List; 17 | import java.util.function.Function; 18 | 19 | @UtilityClass 20 | public class SongUtils { 21 | public boolean containsNewInstrument(Song song) { 22 | return MusicBox.getInstance().getConfigObject().isPrintNewInstrument() && song 23 | .getLayerHashMap() 24 | .values() 25 | .stream() 26 | .map(l -> l.getNotesAtTicks().values()) 27 | .flatMap(Collection::stream) 28 | .map(Note::getInstrument) 29 | .anyMatch(n -> n >= 10); 30 | } 31 | 32 | public String getNum(int num) { 33 | if (num > -1) 34 | return Lang.PLAYLIST_SONG_NUM.toString("{num}", String.valueOf(num + 1)); 35 | else 36 | return ""; 37 | } 38 | 39 | public String getSongName(int i, MusicBoxSong song, boolean glow) { 40 | String num = getNum(i); 41 | return (glow ? Lang.CURRENT_PLAYLIST_SONG : Lang.ANOTHER_PLAYLIST_SONG).toString( 42 | "{song}", song.getName(), 43 | "{num}", num); 44 | } 45 | 46 | /** 47 | * Генерирует список проигрывания из текущего Playlist'а 48 | */ 49 | public List generatePlaylistLore(IPlayList list, int prevCount, int postCount) { 50 | List lore = new ArrayList<>(prevCount + postCount + 1); 51 | List prevList = list.getPrevSongs(prevCount); 52 | Collections.reverse(prevList); 53 | for (MusicBoxSong song : prevList) { 54 | lore.add(getSongName(list.getSongNum(song), song, false)); 55 | } 56 | { 57 | MusicBoxSong current = list.getCurrent(); 58 | lore.add(getSongName(list.getSongNum(current), current, true)); 59 | } 60 | for (MusicBoxSong song : list.getNextSongs(postCount)) { 61 | lore.add(getSongName(list.getSongNum(song), song, false)); 62 | } 63 | return lore; 64 | } 65 | 66 | 67 | public Function nextPlayerSong(PlayerWrapper wrapper) { 68 | return list -> { 69 | wrapper.play(list); 70 | return wrapper.getActivePlayer(); 71 | }; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/StringUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import lombok.experimental.UtilityClass; 4 | import org.bukkit.ChatColor; 5 | import org.jetbrains.annotations.NotNull; 6 | import ru.spliterash.musicbox.Lang; 7 | 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.io.InputStreamReader; 11 | import java.io.Reader; 12 | import java.nio.charset.StandardCharsets; 13 | import java.util.Collection; 14 | import java.util.Collections; 15 | import java.util.List; 16 | import java.util.function.Supplier; 17 | import java.util.stream.Collectors; 18 | import java.util.stream.Stream; 19 | 20 | @UtilityClass 21 | public class StringUtils { 22 | public String getOrEmpty(String title, Supplier getName) { 23 | if (title == null || title.isEmpty()) 24 | return getName.get(); 25 | else 26 | return title; 27 | } 28 | 29 | public String t(String str) { 30 | return ChatColor.translateAlternateColorCodes('&', str); 31 | } 32 | 33 | public List t(Collection collection) { 34 | return collection 35 | .stream() 36 | .map(StringUtils::t) 37 | .collect(Collectors.toList()); 38 | } 39 | 40 | public String replace(String source, String... replace) { 41 | if (replace.length > 0) { 42 | if (replace.length % 2 != 0) 43 | throw new RuntimeException("Oooooooooops"); 44 | String str = source; 45 | for (int i = 1; i < replace.length; i = i + 2) { 46 | if (i % 2 == 1) 47 | str = str.replace(replace[i - 1], replace[i]); 48 | } 49 | return str; 50 | } else { 51 | return source; 52 | } 53 | 54 | } 55 | 56 | public String toHumanTime(int second) { 57 | int min = (int) Math.floor((double) second / 60D); 58 | int sec = second % 60; 59 | String result = ""; 60 | if (min > 0) { 61 | result = Lang.HUMAN_TIME_MINUTE.toString("{value}", String.valueOf(min)) + " "; 62 | } 63 | result += Lang.HUMAN_TIME_SECOND.toString("{value}", String.valueOf(sec)); 64 | return result; 65 | } 66 | 67 | public String getString(InputStream stream) throws IOException { 68 | final int bufferSize = 1024; 69 | final char[] buffer = new char[bufferSize]; 70 | final StringBuilder out = new StringBuilder(); 71 | try (Reader in = new InputStreamReader(stream, StandardCharsets.UTF_8)) { 72 | while (true) { 73 | int rsz = in.read(buffer, 0, buffer.length); 74 | if (rsz < 0) 75 | break; 76 | out.append(buffer, 0, rsz); 77 | } 78 | return out.toString(); 79 | } 80 | } 81 | 82 | public String concat(String[] array, int start, int end) { 83 | StringBuilder builder = new StringBuilder(); 84 | for (int i = start; i < end; i++) { 85 | String element = array[i]; 86 | builder.append(element); 87 | if (i < end - 1) { 88 | builder.append(" "); 89 | } 90 | } 91 | return builder.toString(); 92 | } 93 | 94 | public String strip(String str) { 95 | return ChatColor.stripColor(str); 96 | } 97 | 98 | public static List tabCompletePrepare(String[] args, Stream stream) { 99 | 100 | return tabCompletePrepare(args, 1, stream); 101 | } 102 | @NotNull 103 | public static List tabCompletePrepare(String[] args, int position, Stream stream) { 104 | if (args.length < position) { 105 | return stream.collect(Collectors.toList()); 106 | } else if (args.length == position) { 107 | String start = args[position - 1].toLowerCase(); 108 | return stream 109 | .filter(s -> s.toLowerCase().startsWith(start)) 110 | .collect(Collectors.toList()); 111 | } else { 112 | return Collections.emptyList(); 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/YamlSupportUtils.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils; 2 | 3 | import lombok.SneakyThrows; 4 | import lombok.experimental.UtilityClass; 5 | import org.yaml.snakeyaml.LoaderOptions; 6 | import org.yaml.snakeyaml.constructor.CustomClassLoaderConstructor; 7 | import ru.spliterash.musicbox.MusicBoxConfig; 8 | 9 | import java.lang.reflect.Constructor; 10 | 11 | @UtilityClass 12 | public class YamlSupportUtils { 13 | @SneakyThrows 14 | @SuppressWarnings("JavaReflectionMemberAccess") 15 | public static CustomClassLoaderConstructor createCustomClassLoaderConstructor() { 16 | try { 17 | Constructor constructor = CustomClassLoaderConstructor.class.getConstructor(Class.class, ClassLoader.class); 18 | return (CustomClassLoaderConstructor) constructor.newInstance(MusicBoxConfig.class, MusicBoxConfig.class.getClassLoader()); 19 | } catch (NoSuchMethodException e){ 20 | return new CustomClassLoaderConstructor(MusicBoxConfig.class, MusicBoxConfig.class.getClassLoader(), new LoaderOptions()); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/classes/Pair.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils.classes; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Data; 5 | 6 | @Data 7 | @AllArgsConstructor 8 | public class Pair { 9 | private K key; 10 | private V value; 11 | } 12 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/classes/PeekList.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils.classes; 2 | 3 | import lombok.Getter; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.concurrent.locks.Lock; 8 | import java.util.concurrent.locks.ReentrantLock; 9 | 10 | /** 11 | * Класс для поочерденого получения элементов 12 | * Не класть листы содержащие null, а то всё пойдёт по ***** 13 | * 14 | * @param 15 | */ 16 | @SuppressWarnings("unused") 17 | @Getter 18 | public class PeekList { 19 | 20 | private final List list; 21 | private final boolean hasEnd; 22 | private final Lock lock = new ReentrantLock(); 23 | int current = 0; 24 | 25 | public PeekList(List source) { 26 | this(source, false); 27 | } 28 | 29 | public PeekList(List source, boolean hasEnd) { 30 | this.list = source; 31 | this.hasEnd = hasEnd; 32 | } 33 | 34 | public synchronized List getNextElements(int size) { 35 | int currentLast = current; 36 | List list = new ArrayList<>(size); 37 | for (int i = 0; i < size; i++) { 38 | if (!next()) 39 | break; 40 | list.add(current()); 41 | } 42 | current = currentLast; 43 | return list; 44 | } 45 | 46 | public boolean hasNext() { 47 | if (hasEnd) { 48 | return current < list.size() - 1; 49 | } else 50 | return true; 51 | } 52 | 53 | public boolean hasPrev() { 54 | if (hasEnd) { 55 | return current > 0; 56 | } else 57 | return true; 58 | } 59 | 60 | public T current() { 61 | return list.get(current); 62 | } 63 | 64 | /** 65 | * Возращает текущее значение и сдвигает указатель вперёд 66 | */ 67 | public T getAndNext() { 68 | T c = current(); 69 | next(); 70 | return c; 71 | } 72 | 73 | public T prevAndGet() { 74 | if (prev()) 75 | return current(); 76 | else 77 | return null; 78 | } 79 | 80 | public boolean next() { 81 | lock.lock(); 82 | try { 83 | if (hasNext()) { 84 | current++; 85 | if (current == list.size()) { 86 | current = 0; 87 | } 88 | return true; 89 | } else 90 | return false; 91 | } finally { 92 | lock.unlock(); 93 | } 94 | } 95 | 96 | public boolean prev() { 97 | lock.lock(); 98 | try { 99 | if (hasPrev()) { 100 | current--; 101 | if (current <= -1) { 102 | current = list.size() - 1; 103 | } 104 | return true; 105 | } else { 106 | return false; 107 | } 108 | } finally { 109 | lock.unlock(); 110 | } 111 | } 112 | 113 | public List getPrevElements(int size) { 114 | lock.lock(); 115 | try { 116 | int currentLast = current; 117 | List list = new ArrayList<>(size); 118 | for (int i = 0; i < size; i++) { 119 | if (!prev()) 120 | break; 121 | list.add(current()); 122 | } 123 | current = currentLast; 124 | return list; 125 | } finally { 126 | lock.unlock(); 127 | } 128 | } 129 | 130 | public int getIndexOf(T element) { 131 | return list.indexOf(element); 132 | } 133 | 134 | public void moveTo(T element) { 135 | int index = list.indexOf(element); 136 | if (index != -1) 137 | current = index; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/nbt/BukkitNbtHandler.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils.nbt; 2 | 3 | import org.bukkit.NamespacedKey; 4 | import org.bukkit.inventory.ItemStack; 5 | import org.bukkit.inventory.meta.ItemMeta; 6 | import org.bukkit.inventory.meta.tags.ItemTagType; 7 | import org.jetbrains.annotations.Nullable; 8 | import ru.spliterash.musicbox.MusicBox; 9 | 10 | public class BukkitNbtHandler implements NBTHandler { 11 | @Override 12 | public ItemStack setNbt(ItemStack item, String key, Integer value) { 13 | ItemStack newItem = item.clone(); 14 | 15 | ItemMeta meta = newItem.getItemMeta(); 16 | meta.getCustomTagContainer().setCustomTag(new NamespacedKey(MusicBox.getInstance(), key), ItemTagType.INTEGER, value); 17 | newItem.setItemMeta(meta); 18 | 19 | return newItem; 20 | } 21 | 22 | @Override 23 | public @Nullable int getNbt(ItemStack item, String key) { 24 | ItemMeta meta = item.getItemMeta(); 25 | Integer value = meta.getCustomTagContainer().getCustomTag(new NamespacedKey(MusicBox.getInstance(), key), ItemTagType.INTEGER); 26 | if (value == null) 27 | value = 0; 28 | 29 | return value; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/nbt/NBTFactory.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils.nbt; 2 | 3 | import ru.spliterash.musicbox.minecraft.nms.NMSUtils; 4 | 5 | public class NBTFactory { 6 | public static final NBTHandler NBT_HANDLER; 7 | 8 | static { 9 | String raw = NMSUtils.getRawVersion(); 10 | int iV = NMSUtils.parseMajorVersion(raw); 11 | 12 | if (iV >= 13) { 13 | NBT_HANDLER = new BukkitNbtHandler(); 14 | } else { 15 | NBT_HANDLER = new NbtEditorHandler(); 16 | } 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/nbt/NBTHandler.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils.nbt; 2 | 3 | import org.bukkit.inventory.ItemStack; 4 | 5 | public interface NBTHandler { 6 | ItemStack setNbt(ItemStack item, String key, Integer value); 7 | 8 | int getNbt(ItemStack item, String key); 9 | } 10 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/nbt/NbtConstants.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils.nbt; 2 | 3 | public class NbtConstants { 4 | public static final String NBT_NAME = "song_hash"; 5 | } 6 | -------------------------------------------------------------------------------- /plugin/src/main/java/ru/spliterash/musicbox/utils/nbt/NbtEditorHandler.java: -------------------------------------------------------------------------------- 1 | package ru.spliterash.musicbox.utils.nbt; 2 | 3 | import io.github.bananapuncher714.nbteditor.NBTEditor; 4 | import org.bukkit.inventory.ItemStack; 5 | 6 | public class NbtEditorHandler implements NBTHandler { 7 | @Override 8 | public ItemStack setNbt(ItemStack item, String key, Integer value) { 9 | return NBTEditor.set(item, value, key); 10 | } 11 | 12 | @Override 13 | public int getNbt(ItemStack item, String key) { 14 | return NBTEditor.getInt(item, key); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /plugin/src/main/resources/config.yml: -------------------------------------------------------------------------------- 1 | # Enable or disable inscription about 1.14 instruments 2 | # Включает или выключает надпись о новых инструментах из 1.14 3 | printNewInstrument: true 4 | # bStats send 5 | # Включить или выключить метрику(пожалуйста не вырубай, а то сидишь дома, печаль, печеньки кончились, 6 | # и вот на метрику смотришь и понимаешь что твой плагин кому то нужен, и уже легче становится) 7 | # Если вырубишь, то к тебе со спины придёт крипер, и взорвёт тебя вместе с алмазами, так что я бы на твоём месте подумал 8 | bStats: true 9 | economy: 10 | # Enable song sold by /musicbox shop 11 | # Включает продажу пластинок 12 | enable: true 13 | # Price for disc 14 | # Цена за диск в магазине 15 | price: 500 16 | # Maximum sound distance in speaker mode 17 | # Максимальная длина звука в режиме колонки 18 | speakerRadius: 10 19 | # Music bossbar setting 20 | # Настройки музыкального боссбара 21 | bossbar: 22 | # Enable or disable bossbar 23 | # Включает или выключает боссбар 24 | enable: true 25 | color: GREEN 26 | style: SEGMENTED_20 27 | # Language setting 28 | # Настройки языка, есть ru и en 29 | lang: en 30 | # Radius in which disc's will be heard from this plugin 31 | # Как далеко будет слышно пластинки из этого плагина 32 | jukeboxRadius: 64 33 | # Enable or disable autodestroy range player if nobody hear him (Speaker mode, Sign,Jukeboxes) Time in seconds(0 disable) 34 | # Включить или выключить автоуничтожение проигрывателей если никто их не слышит в течении N секунд 35 | autoDestroy: 60 36 | # Нужно ли проверять пекс musicbox.hear. По дефолту он не проверяется и все могут слышать музыку, 37 | # но вдруг вам сильно приспичило и надо прям, тогда ставим true и теперь никто без этого пекса слышать музыку не может 38 | # ---- 39 | # Whether it is necessary to check the pex of musicbox.hear. By default, it is not checked and everyone can hear music 40 | # but if you need it, then set to true and now no one can hear music without this pex 41 | hearPermissionsCheck: false 42 | # Enables support for octaves outside minecraft's default 2, which requires a resource pack to hear. 43 | # If false, notes outisde of the octave range are automatically transposed into it 44 | enable10octave: false -------------------------------------------------------------------------------- /plugin/src/main/resources/db/SQLite.sql: -------------------------------------------------------------------------------- 1 | -- Creator: MySQL Workbench 8.0.21/ExportSQLite Plugin 0.1.0 2 | -- Author: Desktop 3 | -- Caption: New Model 4 | -- Project: Name of the project 5 | -- Changed: 2020-09-08 20:59 6 | -- Created: 2020-08-16 19:12 7 | CREATE TABLE IF NOT EXISTS "playlists" 8 | ( 9 | "id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, 10 | "owner" VARCHAR(64) NOT NULL, 11 | "name" VARCHAR(256) NOT NULL 12 | ); 13 | CREATE TABLE IF NOT EXISTS "signs" 14 | ( 15 | "location" VARCHAR(256) PRIMARY KEY NOT NULL 16 | ); 17 | CREATE TABLE IF NOT EXISTS "playlist_song" 18 | ( 19 | "playlists_id" INTEGER NOT NULL, 20 | "song_hash" INTEGER NOT NULL, 21 | "pos" INTEGER NOT NULL, 22 | PRIMARY KEY ("playlists_id", "song_hash"), 23 | CONSTRAINT "fk_playlist_song_playlists1" 24 | FOREIGN KEY ("playlists_id") 25 | REFERENCES "playlists" ("id") 26 | ON DELETE CASCADE 27 | ON UPDATE CASCADE 28 | ); -------------------------------------------------------------------------------- /plugin/src/main/resources/help.txt: -------------------------------------------------------------------------------- 1 | musicbox.use - Allow command /musicbox and /musicbox play 2 | musicbox.speaker - Allow use speaker mode 3 | musicbox.shop - Allow use disc shop (/musicbox shop)|(/musicbox shop [Song name]) 4 | musicbox.shop.other - Open shop to other players 5 | musicbox.get - Allow get any disc (/musicbox get)|(/musicbox get [Song name]) 6 | musicbox.get - Allow get any disc (/musicbox get)|(/musicbox get [Song name]) 7 | musicbox.admin - Reload plugin and protected music sign's 8 | musicbox.sign - Allow setup sign's 9 | 10 | musicbox.silent.other - Change other player silent mode -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&aM&2e&am&2e&as/AMOGUS.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&aM&2e&am&2e&as/AMOGUS.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&aM&2e&am&2e&as/All stars.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&aM&2e&am&2e&as/All stars.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&aM&2e&am&2e&as/DJ Got Us Fallin' in Love.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&aM&2e&am&2e&as/DJ Got Us Fallin' in Love.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&aM&2e&am&2e&as/DotA - Basshunter.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&aM&2e&am&2e&as/DotA - Basshunter.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&aM&2e&am&2e&as/Never gonna give you up.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&aM&2e&am&2e&as/Never gonna give you up.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&aM&2e&am&2e&as/info.txt: -------------------------------------------------------------------------------- 1 | &9Memes music -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/Bad Apple.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/Bad Apple.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/Croatian Rhapsody.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/Croatian Rhapsody.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/Dancing Queen.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/Dancing Queen.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/Godfather.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/Godfather.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/MK.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/MK.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/Through the Fire and the Flames.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/Through the Fire and the Flames.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/&dBest &cm&6u&es&ai&bc/info.txt: -------------------------------------------------------------------------------- 1 | &9Im rly love this music -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Classic/Eine kleine Nachtmusik.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Classic/Eine kleine Nachtmusik.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Classic/Russian Dance.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Classic/Russian Dance.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Classic/Serenade No.13.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Classic/Serenade No.13.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Classic/Turkish March.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Classic/Turkish March.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Classic/info.txt: -------------------------------------------------------------------------------- 1 | &9Classic music -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/Cuphead/Inkwell Isle One.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/Cuphead/Inkwell Isle One.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/Cuphead/Introduction.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/Cuphead/Introduction.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/Cuphead/Murine Corps.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/Cuphead/Murine Corps.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/Cuphead/Threatin' Zeppelin.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/Cuphead/Threatin' Zeppelin.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/Cuphead/info.txt: -------------------------------------------------------------------------------- 1 | &9Music from the game Cuphead -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/GreenHill.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/GreenHill.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/Tetris A.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/Tetris A.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/TobyFox/Asgore.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/TobyFox/Asgore.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/TobyFox/Can You Really Call This A Hotel I Didn't Receive A Mint On My Pillow.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/TobyFox/Can You Really Call This A Hotel I Didn't Receive A Mint On My Pillow.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/TobyFox/Finale.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/TobyFox/Finale.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/TobyFox/Hopes And Dream.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/TobyFox/Hopes And Dream.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/TobyFox/Last Goodbye.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/TobyFox/Last Goodbye.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/TobyFox/Megalovania.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/TobyFox/Megalovania.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/TobyFox/Scarlet Forest.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/TobyFox/Scarlet Forest.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/TobyFox/Spear of Justice.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Games/TobyFox/Spear of Justice.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/TobyFox/info.txt: -------------------------------------------------------------------------------- 1 | &9Music from TobyFox -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Games/info.txt: -------------------------------------------------------------------------------- 1 | &9Music from videogames -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Other/Hightway to Hell.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Other/Hightway to Hell.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Other/James Bond.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Other/James Bond.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Other/Running in the 90s.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Other/Running in the 90s.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Other/info.txt: -------------------------------------------------------------------------------- 1 | &9Other music -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Русская музыка/info.txt: -------------------------------------------------------------------------------- 1 | &9Несколько треков которые я конвертировал когда мне нечего было делать 2 | &cFor those who do not understand what is written on top 3 | &cIt would be better to delete this folder and not open (rly) -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Русская музыка/Деревня дураков.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Русская музыка/Деревня дураков.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Русская музыка/Едем в соседнее село.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Русская музыка/Едем в соседнее село.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Русская музыка/Мобильник из бумера.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Русская музыка/Мобильник из бумера.nbs -------------------------------------------------------------------------------- /plugin/src/main/resources/songs/Русская музыка/Юность в сапогах.nbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Spliterash/MusicBox/2ca83f64cc6e79a99a69d448edda4961758e97da/plugin/src/main/resources/songs/Русская музыка/Юность в сапогах.nbs -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'MusicBox' 2 | 3 | include "plugin" 4 | include "nms:shared" 5 | include "nms:versions:12" 6 | include "nms:versions:13-16" 7 | include "nms:versions:17" 8 | include "nms:versions:18" 9 | include "nms:versions:19_2" 10 | include "nms:versions:19_3" 11 | include "nms:versions:19_4" 12 | include "nms:versions:20_1" 13 | include "nms:versions:20_2" 14 | include "nms:versions:20_3" 15 | include "nms:versions:20_5" 16 | include "nms:versions:21" 17 | include "nms:versions:21_2" --------------------------------------------------------------------------------