├── .github └── workflows │ └── build.yaml ├── .gitignore ├── LICENSE ├── README.md ├── assets ├── animation_example.gif ├── nice_example.gif ├── pager_example.gif └── sidebar.gif ├── build.gradle.kts ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── renovate.json ├── run_test_server.sh ├── server └── docker-compose.yaml ├── settings.gradle.kts ├── src ├── main │ └── java │ │ └── me │ │ └── catcoder │ │ └── sidebar │ │ ├── ProtocolSidebar.java │ │ ├── ScoreboardObjective.java │ │ ├── Sidebar.java │ │ ├── SidebarLine.java │ │ ├── pager │ │ ├── PageConsumer.java │ │ └── SidebarPager.java │ │ ├── protocol │ │ ├── ChannelInjector.java │ │ ├── PacketIds.java │ │ ├── ProtocolConstants.java │ │ ├── ScoreNumberFormat.java │ │ └── ScoreboardPackets.java │ │ ├── text │ │ ├── FrameIterator.java │ │ ├── TextFrame.java │ │ ├── TextIterator.java │ │ ├── TextIterators.java │ │ ├── TextProvider.java │ │ ├── impl │ │ │ ├── TextFadeAnimation.java │ │ │ ├── TextSlideAnimation.java │ │ │ └── TextTypingAnimation.java │ │ └── provider │ │ │ ├── AdventureTextProvider.java │ │ │ ├── BungeeCordChatTextProvider.java │ │ │ ├── MiniMessageTextProvider.java │ │ │ └── MiniPlaceholdersTextProvider.java │ │ └── util │ │ ├── NbtComponentSerializer.java │ │ ├── RandomString.java │ │ ├── Reflection.java │ │ ├── buffer │ │ ├── ByteBufNetOutput.java │ │ └── NetOutput.java │ │ ├── lang │ │ ├── ThrowingConsumer.java │ │ ├── ThrowingFunction.java │ │ ├── ThrowingPredicate.java │ │ └── ThrowingSupplier.java │ │ └── version │ │ ├── MinecraftProtocolVersion.java │ │ ├── MinecraftVersion.java │ │ └── VersionUtil.java └── test │ └── java │ └── me │ └── catcoder │ └── sidebar │ └── PacketIdsTest.java └── standalone-plugin ├── .gitignore ├── build.gradle.kts └── src └── main ├── java └── me │ └── catcoder │ └── sidebar │ └── ProtocolSidebarPlugin.java └── resources └── plugin.yml /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: [ push ] 4 | 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@v4 11 | 12 | - name: Set up JDK 17 13 | uses: actions/setup-java@v3 14 | with: 15 | java-version: '17' 16 | distribution: 'adopt' 17 | cache: 'gradle' 18 | 19 | - name: Build with Gradle 20 | run: ./gradlew test build --no-daemon 21 | 22 | - name: Publish with Gradle 23 | if: github.ref == 'refs/heads/master' 24 | env: 25 | GPG_PASSPHRASE: ${{ secrets.GPG_KEY_PASSPHRASE }} 26 | GPG_SECRET_KEY: ${{ secrets.GPG_SECRET_KEY }} 27 | USERNAME: ${{ secrets.REPO_USER }} 28 | TOKEN: ${{ secrets.REPO_TOKEN }} 29 | 30 | run: ./gradlew publish --no-daemon -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # From https://github.com/github/gitignore/blob/master/Gradle.gitignore 2 | .gradle 3 | /build/ 4 | 5 | # Ignore Gradle GUI config 6 | gradle-app.setting 7 | 8 | /bin/ 9 | 10 | # Cache of project 11 | .gradletasknamecache 12 | 13 | # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 14 | # gradle/wrapper/gradle-wrapper.properties 15 | 16 | 17 | 18 | # From https://github.com/github/gitignore/blob/master/Java.gitignore 19 | *.class 20 | 21 | # Mobile Tools for Java (J2ME) 22 | .mtj.tmp/ 23 | 24 | # Package Files # 25 | *.jar 26 | *.war 27 | *.ear 28 | 29 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 30 | !gradle-wrapper.jar 31 | 32 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 33 | hs_err_pid* 34 | 35 | 36 | # From https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore 37 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm 38 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 39 | 40 | # User-specific stuff: 41 | .idea/workspace.xml 42 | .idea/tasks.xml 43 | .idea/dictionaries 44 | .idea/vcs.xml 45 | .idea/jsLibraryMappings.xml 46 | 47 | # Sensitive or high-churn files: 48 | .idea/dataSources.ids 49 | .idea/dataSources.xml 50 | .idea/dataSources.local.xml 51 | .idea/sqlDataSources.xml 52 | .idea/dynamic.xml 53 | .idea/uiDesigner.xml 54 | 55 | # Gradle: 56 | .idea/gradle.xml 57 | .idea/libraries 58 | 59 | .idea/ 60 | 61 | # Mongo Explorer plugin: 62 | .idea/mongoSettings.xml 63 | 64 | ## File-based project format: 65 | *.iws 66 | 67 | *.iml 68 | 69 | ## Plugin-specific files: 70 | 71 | # IntelliJ 72 | /out/ 73 | 74 | # mpeltonen/sbt-idea plugin 75 | .idea_modules/ 76 | 77 | # JIRA plugin 78 | atlassian-ide-plugin.xml 79 | 80 | # Crashlytics plugin (for Android Studio and IntelliJ) 81 | com_crashlytics_export_strings.xml 82 | crashlytics.properties 83 | crashlytics-build.properties 84 | fabric.properties 85 | 86 | 87 | *.DS_Store 88 | .AppleDouble 89 | .LSOverride 90 | 91 | # Icon must end with two \r 92 | Icon 93 | 94 | 95 | # Thumbnails 96 | ._* 97 | 98 | # Files that might appear in the root of a volume 99 | .DocumentRevisions-V100 100 | .fseventsd 101 | .Spotlight-V100 102 | .TemporaryItems 103 | .Trashes 104 | .VolumeIcon.icns 105 | .com.apple.timemachine.donotpresent 106 | 107 | # Directories potentially created on remote AFP share 108 | .AppleDB 109 | .AppleDesktop 110 | Network Trash Folder 111 | Temporary Items 112 | .apdisk 113 | 114 | server/data 115 | 116 | !docker-compose.yaml 117 | !ProtocolSidebar-*.jar -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017-2023 CatCoder and Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
Powerful feature-packed Minecraft scoreboard library
5 |6 | 7 |
12 | 13 | * [Features](#features) 14 | * [Adding to your project](#adding-to-your-project) 15 | * [Maven](#maven) 16 | * [Gradle](#gradle) 17 | * [Gradle (Kotlin DSL)](#gradle-kotlin-dsl) 18 | * [Basic usage](#basic-usage) 19 | * [Conditional lines](#conditional-lines) 20 | * [Score number formatting](#score-number-formatting) 21 | * [Sidebar title animations](#sidebar-title-animations) 22 | * [Sidebar Pager](#sidebar-pager) 23 | 24 |  25 | 26 | 27 | ## Donations 28 | [](https://www.buymeacoffee.com/catcoderr) 29 | 30 | 31 | ## Features 32 | 33 | * No flickering (without using a buffer) 34 | * Does not require any additional libraries/plugins on the server 35 | * Easy to use 36 | * Folia support 37 | * Optionally supports [Adventure API](https://docs.advntr.dev/text.html), [MiniMessage](https://docs.advntr.dev/minimessage/index.html), [MiniPlaceholders](https://github.com/MiniPlaceholders/MiniPlaceholders) 38 | * Extremely fast, can be used asynchronously 39 | * Cool inbuilt animations 40 | * Inbuilt pager for showing multiple sidebars to the player 41 | * Automatic score management system: sidebar reorders lines automatically 42 | * Everything is at the packet level, so it works with other plugins using scoreboard and/or teams 43 | * Supports up to 30 characters per line on 1.12.2 and below 44 | * No character limit on 1.13 and higher 45 | * Supports hex colors on 1.16 and higher 46 | * Minimized NMS interaction, means that packets are constructed at the byte buffer level and then sent directly to the player's channel. 47 | 48 | ## Adding To Your Project 49 | 50 | Instead of manually bundling the library into your JAR file, you can 51 | use [the standalone plugin](https://github.com/CatCoderr/ProtocolSidebar/tree/master/standalone-plugin). 52 | 53 | Simply run `./gradlew clean shadowJar` and put the resulting JAR file located in `bin` folder into your plugins folder. 54 | 55 | In other cases, you must use something like [shadow](https://imperceptiblethoughts.com/shadow/) (for Gradle) 56 | or [maven-shade-plugin](https://maven.apache.org/plugins/maven-shade-plugin/) (for Maven). 57 | 58 | ### Maven 59 | 60 | ```xml 61 |19 | * This class provides methods for creating new sidebars with different text providers. 20 | *
21 | *
22 | * @author CatCoder
23 | */
24 | @UtilityClass
25 | public class ProtocolSidebar {
26 |
27 | /**
28 | * Creates new sidebar with custom text provider.
29 | *
30 | * @param title - sidebar title
31 | * @param plugin - plugin instance
32 | * @param textProvider - text provider
33 | * @param
29 | * Sidebar is a scoreboard with a title and lines.
30 | *
31 | */
32 |
33 | @FieldDefaults(level = AccessLevel.PACKAGE)
34 | public class Sidebar
213 | *
214 | * @param updater - the function that updates the text
215 | * @param condition - the condition
216 | * @return SidebarLine instance
217 | */
218 | public SidebarLine
389 | * This method should be called when the sidebar is no longer needed.
390 | * Otherwise, the sidebar will be kept in memory and will be updated
391 | * for all players.
392 | *
393 | */
394 | public void destroy() {
395 | cancelTitleUpdater();
396 |
397 | for (WrappedTask task : tasks) {
398 | foliaLib.getScheduler().cancelTask(task);
399 | }
400 |
401 | removeViewers();
402 |
403 | synchronized (lines) {
404 | lines.clear();
405 | }
406 |
407 | tasks.clear();
408 | }
409 |
410 | /**
411 | * Sends this sidebar with all lines to the player.
412 | *
413 | * @param player target player
414 | */
415 |
416 | @SneakyThrows
417 | public void addViewer(@NonNull Player player) {
418 | if (!viewers.contains(player.getUniqueId())) {
419 | objective.create(player);
420 |
421 | synchronized (lines) {
422 | for (SidebarLine
305 | * This is useful when looking up fields by a NMS or OBC type.
306 | *
307 | *
308 | * @param lookupName - the class name with variables.
309 | * @return The class.
310 | * @see {@link #getClass()} for more information.
311 | */
312 | public static Class