diff --git a/.editorconfig b/.editorconfig index 095d8c6ef..3788965bf 100644 --- a/.editorconfig +++ b/.editorconfig @@ -76,7 +76,7 @@ ij_java_case_statement_on_separate_line = true ij_java_catch_on_new_line = false ij_java_class_annotation_wrap = split_into_lines ij_java_class_brace_style = end_of_line -ij_java_class_count_to_use_import_on_demand = 5 +ij_java_class_count_to_use_import_on_demand = 999 ij_java_class_names_in_javadoc = 1 ij_java_deconstruction_list_wrap = normal ij_java_do_not_indent_top_level_class_members = false @@ -153,7 +153,7 @@ ij_java_method_parameters_right_paren_on_new_line = false ij_java_method_parameters_wrap = off ij_java_modifier_list_wrap = false ij_java_multi_catch_types_wrap = normal -ij_java_names_count_to_use_import_on_demand = 3 +ij_java_names_count_to_use_import_on_demand = 999 ij_java_new_line_after_lparen_in_annotation = false ij_java_new_line_after_lparen_in_deconstruction_pattern = true ij_java_new_line_after_lparen_in_record_header = false diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 000000000..fe4b4c3d0 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,49 @@ +# This workflow uses actions that GitHub does not certify. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle + +name: Java CI with Gradle + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + + runs-on: ubuntu-latest + permissions: + contents: read + + steps: + - uses: actions/checkout@v5 + with: + fetch-depth: 0 # full history + fetch-tags: true # grab your tags + # Make sure we check out by branch name, not just SHA: + ref: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} + + - name: Set up JDK 21 + uses: actions/setup-java@v5 + with: + java-version: '21' + distribution: 'temurin' + + # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. + # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + + - name: Build with Gradle Wrapper + run: ./gradlew clean build + + - uses: actions/upload-artifact@v4 + with: + name: Staging-Build + path: build/libs + compression-level: '9' diff --git a/.gitignore b/.gitignore index 621f439f7..11ea81483 100644 --- a/.gitignore +++ b/.gitignore @@ -1,34 +1,184 @@ -# Compiled class file -*.class - -# Log file -*.log - -# BlueJ files -*.ctxt - -# Mobile Tools for Java (J2ME) -.mtj.tmp/ - -# Package Files # -*.jar -*.war -*.nar -*.ear -*.zip -*.tar.gz -*.rar -*.xml +# Created by https://www.toptal.com/developers/gitignore/api/intellij,gradle,maven +# Edit at https://www.toptal.com/developers/gitignore?templates=intellij,gradle,maven + +### Intellij ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# AWS User-specific +.idea/**/aws.xml + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +.idea/artifacts +.idea/compiler.xml +.idea/jarRepositories.xml +.idea/modules.xml +.idea/*.iml +.idea/modules *.iml +*.ipr -# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml -hs_err_pid* +# CMake +cmake-build-*/ -# Maven -.classpath -.project -.settings/ +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +### Intellij Patch ### +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 + +.idea/misc.xml +# *.ipr + +# SonarLint plugin +.idea/sonarlint/ + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +# Sonarlint plugin +# https://plugins.jetbrains.com/plugin/7973-sonarlint +.idea/**/sonarlint/ + +# SonarQube Plugin +# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin +.idea/**/sonarIssues.xml + +# Markdown Navigator plugin +# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced +.idea/**/markdown-navigator.xml +.idea/**/markdown-navigator-enh.xml +.idea/**/markdown-navigator/ + +# Cache file creation bug +# See https://youtrack.jetbrains.com/issue/JBR-2257 +.idea/$CACHE_FILE$ + +# CodeStream plugin +# https://plugins.jetbrains.com/plugin/12206-codestream +.idea/codestream.xml + +# Azure Toolkit for IntelliJ plugin +# https://plugins.jetbrains.com/plugin/8053-azure-toolkit-for-intellij +.idea/**/azureSettings.xml + +### Maven ### target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +# https://github.com/takari/maven-wrapper#usage-without-binary-jar +.mvn/wrapper/maven-wrapper.jar + +# Eclipse m2e generated files +# Eclipse Core +.project +# JDT-specific (Eclipse Java Development Tools) +.classpath + +### Gradle ### +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache + +# Eclipse Gradle plugin generated files +# Eclipse Core +# JDT-specific (Eclipse Java Development Tools) + +### Gradle Patch ### +# Java heap dump +*.hprof + +# End of https://www.toptal.com/developers/gitignore/api/intellij,gradle,maven + +# Created by https://www.toptal.com/developers/gitignore/api/git +# Edit at https://www.toptal.com/developers/gitignore?templates=git + +### Git ### +# Created by git for backups. To disable backups in Git: +# $ git config --global mergetool.keepBackup false +*.orig + +# Created by git when using merge tools for conflicts +*.BACKUP.* +*.BASE.* +*.LOCAL.* +*.REMOTE.* +*_BACKUP_*.txt +*_BASE_*.txt +*_LOCAL_*.txt +*_REMOTE_*.txt + +# End of https://www.toptal.com/developers/gitignore/api/git + +# Custom -# .idea -.idea/ \ No newline at end of file +/.idea/git_toolbox_prj.xml +/.idea/.name diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 000000000..3f22c8f34 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt index dae462c79..2ff6e64f7 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,7 @@ MIT License -Copyright (c) 2021 Alps BTE +Copyright (c) Alps BTE +Copyright (c) contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 4dc8376fd..bc48c5b85 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,11 @@ +

- Logo + Plot System Logo

@@ -24,12 +26,9 @@ build status code quality releases - total lines repo size

- - # About The Project The Plot System is an essential part of any BuildTheEarth server system, meant to run alongside the classic Terra servers to make participating a lot easier @@ -49,15 +48,23 @@ The plugin is mostly developed by the Alps-BTE team and is intended for everyone If you have any questions regarding the setup or contribution, please do not hesitate to contact us. All used Libraries and APIs are listed below. + # Features ## Plot Types -![FocusMode_PlotSystemBanner](https://user-images.githubusercontent.com/64250550/184678178-f8b5c3e5-ec35-4b6b-9b1b-ac3170148d34.png)The focus mode is the old well-known mode that was also used by default before the release of v3.0. Build your plot on a floating island in an empty void world. Simple and straightforward, like in the good old days. +![FocusMode_PlotSystemBanner](https://user-images.githubusercontent.com/64250550/184678178-f8b5c3e5-ec35-4b6b-9b1b-ac3170148d34.png) +The focus mode is the old well-known mode that was also used by default before the release of v3.0. Build your plot on a +floating island in an empty void world. Simple and straightforward, like in the good old days.

➖ No Environment
➖ No Neighbouring Plots -


![InspirationMode_PlotSystemBanner](https://user-images.githubusercontent.com/64250550/184681201-2f7e2103-df8d-42a3-93b0-ce42770e4fa8.png)The inspiration mode feels like building in a normal world. By adding the surrounding area of your plot, you will see neighbouring buildings, streets and vegetation. In comparison to the focus mode, you will have a better orientation which helps you when building. This mode is selected as default, when using the Plot System for the first time. +

![InspirationMode_PlotSystemBanner](https://user-images.githubusercontent.com/64250550/184681201-2f7e2103-df8d-42a3-93b0-ce42770e4fa8.png) +The inspiration mode feels like building in a normal world. By adding the surrounding area of your plot, you will see +neighbouring buildings, streets and vegetation. In comparison to the focus mode, you will have a better orientation +which helps you when building. This mode is selected as default, when using the Plot System for the first time.

➕ Environment
➖ No Neighbouring Plots -


![CityInspirationMode_PlotSystemBanner](https://user-images.githubusercontent.com/64250550/184683030-27f1760b-09ad-43f7-b5ed-bdd46c972246.png)The city inspiration mode will give you the full building experience by combining the inspiration mode with other players. Build with your friends and others in one world next to each other and see continuous progress. +

![CityInspirationMode_PlotSystemBanner](https://user-images.githubusercontent.com/64250550/184683030-27f1760b-09ad-43f7-b5ed-bdd46c972246.png) +The city inspiration mode will give you the full building experience by combining the inspiration mode with other +players. Build with your friends and others in one world next to each other and see continuous progress.

⚠️ This mode is not fully stable and still in BETA

➕ Environment
➕ Neighbouring Plots @@ -69,17 +76,34 @@ Tutorial, which needs to be completed to use the Plot-System and other features, building process to understand how it works.

- ## Other Features -✔️ Support for **multiple cities** as well as for **continents** and **countries/states**
✔️ **User-friendly menus** and **commands**
✔️ Inbuilt **Get Started Tutorial** for beginners
✔️ **User-friendly menus** and **commands**
✔️ **Multi-Language** Support (currently up to 7 languages)
✔️ Plot **Group System** (Build together with up to 5 people on one plot)
✔️ **SFTP/FTP** Support
✔️ Detailed **review system** with individual feedback
✔️ Three plot **difficulty levels** (easy, medium and hard)
✔️ Building **Quality of Life tools**
✔️ Full **/tpll support** on plots
✔️ **Leaderboards** when using the Holograms extension
✔️ Automatic **abandoning of inactive plots**
✔️ Automatic **placement of completed plots** on the terra server
✔️ **Easy configuration** and **setup**
-# Installation -💻 To use this system, you currently need at least two servers.
One is running Terra+- with the **[Plot-System-Terra Plugin](https://github.com/AlpsBTE/Plot-System-Terra)** and the -other one is a Spigot Vanilla server for the Plot-System itself.
**For more information check out the [Wiki](https://github.com/AlpsBTE/Plot-System/wiki/Installation)**! +✔️ Support for **multiple cities** as well as for **continents** and **countries/states**
+✔️ **User-friendly menus** and **commands**
+✔️ Inbuilt **Get Started Tutorial** for beginners
+✔️ **User-friendly menus** and **commands**
+✔️ **Multi-Language** Support
+✔️ Plot **Group System** (Build together with up to 5 people on one plot)
+✔️ Detailed **review system** with individual feedback
+✔️ Three plot **difficulty levels** (easy, medium and hard)
+✔️ Building **Quality of Life tools**
+✔️ Full **/tpll support** on plots
+✔️ **Leaderboards** when using the Holograms extension
+✔️ Automatic **abandoning of inactive plots**
+✔️ Automatic **placement of completed plots** on the terra server
+✔️ **Easy configuration** and **setup**
+# Installation +💻 To use this system, you currently need at least two servers.
+One server runs [Terra++](https://github.com/BTE-Germany/TerraPlusMinus) together with the +**[Plot-System-Terra](https://github.com/AlpsBTE/Plot-System-Terra)** plugin, while the other is a Paper server +dedicated to the Plot-System itself.
+**For more information check out the [Wiki](https://github.com/AlpsBTE/Plot-System/wiki/Installation)**! - # Roadmap -📋 Web Interface
📋 Discord Integration
📋 Statistics
+📋 Web Interface
+📋 Discord Integration
+📋 Statistics
+ # Contributing 🔨 Any contributions you make are greatly appreciated. @@ -88,24 +112,20 @@ other one is a Spigot Vanilla server for the Plot-System itself.
**For more * Submitting a fix * Proposing new features - - # License - Distributed under the MIT License. See `LICENSE` for more information. - - # Libraries & APIs -* [Paper API](https://github.com/PaperMC/Paper) -* [FAWE API](https://github.com/IntellectualSites/FastAsyncWorldEdit) -* [WorldGuard API](https://github.com/EngineHub/WorldGuard) -* [Multiverse-Core API](https://github.com/Multiverse/Multiverse-Core) -* [Canvas Menu-Builder Library](https://github.com/IPVP-MC/canvas) -* [Head-DB API](https://github.com/Arcaniax-Development/HeadDatabase-API) -* [Holographic Displays API](https://github.com/filoghost/HolographicDisplays) -* [Maria-DB Library](https://mariadb.com/kb/en/about-mariadb-connector-j/) -* [Hikari-CP](https://github.com/brettwooldridge/HikariCP) -* [Apache Common VFS API](https://commons.apache.org/proper/commons-vfs/commons-vfs2/apidocs/index.html) -* [ProtocolLIB](https://github.com/dmulloy2/ProtocolLib) +* [Paper](https://github.com/PaperMC/Paper) +* [FAWE](https://github.com/IntellectualSites/FastAsyncWorldEdit) +* [WorldGuard](https://github.com/EngineHub/WorldGuard) +* [Multiverse Core](https://github.com/Multiverse/Multiverse-Core) +* [Particle Native](https://github.com/Fierioziy/ParticleNativeAPI) +* [Canvas](https://github.com/AlpsBTE/Canvas) +* [HeadDatabase](https://github.com/Arcaniax-Development/HeadDatabase-API) +* [DecentHolograms](https://github.com/DecentSoftware-eu/DecentHolograms) +* [MariaDB](https://mariadb.com/kb/en/about-mariadb-connector-j/) +* [HikariCP](https://github.com/brettwooldridge/HikariCP) * [Fancy NPCs](https://github.com/FancyMcPlugins/FancyNpcs) +* [AlpsLib](https://github.com/AlpsBTE/Alps-Lib) +* [LangLibs](https://github.com/Cinnazeyy/LangLibs) \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 000000000..6013616a4 --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,113 @@ +plugins { + java + id("com.palantir.git-version") version "4.0.0" + id("com.gradleup.shadow") version "9.0.2" +} + +repositories { + // mavenLocal() // NEVER use in Production/Commits! + maven { + url = uri("https://jitpack.io") + } + + maven { + url = uri("https://repo.papermc.io/repository/maven-public/") + } + + maven { + url = uri("https://mvn.alps-bte.com/repository/alps-bte/") + } + + maven { + url = uri("https://repo.fancyplugins.de/releases") + } + + maven { + url = uri("https://maven.enginehub.org/repo/") + } + + maven { + url = uri("https://repo.onarandombox.com/content/groups/public/") + } + + maven { + url = uri("https://repo.codemc.io/repository/maven-public/") + } + + maven { + url = uri("https://repo.maven.apache.org/maven2/") + } +} + +dependencies { + implementation(libs.com.alpsbte.canvas) + implementation(libs.com.alpsbte.alpslib.alpslib.io) + implementation(libs.com.alpsbte.alpslib.alpslib.hologram) + implementation(libs.com.alpsbte.alpslib.alpslib.utils) + implementation(libs.org.mariadb.jdbc.mariadb.java.client) + implementation(libs.com.zaxxer.hikaricp) + compileOnly(libs.io.papermc.paper.paper.api) + implementation(platform(libs.com.intellectualsites.bom.bom.newest)) + compileOnly("com.fastasyncworldedit:FastAsyncWorldEdit-Core") + compileOnly(libs.com.sk89q.worldguard.worldguard.bukkit) + compileOnly(libs.multiverse.core) + compileOnly(libs.com.github.fierioziy.particlenativeapi.particlenativeapi.plugin) + compileOnly(libs.com.arcaniax.headdatabase.api) + compileOnly(libs.com.github.decentsoftware.eu.decentholograms) + compileOnly(libs.de.oliver.fancynpcs) + compileOnly(libs.li.cinnazeyy.langlibs.api) + compileOnly(libs.commons.io.commons.io) +} + +val versionDetails: groovy.lang.Closure by extra +val details = versionDetails() + +group = "com.alpsbte" +version = "5.0.0" + "-" + details.commitDistance + "-" + details.gitHash + "-SNAPSHOT" +description = "An easy to use building system for the BuildTheEarth project." +java.sourceCompatibility = JavaVersion.VERSION_21 + +tasks.withType { + options.encoding = "UTF-8" +} + +tasks.withType { + options.encoding = "UTF-8" +} + +tasks.shadowJar { + // Exclude annotation classes (e.g. org.jetbrains.annotations) + exclude("org/jetbrains/annotations/**") + // Exclude slf4j classes + exclude("org/slf4j/**") + exclude("META-INF/**") + archiveClassifier = "" + + val relocationPrefix = "alpsplotsystem.libs" + relocate("com.alpsbte.alpslib", "$relocationPrefix.com.alpsbte.alpslib") + relocate("org.mariadb.jdbc", "$relocationPrefix.org.mariadb.jdbc") + relocate("com.zaxxer.hikari", "$relocationPrefix.com.zaxxer.hikari") +} + +tasks.assemble { + dependsOn(tasks.shadowJar) // Ensure that the shadowJar task runs before the build task +} + +tasks.jar { + enabled = false // Disable the default jar task since we are using shadowJar +} + +tasks.processResources { + // work around IDEA-296490 + duplicatesStrategy = DuplicatesStrategy.INCLUDE + with(copySpec { + from("src/main/resources/plugin.yml") { + expand( + mapOf( + "version" to project.version, + "description" to project.description + ) + ) + } + }) +} diff --git a/gradle.properties b/gradle.properties new file mode 100644 index 000000000..e19f37c1b --- /dev/null +++ b/gradle.properties @@ -0,0 +1,3 @@ +# https://docs.gradle.org/current/userguide/build_environment.html#sec:gradle_configuration_properties +org.gradle.configuration-cache=true + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml new file mode 100644 index 000000000..0af5093b9 --- /dev/null +++ b/gradle/libs.versions.toml @@ -0,0 +1,38 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format + +[versions] +com-alpsbte-alpslib-alpslib-hologram = "1.1.1" +com-alpsbte-alpslib-alpslib-io = "1.2.0" +com-alpsbte-alpslib-alpslib-utils = "1.3.6" +com-alpsbte-canvas = "1.3" +com-arcaniax-headdatabase-api = "1.3.2" +com-github-decentsoftware-eu-decentholograms = "2.9.2" +com-github-fierioziy-particlenativeapi-particlenativeapi-plugin = "3.3.2" +multiverse-core = "5.3.0" +com-sk89q-worldguard-worldguard-bukkit = "7.1.0-SNAPSHOT" +com-zaxxer-hikaricp = "6.3.0" +commons-io-commons-io = "2.20.0" +de-oliver-fancynpcs = "2.7.0" +io-papermc-paper-paper-api = "1.21.8-R0.1-SNAPSHOT" +li-cinnazeyy-langlibs-api = "1.5.1" +org-mariadb-jdbc-mariadb-java-client = "2.7.4" +com-intellectualsites-bom-bom-newest = "1.55" # Ref: https://github.com/IntellectualSites/bom + +[libraries] +com-alpsbte-alpslib-alpslib-hologram = { module = "com.alpsbte.alpslib:alpslib-hologram", version.ref = "com-alpsbte-alpslib-alpslib-hologram" } +com-alpsbte-alpslib-alpslib-io = { module = "com.alpsbte.alpslib:alpslib-io", version.ref = "com-alpsbte-alpslib-alpslib-io" } +com-alpsbte-alpslib-alpslib-utils = { module = "com.alpsbte.alpslib:alpslib-utils", version.ref = "com-alpsbte-alpslib-alpslib-utils" } +com-alpsbte-canvas = { module = "com.alpsbte:canvas", version.ref = "com-alpsbte-canvas" } +com-arcaniax-headdatabase-api = { module = "com.arcaniax:HeadDatabase-API", version.ref = "com-arcaniax-headdatabase-api" } +com-github-decentsoftware-eu-decentholograms = { module = "com.github.decentsoftware-eu:decentholograms", version.ref = "com-github-decentsoftware-eu-decentholograms" } +com-github-fierioziy-particlenativeapi-particlenativeapi-plugin = { module = "com.github.fierioziy.particlenativeapi:ParticleNativeAPI-plugin", version.ref = "com-github-fierioziy-particlenativeapi-particlenativeapi-plugin" } +multiverse-core = { module = "org.mvplugins.multiverse.core:multiverse-core", version.ref = "multiverse-core" } +com-sk89q-worldguard-worldguard-bukkit = { module = "com.sk89q.worldguard:worldguard-bukkit", version.ref = "com-sk89q-worldguard-worldguard-bukkit" } +com-zaxxer-hikaricp = { module = "com.zaxxer:HikariCP", version.ref = "com-zaxxer-hikaricp" } +commons-io-commons-io = { module = "commons-io:commons-io", version.ref = "commons-io-commons-io" } +de-oliver-fancynpcs = { module = "de.oliver:FancyNpcs", version.ref = "de-oliver-fancynpcs" } +io-papermc-paper-paper-api = { module = "io.papermc.paper:paper-api", version.ref = "io-papermc-paper-paper-api" } +li-cinnazeyy-langlibs-api = { module = "li.cinnazeyy:LangLibs-API", version.ref = "li-cinnazeyy-langlibs-api" } +org-mariadb-jdbc-mariadb-java-client = { module = "org.mariadb.jdbc:mariadb-java-client", version.ref = "org-mariadb-jdbc-mariadb-java-client" } +com-intellectualsites-bom-bom-newest = { module = "com.intellectualsites.bom:bom-newest", version.ref = "com-intellectualsites-bom-bom-newest" } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..1b33c55ba Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 000000000..2a84e188b --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 000000000..342f59614 --- /dev/null +++ b/gradlew @@ -0,0 +1,233 @@ +#!/bin/sh + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH="\\\"\\\"" + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 000000000..db3a6ac20 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH= + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/pom.xml b/pom.xml index 680e26dd8..bbcc0a996 100644 --- a/pom.xml +++ b/pom.xml @@ -1,27 +1,4 @@ - com.alpsbte PlotSystem - 4.1.4 + 5.0.0 + An easy to use building system for the BuildTheEarth project. @@ -64,16 +42,11 @@ OnARandomBox https://repo.onarandombox.com/content/groups/public/ - + codemc-repo https://repo.codemc.io/repository/maven-public/ - - - dmulloy2-repo - https://repo.dmulloy2.net/repository/public/ - @@ -81,7 +54,7 @@ io.papermc.paper paper-api - 1.21.4-R0.1-SNAPSHOT + 1.21.8-R0.1-SNAPSHOT provided @@ -99,9 +72,9 @@ - com.onarandombox.multiversecore - Multiverse-Core - 4.3.1 + org.mvplugins.multiverse.core + multiverse-core + 5.3.0 provided @@ -115,7 +88,7 @@ com.alpsbte canvas - 1.1 + 1.3 compile @@ -129,14 +102,14 @@ com.github.decentsoftware-eu decentholograms - 2.8.12 + 2.9.2 provided com.alpsbte.alpslib alpslib-io - 1.0.38 + 1.2.0 com.alpsbte.alpslib @@ -147,7 +120,7 @@ com.alpsbte.alpslib alpslib-utils - 1.3.4 + 1.3.6 compile @@ -161,48 +134,39 @@ com.zaxxer HikariCP - 4.0.3 - compile - - - - org.apache.commons - commons-vfs2 - 2.4 - compile - - - - commons-net - commons-net - 3.11.0 - compile - - - - com.jcraft - jsch - 0.1.55 + 6.3.0 + + + org.slf4j + slf4j-api + + compile - com.comphenix.protocol + net.dmulloy2 ProtocolLib - 5.1.0 + 5.4.0 provided de.oliver FancyNpcs - 2.4.0 + 2.7.0 provided li.cinnazeyy - LangLibs - 1.5 + LangLibs-API + 1.5.1 + provided + + + commons-io + commons-io + 2.17.0 provided @@ -226,6 +190,16 @@ ${basedir}/src/main/resources false + + plugin.yml + + + + ${basedir}/src/main/resources + true + + plugin.yml + ./lang @@ -246,7 +220,7 @@ src/main/java/ - ${project.artifactId}-${project.version}-${build.number} + ${project.artifactId}-${project.version}${build.number} org.apache.maven.plugins @@ -292,7 +266,7 @@ UTF-8 UTF-8 - + 21 - + \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 000000000..22487c716 --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1 @@ +rootProject.name = "PlotSystem" diff --git a/src/main/java/com/alpsbte/plotsystem/PlotSystem.java b/src/main/java/com/alpsbte/plotsystem/PlotSystem.java index 011bf1480..201a59126 100644 --- a/src/main/java/com/alpsbte/plotsystem/PlotSystem.java +++ b/src/main/java/com/alpsbte/plotsystem/PlotSystem.java @@ -1,37 +1,14 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem; import com.alpsbte.alpslib.hologram.DecentHologramDisplay; import com.alpsbte.alpslib.io.YamlFileFactory; import com.alpsbte.alpslib.io.config.ConfigNotImplementedException; +import com.alpsbte.alpslib.io.database.DatabaseConfigPaths; +import com.alpsbte.alpslib.io.database.DatabaseConnection; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.alpslib.utils.head.AlpsHeadEventListener; import com.alpsbte.plotsystem.commands.CommandManager; import com.alpsbte.plotsystem.core.EventListener; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; import com.alpsbte.plotsystem.core.holograms.HologramRegister; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.Plot; @@ -42,76 +19,52 @@ import com.alpsbte.plotsystem.core.system.tutorial.TutorialEventListener; import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialNPCTurnTracker; import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; -import com.alpsbte.plotsystem.utils.PacketListener; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.ConfigUtil; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.onarandombox.MultiverseCore.MultiverseCore; -import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import com.google.common.io.CharStreams; import de.oliver.fancynpcs.api.FancyNpcsPlugin; import net.kyori.adventure.text.Component; -import org.apache.maven.artifact.versioning.ComparableVersion; import org.bukkit.Bukkit; import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.ipvp.canvas.MenuFunctionListener; import org.jetbrains.annotations.NotNull; import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.*; -import java.util.function.Consumer; +import java.sql.SQLException; +import java.util.Collections; +import java.util.Objects; +import java.util.UUID; -import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; +import static net.kyori.adventure.text.format.NamedTextColor.YELLOW; public class PlotSystem extends JavaPlugin { - private static final String VERSION = "4.1.3"; - private static PlotSystem plugin; - private CommandManager commandManager; - private boolean pluginEnabled = false; @Override public void onEnable() { - System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog"); // Disable Logging YamlFileFactory.registerPlugin(this); plugin = this; Component successPrefix = text("[", DARK_GRAY).append(text("✔", DARK_GREEN)).append(text("]", DARK_GRAY)).append(text(" ", GRAY)); Component errorPrefix = text("[", DARK_GRAY).append(text("X", RED)).append(text("]", DARK_GRAY)).append(text(" ", GRAY)); - Bukkit.getConsoleSender().sendMessage(text("------------------ Plot-System V" + VERSION + " ------------------", GOLD)); - Bukkit.getConsoleSender().sendMessage(text("Starting plugin...", DARK_GREEN)); - Bukkit.getConsoleSender().sendMessage(empty()); - - // Check for required dependencies, if it returns false disable plugin - if (!DependencyManager.checkForRequiredDependencies()) { - Bukkit.getConsoleSender().sendMessage(errorPrefix.append(text("Could not load required dependencies."))); - Bukkit.getConsoleSender().sendMessage(text("Missing Dependencies:", YELLOW)); - DependencyManager.missingDependencies.forEach(dependency -> Bukkit.getConsoleSender().sendMessage(text(" - " + dependency, YELLOW))); - - this.getServer().getPluginManager().disablePlugin(this); - return; - } - Bukkit.getConsoleSender().sendMessage(successPrefix.append(text("Successfully loaded required dependencies."))); - // Load config, if it throws an exception disable plugin try { ConfigUtil.init(); - Bukkit.getConsoleSender().sendMessage(successPrefix.append(text("Successfully loaded configuration files."))); + getComponentLogger().info(successPrefix.append(text("Successfully loaded configuration files."))); } catch (ConfigNotImplementedException ex) { - Bukkit.getConsoleSender().sendMessage(errorPrefix.append(text("Could not load configuration file."))); - Bukkit.getConsoleSender().sendMessage(text("The config file must be configured!", YELLOW)); - + getComponentLogger().error(errorPrefix.append(text("Could not load configuration file."))); + getComponentLogger().info(text("The config file must be configured!", YELLOW)); this.getServer().getPluginManager().disablePlugin(this); return; } @@ -120,7 +73,7 @@ public void onEnable() { // Load language files try { LangUtil.init(); - Bukkit.getConsoleSender().sendMessage(successPrefix.append(text("Successfully loaded language files."))); + getComponentLogger().info(successPrefix.append(text("Successfully loaded language files."))); } catch (Exception ex) { PlotSystem.getPlugin().getComponentLogger().error(text("Could not load language file."), ex); this.getServer().getPluginManager().disablePlugin(this); @@ -129,12 +82,10 @@ public void onEnable() { // Initialize database connection try { - DatabaseConnection.InitializeDatabase(); - Bukkit.getConsoleSender().sendMessage(successPrefix.append(text("Successfully initialized database connection."))); + initDatabase(); + getComponentLogger().info(successPrefix.append(text("Successfully initialized database connection."))); } catch (Exception ex) { - Bukkit.getConsoleSender().sendMessage(errorPrefix.append(text("Could not initialize database connection."))); - PlotSystem.getPlugin().getComponentLogger().error(text(ex.getMessage()), ex); - + getComponentLogger().error(errorPrefix.append(text("Could not initialize database connection.")), ex); this.getServer().getPluginManager().disablePlugin(this); return; } @@ -146,62 +97,30 @@ public void onEnable() { this.getServer().getPluginManager().registerEvents(new AlpsHeadEventListener(), this); if (getConfig().getBoolean(ConfigPaths.TUTORIAL_ENABLE)) this.getServer().getPluginManager().registerEvents(new TutorialEventListener(), this); - Bukkit.getConsoleSender().sendMessage(successPrefix.append(text("Successfully registered event listeners."))); + getComponentLogger().info(successPrefix.append(text("Successfully registered event listeners."))); } catch (Exception ex) { - Bukkit.getConsoleSender().sendMessage(errorPrefix.append(text("Could not register event listeners."))); - PlotSystem.getPlugin().getComponentLogger().error(text(ex.getMessage()), ex); - + getComponentLogger().error(errorPrefix.append(text("Could not register event listeners.")), ex); this.getServer().getPluginManager().disablePlugin(this); return; } // Register commands try { - commandManager = new CommandManager(); + CommandManager commandManager = new CommandManager(); commandManager.init(); - Bukkit.getConsoleSender().sendMessage(successPrefix.append(text("Successfully registered commands."))); + getComponentLogger().info(successPrefix.append(text("Successfully registered commands."))); } catch (Exception ex) { - Bukkit.getConsoleSender().sendMessage(errorPrefix.append(text("Could not register commands."))); - PlotSystem.getPlugin().getComponentLogger().error(text(ex.getMessage()), ex); - + getComponentLogger().error(errorPrefix.append(text("Could not register commands.")), ex); this.getServer().getPluginManager().disablePlugin(this); return; } - if (!DependencyManager.isWorldGuardExtraFlagsEnabled()) PlotSystem.getPlugin().getComponentLogger().warn(text("WorldGuardExtraFlags is not enabled!")); - - // Check for updates - Bukkit.getConsoleSender().sendMessage(empty()); - Bukkit.getConsoleSender().sendMessage(text("Update-Checker:", GOLD)); - - UpdateChecker.getVersion(version -> { - if (new ComparableVersion(VERSION).compareTo(new ComparableVersion(version)) >= 0) { - Bukkit.getConsoleSender().sendMessage(text("You are using the latest stable version.", YELLOW)); - } else { - UpdateChecker.isUpdateAvailable = true; - Bukkit.getConsoleSender().sendMessage(text("You are using a outdated version!", RED)); - Bukkit.getConsoleSender().sendMessage(text("Latest version: ", GRAY).append(text(version, GREEN)).append(text(" | Your version: ", GRAY)).append(text(VERSION, RED))); - Bukkit.getConsoleSender().sendMessage(text("Update here: ", GRAY).append(text("https://github.com/AlpsBTE/Plot-System/releases", AQUA))); - } - }); - DecentHologramDisplay.registerPlugin(this); HologramRegister.init(); PlotUtils.checkPlotsForLastActivity(); - PlotUtils.syncPlotSchematicFiles(); Utils.ChatUtils.checkForChatInputExpiry(); PlotUtils.Effects.startTimer(); - try { - new PacketListener(); - } catch (NoClassDefFoundError ex) { - Bukkit.getConsoleSender().sendMessage(empty()); - Bukkit.getConsoleSender().sendMessage(text("Could not find Protocol-Lib! Consider installing it to avoid issues.", RED)); - } - - // Cache and register custom heads - Bukkit.getScheduler().runTaskAsynchronously(this, Utils::registerCustomHeads); - // Register tutorials if (getConfig().getBoolean(ConfigPaths.TUTORIAL_ENABLE)) { AbstractTutorial.registerTutorials(Collections.singletonList(BeginnerTutorial.class)); @@ -209,29 +128,31 @@ public void onEnable() { } pluginEnabled = true; - Bukkit.getConsoleSender().sendMessage(empty()); - Bukkit.getConsoleSender().sendMessage(text("Enabled Plot-System plugin.", DARK_GREEN)); - Bukkit.getConsoleSender().sendMessage(text("------------------------------------------------------", GOLD)); - Bukkit.getConsoleSender().sendMessage(text("> ", DARK_GRAY).append(text("Made by ", GRAY)).append(text("Alps BTE (AT/CH/LI)", RED))); - Bukkit.getConsoleSender().sendMessage(text("> ", DARK_GRAY).append(text("GitHub: ", GRAY)).append(text("https://github.com/AlpsBTE/Plot-System", WHITE))); - Bukkit.getConsoleSender().sendMessage(text("------------------------------------------------------", GOLD)); + getComponentLogger().info(text("Enabled Plot-System plugin.", DARK_GREEN)); + getComponentLogger().info(text("------------------------------------------------------", GOLD)); + getComponentLogger().info(text("> ", DARK_GRAY).append(text("Made by ", GRAY)).append(text("Alps BTE (AT/CH/LI)", RED))); + getComponentLogger().info(text("> ", DARK_GRAY).append(text("GitHub: ", GRAY)).append(text("https://github.com/AlpsBTE/Plot-System", WHITE))); + getComponentLogger().info(text("------------------------------------------------------", GOLD)); } @Override public void onDisable() { if (!pluginEnabled) { - Bukkit.getConsoleSender().sendMessage(empty()); - Bukkit.getConsoleSender().sendMessage(text("Disabling plugin...", RED)); - Bukkit.getConsoleSender().sendMessage(text("------------------------------------------------------", GOLD)); - Bukkit.getConsoleSender().sendMessage(text("> ", DARK_GRAY).append(text("Made by ", GRAY)).append(text("Alps BTE (AT/CH/LI)", RED))); - Bukkit.getConsoleSender().sendMessage(text("> ", DARK_GRAY).append(text("GitHub: ", GRAY)).append(text("https://github.com/AlpsBTE/Plot-System", WHITE))); - Bukkit.getConsoleSender().sendMessage(text("------------------------------------------------------", GOLD)); + getComponentLogger().info(text("Disabling plugin...", RED)); + getComponentLogger().info(text("------------------------------------------------------", GOLD)); + getComponentLogger().info(text("> ", DARK_GRAY).append(text("Made by ", GRAY)).append(text("Alps BTE (AT/CH/LI)", RED))); + getComponentLogger().info(text("> ", DARK_GRAY).append(text("GitHub: ", GRAY)).append(text("https://github.com/AlpsBTE/Plot-System", WHITE))); + getComponentLogger().info(text("------------------------------------------------------", GOLD)); DecentHologramDisplay.activeDisplays.forEach(DecentHologramDisplay::delete); } else { + // Close database connection + DatabaseConnection.shutdown(); + // Unload plots for (UUID player : PlotUtils.Cache.getCachedInProgressPlots().keySet()) { - for (Plot plot : PlotUtils.Cache.getCachedInProgressPlots(Builder.byUUID(player))) { + Builder builder = Builder.byUUID(player); + for (Plot plot : PlotUtils.Cache.getCachedInProgressPlots(builder)) { if (plot != null) plot.getWorld().unloadWorld(true); } } @@ -268,140 +189,11 @@ public static PlotSystem getPlugin() { return plugin; } - public CommandManager getCommandManager() { - return commandManager; - } - - - public static class DependencyManager { - - // List with all missing dependencies - private static final List missingDependencies = new ArrayList<>(); - - /** - * Check for all required dependencies and inform in console about missing dependencies - * - * @return True if all dependencies are present - */ - private static boolean checkForRequiredDependencies() { - PluginManager pluginManager = plugin.getServer().getPluginManager(); - if (!pluginManager.isPluginEnabled("DecentHolograms")) { - missingDependencies.add("DecentHolograms"); - } - - if (!pluginManager.isPluginEnabled("Multiverse-Core")) { - missingDependencies.add("Multiverse-Core"); - } - - if (!pluginManager.isPluginEnabled("FastAsyncWorldEdit")) { - missingDependencies.add("FastAsyncWorldEdit"); - } - - if (!pluginManager.isPluginEnabled("WorldGuard")) { - missingDependencies.add("WorldGuard"); - } - - if (!pluginManager.isPluginEnabled("HeadDatabase")) { - missingDependencies.add("HeadDatabase"); - } - - if (!pluginManager.isPluginEnabled("VoidGen")) { - missingDependencies.add("VoidGen"); - } - - if (!pluginManager.isPluginEnabled("LangLibs")) { - missingDependencies.add("LangLibs"); - } - - if (!pluginManager.isPluginEnabled("FancyNpcs")) { - missingDependencies.add("FancyNpcs"); - } - - return missingDependencies.isEmpty(); - } - - /** - * @return True if ParticleNativeAPI is present - */ - public static boolean isParticleNativeAPIEnabled() { - return plugin.getServer().getPluginManager().isPluginEnabled("ParticleNativeAPI"); - } - - public static boolean isMultiverseInventoriesEnabled() { - return plugin.getServer().getPluginManager().isPluginEnabled("Multiverse-Inventories"); - } - - public static boolean isWorldGuardExtraFlagsEnabled() { - return plugin.getServer().getPluginManager().isPluginEnabled("WorldGuardExtraFlags"); - } - - /** - * @param worldName Name of the world - * @return Config path for the world - */ - public static String getMultiverseInventoriesConfigPath(String worldName) { - return PlotSystem.DependencyManager.isMultiverseInventoriesEnabled() ? Objects.requireNonNull(Bukkit.getPluginManager().getPlugin("Multiverse-Inventories")).getDataFolder() + "/worlds/" + worldName : ""; - } - - /** - * @return Multiverse-Core instance - */ - public static MultiverseCore getMultiverseCore() { - return (MultiverseCore) plugin.getServer().getPluginManager().getPlugin("Multiverse-Core"); - } - - /** - * @return World Edit instance - */ - public static WorldEdit getWorldEdit() { - return WorldEdit.getInstance(); - } - - /** - * @return World Guard instance - */ - public static WorldGuardPlugin getWorldGuard() { - return WorldGuardPlugin.inst(); - } - - /** - * @param worldName Name of the world - * @return Config path for the world - */ - public static String getWorldGuardConfigPath(String worldName) { - return Objects.requireNonNull(Bukkit.getPluginManager().getPlugin("WorldGuard")).getDataFolder() + "/worlds/" + worldName; - } - - /** - * @return Protocol Lib Instance - */ - public static ProtocolManager getProtocolManager() {return ProtocolLibrary.getProtocolManager();} - } - - public static class UpdateChecker { - private static final int RESOURCE_ID = 95757; - private static boolean isUpdateAvailable = false; - - /** - * Get the latest plugin version from SpigotMC - * - * @param version Returns latest stable version - */ - public static void getVersion(final Consumer version) { - try (InputStream inputStream = new URI("https://api.spigotmc.org/legacy/update.php?resource=" + RESOURCE_ID).toURL().openStream(); Scanner scanner = new Scanner(inputStream)) { - if (scanner.hasNext()) { - version.accept(scanner.next()); - } - } catch (IOException | URISyntaxException ex) { - PlotSystem.getPlugin().getComponentLogger().warn(text("Cannot look for new updates:" + ex.getMessage())); - } - } - - /** - * @return True if an update is available - */ - public static boolean updateAvailable() { - return isUpdateAvailable; + public void initDatabase() throws IOException, SQLException, ClassNotFoundException { + DatabaseConnection.initializeDatabase(DatabaseConfigPaths.getConfig(getConfig()), true); + var initScript = CharStreams.toString(Objects.requireNonNull(getTextResource("DATABASE.sql"))); + try (var con = DatabaseConnection.getConnection(); var s = con.createStatement()) { + s.execute(initScript); } } } \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/commands/BaseCommand.java b/src/main/java/com/alpsbte/plotsystem/commands/BaseCommand.java index b308ac4cb..9f696a6dd 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/BaseCommand.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/BaseCommand.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands; import com.alpsbte.plotsystem.utils.Utils; @@ -99,7 +75,7 @@ public List getSubCommands() { * @return null if sender is not a player */ protected Player getPlayer(CommandSender sender) { - return sender instanceof Player ? (Player) sender : null; + return sender instanceof Player p ? p : null; } /** diff --git a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Companion.java b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Companion.java index cd7087899..006d06a77 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Companion.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Companion.java @@ -1,30 +1,5 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands; -import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.core.menus.companion.CompanionMenu; import com.alpsbte.plotsystem.core.menus.tutorial.TutorialStagesMenu; import com.alpsbte.plotsystem.core.menus.tutorial.TutorialsMenu; @@ -33,19 +8,13 @@ import com.alpsbte.plotsystem.core.system.tutorial.Tutorial; import com.alpsbte.plotsystem.core.system.tutorial.TutorialCategory; import com.alpsbte.plotsystem.utils.Utils; -import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; - -import static net.kyori.adventure.text.Component.text; - public class CMD_Companion extends BaseCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { @@ -54,20 +23,15 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @N return true; } - if (getPlayer(sender) == null) return true; + Player player = getPlayer(sender); + if (player == null) return true; - try { - FileConfiguration config = PlotSystem.getPlugin().getConfig(); - Tutorial tutorial = AbstractTutorial.getActiveTutorial(getPlayer(sender).getUniqueId()); - if (tutorial != null) { - new TutorialStagesMenu(getPlayer(sender), tutorial.getId()); - } else if (config.getBoolean(ConfigPaths.TUTORIAL_ENABLE) && config.getBoolean(ConfigPaths.TUTORIAL_REQUIRE_BEGINNER_TUTORIAL) && - !TutorialPlot.isPlotCompleted(getPlayer(sender), TutorialCategory.BEGINNER.getId()) && getPlayer(sender).hasPermission("plotsystem.tutorial")) { - new TutorialsMenu(getPlayer(sender)); - } else CompanionMenu.open((Player) sender); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + Tutorial tutorial = AbstractTutorial.getActiveTutorial(player.getUniqueId()); + if (tutorial != null) { + new TutorialStagesMenu(player, tutorial.getId()); + } else if (TutorialPlot.isRequiredAndInProgress(TutorialCategory.BEGINNER.getId(), player.getUniqueId()) && player.hasPermission("plotsystem.tutorial")) { + new TutorialsMenu(player); + } else CompanionMenu.open((Player) sender); return true; } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Plots.java b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Plots.java index 302425b8f..4d8955826 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Plots.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Plots.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands; import com.alpsbte.plotsystem.PlotSystem; @@ -30,6 +6,7 @@ import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; +import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.command.Command; @@ -37,42 +14,40 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; - -import static net.kyori.adventure.text.Component.text; +import java.util.concurrent.CompletableFuture; public class CMD_Plots extends BaseCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { - if (!sender.hasPermission(getPermission())) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + Player player = getPlayer(sender); + if (player == null) { + Bukkit.getConsoleSender().sendMessage(Component.text("This command can only be used as a player!", NamedTextColor.RED)); return true; } - if (getPlayer(sender) == null) { - Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + if (!sender.hasPermission(getPermission())) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); return true; } - Player player = (Player) sender; - - try { - if (args.length < 1) { - new PlayerPlotsMenu(player, Builder.byUUID(player.getUniqueId())); - return true; - } + if (args.length < 1) { + CompletableFuture.runAsync(() -> { + Builder builder = Builder.byUUID(player.getUniqueId()); + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> new PlayerPlotsMenu(player, builder)); + }); + } - Builder builder = Builder.getBuilderByName(args[0]); - if (builder == null) { - player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_NOT_FOUND))); - return true; - } + CompletableFuture.runAsync(() -> { + Builder builder = Builder.byName(args[0]); + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + if (builder == null) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_NOT_FOUND))); + return; + } - new PlayerPlotsMenu(player, builder); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + new PlayerPlotsMenu(player, builder); + }); + }); return true; } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tpll.java b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tpll.java index 78bbeccb2..de91f1e79 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tpll.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tpll.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands; import com.alpsbte.plotsystem.PlotSystem; @@ -46,7 +22,6 @@ import java.io.IOException; import java.math.RoundingMode; -import java.sql.SQLException; import java.text.DecimalFormat; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -74,78 +49,87 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @N return true; } - try { - if (args == null || args.length < 2 || args.length > 3) { - sendInfo(sender); - return true; - } + if (args == null || args.length < 2 || args.length > 3) { + sendInfo(sender); + return true; + } - String[] splitCoords = args[0].split(","); - if (splitCoords.length == 2) { - args = splitCoords; - } + String[] splitCoords = args[0].split(","); + if (splitCoords.length == 2) { + args = splitCoords; + } - if (args[0].endsWith(",")) { - args[0] = args[0].substring(0, args[0].length() - 1); - } - if (args[1].endsWith(",")) { - args[1] = args[1].substring(0, args[1].length() - 1); - } + if (args[0].endsWith(",")) { + args[0] = args[0].substring(0, args[0].length() - 1); + } + if (args[1].endsWith(",")) { + args[1] = args[1].substring(0, args[1].length() - 1); + } + + // Parse coordinates to doubles + double lat; + double lon; + try { + lat = Double.parseDouble(args[0]); + lon = Double.parseDouble(args[1]); + } catch (Exception ignore) { + sendInfo(sender); + return true; + } - // Parse coordinates to doubles - double lat; - double lon; + CompletableFuture.runAsync(() -> { try { - lat = Double.parseDouble(args[0]); - lon = Double.parseDouble(args[1]); - } catch (Exception ignore) { - sendInfo(sender); - return true; - } + // Get the terra coordinates from the irl coordinates + double[] terraCoords = CoordinateConversion.convertFromGeo(lon, lat); - // Get the terra coordinates from the irl coordinates - double[] terraCoords = CoordinateConversion.convertFromGeo(lon, lat); + // Get plot, that the player is in + AbstractPlot plot = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unfinished, Status.unreviewed, Status.completed); - // Get plot, that the player is in - AbstractPlot plot = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unfinished, Status.unreviewed, Status.completed); + // Convert terra coordinates to plot relative coordinates + CompletableFuture plotCoordsFuture = plot != null ? PlotUtils.convertTerraToPlotXZ(plot, terraCoords) : null; - // Convert terra coordinates to plot relative coordinates - CompletableFuture plotCoords = plot != null ? PlotUtils.convertTerraToPlotXZ(plot, terraCoords) : null; + if (plotCoordsFuture == null) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.CANNOT_TELEPORT_OUTSIDE_PLOT))); + return; + } - if (plotCoords == null) { - player.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.CANNOT_TELEPORT_OUTSIDE_PLOT))); - return true; - } + double[] plotCoordinates = plotCoordsFuture.get(); - // Get Highest Y - int highestY = 0; - Location block = new Location(playerWorld, plotCoords.get()[0], 0, plotCoords.get()[1]); - for (int i = 1; i < 256; i++) { - block.add(0, 1, 0); - if (!block.getBlock().isEmpty()) { - highestY = i; - } - } - if (highestY < PlotWorld.MIN_WORLD_HEIGHT) { - highestY = PlotWorld.MIN_WORLD_HEIGHT; - } + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + int highestY = getHighestY(playerWorld, plotCoordinates); - player.teleport(new Location(playerWorld, plotCoords.get()[0], highestY + 1, plotCoords.get()[1], player.getLocation().getYaw(), player.getLocation().getPitch())); + player.teleport(new Location(playerWorld, plotCoordinates[0], highestY + 1f, plotCoordinates[1], player.getLocation().getYaw(), player.getLocation().getPitch())); - DecimalFormat df = new DecimalFormat("##.#####"); - df.setRoundingMode(RoundingMode.FLOOR); - player.sendMessage(Utils.ChatUtils.getInfoFormat(langUtil.get(sender, LangPaths.Message.Info.TELEPORTING_TPLL, df.format(lat), df.format(lon)))); + DecimalFormat df = new DecimalFormat("##.#####"); + df.setRoundingMode(RoundingMode.FLOOR); + player.sendMessage(Utils.ChatUtils.getInfoFormat(langUtil.get(sender, LangPaths.Message.Info.TELEPORTING_TPLL, df.format(lat), df.format(lon)))); + }); + } catch (IOException | OutOfProjectionBoundsException ex) { + PlotSystem.getPlugin().getComponentLogger().error(text("A coordinate conversion error occurred!"), ex); + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); + } catch (InterruptedException ex) { + Thread.currentThread().interrupt(); + sendInfo(sender); + } catch (ExecutionException ex) { + sendInfo(sender); + } + }); + return true; + } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - } catch (IOException | OutOfProjectionBoundsException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A coordinate conversion error occurred!"), ex); - player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - } catch (InterruptedException | ExecutionException ex) { - sendInfo(sender); + private static int getHighestY(World playerWorld, double[] plotCoordinates) { + int highestY = 0; + Location block = new Location(playerWorld, plotCoordinates[0], 0, plotCoordinates[1]); + for (int i = 1; i < 256; i++) { + block.add(0, 1, 0); + if (!block.getBlock().isEmpty()) { + highestY = i; + } } - return true; + if (highestY < PlotWorld.MIN_WORLD_HEIGHT) { + highestY = PlotWorld.MIN_WORLD_HEIGHT; + } + return highestY; } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tutorial.java b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tutorial.java index a98b526f2..595ce97b5 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tutorial.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/CMD_Tutorial.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands; @@ -47,29 +23,30 @@ public class CMD_Tutorial extends BaseCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { - if (sender.hasPermission(getPermission())) { - if (getPlayer(sender) != null) { - if (PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.TUTORIAL_ENABLE)) { - if (args.length == 0) { - Tutorial tutorial = AbstractTutorial.getActiveTutorial(getPlayer(sender).getUniqueId()); - if (tutorial != null) { - new TutorialStagesMenu(tutorial.getPlayer(), tutorial.getId()); - } else { - new TutorialsMenu(getPlayer(sender)); - } - } else if (args.length == 1 && AlpsUtils.tryParseInt(args[0]) != null) { - int tutorialId = Integer.parseInt(args[0]); - if (TutorialCategory.byId(tutorialId) == null) return true; - AbstractTutorial.loadTutorial(getPlayer(sender), tutorialId); - } - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.TUTORIAL_DISABLED))); - } + if (!sender.hasPermission(getPermission())) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + return true; + } + if (getPlayer(sender) == null) { + Bukkit.getConsoleSender().sendMessage(Component.text("This command can only be used as a player!", NamedTextColor.RED)); + return true; + } + if (!PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.TUTORIAL_ENABLE)) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.TUTORIAL_DISABLED))); + return true; + } + + if (args.length == 0) { + Tutorial tutorial = AbstractTutorial.getActiveTutorial(getPlayer(sender).getUniqueId()); + if (tutorial != null) { + new TutorialStagesMenu(tutorial.getPlayer(), tutorial.getId()); } else { - Bukkit.getConsoleSender().sendMessage(Component.text("This command can only be used as a player!", NamedTextColor.RED)); + new TutorialsMenu(getPlayer(sender)); } - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + } else if (args.length == 1 && AlpsUtils.tryParseInt(args[0]) != null) { + int tutorialId = Integer.parseInt(args[0]); + if (TutorialCategory.byId(tutorialId) == null) return true; + AbstractTutorial.loadTutorial(getPlayer(sender), tutorialId); } return true; } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/CommandManager.java b/src/main/java/com/alpsbte/plotsystem/commands/CommandManager.java index 373e55c15..95b4634ff 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/CommandManager.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/CommandManager.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands; import com.alpsbte.plotsystem.PlotSystem; @@ -30,9 +6,9 @@ import com.alpsbte.plotsystem.commands.admin.CMD_SetLeaderboard; import com.alpsbte.plotsystem.commands.admin.setup.CMD_Setup; import com.alpsbte.plotsystem.commands.plot.CMD_Plot; +import com.alpsbte.plotsystem.commands.review.CMD_EditFeedback; import com.alpsbte.plotsystem.commands.review.CMD_EditPlot; import com.alpsbte.plotsystem.commands.review.CMD_Review; -import com.alpsbte.plotsystem.commands.review.CMD_EditFeedback; import com.alpsbte.plotsystem.commands.review.CMD_UndoReview; import java.util.ArrayList; @@ -40,32 +16,33 @@ import java.util.Objects; public class CommandManager { - - public final List baseCommands = new ArrayList() {{ + public final List baseCommands = new ArrayList<>(); + + public CommandManager() { // Default Commands - add(new CMD_CancelChat()); - add(new CMD_Companion()); - add(new CMD_Plots()); - add(new CMD_Tpll()); + baseCommands.add(new CMD_CancelChat()); + baseCommands.add(new CMD_Companion()); + baseCommands.add(new CMD_Plots()); + baseCommands.add(new CMD_Tpll()); // Plot Commands - add(new CMD_Plot()); + baseCommands.add(new CMD_Plot()); // Review Commands - add(new CMD_Review()); - add(new CMD_UndoReview()); - add(new CMD_EditFeedback()); - add(new CMD_EditPlot()); + baseCommands.add(new CMD_Review()); + baseCommands.add(new CMD_UndoReview()); + baseCommands.add(new CMD_EditFeedback()); + baseCommands.add(new CMD_EditPlot()); // Admin Commands - add(new CMD_DeletePlot()); - add(new CMD_SetLeaderboard()); - add(new CMD_PReload()); + baseCommands.add(new CMD_DeletePlot()); + baseCommands.add(new CMD_SetLeaderboard()); + baseCommands.add(new CMD_PReload()); // Admin Setup Commands - add(new CMD_Setup()); - add(new CMD_Tutorial()); - }}; + baseCommands.add(new CMD_Setup()); + baseCommands.add(new CMD_Tutorial()); + } public void init() { for (BaseCommand baseCmd : baseCommands) { @@ -74,8 +51,4 @@ public void init() { } } } - - public List getBaseCommands() { - return baseCommands; - } } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/ICommand.java b/src/main/java/com/alpsbte/plotsystem/commands/ICommand.java index 391484098..803126079 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/ICommand.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/ICommand.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands; import org.bukkit.command.CommandSender; diff --git a/src/main/java/com/alpsbte/plotsystem/commands/SubCommand.java b/src/main/java/com/alpsbte/plotsystem/commands/SubCommand.java index 4250fc4e5..ae6fbd9a8 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/SubCommand.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/SubCommand.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands; import com.alpsbte.plotsystem.utils.io.LangUtil; diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_DeletePlot.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_DeletePlot.java index 2f460d6dc..35775b98a 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_DeletePlot.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_DeletePlot.java @@ -1,38 +1,19 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.admin; import com.alpsbte.alpslib.utils.AlpsUtils; +import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; import com.alpsbte.plotsystem.utils.Utils; +import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; +import java.util.concurrent.CompletableFuture; + public class CMD_DeletePlot extends BaseCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { @@ -41,22 +22,33 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @N return true; } - if (!(args.length > 0 && AlpsUtils.tryParseInt(args[0]) != null)) { + if (args.length == 0) { sendInfo(sender); return true; } - int plotID = Integer.parseInt(args[0]); - if (!PlotUtils.plotExists(plotID)) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find plot with ID #" + plotID + "!")); + Integer plotID = AlpsUtils.tryParseInt(args[0]); + + if (plotID == null) { + sendInfo(sender); return true; } - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Deleting plot...")); - if (PlotUtils.Actions.deletePlot(new Plot(plotID))) { - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully deleted plot with the ID §6#" + plotID + "§a!")); - if (getPlayer(sender) != null) getPlayer(sender).playSound(getPlayer(sender).getLocation(), Utils.SoundUtils.DONE_SOUND, 1f, 1f); - } else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An unexpected error has occurred!")); + CompletableFuture.runAsync(() -> { + Plot plot = DataProvider.PLOT.getPlotById(plotID); + if (plot == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find plot with ID #" + plotID + "!")); + return; + } + + sender.sendMessage(Utils.ChatUtils.getInfoFormat("Deleting plot...")); + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + if (PlotUtils.Actions.deletePlot(plot)) { + sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully deleted plot with the ID §6#" + plotID + "§a!")); + if (getPlayer(sender) != null) getPlayer(sender).playSound(getPlayer(sender).getLocation(), Utils.SoundUtils.DONE_SOUND, 1f, 1f); + } else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An unexpected error has occurred!")); + }); + }); return true; } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_PReload.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_PReload.java index 4c09f0b17..409a60e4c 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_PReload.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_PReload.java @@ -1,36 +1,12 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.admin; import com.alpsbte.alpslib.hologram.DecentHologramDisplay; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; import com.alpsbte.plotsystem.core.holograms.HologramConfiguration; import com.alpsbte.plotsystem.core.holograms.HologramRegister; import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.io.LangUtil; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -41,24 +17,25 @@ public class CMD_PReload extends BaseCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { + PlotSystem plugin = PlotSystem.getPlugin(); if (!sender.hasPermission(getPermission())) { sender.sendMessage(Utils.ChatUtils.getAlertFormat("You don't have permission to use this command!")); return true; } try { - PlotSystem.getPlugin().reloadConfig(); + plugin.reloadConfig(); + LangUtil.getInstance().reloadFiles(); sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully reloaded config!")); DecentHologramDisplay.activeDisplays.forEach(leaderboard -> leaderboard.setLocation(HologramRegister .getLocation((HologramConfiguration) leaderboard))); HologramRegister.reload(); sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully reloaded leaderboards!")); - - DatabaseConnection.InitializeDatabase(); + plugin.initDatabase(); } catch (Exception ex) { sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + plugin.getComponentLogger().error(text("An error occurred!"), ex); } return true; } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_SetLeaderboard.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_SetLeaderboard.java index a35a2cfc0..f2d18813b 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_SetLeaderboard.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/admin/CMD_SetLeaderboard.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.admin; import com.alpsbte.alpslib.hologram.DecentHologramDisplay; diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup.java index 7d49fce12..05b64e36d 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.admin.setup; import com.alpsbte.plotsystem.commands.BaseCommand; @@ -33,11 +9,11 @@ public class CMD_Setup extends BaseCommand { public CMD_Setup() { registerSubCommand(new CMD_Setup_BuildTeam(this)); - registerSubCommand(new CMD_Setup_FTP(this)); registerSubCommand(new CMD_Setup_Server(this)); registerSubCommand(new CMD_Setup_Country(this)); registerSubCommand(new CMD_Setup_City(this)); registerSubCommand(new CMD_Setup_Difficulty(this)); + registerSubCommand(new CMD_Setup_ReviewCriteria(this)); } @Override @@ -68,16 +44,4 @@ public String[] getParameter() { public String getPermission() { return null; } - - public static String appendArgs(String[] args, int startIndex) { - StringBuilder name = new StringBuilder(); - for (int i = startIndex; i < args.length; i++) { - name.append(args[i]); - // Add space between words - if (i != args.length - 1) { - name.append(" "); - } - } - return name.toString(); - } } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_BuildTeam.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_BuildTeam.java index ace57dde0..d80acb731 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_BuildTeam.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_BuildTeam.java @@ -1,44 +1,23 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.admin.setup; import com.alpsbte.alpslib.utils.AlpsUtils; -import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.BuildTeam; import com.alpsbte.plotsystem.core.system.Builder; -import com.alpsbte.plotsystem.core.system.Country; +import com.alpsbte.plotsystem.core.system.review.ToggleCriteria; import com.alpsbte.plotsystem.utils.Utils; import org.bukkit.command.CommandSender; -import java.sql.SQLException; import java.util.List; +import java.util.Optional; import java.util.StringJoiner; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; public class CMD_Setup_BuildTeam extends SubCommand { public CMD_Setup_BuildTeam(BaseCommand baseCommand) { @@ -51,10 +30,11 @@ private void register() { registerSubCommand(new CMD_Setup_BuildTeam_Add(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_BuildTeam_Remove(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_BuildTeam_SetName(getBaseCommand(), this)); - registerSubCommand(new CMD_Setup_BuildTeam_AddCountry(getBaseCommand(), this)); - registerSubCommand(new CMD_Setup_BuildTeam_RemoveCountry(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_BuildTeam_AddReviewer(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_BuildTeam_RemoveReviewer(getBaseCommand(), this)); + registerSubCommand(new CMD_Setup_BuildTeam_Criteria(getBaseCommand(), this)); + registerSubCommand(new CMD_Setup_BuildTeam_AssignCriteria(getBaseCommand(), this)); + registerSubCommand(new CMD_Setup_BuildTeam_RemoveCriteria(getBaseCommand(), this)); } @Override @@ -90,27 +70,25 @@ public CMD_Setup_BuildTeam_List(BaseCommand baseCommand, SubCommand subCommand) @Override public void onCommand(CommandSender sender, String[] args) { - List buildTeams = BuildTeam.getBuildTeams(); + List buildTeams = DataProvider.BUILD_TEAM.getBuildTeams(); if (buildTeams.isEmpty()) { sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently no build teams registered in the database!")); return; } sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently " + buildTeams.size() + " build teams registered in the database:")); - sender.sendMessage("§8--------------------------"); + sender.sendMessage(text("--------------------------", DARK_GRAY)); for (BuildTeam b : buildTeams) { - try { - StringJoiner countriesAsString = new StringJoiner(", "); - StringJoiner reviewersAsString = new StringJoiner(", "); - b.getCountries().forEach(c -> countriesAsString.add(String.valueOf(c.getID()))); - b.getReviewers().forEach(r -> {try {reviewersAsString.add(r.getName());} catch (SQLException ex) {PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex);}}); - sender.sendMessage(" §6> §b" + b.getID() + " (" + b.getName() + ") §f- Country IDs: " + (countriesAsString.length() == 0 ? "No Countries" : countriesAsString) + " - Reviewers: " + (reviewersAsString.length() == 0 ? "No Reviewers" : reviewersAsString)); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + StringJoiner citiesAsString = new StringJoiner(", "); + StringJoiner reviewersAsString = new StringJoiner(", "); + b.getCityProjects().forEach(c -> citiesAsString.add(c.getId())); + b.getReviewers().forEach(r -> reviewersAsString.add(r.getName())); + sender.sendMessage(text(" » ", DARK_GRAY) + .append(text(b.getId() + " (" + b.getName() + ") ", AQUA)) + .append(text("- City Project IDs: " + (citiesAsString.length() == 0 ? "No City Projects" : citiesAsString) + + " - Reviewers: " + (reviewersAsString.length() == 0 ? "No Reviewers" : reviewersAsString), WHITE))); } - sender.sendMessage("§8--------------------------"); + sender.sendMessage(text("--------------------------", DARK_GRAY)); } @Override @@ -142,19 +120,16 @@ public CMD_Setup_BuildTeam_Add(BaseCommand baseCommand, SubCommand subCommand) { @Override public void onCommand(CommandSender sender, String[] args) { if (args.length <= 1) {sendInfo(sender); return;} - if (args[1].length() > 45) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build team name cannot be longer than 45 characters!")); + + String name = args[1]; + if (name.length() > 255) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build team name cannot be longer than 255 characters!")); return; } - try { - String name = CMD_Setup.appendArgs(args, 1); - BuildTeam.addBuildTeam(name); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added build team with name '" + name + "'!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + boolean successful = DataProvider.BUILD_TEAM.addBuildTeam(name); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added build team with name '" + name + "'!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override @@ -185,21 +160,23 @@ public CMD_Setup_BuildTeam_Remove(BaseCommand baseCommand, SubCommand subCommand @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 1 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} + if (args.length <= 1) {sendInfo(sender); return;} + + Integer input = AlpsUtils.tryParseInt(args[1]); + if (input == null) {sendInfo(sender); return;} + + Optional buildTeam = DataProvider.BUILD_TEAM.getBuildTeam(input); // Check if build team exists - try { - if (BuildTeam.getBuildTeams().stream().noneMatch(b -> b.getID() == Integer.parseInt(args[1]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any build team with ID " + args[1] + "!")); - sendInfo(sender); - return; - } - BuildTeam.removeBuildTeam(Integer.parseInt(args[1])); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed build team with ID " + args[1] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + if (buildTeam.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any build team with ID " + args[1] + "!")); + sendInfo(sender); + return; } + + boolean successful = DataProvider.BUILD_TEAM.removeBuildTeam(buildTeam.get().getId()); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed build team with ID " + args[1] + "!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override @@ -230,23 +207,28 @@ public CMD_Setup_BuildTeam_SetName(BaseCommand baseCommand, SubCommand subComman @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} - - // Check if build team exits - try { - if (BuildTeam.getBuildTeams().stream().noneMatch(b -> b.getID() == Integer.parseInt(args[1]))) return; - String name = CMD_Setup.appendArgs(args, 2); - if (name.length() > 45) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build team name cannot be longer than 45 characters!")); - return; - } - - BuildTeam.setBuildTeamName(Integer.parseInt(args[1]), name); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully changed name of build team with ID " + args[1] + " to '" + name + "'!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + if (args.length <= 2) {sendInfo(sender); return;} + + Integer input = AlpsUtils.tryParseInt(args[1]); + if (input == null) {sendInfo(sender); return;} + + Optional buildTeam = DataProvider.BUILD_TEAM.getBuildTeam(input); + + // Check if build team exists + if (buildTeam.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build team could not be found!")); + return; + } + + String name = args[2]; + if (name.length() > 255) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build team name cannot be longer than 255 characters!")); + return; } + + boolean successful = buildTeam.get().setName(name); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully changed name of build team with ID " + args[1] + " to '" + name + "'!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override @@ -270,37 +252,38 @@ public String getPermission() { } } - public static class CMD_Setup_BuildTeam_AddCountry extends SubCommand { - public CMD_Setup_BuildTeam_AddCountry(BaseCommand baseCommand, SubCommand subCommand) { + public static class CMD_Setup_BuildTeam_AddReviewer extends SubCommand { + public CMD_Setup_BuildTeam_AddReviewer(BaseCommand baseCommand, SubCommand subCommand) { super(baseCommand, subCommand); } @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null || AlpsUtils.tryParseInt(args[2]) == null) { - sendInfo(sender); + if (args.length <= 2) {sendInfo(sender); return;} + + Integer input = AlpsUtils.tryParseInt(args[1]); + if (input == null) {sendInfo(sender); return;} + + // Check if build team exists + Optional buildTeam = DataProvider.BUILD_TEAM.getBuildTeam(input); + if (buildTeam.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build team could not be found!")); return; } - // Check if build team and country exists - try { - if (BuildTeam.getBuildTeams().stream().noneMatch(b -> b.getID() == Integer.parseInt(args[1]))) return; - if (Country.getCountries().stream().noneMatch(c -> c.getID() == Integer.parseInt(args[2]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Country could not be found or is already added to the build team!")); - return; - } - Country country = new Country(Integer.parseInt(args[2])); - BuildTeam.addCountry(Integer.parseInt(args[1]), country.getID()); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added country '" + country.getName() + "' to build team with ID " + args[1] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + Builder builder = Builder.byName(args[2]); + if (builder == null || DataProvider.BUILD_TEAM.getBuildTeamsByReviewer(builder.getUUID()).stream().anyMatch(b -> b.getId() == buildTeam.get().getId())) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Player could not be found or is already reviewer for this build team!")); + return; } + boolean successful = buildTeam.get().addReviewer(builder); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added '" + builder.getName() + "' as reviewer to build team with ID " + buildTeam.get().getName() + "!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override public String[] getNames() { - return new String[]{"addcountry"}; + return new String[]{"addreviewer"}; } @Override @@ -310,46 +293,49 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"BuildTeam-ID", "Country-ID"}; + return new String[]{"BuildTeam-ID", "Name"}; } @Override public String getPermission() { - return "plotsystem.admin.pss.buildteam.addcountry"; + return "plotsystem.admin.pss.buildteam.addreviewer"; } } - public static class CMD_Setup_BuildTeam_RemoveCountry extends SubCommand { - public CMD_Setup_BuildTeam_RemoveCountry(BaseCommand baseCommand, SubCommand subCommand) { + public static class CMD_Setup_BuildTeam_RemoveReviewer extends SubCommand { + public CMD_Setup_BuildTeam_RemoveReviewer(BaseCommand baseCommand, SubCommand subCommand) { super(baseCommand, subCommand); } @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null || AlpsUtils.tryParseInt(args[2]) == null) { - sendInfo(sender); + if (args.length <= 2) {sendInfo(sender); return;} + + Integer input = AlpsUtils.tryParseInt(args[1]); + if (input == null) {sendInfo(sender); return;} + + // Check if build team exists + Optional buildTeam = DataProvider.BUILD_TEAM.getBuildTeam(input); + + if (buildTeam.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build team could not be found!")); return; } - // Check if build team and country exists - try { - if (BuildTeam.getBuildTeams().stream().noneMatch(b -> b.getID() == Integer.parseInt(args[1]))) return; - if (Country.getCountries().stream().noneMatch(c -> c.getID() == Integer.parseInt(args[2]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Country could not be found or is not added to the build team!")); - return; - } - Country country = new Country(Integer.parseInt(args[2])); - BuildTeam.removeCountry(Integer.parseInt(args[1]), country.getID()); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed country '" + country.getName() + "' from build team with ID " + args[1] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + Builder builder = Builder.byName(args[2]); + if (builder == null || DataProvider.BUILD_TEAM.getBuildTeamsByReviewer(builder.getUUID()).stream().noneMatch(b -> b.getId() == buildTeam.get().getId())) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Player could not be found or is not a reviewer for this build team!")); + return; } + + boolean successful = buildTeam.get().removeReviewer(builder.getUUID().toString()); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed '" + builder.getName() + "' as reviewer from build team with ID " + args[1] + "!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override public String[] getNames() { - return new String[]{"removecountry"}; + return new String[]{"removereviewer"}; } @Override @@ -359,46 +345,45 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"BuildTeam-ID", "Country-ID"}; + return new String[]{"BuildTeam-ID", "Name"}; } @Override public String getPermission() { - return "plotsystem.admin.pss.buildteam.removecountry"; + return "plotsystem.admin.pss.buildteam.removereviewer"; } } - public static class CMD_Setup_BuildTeam_AddReviewer extends SubCommand { - public CMD_Setup_BuildTeam_AddReviewer(BaseCommand baseCommand, SubCommand subCommand) { + public static class CMD_Setup_BuildTeam_Criteria extends SubCommand { + public CMD_Setup_BuildTeam_Criteria(BaseCommand baseCommand, SubCommand subCommand) { super(baseCommand, subCommand); } @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null) { - sendInfo(sender); + if (args.length <= 1) {sendInfo(sender); return;} + + Integer input = AlpsUtils.tryParseInt(args[1]); + if (input == null) {sendInfo(sender); return;} + + List criteria = DataProvider.REVIEW.getBuildTeamToggleCriteria(input); + if (criteria.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently no toggle criteria assigned to the build team " + args[1] + " in the database!")); return; } - // Check if build team exits - try { - if (BuildTeam.getBuildTeams().stream().noneMatch(b -> b.getID() == Integer.parseInt(args[1]))) return; - Builder builder = Builder.getBuilderByName(args[2]); - if (builder == null || BuildTeam.getBuildTeamsByReviewer(builder.getUUID()).stream().anyMatch(b -> b.getID() == Integer.parseInt(args[1]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Player could not be found or is already reviewer for this build team!")); - return; - } - BuildTeam.addReviewer(Integer.parseInt(args[1]), builder.getUUID().toString()); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added '" + builder.getName() + "' as reviewer to build team with ID " + args[1] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently " + criteria.size() + " toggle criteria associated to this build team:")); + sender.sendMessage(text("--------------------------", DARK_GRAY)); + for (ToggleCriteria c : criteria) { + sender.sendMessage(text(" » ", DARK_GRAY) + .append(text(c.criteriaName() + " (" + (c.isOptional() ? "optional" : "required") + ")"))); } + sender.sendMessage(text("--------------------------", DARK_GRAY)); } @Override public String[] getNames() { - return new String[]{"addreviewer"}; + return new String[]{"criteria"}; } @Override @@ -408,44 +393,49 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"BuildTeam-ID", "Name"}; + return new String[]{"Build-Team-ID"}; } @Override public String getPermission() { - return "plotsystem.admin.pss.buildteam.addreviewer"; + return "plotsystem.admin.pss.buildteam.criteria"; } } - public static class CMD_Setup_BuildTeam_RemoveReviewer extends SubCommand { - public CMD_Setup_BuildTeam_RemoveReviewer(BaseCommand baseCommand, SubCommand subCommand) { + public static class CMD_Setup_BuildTeam_AssignCriteria extends SubCommand { + public CMD_Setup_BuildTeam_AssignCriteria(BaseCommand baseCommand, SubCommand subCommand) { super(baseCommand, subCommand); } @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} - - // Check if build team exits - try { - if (BuildTeam.getBuildTeams().stream().noneMatch(b -> b.getID() == Integer.parseInt(args[1]))) return; - - Builder builder = Builder.getBuilderByName(args[2]); - if (builder == null || BuildTeam.getBuildTeamsByReviewer(builder.getUUID()).stream().noneMatch(b -> b.getID() == Integer.parseInt(args[1]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Player could not be found or is not a reviewer for this build team!")); - return; - } - BuildTeam.removeReviewer(Integer.parseInt(args[1]), builder.getUUID().toString()); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed '" + builder.getName() + "' as reviewer from build team with ID " + args[1] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + if (args.length <= 2) {sendInfo(sender); return;} + + Integer input = AlpsUtils.tryParseInt(args[1]); + if (input == null) {sendInfo(sender); return;} + + // Check if build team exists + Optional buildTeam = DataProvider.BUILD_TEAM.getBuildTeam(input); + if (buildTeam.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build team could not be found!")); + return; + } + + // Check if toggle criteria exists + Optional criteria = DataProvider.REVIEW.getToggleCriteria(args[2]); + if (criteria.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Toggle criteria could not be found!")); + return; } + + boolean successful = DataProvider.REVIEW.assignBuildTeamToggleCriteria(buildTeam.get().getId(), criteria.get()); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully assigned criteria '" + criteria.get().criteriaName() + "' to build team with ID '" + args[1] + "'!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override public String[] getNames() { - return new String[]{"removereviewer"}; + return new String[]{"assigncriteria"}; } @Override @@ -455,12 +445,65 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"BuildTeam-ID", "Name"}; + return new String[]{"Build-Team-ID", "Criteria-Name"}; } @Override public String getPermission() { - return "plotsystem.admin.pss.buildteam.removereviewer"; + return "plotsystem.admin.pss.buildteam.assigncriteria"; + } + } + + public static class CMD_Setup_BuildTeam_RemoveCriteria extends SubCommand { + public CMD_Setup_BuildTeam_RemoveCriteria(BaseCommand baseCommand, SubCommand subCommand) { + super(baseCommand, subCommand); + } + + @Override + public void onCommand(CommandSender sender, String[] args) { + if (args.length <= 2) {sendInfo(sender); return;} + + Integer input = AlpsUtils.tryParseInt(args[1]); + if (input == null) {sendInfo(sender); return;} + + // Check if build team exists + Optional buildTeam = DataProvider.BUILD_TEAM.getBuildTeam(input); + if (buildTeam.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build team could not be found!")); + return; + } + + // Check if toggle criteria exists + Optional criteria = DataProvider.REVIEW.getBuildTeamToggleCriteria(buildTeam.get().getId()) + .stream().filter(t -> t.criteriaName().equalsIgnoreCase(args[2])).findFirst(); + if (criteria.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Toggle criteria could not be found or is not assigned!")); + return; + } + + boolean successful = DataProvider.REVIEW.removeBuildTeamToggleCriteria(buildTeam.get().getId(), criteria.get()); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed criteria '" + criteria.get().criteriaName() + "' from build team with ID '" + args[1] + "'!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); + } + + @Override + public String[] getNames() { + return new String[]{"removecriteria"}; + } + + @Override + public String getDescription() { + return null; + } + + @Override + public String[] getParameter() { + return new String[]{"Build-Team-ID", "Criteria-Name"}; + } + + @Override + public String getPermission() { + return "plotsystem.admin.pss.buildteam.removecriteria"; } } } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_City.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_City.java index 41d925de9..34e6b5b1c 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_City.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_City.java @@ -1,42 +1,22 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.admin.setup; import com.alpsbte.alpslib.utils.AlpsUtils; -import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.CityProject; import com.alpsbte.plotsystem.core.system.Country; import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.io.LangPaths; import org.bukkit.command.CommandSender; -import java.sql.SQLException; import java.util.List; +import java.util.Optional; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; public class CMD_Setup_City extends SubCommand { @@ -49,8 +29,8 @@ private void register() { registerSubCommand(new CMD_Setup_City_List(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_City_Add(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_City_Remove(getBaseCommand(), this)); - registerSubCommand(new CMD_Setup_City_SetName(getBaseCommand(), this)); - registerSubCommand(new CMD_Setup_City_SetDescription(getBaseCommand(), this)); + registerSubCommand(new CMD_Setup_City_SetServer(getBaseCommand(), this)); + registerSubCommand(new CMD_Setup_City_SetBuildTeam(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_City_SetVisible(getBaseCommand(), this)); } @@ -87,23 +67,23 @@ public CMD_Setup_City_List(BaseCommand baseCommand, SubCommand subCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - List cities = CityProject.getCityProjects(false); + List cities = DataProvider.CITY_PROJECT.get(false); if (cities.isEmpty()) { sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently no City Projects registered in the database!")); return; } sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently " + cities.size() + " City Projects registered in the database:")); - sender.sendMessage("§8--------------------------"); + sender.sendMessage(text("--------------------------", DARK_GRAY)); for (CityProject c : cities) { - try { - sender.sendMessage(" §6> §b" + c.getID() + " (" + c.getName() + ") §f- Description: " + c.getDescription() + " - Country: " + c.getCountry().getName() + " - Visible: " + c.isVisible()); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + sender.sendMessage(text(" » ", DARK_GRAY) + .append(text(c.getId(), AQUA)) + .append(text(" - Country: " + c.getCountry().getCode() + + " - Server: " + c.getServerName() + + " - Build Team: " + c.getBuildTeam().getName() + + " - Visible: " + c.isVisible(), WHITE))); } - sender.sendMessage("§8--------------------------"); + sender.sendMessage(text("--------------------------", DARK_GRAY)); } @Override @@ -134,27 +114,47 @@ public CMD_Setup_City_Add(BaseCommand baseCommand, SubCommand subCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} + if (args.length <= 4) {sendInfo(sender); return;} - Country country = Country.getCountries().stream().filter(c -> c.getID() == Integer.parseInt(args[1])).findFirst().orElse(null); - if (country == null) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any country with ID " + args[1] + "!")); + String cityProjectId = args[1].toLowerCase(); + String countryCode = args[2]; + Optional country = DataProvider.COUNTRY.getCountryByCode(countryCode); + if (country.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any country with code " + countryCode + "!")); sender.sendMessage(Utils.ChatUtils.getAlertFormat("Type to see all countries!")); return; } - String name = CMD_Setup.appendArgs(args, 2); - if (name.length() > 45) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("City Project name cannot be longer than 45 characters!")); + String serverName = args[3]; + if (serverName.length() > 255) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Server name cannot be longer than 255 characters!")); + return; + } + // Check if server exists + if (!DataProvider.SERVER.serverExists(serverName)) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any server with Name " + serverName + "!")); + sendInfo(sender); + return; + } + + Integer buildTeamId = AlpsUtils.tryParseInt(args[4]); + if (buildTeamId == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build Team ID must be a number!")); + sendInfo(sender); + return; + } + if (DataProvider.BUILD_TEAM.getBuildTeam(buildTeamId).isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any build team with ID " + buildTeamId + "!")); + sendInfo(sender); return; } - try { - CityProject.addCityProject(country, name); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added City Project with name '" + name + "' in country with the ID " + args[1] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + boolean added = DataProvider.CITY_PROJECT.add(cityProjectId, buildTeamId, country.get().getCode(), serverName); + if (!added) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while adding City Project! Check console for any exceptions.")); + return; } + sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added City Project with Name '" + cityProjectId + "' under country with the code " + countryCode + "!")); + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Edit the " + LangPaths.Database.CITY_PROJECT + "." + cityProjectId + " language config setting, otherwise the name will be undefined!")); } @Override @@ -169,7 +169,7 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"Country-ID", "Name"}; + return new String[]{"City-Project-Name", "Country-Code", "Server-Name", "Build-Team-ID"}; } @Override @@ -185,21 +185,20 @@ public CMD_Setup_City_Remove(BaseCommand baseCommand, SubCommand subCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 1 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} + if (args.length <= 1) {sendInfo(sender); return;} + String cityProjectId = args[1]; // Check if City Project exists - try { - if (CityProject.getCityProjects(false).stream().noneMatch(c -> c.getID() == Integer.parseInt(args[1]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any City Project with ID " + args[1] + "!")); - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Type to see all City Projects!")); - return; - } - CityProject.removeCityProject(Integer.parseInt(args[1])); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed City Project with ID " + args[1] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + Optional cityProject = DataProvider.CITY_PROJECT.getById(cityProjectId); + if (cityProject.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any City Project with ID " + cityProjectId + "!")); + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Type to see all City Projects!")); + return; } + + boolean removed = DataProvider.CITY_PROJECT.remove(cityProjectId); + if (removed) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed City Project with ID " + cityProjectId + "!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while removing city project! Check console for any exceptions.")); } @Override @@ -223,37 +222,39 @@ public String getPermission() { } } - public static class CMD_Setup_City_SetName extends SubCommand { - public CMD_Setup_City_SetName(BaseCommand baseCommand, SubCommand subCommand) { + public static class CMD_Setup_City_SetServer extends SubCommand { + public CMD_Setup_City_SetServer(BaseCommand baseCommand, SubCommand subCommand) { super(baseCommand, subCommand); } @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} + if (args.length <= 2) {sendInfo(sender); return;} // Check if City Project exits - try { - if (CityProject.getCityProjects(false).stream().noneMatch(c -> c.getID() == Integer.parseInt(args[1]))) return; - - String name = CMD_Setup.appendArgs(args, 2); - if (name.length() > 45) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("City Project name cannot be longer than 45 characters!")); - return; - } + Optional cityProject = DataProvider.CITY_PROJECT.getById(args[1]); + if (cityProject.isEmpty()) return; - CityProject.setCityProjectName(Integer.parseInt(args[1]), name); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully changed name of City Project with ID " + args[1] + " to '" + name + "'!")); - - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + String serverName = args[2]; + if (serverName.length() > 255) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Server name cannot be longer than 255 characters!")); + return; + } + // Check if server exists + if (!DataProvider.SERVER.serverExists(serverName)) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any server with ID " + serverName + "!")); + sendInfo(sender); + return; } + + boolean successful = cityProject.get().setServer(serverName); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully changed server of City Project with ID " + args[1] + " to '" + serverName + "'!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while updating city project server! Check console for any exceptions.")); } @Override public String[] getNames() { - return new String[]{"setname"}; + return new String[]{"setserver"}; } @Override @@ -263,44 +264,41 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"City-ID", "Name"}; + return new String[]{"City-ID", "Server-Name"}; } @Override public String getPermission() { - return "plotsystem.admin.pss.city.setname"; + return "plotsystem.admin.pss.city.setserver"; } } - public static class CMD_Setup_City_SetDescription extends SubCommand { - public CMD_Setup_City_SetDescription(BaseCommand baseCommand, SubCommand subCommand) { + public static class CMD_Setup_City_SetBuildTeam extends SubCommand { + public CMD_Setup_City_SetBuildTeam(BaseCommand baseCommand, SubCommand subCommand) { super(baseCommand, subCommand); } @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} + if (args.length <= 2) {sendInfo(sender); return;} // Check if City Project exits - try { - if (CityProject.getCityProjects(false).stream().noneMatch(c -> c.getID() == Integer.parseInt(args[1]))) return; - - String description = CMD_Setup.appendArgs(args, 2); - if (description.length() > 255) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("City Project description cant be longer than 255 characters!")); - return; - } - CityProject.setCityProjectDescription(Integer.parseInt(args[1]), description); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set description of City Project with ID " + args[1] + " to '" + description + "'!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + Optional cityProject = DataProvider.CITY_PROJECT.getById(args[1]); + if (cityProject.isEmpty()) return; + + // Check if Build Team exists + int buildTeamId = Integer.parseInt(args[2]); + if (DataProvider.BUILD_TEAM.getBuildTeam(buildTeamId).isEmpty()) return; + + boolean successful = cityProject.get().setBuildTeam(buildTeamId); + + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set Build Team of City Project with ID " + args[1] + " to " + buildTeamId + "!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while updating city project build team! Check console for any exceptions.")); } @Override public String[] getNames() { - return new String[]{"setdescription"}; + return new String[]{"setbuildteam"}; } @Override @@ -310,12 +308,12 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"City-ID", "Description"}; + return new String[]{"City-ID", "Build-Team-ID"}; } @Override public String getPermission() { - return "plotsystem.admin.pss.city.setdescription"; + return "plotsystem.admin.pss.city.setbuildteam"; } } @@ -326,19 +324,19 @@ public CMD_Setup_City_SetVisible(BaseCommand baseCommand, SubCommand subCommand) @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} + if (args.length <= 2) {sendInfo(sender); return;} + String id = args[1]; // Check if City Project exits - try { - if (CityProject.getCityProjects(false).stream().noneMatch(c -> c.getID() == Integer.parseInt(args[1]))) return; - if (!args[2].equalsIgnoreCase("true") && !args[2].equalsIgnoreCase("false")) return; - - CityProject.setCityProjectVisibility(Integer.parseInt(args[1]), args[2].equalsIgnoreCase("true")); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set visibility of City Project with ID " + args[1] + " to " + args[2].toUpperCase() + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + Optional cityProject = DataProvider.CITY_PROJECT.getById(id); + if (cityProject.isEmpty()) return; + if (!args[2].equalsIgnoreCase("true") && !args[2].equalsIgnoreCase("false")) return; + + boolean isVisible = args[2].equalsIgnoreCase("true"); + boolean successful = cityProject.get().setVisible(isVisible); + + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set visibility of City Project with ID " + id + " to " + args[2].toUpperCase() + "!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while updating city project visibility! Check console for any exceptions.")); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Country.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Country.java index 20353fe42..bd23d1257 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Country.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Country.java @@ -1,43 +1,21 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.admin.setup; -import com.alpsbte.alpslib.utils.AlpsUtils; -import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Country; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Continent; +import com.alpsbte.plotsystem.utils.io.LangPaths; import org.bukkit.command.CommandSender; -import java.sql.SQLException; import java.util.Arrays; import java.util.List; +import java.util.Optional; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; public class CMD_Setup_Country extends SubCommand { @@ -50,7 +28,7 @@ private void register() { registerSubCommand(new CMD_Setup_Country_List(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_Country_Add(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_Country_Remove(getBaseCommand(), this)); - registerSubCommand(new CMD_Setup_Country_SetHead(getBaseCommand(), this)); + registerSubCommand(new CMD_Setup_Country_SetMaterial(getBaseCommand(), this)); } @Override @@ -86,22 +64,18 @@ public CMD_Setup_Country_List(BaseCommand baseCommand, SubCommand subCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - List countries = Country.getCountries(); + List countries = DataProvider.COUNTRY.getCountries(); if (countries.isEmpty()) { sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently no countries registered in the database!")); return; } sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently " + countries.size() + " Countries registered in the database:")); - sender.sendMessage("§8--------------------------"); + sender.sendMessage(text("--------------------------", DARK_GRAY)); for (Country c : countries) { - try { - sender.sendMessage(" §6> §b" + c.getID() + " (" + c.getName() + ") §f- Server: " + c.getServer().getID() + " (" + c.getServer().getName() + ")"); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + sender.sendMessage(text(" » ", DARK_GRAY).append(text(c.getCode(), AQUA))); } - sender.sendMessage("§8--------------------------"); + sender.sendMessage(text("--------------------------", DARK_GRAY)); } @Override @@ -132,27 +106,35 @@ public CMD_Setup_Country_Add(BaseCommand baseCommand, SubCommand subCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 3 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} + if (args.length <= 3) {sendInfo(sender); return;} - if (args[2].length() > 45) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Country name cannot be longer than 45 characters!")); + String code = args[1]; + if (code.length() > 2) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Country code cannot be longer than 2 characters!")); return; } Continent continent; try { - continent = Continent.valueOf(args[3].toUpperCase()); + continent = Continent.fromDatabase(args[2].toUpperCase()); + if (continent == null) { + continent = Continent.valueOf(args[2].toUpperCase()); + } } catch (IllegalArgumentException e) { sender.sendMessage(Utils.ChatUtils.getAlertFormat("Unknown continent! " + Arrays.toString(Continent.values()))); return; } - try { - Country.addCountry(Integer.parseInt(args[1]), args[2], continent); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added country!")); - } catch (SQLException ex) { + + String material = args[3]; + String customModelData = args.length > 4 ? args[4] : null; + + boolean successful = DataProvider.COUNTRY.addCountry(code, continent, material, customModelData); + if (!successful) { sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + return; } + sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added country!")); + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Edit the " + LangPaths.Database.COUNTRY + "." + code + " language config setting, otherwise name & id will be undefined!")); } @Override @@ -167,7 +149,7 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"Server-ID", "Name", "Continent"}; + return new String[]{"Code", "Continent", "Material", "CustomModelData?"}; } @Override @@ -183,21 +165,18 @@ public CMD_Setup_Country_Remove(BaseCommand baseCommand, SubCommand subCommand) @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 1 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} + if (args.length <= 1) {sendInfo(sender); return;} + String code = args[1]; // Check if country exists - try { - if (Country.getCountries().stream().noneMatch(c -> c.getID() == Integer.parseInt(args[1]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any country with ID " + args[1] + "!")); - sendInfo(sender); - return; - } - Country.removeCountry(Integer.parseInt(args[1])); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed country!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + if (DataProvider.COUNTRY.getCountryByCode(code).isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any country with code " + code + "!")); + sendInfo(sender); + return; } + boolean successful = DataProvider.COUNTRY.removeCountry(code); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed country!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override @@ -212,7 +191,7 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"Country-ID"}; + return new String[]{"Country-Code"}; } @Override @@ -221,36 +200,38 @@ public String getPermission() { } } - public static class CMD_Setup_Country_SetHead extends SubCommand { - public CMD_Setup_Country_SetHead(BaseCommand baseCommand, SubCommand subCommand) { + public static class CMD_Setup_Country_SetMaterial extends SubCommand { + public CMD_Setup_Country_SetMaterial(BaseCommand baseCommand, SubCommand subCommand) { super(baseCommand, subCommand); } @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null || AlpsUtils.tryParseInt(args[2]) == null) { + if (args.length <= 2) { sendInfo(sender); return; } + String code = args[1]; + String material = args[2]; + String customModelData = args.length > 3 ? args[3] : null; + // Check if country exists - try { - if (Country.getCountries().stream().noneMatch(c -> c.getID() == Integer.parseInt(args[1]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any country with name " + args[1] + "!")); - sendInfo(sender); - return; - } - Country.setHeadID(Integer.parseInt(args[1]), Integer.parseInt(args[2])); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set head id of country " + args[1] + " to " + args[2] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + Optional country = DataProvider.COUNTRY.getCountryByCode(code); + if (country.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any country with code " + code + "!")); + sendInfo(sender); + return; } + + boolean successful = country.get().setMaterialAndModelData(material, customModelData); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully updated country with code " + code + "! Material: " + material + " CustomModelData: " + (customModelData == null ? "NULL" : customModelData))); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override public String[] getNames() { - return new String[]{"sethead"}; + return new String[]{"setmaterial"}; } @Override @@ -260,12 +241,12 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"Country-ID", "Head-ID"}; + return new String[]{"Country-Code", "Material", "CustomModelData?"}; } @Override public String getPermission() { - return "plotsystem.admin.pss.country.sethead"; + return "plotsystem.admin.pss.country.setmaterial"; } } } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Difficulty.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Difficulty.java index b790aa701..a040cd3a3 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Difficulty.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Difficulty.java @@ -1,41 +1,20 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.admin.setup; import com.alpsbte.alpslib.utils.AlpsUtils; -import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Difficulty; import com.alpsbte.plotsystem.utils.Utils; import org.bukkit.command.CommandSender; -import java.sql.SQLException; import java.util.List; +import java.util.Optional; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; public class CMD_Setup_Difficulty extends SubCommand { @@ -83,13 +62,15 @@ public CMD_Setup_Difficulty_List(BaseCommand baseCommand, SubCommand subCommand) @Override public void onCommand(CommandSender sender, String[] args) { - List difficulties = Difficulty.getDifficulties(); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently " + difficulties.size() + " Difficulties registered in the database:")); - sender.sendMessage("§8--------------------------"); + List difficulties = DataProvider.DIFFICULTY.getDifficulties(); + sender.sendMessage(text("--------------------------", DARK_GRAY)); for (Difficulty d : difficulties) { - sender.sendMessage(" §6> §b" + d.getID() + " (" + d.getDifficulty().name() + ") §f- Multiplier: " + d.getMultiplier() + " - Score Requirement: " + d.getScoreRequirement()); + sender.sendMessage(text(" » ", DARK_GRAY) + .append(text(d.getID(), AQUA)) + .append(text("Multiplier: " + d.getMultiplier(), WHITE)) + .append(text(" - Score Requirement: " + d.getScoreRequirement(), WHITE))); } - sender.sendMessage("§8--------------------------"); + sender.sendMessage(text("--------------------------", DARK_GRAY)); } @Override @@ -120,20 +101,18 @@ public CMD_Setup_Difficulty_SetMultiplier(BaseCommand baseCommand, SubCommand su @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null || AlpsUtils.tryParseDouble(args[2]) == null) { + if (args.length <= 2 || AlpsUtils.tryParseDouble(args[2]) == null) { sendInfo(sender); return; } // Check if difficulty exists - try { - if (Difficulty.getDifficulties().stream().noneMatch(c -> c.getID() == Integer.parseInt(args[1]))) return; - Difficulty.setMultiplier(Integer.parseInt(args[1]), Double.parseDouble(args[2])); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set multiplier of Difficulty with ID " + args[1] + " to " + args[2] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + Optional difficulty = DataProvider.DIFFICULTY.getDifficultyById(args[1]); + if (difficulty.isEmpty()) return; + + boolean successful = difficulty.get().setMultiplier(Double.parseDouble(args[2])); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set multiplier of Difficulty with ID " + args[1] + " to " + args[2] + "!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override @@ -164,20 +143,18 @@ public CMD_Setup_Difficulty_SetRequirement(BaseCommand baseCommand, SubCommand s @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null || AlpsUtils.tryParseInt(args[2]) == null) { + if (args.length <= 2 || AlpsUtils.tryParseInt(args[2]) == null) { sendInfo(sender); return; } // Check if difficulty exists - try { - if (Difficulty.getDifficulties().stream().noneMatch(c -> c.getID() == Integer.parseInt(args[1]))) return; - Difficulty.setScoreRequirement(Integer.parseInt(args[1]), Integer.parseInt(args[2])); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set score requirement of Difficulty with ID " + args[1] + " to " + args[2] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + Optional difficulty = DataProvider.DIFFICULTY.getDifficultyById(args[1]); + if (difficulty.isEmpty()) return; + + boolean successful = difficulty.get().setScoreRequirement(Integer.parseInt(args[2])); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set score requirement of Difficulty with ID " + args[1] + " to " + args[2] + "!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_FTP.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_FTP.java deleted file mode 100644 index 8dfee205e..000000000 --- a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_FTP.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.commands.admin.setup; - -import com.alpsbte.alpslib.utils.AlpsUtils; -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.commands.BaseCommand; -import com.alpsbte.plotsystem.commands.SubCommand; -import com.alpsbte.plotsystem.core.system.FTPConfiguration; -import com.alpsbte.plotsystem.utils.Utils; -import org.bukkit.command.CommandSender; - -import java.sql.SQLException; -import java.util.List; - -import static net.kyori.adventure.text.Component.text; - -public class CMD_Setup_FTP extends SubCommand { - - public CMD_Setup_FTP(BaseCommand baseCommand) { - super(baseCommand); - register(); - } - - private void register() { - registerSubCommand(new CMD_Setup_FTP_List(getBaseCommand(), this)); - registerSubCommand(new CMD_Setup_FTP_Add(getBaseCommand(), this)); - registerSubCommand(new CMD_Setup_FTP_Remove(getBaseCommand(), this)); - registerSubCommand(new CMD_Setup_FTP_SetPath(getBaseCommand(), this)); - } - - @Override - public void onCommand(CommandSender sender, String[] args) { - sendInfo(sender); - } - - @Override - public String[] getNames() { - return new String[]{"ftp"}; - } - - @Override - public String getDescription() { - return "Configure SFTP/FTP configurations"; - } - - @Override - public String[] getParameter() { - return new String[0]; - } - - @Override - public String getPermission() { - return "plotsystem.admin.pss.ftp"; - } - - - public static class CMD_Setup_FTP_List extends SubCommand { - public CMD_Setup_FTP_List(BaseCommand baseCommand, SubCommand subCommand) { - super(baseCommand, subCommand); - } - - @Override - public void onCommand(CommandSender sender, String[] args) { - List ftpConfigs = FTPConfiguration.getFTPConfigurations(); - if (ftpConfigs.isEmpty()) { - sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently no FTP Configurations registered in the database!")); - return; - } - - sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently " + ftpConfigs.size() + " FTP-Configurations registered in the database:")); - sender.sendMessage("§8--------------------------"); - for (FTPConfiguration ftp : ftpConfigs) { - sender.sendMessage(" §6> §b" + ftp.getID() + " §f- Address: " + ftp.getAddress() + " - Port: " + ftp.getPort() + " - SFTP: " + (ftp.isSFTP() ? "True" : "False") + " - Username: " + getCensorString(ftp.getUsername().length()) + " - Password: " + getCensorString(ftp.getPassword().length()) + " - Path: " + ftp.getSchematicPath()); - } - sender.sendMessage("§8--------------------------"); - } - - @Override - public String[] getNames() { - return new String[]{"list"}; - } - - @Override - public String getDescription() { - return null; - } - - @Override - public String[] getParameter() { - return new String[0]; - } - - @Override - public String getPermission() { - return "plotsystem.admin.pss.ftp.list"; - } - - public String getCensorString(int length) { - StringBuilder output = new StringBuilder(); - for (int i = 0; i < length; i++) { - output.append("*"); - } - return output.toString(); - } - } - - public static class CMD_Setup_FTP_Add extends SubCommand { - public CMD_Setup_FTP_Add(BaseCommand baseCommand, SubCommand subCommand) { - super(baseCommand, subCommand); - } - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 5 || AlpsUtils.tryParseInt(args[2]) == null) {sendInfo(sender); return;} - if (!args[3].equalsIgnoreCase("true") && !args[3].equalsIgnoreCase("false")) return; - if (args[1].toLowerCase().startsWith("sftp:") || args[1].toLowerCase().startsWith("ftp:")) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Please remove the protocol URL from the host address!")); - return; - } - try { - FTPConfiguration.addFTPConfiguration(args[1], Integer.parseInt(args[2]), args[3].equalsIgnoreCase("true"), args[4], args[5]); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added FTP-Configuration!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - } - - @Override - public String[] getNames() { - return new String[]{"add"}; - } - - @Override - public String getDescription() { - return null; - } - - @Override - public String[] getParameter() { - return new String[]{"Address", "Port", "isSFTP (True/False)", "Username", "Password"}; - } - - @Override - public String getPermission() { - return "plotsystem.admin.pss.ftp.add"; - } - } - - public static class CMD_Setup_FTP_Remove extends SubCommand { - public CMD_Setup_FTP_Remove(BaseCommand baseCommand, SubCommand subCommand) { - super(baseCommand, subCommand); - } - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 1 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} - - // Check if ftp config exists - try { - if (FTPConfiguration.getFTPConfigurations().stream().noneMatch(f -> f.getID() == Integer.parseInt(args[1]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any FTP-Configurations with ID " + args[1] + "!")); - sendInfo(sender); - return; - } - FTPConfiguration.removeFTPConfiguration(Integer.parseInt(args[1])); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed FTP-Configuration!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - } - - @Override - public String[] getNames() { - return new String[]{"remove"}; - } - - @Override - public String getDescription() { - return null; - } - - @Override - public String[] getParameter() { - return new String[]{"FTP-ID"}; - } - - @Override - public String getPermission() { - return "plotsystem.admin.pss.ftp.remove"; - } - } - - public static class CMD_Setup_FTP_SetPath extends SubCommand { - public CMD_Setup_FTP_SetPath(BaseCommand baseCommand, SubCommand subCommand) { - super(baseCommand, subCommand); - } - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} - - // Check if ftp config exists - try { - if (FTPConfiguration.getFTPConfigurations().stream().noneMatch(f -> f.getID() == Integer.parseInt(args[1]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any FTP-Configurations with ID " + args[1] + "!")); - sendInfo(sender); - return; - } - FTPConfiguration.setSchematicPath(Integer.parseInt(args[1]), args[2]); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set path of FTP-Configuration " + args[1] + " to " + args[2] + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - } - - @Override - public String[] getNames() { - return new String[]{"setpath"}; - } - - @Override - public String getDescription() { - return null; - } - - @Override - public String[] getParameter() { - return new String[]{"FTP-ID", "Path"}; - } - - @Override - public String getPermission() { - return "plotsystem.admin.pss.ftp.setpath"; - } - } -} diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_ReviewCriteria.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_ReviewCriteria.java new file mode 100644 index 000000000..ef05a1f04 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_ReviewCriteria.java @@ -0,0 +1,233 @@ +package com.alpsbte.plotsystem.commands.admin.setup; + +import com.alpsbte.plotsystem.commands.BaseCommand; +import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.system.review.ToggleCriteria; +import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.io.LangPaths; +import org.bukkit.command.CommandSender; + +import java.util.List; +import java.util.Optional; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; + +public class CMD_Setup_ReviewCriteria extends SubCommand { + public CMD_Setup_ReviewCriteria(BaseCommand baseCommand) { + super(baseCommand); + registerSubCommand(new CMD_Setup_ReviewCriteria_List(getBaseCommand(), this)); + registerSubCommand(new CMD_Setup_ReviewCriteria_Add(getBaseCommand(), this)); + registerSubCommand(new CMD_Setup_ReviewCriteria_Remove(getBaseCommand(), this)); + registerSubCommand(new CMD_Setup_ReviewCriteria_SetOptional(getBaseCommand(), this)); + } + + @Override + public void onCommand(CommandSender sender, String[] args) { + sendInfo(sender); + } + + @Override + public String[] getNames() { + return new String[]{"review"}; + } + + @Override + public String getDescription() { + return "Configure review criteria"; + } + + @Override + public String[] getParameter() { + return new String[0]; + } + + @Override + public String getPermission() { + return "plotsystem.admin.pss.review"; + } + + public static class CMD_Setup_ReviewCriteria_List extends SubCommand { + + public CMD_Setup_ReviewCriteria_List(BaseCommand baseCommand, SubCommand subCommand) { + super(baseCommand, subCommand); + } + + @Override + public void onCommand(CommandSender sender, String[] args) { + List criteria = DataProvider.REVIEW.getAllToggleCriteria(); + if (criteria.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently no toggle criteria registered in the database!")); + return; + } + + sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently " + criteria.size() + " toggle criteria registered in the database:")); + sender.sendMessage(text("--------------------------", DARK_GRAY)); + for (ToggleCriteria c : criteria) { + sender.sendMessage(text(" » ", DARK_GRAY) + .append(text(c.criteriaName() + " (" + (c.isOptional() ? "optional" : "required") + ")"))); + } + sender.sendMessage(text("--------------------------", DARK_GRAY)); + } + + @Override + public String[] getNames() { + return new String[]{"list"}; + } + + @Override + public String getDescription() { + return null; + } + + @Override + public String[] getParameter() { + return new String[0]; + } + + @Override + public String getPermission() { + return "plotsystem.admin.pss.review.list"; + } + } + + public static class CMD_Setup_ReviewCriteria_Add extends SubCommand { + public CMD_Setup_ReviewCriteria_Add(BaseCommand baseCommand, SubCommand subCommand) { + super(baseCommand, subCommand); + } + + @Override + public void onCommand(CommandSender sender, String[] args) { + if (args.length <= 2) {sendInfo(sender); return;} + + String name = args[1]; + if (name.length() > 255) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Toggle criteria name cannot be longer than 255 characters!")); + return; + } + + boolean isOptional = args[2].equalsIgnoreCase("true"); + + boolean successful = DataProvider.REVIEW.addToggleCriteria(name, isOptional); + if (!successful) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); + return; + } + + sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added country!")); + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Edit the " + LangPaths.Database.TOGGLE_CRITERIA + "." + name + " language config setting, otherwise the name will be the ID of the Toggle Criteria & no description will be present!")); + sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added toggle criteria with name '" + name + "'!")); + } + + @Override + public String[] getNames() { + return new String[]{"add"}; + } + + @Override + public String getDescription() { + return null; + } + + @Override + public String[] getParameter() { + return new String[]{"Name","Is-Optional"}; + } + + @Override + public String getPermission() { + return "plotsystem.admin.pss.review.add"; + } + } + + public static class CMD_Setup_ReviewCriteria_Remove extends SubCommand { + public CMD_Setup_ReviewCriteria_Remove(BaseCommand baseCommand, SubCommand subCommand) { + super(baseCommand, subCommand); + } + + @Override + public void onCommand(CommandSender sender, String[] args) { + if (args.length <= 1) {sendInfo(sender); return;} + String name = args[1]; + + // Check if criteria exists + Optional criteria = DataProvider.REVIEW.getToggleCriteria(name); + if (criteria.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any toggle criteria with name " + name + "!")); + sendInfo(sender); + return; + } + + boolean successful = DataProvider.REVIEW.removeToggleCriteria(criteria.get().criteriaName()); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed toggle criteria with name " + name + "!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); + } + + @Override + public String[] getNames() { + return new String[]{"remove"}; + } + + @Override + public String getDescription() { + return null; + } + + @Override + public String[] getParameter() { + return new String[]{"Name"}; + } + + @Override + public String getPermission() { + return "plotsystem.admin.pss.review.remove"; + } + } + + public static class CMD_Setup_ReviewCriteria_SetOptional extends SubCommand { + public CMD_Setup_ReviewCriteria_SetOptional(BaseCommand baseCommand, SubCommand subCommand) { + super(baseCommand, subCommand); + } + + @Override + public void onCommand(CommandSender sender, String[] args) { + if (args.length <= 2) {sendInfo(sender); return;} + String name = args[1]; + + // Check if criteria exits + Optional criteria = DataProvider.REVIEW.getToggleCriteria(name); + if (criteria.isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Toggle criteria could not be found!")); + return; + } + + + boolean isOptional = args[2].equalsIgnoreCase("true"); + + boolean successful = DataProvider.REVIEW.setToggleCriteriaOptional(name, isOptional); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully changed optionality of toggle criteria with name " + name + " to '" + isOptional + "'!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); + } + + @Override + public String[] getNames() { + return new String[]{"setoptional"}; + } + + @Override + public String getDescription() { + return null; + } + + @Override + public String[] getParameter() { + return new String[]{"Name", "Is-Optional"}; + } + + @Override + public String getPermission() { + return "plotsystem.admin.pss.buildteam.setoptional"; + } + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Server.java b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Server.java index 16cfb6bb3..f80821133 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Server.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/admin/setup/CMD_Setup_Server.java @@ -1,47 +1,17 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.admin.setup; import com.alpsbte.alpslib.utils.AlpsUtils; -import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; -import com.alpsbte.plotsystem.core.system.FTPConfiguration; -import com.alpsbte.plotsystem.core.system.Server; -import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.utils.Utils; -import org.apache.commons.io.FileUtils; import org.bukkit.command.CommandSender; -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.sql.SQLException; import java.util.List; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; public class CMD_Setup_Server extends SubCommand { @@ -54,7 +24,6 @@ private void register() { registerSubCommand(new CMD_Setup_Server_List(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_Server_Add(getBaseCommand(), this)); registerSubCommand(new CMD_Setup_Server_Remove(getBaseCommand(), this)); - registerSubCommand(new CMD_Setup_Server_SetFTP(getBaseCommand(), this)); } @Override @@ -90,22 +59,18 @@ public CMD_Setup_Server_List(BaseCommand baseCommand, SubCommand subCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - List servers = Server.getServers(); + List servers = DataProvider.SERVER.getServers(); if (servers.isEmpty()) { sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently no Servers registered in the database!")); return; } sender.sendMessage(Utils.ChatUtils.getInfoFormat("There are currently " + servers.size() + " Servers registered in the database:")); - sender.sendMessage("§8--------------------------"); - for (Server s : servers) { - try { - sender.sendMessage(" §6> §b" + s.getID() + " (" + s.getName() + ") §f- FTP-Configuration: " + (s.getFTPConfiguration() == null ? "None" : s.getFTPConfiguration().getID())); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + + for (String server : servers) { + sender.sendMessage(text(" » ", DARK_GRAY).append(text(server, AQUA))); } - sender.sendMessage("§8--------------------------"); + sender.sendMessage(text("--------------------------", DARK_GRAY)); } @Override @@ -136,23 +101,24 @@ public CMD_Setup_Server_Add(BaseCommand baseCommand, SubCommand subCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 1) {sendInfo(sender); return;} - if (args[1].length() > 45) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Server name cannot be longer than 45 characters!")); + if (args.length <= 2 || AlpsUtils.tryParseInt(args[2]) == null) {sendInfo(sender); return;} + + String serverName = args[1]; + if (serverName.length() > 255) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Server name cannot be longer than 255 characters!")); sendInfo(sender); return; } - try { - Server server = Server.addServer(args[1]); - Path serverPath = Paths.get(PlotUtils.getDefaultSchematicPath(), String.valueOf(server.getID())); - if (serverPath.toFile().exists()) FileUtils.deleteDirectory(serverPath.toFile()); - if (!serverPath.toFile().mkdirs()) throw new IOException(); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added server!")); - } catch (SQLException | IOException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + int buildTeamId = AlpsUtils.tryParseInt(args[2]); + if (DataProvider.BUILD_TEAM.getBuildTeam(buildTeamId).isEmpty()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Build team with id " + buildTeamId + " could not be found!")); + return; } + + boolean successful = DataProvider.SERVER.addServer(serverName, buildTeamId); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully added server!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override @@ -167,7 +133,7 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"Name"}; + return new String[]{"Name", "BuildTeamId"}; } @Override @@ -183,23 +149,19 @@ public CMD_Setup_Server_Remove(BaseCommand baseCommand, SubCommand subCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 1 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} + if (args.length <= 1) {sendInfo(sender); return;} + String name = args[1]; // Check if server exists - try { - if (Server.getServers().stream().noneMatch(s -> s.getID() == Integer.parseInt(args[1]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any server with ID " + args[1] + "!")); - sendInfo(sender); - return; - } - Server.removeServer(Integer.parseInt(args[1])); - Path serverPath = Paths.get(PlotUtils.getDefaultSchematicPath(), args[1]); - if (serverPath.toFile().exists()) FileUtils.deleteDirectory(serverPath.toFile()); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed server with ID " + args[1] + "!")); - } catch (SQLException | IOException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + if (!DataProvider.SERVER.serverExists(name)) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any server with name " + name + "!")); + sendInfo(sender); + return; } + + boolean successful = DataProvider.SERVER.removeServer(name); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully removed server with name " + name + "!")); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command! Check console for any exceptions.")); } @Override @@ -214,7 +176,7 @@ public String getDescription() { @Override public String[] getParameter() { - return new String[]{"Server-ID"}; + return new String[]{"Name"}; } @Override @@ -222,55 +184,4 @@ public String getPermission() { return "plotsystem.admin.pss.server.remove"; } } - - public static class CMD_Setup_Server_SetFTP extends SubCommand { - public CMD_Setup_Server_SetFTP(BaseCommand baseCommand, SubCommand subCommand) { - super(baseCommand, subCommand); - } - - @Override - public void onCommand(CommandSender sender, String[] args) { - if (args.length <= 2 || AlpsUtils.tryParseInt(args[1]) == null) {sendInfo(sender); return;} - - // Check if server exists - try { - if (Server.getServers().stream().noneMatch(s -> s.getID() == Integer.parseInt(args[1]))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any server with ID " + args[1] + "!")); - sendInfo(sender); - return; - } - if (!args[2].equalsIgnoreCase("none") && (AlpsUtils.tryParseInt(args[2]) == null || FTPConfiguration.getFTPConfigurations().stream().noneMatch(f -> f.getID() == Integer.parseInt(args[2])))) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("Could not find any ftp configurations with ID " + args[2] + "!")); - sendInfo(sender); - return; - } - int ftpID = AlpsUtils.tryParseInt(args[2]) != null ? Integer.parseInt(args[2]) : -1; - Server.setFTP(Integer.parseInt(args[1]), ftpID); - sender.sendMessage(Utils.ChatUtils.getInfoFormat("Successfully set FTP Configuration of server with ID " + args[1] + " to " + (ftpID == -1 ? "None" : ftpID) + "!")); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - } - - @Override - public String[] getNames() { - return new String[]{"setftp"}; - } - - @Override - public String getDescription() { - return null; - } - - @Override - public String[] getParameter() { - return new String[]{"Server-ID", "FTP-ID/None"}; - } - - @Override - public String getPermission() { - return "plotsystem.admin.pss.server.setftp"; - } - } } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot.java index 825ba9eb0..37935dbcb 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot.java @@ -1,30 +1,8 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.plot; +import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; +import com.alpsbte.plotsystem.utils.io.ConfigPaths; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; @@ -37,10 +15,12 @@ public CMD_Plot() { registerSubCommand(new CMD_Plot_Links(this)); registerSubCommand(new CMD_Plot_Submit(this)); registerSubCommand(new CMD_Plot_Abandon(this)); - registerSubCommand(new CMD_Plot_Invite(this)); + if (PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.ENABLE_GROUP_SUPPORT)) { + registerSubCommand(new CMD_Plot_Invite(this)); + registerSubCommand(new CMD_Plot_Members(this)); + } registerSubCommand(new CMD_Plot_Feedback(this)); registerSubCommand(new CMD_Plot_UndoSubmit(this)); - registerSubCommand(new CMD_Plot_Members(this)); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java index 75b4490da..7dd10f9a1 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Abandon.java @@ -1,33 +1,10 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.plot; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; @@ -35,14 +12,12 @@ import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; - -import java.sql.SQLException; -import java.util.Objects; -import static net.kyori.adventure.text.Component.text; +import java.util.concurrent.CompletableFuture; public class CMD_Plot_Abandon extends SubCommand { @@ -52,42 +27,52 @@ public CMD_Plot_Abandon(BaseCommand baseCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - @Nullable Player player = getPlayer(sender); - try { + CompletableFuture.runAsync(() -> { Plot plot; + if (!(sender instanceof Player player)) { + sendInfo(sender); + return; + } + if (args.length > 0 && AlpsUtils.tryParseInt(args[0]) != null) { - int plotID = Integer.parseInt(args[0]); - if (PlotUtils.plotExists(plotID)) { - plot = new Plot(plotID); - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); - return; - } - } else if (player != null && PlotUtils.isPlotWorld(player.getWorld())) { + plot = DataProvider.PLOT.getPlotById(Integer.parseInt(args[0])); + } else if (PlotUtils.isPlotWorld(player.getWorld())) { AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unfinished); - if (p instanceof Plot) { - plot = (Plot) p; - } else { + if (!(p instanceof Plot)) { sendInfo(sender); return; } + plot = (Plot) p; } else { sendInfo(sender); return; } - if (Objects.requireNonNull(plot).getStatus() == Status.unfinished) { - if (Utils.isOwnerOrReviewer(sender, player, plot) && PlotUtils.Actions.abandonPlot(plot)) { - sender.sendMessage(Utils.ChatUtils.getInfoFormat(langUtil.get(sender, LangPaths.Message.Info.ABANDONED_PLOT, plot.getID() + ""))); - if (player != null) player.playSound(player.getLocation(), Utils.SoundUtils.ABANDON_PLOT_SOUND, 1, 1); - } - } else { + if (plot == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); + return; + } + if (!Utils.isOwnerOrReviewer(sender, player, plot)) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLAYER_IS_NOT_ALLOWED))); + return; + } + if (plot.getStatus() != Status.unfinished) { sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.CAN_ONLY_ABANDON_UNFINISHED_PLOTS))); + return; } - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + + if (plot.getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(player, LangPaths.Message.Error.CANNOT_MODIFY_LEGACY_PLOT))); + return; + } + + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + if (PlotUtils.Actions.abandonPlot(plot)) { + sender.sendMessage(Utils.ChatUtils.getInfoFormat(langUtil.get(sender, LangPaths.Message.Info.ABANDONED_PLOT, plot.getId() + ""))); + player.playSound(player.getLocation(), Utils.SoundUtils.ABANDON_PLOT_SOUND, 1, 1); + } + }); + }); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Feedback.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Feedback.java index 0af9373da..1c298ed39 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Feedback.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Feedback.java @@ -1,33 +1,10 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.plot; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.menus.FeedbackMenu; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; @@ -39,9 +16,9 @@ import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; -import java.sql.SQLException; -import java.util.Objects; +import java.util.concurrent.CompletableFuture; import static net.kyori.adventure.text.Component.text; @@ -53,46 +30,44 @@ public CMD_Plot_Feedback(BaseCommand baseCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - try { - if (getPlayer(sender) != null) { - Plot plot; - if (args.length > 0 && AlpsUtils.tryParseInt(args[0]) != null) { - int plotID = Integer.parseInt(args[0]); - if (PlotUtils.plotExists(plotID)) { - plot = new Plot(plotID); - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); - return; - } - } else if (PlotUtils.isPlotWorld(getPlayer(sender).getWorld())) { - AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()), Status.completed); - if (p instanceof Plot) { - plot = (Plot) p; - } else { - sendInfo(sender); - return; - } - } else { + Player player = getPlayer(sender); + if (player == null) { + Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + return; + } + + CompletableFuture.runAsync(() -> { + Plot plot; + if (args.length > 0 && AlpsUtils.tryParseInt(args[0]) != null) { + plot = DataProvider.PLOT.getPlotById(Integer.parseInt(args[0])); + } else if (PlotUtils.isPlotWorld(player.getWorld())) { + AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unfinished); + if (!(p instanceof Plot)) { sendInfo(sender); return; } - - if (Objects.requireNonNull(plot).getPlotOwner().getUUID().equals(getPlayer(sender).getUniqueId()) || plot.getPlotMembers().stream().anyMatch(m -> m.getUUID().equals(getPlayer(sender).getUniqueId())) || getPlayer(sender).hasPermission("plotsystem.plot.review")) { - if (plot.isReviewed()) { - new FeedbackMenu(getPlayer(sender), plot.getID()); - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_HAS_NOT_YET_REVIEWED))); - } - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); - } + plot = (Plot) p; } else { - Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + sendInfo(sender); + return; } - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + + if (plot == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); + return; + } + if (!plot.getPlotOwner().getUUID().equals(player.getUniqueId()) + && plot.getPlotMembers().stream().noneMatch(m -> m.getUUID().equals(player.getUniqueId())) && !player.hasPermission("plotsystem.plot.review")) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + return; + } + if (!plot.isReviewed()) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_HAS_NOT_YET_REVIEWED))); + return; + } + + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> new FeedbackMenu(player, plot.getId())); + }); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Invite.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Invite.java index 6c7ad6236..402b0578e 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Invite.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Invite.java @@ -1,40 +1,14 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.plot; -import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; -import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.PlotMemberInvitation; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.LangPaths; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; - -import java.sql.SQLException; +import org.bukkit.entity.Player; import static net.kyori.adventure.text.Component.text; @@ -46,40 +20,43 @@ public CMD_Plot_Invite(BaseCommand baseCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - if (args.length > 0) { - FileConfiguration config = PlotSystem.getPlugin().getConfig(); - if (getPlayer(sender) != null && config.getBoolean(ConfigPaths.ENABLE_GROUP_SUPPORT)) { - PlotMemberInvitation invite = null; - for (PlotMemberInvitation item : PlotMemberInvitation.invitationsList) { - if (item.invitee.getUniqueId().toString().equals(getPlayer(sender).getUniqueId().toString())) { - invite = item; - try { - switch (args[0]) { - case "accept": - item.acceptInvite(); - break; - case "reject": - item.rejectInvite(); - break; - default: - sendInfo(sender); - break; - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - } - } + Player player = getPlayer(sender); + if (player == null) { + Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + return; + } - if (invite != null) { - PlotMemberInvitation.invitationsList.remove(invite); - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_INVITATIONS))); - } - } - } else { + if (args.length == 0) { sendInfo(sender); + return; + } + + PlotMemberInvitation invite = null; + for (PlotMemberInvitation item : PlotMemberInvitation.invitationsList) { + if (!item.invitee.getUniqueId().toString().equals(player.getUniqueId().toString())) { + continue; + } + + invite = item; + switch (args[0]) { + case "accept": + item.acceptInvite(); + break; + case "reject": + item.rejectInvite(); + break; + default: + sendInfo(sender); + break; + } } + + if (invite == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_INVITATIONS))); + return; + } + + PlotMemberInvitation.invitationsList.remove(invite); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Links.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Links.java index 955eec374..b3dfddaeb 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Links.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Links.java @@ -1,33 +1,9 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.plot; import com.alpsbte.alpslib.utils.AlpsUtils; -import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; @@ -37,8 +13,9 @@ import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; -import java.sql.SQLException; +import java.util.concurrent.CompletableFuture; import static net.kyori.adventure.text.Component.text; @@ -50,26 +27,35 @@ public CMD_Plot_Links(BaseCommand baseCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - try { - if (getPlayer(sender) != null) { - if (args.length > 0 && AlpsUtils.tryParseInt(args[0]) != null) { - int plotID = Integer.parseInt(args[0]); - if (PlotUtils.plotExists(plotID)) { - PlotUtils.ChatFormatting.sendLinkMessages(new Plot(plotID), getPlayer(sender)); - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); - } - } else if (PlotUtils.isPlotWorld(getPlayer(sender).getWorld())) { - PlotUtils.ChatFormatting.sendLinkMessages(PlotUtils.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()), Status.unfinished, Status.unreviewed), getPlayer(sender)); - } else { + Player player = getPlayer(sender); + if (player == null) { + Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + return; + } + + CompletableFuture.runAsync(() -> { + Builder builder = Builder.byUUID(player.getUniqueId()); + if (args.length == 0) { + if (!PlotUtils.isPlotWorld(player.getWorld())) { sendInfo(sender); + return; } - } else { - Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + PlotUtils.ChatFormatting.sendLinkMessages(PlotUtils.getCurrentPlot(builder, Status.unfinished, Status.unreviewed), player); + return; } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + + if (AlpsUtils.tryParseInt(args[0]) == null) { + sendInfo(sender); + return; + } + Plot plot = DataProvider.PLOT.getPlotById(Integer.parseInt(args[0])); + if (plot == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); + return; + } + + PlotUtils.ChatFormatting.sendLinkMessages(plot, player); + }); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Members.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Members.java index e60229fb5..3b61e769c 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Members.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Members.java @@ -1,33 +1,10 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.plot; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.menus.PlotMemberMenu; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; @@ -35,12 +12,14 @@ import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; +import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; -import java.sql.SQLException; -import java.util.Objects; +import java.util.concurrent.CompletableFuture; import static net.kyori.adventure.text.Component.text; @@ -52,45 +31,60 @@ public CMD_Plot_Members(BaseCommand baseCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - try { - if (getPlayer(sender) != null) { - Plot plot; - // Get Plot - if (args.length > 0 && AlpsUtils.tryParseInt(args[0]) != null) { - //plot members - int plotID = Integer.parseInt(args[0]); - if (PlotUtils.plotExists(plotID)) { - plot = new Plot(plotID); - } else { + Player player = getPlayer(sender); + if (player == null) { + Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + return; + } + + CompletableFuture.runAsync(() -> { + Plot plot; + + // Use tryParseInt result (avoids double parsing) and handle null safely + if (args.length > 0) { + Integer id = AlpsUtils.tryParseInt(args[0]); + if (id != null) { + plot = DataProvider.PLOT.getPlotById(id); + if (plot == null) { sender.sendMessage(Utils.ChatUtils.getAlertFormat("This plot does not exist!")); return; } - } else if (PlotUtils.isPlotWorld(getPlayer(sender).getWorld())) { - //plot members - AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()), Status.unfinished, Status.unreviewed); - if (p instanceof Plot) { - plot = (Plot) p; - } else { - sendInfo(sender); - return; - } } else { - sendInfo(sender); + sender.sendMessage(Utils.ChatUtils.getAlertFormat("Invalid plot ID.")); return; } - - if (Objects.requireNonNull(plot).getPlotOwner().getUUID().equals(getPlayer(sender).getUniqueId()) || getPlayer(sender).hasPermission("plotsystem.admin")) { - new PlotMemberMenu(plot, getPlayer(sender)); + } else if (PlotUtils.isPlotWorld(player.getWorld())) { + AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unfinished, Status.unreviewed); + if (p instanceof Plot pl) { + plot = pl; } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("You don't have permission to manage this plot's members!")); + sendInfo(sender); + return; } } else { - Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + sendInfo(sender); + return; } - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat("An error occurred while executing command!")); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + + // Guard against missing owner data + if (plot.getPlotOwner() == null || plot.getPlotOwner().getUUID() == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("This plot has no owner assigned. Contact an admin.")); + return; + } + + if (!plot.getPlotOwner().getUUID().equals(player.getUniqueId()) && !player.hasPermission("plotsystem.admin")) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat("You don't have permission to manage this plot's members!")); + return; + } + if (plot.getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(player, LangPaths.Message.Error.CANNOT_MODIFY_LEGACY_PLOT))); + return; + } + + // Switch to main thread for menu creation (GUI operations must be on main thread) + Plot finalPlot = plot; + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> new PlotMemberMenu(finalPlot, player)); + }); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Submit.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Submit.java index 9b992572d..dd24a910f 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Submit.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Submit.java @@ -1,33 +1,10 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.plot; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; @@ -35,12 +12,15 @@ import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; -import java.sql.SQLException; +import java.util.List; import java.util.Objects; +import java.util.concurrent.CompletableFuture; import static net.kyori.adventure.text.Component.text; @@ -52,58 +32,68 @@ public CMD_Plot_Submit(BaseCommand baseCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - try { + Player player = getPlayer(sender); + if (player == null) { + Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + return; + } + + CompletableFuture.runAsync(() -> { Plot plot; - @Nullable Player player = getPlayer(sender); if (args.length > 0 && AlpsUtils.tryParseInt(args[0]) != null) { - int plotID = Integer.parseInt(args[0]); - if (PlotUtils.plotExists(plotID)) { - plot = new Plot(plotID); - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); - return; - } - } else if (player != null && PlotUtils.isPlotWorld(player.getWorld())) { - AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId())); - if (p instanceof Plot) { - plot = (Plot) p; - } else { + plot = DataProvider.PLOT.getPlotById(Integer.parseInt(args[0])); + } else if (PlotUtils.isPlotWorld(player.getWorld())) { + AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unfinished); + if (!(p instanceof Plot)) { sendInfo(sender); return; } + plot = (Plot) p; } else { sendInfo(sender); return; } - if (Utils.isOwnerOrReviewer(sender, player, plot)) { - if (Objects.requireNonNull(plot).getStatus() == Status.unfinished) { - PlotUtils.Actions.submitPlot(plot); - - if (plot.getPlotMembers().isEmpty()) { - // Plot was made alone - langUtil.broadcast(LangPaths.Message.Info.FINISHED_PLOT, String.valueOf(plot.getID()), plot.getPlotOwner().getName()); - } else { - // Plot was made in a group - StringBuilder sb = new StringBuilder(plot.getPlotOwner().getName() + ", "); - - for (int i = 0; i < plot.getPlotMembers().size(); i++) { - sb.append(i == plot.getPlotMembers().size() - 1 ? - plot.getPlotMembers().get(i).getName() : - plot.getPlotMembers().get(i).getName() + ", "); - } - langUtil.broadcast(LangPaths.Message.Info.FINISHED_PLOT, String.valueOf(plot.getID()), sb.toString()); - } + if (plot == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); + return; + } + if (!Utils.isOwnerOrReviewer(sender, player, plot)) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLAYER_IS_NOT_ALLOWED))); + return; + } + if (plot.getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.CANNOT_MODIFY_LEGACY_PLOT))); + return; + } + if (plot.getStatus() != Status.unfinished) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.CAN_ONLY_SUBMIT_UNFINISHED_PLOTS))); + return; + } + + List plotMembers = plot.getPlotMembers(); + + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { - if (player != null) player.playSound(player.getLocation(), Utils.SoundUtils.FINISH_PLOT_SOUND, 1, 1); + PlotUtils.Actions.submitPlot(plot); + if (plotMembers.isEmpty()) { + // Plot was made alone + langUtil.broadcast(LangPaths.Message.Info.FINISHED_PLOT, String.valueOf(plot.getId()), plot.getPlotOwner().getName()); } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.CAN_ONLY_SUBMIT_UNFINISHED_PLOTS))); + // Plot was made in a group + StringBuilder sb = new StringBuilder(plot.getPlotOwner().getName() + ", "); + + for (int i = 0; i < plotMembers.size(); i++) { + sb.append(i == plotMembers.size() - 1 ? + plotMembers.get(i).getName() : + plotMembers.get(i).getName() + ", "); + } + langUtil.broadcast(LangPaths.Message.Info.FINISHED_PLOT, String.valueOf(plot.getId()), sb.toString()); } - } - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + + Objects.requireNonNull(player).playSound(player.getLocation(), Utils.SoundUtils.FINISH_PLOT_SOUND, 1, 1); + }); + }); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Teleport.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Teleport.java index 0ce04f455..b4c9033bc 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Teleport.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_Teleport.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.plot; import com.alpsbte.alpslib.utils.AlpsUtils; @@ -29,20 +5,22 @@ import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.ICommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.generator.DefaultPlotGenerator; -import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; -import java.sql.SQLException; - -import static net.kyori.adventure.text.Component.text; +import java.util.concurrent.CompletableFuture; public class CMD_Plot_Teleport extends SubCommand implements ICommand { @@ -52,30 +30,45 @@ public CMD_Plot_Teleport(BaseCommand baseCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - try { - if (getPlayer(sender) != null) { - if (args.length > 0 && AlpsUtils.tryParseInt(args[0]) != null) { - int plotID = Integer.parseInt(args[0]); - Plot plot; - if (PlotUtils.plotExists(plotID) && (plot = new Plot(plotID)).getStatus() != Status.unclaimed) { - plot.getWorld().teleportPlayer(getPlayer(sender)); - } else { - if (sender.hasPermission("plotsystem.admin") && PlotUtils.plotExists(plotID)) { - new DefaultPlotGenerator(new Plot(plotID), Builder.byUUID(getPlayer(sender).getUniqueId())); - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); - } - } - } else { - sendInfo(sender); + Player player = getPlayer(sender); + if (player == null) { + Bukkit.getConsoleSender().sendMessage(Component.text("This command can only be used as a player!", NamedTextColor.RED)); + return; + } + + if (args.length == 0 || AlpsUtils.tryParseInt(args[0]) == null) { + sendInfo(sender); + return; + } + + int plotID = Integer.parseInt(args[0]); + + CompletableFuture.runAsync(() -> { + Plot plot = DataProvider.PLOT.getPlotById(plotID); + + if (plot != null && plot.getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.CANNOT_LOAD_LEGACY_PLOT))); + return; + } + + if (plot == null || plot.getStatus() == Status.unclaimed) { + if (!sender.hasPermission("plotsystem.admin") || plot == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); + return; + } + + Builder builder = Builder.byUUID(player.getUniqueId()); + if (builder == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); + return; } - } else { - Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> new DefaultPlotGenerator(plot, builder)); + return; } - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> plot.getWorld().teleportPlayer(player)); + }); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java index a284bb2ee..a9b89bb9c 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/plot/CMD_Plot_UndoSubmit.java @@ -1,33 +1,10 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.plot; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; import com.alpsbte.plotsystem.commands.SubCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; @@ -35,12 +12,13 @@ import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import net.kyori.adventure.text.format.NamedTextColor; +import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import org.jetbrains.annotations.Nullable; -import java.sql.SQLException; -import java.util.Objects; +import java.util.concurrent.CompletableFuture; import static net.kyori.adventure.text.Component.text; @@ -52,43 +30,51 @@ public CMD_Plot_UndoSubmit(BaseCommand baseCommand) { @Override public void onCommand(CommandSender sender, String[] args) { - try { + if (!(sender instanceof Player player)) { + Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + return; + } + + CompletableFuture.runAsync(() -> { Plot plot; - @Nullable Player player = getPlayer(sender); if (args.length > 0 && AlpsUtils.tryParseInt(args[0]) != null) { - int plotID = Integer.parseInt(args[0]); - if (PlotUtils.plotExists(plotID)) { - plot = new Plot(plotID); - } else { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); - return; - } - } else if (player != null && PlotUtils.isPlotWorld(player.getWorld())) { - AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unreviewed); - if (p instanceof Plot) { - plot = (Plot) p; - } else { + plot = DataProvider.PLOT.getPlotById(Integer.parseInt(args[0])); + } else if (PlotUtils.isPlotWorld(player.getWorld())) { + AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unfinished); + if (!(p instanceof Plot)) { sendInfo(sender); return; } + plot = (Plot) p; } else { sendInfo(sender); return; } - if (Objects.requireNonNull(plot).getStatus() == Status.unreviewed) { - if (Utils.isOwnerOrReviewer(sender, player, plot)) { - PlotUtils.Actions.undoSubmit(plot); - sender.sendMessage(Utils.ChatUtils.getInfoFormat(langUtil.get(sender, LangPaths.Message.Info.UNDID_SUBMISSION, plot.getID() + ""))); - if (player != null) player.playSound(player.getLocation(), Utils.SoundUtils.FINISH_PLOT_SOUND, 1, 1); - } - } else { + if (plot == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); + return; + } + if (!Utils.isOwnerOrReviewer(sender, player, plot)) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLAYER_IS_NOT_ALLOWED))); + return; + } + if (plot.getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.CANNOT_MODIFY_LEGACY_PLOT))); + return; + } + if (plot.getStatus() != Status.unreviewed) { sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.CAN_ONLY_UNDO_SUBMISSIONS_UNREVIEWED_PLOTS))); + return; } - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + PlotUtils.Actions.undoSubmit(plot); + + sender.sendMessage(Utils.ChatUtils.getInfoFormat(langUtil.get(sender, LangPaths.Message.Info.UNDID_SUBMISSION, plot.getId() + ""))); + player.playSound(player.getLocation(), Utils.SoundUtils.FINISH_PLOT_SOUND, 1, 1); + }); + }); } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditFeedback.java b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditFeedback.java index 14a4d4c97..d90819163 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditFeedback.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditFeedback.java @@ -1,85 +1,83 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.review; import com.alpsbte.alpslib.utils.AlpsUtils; -import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; -import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; +import com.alpsbte.plotsystem.core.system.review.PlotReview; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; +import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.RED; public class CMD_EditFeedback extends BaseCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { - if (!sender.hasPermission(getPermission())) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + Player player = getPlayer(sender); + if (player == null) { + Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", RED)); return true; } - if (args.length <= 1 || AlpsUtils.tryParseInt(args[0]) == null) {sendInfo(sender); return true;} - int plotID = Integer.parseInt(args[0]); + CompletableFuture.runAsync(() -> { + if (!DataProvider.BUILD_TEAM.isAnyReviewer(player.getUniqueId()) && !sender.hasPermission("plotsystem.admin")) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + return; + } - if (!PlotUtils.plotExists(plotID)) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); - return true; - } + if (args.length < 1) { + sendInfo(sender); + return; + } + + Integer plotId = AlpsUtils.tryParseInt(args[0]); - Plot plot = new Plot(plotID); - try { - if (!plot.isReviewed() && !plot.isRejected()) { + if (plotId == null) { + sendInfo(sender); + return; + } + + Plot plot = DataProvider.PLOT.getPlotById(plotId); + + if (plot.getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.CANNOT_MODIFY_LEGACY_PLOT))); + return; + } + + Optional review = plot.getLatestReview(); + if (review.isEmpty()) { sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLOT_EITHER_UNCLAIMED_OR_UNREVIEWED))); - return true; + return; } - if (getPlayer(sender) != null && !sender.hasPermission("plotsystem.admin") && !plot.getReview().getReviewer().getUUID().equals(((Player) sender).getUniqueId())) { + + Builder builder = DataProvider.BUILDER.getBuilderByUUID(player.getUniqueId()); + if (DataProvider.BUILDER.canNotReviewPlot(builder.getUUID(), plot) && !sender.hasPermission("plotsystem.admin")) { sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.CANNOT_SEND_FEEDBACK))); - return true; + return; } StringBuilder feedback = new StringBuilder(); for (int i = 2; i <= args.length; i++) { feedback.append(args.length == 2 ? "" : " ").append(args[i - 1]); } - plot.getReview().setFeedback(feedback.toString()); - sender.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Info.UPDATED_PLOT_FEEDBACK, plot.getID() + ""))); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + boolean successful = review.get().updateFeedback(feedback.toString()); + if (successful) sender.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Info.UPDATED_PLOT_FEEDBACK, plot.getId() + ""))); + else sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); + }); return true; } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditPlot.java b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditPlot.java index 2c01c1eb1..595904d1b 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditPlot.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_EditPlot.java @@ -1,117 +1,97 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.review; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; +import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; +import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; import com.alpsbte.plotsystem.utils.io.ConfigPaths; -import com.alpsbte.plotsystem.core.system.Builder; -import com.alpsbte.plotsystem.core.system.plot.Plot; -import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.ConfigUtil; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.Component; import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; +import java.util.concurrent.CompletableFuture; -import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.RED; public class CMD_EditPlot extends BaseCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { - if (getPlayer(sender) == null) { - Bukkit.getConsoleSender().sendMessage(text("This command can only be used as a player!", NamedTextColor.RED)); + Player player = getPlayer(sender); + if (player == null) { + Bukkit.getConsoleSender().sendMessage(Component.text("This command can only be used as a player!", RED)); return true; } + // TODO: don't register command if this config value is false if (!ConfigUtil.getInstance().configs[1].getBoolean(ConfigPaths.EDITPLOT_ENABLED)) { sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.COMMAND_DISABLED))); return true; } - if (!sender.hasPermission(getPermission())) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); - return true; - } + CompletableFuture.runAsync(() -> { + if (!DataProvider.BUILD_TEAM.isAnyReviewer(player.getUniqueId()) && !sender.hasPermission("plotsystem.admin")) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + return; + } - try { Plot plot; if (args.length > 0 && AlpsUtils.tryParseInt(args[0]) != null) { - int plotID = Integer.parseInt(args[0]); - if (!PlotUtils.plotExists(plotID)) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); - return true; - } - plot = new Plot(plotID); - } else if (getPlayer(sender) != null && PlotUtils.isPlotWorld(getPlayer(sender).getWorld())) { - AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(getPlayer(sender).getUniqueId()), Status.unfinished, Status.unreviewed); - if (p instanceof Plot) { - plot = (Plot) p; - } else { + plot = DataProvider.PLOT.getPlotById(Integer.parseInt(args[0])); + } else if (PlotUtils.isPlotWorld(player.getWorld())) { + AbstractPlot p = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unfinished); + if (!(p instanceof Plot)) { sendInfo(sender); - return true; + return; } + plot = (Plot) p; } else { sendInfo(sender); - return true; + return; } + if (plot == null) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); + return; + } if (plot.getStatus() == Status.completed) { sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_IS_NOT_ALLOWED))); - return true; + return; } - Builder builder = Builder.byUUID(getPlayer(sender).getUniqueId()); - int countryID = plot.getCity().getCountry().getID(); - if (!builder.isReviewer() || builder.getAsReviewer().getCountries().stream().noneMatch(c -> c.getID() == countryID) || plot.getPlotOwner().getUUID() == builder.getUUID() || plot.getPlotMembers().stream().anyMatch(b -> b.getUUID() == builder.getUUID())) { - return true; + Builder builder = Builder.byUUID(player.getUniqueId()); + if (DataProvider.BUILDER.canNotReviewPlot(builder.getUUID(), plot) && !sender.hasPermission("plotsystem.admin")) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + return; } - if (!plot.getPermissions().hasBuildingPerms(builder.getUUID())) { - plot.getPermissions().addBuilderPerms(builder.getUUID()).save(); - sender.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Info.ENABLED_PLOT_PERMISSIONS, plot.getID() + ""))); - return true; - } + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + + if (!plot.getPermissions().hasBuildingPerms(builder.getUUID())) { + plot.getPermissions().addBuilderPerms(builder.getUUID()).save(); + sender.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Info.ENABLED_PLOT_PERMISSIONS, plot.getId() + ""))); + return; + } + + plot.getPermissions().removeBuilderPerms(builder.getUUID()).save(); + sender.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Info.DISABLED_PLOT_PERMISSIONS, plot.getId() + ""))); + }); + }); + - plot.getPermissions().removeBuilderPerms(builder.getUUID()).save(); - sender.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Info.DISABLED_PLOT_PERMISSIONS, plot.getID() + ""))); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } return true; } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_Review.java b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_Review.java index 98d4a10cf..01b234dbf 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_Review.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_Review.java @@ -1,34 +1,11 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.review; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; -import com.alpsbte.plotsystem.core.menus.ReviewMenu; -import com.alpsbte.plotsystem.core.menus.ReviewPlotMenu; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.menus.review.ReviewMenu; +import com.alpsbte.plotsystem.core.menus.review.ReviewPlotMenu; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; @@ -45,7 +22,7 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; +import java.util.concurrent.CompletableFuture; import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.format.NamedTextColor.RED; @@ -53,85 +30,103 @@ public class CMD_Review extends BaseCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { - if (getPlayer(sender) == null) { + Player player = getPlayer(sender); + if (player == null) { Bukkit.getConsoleSender().sendMessage(Component.text("This command can only be used as a player!", RED)); return true; } - if (!sender.hasPermission(getPermission())) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); - return true; - } + CompletableFuture.runAsync(() -> { + if (!DataProvider.BUILD_TEAM.isAnyReviewer(player.getUniqueId()) && !sender.hasPermission("plotsystem.admin")) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + return; + } - if (args.length > 0 && AlpsUtils.tryParseInt(args[0]) == null) { - sendInfo(sender); - return true; - } + Builder builder = DataProvider.BUILDER.getBuilderByUUID(player.getUniqueId()); + AbstractPlot currentPlot = PlotUtils.getCurrentPlot(builder); - Bukkit.getScheduler().runTaskAsynchronously(PlotSystem.getPlugin(), () -> { - Plot plot = null; - if (args.length > 0) { - int plotId = Integer.parseInt(args[0]); - if (!PlotUtils.plotExists(plotId)) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, - LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); - return; - } - plot = new Plot(plotId); + if (args.length == 0 && !(currentPlot instanceof Plot)) { + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> new ReviewMenu(player)); + return; } - try { - Builder.Reviewer builder = Builder.byUUID(getPlayer(sender).getUniqueId()).getAsReviewer(); - Player player = (Player) sender; - - // Check if the given plot is valid - if (plot != null && plot.getStatus() != Status.unreviewed) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, - LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); + Plot plotToReview; + if (args.length == 0) plotToReview = (Plot) currentPlot; + else { + Integer id = AlpsUtils.tryParseInt(args[0]); + if (id == null) { + sendInfo(sender); return; } - // Check if the reviewer is on the plot - AbstractPlot currentPlot = PlotUtils.getCurrentPlot(Builder.byUUID(player.getUniqueId()), Status.unreviewed); - boolean teleportPlayer = false; - if (currentPlot instanceof Plot cp) { - if (plot != null && plot.getID() != currentPlot.getID()) teleportPlayer = true; - else plot = cp; - } else if (plot == null) { - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> new ReviewMenu(player)); - return; - } else teleportPlayer = true; - - // If the reviewer is not on the plot, teleport the player - if (teleportPlayer) { - Plot finalPlot = plot; - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> finalPlot.getWorld().teleportPlayer(player)); + plotToReview = DataProvider.PLOT.getPlotById(id); + if (plotToReview == null || plotToReview.getStatus() != Status.unreviewed) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(player, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); return; } + } - // Check if player is allowed to review this plot (cannot be the owner or a member of this plot) - if ((plot.getPlotOwner().getUUID().toString().equals(player.getUniqueId().toString()) || - (!plot.getPlotMembers().isEmpty() && plot.getPlotMembers().stream() - .anyMatch(b -> b.getUUID().toString().equals(player.getUniqueId().toString())))) && - !PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DEV_MODE)) { - player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(player, - LangPaths.Message.Error.CANNOT_REVIEW_OWN_PLOT))); - return; - } + if (plotToReview.getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(player, LangPaths.Message.Error.CANNOT_LOAD_LEGACY_PLOT))); + return; + } - // Check if the reviewer is allowed to review this plot in this city project - int countryID = plot.getCity().getCountry().getID(); - if (builder.getCountries().stream().anyMatch(c -> c.getID() == countryID)) { - Plot finalPlot = plot; - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> new ReviewPlotMenu(player, finalPlot)); - return; + if (DataProvider.BUILDER.canNotReviewPlot(builder.getUUID(), plotToReview) && !sender.hasPermission("plotsystem.admin")) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + return; + } + + // Players cannot review their own plots + boolean isParticipant = plotToReview.getPlotOwner().getUUID().equals(player.getUniqueId()) || plotToReview.getPlotMembers().stream().anyMatch(b -> b.getUUID().equals(player.getUniqueId())); + if (!PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DEV_MODE) && isParticipant) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(player, LangPaths.Message.Error.CANNOT_REVIEW_OWN_PLOT))); + return; + } + + // Check if the reviewer is on the plot + boolean teleportPlayer = false; + if (currentPlot instanceof Plot currentPlotCast) { + if (plotToReview.getId() != currentPlotCast.getId()) { + teleportPlayer = true; + if (PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DEV_MODE)) { + PlotSystem.getPlugin().getComponentLogger().info(text("Review: Player on different plot, will teleport. Current: " + currentPlotCast.getId() + ", Target: " + plotToReview.getId())); + } + } else { + if (PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DEV_MODE)) { + PlotSystem.getPlugin().getComponentLogger().info(text("Review: Player on target plot " + plotToReview.getId() + ", opening menu directly")); + } } + } else { + teleportPlayer = true; + if (PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DEV_MODE)) { + PlotSystem.getPlugin().getComponentLogger().info(text("Review: Player not on any plot, will teleport to plot " + plotToReview.getId())); + } + } - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> new ReviewMenu(player)); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(langUtil.get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + Plot finalPlotToReview = plotToReview; + + // If the reviewer is not on the plot, teleport the player first + if (teleportPlayer) { + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + plotToReview.getWorld().teleportPlayer(player); + if (PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DEV_MODE)) { + PlotSystem.getPlugin().getComponentLogger().info(text("Review: Teleported player, scheduling menu open in 20 ticks")); + } + }); + return; } + + // Player is already on the plot, open menu on main thread + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + if (PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DEV_MODE)) { + PlotSystem.getPlugin().getComponentLogger().info(text("Review: Opening ReviewPlotMenu for plot if status is unreviewed" + finalPlotToReview.getId() + " (no teleport needed)")); + } + if (finalPlotToReview.getStatus() == Status.unreviewed) { + new ReviewPlotMenu(player, finalPlotToReview); + } else { + new ReviewMenu(player); + } + }); }); return true; } @@ -153,6 +148,6 @@ public String[] getParameter() { @Override public String getPermission() { - return "plotsystem.review"; + return ""; } } diff --git a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_UndoReview.java b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_UndoReview.java index 1224e274b..f0c47b016 100644 --- a/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_UndoReview.java +++ b/src/main/java/com/alpsbte/plotsystem/commands/review/CMD_UndoReview.java @@ -1,83 +1,85 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.commands.review; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.commands.BaseCommand; -import com.alpsbte.plotsystem.core.system.Review; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; -import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; +import com.alpsbte.plotsystem.core.system.review.PlotReview; import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.enums.Status; +import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; +import net.kyori.adventure.text.Component; +import org.bukkit.Bukkit; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; +import java.util.Optional; +import java.util.concurrent.CompletableFuture; -import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.RED; public class CMD_UndoReview extends BaseCommand { @Override public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String s, String[] args) { - if (!sender.hasPermission(getPermission())) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + Player player = getPlayer(sender); + if (player == null) { + Bukkit.getConsoleSender().sendMessage(Component.text("This command can only be used as a player!", RED)); return true; } - if (args.length == 0 || AlpsUtils.tryParseInt(args[0]) == null) { - sendInfo(sender); - return true; - } + CompletableFuture.runAsync(() -> { + if (!DataProvider.BUILD_TEAM.isAnyReviewer(player.getUniqueId()) && !sender.hasPermission("plotsystem.admin")) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + return; + } - int plotID = Integer.parseInt(args[0]); - if (!PlotUtils.plotExists(plotID)) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); - return true; - } + if (args.length < 1 || AlpsUtils.tryParseInt(args[0]) == null) { + sendInfo(sender); + return; + } - try { - Plot plot = new Plot(plotID); - if (!plot.isReviewed()) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLOT_EITHER_UNCLAIMED_OR_UNREVIEWED))); - return true; + Plot plot = DataProvider.PLOT.getPlotById(Integer.parseInt(args[0])); + if (plot == null || plot.getStatus() != Status.completed) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, + LangPaths.Message.Error.PLOT_DOES_NOT_EXIST))); + return; } - if (getPlayer(sender) != null && !sender.hasPermission("plotsystem.admin") && !plot.getReview().getReviewer().getUUID().equals(getPlayer(sender).getUniqueId())) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.CANNOT_UNDO_REVIEW))); - return true; + if (plot.getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.CANNOT_MODIFY_LEGACY_PLOT))); + return; } - Review.undoReview(plot.getReview()); - sender.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Info.UNDID_REVIEW, plot.getID() + "", plot.getPlotOwner().getName()))); - } catch (SQLException ex) { - sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + Builder builder = DataProvider.BUILDER.getBuilderByUUID(player.getUniqueId()); + if (DataProvider.BUILDER.canNotReviewPlot(builder.getUUID(), plot) && !sender.hasPermission("plotsystem.admin")) { + sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_HAS_NO_PERMISSIONS))); + return; + } + + // Players cannot review their own plots + boolean isParticipant = plot.getPlotOwner().getUUID() == player.getUniqueId() || plot.getPlotMembers().stream().anyMatch(b -> b.getUUID() == player.getUniqueId()); + if (!PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DEV_MODE) && isParticipant) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(player, LangPaths.Message.Error.CANNOT_REVIEW_OWN_PLOT))); + return; + } + + Optional review = plot.getLatestReview(); + if (review.isEmpty()) { + player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(player, LangPaths.Message.Error.REVIEW_NOT_FOUND))); + return; + } + + boolean successful = review.get().undoReview(); + if (successful) player.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(player, LangPaths.Message.Info.UNDID_REVIEW, plot.getId() + "", plot.getPlotOwner().getName()))); + else player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(player, LangPaths.Message.Error.ERROR_OCCURRED))); + }); return true; } diff --git a/src/main/java/com/alpsbte/plotsystem/core/EventListener.java b/src/main/java/com/alpsbte/plotsystem/core/EventListener.java index 6087f7005..0d38d00c0 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/EventListener.java +++ b/src/main/java/com/alpsbte/plotsystem/core/EventListener.java @@ -1,52 +1,32 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core; import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.menus.companion.CompanionMenu; +import com.alpsbte.plotsystem.core.menus.review.ReviewMenu; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.CityProject; +import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.TutorialPlot; +import com.alpsbte.plotsystem.core.system.plot.generator.DefaultPlotGenerator; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; +import com.alpsbte.plotsystem.core.system.review.ReviewNotification; import com.alpsbte.plotsystem.core.system.tutorial.AbstractPlotTutorial; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; import com.alpsbte.plotsystem.core.system.tutorial.Tutorial; import com.alpsbte.plotsystem.core.system.tutorial.TutorialCategory; +import com.alpsbte.plotsystem.utils.DependencyManager; import com.alpsbte.plotsystem.utils.PlotMemberInvitation; +import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.chat.ChatInput; -import com.alpsbte.plotsystem.utils.chat.PlayerInviteeChatInput; import com.alpsbte.plotsystem.utils.chat.PlayerFeedbackChatInput; +import com.alpsbte.plotsystem.utils.chat.PlayerInviteeChatInput; +import com.alpsbte.plotsystem.utils.enums.Status; import com.alpsbte.plotsystem.utils.io.ConfigPaths; -import com.alpsbte.plotsystem.core.menus.ReviewMenu; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; -import com.alpsbte.plotsystem.core.system.plot.Plot; -import com.alpsbte.plotsystem.core.system.Builder; -import com.alpsbte.plotsystem.core.system.plot.generator.DefaultPlotGenerator; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.alpsbte.plotsystem.utils.Utils; -import com.alpsbte.plotsystem.utils.enums.Status; +import com.destroystokyo.paper.event.player.PlayerClientOptionsChangeEvent; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.protection.flags.Flags; @@ -54,7 +34,9 @@ import com.sk89q.worldguard.protection.regions.RegionQuery; import io.papermc.paper.event.player.AsyncChatEvent; import li.cinnazeyy.langlibs.core.event.LanguageChangeEvent; +import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.title.Title; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Material; @@ -68,125 +50,56 @@ import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.*; +import org.bukkit.event.player.PlayerChangedWorldEvent; +import org.bukkit.event.player.PlayerDropItemEvent; +import org.bukkit.event.player.PlayerInteractAtEntityEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.player.PlayerSwapHandItemsEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; +import java.time.Duration; import java.util.List; import java.util.Locale; import java.util.UUID; +import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class EventListener implements Listener { @EventHandler public void onPlayerJoinEvent(PlayerJoinEvent event) { - // User has joined for the first time - // Adding user to the database - Bukkit.getScheduler().runTaskAsynchronously(PlotSystem.getPlugin(), () -> { - // Add Items - Utils.updatePlayerInventorySlots(event.getPlayer()); - - // Check if player even exists in database. - try (ResultSet rs = DatabaseConnection.createStatement("SELECT * FROM plotsystem_builders WHERE uuid = ?") - .setValue(event.getPlayer().getUniqueId().toString()).executeQuery()) { - - if (!rs.first()) { - DatabaseConnection.createStatement("INSERT INTO plotsystem_builders (uuid, name) VALUES (?, ?)") - .setValue(event.getPlayer().getUniqueId().toString()) - .setValue(event.getPlayer().getName()) - .executeUpdate(); - } + Player player = event.getPlayer(); - DatabaseConnection.closeResultSet(rs); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - - // Inform player about update - if (event.getPlayer().hasPermission("plotsystem.admin") && PlotSystem.UpdateChecker.updateAvailable() && PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.CHECK_FOR_UPDATES)) { - event.getPlayer().sendMessage(Utils.ChatUtils.getInfoFormat("There is a new update for the Plot-System available. Check your console for more information!")); - event.getPlayer().playSound(event.getPlayer().getLocation(), Utils.SoundUtils.NOTIFICATION_SOUND, 1f, 1f); - } - - // Check if player has changed his name - Builder builder = Builder.byUUID(event.getPlayer().getUniqueId()); - try { - if (!builder.getName().equals(event.getPlayer().getName())) { - DatabaseConnection.createStatement("UPDATE plotsystem_builders SET name = ? WHERE uuid = ?") - .setValue(event.getPlayer().getName()).setValue(event.getPlayer().getUniqueId().toString()).executeUpdate(); - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - - // Informing player about new feedback - try { - List plots = Plot.getPlots(builder, Status.completed, Status.unfinished); - List reviewedPlots = new ArrayList<>(); - - for (Plot plot : plots) { - if (plot.isReviewed() && !plot.getReview().isFeedbackSent()) { - reviewedPlots.add(plot); - plot.getReview().setFeedbackSent(true); - } - } - - if (!reviewedPlots.isEmpty()) { - PlotUtils.ChatFormatting.sendFeedbackMessage(reviewedPlots, event.getPlayer()); - event.getPlayer().sendTitle("", "§6§l" + reviewedPlots.size() + " §a§lPlot" + (reviewedPlots.size() == 1 ? " " : "s ") + (reviewedPlots.size() == 1 ? "has" : "have") + " been reviewed!", 20, 150, 20); - } - } catch (Exception ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while trying to inform the player about his plot feedback!"), ex); - } + // Add Items + Utils.updatePlayerInventorySlots(player); - // Informing player about unfinished plots - try { - List plots = Plot.getPlots(builder, Status.unfinished); - if (!plots.isEmpty()) { - PlotUtils.ChatFormatting.sendUnfinishedPlotReminderMessage(plots, event.getPlayer()); - event.getPlayer().sendMessage(""); - } - } catch (Exception ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while trying to inform the player about his unfinished plots!"), ex); - } + // User has joined for the first time + // Adding user to the database - // Informing reviewer about new reviews - try { - if (event.getPlayer().hasPermission("plotsystem.review") && builder.isReviewer()) { - List unreviewedPlots = Plot.getPlots(builder.getAsReviewer().getCountries(), Status.unreviewed); + // Create builder if it does not exist in database. + boolean successful = DataProvider.BUILDER.addBuilderIfNotExists(player.getUniqueId(), player.getName()); + if (!successful) PlotSystem.getPlugin().getComponentLogger().error(text("BUILDER COULD NOT BE CREATED!!", RED)); - if (!unreviewedPlots.isEmpty()) { - PlotUtils.ChatFormatting.sendUnreviewedPlotsReminderMessage(unreviewedPlots, event.getPlayer()); - } - } - } catch (Exception ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while trying to inform the player about unreviewed plots!"), ex); - } + // Check if player has changed their name + Builder builder = Builder.byUUID(player.getUniqueId()); + if (!builder.getName().equals(player.getName())) { + successful = builder.setName(player.getName()); + if (!successful) PlotSystem.getPlugin().getComponentLogger().error(text("Builder name could not be updated!", RED)); + } - // Start or notify the player if he has not completed the beginner tutorial yet (only if required) - try { - if (PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.TUTORIAL_REQUIRE_BEGINNER_TUTORIAL) && - !TutorialPlot.isPlotCompleted(event.getPlayer(), TutorialCategory.BEGINNER.getId())) { - if (!event.getPlayer().hasPlayedBefore()) { - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), - () -> event.getPlayer().performCommand("tutorial " + TutorialCategory.BEGINNER.getId())); - } else { - AbstractPlotTutorial.sendTutorialRequiredMessage(event.getPlayer(), TutorialCategory.BEGINNER.getId()); - event.getPlayer().playSound(event.getPlayer().getLocation(), Utils.SoundUtils.NOTIFICATION_SOUND, 1f, 1f); - } - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - }); + Bukkit.getScheduler().runTaskAsynchronously(PlotSystem.getPlugin(), () -> sendNotices(event.getPlayer(), builder)); } @EventHandler - public void onPlayerInteractEvent(PlayerInteractEvent event) { + public void onPlayerInteractEvent(@NotNull PlayerInteractEvent event) { if (event.getAction().equals(Action.RIGHT_CLICK_BLOCK) || event.getAction().equals(Action.RIGHT_CLICK_AIR)) { if (event.getItem() != null && event.getItem().equals(CompanionMenu.getMenuItem(event.getPlayer()))) { event.getPlayer().performCommand("companion"); @@ -196,40 +109,18 @@ public void onPlayerInteractEvent(PlayerInteractEvent event) { } // Open/Close iron trap door when right-clicking - if (event.getAction().equals(Action.RIGHT_CLICK_AIR) || event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) { - if (event.getHand() != EquipmentSlot.OFF_HAND) { - if (!event.getPlayer().isSneaking()) { - if (event.getClickedBlock() != null && event.getClickedBlock().getType() == Material.IRON_TRAPDOOR) { - RegionContainer regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer(); - RegionQuery query = regionContainer.createQuery(); - - if (query.testBuild(BukkitAdapter.adapt(event.getPlayer().getLocation()), PlotSystem.DependencyManager.getWorldGuard().wrapPlayer(event.getPlayer()), Flags.INTERACT)) { - BlockState state = event.getClickedBlock().getState(); - Openable tp = (Openable) state.getBlockData(); - if (!tp.isOpen()) { - tp.setOpen(true); - event.getPlayer().playSound(event.getClickedBlock().getLocation(), "block.iron_trapdoor.open", 1f, 1f); - } else { - tp.setOpen(false); - event.getPlayer().playSound(event.getClickedBlock().getLocation(), "block.iron_trapdoor.close", 1f, 1f); - } - state.update(); - } - } - } - } - } + handleIronTrapdoorClick(event); } @EventHandler - public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) throws SQLException { + public void onPlayerInteractAtEntity(@NotNull PlayerInteractAtEntityEvent event) { if (event.getRightClicked().getType().equals(EntityType.PLAYER) && event.getHand() == EquipmentSlot.HAND) { event.getPlayer().performCommand("plots " + Builder.byUUID(event.getRightClicked().getUniqueId()).getName()); } } @EventHandler - public void onPlayerQuitEvent(PlayerQuitEvent event) { + public void onPlayerQuitEvent(@NotNull PlayerQuitEvent event) { final World w = event.getPlayer().getWorld(); DefaultPlotGenerator.playerPlotGenerationHistory.remove(event.getPlayer().getUniqueId()); @@ -249,10 +140,13 @@ public void onPlayerQuitEvent(PlayerQuitEvent event) { if (plotWorld != null && !plotWorld.getWorldName().toLowerCase(Locale.ROOT).startsWith("t-")) plotWorld.unloadWorld(false); }, 60L); + + PlotUtils.plotReminder.get(event.getPlayer().getUniqueId()).cancel(); + PlotUtils.plotReminder.remove(event.getPlayer().getUniqueId()); } @EventHandler - public void onPlayerChangedWorldEvent(PlayerChangedWorldEvent event) { + public void onPlayerChangedWorldEvent(@NotNull PlayerChangedWorldEvent event) { Bukkit.getScheduler().scheduleSyncDelayedTask(PlotSystem.getPlugin(), () -> { PlotWorld plotWorld = PlotWorld.getPlotWorldByName(event.getFrom().getName()); if (plotWorld != null) plotWorld.unloadWorld(false); @@ -262,24 +156,21 @@ public void onPlayerChangedWorldEvent(PlayerChangedWorldEvent event) { } @EventHandler - public void onInventoryClickEvent(InventoryClickEvent event) { - if (event.getCurrentItem() != null && event.getCurrentItem().equals(CompanionMenu.getMenuItem((Player) event.getWhoClicked()))) { - event.setCancelled(true); - } else if (event.getCurrentItem() != null && event.getCurrentItem().equals(ReviewMenu.getMenuItem(((Player) event.getWhoClicked()).getPlayer()))) { + public void onInventoryClickEvent(@NotNull InventoryClickEvent event) { + if (event.getCurrentItem() != null && (event.getCurrentItem().equals(CompanionMenu.getMenuItem((Player) event.getWhoClicked())) || event.getCurrentItem().equals(ReviewMenu.getMenuItem(((Player) event.getWhoClicked()))))) { event.setCancelled(true); } - if (event.getWhoClicked().getGameMode() == GameMode.CREATIVE) { - if (event.getCursor().isSimilar(CompanionMenu.getMenuItem((Player) event.getWhoClicked())) || - event.getCursor().isSimilar(ReviewMenu.getMenuItem((Player) event.getWhoClicked()))) { - event.setCursor(ItemStack.empty()); - event.setCancelled(true); - } + if (event.getWhoClicked().getGameMode() == GameMode.CREATIVE && (event.getCursor().isSimilar(CompanionMenu.getMenuItem((Player) event.getWhoClicked())) || + event.getCursor().isSimilar(ReviewMenu.getMenuItem((Player) event.getWhoClicked())))) { + event.getView().setCursor(ItemStack.empty()); + event.setCancelled(true); } + } @EventHandler - public void onlPlayerItemDropEvent(PlayerDropItemEvent event) { + public void onlPlayerItemDropEvent(@NotNull PlayerDropItemEvent event) { if (event.getItemDrop().getItemStack().equals(CompanionMenu.getMenuItem(event.getPlayer())) || event.getItemDrop().getItemStack().equals(ReviewMenu.getMenuItem(event.getPlayer()))) { event.setCancelled(true); @@ -287,7 +178,7 @@ public void onlPlayerItemDropEvent(PlayerDropItemEvent event) { } @EventHandler - public void onPlayerSwapHandItemsEvent(PlayerSwapHandItemsEvent event) { + public void onPlayerSwapHandItemsEvent(@NotNull PlayerSwapHandItemsEvent event) { if (event.getMainHandItem().equals(CompanionMenu.getMenuItem(event.getPlayer())) || event.getMainHandItem().equals(ReviewMenu.getMenuItem(event.getPlayer()))) event.setCancelled(true); if (event.getOffHandItem().equals(CompanionMenu.getMenuItem(event.getPlayer())) || @@ -295,7 +186,7 @@ public void onPlayerSwapHandItemsEvent(PlayerSwapHandItemsEvent event) { } @EventHandler(priority = EventPriority.LOWEST) - public void onPlayerChatEvent(AsyncChatEvent event) throws SQLException { + public void onPlayerChatEvent(@NotNull AsyncChatEvent event) { UUID playerUUID = event.getPlayer().getUniqueId(); if (ChatInput.awaitChatInput.containsKey(playerUUID)) { event.setCancelled(true); @@ -303,17 +194,17 @@ public void onPlayerChatEvent(AsyncChatEvent event) throws SQLException { ChatInput input = ChatInput.awaitChatInput.get(playerUUID); if (input instanceof PlayerFeedbackChatInput feedbackInput) { - feedbackInput.getReview().setFeedback(messageComp.content()); + feedbackInput.getReview().updateFeedback(messageComp.content()); ChatInput.awaitChatInput.remove(playerUUID); event.getPlayer().sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(event.getPlayer(), - LangPaths.Message.Info.UPDATED_PLOT_FEEDBACK, String.valueOf(feedbackInput.getReview().getPlotID())))); + LangPaths.Message.Info.UPDATED_PLOT_FEEDBACK, String.valueOf(feedbackInput.getReview().getPlot().getId())))); } else if (input instanceof PlayerInviteeChatInput inviteeInput) { Player player = Bukkit.getPlayer(messageComp.content()); if (player == null) { event.getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance() .get(event.getPlayer(), LangPaths.Message.Error.PLAYER_NOT_FOUND))); - } else if (!player.isOnline() || !TutorialPlot.isPlotCompleted(player, TutorialCategory.BEGINNER.getId())) { + } else if (!player.isOnline()) { event.getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance() .get(event.getPlayer(), LangPaths.Message.Error.PLAYER_IS_NOT_ONLINE))); } else if (inviteeInput.getPlot().getPlotMembers().contains(Builder.byUUID(player.getUniqueId()))) { @@ -322,6 +213,9 @@ public void onPlayerChatEvent(AsyncChatEvent event) throws SQLException { } else if (inviteeInput.getPlot().getPlotOwner().getUUID().toString().equals(player.getUniqueId().toString())) { event.getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance() .get(event.getPlayer(), LangPaths.Message.Error.PLAYER_IS_PLOT_OWNER))); + } else if (TutorialPlot.isRequiredAndInProgress(TutorialCategory.BEGINNER.getId(), player.getUniqueId())) { + event.getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance() + .get(event.getPlayer(), LangPaths.Message.Error.PLAYER_MISSING_TUTORIAL))); } else { new PlotMemberInvitation(Bukkit.getPlayer(messageComp.content()), inviteeInput.getPlot()); ChatInput.awaitChatInput.remove(playerUUID); @@ -334,7 +228,80 @@ public void onPlayerChatEvent(AsyncChatEvent event) throws SQLException { } @EventHandler - public void onLanguageChange(LanguageChangeEvent event) { + public void onLanguageChange(@NotNull LanguageChangeEvent event) { Utils.updatePlayerInventorySlots(event.getPlayer()); } + + @EventHandler + public void onPlayerClientOptionsChange(@NotNull PlayerClientOptionsChangeEvent e) { + Utils.updatePlayerInventorySlots(e.getPlayer()); + } + + private void handleIronTrapdoorClick(@NotNull PlayerInteractEvent event) { + if (!event.getAction().equals(Action.RIGHT_CLICK_AIR) && !event.getAction().equals(Action.RIGHT_CLICK_BLOCK)) return; + if (event.getHand() == EquipmentSlot.OFF_HAND) return; + if (event.getPlayer().isSneaking()) return; + if (event.getClickedBlock() == null || event.getClickedBlock().getType() != Material.IRON_TRAPDOOR) return; + + RegionContainer regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer(); + RegionQuery query = regionContainer.createQuery(); + + if (!query.testBuild(BukkitAdapter.adapt(event.getPlayer().getLocation()), DependencyManager.getWorldGuard().wrapPlayer(event.getPlayer()), Flags.INTERACT)) return; + + BlockState state = event.getClickedBlock().getState(); + Openable tp = (Openable) state.getBlockData(); + if (!tp.isOpen()) { + tp.setOpen(true); + event.getPlayer().playSound(event.getClickedBlock().getLocation(), "block.iron_trapdoor.open", 1f, 1f); + } else { + tp.setOpen(false); + event.getPlayer().playSound(event.getClickedBlock().getLocation(), "block.iron_trapdoor.close", 1f, 1f); + } + state.update(); + } + + private void sendNotices(@NotNull Player player, Builder builder) { + sendReviewNotices(player, builder); + + // Start or notify the player if he has not completed the beginner tutorial yet (only if required) + if (TutorialPlot.isRequiredAndInProgress(TutorialCategory.BEGINNER.getId(), player.getUniqueId())) { + if (!player.hasPlayedBefore()) { + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), + () -> player.performCommand("tutorial " + TutorialCategory.BEGINNER.getId())); + } else { + AbstractPlotTutorial.sendTutorialRequiredMessage(player, TutorialCategory.BEGINNER.getId()); + player.playSound(player.getLocation(), Utils.SoundUtils.NOTIFICATION_SOUND, 1f, 1f); + } + } + } + + private void sendReviewNotices(@NotNull Player player, Builder builder) { + // Informing player about new feedback + List notifications = DataProvider.REVIEW.getReviewNotifications(player.getUniqueId()); + if (!notifications.isEmpty()) { + PlotUtils.ChatFormatting.sendFeedbackMessage(notifications, player); + Component subtitleComp = LangUtil.getInstance().getComponent(player.getUniqueId(), + notifications.size() == 1 + ? LangPaths.Message.Info.PLOTS_REVIEWED_SINGULAR + : LangPaths.Message.Info.PLOTS_REVIEWED_PLURAL, + GREEN, text(notifications.size(), GOLD).decoration(BOLD, true)); + player.showTitle(Title.title( + empty(), + subtitleComp, + Title.Times.times(Duration.ofSeconds(1), Duration.ofSeconds(8), Duration.ofSeconds(1))) + ); + } + PlotUtils.informPlayerAboutUnfinishedPlots(player, builder); + PlotUtils.startUnfinishedPlotReminderTimer(player); + + // Informing reviewer about new reviews + if (player.hasPermission("plotsystem.admin") || DataProvider.BUILD_TEAM.isAnyReviewer(builder.getUUID())) { + List reviewerCityProjects = DataProvider.BUILD_TEAM.getReviewerCities(builder.getUUID()); + List unreviewedPlots = DataProvider.PLOT.getPlots(reviewerCityProjects, Status.unreviewed); + + if (!unreviewedPlots.isEmpty()) { + PlotUtils.ChatFormatting.sendUnreviewedPlotsReminderMessage(unreviewedPlots, player); + } + } + } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/DataProvider.java b/src/main/java/com/alpsbte/plotsystem/core/database/DataProvider.java new file mode 100644 index 000000000..2e557d18c --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/database/DataProvider.java @@ -0,0 +1,25 @@ +package com.alpsbte.plotsystem.core.database; + +import com.alpsbte.plotsystem.core.database.providers.BuildTeamProvider; +import com.alpsbte.plotsystem.core.database.providers.BuilderProvider; +import com.alpsbte.plotsystem.core.database.providers.CityProjectProvider; +import com.alpsbte.plotsystem.core.database.providers.CountryProvider; +import com.alpsbte.plotsystem.core.database.providers.DifficultyProvider; +import com.alpsbte.plotsystem.core.database.providers.PlotProvider; +import com.alpsbte.plotsystem.core.database.providers.ReviewProvider; +import com.alpsbte.plotsystem.core.database.providers.ServerProvider; +import com.alpsbte.plotsystem.core.database.providers.TutorialPlotProvider; + +public final class DataProvider { + public static final BuilderProvider BUILDER = new BuilderProvider(); + public static final PlotProvider PLOT = new PlotProvider(); + public static final DifficultyProvider DIFFICULTY = new DifficultyProvider(); + public static final CityProjectProvider CITY_PROJECT = new CityProjectProvider(); + public static final CountryProvider COUNTRY = new CountryProvider(); + public static final ServerProvider SERVER = new ServerProvider(); + public static final TutorialPlotProvider TUTORIAL_PLOT = new TutorialPlotProvider(); + public static final ReviewProvider REVIEW = new ReviewProvider(); + public static final BuildTeamProvider BUILD_TEAM = new BuildTeamProvider(BUILDER, CITY_PROJECT); // has to be initialized after builder and city project providers + + private DataProvider() {} +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/DatabaseConnection.java b/src/main/java/com/alpsbte/plotsystem/core/database/DatabaseConnection.java deleted file mode 100644 index 88daf8317..000000000 --- a/src/main/java/com/alpsbte/plotsystem/core/database/DatabaseConnection.java +++ /dev/null @@ -1,418 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021-2022, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.core.database; - -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.utils.io.ConfigPaths; -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; -import org.bukkit.configuration.file.FileConfiguration; - -import java.sql.*; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -import static net.kyori.adventure.text.Component.text; - -public class DatabaseConnection { - - private final static HikariConfig config = new HikariConfig(); - private static HikariDataSource dataSource; - - private static String URL; - private static String name; - private static String username; - private static String password; - - private static int connectionClosed, connectionOpened; - - public static void InitializeDatabase() throws ClassNotFoundException, SQLException { - Class.forName("org.mariadb.jdbc.Driver"); - - FileConfiguration configFile = PlotSystem.getPlugin().getConfig(); - URL = configFile.getString(ConfigPaths.DATABASE_URL); - name = configFile.getString(ConfigPaths.DATABASE_NAME); - username = configFile.getString(ConfigPaths.DATABASE_USERNAME); - password = configFile.getString(ConfigPaths.DATABASE_PASSWORD); - - createDatabase(); - - config.setJdbcUrl(URL + name); - config.setUsername(username); - config.setPassword(password); - config.addDataSourceProperty("cachePrepStmts", "true"); - config.addDataSourceProperty("prepStmtCacheSize", "250"); - config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048"); - - dataSource = new HikariDataSource(config); - - createTables(); - } - - @Deprecated - public static Connection getConnection() { - int retries = 3; - while (retries > 0) { - try { - return dataSource.getConnection(); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("Database connection failed!"), ex); - } - retries--; - } - return null; - } - - public static StatementBuilder createStatement(String sql) { - return new StatementBuilder(sql); - } - - public static void closeResultSet(ResultSet resultSet) throws SQLException { - if (resultSet.isClosed() - && resultSet.getStatement().isClosed() - && resultSet.getStatement().getConnection().isClosed()) - return; - - resultSet.close(); - resultSet.getStatement().close(); - resultSet.getStatement().getConnection().close(); - - connectionClosed++; - - if (connectionOpened > connectionClosed + 5) { - PlotSystem.getPlugin().getComponentLogger().error(text("There are multiple database connections opened. Please report this issue.")); - PlotSystem.getPlugin().getComponentLogger().error(text("Connections Open: " + (connectionOpened - connectionClosed))); - } - } - - private static void createDatabase() throws SQLException { - try (Connection con = DriverManager.getConnection(URL, username, password)) { - try (Statement statement = con.createStatement()) { - statement.executeUpdate("CREATE DATABASE IF NOT EXISTS `" + name + "`"); - } - } - } - - private static void createTables() { - try (Connection con = dataSource.getConnection()) { - for (String table : Tables.getTables()) { - Objects.requireNonNull(con).prepareStatement(table).executeUpdate(); - } - - try (ResultSet rs = con.prepareStatement("SELECT COUNT(id) FROM plotsystem_difficulties").executeQuery()) { - if (rs.next()) { - if (rs.getInt(1) == 0) { - con.prepareStatement("INSERT INTO plotsystem_difficulties (id, name) VALUES (1, 'EASY')").executeUpdate(); - con.prepareStatement("INSERT INTO plotsystem_difficulties (id, name, multiplier) VALUES (2, 'MEDIUM', 1.5)").executeUpdate(); - con.prepareStatement("INSERT INTO plotsystem_difficulties (id, name, multiplier) VALUES (3, 'HARD', 2)").executeUpdate(); - } - } - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while creating á database table"), ex); - } - } - - /** - * Returns a missing auto increment id - * - * @param table in the database - * @return smallest missing auto increment id in the table - */ - public static int getTableID(String table) { - try { - String query = "SELECT id + 1 available_id FROM $table t WHERE NOT EXISTS (SELECT * FROM $table WHERE $table.id = t.id + 1) ORDER BY id LIMIT 1" - .replace("$table", table); - try (ResultSet rs = DatabaseConnection.createStatement(query).executeQuery()) { - if (rs.next()) { - int i = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return i; - } - - DatabaseConnection.closeResultSet(rs); - return 1; - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - return 1; - } - } - - public static class StatementBuilder { - private final String sql; - private final List values = new ArrayList<>(); - - public StatementBuilder(String sql) { - this.sql = sql; - } - - public StatementBuilder setValue(Object value) { - values.add(value instanceof Boolean ? ((boolean) value ? 1 : 0) : value); - return this; - } - - public ResultSet executeQuery() throws SQLException { - Connection con = dataSource.getConnection(); - PreparedStatement ps = Objects.requireNonNull(con).prepareStatement(sql); - ResultSet rs = iterateValues(ps).executeQuery(); - - connectionOpened++; - - return rs; - } - - public void executeUpdate() throws SQLException { - try (Connection con = dataSource.getConnection()) { - try (PreparedStatement ps = Objects.requireNonNull(con).prepareStatement(sql)) { - iterateValues(ps).executeUpdate(); - } - } - } - - private PreparedStatement iterateValues(PreparedStatement ps) throws SQLException { - for (int i = 0; i < values.size(); i++) { - ps.setObject(i + 1, values.get(i)); - } - return ps; - } - } - - private static class Tables { - private final static List tables; - - public static List getTables() { - return tables; - } - - static { - tables = Arrays.asList( - // FTP Configurations - "CREATE TABLE IF NOT EXISTS `plotsystem_ftp_configurations`" + - "(" + - " `id` int NOT NULL AUTO_INCREMENT ," + - " `address` varchar(255) NOT NULL ," + - " `port` int NOT NULL ," + - " `isSFTP` tinyint NOT NULL DEFAULT 1 ," + - " `username` varchar(255) NOT NULL ," + - " `password` varchar(255) NOT NULL ," + - " `schematics_path` varchar(255) NULL ," + - "PRIMARY KEY (`id`)" + - ");", - - // Servers - "CREATE TABLE IF NOT EXISTS `plotsystem_servers`" + - "(" + - " `id` int NOT NULL AUTO_INCREMENT ," + - " `ftp_configuration_id` int NULL ," + - " `name` varchar(45) NOT NULL ," + - "PRIMARY KEY (`id`)," + - "KEY `fkIdx_30` (`ftp_configuration_id`)," + - "CONSTRAINT `FK_29` FOREIGN KEY `fkIdx_30` (`ftp_configuration_id`) REFERENCES `plotsystem_ftp_configurations` (`id`)" + - ");", - - // Countries - "CREATE TABLE IF NOT EXISTS `plotsystem_countries`" + - "(" + - " `id` int NOT NULL AUTO_INCREMENT ," + - " `server_id` int NOT NULL ," + - " `name` varchar(45) NOT NULL ," + - " `head_id` varchar(10) NULL ," + - "PRIMARY KEY (`id`)," + - "KEY `fkIdx_38` (`server_id`)," + - "CONSTRAINT `FK_37` FOREIGN KEY `fkIdx_38` (`server_id`) REFERENCES `plotsystem_servers` (`id`)" + - ");", - "ALTER TABLE plotsystem_countries ADD COLUMN IF NOT EXISTS `continent` enum('europe', 'asia', 'africa', 'oceania', 'south america', 'north america') NOT NULL;", - - // City Projects - "CREATE TABLE IF NOT EXISTS `plotsystem_city_projects`" + - "(" + - " `id` int NOT NULL AUTO_INCREMENT ," + - " `country_id` int NOT NULL ," + - " `name` varchar(45) NOT NULL ," + - " `description` varchar(255) NOT NULL ," + - " `visible` tinyint DEFAULT 0 ," + - "PRIMARY KEY (`id`)," + - "KEY `fkIdx_44` (`country_id`)," + - "CONSTRAINT `FK_43` FOREIGN KEY `fkIdx_44` (`country_id`) REFERENCES `plotsystem_countries` (`id`)" + - ");", - - // Builders - "CREATE TABLE IF NOT EXISTS `plotsystem_builders`" + - "(" + - " `uuid` varchar(36) NOT NULL COLLATE 'utf8mb4_general_ci'," + - " `name` varchar(16) NOT NULL ," + - " `score` int DEFAULT 0 ," + - " `completed_plots` int DEFAULT 0 ," + - " `first_slot` int NULL ," + - " `second_slot` int NULL ," + - " `third_slot` int NULL ," + - "PRIMARY KEY (`uuid`)" + - ");", - "ALTER TABLE plotsystem_builders ADD COLUMN IF NOT EXISTS lang varchar(5) NULL;", - "ALTER TABLE plotsystem_builders ADD COLUMN IF NOT EXISTS setting_plot_type int DEFAULT 1;", - - // Reviews - "CREATE TABLE IF NOT EXISTS `plotsystem_reviews`" + - "(" + - " `id` int NOT NULL AUTO_INCREMENT ," + - " `reviewer_uuid` varchar(36) NOT NULL COLLATE 'utf8mb4_general_ci'," + - " `rating` varchar(45) NOT NULL ," + - " `feedback` varchar(420) NOT NULL ," + - " `review_date` datetime NOT NULL ," + - " `sent` tinyint DEFAULT 0 ," + - "PRIMARY KEY (`id`)," + - "KEY `fkIdx_73` (`reviewer_uuid`)," + - "CONSTRAINT `FK_72` FOREIGN KEY `fkIdx_73` (`reviewer_uuid`) REFERENCES `plotsystem_builders` (`uuid`)" + - ");", - - // Difficulties - "CREATE TABLE IF NOT EXISTS `plotsystem_difficulties`" + - "(" + - " `id` int NOT NULL AUTO_INCREMENT ," + - " `name` varchar(45) NOT NULL ," + - " `multiplier` double DEFAULT 1 ," + - " `score_requirment` int DEFAULT 0 ," + - "PRIMARY KEY (`id`)" + - ");", - - // Plots - "CREATE TABLE IF NOT EXISTS `plotsystem_plots`" + - "(" + - " `id` int NOT NULL AUTO_INCREMENT ," + - " `city_project_id` int NOT NULL ," + - " `difficulty_id` int NOT NULL ," + - " `review_id` int NULL ," + - " `owner_uuid` varchar(36) NULL COLLATE 'utf8mb4_general_ci'," + - " `member_uuids` varchar(110) NULL ," + - " `status` enum ('unclaimed', 'unfinished', 'unreviewed', 'completed') NOT NULL DEFAULT 'unclaimed' ," + - " `mc_coordinates` varchar(255) NOT NULL ," + - " `score` int NULL ," + - " `last_activity` datetime NULL ," + - " `create_date` datetime NOT NULL ," + - " `create_player` varchar(36) NOT NULL ," + - " `pasted` tinyint DEFAULT 0 ," + - "PRIMARY KEY (`id`)," + - "KEY `fkIdx_57` (`city_project_id`)," + - "CONSTRAINT `FK_56` FOREIGN KEY `fkIdx_57` (`city_project_id`) REFERENCES `plotsystem_city_projects` (`id`)," + - "KEY `fkIdx_60` (`owner_uuid`)," + - "CONSTRAINT `FK_59` FOREIGN KEY `fkIdx_60` (`owner_uuid`) REFERENCES `plotsystem_builders` (`uuid`)," + - "KEY `fkIdx_70` (`review_id`)," + - "CONSTRAINT `FK_69` FOREIGN KEY `fkIdx_70` (`review_id`) REFERENCES `plotsystem_reviews` (`id`)," + - "KEY `fkIdx_82` (`difficulty_id`)," + - "CONSTRAINT `FK_81` FOREIGN KEY `fkIdx_82` (`difficulty_id`) REFERENCES `plotsystem_difficulties` (`id`)" + - ");", - "ALTER TABLE plotsystem_plots ADD COLUMN IF NOT EXISTS outline longtext NULL DEFAULT NULL;", - "ALTER TABLE plotsystem_plots ADD COLUMN IF NOT EXISTS type int NOT NULL DEFAULT 1;", - "ALTER TABLE plotsystem_plots ADD COLUMN IF NOT EXISTS version DOUBLE NULL DEFAULT NULL;", - - // API Keys - "CREATE TABLE IF NOT EXISTS `plotsystem_api_keys`" + - "(" + - " `id` int NOT NULL AUTO_INCREMENT ," + - " `api_key` varchar(32) NOT NULL ," + - " `created_at` timestamp NOT NULL DEFAULT current_timestamp()," + - "PRIMARY KEY (`id`)" + - ");", - - // Build-Teams - "CREATE TABLE IF NOT EXISTS `plotsystem_buildteams` (" + - "`id` INT(11) NOT NULL AUTO_INCREMENT," + - "`name` VARCHAR(45) NOT NULL COLLATE 'utf8mb4_general_ci'," + - "`api_key_id` INT(11) NULL DEFAULT NULL," + - "PRIMARY KEY (`id`) USING BTREE," + - "KEY `FK_132` (`api_key_id`)," + - "CONSTRAINT `FK_130` FOREIGN KEY `FK_132` (`api_key_id`) REFERENCES `plotsystem_api_keys` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT" + - ")" + - "COLLATE='utf8mb4_general_ci'" + - "ENGINE=InnoDB" + - ";", - - // Build-Team has Countries - "CREATE TABLE IF NOT EXISTS `plotsystem_buildteam_has_countries` (" + - "`id` INT(11) NOT NULL AUTO_INCREMENT," + - "`country_id` INT(11) NOT NULL," + - "`buildteam_id` INT(11) NOT NULL," + - "PRIMARY KEY (`id`) USING BTREE," + - "KEY `FK_115` (`buildteam_id`)," + - "KEY `FK_118` (`country_id`)," + - "CONSTRAINT `FK_113` FOREIGN KEY `FK_115` (`buildteam_id`) REFERENCES `plotsystem_buildteams` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT," + - "CONSTRAINT `FK_116` FOREIGN KEY `FK_118` (`country_id`) REFERENCES `plotsystem_countries` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT" + - ")" + - "COLLATE='utf8mb4_general_ci'" + - "ENGINE=InnoDB" + - ";", - - // Builder Is Reviewer - "CREATE TABLE IF NOT EXISTS `plotsystem_builder_is_reviewer` (" + - "`id` INT(11) NOT NULL AUTO_INCREMENT," + - "`builder_uuid` VARCHAR(36) NOT NULL COLLATE 'utf8mb4_general_ci'," + - "`buildteam_id` INT(11) NOT NULL," + - "PRIMARY KEY (`id`) USING BTREE," + - "INDEX `FK_138` (`builder_uuid`) USING BTREE," + - "INDEX `FK_141` (`buildteam_id`) USING BTREE," + - "CONSTRAINT `FK_136` FOREIGN KEY (`builder_uuid`) REFERENCES `plotsystem_builders` (`uuid`) ON UPDATE RESTRICT ON DELETE RESTRICT," + - "CONSTRAINT `FK_139` FOREIGN KEY (`buildteam_id`) REFERENCES `plotsystem_buildteams` (`id`) ON UPDATE RESTRICT ON DELETE RESTRICT" + - ")" + - "COLLATE='utf8mb4_general_ci'" + - "ENGINE=InnoDB" + - ";", - - // Payouts - "CREATE TABLE IF NOT EXISTS `plotsystem_payouts` (" + - "`id` INT(11) NOT NULL AUTO_INCREMENT," + - "`timeframe` ENUM('DAILY','WEEKLY','MONTHLY','YEARLY') NOT NULL COLLATE 'utf8mb4_general_ci'," + - "`position` INT(11) NOT NULL COMMENT 'position on the leaderboard for this timeframe'," + - "`payout_amount` VARCHAR(100) NOT NULL COLLATE 'utf8mb4_general_ci'," + - "PRIMARY KEY (`id`) USING BTREE" + - ")" + - "COLLATE='utf8mb4_general_ci'" + - "ENGINE=InnoDB" + - ";", - - // Tutorial Plots - "CREATE TABLE IF NOT EXISTS `plotsystem_plots_tutorial` (" + - "`id` INT(11) NOT NULL AUTO_INCREMENT," + - "`player_uuid` VARCHAR(36) NOT NULL COLLATE 'utf8mb4_general_ci'," + - "`tutorial_id` INT(11) NOT NULL," + - "`stage_id` INT(11) NOT NULL DEFAULT '0'," + - "`is_completed` TINYINT(4) NOT NULL DEFAULT '0'," + - "`create_date` DATETIME NOT NULL DEFAULT current_timestamp()," + - "`last_stage_complete_date` DATETIME NULL DEFAULT NULL," + - "`complete_date` DATETIME NULL DEFAULT NULL," + - "PRIMARY KEY (`id`) USING BTREE," + - "INDEX `FK_142` (`player_uuid`) USING BTREE," + - "CONSTRAINT `FK_12` FOREIGN KEY (`player_uuid`) REFERENCES `plotsystem_builders` (`uuid`) ON UPDATE RESTRICT ON DELETE RESTRICT" + - ")" + - "COLLATE='utf8mb4_general_ci'" + - "ENGINE=InnoDB" + - ";" - ); - } - } -} diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/providers/BuildTeamProvider.java b/src/main/java/com/alpsbte/plotsystem/core/database/providers/BuildTeamProvider.java new file mode 100644 index 000000000..f9ebdec22 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/database/providers/BuildTeamProvider.java @@ -0,0 +1,145 @@ +package com.alpsbte.plotsystem.core.database.providers; + +import com.alpsbte.alpslib.io.database.SqlHelper; +import com.alpsbte.plotsystem.core.system.BuildTeam; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.CityProject; +import com.alpsbte.plotsystem.utils.Utils; +import org.jetbrains.annotations.NotNull; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class BuildTeamProvider { + private static final List BUILD_TEAMS = new ArrayList<>(); + private final CityProjectProvider cityProjectProvider; + + public BuildTeamProvider(BuilderProvider builderProvider, CityProjectProvider cityProjectProvider) { + this.cityProjectProvider = cityProjectProvider; + + String qBuildTeams = "SELECT build_team_id, name FROM build_team;"; + // cache all build teams + Utils.handleSqlException(() -> SqlHelper.runQuery(qBuildTeams, ps -> { + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + int buildTeamId = rs.getInt(1); + List cityProjects = cityProjectProvider.getCityProjectsByBuildTeam(buildTeamId); + List reviewers = builderProvider.getReviewersByBuildTeam(buildTeamId); + BUILD_TEAMS.add(new BuildTeam(buildTeamId, rs.getString(2), cityProjects, reviewers)); + } + })); + } + + public Optional getBuildTeam(int id) { + return BUILD_TEAMS.stream().filter(b -> b.getId() == id).findFirst(); + } + + public List getBuildTeamsByReviewer(@NotNull UUID reviewerUUID) { + var l = BUILD_TEAMS.stream() + .filter(b -> b.getReviewers().stream() + .anyMatch(r -> r.getUUID().equals(reviewerUUID))) + .toList(); + if (!l.isEmpty()) return l; + + String qIdByUuid = "SELECT build_team_id FROM build_team_has_reviewer WHERE uuid = ?;"; + return Utils.handleSqlException(new ArrayList<>(), () -> SqlHelper.runQuery(qIdByUuid, ps -> { + ps.setString(1, reviewerUUID.toString()); + ResultSet rs = ps.executeQuery(); + List buildTeams = new ArrayList<>(); + while (rs.next()) { + Optional buildTeam = getBuildTeam(rs.getInt(1)); + if (buildTeam.isEmpty()) continue; + buildTeams.add(buildTeam.get()); + } + return buildTeams; + })); + } + + public List getBuildTeams() { + return BUILD_TEAMS; + } + + public boolean addBuildTeam(String name) { + if (BUILD_TEAMS.stream().anyMatch(b -> b.getName().equals(name))) return false; + + String qInsert = "INSERT INTO build_team (name) VALUES (?);"; + String qByName = "SELECT build_team_id FROM build_team WHERE name = ?;"; + // get the last inserted build team id + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qInsert, ps -> { + ps.setString(1, name); + boolean result = ps.executeUpdate() > 0; + + if (result) { + Utils.handleSqlException(() -> SqlHelper.runQuery(qByName, ps.getConnection(), ps2 -> { + ps2.setString(1, name); + ResultSet rs = ps2.executeQuery(); + rs.next(); // get the last inserted build team id + BUILD_TEAMS.add(new BuildTeam(rs.getInt(1), name)); + return null; // no need to return anything + })); + } + return result; + }))); + } + + public boolean removeBuildTeam(int id) { + Optional cachedBuildTeam = getBuildTeam(id); + if (cachedBuildTeam.isEmpty()) return false; + + String qDeleteById = "DELETE FROM build_team WHERE build_team_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qDeleteById, ps -> { + ps.setInt(1, id); + boolean result = ps.executeUpdate() > 0; + if (result) BUILD_TEAMS.remove(cachedBuildTeam.get()); + return result; + }))); + } + + public boolean setBuildTeamName(int id, String newName) { + String qSetNameById = "UPDATE build_team SET name = ? WHERE build_team_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetNameById, ps -> { + ps.setString(1, newName); + ps.setInt(2, id); + return ps.executeUpdate() > 0; + }))); + } + + public boolean addReviewer(int id, String reviewerUUID) { + String qInsertReviewer = "INSERT INTO build_team_has_reviewer (build_team_id, uuid) VALUES (?, ?);"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runInsertQuery(qInsertReviewer, ps -> { + ps.setInt(1, id); + ps.setString(2, reviewerUUID); + return ps.executeUpdate() > 0; + }))); + } + + public boolean removeReviewer(int id, String reviewerUUID) { + String qDeleteReviewer = "DELETE FROM build_team_has_reviewer WHERE build_team_id = ? AND uuid = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qDeleteReviewer, ps -> { + ps.setInt(1, id); + ps.setString(2, reviewerUUID); + return ps.executeUpdate() > 0; + }))); + } + + public boolean isAnyReviewer(@NotNull UUID reviewerUUID) { + return BUILD_TEAMS.stream() + .anyMatch(bt -> bt.getReviewers().stream() + .anyMatch(r -> r.getUUID().equals(reviewerUUID)) + ); + } + + public List getReviewerCities(UUID reviewerUUID) { + List buildTeams = BUILD_TEAMS.stream().filter(b + -> b.getReviewers().stream().anyMatch(r -> r.getUUID().equals(reviewerUUID))).toList(); + List cities = new ArrayList<>(); + + for (BuildTeam buildTeam : buildTeams) { + cities.addAll(cityProjectProvider.getCityProjectsByBuildTeam(buildTeam.getId())); + } + return cities; + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/providers/BuilderProvider.java b/src/main/java/com/alpsbte/plotsystem/core/database/providers/BuilderProvider.java new file mode 100644 index 000000000..ad2d65780 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/database/providers/BuilderProvider.java @@ -0,0 +1,253 @@ +package com.alpsbte.plotsystem.core.database.providers; + +import com.alpsbte.alpslib.io.database.SqlHelper; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.holograms.leaderboards.LeaderboardTimeframe; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.enums.Slot; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class BuilderProvider { + protected static final Map BUILDERS = new HashMap<>(); + private static final String Q_SLOTS_BY_UUID = "SELECT first_slot, second_slot, third_slot FROM builder WHERE uuid = ?;"; + + public Builder getBuilderByUUID(UUID uuid) { + if (BUILDERS.containsKey(uuid)) return BUILDERS.get(uuid); + + String qByUuid = "SELECT name, score, first_slot, second_slot, third_slot, plot_type FROM builder WHERE uuid = ?;"; + return Utils.handleSqlException(null, () -> SqlHelper.runQuery(qByUuid, ps -> { + ps.setString(1, uuid.toString()); + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + Builder builder = new Builder(uuid, rs.getString(1), rs.getInt(2), rs.getInt(3), + rs.getInt(4), rs.getInt(5), rs.getInt(6)); + BUILDERS.put(uuid, builder); // cache the builder + return builder; + } + return null; + })); + } + + public Builder getBuilderByName(String name) { + for (var i : BUILDERS.values()) { + if (i.getName().equalsIgnoreCase(name)) { + return i; // return cached builder if name matches + } + } + + String qUuidByName = "SELECT uuid FROM builder WHERE name = ?;"; + return Utils.handleSqlException(null, () -> SqlHelper.runQuery(qUuidByName, ps -> { + ps.setString(1, name); + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + String uuid = rs.getString(1); + if (uuid != null) return getBuilderByUUID(UUID.fromString(uuid)); + } + return null; + })); + } + + public boolean addBuilderIfNotExists(UUID uuid, String name) { + if (BUILDERS.containsKey(uuid)) return true; + + String qExistsByUuid = "SELECT 1 FROM builder WHERE uuid = ?;"; + String qInsert = "INSERT INTO builder (uuid, name, plot_type) VALUES (?, ?, 1);"; + // builder already exists + // insert new builder + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qExistsByUuid, ps -> { + ps.setString(1, uuid.toString()); + ResultSet rs = ps.executeQuery(); + if (rs.next()) return true; // builder already exists + + return SqlHelper.runQuery(qInsert, ps.getConnection(), insertStmt -> { + insertStmt.setString(1, uuid.toString()); + insertStmt.setString(2, name); + return insertStmt.executeUpdate() > 0; // insert new builder + }); + }))); + } + + public boolean setName(@NotNull UUID uuid, String name) { + String qSetNameByUuid = "UPDATE builder SET name = ? WHERE uuid = ?;"; + // update builder name + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetNameByUuid, ps -> { + ps.setString(1, name); + ps.setString(2, uuid.toString()); + return ps.executeUpdate() > 0; // update builder name + }))); + } + + public boolean addScore(@NotNull UUID uuid, int score) { + String qIncreaseScoreByUuid = "UPDATE builder b SET score = (b.score + ?) WHERE uuid = ?;"; + // increase score by given value + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qIncreaseScoreByUuid, ps -> { + ps.setInt(1, score); + ps.setString(2, uuid.toString()); + return ps.executeUpdate() > 0; // increase score by given value + }))); + } + + public boolean setSlot(UUID uuid, int plotID, @NotNull Slot slot) { + String qBuilderSetSlotByUuid = "UPDATE builder b SET " + slot.name().toLowerCase() + "_slot = " + (plotID > 0 ? "?" : "DEFAULT(first_slot)") + " WHERE uuid = ?;"; + // update builder slot + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qBuilderSetSlotByUuid, ps -> { + if (plotID > 0) ps.setInt(1, plotID); + ps.setString(plotID > 0 ? 2 : 1, uuid.toString()); + return ps.executeUpdate() > 0; // update builder slot + }))); + } + + public boolean setPlotType(@NotNull UUID uuid, int plotTypeId) { + String qSetPlotTypeByUuid = "UPDATE builder b SET plot_type = ? WHERE uuid = ?;"; + // update plot type + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetPlotTypeByUuid, ps -> { + ps.setInt(1, plotTypeId); + ps.setString(2, uuid.toString()); + return ps.executeUpdate() > 0; // update plot type + }))); + } + + public int getCompletedBuildsCount(@NotNull UUID uuid) { + String qBuilderCompletedBuildsCountByUuid = "SELECT COUNT(p.plot_id) AS completed_plots FROM plot p INNER JOIN builder_is_plot_member " + + "bipm ON p.plot_id = bipm.plot_id WHERE p.status = 'completed' AND (p.owner_uuid = ? OR bipm.uuid = ?);"; + Integer result = Utils.handleSqlException(0, () -> SqlHelper.runQuery(qBuilderCompletedBuildsCountByUuid, ps -> { + ps.setString(1, uuid.toString()); + ps.setString(2, uuid.toString()); + ResultSet rs = ps.executeQuery(); + if (rs.next()) return rs.getInt(1); + return 0; + })); + return result != null ? result : 0; + } + + public Slot getFreeSlot(@NotNull UUID uuid) { + return Utils.handleSqlException(null, () -> SqlHelper.runQuery(Q_SLOTS_BY_UUID, ps -> { + ps.setString(1, uuid.toString()); + ResultSet rs = ps.executeQuery(); + if (!rs.next()) return null; // no slots found + for (int i = 1; i <= 3; i++) { + if (rs.getString(i) == null) return Slot.values()[i - 1]; // return first free slot + } + return null; // no free slots found + })); + } + + public Slot getSlot(@NotNull UUID uuid, int plotId) { + return Utils.handleSqlException(null, () -> SqlHelper.runQuery(Q_SLOTS_BY_UUID, ps -> { + ps.setString(1, uuid.toString()); + ResultSet rs = ps.executeQuery(); + if (!rs.next()) return null; // no slots found + if (rs.getInt(1) == plotId) return Slot.FIRST; // first slot + if (rs.getInt(2) == plotId) return Slot.SECOND; // second slot + if (rs.getInt(3) == plotId) return Slot.THIRD; // third slot + return null; // no matching slot found + })); + } + + public boolean canNotReviewPlot(@NotNull UUID uuid, Plot plot) { + return DataProvider.BUILD_TEAM.getReviewerCities(uuid).stream().noneMatch(c -> c.getId().equals(plot.getCityProject().getId())); + } + + public List getReviewersByBuildTeam(int buildTeamId) { + String qReviewerUuidByBtId = "SELECT uuid FROM build_team_has_reviewer WHERE build_team_id = ?;"; + return Utils.handleSqlException(new ArrayList<>(), () -> SqlHelper.runQuery(qReviewerUuidByBtId, ps -> { + ps.setInt(1, buildTeamId); + ResultSet rs = ps.executeQuery(); + List builders = new ArrayList<>(); + while (rs.next()) { + Builder builder = getBuilderByUUID(UUID.fromString(rs.getString(1))); + if (builder != null) builders.add(builder); + } + return builders; + })); + } + + /** + * Retrieves the leaderboard entries for all players within a specified timeframe, including their names and scores. + * + * @param sortBy the timeframe used to filter leaderboard data (e.g., daily, weekly, etc.). + * @return provides a map of player names and their scores, or an empty map if no data is found. + */ + public Map getLeaderboardEntries(LeaderboardTimeframe sortBy) { + return Utils.handleSqlException(new LinkedHashMap<>(), () -> SqlHelper.runQuery(getLeaderboardQuery(sortBy), ps -> { + ResultSet rs = ps.executeQuery(); + LinkedHashMap playerEntries = new LinkedHashMap<>(); + while (rs.next()) { + playerEntries.put(rs.getString(1), rs.getInt(2)); + } + return playerEntries; + })); + } + + /** + * Constructs a SQL query to retrieve leaderboard data by sorting based on a given timeframe. + * + *

This query returns the top leaderboard entries ordered by the score + * within the specified timeframe.

+ * + * @param sortBy the timeframe used to filter entries. Determines the minimum date for reviews + * (e.g., daily, weekly, monthly, yearly). + * @return the constructed SQL query as a {@code String}. + */ + @Contract(pure = true) + private static @NotNull String getLeaderboardQuery(@NotNull LeaderboardTimeframe sortBy) { + String minimumDate = switch (sortBy) { + case DAILY -> "(NOW() - INTERVAL 1 DAY)"; + case WEEKLY -> "(NOW() - INTERVAL 1 WEEK)"; + case MONTHLY -> "(NOW() - INTERVAL 1 MONTH)"; + case YEARLY -> "(NOW() - INTERVAL 1 YEAR)"; + default -> null; + }; + + return "WITH latest_reviews AS ( " + + " SELECT pr.* " + + " FROM plot_review pr " + + " INNER JOIN ( " + + " SELECT plot_id, MAX(review_date) AS latest_review_date " + + " FROM plot_review " + + " GROUP BY plot_id " + + " ) latest ON pr.plot_id = latest.plot_id AND pr.review_date = latest.latest_review_date " + + "), " + + "plot_member_counts AS ( " + + " SELECT plot_id, COUNT(*) AS member_count " + + " FROM builder_is_plot_member " + + " GROUP BY plot_id " + + "), " + + "all_builders AS ( " + + " SELECT " + + " p.owner_uuid AS builder_uuid, " + + " p.plot_id " + + " FROM plot p " + + " WHERE p.status = 'completed' " + + " UNION ALL " + + " SELECT " + + " bipm.uuid AS builder_uuid, " + + " bipm.plot_id " + + " FROM builder_is_plot_member bipm " + + " JOIN plot p ON p.plot_id = bipm.plot_id " + + " WHERE p.status = 'completed' " + + ") " + + "SELECT b.name, SUM( " + + " IF(pmc.member_count IS NULL OR pmc.member_count = 0, lr.score, FLOOR(lr.score / (pmc.member_count + 1))) " + + ") AS total_score " + + "FROM all_builders ab " + + "JOIN builder b ON b.uuid = ab.builder_uuid " + + "JOIN latest_reviews lr ON lr.plot_id = ab.plot_id " + + "LEFT JOIN plot_member_counts pmc ON pmc.plot_id = ab.plot_id " + + (minimumDate != null ? "WHERE lr.review_date BETWEEN " + minimumDate + " AND NOW() " : "") + + "GROUP BY b.name " + + "ORDER BY total_score DESC, b.name " + + "LIMIT 10;"; + } +} \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/providers/CityProjectProvider.java b/src/main/java/com/alpsbte/plotsystem/core/database/providers/CityProjectProvider.java new file mode 100644 index 000000000..2030e3dee --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/database/providers/CityProjectProvider.java @@ -0,0 +1,105 @@ +package com.alpsbte.plotsystem.core.database.providers; + +import com.alpsbte.alpslib.io.database.SqlHelper; +import com.alpsbte.plotsystem.core.system.CityProject; +import com.alpsbte.plotsystem.utils.Utils; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class CityProjectProvider { + protected static final List CITY_PROJECTS = new ArrayList<>(); + + public CityProjectProvider() { + String qCityProjects = "SELECT city_project_id, country_code, server_name, is_visible, build_team_id FROM city_project;"; + Utils.handleSqlException(() -> SqlHelper.runQuery(qCityProjects, ps -> { + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + CITY_PROJECTS.add(new CityProject(rs.getString(1), // cache all city projects + rs.getString(2), rs.getString(3), rs.getBoolean(4), rs.getInt(5))); + } + })); + } + + public Optional getById(String id) { + return CITY_PROJECTS.stream().filter(c -> c.getId().equals(id)).findFirst(); + } + + public List getByCountryCode(String countryCode, boolean onlyVisible) { + return CITY_PROJECTS.stream().filter(c -> (!onlyVisible || c.isVisible()) && + c.getCountry().getCode().equals(countryCode)).toList(); + } + + public List get(boolean onlyVisible) { + return CITY_PROJECTS.stream().filter(c -> !onlyVisible || c.isVisible()).toList(); + } + + public List getCityProjectsByBuildTeam(int buildTeamId) { + String qIdByBtId = "SELECT city_project_id FROM city_project WHERE build_team_id = ?;"; + return Utils.handleSqlException(new ArrayList<>(), () -> SqlHelper.runQuery(qIdByBtId, ps -> { + ps.setInt(1, buildTeamId); + ResultSet rs = ps.executeQuery(); + List cityProjects = new ArrayList<>(); + while (rs.next()) { + Optional city = getById(rs.getString(1)); + city.ifPresent(cityProjects::add); + } + return cityProjects; + })); + } + + public boolean add(String id, int buildTeamId, String countryCode, String serverName) { + if (getById(id).isPresent()) return true; + + String qInsert = "INSERT INTO city_project (city_project_id, build_team_id, country_code, server_name) VALUES (?, ?, ?, ?);"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qInsert, ps -> { + ps.setString(1, id); + ps.setInt(2, buildTeamId); + ps.setString(3, countryCode); + ps.setString(4, serverName); + boolean result = ps.executeUpdate() > 0; + if (result) CITY_PROJECTS.add(new CityProject(id, countryCode, serverName, true, buildTeamId)); + return result; + }))); + } + + public boolean remove(String id) { + Optional cityProject = getById(id); + String qDelete = "DELETE FROM city_project WHERE city_project_id = ?;"; + return cityProject.filter(project -> Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qDelete, ps -> { + ps.setString(1, id); + boolean result = ps.executeUpdate() > 0; + if (result) CITY_PROJECTS.remove(project); + return result; + })))).isPresent(); + } + + public boolean setVisibility(String id, boolean isVisible) { + String qUpdateVisible = "UPDATE city_project SET is_visible = ? WHERE city_project_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qUpdateVisible, ps -> { + ps.setBoolean(1, isVisible); + ps.setString(2, id); + return ps.executeUpdate() > 0; + }))); + } + + public boolean setServer(String id, String serverName) { + String qUpdateServerName = "UPDATE city_project SET server_name = ? WHERE city_project_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qUpdateServerName, ps -> { + ps.setString(1, serverName); + ps.setString(2, id); + return ps.executeUpdate() > 0; + }))); + } + + public boolean setBuildTeam(String id, int buildTeamId) { + String qUpdateBuildTeamId = "UPDATE city_project SET build_team_id = ? WHERE city_project_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qUpdateBuildTeamId, ps -> { + ps.setInt(1, buildTeamId); + ps.setString(2, id); + return ps.executeUpdate() > 0; + }))); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/providers/CountryProvider.java b/src/main/java/com/alpsbte/plotsystem/core/database/providers/CountryProvider.java new file mode 100644 index 000000000..df759ce1c --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/database/providers/CountryProvider.java @@ -0,0 +1,79 @@ +package com.alpsbte.plotsystem.core.database.providers; + +import com.alpsbte.alpslib.io.database.SqlHelper; +import com.alpsbte.plotsystem.core.system.Country; +import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.enums.Continent; +import org.jetbrains.annotations.Nullable; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +public class CountryProvider { + protected static final List COUNTRIES = new ArrayList<>(); + + public CountryProvider() { + String qAll = "SELECT country_code, continent, material, custom_model_data FROM country;"; + Utils.handleSqlException(() -> SqlHelper.runQuery(qAll, ps -> { + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + Continent continent = Continent.fromDatabase(rs.getString(2)); + Country country = new Country(rs.getString(1), continent, rs.getString(3), + rs.getString(4)); + COUNTRIES.add(country); // cache all countries + } + })); + } + + public List getCountries() { + return COUNTRIES; + } + + public List getCountriesByContinent(Continent continent) { + return COUNTRIES.stream().filter(c -> c.getContinent() == continent).toList(); + } + + public Optional getCountryByCode(String code) { + return COUNTRIES.stream().filter(c -> c.getCode().equals(code)).findFirst(); + } + + public boolean setMaterialAndCustomModelData(String code, String material, @Nullable String customModelData) { + String qSetItem = "UPDATE country SET material = ?, custom_model_data = ? WHERE country_code = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetItem, ps -> { + ps.setString(1, material); + ps.setString(2, customModelData); + ps.setString(3, code); + return ps.executeUpdate() > 0; + }))); + } + + public boolean addCountry(String code, Continent continent, String material, @Nullable String customModelData) { + if (getCountryByCode(code).isPresent()) return true; + + String qInsert = "INSERT INTO country (country_code, continent, material, custom_model_data) VALUES (?, ?, ?, ?);"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qInsert, ps -> { + ps.setString(1, code); + ps.setString(2, continent.databaseEnum); + ps.setString(3, material); + ps.setString(4, customModelData); + boolean result = ps.executeUpdate() > 0; + if (result) COUNTRIES.add(new Country(code, continent, material, customModelData)); + return result; + }))); + } + + public boolean removeCountry(String code) { + Optional cachedCountry = getCountryByCode(code); + if (cachedCountry.isEmpty()) return false; + + String qDelete = "DELETE FROM country WHERE country_code = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qDelete, ps -> { + ps.setString(1, code); + boolean result = ps.executeUpdate() > 0; + if (result) COUNTRIES.remove(cachedCountry.get()); + return result; + }))); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/providers/DifficultyProvider.java b/src/main/java/com/alpsbte/plotsystem/core/database/providers/DifficultyProvider.java new file mode 100644 index 000000000..95d6d2914 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/database/providers/DifficultyProvider.java @@ -0,0 +1,79 @@ +package com.alpsbte.plotsystem.core.database.providers; + +import com.alpsbte.alpslib.io.database.SqlHelper; +import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.Difficulty; +import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.enums.PlotDifficulty; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +import static net.kyori.adventure.text.Component.text; + +public class DifficultyProvider { + protected static final List DIFFICULTIES = new ArrayList<>(); + + public DifficultyProvider() { + // cache all difficulties + String qAll = "SELECT difficulty_id, multiplier, score_requirement FROM plot_difficulty;"; + Utils.handleSqlException(() -> SqlHelper.runQuery(qAll, ps -> { + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + String id = rs.getString(1); + double multiplier = rs.getDouble(2); + int scoreRequirement = rs.getInt(3); + + Difficulty difficulty = new Difficulty(PlotDifficulty.valueOf(id), id, multiplier, scoreRequirement); + DIFFICULTIES.add(difficulty); // cache all difficulties + } + })); + } + + public List getDifficulties() { + return DIFFICULTIES; + } + + public Optional getDifficultyById(String id) { + return DIFFICULTIES.stream().filter(d -> d.getID().equalsIgnoreCase(id)).findAny(); + } + + public Optional getDifficultyByEnum(PlotDifficulty difficulty) { + if (difficulty == null) return Optional.empty(); + return DIFFICULTIES.stream().filter(d -> d.getID().equalsIgnoreCase(difficulty.name())).findFirst(); + } + + public boolean setMultiplier(String id, double multiplier) { + String qSetMulti = "UPDATE plot_difficulty SET multiplier = ? WHERE difficulty_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetMulti, ps -> { + ps.setDouble(1, multiplier); + ps.setString(2, id); + return ps.executeUpdate() > 0; + }))); + } + + public boolean setScoreRequirement(String id, int scoreRequirement) { + String qSetScoreRequirement = "UPDATE plot_difficulty SET score_requirement = ? WHERE difficulty_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetScoreRequirement, ps -> { + ps.setInt(1, scoreRequirement); + ps.setString(2, id); + return ps.executeUpdate() > 0; + }))); + } + + public boolean builderMeetsRequirements(Builder builder, PlotDifficulty plotDifficulty) { + Optional cachedDifficulty = getDifficultyByEnum(plotDifficulty); + if (cachedDifficulty.isEmpty()) { + PlotSystem.getPlugin().getComponentLogger().error(text("No database entry for difficulty " + + plotDifficulty.toString() + " was found!")); + return false; + } + + int playerScore = builder.getScore(); + int scoreRequirement = cachedDifficulty.get().getScoreRequirement(); + return playerScore >= scoreRequirement; + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/providers/PlotProvider.java b/src/main/java/com/alpsbte/plotsystem/core/database/providers/PlotProvider.java new file mode 100644 index 000000000..c06507f41 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/database/providers/PlotProvider.java @@ -0,0 +1,268 @@ +package com.alpsbte.plotsystem.core.database.providers; + +import com.alpsbte.alpslib.io.database.SqlHelper; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.CityProject; +import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.core.system.plot.utils.PlotType; +import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.enums.PlotDifficulty; +import com.alpsbte.plotsystem.utils.enums.Status; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.sql.Date; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class PlotProvider { + private static final String PLOT_SQL_COLUMNS = "plot.plot_id, plot.city_project_id, plot.difficulty_id, " + + "plot.owner_uuid, plot.status, plot.outline_bounds, plot.last_activity_date, " + + "plot.plot_version, plot.plot_type"; + + public Plot getPlotById(int plotId) { + String qGet = "SELECT " + PLOT_SQL_COLUMNS + " FROM plot WHERE plot_id = ?;"; + return Utils.handleSqlException(null, () -> SqlHelper.runQuery(qGet, ps -> { + ps.setInt(1, plotId); + ResultSet rs = ps.executeQuery(); + if (!rs.next()) return null; // No plot found + return extractPlot(rs); + })); + } + + public List getPlots(@NotNull Status status) { + String qAllByStatus = "SELECT " + PLOT_SQL_COLUMNS + " FROM plot WHERE status = ?;"; + return Utils.handleSqlException(List.of(), () -> SqlHelper.runQuery(qAllByStatus, ps -> { + ps.setString(1, status.name()); + ResultSet rs = ps.executeQuery(); + List plots = new ArrayList<>(); + while (rs.next()) { + plots.add(extractPlot(rs)); + } + return plots; + })); + } + + public List getPlots(@NotNull CityProject city, Status @NotNull ... statuses) { + String query = "SELECT " + PLOT_SQL_COLUMNS + " FROM plot WHERE city_project_id = ?"; + query += statuses.length > 0 ? " AND status IN (" + "?,".repeat(statuses.length - 1) + "?);" : ";"; + String qPlotsWithCityAndStatuses = query; + return Utils.handleSqlException(List.of(), () -> SqlHelper.runQuery(qPlotsWithCityAndStatuses, ps -> { + ps.setString(1, city.getId()); + for (int i = 0; i < statuses.length; i++) ps.setString(i + 2, statuses[i].name()); + ResultSet rs = ps.executeQuery(); + List plots = new ArrayList<>(); + while (rs.next()) plots.add(extractPlot(rs)); + return plots; + })); + } + + public List getPlots(@NotNull CityProject city, @NotNull PlotDifficulty plotDifficulty, @NotNull Status status) { + String qAllByCityDifficultyStatus = "SELECT " + PLOT_SQL_COLUMNS + " FROM plot WHERE city_project_id = ? AND difficulty_id = ? AND status = ?;"; + return Utils.handleSqlException(List.of(), () -> SqlHelper.runQuery(qAllByCityDifficultyStatus, ps -> { + ps.setString(1, city.getId()); + ps.setString(2, plotDifficulty.name()); + ps.setString(3, status.name()); + ResultSet rs = ps.executeQuery(); + List plots = new ArrayList<>(); + while (rs.next()) plots.add(extractPlot(rs)); + return plots; + })); + } + + public List getPlots(@NotNull List cities, Status... statuses) { + if (cities.isEmpty()) return List.of(); + + String cityPlaceholders = "?,".repeat(cities.size() - 1) + "?"; + String query = "SELECT " + PLOT_SQL_COLUMNS + " FROM plot WHERE city_project_id IN (" + cityPlaceholders + ")"; + query += statuses.length > 0 ? " AND status IN (" + "?,".repeat(statuses.length - 1) + "?) ORDER BY plot.plot_id;" : ";"; + String qPlotsWithCitiesAndStatuses = query; + + return Utils.handleSqlException(List.of(), () -> SqlHelper.runQuery(qPlotsWithCitiesAndStatuses, ps -> { + int index = 1; + for (CityProject city : cities) ps.setString(index++, city.getId()); + for (Status status : statuses) ps.setString(index++, status.name()); + + ResultSet rs = ps.executeQuery(); + List plots = new ArrayList<>(); + while (rs.next()) plots.add(extractPlot(rs)); + return plots; + })); + } + + public List getPlots(@NotNull Builder builder, Status @NotNull ... statuses) { + String query = "SELECT " + PLOT_SQL_COLUMNS + " FROM plot LEFT JOIN builder_is_plot_member pm ON " + + "plot.plot_id = pm.plot_id WHERE (plot.owner_uuid = ? OR pm.uuid = ?)"; + query += statuses.length > 0 ? "AND plot.status IN (" + "?,".repeat(statuses.length - 1) + "?);" : ";"; + String qPlotsWithBuilderAndStatuses = query; + return Utils.handleSqlException(List.of(), () -> SqlHelper.runQuery(qPlotsWithBuilderAndStatuses, ps -> { + String builderUUID = builder.getUUID().toString(); + ps.setString(1, builderUUID); + ps.setString(2, builderUUID); + for (int i = 0; i < statuses.length; i++) ps.setString(i + 3, statuses[i].name()); + + ResultSet rs = ps.executeQuery(); + List plots = new ArrayList<>(); + while (rs.next()) plots.add(extractPlot(rs)); + return plots; + })); + } + + private @NotNull Plot extractPlot(@NotNull ResultSet rs) throws SQLException { + int plotId = rs.getInt("plot_id"); + CityProject cityProject = DataProvider.CITY_PROJECT.getById(rs.getString("city_project_id")).orElseThrow(); + PlotDifficulty difficulty = DataProvider.DIFFICULTY.getDifficultyById(rs.getString("difficulty_id")).orElseThrow().getDifficulty(); + + String ownerUUIDString = rs.getString("owner_uuid"); + UUID ownerUUID = ownerUUIDString != null ? UUID.fromString(ownerUUIDString) : null; + + Status status = Status.valueOf(rs.getString("status")); + String outlineBounds = rs.getString("outline_bounds"); + Date lastActivity = rs.getDate("last_activity_date"); + + double version = rs.getDouble("plot_version"); + PlotType type = PlotType.byId(rs.getInt("plot_type")); + + return new Plot( + plotId, + cityProject, + difficulty, + ownerUUID, + status, + outlineBounds, + lastActivity != null ? lastActivity.toLocalDate() : null, + version, + type, + getPlotMembers(plotId)); + } + + public List getPlotMembers(int plotId) { + String qAllMembers = "SELECT uuid FROM builder_is_plot_member WHERE plot_id = ?;"; + return Utils.handleSqlException(new ArrayList<>(), () -> SqlHelper.runQuery(qAllMembers, ps -> { + ps.setInt(1, plotId); + ResultSet rs = ps.executeQuery(); + List members = new ArrayList<>(); + while (rs.next()) { + members.add(Builder.byUUID(UUID.fromString(rs.getString(1)))); + } + return members; + })); + } + + public byte[] getInitialSchematic(int plotId) { + return getSchematic(plotId, "initial_schematic"); + } + + public byte[] getCompletedSchematic(int plotId) { + return getSchematic(plotId, "complete_schematic"); + } + + private byte @Nullable [] getSchematic(int plotId, String name) { + String qName = "SELECT " + name + " FROM plot WHERE plot_id = ?;"; + return Utils.handleSqlException(null, () -> SqlHelper.runQuery(qName, ps -> { + ps.setInt(1, plotId); + ResultSet rs = ps.executeQuery(); + if (!rs.next()) return null; + return rs.getBytes(1); + })); + } + + public boolean setCompletedSchematic(int plotId, byte[] completedSchematic) { + String qSetCompleteSchematic = "UPDATE plot SET complete_schematic = ? WHERE plot_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetCompleteSchematic, ps -> { + ps.setBytes(1, completedSchematic); + ps.setInt(2, plotId); + return ps.executeUpdate() > 0; + }))); + } + + public boolean setPlotOwner(int plotId, UUID ownerUUID) { + String qSetOwner = "UPDATE plot SET owner_uuid = " + (ownerUUID == null ? "DEFAULT(owner_uuid)" : "?") + " WHERE plot_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetOwner, ps -> { + if (ownerUUID == null) { + ps.setInt(1, plotId); + } else { + ps.setString(1, ownerUUID.toString()); + ps.setInt(2, plotId); + } + return ps.executeUpdate() > 0; + }))); + } + + public boolean setLastActivity(int plotId, LocalDate activityDate) { + String qSetLastActivityDate = "UPDATE plot SET last_activity_date = ? WHERE plot_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetLastActivityDate, ps -> { + ps.setDate(1, activityDate == null ? null : Date.valueOf(activityDate)); + ps.setInt(2, plotId); + return ps.executeUpdate() > 0; + }))); + } + + public boolean setStatus(int plotId, @NotNull Status status) { + String qSetStatus = "UPDATE plot SET status = ? WHERE plot_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetStatus, ps -> { + ps.setString(1, status.name()); + ps.setInt(2, plotId); + return ps.executeUpdate() > 0; + }))); + } + + public boolean setMcVersion(int plotId) { + String qSetMcVersion = "UPDATE plot SET mc_version = ? WHERE plot_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetMcVersion, ps -> { + ps.setString(1, Bukkit.getMinecraftVersion()); + ps.setInt(2, plotId); + return ps.executeUpdate() > 0; + }))); + } + + public boolean setPlotType(int plotId, @NotNull PlotType type) { + String qSetType = "UPDATE plot SET plot_type = ? WHERE plot_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetType, ps -> { + ps.setInt(1, type.getId()); + ps.setInt(2, plotId); + return ps.executeUpdate() > 0; + }))); + } + + public boolean setPasted(int plotId, boolean pasted) { + String qSetPasted = "UPDATE plot SET is_pasted = ? WHERE plot_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetPasted, ps -> { + ps.setBoolean(1, pasted); + ps.setInt(2, plotId); + return ps.executeUpdate() > 0; + }))); + } + + public boolean deletePlot(int plotId) { + String qDelete = "DELETE FROM plot WHERE plot_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qDelete, ps -> { + ps.setInt(1, plotId); + return ps.executeUpdate() > 0; + }))); + } + + public boolean addPlotMember(int id, Builder member) { + String qInsertPlotMember = "INSERT INTO builder_is_plot_member (plot_id, uuid) VALUES (?, ?);"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qInsertPlotMember, ps -> { + ps.setInt(1, id); + ps.setString(2, member.getUUID().toString()); + return ps.executeUpdate() > 0; + }))); + } + + public boolean removePlotMember(int id, Builder member) { + String qDeletePlotMember = "DELETE FROM builder_is_plot_member WHERE plot_id = ? AND uuid = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qDeletePlotMember, ps -> { + ps.setInt(1, id); + ps.setString(2, member.getUUID().toString()); + return ps.executeUpdate() > 0; + }))); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/providers/ReviewProvider.java b/src/main/java/com/alpsbte/plotsystem/core/database/providers/ReviewProvider.java new file mode 100644 index 000000000..f5656fff1 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/database/providers/ReviewProvider.java @@ -0,0 +1,345 @@ +package com.alpsbte.plotsystem.core.database.providers; + +import com.alpsbte.alpslib.io.database.SqlHelper; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; +import com.alpsbte.plotsystem.core.system.review.BuildTeamToggleCriteria; +import com.alpsbte.plotsystem.core.system.review.PlotReview; +import com.alpsbte.plotsystem.core.system.review.ReviewNotification; +import com.alpsbte.plotsystem.core.system.review.ReviewRating; +import com.alpsbte.plotsystem.core.system.review.ToggleCriteria; +import com.alpsbte.plotsystem.utils.Utils; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; + +public class ReviewProvider { + protected static final List NOTIFICATIONS = new ArrayList<>(); + protected static final List TOGGLE_CRITERIA = new ArrayList<>(); + protected static final List BUILD_TEAM_TOGGLE_CRITERIA = new ArrayList<>(); + + public ReviewProvider() { + // cache all review notifications + String qAllNotifys = "SELECT review_id, uuid FROM builder_has_review_notification;"; + Utils.handleSqlException(() -> SqlHelper.runQuery(qAllNotifys, ps -> { + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + NOTIFICATIONS.add(new ReviewNotification(rs.getInt(1), UUID.fromString(rs.getString(2)))); + } + })); + + // cache all toggle criteria + String qAllToggleCriterias = "SELECT criteria_name, is_optional FROM review_toggle_criteria;"; + Utils.handleSqlException(() -> SqlHelper.runQuery(qAllToggleCriterias, ps -> { + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + TOGGLE_CRITERIA.add(new ToggleCriteria(rs.getString(1), rs.getBoolean(2))); + } + })); + + // cache all build team toggle criteria + String qAllBuildteamCriteria = "SELECT criteria_name, build_team_id FROM build_team_uses_toggle_criteria;"; + Utils.handleSqlException(() -> SqlHelper.runQuery(qAllBuildteamCriteria, ps -> { + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + String criteriaName = rs.getString(1); + ToggleCriteria toggle = TOGGLE_CRITERIA.stream().filter(c -> c.criteriaName().equals(criteriaName)).findFirst().orElseThrow(); + BUILD_TEAM_TOGGLE_CRITERIA.add(new BuildTeamToggleCriteria(rs.getInt(2), toggle)); + } + })); + } + + public Optional getReview(int reviewId) { + String qById = "SELECT plot_id, rating, score, feedback, reviewed_by FROM plot_review WHERE review_id = ?;"; + return Utils.handleSqlException(Optional.empty(), () -> SqlHelper.runQuery(qById, ps -> { + ps.setInt(1, reviewId); + ResultSet rs = ps.executeQuery(); + if (!rs.next()) return Optional.empty(); + + int plotId = rs.getInt(1); + ReviewRating rating = getReviewRating(reviewId, rs.getString(2)); + int score = rs.getInt(3); + String feedback = rs.getString(4); + UUID reviewedBy = UUID.fromString(rs.getString(5)); + + return Optional.of(new PlotReview(reviewId, plotId, rating, score, feedback, reviewedBy)); + })); + } + + public Optional getLatestReview(int plotId) { + String qLatestByPlotId = "SELECT review_id, rating, score, feedback, reviewed_by FROM plot_review WHERE plot_id = ? ORDER BY review_date DESC LIMIT 1;"; + return Utils.handleSqlException(Optional.empty(), () -> SqlHelper.runQuery(qLatestByPlotId, ps -> { + ps.setInt(1, plotId); + ResultSet rs = ps.executeQuery(); + if (!rs.next()) return Optional.empty(); + + int reviewId = rs.getInt(1); + ReviewRating rating = getReviewRating(reviewId, rs.getString(2)); + int score = rs.getInt(3); + String feedback = rs.getString(4); + UUID reviewedBy = UUID.fromString(rs.getString(5)); + + return Optional.of(new PlotReview(reviewId, plotId, rating, score, feedback, reviewedBy)); + })); + } + + public List getPlotReviewHistory(int plotId) { + String qByPlotId = "SELECT review_id, rating, score, feedback, reviewed_by FROM plot_review WHERE plot_id = ?;"; + return Utils.handleSqlException(new ArrayList<>(), () -> SqlHelper.runQuery(qByPlotId, ps -> { + ps.setInt(1, plotId); + ResultSet rs = ps.executeQuery(); + List reviews = new ArrayList<>(); + while (rs.next()) { + int reviewId = rs.getInt(1); + ReviewRating rating = getReviewRating(reviewId, rs.getString(2)); + int score = rs.getInt(3); + String feedback = rs.getString(4); + UUID reviewedBy = UUID.fromString(rs.getString(5)); + + reviews.add(new PlotReview(reviewId, plotId, rating, score, feedback, reviewedBy)); + } + return reviews; + })); + } + + private @NotNull ReviewRating getReviewRating(int reviewId, @NotNull String ratingString) { + int accuracyPoints = Integer.parseInt(ratingString.split(",")[0]); + int blockPalettePoints = Integer.parseInt(ratingString.split(",")[1]); + Map toggleCriteria = getReviewToggleCriteria(reviewId); + return new ReviewRating(accuracyPoints, blockPalettePoints, toggleCriteria); + } + + public boolean updateFeedback(int reviewId, String newFeedback) { + String qSetFeedback = "UPDATE plot_review SET feedback = ? WHERE review_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetFeedback, ps -> { + ps.setString(1, newFeedback); + ps.setInt(2, reviewId); + return ps.executeUpdate() > 0; + }))); + } + + public PlotReview createReview(@NotNull Plot plot, ReviewRating rating, int score, UUID reviewerUUID) { + boolean result = DataProvider.PLOT.setMcVersion(plot.getId()); + if (!result) return null; + + // Create Review + String qInsert = "INSERT INTO plot_review (plot_id, rating, score, reviewed_by) VALUES (?, ?, ?, ?);"; + result = Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qInsert, ps -> { + ps.setInt(1, plot.getId()); + ps.setString(2, rating.getRatingDatabaseString()); + ps.setInt(3, score); + ps.setString(4, reviewerUUID.toString()); + return ps.executeUpdate() > 0; + }))); + + if (!result) return null; + + PlotReview review = plot.getLatestReview().orElseThrow(); + Map allToggles = rating.getAllToggles(); + for (Map.Entry criteriaEntry : allToggles.entrySet()) { + if (!addReviewToggleCriteria(review.getReviewId(), criteriaEntry.getKey(), criteriaEntry.getValue())) + return null; + } + + + // create feedback notifications + createReviewNotification(review.getReviewId(), plot.getPlotOwner().getUUID()); + for (Builder builder : plot.getPlotMembers()) { + createReviewNotification(review.getReviewId(), builder.getUUID()); + } + return review; + } + + public boolean removeReview(int reviewId) { + // remove all review notifications + List notifications = getReviewNotifications(reviewId); + for (ReviewNotification notification : notifications) { + removeReviewNotification(notification.reviewId(), notification.uuid()); + } + + // remove checked toggle criteria + removeCheckedToggleCriteria(reviewId); + + // remove review + String qDelete = "DELETE FROM plot_review WHERE review_id = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qDelete, ps -> { + ps.setInt(1, reviewId); + return ps.executeUpdate() > 0; + }))); + } + + public boolean removeAllReviewsOfPlot(int plotId) { + String qIdsByPlotId = "SELECT review_id FROM plot_review WHERE plot_id = ?;"; + List reviewIds = new ArrayList<>(); + Utils.handleSqlException(() -> SqlHelper.runQuery(qIdsByPlotId, ps -> { + ps.setInt(1, plotId); + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + reviewIds.add(rs.getInt(1)); + } + })); + + boolean successful = true; + for (int reviewId : reviewIds) { + successful = successful && removeReview(reviewId); + } + return successful; + } + + // --- Toggle Criteria --- + public Optional getToggleCriteria(String criteriaName) { + return TOGGLE_CRITERIA.stream().filter(c -> c.criteriaName().equals(criteriaName)).findFirst(); + } + + public boolean addToggleCriteria(String criteriaName, boolean isOptional) { + Optional criteria = TOGGLE_CRITERIA.stream().filter(t -> t.criteriaName().equals(criteriaName)).findFirst(); + if (criteria.isPresent()) return false; + + String qInsertToggleCriteria = "INSERT INTO review_toggle_criteria (criteria_name, is_optional) VALUES (?, ?);"; + if (!Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qInsertToggleCriteria, ps -> { + ps.setString(1, criteriaName); + ps.setBoolean(2, isOptional); + return ps.executeUpdate() > 0; + })))) return false; + TOGGLE_CRITERIA.add(new ToggleCriteria(criteriaName, isOptional)); + return true; + } + + public boolean removeToggleCriteria(String criteriaName) { + Optional criteria = TOGGLE_CRITERIA.stream().filter(t -> t.criteriaName().equals(criteriaName)).findFirst(); + if (criteria.isEmpty()) return false; + + String qDeleteToggleCriteria = "DELETE FROM review_toggle_criteria WHERE criteria_name = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qDeleteToggleCriteria, ps -> { + ps.setString(1, criteriaName); + boolean successful = ps.executeUpdate() > 0; + if (successful) TOGGLE_CRITERIA.remove(criteria.get()); + return successful; + }))); + } + + public boolean setToggleCriteriaOptional(String criteriaName, boolean isOptional) { + Optional criteria = TOGGLE_CRITERIA.stream().filter(t -> t.criteriaName().equals(criteriaName)).findFirst(); + if (criteria.isEmpty()) return false; + + String qSetToggleCriteriaOptional = "UPDATE review_toggle_criteria SET is_optional = ? WHERE criteria_name = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetToggleCriteriaOptional, ps -> { + ps.setBoolean(1, isOptional); + ps.setString(2, criteriaName); + return ps.executeUpdate() > 0; + }))); + } + + public List getAllToggleCriteria() {return TOGGLE_CRITERIA.stream().toList();} + + public List getBuildTeamToggleCriteria(int buildTeamId) { + return BUILD_TEAM_TOGGLE_CRITERIA.stream().filter(c -> c.buildTeamId() == buildTeamId).map(BuildTeamToggleCriteria::criteria).toList(); + } + + public boolean assignBuildTeamToggleCriteria(int buildTeamId, ToggleCriteria criteria) { + Optional existingCriteria = getBuildTeamToggleCriteria(buildTeamId).stream().filter(t -> + t.criteriaName().equals(criteria.criteriaName())).findFirst(); + if (existingCriteria.isPresent()) return false; + String qInsertCriteriaToBuildteam = "INSERT INTO build_team_uses_toggle_criteria (build_team_id, criteria_name) VALUES (?, ?);"; + if (!Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qInsertCriteriaToBuildteam, ps -> { + ps.setInt(1, buildTeamId); + ps.setString(2, criteria.criteriaName()); + return ps.executeUpdate() > 0; + })))) return false; + BUILD_TEAM_TOGGLE_CRITERIA.add(new BuildTeamToggleCriteria(buildTeamId, criteria)); + return true; + } + + public boolean removeBuildTeamToggleCriteria(int buildTeamId, ToggleCriteria criteria) { + Optional existingCriteria = BUILD_TEAM_TOGGLE_CRITERIA.stream().filter(btc -> + btc.buildTeamId() == buildTeamId && btc.criteria().criteriaName().equals(criteria.criteriaName())).findFirst(); + if (existingCriteria.isEmpty()) return false; + String qDeleteCriteriaToBuildteam = "DELETE FROM build_team_uses_toggle_criteria WHERE build_team_id = ? AND criteria_name = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qDeleteCriteriaToBuildteam, ps -> { + ps.setInt(1, buildTeamId); + ps.setString(2, criteria.criteriaName()); + boolean successful = ps.executeUpdate() > 0; + if (successful) BUILD_TEAM_TOGGLE_CRITERIA.remove(existingCriteria.get()); + return successful; + }))); + } + + public Map getReviewToggleCriteria(int reviewId) { + String qReviewToggleCriteriasByReviewId = "SELECT criteria_name, is_checked FROM review_contains_toggle_criteria WHERE review_id = ?;"; + return Utils.handleSqlException(new HashMap<>(), () -> SqlHelper.runQuery(qReviewToggleCriteriasByReviewId, ps -> { + ps.setInt(1, reviewId); + ResultSet rs = ps.executeQuery(); + HashMap toggleCriteriaList = new HashMap<>(); + while (rs.next()) { + boolean isChecked = rs.getBoolean(2); + toggleCriteriaList.put(getToggleCriteria(rs.getString(1)).orElseThrow(), isChecked); + } + return toggleCriteriaList; + })); + } + + public boolean addReviewToggleCriteria(int reviewId, @NotNull ToggleCriteria toggle, boolean isChecked) { + String qInsertToggleCriteriaToReview = "INSERT INTO review_contains_toggle_criteria (review_id, criteria_name, is_checked) VALUES (?, ?, ?);"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qInsertToggleCriteriaToReview, ps -> { + ps.setInt(1, reviewId); + ps.setString(2, toggle.criteriaName()); + ps.setBoolean(3, isChecked); + return ps.executeUpdate() > 0; + }))); + } + + public void removeCheckedToggleCriteria(int reviewId) { + String qDeleteToggleCriteriaToReview = "DELETE FROM review_contains_toggle_criteria WHERE review_id = ?;"; + Utils.handleSqlException(() -> SqlHelper.runStatement(qDeleteToggleCriteriaToReview, ps -> ps.setInt(1, reviewId))); + } + + // --- Review Notification --- + public Optional getReviewNotification(int reviewId, UUID uuid) { + return NOTIFICATIONS.stream().filter(n -> n.reviewId() == reviewId && n.uuid() == uuid).findFirst(); + } + + public List getReviewNotifications(int reviewId) { + return NOTIFICATIONS.stream().filter(n -> n.reviewId() == reviewId).toList(); + } + + public List getReviewNotifications(UUID uuid) { + return NOTIFICATIONS.stream().filter(n -> n.uuid() == uuid).toList(); + } + + public void removeReviewNotification(int reviewId, UUID uuid) { + Optional notification = getReviewNotification(reviewId, uuid); + if (notification.isEmpty()) return; + + String qDeleteReviewNotify = "DELETE FROM builder_has_review_notification WHERE review_id = ? AND uuid = ?;"; + Utils.handleSqlException(() -> SqlHelper.runQuery(qDeleteReviewNotify, ps -> { + ps.setInt(1, reviewId); + ps.setString(2, uuid.toString()); + if (ps.executeUpdate() > 0) NOTIFICATIONS.remove(notification.get()); + })); + } + + public void createReviewNotification(int reviewId, UUID uuid) { + Player player = Bukkit.getPlayer(uuid); + if (player != null && player.isOnline()) { + PlotUtils.ChatFormatting.sendFeedbackMessage(List.of(new ReviewNotification(reviewId, uuid)), player); + return; + } + + String qInsertReviewNotify = "INSERT INTO builder_has_review_notification (review_id, uuid) VALUES (?, ?);"; + Utils.handleSqlException(() -> SqlHelper.runQuery(qInsertReviewNotify, ps -> { + ps.setInt(1, reviewId); + ps.setString(2, uuid.toString()); + if (ps.executeUpdate() > 0) NOTIFICATIONS.add(new ReviewNotification(reviewId, uuid)); + })); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/providers/ServerProvider.java b/src/main/java/com/alpsbte/plotsystem/core/database/providers/ServerProvider.java new file mode 100644 index 000000000..6da3f21a6 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/database/providers/ServerProvider.java @@ -0,0 +1,56 @@ +package com.alpsbte.plotsystem.core.database.providers; + +import com.alpsbte.alpslib.io.database.SqlHelper; +import com.alpsbte.plotsystem.utils.Utils; + +import java.sql.ResultSet; +import java.util.ArrayList; +import java.util.List; + +public class ServerProvider { + protected static final List SERVERS = new ArrayList<>(); + + public ServerProvider() { + String qAll = "SELECT server_name FROM server;"; + + Utils.handleSqlException(() -> SqlHelper.runQuery(qAll, ps -> { + ResultSet rs = ps.executeQuery(); + while (rs.next()) { + SERVERS.add(rs.getString(1)); // cache all servers + } + })); + } + + public boolean serverExists(String serverName) { + return SERVERS.stream().anyMatch(s -> s.equals(serverName)); + } + + public List getServers() { + return SERVERS; + } + + public boolean addServer(String name, int buildTeamId) { + if (serverExists(name)) return true; + + String qInsert = "INSERT INTO server (server_name, build_team_id) VALUES (?, ?);"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qInsert, ps -> { + ps.setString(1, name); + ps.setInt(2, buildTeamId); + boolean result = ps.executeUpdate() > 0; + if (result) SERVERS.add(name); + return result; + }))); + } + + public boolean removeServer(String name) { + if (!serverExists(name)) return false; + + String qDelete = "DELETE FROM server WHERE server_name = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qDelete, ps -> { + ps.setString(1, name); + boolean result = ps.executeUpdate() > 0; + if (result) SERVERS.remove(name); + return result; + }))); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/database/providers/TutorialPlotProvider.java b/src/main/java/com/alpsbte/plotsystem/core/database/providers/TutorialPlotProvider.java new file mode 100644 index 000000000..ae9e46601 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/database/providers/TutorialPlotProvider.java @@ -0,0 +1,85 @@ +package com.alpsbte.plotsystem.core.database.providers; + +import com.alpsbte.alpslib.io.database.SqlHelper; +import com.alpsbte.plotsystem.core.system.plot.TutorialPlot; +import com.alpsbte.plotsystem.utils.Utils; + +import java.sql.Date; +import java.sql.ResultSet; +import java.sql.Timestamp; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Deque; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map; +import java.util.Optional; + +public class TutorialPlotProvider { + public static final Map tutorialPlots = new HashMap<>(); + public static final Deque freeTutorialPlotIds = new LinkedList<>(); + + public Optional getById(int id) { + return tutorialPlots.keySet().stream().filter(t -> tutorialPlots.get(t) == id).findFirst(); + } + + public Optional getByTutorialId(int tutorialId, String playerUUID) { + Optional tutorialPlot = tutorialPlots.keySet().stream() + .filter(t -> t.getTutorialID() == tutorialId && t.getUUID().toString().equals(playerUUID)).findFirst(); + + if (tutorialPlot.isPresent()) return tutorialPlot; + + String qGet = "SELECT stage_id, is_complete, last_stage_complete_date FROM tutorial WHERE tutorial_id = ? AND uuid = ?;"; + return Utils.handleSqlException(tutorialPlot, () -> SqlHelper.runQuery(qGet, ps -> { + ps.setInt(1, tutorialId); + ps.setString(2, playerUUID); + ResultSet rs = ps.executeQuery(); + if (rs.next()) { + int plotId = freeTutorialPlotIds.isEmpty() ? 0 : freeTutorialPlotIds.poll(); + int stageId = rs.getInt(1); + boolean isComplete = rs.getBoolean(2); + Date lastStageCompleteDate = rs.getDate(3); + TutorialPlot newTutorialPlot = new TutorialPlot(plotId, tutorialId, playerUUID, stageId, + isComplete, lastStageCompleteDate != null ? lastStageCompleteDate.toLocalDate() : null); + tutorialPlots.put(newTutorialPlot, plotId); + + return Optional.of(newTutorialPlot); + } + return Optional.empty(); + })); + + } + + public boolean add(int tutorialId, String playerUUID) { + if (getByTutorialId(tutorialId, playerUUID).isPresent()) return false; + + String qInsert = "INSERT INTO tutorial (tutorial_id, uuid) VALUES (?, ?);"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qInsert, ps -> { + ps.setInt(1, tutorialId); + ps.setString(2, playerUUID); + return ps.executeUpdate() > 0; + }))); + } + + public boolean setStageId(int tutorialId, String playerUUID, int stageId) { + String qSetStage = "UPDATE tutorial SET stage_id = ?, last_stage_complete_date = ? WHERE tutorial_id = ? AND uuid = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetStage, ps -> { + ps.setInt(1, stageId); + ps.setObject(2, LocalDate.now()); + ps.setInt(3, tutorialId); + ps.setString(4, playerUUID); + return ps.executeUpdate() > 0; + }))); + } + + public boolean setComplete(int tutorialId, String playerUUID) { + String qSetComplete = "UPDATE tutorial SET is_complete = ?, last_stage_complete_date = ? WHERE tutorial_id = ? AND uuid = ?;"; + return Boolean.TRUE.equals(Utils.handleSqlException(false, () -> SqlHelper.runQuery(qSetComplete, ps -> { + ps.setBoolean(1, true); + ps.setObject(2, Timestamp.valueOf(LocalDateTime.now())); + ps.setInt(3, tutorialId); + ps.setString(4, playerUUID); + return ps.executeUpdate() > 0; + }))); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/holograms/HologramConfiguration.java b/src/main/java/com/alpsbte/plotsystem/core/holograms/HologramConfiguration.java index 8d2d313ac..b42cbccad 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/holograms/HologramConfiguration.java +++ b/src/main/java/com/alpsbte/plotsystem/core/holograms/HologramConfiguration.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.holograms; public interface HologramConfiguration { diff --git a/src/main/java/com/alpsbte/plotsystem/core/holograms/HologramRegister.java b/src/main/java/com/alpsbte/plotsystem/core/holograms/HologramRegister.java index d8b92f732..72652253b 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/holograms/HologramRegister.java +++ b/src/main/java/com/alpsbte/plotsystem/core/holograms/HologramRegister.java @@ -2,6 +2,7 @@ import com.alpsbte.alpslib.hologram.DecentHologramDisplay; import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.holograms.leaderboards.ScoreLeaderboard; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.ConfigUtil; import org.bukkit.Bukkit; @@ -12,13 +13,14 @@ import java.util.Objects; public final class HologramRegister { + private HologramRegister() {} + /** - * Registers the {@link ScoreLeaderboard}, {@link PlotsLeaderboard} and adds + * Registers the {@link ScoreLeaderboard} and adds * them to {@link DecentHologramDisplay#activeDisplays}. */ public static void init() { new ScoreLeaderboard(); - new PlotsLeaderboard(); } public static void reload() { diff --git a/src/main/java/com/alpsbte/plotsystem/core/holograms/PlotTutorialHologram.java b/src/main/java/com/alpsbte/plotsystem/core/holograms/PlotTutorialHologram.java index 5e729f947..9ed7dd9cc 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/holograms/PlotTutorialHologram.java +++ b/src/main/java/com/alpsbte/plotsystem/core/holograms/PlotTutorialHologram.java @@ -1,32 +1,8 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.holograms; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorialHologram; -import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.message.ChatMessageTask; +import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import net.kyori.adventure.text.Component; @@ -35,7 +11,12 @@ import org.bukkit.Sound; import org.bukkit.entity.Player; -import static org.bukkit.ChatColor.*; +import static org.bukkit.ChatColor.BOLD; +import static org.bukkit.ChatColor.DARK_GRAY; +import static org.bukkit.ChatColor.GOLD; +import static org.bukkit.ChatColor.GRAY; +import static org.bukkit.ChatColor.GREEN; +import static org.bukkit.ChatColor.YELLOW; public class PlotTutorialHologram extends AbstractTutorialHologram { public PlotTutorialHologram(Player player, int plotTutorialId, int holoId, String content) { diff --git a/src/main/java/com/alpsbte/plotsystem/core/holograms/PlotsLeaderboard.java b/src/main/java/com/alpsbte/plotsystem/core/holograms/PlotsLeaderboard.java deleted file mode 100644 index 51d4e1e0c..000000000 --- a/src/main/java/com/alpsbte/plotsystem/core/holograms/PlotsLeaderboard.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.core.holograms; - -import com.alpsbte.alpslib.hologram.DecentHologramDisplay; -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.system.Builder; -import com.alpsbte.plotsystem.utils.io.ConfigPaths; -import com.alpsbte.plotsystem.utils.items.BaseItems; -import org.bukkit.inventory.ItemStack; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.UUID; -import java.util.logging.Level; - -public class PlotsLeaderboard extends DecentHologramDisplay implements HologramConfiguration { - protected PlotsLeaderboard() { - super(ConfigPaths.PLOTS_LEADERBOARD, null, false); - setLocation(HologramRegister.getLocation(this)); - setEnabled(PlotSystem.getPlugin().getConfig().getBoolean(getEnablePath())); - } - - @Override - public ItemStack getItem() { - return new ItemStack(BaseItems.LEADERBOARD_PLOT.getItem()); - } - - @Override - public String getTitle(UUID playerUUID) { - return "§b§lCOMPLETED PLOTS §6§l[Lifetime]"; - } - - @Override - public List> getContent(UUID playerUUID) { - try { - ArrayList> lines = new ArrayList<>(); - - List> entries = Builder.getBuildersByCompletedBuilds(10); - for (int i = 0; i < 10; i++) { - Builder.DatabaseEntry entry = i < entries.size() && entries.get(i).getValue() != 0 ? entries.get(i) : null; - lines.add(new HologramRegister.LeaderboardPositionLine(i + 1, entry != null ? entry.getKey() : null, entry != null ? entry.getValue() : 0)); - } - - return lines; - } catch (SQLException ex) { - PlotSystem.getPlugin().getLogger().log(Level.SEVERE, "An error occurred while reading leaderboard content", ex); - } - return new ArrayList<>(); - } - - @Override - public boolean hasViewPermission(UUID uuid) { - return true; - } - - @Override - public String getEnablePath() { - return ConfigPaths.PLOTS_LEADERBOARD_ENABLE; - } - - @Override - public String getXPath() { - return ConfigPaths.PLOTS_LEADERBOARD_X; - } - - @Override - public String getYPath() { - return ConfigPaths.PLOTS_LEADERBOARD_Y; - } - - @Override - public String getZPath() { - return ConfigPaths.PLOTS_LEADERBOARD_Z; - } -} \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/core/holograms/ScoreLeaderboard.java b/src/main/java/com/alpsbte/plotsystem/core/holograms/ScoreLeaderboard.java deleted file mode 100644 index 4625c69f0..000000000 --- a/src/main/java/com/alpsbte/plotsystem/core/holograms/ScoreLeaderboard.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.core.holograms; - -import com.alpsbte.alpslib.hologram.DecentHologramPagedDisplay; -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.system.Builder; -import com.alpsbte.plotsystem.core.system.Payout; -import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; -import com.alpsbte.plotsystem.utils.io.ConfigPaths; -import com.alpsbte.plotsystem.utils.io.ConfigUtil; -import com.alpsbte.plotsystem.utils.io.LangPaths; -import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.alpsbte.plotsystem.utils.items.BaseItems; -import eu.decentsoftware.holograms.api.DHAPI; -import eu.decentsoftware.holograms.api.holograms.Hologram; -import net.kyori.adventure.text.Component; -import net.kyori.adventure.text.TextComponent; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; -import org.bukkit.Bukkit; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.scheduler.BukkitRunnable; - -import java.sql.SQLException; -import java.text.DecimalFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; -import java.util.logging.Level; -import java.util.stream.Collectors; - -public class ScoreLeaderboard extends DecentHologramPagedDisplay implements HologramConfiguration { - private final DecimalFormat df = new DecimalFormat("#.##"); - private LeaderboardTimeframe sortByLeaderboard; - - protected ScoreLeaderboard() { - super("score-leaderboard", null, false, PlotSystem.getPlugin()); - setEnabled(PlotSystem.getPlugin().getConfig().getBoolean(getEnablePath())); - setLocation(HologramRegister.getLocation(this)); - - new BukkitRunnable() { - @Override - public void run() { - for (Player player : getPlayersInRadiusForRanking()) { - if (AbstractTutorial.getActiveTutorial(player.getUniqueId()) != null) continue; - player.sendActionBar(getRankingString(player)); - } - } - }.runTaskTimerAsynchronously(PlotSystem.getPlugin(), 0L, 20L); - } - - @Override - public List getPages() { - if (ConfigUtil.getInstance() == null) return new ArrayList<>(); - FileConfiguration config = PlotSystem.getPlugin().getConfig(); - return Arrays.stream(LeaderboardTimeframe.values()) - .filter(p -> config.getBoolean(p.configPath)).map(LeaderboardTimeframe::toString).collect(Collectors.toList()); - } - - @Override - public void create(Player player) { - if (getPages().isEmpty()) { - PlotSystem.getPlugin().getLogger().log(Level.WARNING, "Unable to initialize Score-Leaderboard - No display pages enabled! Check config for display-options."); - return; - } - - super.create(player); - } - - @Override - public boolean hasViewPermission(UUID uuid) { - return true; - } - - @Override - public ItemStack getItem() { - return new ItemStack(BaseItems.LEADERBOARD_SCORE.getItem()); - } - - @Override - public String getTitle(UUID playerUUID) { - return "§b§lTOP SCORE §6§l[" + (sortByLeaderboard.toString().charAt(0) + - sortByLeaderboard.toString().toLowerCase().substring(1)) + "]"; - } - - @Override - public List> getHeader(UUID playerUUID) { - sortByLeaderboard = LeaderboardTimeframe.valueOf(currentPage); - return super.getHeader(playerUUID); - } - - @Override - public List> getContent(UUID playerUUID) { - try { - ArrayList> lines = new ArrayList<>(); - - for (int index = 0; index < 10; index++) { - lines.add(new LeaderboardPositionLineWithPayout(index + 1, null, 0)); - } - - int index = 0; - for (Builder.DatabaseEntry entry : Builder.getBuildersByScore(sortByLeaderboard)) { - lines.set(index, new LeaderboardPositionLineWithPayout(index + 1, entry.getKey(), entry.getValue())); - index++; - } - - return lines; - } catch (SQLException ex) { - PlotSystem.getPlugin().getLogger().log(Level.SEVERE, "An error occurred while reading leaderboard content", ex); - } - return new ArrayList<>(); - } - - private Component getRankingString(Player player) { - int position, rows, myScore; - try { - position = Builder.getBuilderScorePosition(player.getUniqueId(), sortByLeaderboard); - rows = Builder.getBuildersInSort(sortByLeaderboard); - myScore = Builder.getBuilderScore(player.getUniqueId(), sortByLeaderboard); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(Component.text("A SQL error occurred!"), ex); - return Component.empty(); - } - - // Start building the component - TextComponent.Builder builder = Component.text() - .append(Component.text(" " + LangUtil.getInstance().get(player, sortByLeaderboard.langPath)) - .color(NamedTextColor.GOLD) - .decorate(TextDecoration.BOLD) - ) - .append(Component.text(" ➜ ") - .color(NamedTextColor.DARK_GRAY) - .decorate(TextDecoration.BOLD) - ); - - if (position == -1) { - builder.append(Component.text(LangUtil.getInstance().get(player, LangPaths.Leaderboards.NOT_ON_LEADERBOARD)) - .color(NamedTextColor.RED) - .decoration(TextDecoration.BOLD, false) - ); - } else if (position < 50) { - builder.append(Component.text( - LangUtil.getInstance().get(player, LangPaths.Leaderboards.ACTIONBAR_POSITION, String.valueOf(position))) - .color(NamedTextColor.GREEN) - .decoration(TextDecoration.BOLD, false) - ); - } else { - String topPercentage = df.format(position * 1.0 / rows); - builder.append(Component.text( - LangUtil.getInstance().get(player, LangPaths.Leaderboards.ACTIONBAR_PERCENTAGE, topPercentage)) - .decoration(TextDecoration.BOLD, false) - ); - } - - if (myScore != -1) { - builder.append( - Component.text(" (", NamedTextColor.DARK_GRAY) - .append(Component.text(myScore + " points", NamedTextColor.AQUA)) - .append(Component.text(")", NamedTextColor.DARK_GRAY)) - ); - } - - return builder.build(); - } - - private List getPlayersInRadiusForRanking() { - FileConfiguration config = PlotSystem.getPlugin().getConfig(); - boolean actionBarEnabled = config.getBoolean(ConfigPaths.DISPLAY_OPTIONS_ACTION_BAR_ENABLE, true); - int actionBarRadius = config.getInt(ConfigPaths.DISPLAY_OPTIONS_ACTION_BAR_RADIUS, 30); - List players = new ArrayList<>(); - if (!actionBarEnabled) return players; - for (Player player : Bukkit.getOnlinePlayers()) { - Hologram holo = DHAPI.getHologram(player.getUniqueId() + "-" + getId()); - if (holo == null) continue; - if (player.getWorld().getName().equals(holo.getLocation().getWorld().getName()) && - holo.getLocation().distance(player.getLocation()) <= actionBarRadius) { - players.add(player); - } - } - return players; - } - - @Override - public long getInterval() { - return PlotSystem.getPlugin().getConfig().getInt(ConfigPaths.DISPLAY_OPTIONS_INTERVAL) * 20L; - } - - @Override - public String getEnablePath() { - return ConfigPaths.SCORE_LEADERBOARD_ENABLE; - } - - @Override - public String getXPath() { - return ConfigPaths.SCORE_LEADERBOARD_X; - } - - @Override - public String getYPath() { - return ConfigPaths.SCORE_LEADERBOARD_Y; - } - - @Override - public String getZPath() { - return ConfigPaths.SCORE_LEADERBOARD_Z; - } - - public enum LeaderboardTimeframe { - DAILY(ConfigPaths.DISPLAY_OPTIONS_SHOW_DAILY), - WEEKLY(ConfigPaths.DISPLAY_OPTIONS_SHOW_WEEKLY), - MONTHLY(ConfigPaths.DISPLAY_OPTIONS_SHOW_MONTHLY), - YEARLY(ConfigPaths.DISPLAY_OPTIONS_SHOW_YEARLY), - LIFETIME(ConfigPaths.DISPLAY_OPTIONS_SHOW_LIFETIME); - - public final String configPath; - public final String langPath; - - LeaderboardTimeframe(String configPath) { - this.configPath = configPath; - this.langPath = LangPaths.Leaderboards.PAGES + name(); - } - } - - private class LeaderboardPositionLineWithPayout extends HologramRegister.LeaderboardPositionLine { - private final int position; - - public LeaderboardPositionLineWithPayout(int position, String username, int score) { - super(position, username, score); - this.position = position; - } - - @Override - public String getLine() { - try { - String line = super.getLine(); - Payout payout = sortByLeaderboard != LeaderboardTimeframe.LIFETIME ? Payout.getPayout(sortByLeaderboard, position) : null; - if (payout == null) return line; - String payoutAmount = payout.getPayoutAmount(); - try { - // if payout amount can be number, prefix with dollar sign - Integer.valueOf(payoutAmount); - payoutAmount = "$" + payoutAmount; - } catch (NumberFormatException ignored) {} - - return line + " §7- §e§l" + payoutAmount; - } catch (SQLException e) { - return super.getLine() + " §7- §cSQL ERR"; - } - } - } -} \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/core/holograms/leaderboards/LeaderboardTimeframe.java b/src/main/java/com/alpsbte/plotsystem/core/holograms/leaderboards/LeaderboardTimeframe.java new file mode 100644 index 000000000..dc722dd0b --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/holograms/leaderboards/LeaderboardTimeframe.java @@ -0,0 +1,20 @@ +package com.alpsbte.plotsystem.core.holograms.leaderboards; + +import com.alpsbte.plotsystem.utils.io.ConfigPaths; +import com.alpsbte.plotsystem.utils.io.LangPaths; + +public enum LeaderboardTimeframe { + DAILY(ConfigPaths.DISPLAY_OPTIONS_SHOW_DAILY), + WEEKLY(ConfigPaths.DISPLAY_OPTIONS_SHOW_WEEKLY), + MONTHLY(ConfigPaths.DISPLAY_OPTIONS_SHOW_MONTHLY), + YEARLY(ConfigPaths.DISPLAY_OPTIONS_SHOW_YEARLY), + LIFETIME(ConfigPaths.DISPLAY_OPTIONS_SHOW_LIFETIME); + + public final String configPath; + public final String langPath; + + LeaderboardTimeframe(String configPath) { + this.configPath = configPath; + this.langPath = LangPaths.Leaderboards.PAGES + name(); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/holograms/leaderboards/ScoreLeaderboard.java b/src/main/java/com/alpsbte/plotsystem/core/holograms/leaderboards/ScoreLeaderboard.java new file mode 100644 index 000000000..e4ec49e28 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/holograms/leaderboards/ScoreLeaderboard.java @@ -0,0 +1,112 @@ +package com.alpsbte.plotsystem.core.holograms.leaderboards; + +import com.alpsbte.alpslib.hologram.DecentHologramPagedDisplay; +import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.holograms.HologramConfiguration; +import com.alpsbte.plotsystem.core.holograms.HologramRegister; +import com.alpsbte.plotsystem.utils.io.ConfigPaths; +import com.alpsbte.plotsystem.utils.io.ConfigUtil; +import com.alpsbte.plotsystem.utils.items.BaseItems; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.logging.Level; + +public class ScoreLeaderboard extends DecentHologramPagedDisplay implements HologramConfiguration { + private LeaderboardTimeframe sortByLeaderboard; + + public ScoreLeaderboard() { + super("score-leaderboard", null, false, PlotSystem.getPlugin()); + setEnabled(PlotSystem.getPlugin().getConfig().getBoolean(getEnablePath())); + setLocation(HologramRegister.getLocation(this)); + } + + @Override + public List getPages() { + if (ConfigUtil.getInstance() == null) return new ArrayList<>(); + FileConfiguration config = PlotSystem.getPlugin().getConfig(); + return Arrays.stream(LeaderboardTimeframe.values()) + .filter(p -> config.getBoolean(p.configPath)).map(LeaderboardTimeframe::toString).toList(); + } + + @Override + public void create(Player player) { + if (getPages().isEmpty()) { + PlotSystem.getPlugin().getLogger().log(Level.WARNING, "Unable to initialize Score-Leaderboard - No display pages enabled! Check config for display-options."); + return; + } + + super.create(player); + } + + @Override + public boolean hasViewPermission(UUID uuid) { + return true; + } + + @Override + public ItemStack getItem() { + return new ItemStack(BaseItems.LEADERBOARD_SCORE.getItem()); + } + + @Override + public String getTitle(UUID playerUUID) { + return "§b§lTOP SCORE §6§l[" + (sortByLeaderboard.toString().charAt(0) + + sortByLeaderboard.toString().toLowerCase().substring(1)) + "]"; + } + + @Override + public List> getHeader(UUID playerUUID) { + sortByLeaderboard = LeaderboardTimeframe.valueOf(currentPage); + return super.getHeader(playerUUID); + } + + @Override + public List> getContent(UUID playerUUID) { + ArrayList> lines = new ArrayList<>(); + + for (int index = 0; index < 10; index++) { + lines.add(new HologramRegister.LeaderboardPositionLine(index + 1, null, 0)); + } + + Map playerRankings = DataProvider.BUILDER.getLeaderboardEntries(sortByLeaderboard); + int i = 0; + for (Map.Entry entry : playerRankings.entrySet()) { + lines.set(i, new HologramRegister.LeaderboardPositionLine(i + 1, entry.getKey(), entry.getValue())); + i++; + } + return lines; + } + + @Override + public long getInterval() { + return PlotSystem.getPlugin().getConfig().getInt(ConfigPaths.DISPLAY_OPTIONS_INTERVAL) * 20L; + } + + @Override + public String getEnablePath() { + return ConfigPaths.SCORE_LEADERBOARD_ENABLE; + } + + @Override + public String getXPath() { + return ConfigPaths.SCORE_LEADERBOARD_X; + } + + @Override + public String getYPath() { + return ConfigPaths.SCORE_LEADERBOARD_Y; + } + + @Override + public String getZPath() { + return ConfigPaths.SCORE_LEADERBOARD_Z; + } +} \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractMenu.java index 0dfc4ce4a..0b3c2f21f 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractMenu.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus; import com.alpsbte.plotsystem.PlotSystem; @@ -38,11 +14,11 @@ public abstract class AbstractMenu { private final Player menuPlayer; private final String title; - public AbstractMenu(int rows, String title, Player menuPlayer) { + protected AbstractMenu(int rows, String title, Player menuPlayer) { this(rows, title, menuPlayer, true); } - public AbstractMenu(int rows, String title, Player menuPlayer, boolean reload) { + protected AbstractMenu(int rows, String title, Player menuPlayer, boolean reload) { this.title = title; this.menuPlayer = menuPlayer; this.menu = ChestMenu.builder(rows).title(text(title)).redraw(true).build(); @@ -53,12 +29,16 @@ public AbstractMenu(int rows, String title, Player menuPlayer, boolean reload) { /** * Places items asynchronously in the menu after it is opened */ - protected abstract void setMenuItemsAsync(); + protected void setMenuItemsAsync() { + // Default just does nothing, for use-cases which doesn't need it. + } /** * Sets click events for the items placed in the menu async after it is opened */ - protected abstract void setItemClickEventsAsync(); + protected void setItemClickEventsAsync() { + // Default just does nothing, for use-cases which doesn't need it. + } /** * Places pre-defined items in the menu before it is opened diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractPaginatedMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractPaginatedMenu.java index 8c52640e2..57231c609 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractPaginatedMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/AbstractPaginatedMenu.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021-2022, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus; import com.alpsbte.plotsystem.PlotSystem; @@ -36,7 +12,7 @@ public abstract class AbstractPaginatedMenu extends AbstractMenu { private int totalItemsAmount; private int currentPage = 0; - public AbstractPaginatedMenu(int rows, int pagedRows, String title, Player menuPlayer) { + protected AbstractPaginatedMenu(int rows, int pagedRows, String title, Player menuPlayer) { super(rows, title, menuPlayer, false); this.maxItemsPerPage = pagedRows * 9; reloadMenuAsync(); diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/BuilderUtilitiesMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/BuilderUtilitiesMenu.java index 8f0e74b96..1c3f26ac4 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/BuilderUtilitiesMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/BuilderUtilitiesMenu.java @@ -1,35 +1,12 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; -import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; +import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; +import com.alpsbte.plotsystem.utils.items.BaseItems; import com.alpsbte.plotsystem.utils.items.MenuItems; import net.kyori.adventure.text.Component; import org.bukkit.Material; @@ -100,9 +77,9 @@ protected void setItemClickEventsAsync() { @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(Component.empty()).build()) - .pattern("111111111") - .pattern("000000000") + .item(Utils.DEFAULT_ITEM) + .pattern(Utils.FULL_MASK) + .pattern(Utils.EMPTY_MASK) .pattern("111101111") .build(); } @@ -111,7 +88,7 @@ protected Mask getMask() { * @return Menu item */ public static ItemStack getMenuItem(Player player) { - return new ItemBuilder(Material.GOLDEN_AXE) + return new ItemBuilder(BaseItems.BUILDER_UTILITIES.getItem()) .setName(Component.text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.BUILDER_UTILITIES), AQUA, BOLD)) .setLore(new LoreBuilder() .addLine(LangUtil.getInstance().get(player, LangPaths.MenuDescription.BUILDER_UTILITIES), true).build()) diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/FeedbackMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/FeedbackMenu.java index 6c97e3cd2..88a162a69 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/FeedbackMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/FeedbackMenu.java @@ -1,62 +1,42 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus; import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; -import com.alpsbte.plotsystem.core.system.Review; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.core.system.review.PlotReview; +import com.alpsbte.plotsystem.core.system.review.ToggleCriteria; import com.alpsbte.plotsystem.utils.Utils; -import com.alpsbte.plotsystem.utils.enums.Category; -import com.alpsbte.plotsystem.utils.items.MenuItems; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; +import com.alpsbte.plotsystem.utils.items.BaseItems; +import com.alpsbte.plotsystem.utils.items.MenuItems; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; import org.ipvp.canvas.mask.BinaryMask; import org.ipvp.canvas.mask.Mask; -import java.sql.ResultSet; -import java.sql.SQLException; - import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class FeedbackMenu extends AbstractMenu { - private Review review = null; + private PlotReview review = null; private final Plot plot; - public FeedbackMenu(Player player, int plotID) throws SQLException { + public FeedbackMenu(Player player, int plotID) { super(3, LangUtil.getInstance().get(player, LangPaths.MenuTitle.FEEDBACK, String.valueOf(plotID)), player); - this.plot = new Plot(plotID); + this.plot = DataProvider.PLOT.getPlotById(plotID); } @Override @@ -68,84 +48,91 @@ protected void setPreviewItems() { @Override protected void setMenuItemsAsync() { // Get review id from plot - try (ResultSet rs = DatabaseConnection.createStatement("SELECT review_id FROM plotsystem_plots WHERE id = ?") - .setValue(plot.getID()).executeQuery()) { - - if (rs.next()) this.review = new Review(rs.getInt(1)); - DatabaseConnection.closeResultSet(rs); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + plot.getLatestReview().ifPresent(value -> this.review = value); // Set score item - try { - getMenu().getSlot(10).setItem(new ItemBuilder(Material.NETHER_STAR) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.SCORE), AQUA, BOLD)) - .setLore(new LoreBuilder() - .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.TOTAL_SCORE) + ": ", GRAY).append(text(plot.getTotalScore(), WHITE))) - .emptyLine() - .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.ACCURACY) + ": ", GRAY) - .append(Utils.ItemUtils.getColoredPointsComponent(review.getRating(Category.ACCURACY)) - .append(text("/", DARK_GRAY)) - .append(text("5", GREEN)))) - .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.BLOCK_PALETTE) + ": ", GRAY) - .append(Utils.ItemUtils.getColoredPointsComponent(review.getRating(Category.BLOCKPALETTE))) - .append(text("/", DARK_GRAY)) - .append(text("5", GREEN))) - .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.DETAILING) + ": ", GRAY) - .append(Utils.ItemUtils.getColoredPointsComponent(review.getRating(Category.DETAILING))) - .append(text("/", DARK_GRAY)) - .append(text("5", GREEN))) - .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.TECHNIQUE) + ": ", GRAY) - .append(Utils.ItemUtils.getColoredPointsComponent(review.getRating(Category.TECHNIQUE))) - .append(text("/", DARK_GRAY)) - .append(text("5", GREEN))) - .emptyLine() - .addLine(plot.isRejected() - ? text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.REJECTED), RED, BOLD) - : text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.ACCEPTED), GREEN, BOLD)) - .build()) - .build()); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - getMenu().getSlot(10).setItem(MenuItems.errorItem(getMenuPlayer())); - } + getMenu().getSlot(10).setItem(new ItemBuilder(BaseItems.REVIEW_SCORE.getItem()) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.SCORE), AQUA, BOLD)) + .setLore(new LoreBuilder() + .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.TOTAL_SCORE) + ": ", GRAY).append(text(review.getScore(), WHITE))) + .emptyLine() + .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.ACCURACY) + ": ", GRAY) + .append(Utils.ItemUtils.getColoredPointsComponent(review.getRating().getAccuracyPoints(), 5) + .append(text("/", DARK_GRAY)) + .append(text("5", GREEN)))) + .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.BLOCK_PALETTE) + ": ", GRAY) + .append(Utils.ItemUtils.getColoredPointsComponent(review.getRating().getBlockPalettePoints(), 5)) + .append(text("/", DARK_GRAY)) + .append(text("5", GREEN))) + .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.TOGGLE_POINTS) + ": ", GRAY) + .append(Utils.ItemUtils.getColoredPointsComponent(review.getRating().getTogglePoints(), 10)) + .append(text("/", DARK_GRAY)) + .append(text("10", GREEN))) + .emptyLine() + .addLine(plot.isRejected() + ? text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.REJECTED), RED, BOLD) + : text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.ACCEPTED), GREEN, BOLD)) + .build()) + .build()); + + // Set toggles item + getMenu().getSlot(12).setItem(getTogglesItem()); // Set feedback text item - try { - getMenu().getSlot(13).setItem(new ItemBuilder(Material.WRITABLE_BOOK) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.FEEDBACK), AQUA, BOLD)) - .setLore(new LoreBuilder() - .addLine(plot.getReview().getFeedback().replaceAll("//", " "), true) - .build()) - .build()); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - getMenu().getSlot(13).setItem(MenuItems.errorItem(getMenuPlayer())); - } + String feedbackText = review.getFeedback() == null ? LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.NO_FEEDBACK) : review.getFeedback(); + getMenu().getSlot(14).setItem(new ItemBuilder(BaseItems.REVIEW_FEEDBACK.getItem()) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.FEEDBACK), AQUA, BOLD)) + .setLore(new LoreBuilder() + .addLine(feedbackText.replace("//", " "), true) + .build()) + .build()); // Set reviewer item - try { - getMenu().getSlot(16).setItem(new ItemBuilder(AlpsHeadUtils.getPlayerHead(review.getReviewer().getUUID())) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.REVIEWER), AQUA, BOLD)) - .setLore(new LoreBuilder().addLine(review.getReviewer().getName()).build()) - .build()); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - getMenu().getSlot(13).setItem(MenuItems.errorItem(getMenuPlayer())); - } + getMenu().getSlot(16).setItem(new ItemBuilder(AlpsHeadUtils.getPlayerHead(review.getReviewerUUID())) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.REVIEWER), AQUA, BOLD)) + .setLore(new LoreBuilder().addLine(review.getReviewer().getName()).build()) + .build()); } - @Override - protected void setItemClickEventsAsync() {} - @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(empty()).build()) - .pattern("111111111") - .pattern("000000000") - .pattern("111111111") + .item(Utils.DEFAULT_ITEM) + .pattern(Utils.FULL_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.FULL_MASK) .build(); } -} + + private ItemStack getTogglesItem() { + ItemBuilder itemBuilder = new ItemBuilder(BaseItems.REVIEW_TOGGLE_CHECKED.getItem()) + .setName(text("Toggle Criteria", AQUA, BOLD)); + + + int totalCheckCriteriaCount = review.getRating().getAllToggles().size(); + int checkedCount = review.getRating().getCheckedToggles().size(); + LoreBuilder loreBuilder = new LoreBuilder() + .addLine(text(checkedCount + "/" + totalCheckCriteriaCount, GRAY)); + + if (!review.getRating().getUncheckedToggles().isEmpty()) { + loreBuilder.emptyLine(); + loreBuilder.addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.CRITERIA_NOT_FULFILLED) + ":", RED, BOLD)); + for (ToggleCriteria unchecked : review.getRating().getUncheckedToggles()) { + loreBuilder.addLine(text("• ", DARK_GRAY).append(text(unchecked.getDisplayName(getMenuPlayer()), GRAY) + .append(unchecked.isOptional() + ? empty() + : text(" - ").append(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.REQUIRED), GOLD))))); + } + } + + if (!review.getRating().getCheckedToggles().isEmpty()) { + loreBuilder.emptyLine(); + loreBuilder.addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.CRITERIA_FULFILLED) + ":", GREEN, BOLD)); + for (ToggleCriteria unchecked : review.getRating().getCheckedToggles()) { + loreBuilder.addLine(text("• ", DARK_GRAY).append(text(unchecked.getDisplayName(getMenuPlayer()), GRAY))); + } + } + + return itemBuilder.setLore(loreBuilder.build()).build(); + } +} \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/PlayerPlotsMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/PlayerPlotsMenu.java index 75b5bd7ce..09b11c689 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/PlayerPlotsMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/PlayerPlotsMenu.java @@ -1,53 +1,37 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus; import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; +import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; -import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; -import com.alpsbte.alpslib.utils.item.ItemBuilder; +import com.alpsbte.plotsystem.core.system.review.PlotReview; +import com.alpsbte.plotsystem.core.system.review.ReviewRating; import com.alpsbte.plotsystem.utils.Utils; -import com.alpsbte.plotsystem.utils.enums.Category; -import com.alpsbte.plotsystem.utils.items.BaseItems; -import com.alpsbte.plotsystem.utils.items.MenuItems; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; +import com.alpsbte.plotsystem.utils.items.BaseItems; +import com.alpsbte.plotsystem.utils.items.MenuItems; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.ipvp.canvas.mask.BinaryMask; import org.ipvp.canvas.mask.Mask; +import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; import java.util.List; +import java.util.Optional; -import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class PlayerPlotsMenu extends AbstractMenu { @@ -56,7 +40,7 @@ public class PlayerPlotsMenu extends AbstractMenu { private int plotDisplayCount = 0; - public PlayerPlotsMenu(Player menuPlayer, Builder builder) throws SQLException { + public PlayerPlotsMenu(Player menuPlayer, @NotNull Builder builder) { super(6, LangUtil.getInstance().get(menuPlayer.getPlayer(), LangPaths.MenuTitle.PLAYER_PLOTS, builder.getName() + "'"), menuPlayer); this.builder = builder; } @@ -75,48 +59,34 @@ protected void setPreviewItems() { @Override protected void setMenuItemsAsync() { // Set player stats item - try { - getMenu().getSlot(4) - .setItem(new ItemBuilder(AlpsHeadUtils.getPlayerHead(builder.getUUID())) - .setName(text(builder.getName(), GOLD).decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.SCORE) + ": ", GRAY) - .append(text(builder.getScore(), WHITE))) - .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.COMPLETED_PLOTS) + ": ", GRAY) - .append(text(builder.getCompletedBuilds(), WHITE))) - .build()) - .build()); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - getMenu().getSlot(4).setItem(MenuItems.errorItem(getMenuPlayer())); - } + getMenu().getSlot(4) + .setItem(new ItemBuilder(AlpsHeadUtils.getPlayerHead(builder.getUUID())) + .setName(text(builder.getName(), GOLD).decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.SCORE) + ": ", GRAY) + .append(text(builder.getScore(), WHITE))) + .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.COMPLETED_PLOTS) + ": ", GRAY) + .append(text(builder.getCompletedBuildsCount(), WHITE))) + .build()) + .build()); // Set player plot items - try { - plots = Plot.getPlots(builder); - - plotDisplayCount = Math.min(plots.size(), 36); - for (int i = 0; i < plotDisplayCount; i++) { - Plot plot = plots.get(i); - try { - ItemStack item = switch (plot.getStatus()) { - case unfinished -> BaseItems.PLOT_UNFINISHED.getItem(); - case unreviewed -> BaseItems.PLOT_UNREVIEWED.getItem(); - default -> BaseItems.PLOT_COMPLETED.getItem(); - }; - - getMenu().getSlot(9 + i) - .setItem(new ItemBuilder(item) - .setName(text(plot.getCity().getName() + " | " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.PLOT_NAME) + " #" + plot.getID(), AQUA).decoration(BOLD, true)) - .setLore(getLore(plot, getMenuPlayer()).build()) - .build()); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - getMenu().getSlot(9 + i).setItem(MenuItems.errorItem(getMenuPlayer())); - } - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + plots = DataProvider.PLOT.getPlots(builder); + + plotDisplayCount = Math.min(plots.size(), 36); + for (int i = 0; i < plotDisplayCount; i++) { + Plot plot = plots.get(i); + ItemStack item = switch (plot.getStatus()) { + case unfinished -> BaseItems.PLOT_UNFINISHED.getItem(); + case unreviewed -> BaseItems.PLOT_UNREVIEWED.getItem(); + default -> BaseItems.PLOT_COMPLETED.getItem(); + }; + + getMenu().getSlot(9 + i) + .setItem(new ItemBuilder(item) + .setName(text(plot.getCityProject().getName(getMenuPlayer()) + " | " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.PLOT_NAME) + " #" + plot.getId(), AQUA).decoration(BOLD, true)) + .setLore(getLore(plot, getMenuPlayer()).build()) + .build()); } } @@ -126,12 +96,8 @@ protected void setItemClickEventsAsync() { for (int i = 0; i < plotDisplayCount; i++) { int itemSlot = i; getMenu().getSlot(9 + i).setClickHandler((clickPlayer, clickInformation) -> { - try { - new PlotActionsMenu(clickPlayer, plots.get(itemSlot)); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - clickPlayer.closeInventory(); - } + if (plots.get(itemSlot).getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) return; + new PlotActionsMenu(clickPlayer, plots.get(itemSlot)); }); } @@ -142,12 +108,12 @@ protected void setItemClickEventsAsync() { @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(empty()).build()) + .item(Utils.DEFAULT_ITEM) .pattern("111101111") - .pattern("000000000") - .pattern("000000000") - .pattern("000000000") - .pattern("000000000") + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) .pattern("111101111") .build(); } @@ -159,57 +125,67 @@ protected Mask getMask() { * @param p player instance for language system * @return description lore for plot item */ - private LoreBuilder getLore(Plot plot, Player p) throws SQLException { - LoreBuilder builder = new LoreBuilder(); + private @NotNull LoreBuilder getLore(@NotNull Plot plot, Player p) { + LoreBuilder loreBuilder = new LoreBuilder(); + + Optional review = plot.getLatestReview(); + int score = (review.isEmpty() || plot.isRejected()) ? 0 : review.get().getScore(); if (plot.getPlotMembers().isEmpty()) { // Plot is single player plot - builder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Plot.TOTAL_SCORE) + ": ", GRAY) - .append(text((plot.getTotalScore() == -1 ? 0 : plot.getTotalScore()), WHITE))); + loreBuilder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Plot.TOTAL_SCORE) + ": ", GRAY) + .append(text(score, WHITE))); } else { // Plot is multiplayer plot - builder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Plot.OWNER) + ": ", GRAY) + loreBuilder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Plot.OWNER) + ": ", GRAY) .append(text(plot.getPlotOwner().getName(), WHITE))); - builder.emptyLine(); + loreBuilder.emptyLine(); - int score = (plot.getTotalScore() == -1 ? 0 : plot.getTotalScore()); - builder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Plot.TOTAL_SCORE) + ": ", GRAY) + loreBuilder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Plot.TOTAL_SCORE) + ": ", GRAY) .append(text(score + " ", WHITE)) - .append(text(LangUtil.getInstance().get(p, LangPaths.Plot.GroupSystem.SHARED_BY_MEMBERS, Integer.toString(plot.getPlotMembers().size() + 1)), DARK_GRAY))); + .append(text(LangUtil.getInstance().get(p, LangPaths.Plot.GroupSystem.SHARED_BY_MEMBERS, + Integer.toString(plot.getPlotMembers().size() + 1)), DARK_GRAY))); } - if (plot.isReviewed() || plot.isRejected()) { - builder.emptyLine(); - builder.addLines( + if (review.isPresent()) { + ReviewRating rating = review.get().getRating(); + loreBuilder.emptyLine(); + loreBuilder.addLines( text(LangUtil.getInstance().get(p, LangPaths.Review.Criteria.ACCURACY) + ": ", GRAY) - .append(Utils.ItemUtils.getColoredPointsComponent(plot.getReview().getRating(Category.ACCURACY))) + .append(Utils.ItemUtils.getColoredPointsComponent(rating.getAccuracyPoints(), 5)) .append(text("/", DARK_GRAY)).append(text("5", GREEN)), text(LangUtil.getInstance().get(p, LangPaths.Review.Criteria.BLOCK_PALETTE) + ": ", GRAY) - .append(Utils.ItemUtils.getColoredPointsComponent(plot.getReview().getRating(Category.BLOCKPALETTE))) - .append(text("/", DARK_GRAY)).append(text("5", GREEN)), - text(LangUtil.getInstance().get(p, LangPaths.Review.Criteria.DETAILING) + ": ", GRAY) - .append(Utils.ItemUtils.getColoredPointsComponent(plot.getReview().getRating(Category.DETAILING))) - .append(text("/", DARK_GRAY)).append(text("5", GREEN)), - text(LangUtil.getInstance().get(p, LangPaths.Review.Criteria.TECHNIQUE) + ": ", GRAY) - .append(Utils.ItemUtils.getColoredPointsComponent(plot.getReview().getRating(Category.TECHNIQUE))) + .append(Utils.ItemUtils.getColoredPointsComponent(rating.getBlockPalettePoints(), 5)) .append(text("/", DARK_GRAY)).append(text("5", GREEN)) ); - builder.emptyLine(); - builder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Review.FEEDBACK) + ":", GRAY)); - builder.addLine(text(plot.getReview().getFeedback().replaceAll("//", " "), WHITE), true); + if (plot.getVersion() > AbstractPlot.LEGACY_VERSION_THRESHOLD) { + loreBuilder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Review.TOGGLE_POINTS) + ": ", GRAY) + .append(Utils.ItemUtils.getColoredPointsComponent(rating.getTogglePoints(), 10)) + .append(text("/", DARK_GRAY)).append(text("10", GREEN))); + } + loreBuilder.emptyLine(); + loreBuilder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Review.FEEDBACK) + ":", GRAY)); + String feedback = review.get().getFeedback() == null + ? LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.NO_FEEDBACK) + : review.get().getFeedback().replace("//", " "); + loreBuilder.addLine(text(feedback, WHITE), true); } - builder.emptyLine(); - if (plot.isReviewed() && plot.isRejected()) builder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Review.REJECTED), RED, BOLD)); - builder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Plot.STATUS) + ": ", GRAY) + loreBuilder.emptyLine(); + if (plot.isRejected()) loreBuilder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Review.REJECTED), RED, BOLD)); + loreBuilder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Plot.STATUS) + ": ", GRAY) .append(text(plot.getStatus().name().substring(0, 1).toUpperCase() + plot.getStatus().name().substring(1), WHITE))); - return builder; + + if (plot.getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) { + loreBuilder.addLine(text(LangUtil.getInstance().get(p, LangPaths.Note.LEGACY), RED).decoration(BOLD, true)); + } + return loreBuilder; } /** * @return Menu item */ - public static ItemStack getMenuItem(Player p) { + public static ItemStack getMenuItem(@NotNull Player p) { return new ItemBuilder(AlpsHeadUtils.getPlayerHead(p.getUniqueId())) .setName(text(LangUtil.getInstance().get(p, LangPaths.MenuTitle.SHOW_PLOTS), AQUA, BOLD)) .setLore(new LoreBuilder() diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/PlotActionsMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/PlotActionsMenu.java index 7b0c8f652..d2924c14b 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/PlotActionsMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/PlotActionsMenu.java @@ -1,104 +1,76 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus; -import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; +import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.alpsbte.plotsystem.utils.items.CustomHeads; -import com.alpsbte.plotsystem.utils.items.MenuItems; -import net.kyori.adventure.text.Component; -import org.bukkit.Material; +import com.alpsbte.plotsystem.utils.items.BaseItems; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.ipvp.canvas.mask.BinaryMask; import org.ipvp.canvas.mask.Mask; +import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; - -import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class PlotActionsMenu extends AbstractMenu { private final Plot plot; - private final boolean hasFeedback; + private final boolean hasReview; + final FileConfiguration config; - public PlotActionsMenu(Player menuPlayer, Plot plot) throws SQLException { - super(3, LangUtil.getInstance().get(menuPlayer, LangPaths.Plot.PLOT_NAME) + " #" + plot.getID() + " | " + plot.getStatus().name().substring(0, 1).toUpperCase() + plot.getStatus().name().substring(1), menuPlayer); + public PlotActionsMenu(Player menuPlayer, @NotNull Plot plot) { + super(3, LangUtil.getInstance().get(menuPlayer, LangPaths.Plot.PLOT_NAME) + " #" + plot.getId() + " | " + plot.getStatus().name().substring(0, 1).toUpperCase() + plot.getStatus().name().substring(1), menuPlayer); this.plot = plot; - hasFeedback = plot.isReviewed() || plot.isRejected(); + hasReview = plot.getLatestReview().isPresent(); + config = PlotSystem.getPlugin().getConfig(); } @Override protected void setMenuItemsAsync() { // Set plot submit or undo submit item - try { - if (plot.getStatus().equals(Status.unreviewed)) { - getMenu().getSlot(10) - .setItem(new ItemBuilder(Material.FIRE_CHARGE, 1) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.UNDO_SUBMIT), RED).decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.UNDO_SUBMIT), true).build()) - .build()); - } else { - getMenu().getSlot(10) - .setItem(new ItemBuilder(Material.NAME_TAG, 1) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.SUBMIT), GREEN).decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.SUBMIT_PLOT)).color(GRAY), true) - .emptyLine() - .addLine(Utils.ItemUtils.getNoteFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.WONT_BE_ABLE_CONTINUE_BUILDING))) - .build()) - .build()); - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - getMenu().getSlot(10).setItem(MenuItems.errorItem(getMenuPlayer())); + if (plot.getStatus().equals(Status.unreviewed)) { + getMenu().getSlot(10) + .setItem(new ItemBuilder(BaseItems.PLOT_UNDO_SUBMIT.getItem()) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.UNDO_SUBMIT), RED).decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.UNDO_SUBMIT), true).build()) + .build()); + } else { + getMenu().getSlot(10) + .setItem(new ItemBuilder(BaseItems.PLOT_SUBMIT.getItem()) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.SUBMIT), GREEN).decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.SUBMIT_PLOT)).color(GRAY), true) + .emptyLine() + .addLine(Utils.ItemUtils.getNoteFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.WONT_BE_ABLE_CONTINUE_BUILDING))) + .build()) + .build()); } // Set teleport to plot item - getMenu().getSlot(hasFeedback ? 12 : 13) - .setItem(new ItemBuilder(Material.COMPASS, 1) + getMenu().getSlot(hasReview ? 12 : 13) + .setItem(new ItemBuilder(BaseItems.PLOT_TELEPORT.getItem()) .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.TELEPORT), GOLD).decoration(BOLD, true)) .setLore(new LoreBuilder().addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.TELEPORT)).color(GRAY), true).build()) .build()); // Set plot abandon item - getMenu().getSlot(hasFeedback ? 14 : 16) - .setItem(new ItemBuilder(Material.BARRIER, 1) + getMenu().getSlot(hasReview ? 14 : 16) + .setItem(new ItemBuilder(BaseItems.PLOT_ABANDON.getItem()) .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.ABANDON), RED).decoration(BOLD, true)) .setLore(new LoreBuilder() .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.ABANDON), true) @@ -108,42 +80,39 @@ protected void setMenuItemsAsync() { .build()); // Set plot feedback item - if (hasFeedback) { + if (hasReview) { getMenu().getSlot(16) - .setItem(new ItemBuilder(Material.WRITABLE_BOOK) + .setItem(new ItemBuilder(BaseItems.REVIEW_FEEDBACK.getItem()) .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.FEEDBACK), AQUA).decoration(BOLD, true)) .setLore(new LoreBuilder().addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.FEEDBACK), true).build()) .build()); } - + // Set plot members item - try { - if (!plot.isReviewed()) { - FileConfiguration config = PlotSystem.getPlugin().getConfig(); - if ((getMenuPlayer() == plot.getPlotOwner().getPlayer() || getMenuPlayer().hasPermission("plotsystem.admin")) && config.getBoolean(ConfigPaths.ENABLE_GROUP_SUPPORT)) { - getMenu().getSlot(22) - .setItem(new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.ADD_BUTTON.getId())) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.MANAGE_MEMBERS), AQUA).decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.MANAGE_MEMBERS), true) - .emptyLine() - .addLine(Utils.ItemUtils.getNoteFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.SCORE_WILL_BE_SPLIT))) - .build()) - .build()); - } else if (plot.getPlotMembers().stream().anyMatch(m -> m.getUUID().equals(getMenuPlayer().getUniqueId()))) { - getMenu().getSlot(22) - .setItem(new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.REMOVE_BUTTON.getId())) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.LEAVE_PLOT), AQUA).decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.LEAVE_PLOT), true) - .emptyLine() - .addLine(Utils.ItemUtils.getNoteFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.WONT_BE_ABLE_CONTINUE_BUILDING))) - .build()) - .build()); - } + if (!plot.isReviewed() && config.getBoolean(ConfigPaths.ENABLE_GROUP_SUPPORT)) { + if ((getMenuPlayer() == plot.getPlotOwner().getPlayer() || getMenuPlayer().hasPermission("plotsystem.admin"))) { + getMenu().getSlot(22) + .setItem(new ItemBuilder(BaseItems.MENU_ADD.getItem()) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.MANAGE_MEMBERS), AQUA).decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.MANAGE_MEMBERS), true) + .emptyLine() + .addLine(Utils.ItemUtils.getNoteFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.SCORE_WILL_BE_SPLIT))) + .build()) + .build()); + } else if (plot.getPlotMembers().stream().anyMatch(m -> m.getUUID().equals(getMenuPlayer().getUniqueId()))) { + getMenu().getSlot(22) + .setItem(new ItemBuilder(BaseItems.MENU_REMOVE.getItem()) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.LEAVE_PLOT), AQUA).decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.LEAVE_PLOT), true) + .emptyLine() + .addLine(Utils.ItemUtils.getNoteFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.WONT_BE_ABLE_CONTINUE_BUILDING))) + .build()) + .build()); } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + } else { + getMenu().getSlot(22).setItem(Utils.DEFAULT_ITEM); } } @@ -152,36 +121,36 @@ protected void setItemClickEventsAsync() { // Set click event for submit or undo submit plot item getMenu().getSlot(10).setClickHandler((clickPlayer, clickInformation) -> { clickPlayer.closeInventory(); - try { - clickPlayer.performCommand("plot " + (plot.getStatus().equals(Status.unreviewed) ? "undosubmit " : "submit ") + plot.getID()); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + clickPlayer.performCommand("plot " + (plot.getStatus().equals(Status.unreviewed) ? "undosubmit " : "submit ") + plot.getId()); }); // Set click event for teleport to plot item - getMenu().getSlot(hasFeedback ? 12 : 13).setClickHandler((clickPlayer, clickInformation) -> { + getMenu().getSlot(hasReview ? 12 : 13).setClickHandler((clickPlayer, clickInformation) -> { clickPlayer.closeInventory(); + if (plot.getVersion() <= AbstractPlot.LEGACY_VERSION_THRESHOLD) { + clickPlayer.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(clickPlayer, LangPaths.Message.Error.CANNOT_LOAD_LEGACY_PLOT))); + return; + } plot.getWorld().teleportPlayer(clickPlayer); }); // Set click event for abandon plot item - getMenu().getSlot(hasFeedback ? 14 : 16).setClickHandler((clickPlayer, clickInformation) -> { + getMenu().getSlot(hasReview ? 14 : 16).setClickHandler((clickPlayer, clickInformation) -> { clickPlayer.closeInventory(); - clickPlayer.performCommand("plot abandon " + plot.getID()); + clickPlayer.performCommand("plot abandon " + plot.getId()); }); // Set click event for feedback menu button - if (hasFeedback) { + if (hasReview) { getMenu().getSlot(16).setClickHandler((clickPlayer, clickInformation) -> { clickPlayer.closeInventory(); - clickPlayer.performCommand("plot feedback " + plot.getID()); + clickPlayer.performCommand("plot feedback " + plot.getId()); }); } // Set click event for plot members item - getMenu().getSlot(22).setClickHandler((clickPlayer, clickInformation) -> { - try { + if (!plot.isReviewed() && config.getBoolean(ConfigPaths.ENABLE_GROUP_SUPPORT)) { + getMenu().getSlot(22).setClickHandler((clickPlayer, clickInformation) -> { if (plot.isReviewed()) return; if (plot.getStatus() != Status.unfinished) { clickPlayer.closeInventory(); @@ -196,21 +165,19 @@ protected void setItemClickEventsAsync() { // Leave Plot clickPlayer.closeInventory(); plot.removePlotMember(Builder.byUUID(clickPlayer.getUniqueId())); - clickPlayer.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.LEFT_PLOT, Integer.toString(plot.getID())))); + clickPlayer.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.LEFT_PLOT, Integer.toString(plot.getId())))); } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - }); + }); + } } @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(Component.empty()).build()) - .pattern("111111111") - .pattern("000000000") - .pattern("111111111") + .item(Utils.DEFAULT_ITEM) + .pattern(Utils.FULL_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.FULL_MASK) .build(); } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/PlotMemberMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/PlotMemberMenu.java index 34992e0f1..1fc54affd 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/PlotMemberMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/PlotMemberMenu.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus; import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; @@ -35,21 +11,23 @@ import com.alpsbte.plotsystem.utils.chat.PlayerInviteeChatInput; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.alpsbte.plotsystem.utils.items.CustomHeads; +import com.alpsbte.plotsystem.utils.items.BaseItems; import com.alpsbte.plotsystem.utils.items.MenuItems; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.event.inventory.InventoryCloseEvent; import org.bukkit.inventory.ItemStack; import org.ipvp.canvas.mask.BinaryMask; import org.ipvp.canvas.mask.Mask; +import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; import java.util.List; import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class PlotMemberMenu extends AbstractMenu { @@ -58,9 +36,16 @@ public class PlotMemberMenu extends AbstractMenu { private final ItemStack emptyMemberSlotItem = new ItemBuilder(Material.GREEN_STAINED_GLASS_PANE, 1).setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.GroupSystem.EMPTY_MEMBER_SLOTS), DARK_GREEN).decoration(BOLD, true)).build(); private List builders; - public PlotMemberMenu(Plot plot, Player menuPlayer) { - super(3, LangUtil.getInstance().get(menuPlayer, LangPaths.MenuTitle.MANAGE_MEMBERS) + " | " + LangUtil.getInstance().get(menuPlayer, LangPaths.Plot.PLOT_NAME) + " #" + plot.getID(), menuPlayer); + public PlotMemberMenu(@NotNull Plot plot, Player menuPlayer) { + // Avoid opening the menu before 'plot' is assigned + super(3, + LangUtil.getInstance().get(menuPlayer, LangPaths.MenuTitle.MANAGE_MEMBERS) + " | " + + LangUtil.getInstance().get(menuPlayer, LangPaths.Plot.PLOT_NAME) + " #" + plot.getId(), + menuPlayer, + false); this.plot = plot; + // Now that 'plot' is set, we can safely load the menu + reloadMenuAsync(); } @Override @@ -69,23 +54,21 @@ protected void setPreviewItems() { getMenu().getSlot(10).setItem(MenuItems.loadingItem(Material.PLAYER_HEAD, getMenuPlayer())); // Set loading item for plot member items - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { - try { - List plotMembers = plot.getPlotMembers(); - for (int i = 1; i <= 3; i++) { - getMenu().getSlot(11 + i).setItem(plotMembers.size() >= i - ? MenuItems.loadingItem(Material.PLAYER_HEAD, getMenuPlayer()) - : emptyMemberSlotItem); - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + if (plot != null) { + List plotMembers = plot.getPlotMembers(); + for (int i = 1; i <= 3; i++) { + getMenu().getSlot(11 + i).setItem(plotMembers.size() >= i + ? MenuItems.loadingItem(Material.PLAYER_HEAD, getMenuPlayer()) + : emptyMemberSlotItem); } - }); + } else { + PlotSystem.getPlugin().getComponentLogger().warn(text("PlotMemberMenu: plot is null in setPreviewItems")); + } // Set add plot member item - ItemStack whitePlus = AlpsHeadUtils.getCustomHead(CustomHeads.ADD_BUTTON.getId()); + ItemStack addItem = BaseItems.MENU_ADD.getItem(); getMenu().getSlot(16) - .setItem(new ItemBuilder(whitePlus) + .setItem(new ItemBuilder(addItem) .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.ADD_MEMBER_TO_PLOT), GOLD, BOLD)) .setLore(new LoreBuilder() .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.ADD_MEMBER_TO_PLOT), true) @@ -102,55 +85,57 @@ protected void setPreviewItems() { @Override protected void setMenuItemsAsync() { - // Set plot owner item - try { - getMenu().getSlot(10) - .setItem(new ItemBuilder(AlpsHeadUtils.getPlayerHead(plot.getPlotOwner().getUUID())) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.OWNER), GOLD, BOLD)) - .setLore(new LoreBuilder() - .addLine(plot.getPlotOwner().getName()).build()) - .build()); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + if (plot == null) { + PlotSystem.getPlugin().getComponentLogger().error(text("PlotMemberMenu: plot is null in setMenuItemsAsync, cannot load menu items")); + return; } + // Set plot owner item + getMenu().getSlot(10) + .setItem(new ItemBuilder(AlpsHeadUtils.getPlayerHead(plot.getPlotOwner().getUUID())) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.OWNER), GOLD, BOLD)) + .setLore(new LoreBuilder() + .addLines(text(plot.getPlotOwner().getName()), + empty(), + text(Utils.ItemUtils.getActionFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.Action.CLICK_TO_OPEN_PLOTS_MENUE)))) + .build()) + .build()); + // Set plot member items - try { - builders = plot.getPlotMembers(); - for (int i = 12; i < 15; i++) { - if (builders.size() < (i - 11)) return; - - Builder builder = builders.get(i - 12); - getMenu().getSlot(i) - .setItem(new ItemBuilder(AlpsHeadUtils.getPlayerHead(builder.getUUID())) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.MEMBER), AQUA, BOLD)) - .setLore(new LoreBuilder() - .addLines(text(builder.getName()), - empty(), - text(Utils.ItemUtils.getActionFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.Action.CLICK_TO_REMOVE_PLOT_MEMBER)))) - .build()) - .build()); - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + builders = plot.getPlotMembers(); + for (int i = 12; i < 15; i++) { + if (builders.size() < (i - 11)) return; + + Builder builder = builders.get(i - 12); + getMenu().getSlot(i) + .setItem(new ItemBuilder(AlpsHeadUtils.getPlayerHead(builder.getUUID())) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.MEMBER), AQUA, BOLD)) + .setLore(new LoreBuilder() + .addLines(text(builder.getName()), + empty(), + text(Utils.ItemUtils.getActionFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Note.Action.CLICK_TO_REMOVE_PLOT_MEMBER)))) + .build()) + .build()); } } @Override protected void setItemClickEventsAsync() { + // Set click event for owner slot + getMenu().getSlot(10).setClickHandler((clickPlayer, clickInformation) -> { + clickPlayer.closeInventory(InventoryCloseEvent.Reason.OPEN_NEW); + new PlayerPlotsMenu(clickPlayer, plot.getPlotOwner()); + }); + // Set click event for member slots for (int i = 12; i < 15; i++) { int itemSlot = i; getMenu().getSlot(i).setClickHandler((clickPlayer, clickInformation) -> { if (getMenu().getSlot(itemSlot).getItem(clickPlayer).equals(emptyMemberSlotItem)) return; Builder builder = builders.get(itemSlot - 12); - try { - plot.removePlotMember(builder); - clickPlayer.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), - LangPaths.Message.Info.REMOVED_PLOT_MEMBER, builder.getName(), Integer.toString(plot.getID())))); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + plot.removePlotMember(builder); + clickPlayer.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), + LangPaths.Message.Info.REMOVED_PLOT_MEMBER, builder.getName(), Integer.toString(plot.getId())))); reloadMenuAsync(); }); } @@ -163,22 +148,18 @@ protected void setItemClickEventsAsync() { }); // Set click event for back item - getMenu().getSlot(22).setClickHandler((clickPlayer, clickInformation) -> { - try { - new PlotActionsMenu(clickPlayer, plot); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - }); + getMenu().getSlot(22).setClickHandler((clickPlayer, clickInformation) + -> new PlotActionsMenu(clickPlayer, plot)); } @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(empty()).build()) - .pattern("111111111") - .pattern("000000000") + .item(Utils.DEFAULT_ITEM) + .pattern(Utils.FULL_MASK) + .pattern(Utils.EMPTY_MASK) .pattern("111101111") .build(); } -} \ No newline at end of file +} + diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/PlotTypeMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/PlotTypeMenu.java index 114263d22..a44216cfa 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/PlotTypeMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/PlotTypeMenu.java @@ -1,38 +1,15 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus; -import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; +import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.utils.PlotType; import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.alpsbte.plotsystem.utils.items.CustomHeads; +import com.alpsbte.plotsystem.utils.items.BaseItems; import com.alpsbte.plotsystem.utils.items.MenuItems; import org.bukkit.Material; import org.bukkit.entity.Player; @@ -41,7 +18,9 @@ import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.RED; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class PlotTypeMenu extends AbstractMenu { @@ -62,12 +41,12 @@ protected void setPreviewItems() { protected void setMenuItemsAsync() { // Set plot type items getMenu().getSlot(11).setItem( - new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.FOCUS_MODE_BUTTON.getId())) + new ItemBuilder(BaseItems.PLOT_FOCUS_MODE.getItem()) .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.SELECT_FOCUS_MODE), GOLD, BOLD)) .setLore(new LoreBuilder() .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.SELECT_FOCUS_MODE), true) .build()) - .setEnchanted(builder.getPlotTypeSetting().getId() == PlotType.FOCUS_MODE.getId()) + .setEnchanted(builder.getPlotType().getId() == PlotType.FOCUS_MODE.getId()) .build()); getMenu().getSlot(13).setItem( @@ -76,28 +55,30 @@ protected void setMenuItemsAsync() { .setLore(new LoreBuilder() .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.SELECT_INSPIRATION_MODE), true) .build()) - .setEnchanted(builder.getPlotTypeSetting().getId() == PlotType.LOCAL_INSPIRATION_MODE.getId()) + .setEnchanted(builder.getPlotType().getId() == PlotType.LOCAL_INSPIRATION_MODE.getId()) .build()); - getMenu().getSlot(15).setItem( - new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.CITY_INSPIRATION_MODE_BUTTON.getId())) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.SELECT_CITY_INSPIRATION_MODE), GOLD, BOLD) - .append(text(" [", DARK_GRAY).append(text("BETA", RED).append(text("]", DARK_GRAY))))) // temporary BETA tag - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.SELECT_CITY_INSPIRATION_MODE), true) - .build()) - .setEnchanted(builder.getPlotTypeSetting().getId() == PlotType.CITY_INSPIRATION_MODE.getId()) - .build()); + boolean inspirationModeDisabled = PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DISABLE_CITY_INSPIRATION_MODE); // TODO remove or enhance as soon CIM is working again + getMenu().getSlot(15).setItem(!inspirationModeDisabled ? + new ItemBuilder(BaseItems.PLOT_CITY_INSPIRATION_MODE.getItem()) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.SELECT_CITY_INSPIRATION_MODE), GOLD, BOLD) + .append(text(" [", DARK_GRAY).append(text("BETA", RED).append(text("]", DARK_GRAY))))) // temporary BETA tag + .setLore(new LoreBuilder() + .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.SELECT_CITY_INSPIRATION_MODE), true) + .build()) + .setEnchanted(builder.getPlotType().getId() == PlotType.CITY_INSPIRATION_MODE.getId()) + .build() : Utils.DEFAULT_ITEM); + + // Set selected glass pane int selectedPlotTypeSlot = 13; - if (builder.getPlotTypeSetting() == PlotType.FOCUS_MODE) + if (builder.getPlotType() == PlotType.FOCUS_MODE) selectedPlotTypeSlot = 11; - if (builder.getPlotTypeSetting() == PlotType.CITY_INSPIRATION_MODE) + if (builder.getPlotType() == PlotType.CITY_INSPIRATION_MODE) selectedPlotTypeSlot = 15; getMenu().getSlot(selectedPlotTypeSlot - 9).setItem(new ItemBuilder(Material.LIME_STAINED_GLASS_PANE, 1).setName(empty()).build()); - // Set back item getMenu().getSlot(22).setItem(MenuItems.backMenuItem(getMenuPlayer())); } @@ -106,22 +87,28 @@ protected void setMenuItemsAsync() { protected void setItemClickEventsAsync() { // Set click event for plot type items getMenu().getSlot(11).setClickHandler(((clickPlayer, clickInformation) -> { - builder.setPlotTypeSetting(PlotType.FOCUS_MODE); + boolean successful = builder.setPlotType(PlotType.FOCUS_MODE); + if (!successful) return; getMenuPlayer().playSound(getMenuPlayer().getLocation(), Utils.SoundUtils.DONE_SOUND, 1f, 1f); reloadMenuAsync(); })); getMenu().getSlot(13).setClickHandler(((clickPlayer, clickInformation) -> { - builder.setPlotTypeSetting(PlotType.LOCAL_INSPIRATION_MODE); + boolean successful = builder.setPlotType(PlotType.LOCAL_INSPIRATION_MODE); + if (!successful) return; getMenuPlayer().playSound(getMenuPlayer().getLocation(), Utils.SoundUtils.DONE_SOUND, 1f, 1f); reloadMenuAsync(); })); - getMenu().getSlot(15).setClickHandler(((clickPlayer, clickInformation) -> { - builder.setPlotTypeSetting(PlotType.CITY_INSPIRATION_MODE); - getMenuPlayer().playSound(getMenuPlayer().getLocation(), Utils.SoundUtils.DONE_SOUND, 1f, 1f); - reloadMenuAsync(); - })); + boolean inspirationModeDisabled = PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DISABLE_CITY_INSPIRATION_MODE); // TODO improve or remove when CIM ist working again + if (!inspirationModeDisabled) { + getMenu().getSlot(15).setClickHandler(((clickPlayer, clickInformation) -> { + boolean successful = builder.setPlotType(PlotType.CITY_INSPIRATION_MODE); + if (!successful) return; + getMenuPlayer().playSound(getMenuPlayer().getLocation(), Utils.SoundUtils.DONE_SOUND, 1f, 1f); + reloadMenuAsync(); + })); + } // Set click event for back item getMenu().getSlot(22).setClickHandler((clickPlayer, clickInformation) -> new SettingsMenu(clickPlayer)); @@ -130,9 +117,9 @@ protected void setItemClickEventsAsync() { @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(empty()).build()) - .pattern("111111111") - .pattern("000000000") + .item(Utils.DEFAULT_ITEM) + .pattern(Utils.FULL_MASK) + .pattern(Utils.EMPTY_MASK) .pattern("111101111") .build(); } diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewMenu.java deleted file mode 100644 index 03b40ed77..000000000 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewMenu.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.core.menus; - -import com.alpsbte.alpslib.utils.item.ItemBuilder; -import com.alpsbte.alpslib.utils.item.LegacyLoreBuilder; -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.system.Builder; -import com.alpsbte.plotsystem.core.system.Country; -import com.alpsbte.plotsystem.core.system.plot.Plot; -import com.alpsbte.plotsystem.utils.Utils; -import com.alpsbte.plotsystem.utils.enums.Status; -import com.alpsbte.plotsystem.utils.io.LangPaths; -import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.alpsbte.plotsystem.utils.items.BaseItems; -import com.alpsbte.plotsystem.utils.items.MenuItems; -import net.kyori.adventure.text.Component; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.ipvp.canvas.mask.BinaryMask; -import org.ipvp.canvas.mask.Mask; - -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import static net.kyori.adventure.text.Component.text; - -public class ReviewMenu extends AbstractPaginatedMenu { - private List countries = new ArrayList<>(); - private Country filteredCountry = null; - - public ReviewMenu(Player player) { - super(6, 4, LangUtil.getInstance().get(player, LangPaths.Review.MANAGE_AND_REVIEW_PLOTS), player); - } - - @Override - protected List getSource() { - List plots = new ArrayList<>(); - try { - countries = Builder.byUUID(getMenuPlayer().getUniqueId()).getAsReviewer().getCountries(); - plots.addAll(Plot.getPlots(countries, Status.unreviewed)); - plots.addAll(Plot.getPlots(countries, Status.unfinished)); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - return plots; - } - - @Override - protected void setPreviewItems() { - // Set close item - getMenu().getSlot(49).setItem(MenuItems.closeMenuItem(getMenuPlayer())); - - super.setPreviewItems(); - } - - @Override - protected void setPaginatedMenuItemsAsync(List source) { - // Set filter item - getMenu().getSlot(7).setItem(getFilterItem(getMenuPlayer())); - - // Set unreviewed and unfinished plot items - List plots = getFilteredPlots(source); - for (int i = 0; i < plots.size(); i++) { - try { - Plot plot = plots.get(i); - List lines = new ArrayList<>(); - lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.ID) + ": §f" + plot.getID()); - lines.add(""); - lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.OWNER) + ": §f" + plot.getPlotOwner().getName()); - if (!plot.getPlotMembers().isEmpty()) lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.MEMBERS) + ": §f" + plot.getPlotMembers().stream().map(m -> { - try {return m.getName();} catch (SQLException ex) {PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex);} - return ""; - }).collect(Collectors.joining(", ")) - ); - lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.CITY) + ": §f" + plot.getCity().getName()); - lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.COUNTRY) + ": §f" + plot.getCity().getCountry().getName()); - lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.DIFFICULTY) + ": §f" + plot.getDifficulty().name().charAt(0) + plot.getDifficulty().name().substring(1).toLowerCase()); - - getMenu().getSlot(i + 9).setItem(new ItemBuilder(plot.getStatus() == Status.unfinished ? Material.MAP : Material.FILLED_MAP, 1) - .setName("§b§l" + LangUtil.getInstance().get(getMenuPlayer(), plot.getStatus() == Status.unfinished ? LangPaths.Review.MANAGE_PLOT : LangPaths.Review.REVIEW_PLOT)) - .setLore(lines) - .build()); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - getMenu().getSlot(i).setItem(MenuItems.errorItem(getMenuPlayer())); - } - } - } - - @Override - protected void setPaginatedItemClickEventsAsync(List source) { - // Set click event for unreviewed and unfinished plot items - List plots = getFilteredPlots(source); - for (int i = 0; i < plots.size(); i++) { - Plot plot = plots.get(i); - getMenu().getSlot(i + 9).setClickHandler((player, info) -> { - try { - if (plot.getStatus() == Status.unfinished) { - new PlotActionsMenu(getMenuPlayer(), plot); - return; - } - - player.performCommand("review " + plot.getID()); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - getMenuPlayer().closeInventory(); - } - }); - } - } - - @Override - protected void setMenuItemsAsync() { - // Set previous page item - if (hasPreviousPage()) getMenu().getSlot(46).setItem(MenuItems.previousPageItem(getMenuPlayer())); - - // Set next page item - if (hasNextPage()) getMenu().getSlot(52).setItem(MenuItems.nextPageItem(getMenuPlayer())); - } - - @Override - protected void setItemClickEventsAsync() { - // Set click event for filter item - getMenu().getSlot(7).setClickHandler((clickPlayer, clickInformation) -> { - clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); - if (countries.isEmpty()) return; - - if (filteredCountry == null) { - filteredCountry = countries.get(0); - } else { - int index = countries.indexOf(filteredCountry); - filteredCountry = index + 1 >= countries.size() ? null : countries.get(index + 1); - } - - reloadMenuAsync(false); - }); - - // Set click event for previous page item - getMenu().getSlot(46).setClickHandler((clickPlayer, clickInformation) -> { - if (hasPreviousPage()) { - previousPage(); - clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); - } - }); - - // Set click event for close item - getMenu().getSlot(49).setClickHandler((clickPlayer, clickInformation) -> clickPlayer.closeInventory()); - - // Set click event for next page item - getMenu().getSlot(52).setClickHandler((clickPlayer, clickInformation) -> { - if (hasNextPage()) { - nextPage(); - clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); - } - }); - } - - @Override - protected Mask getMask() { - return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(Component.empty()).build()) - .pattern("111111111") - .pattern("000000000") - .pattern("000000000") - .pattern("000000000") - .pattern("000000000") - .pattern("111101111") - .build(); - } - - private List getFilteredPlots(List plots) { - List filteredPlots = plots.stream().map(p -> (Plot) p).collect(Collectors.toList()); - if (filteredCountry != null) filteredPlots = filteredPlots.stream().filter(p -> { - try { - return p.getCity().getCountry().getID() == filteredCountry.getID(); - } catch (SQLException ex) {PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex);} - return false; - }).collect(Collectors.toList()); - return filteredPlots; - } - - private ItemStack getFilterItem(Player langPlayer) { - LegacyLoreBuilder LegacyLoreBuilder = new LegacyLoreBuilder(); - LegacyLoreBuilder.addLine((filteredCountry == null ? "§b§l> §f§l" : "§7") + LangUtil.getInstance().get(langPlayer, LangPaths.MenuDescription.FILTER)); - LegacyLoreBuilder.emptyLine(); - - countries.forEach(c -> { - if (filteredCountry != null && filteredCountry.getID() == c.getID()) { - LegacyLoreBuilder.addLine("§b§l> §f§l" + filteredCountry.getName()); - } else LegacyLoreBuilder.addLine("§7" + c.getName()); - }); - - return new ItemBuilder(MenuItems.filterItem(getMenuPlayer())) - .setLore(LegacyLoreBuilder.build()) - .setEnchanted(filteredCountry != null) - .build(); - } - - /** - * @return Menu item - */ - public static ItemStack getMenuItem(Player player) { - return new ItemBuilder(BaseItems.REVIEW_ITEM.getItem()) - .setName("§b§l" + LangUtil.getInstance().get(player, LangPaths.MenuTitle.REVIEW_PLOTS) + " §7(" + LangUtil.getInstance().get(player, LangPaths.Note.Action.RIGHT_CLICK) + ")") - .setEnchanted(true) - .build(); - } -} diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewPlotMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewPlotMenu.java deleted file mode 100644 index e6a5b2913..000000000 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/ReviewPlotMenu.java +++ /dev/null @@ -1,558 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.core.menus; - -import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; -import com.alpsbte.alpslib.utils.item.ItemBuilder; -import com.alpsbte.alpslib.utils.item.LoreBuilder; -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.system.Builder; -import com.alpsbte.plotsystem.core.system.Review; -import com.alpsbte.plotsystem.core.system.plot.Plot; -import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; -import com.alpsbte.plotsystem.utils.Utils; -import com.alpsbte.plotsystem.utils.chat.ChatInput; -import com.alpsbte.plotsystem.utils.chat.PlayerFeedbackChatInput; -import com.alpsbte.plotsystem.utils.enums.Status; -import com.alpsbte.plotsystem.utils.io.LangPaths; -import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.alpsbte.plotsystem.utils.items.BaseItems; -import com.alpsbte.plotsystem.utils.items.CustomHeads; -import com.alpsbte.plotsystem.utils.items.MenuItems; -import com.sk89q.worldedit.WorldEditException; -import net.kyori.adventure.text.Component; -import org.bukkit.Bukkit; -import org.bukkit.Material; -import org.bukkit.enchantments.Enchantment; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.meta.ItemMeta; -import org.ipvp.canvas.mask.BinaryMask; -import org.ipvp.canvas.mask.Mask; - -import java.io.IOException; -import java.sql.SQLException; -import java.util.Collections; -import java.util.Objects; - -import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; -import static net.kyori.adventure.text.format.TextDecoration.BOLD; - -public class ReviewPlotMenu extends AbstractMenu { - private final Plot plot; - - boolean sentWarning = false; - - public ReviewPlotMenu(Player player, Plot plot) { - super(6, LangUtil.getInstance().get(player, LangPaths.MenuTitle.REVIEW_PLOT, Integer.toString(plot.getID())), player); - this.plot = plot; - } - - @Override - protected void setPreviewItems() { - final ItemStack[] itemPointZero = new ItemStack[4]; - final ItemStack[] itemPointOne = new ItemStack[4]; - final ItemStack[] itemPointTwo = new ItemStack[4]; - final ItemStack[] itemPointThree = new ItemStack[4]; - final ItemStack[] itemPointFour = new ItemStack[4]; - final ItemStack[] itemPointFive = new ItemStack[4]; - - for (int i = 0; i < 54; i++) { - int column = (i % 9) + 1; - int row = (i - (i % 9)) / 9 + 1; - int position = ((i + 1) - (i + 1) % 9) / 54; - if (column > 2 && column < 9 && row > 1 && row < 6) { - if ((i + 1) % 9 == 3) { - itemPointZero[position] = getZeroPointItem(); - - //Add Enchantment - ItemMeta itemMeta = itemPointZero[position].getItemMeta(); - Objects.requireNonNull(itemMeta).addEnchant(Enchantment.POWER, 1, true); - itemPointZero[position].setItemMeta(itemMeta); - getMenu().getSlot(i).setItem(itemPointZero[(i - (i + 1) % 9) / 54]); - } else if ((i + 1) % 9 == 4) { - itemPointOne[position] = getOnePointItem(); - getMenu().getSlot(i).setItem(itemPointOne[(i - (i + 1) % 9) / 54]); - } else if ((i + 1) % 9 == 5) { - itemPointTwo[position] = getTwoPointItem(); - getMenu().getSlot(i).setItem(itemPointTwo[(i - (i + 1) % 9) / 54]); - } else if ((i + 1) % 9 == 6) { - itemPointThree[position] = getThreePointItem(); - getMenu().getSlot(i).setItem(itemPointThree[(i - (i + 1) % 9) / 54]); - } else if ((i + 1) % 9 == 7) { - itemPointFour[position] = getFourPointItem(); - getMenu().getSlot(i).setItem(itemPointFour[(i - (i + 1) % 9) / 54]); - } else if ((i + 1) % 9 == 8) { - itemPointFive[position] = getFivePointItem(); - getMenu().getSlot(i).setItem(itemPointFive[(i - (i + 1) % 9) / 54]); - } - } - } - - getMenu().getSlot(4).setItem(MenuItems.loadingItem(Material.MAP, getMenuPlayer())); - - getMenu().getSlot(10).setItem(getAccuracyItem()); - getMenu().getSlot(19).setItem(getBlockPaletteItem()); - getMenu().getSlot(28).setItem(getDetailingItem()); - getMenu().getSlot(37).setItem(getTechniqueItem()); - - getMenu().getSlot(48).setItem(getSubmitItem()); - getMenu().getSlot(50).setItem(getCancelItem()); - - super.setPreviewItems(); - } - - @Override - protected void setMenuItemsAsync() { - // Set back item - getMenu().getSlot(1).setItem(MenuItems.backMenuItem(getMenuPlayer())); - - // Set plot information item - getMenu().getSlot(4).setItem(getPlotInfoItem()); - - // Set review information item - getMenu().getSlot(7).setItem(getReviewInfoItem()); - } - - @Override - protected void setItemClickEventsAsync() { - // Set click event for back item - getMenu().getSlot(1).setClickHandler((clickPlayer, clickInformation) -> new ReviewMenu(getMenuPlayer())); - - // Set click event for close item - getMenu().getSlot(50).setClickHandler((clickPlayer, clickInformation) -> clickPlayer.closeInventory()); - - // Set click event for plot info item - getMenu().getSlot(4).setClickHandler((clickPlayer, clickInformation) -> { - try { - new PlotActionsMenu(clickPlayer, plot); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - }); - - // Set click event for submit item - getMenu().getSlot(48).setClickHandler((clickPlayer, clickInformation) -> { - Bukkit.getScheduler().runTaskAsynchronously(PlotSystem.getPlugin(), () -> { - try { - StringBuilder score = new StringBuilder(); - - int totalRating = 0; - boolean isRejected = false; - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 6; j++) { - if (Objects.requireNonNull(getMenu().getSlot(11 + (i * 9) + j).getItem(clickPlayer).getItemMeta()).hasEnchant(Enchantment.POWER)) { - if (i == 3) { - score.append(j); - } else { - score.append(j).append(","); - } - totalRating += j; - if (j == 0) isRejected = true; - } - } - } - if (totalRating <= 8) isRejected = true; - - if (totalRating == 0 && !sentWarning) { - clickPlayer.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_WILL_GET_ABANDONED))); - clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.CREATE_PLOT_SOUND, 1, 1); - sentWarning = true; - return; - } else if (isRejected && !sentWarning) { - clickPlayer.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_WILL_GET_REJECTED))); - clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.CREATE_PLOT_SOUND, 1, 1); - sentWarning = true; - return; - } else if (totalRating == 0) { - plot.setStatus(Status.unfinished); - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> clickPlayer.performCommand("plot abandon " + plot.getID())); - return; - } - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> clickPlayer.closeInventory()); - - if (plot.isReviewed()) { - plot.getReview().setRating(score.toString()); - plot.getReview().setReviewer(clickPlayer.getUniqueId()); - } else new Review(plot.getID(), clickPlayer.getUniqueId(), score.toString()); - - double totalRatingWithMultiplier = totalRating * Plot.getMultiplierByDifficulty(plot.getDifficulty()); - totalRating = (int) Math.floor(totalRatingWithMultiplier); - plot.setTotalScore(totalRating); - - Component reviewerConfirmationMessage; - - if (!isRejected) { - clickPlayer.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.SAVING_PLOT))); - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { - try { - PlotSystem.getPlugin().getComponentLogger().warn(text("Saving plot schematic (ID: " + plot.getID() + ")...")); - if (!PlotUtils.savePlotAsSchematic(plot)) { - clickPlayer.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Error.ERROR_OCCURRED))); - PlotSystem.getPlugin().getComponentLogger().warn(text("Could not save finished plot schematic (ID: " + plot.getID() + ")!")); - } - } catch (IOException | SQLException | WorldEditException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("Could not save finished plot schematic (ID: " + plot.getID() + ")!"), ex); - } - }); - - plot.setStatus(Status.completed); - plot.getReview().setFeedbackSent(false); - plot.getReview().setFeedback("No Feedback"); - plot.getPlotOwner().addCompletedBuild(1); - - // Remove Plot from Owner - plot.getPlotOwner().removePlot(plot.getSlot()); - - if (plot.getPlotMembers().isEmpty()) { - // Plot was made alone - reviewerConfirmationMessage = Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_MARKED_REVIEWED, Integer.toString(plot.getID()), plot.getPlotOwner().getName())); - - // Builder gets 100% of score - plot.getPlotOwner().addScore(totalRating); - } else { - // Plot was made in a group - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < plot.getPlotMembers().size(); i++) { - sb.append(i == plot.getPlotMembers().size() - 1 ? - plot.getPlotMembers().get(i).getName() : - plot.getPlotMembers().get(i).getName() + ", "); - } - reviewerConfirmationMessage = Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_MARKED_REVIEWED, Integer.toString(plot.getID()), sb.toString())); - - // Score gets split between all participants - plot.getPlotOwner().addScore(plot.getSharedScore()); - - for (Builder builder : plot.getPlotMembers()) { - // Score gets split between all participants - builder.addScore(plot.getSharedScore()); - builder.addCompletedBuild(1); - - // Remove Slot from Member - builder.removePlot(builder.getSlot(plot)); - } - } - } else { - if (!plot.getPlotMembers().isEmpty()) { - // Plot was made alone - reviewerConfirmationMessage = Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_REJECTED, Integer.toString(plot.getID()), plot.getPlotOwner().getName())); - } else { - // Plot was made in a group - StringBuilder sb = new StringBuilder(); - - for (int i = 0; i < plot.getPlotMembers().size(); i++) { - sb.append(i == plot.getPlotMembers().size() - 1 ? - plot.getPlotMembers().get(i).getName() : - plot.getPlotMembers().get(i).getName() + ", "); - } - reviewerConfirmationMessage = Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_REJECTED, Integer.toString(plot.getID()), sb.toString())); - } - - PlotUtils.Actions.undoSubmit(plot); - } - - boolean finalIsRejected = isRejected; - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { - for (Player player : plot.getWorld().getBukkitWorld().getPlayers()) { - player.teleport(Utils.getSpawnLocation()); - } - - // Delete plot world after reviewing - try { - if (!finalIsRejected && plot.getPlotType().hasOnePlotPerWorld()) - plot.getWorld().deleteWorld(); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - - clickPlayer.sendMessage(reviewerConfirmationMessage); - clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.FINISH_PLOT_SOUND, 1f, 1f); - - try { - ChatInput.awaitChatInput.put(clickPlayer.getUniqueId(), - new PlayerFeedbackChatInput(clickPlayer.getUniqueId(), plot.getReview())); - PlayerFeedbackChatInput.sendChatInputMessage(clickPlayer); - } catch (SQLException ex) {PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex);} - }); - - for (Builder member : plot.getPlotMembers()) { - if (member.isOnline()) PlotUtils.ChatFormatting.sendFeedbackMessage(Collections.singletonList(plot), member.getPlayer()); - } - - if (plot.getPlotOwner().isOnline()) { - PlotUtils.ChatFormatting.sendFeedbackMessage(Collections.singletonList(plot), plot.getPlotOwner().getPlayer()); - plot.getReview().setFeedbackSent(true); - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - }); - }); - - // Set click event for point selection items - for (int i = 0; i < 54; i++) { - int slot = i; - - int column = (slot % 9) + 1; - int row = (slot - (slot % 9)) / 9 + 1; - - ItemMeta meta = getMenu().getSlot(slot).getItem(getMenuPlayer()).getItemMeta(); - - if (column > 2 && column < 9 && row > 1 && row < 6) { - //Go through the whole points row - getMenu().getSlot(i).setClickHandler((clickPlayer, clickInformation) -> { - for (int j = 0; j < 6; j++) { - if (!Objects.requireNonNull(getMenu().getSlot(slot - (column - 1) + j + 2).getItem(clickPlayer).getItemMeta()).hasEnchant(Enchantment.POWER)) continue; - - ItemStack itemPrevious = getMenu().getSlot(slot - (column - 1) + j + 2).getItem(clickPlayer); - ItemMeta metaPrevious = itemPrevious.getItemMeta(); - assert metaPrevious != null; - metaPrevious.removeEnchant(Enchantment.POWER); - itemPrevious.setItemMeta(metaPrevious); - getMenu().getSlot(slot - (column - 1) + j + 2).setItem(itemPrevious); - } - - assert meta != null; - meta.addEnchant(Enchantment.POWER, 1, true); - clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); - - ItemStack newItem = getMenu().getSlot(slot).getItem(clickPlayer); - newItem.setItemMeta(meta); - getMenu().getSlot(slot).setItem(newItem); - sentWarning = false; - }); - } - } - } - - @Override - protected Mask getMask() { - return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(Component.empty()).build()) - .pattern("101101101") - .pattern("100000001") - .pattern("100000001") - .pattern("100000001") - .pattern("100000001") - .pattern("111010111") - .build(); - } - - // --- Info Items --- - private ItemStack getPlotInfoItem() { - String plotOwner, city, country, difficulty; - Player plotOwnerPlayer; - - try { - plotOwner = plot.getPlotOwner().getName(); - city = plot.getCity().getName(); - country = plot.getCity().getCountry().getName(); - difficulty = plot.getDifficulty().name().charAt(0) + plot.getDifficulty().name().substring(1).toLowerCase(); - - plotOwnerPlayer = plot.getPlotOwner().getPlayer(); - } catch (SQLException e) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), e); - return MenuItems.errorItem(getMenuPlayer()); - } - - - return new ItemBuilder(BaseItems.REVIEW_INFO_PLOT.getItem()) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.REVIEW_PLOT)) - .color(AQUA) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.ID) + ": ", GRAY).append(text(plot.getID(), WHITE))) - .emptyLine() - .addLines(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.OWNER) + ": ", GRAY).append(text(plotOwner, WHITE)), - text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.CITY) + ": ", GRAY).append(text(city, WHITE)), - text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.COUNTRY) + ": ", GRAY).append(text(country, WHITE)), - text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.DIFFICULTY) + ": ", GRAY).append(text(difficulty, WHITE))) - .emptyLine() - .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.PLAYER_LANGUAGE) + ": ", GRAY).append(text(LangUtil.getInstance().get(plotOwnerPlayer, "lang.name"), WHITE))) - .build()) - .build(); - } - - private ItemStack getReviewInfoItem() { - String points = LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS); - - return new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.INFO_BUTTON.getId())) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.INFORMATION), AQUA).decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLines(true, LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.INFORMATION)) - .emptyLine() - .addLines(text(points + " <= 0: ", WHITE).append(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.ABANDONED), RED)), - text(points + " <= 8: ", WHITE).append(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.REJECTED), YELLOW)), - text(points + " > 8: ", WHITE).append(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.ACCEPTED), GREEN))) - .build()) - .build(); - } - - // --- Category Items --- - private ItemStack getAccuracyItem() { - return new ItemBuilder(BaseItems.REVIEW_ACCURACY.getItem()) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.ACCURACY)) - .color(GREEN) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLines(true, LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.ACCURACY_DESC)) - .build()) - .build(); - } - - private ItemStack getBlockPaletteItem() { - return new ItemBuilder(BaseItems.REVIEW_BLOCK_PALETTE.getItem()) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.BLOCK_PALETTE)) - .color(GREEN) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLines(true, LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.BLOCK_PALETTE_DESC)) - .build()) - .build(); - } - - private ItemStack getDetailingItem() { - return new ItemBuilder(BaseItems.REVIEW_DETAILING.getItem()) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.DETAILING)) - .color(GREEN) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLines(true, LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.DETAILING_DESC)) - .build()) - .build(); - } - - private ItemStack getTechniqueItem() { - return new ItemBuilder(BaseItems.REVIEW_TECHNIQUE.getItem()) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.TECHNIQUE)) - .color(GREEN) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLines(true, LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.TECHNIQUE_DESC)) - .build()) - .build(); - } - - // --- Button Items --- - private ItemStack getSubmitItem() { - return new ItemBuilder(BaseItems.REVIEW_SUBMIT.getItem()) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.SUBMIT)) - .color(GREEN) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.SUBMIT_REVIEW), true) - .build()) - .build(); - } - - private ItemStack getCancelItem() { - return new ItemBuilder(BaseItems.REVIEW_CANCEL.getItem()) - .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.CANCEL)) - .color(RED) - .decoration(BOLD, true)) - .build(); - } - - // --- Point Items --- - private ItemStack getZeroPointItem() { - return new ItemBuilder(BaseItems.REVIEW_POINT_ZERO.getItem()) - .setName(text("0 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS)) - .color(GRAY) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) - .build()) - .build(); - } - - private ItemStack getOnePointItem() { - return new ItemBuilder(BaseItems.REVIEW_POINT_ONE.getItem()) - .setName(text("1 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINT)) - .color(RED) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) - .build()) - .build(); - } - - private ItemStack getTwoPointItem() { - ItemStack item = BaseItems.REVIEW_POINT_TWO.getItem(); - item.setAmount(2); - - return new ItemBuilder(item) - .setName(text("2 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS)) - .color(GOLD) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) - .build()) - .build(); - } - - private ItemStack getThreePointItem() { - ItemStack item = BaseItems.REVIEW_POINT_THREE.getItem(); - item.setAmount(3); - - return new ItemBuilder(item) - .setName(text("3 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS)) - .color(YELLOW) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) - .build()) - .build(); - } - - private ItemStack getFourPointItem() { - ItemStack item = BaseItems.REVIEW_POINT_FOUR.getItem(); - item.setAmount(4); - - return new ItemBuilder(item) - .setName(text("4 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS)) - .color(DARK_GREEN) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) - .build()) - .build(); - } - - private ItemStack getFivePointItem() { - ItemStack item = BaseItems.REVIEW_POINT_FIVE.getItem(); - item.setAmount(5); - - return new ItemBuilder(item) - .setName(text("5 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS)) - .color(GREEN) - .decoration(BOLD, true)) - .setLore(new LoreBuilder() - .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) - .build()) - .build(); - } -} diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/SettingsMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/SettingsMenu.java index 707d08784..546d61285 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/SettingsMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/SettingsMenu.java @@ -1,50 +1,24 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus; -import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; +import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.alpsbte.plotsystem.utils.items.CustomHeads; +import com.alpsbte.plotsystem.utils.items.BaseItems; import com.alpsbte.plotsystem.utils.items.MenuItems; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.ipvp.canvas.mask.BinaryMask; import org.ipvp.canvas.mask.Mask; import java.util.function.Consumer; -import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; import static net.kyori.adventure.text.format.NamedTextColor.GOLD; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class SettingsMenu extends AbstractMenu { - private Consumer onBack = (player) -> player.performCommand("companion"); + private Consumer onBack = player -> player.performCommand("companion"); public SettingsMenu(Player player) { super(3, LangUtil.getInstance().get(player, LangPaths.MenuTitle.SETTINGS), player); @@ -59,7 +33,7 @@ public SettingsMenu(Player player, Consumer onBack) { protected void setMenuItemsAsync() { // Set language item getMenu().getSlot(11).setItem( - new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.GLOBE_HEAD.getId())) + new ItemBuilder(BaseItems.LANGUAGE_ITEM.getItem()) .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.SELECT_LANGUAGE), GOLD, BOLD)) .setLore(new LoreBuilder() .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.SELECT_LANGUAGE)) @@ -68,7 +42,7 @@ protected void setMenuItemsAsync() { // Set Plot type item getMenu().getSlot(15).setItem( - new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.PLOT_TYPE_BUTTON.getId())) + new ItemBuilder(BaseItems.PLOT_TYPE.getItem()) .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.SELECT_PLOT_TYPE), GOLD, BOLD)) .setLore(new LoreBuilder() .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.SELECT_PLOT_TYPE)) @@ -94,9 +68,9 @@ protected void setItemClickEventsAsync() { @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(empty()).build()) - .pattern("111111111") - .pattern("000000000") + .item(Utils.DEFAULT_ITEM) + .pattern(Utils.FULL_MASK) + .pattern(Utils.EMPTY_MASK) .pattern("111101111") .build(); } diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/SpecialToolsMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/SpecialToolsMenu.java index 7b1f788e7..0db6c7885 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/SpecialToolsMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/SpecialToolsMenu.java @@ -1,35 +1,11 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; +import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import com.alpsbte.plotsystem.utils.items.MenuItems; -import net.kyori.adventure.text.Component; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.entity.Player; @@ -73,9 +49,9 @@ protected void setItemClickEventsAsync() { @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(Component.empty()).build()) - .pattern("111111111") - .pattern("000000000") + .item(Utils.DEFAULT_ITEM) + .pattern(Utils.FULL_MASK) + .pattern(Utils.EMPTY_MASK) .pattern("111101111") .build(); } diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CityProjectMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CityProjectMenu.java index 803c40edf..e9ab62abc 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CityProjectMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CityProjectMenu.java @@ -1,31 +1,7 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus.companion; -import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.menus.AbstractPaginatedMenu; import com.alpsbte.plotsystem.core.menus.tutorial.TutorialsMenu; import com.alpsbte.plotsystem.core.system.Builder; @@ -40,14 +16,12 @@ import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import com.alpsbte.plotsystem.utils.items.MenuItems; -import net.kyori.adventure.text.Component; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.ipvp.canvas.mask.BinaryMask; import org.ipvp.canvas.mask.Mask; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; -import java.sql.SQLException; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; @@ -58,7 +32,7 @@ public class CityProjectMenu extends AbstractPaginatedMenu { private PlotDifficulty selectedPlotDifficulty; CityProjectMenu(Player player, @NotNull Country country, PlotDifficulty selectedPlotDifficulty) { - super(6, 4, country.getName() + " → " + LangUtil.getInstance().get(player, LangPaths.MenuTitle.COMPANION_SELECT_CITY), player); + super(6, 4, country.getName(player) + " → " + LangUtil.getInstance().get(player, LangPaths.MenuTitle.COMPANION_SELECT_CITY), player); this.country = country; this.selectedPlotDifficulty = selectedPlotDifficulty; } @@ -68,31 +42,25 @@ protected void setPreviewItems() { getMenu().getSlot(0).setItem(MenuItems.getRandomItem(getMenuPlayer())); // Set random selection item getMenu().getSlot(1).setItem(MenuItems.backMenuItem(getMenuPlayer())); - for (Map.Entry entry : CompanionMenu.getFooterItems(45, getMenuPlayer(), player -> new CountryMenu(player, country.getContinent())).entrySet()) { - getMenu().getSlot(entry.getKey()).setItem(entry.getValue().item); - } + Map footerItems = CompanionMenu.getFooterItems(45, getMenuPlayer(), player -> new CountryMenu(player, country.getContinent())); + footerItems.forEach((index, footerItem) -> getMenu().getSlot(index).setItem(footerItem.item())); // Set loading item for plots difficulty item getMenu().getSlot(6).setItem(CompanionMenu.getDifficultyItem(getMenuPlayer(), selectedPlotDifficulty)); // Set tutorial item getMenu().getSlot(7).setItem(PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.TUTORIAL_ENABLE) ? - TutorialsMenu.getTutorialItem(getMenuPlayer()) : new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(Component.empty()).build()); + TutorialsMenu.getTutorialItem(getMenuPlayer()) : Utils.DEFAULT_ITEM); // Set previous page item - if (hasPreviousPage()) - getMenu().getSlot(45).setItem(MenuItems.previousPageItem(getMenuPlayer())); + getMenu().getSlot(45).setItem(hasPreviousPage() ? MenuItems.previousPageItem(getMenuPlayer()) : Utils.DEFAULT_ITEM); // Set next page item - if (hasNextPage()) - getMenu().getSlot(53).setItem(MenuItems.nextPageItem(getMenuPlayer())); + getMenu().getSlot(53).setItem(hasNextPage() ? MenuItems.nextPageItem(getMenuPlayer()) : Utils.DEFAULT_ITEM); super.setPreviewItems(); } - @Override - protected void setMenuItemsAsync() {} - @Override protected void setItemClickEventsAsync() { getMenu().getSlot(0).setClickHandler((clickPlayer, clickInformation) -> @@ -101,24 +69,24 @@ protected void setItemClickEventsAsync() { getMenu().getSlot(1).setClickHandler((clickPlayer, clickInformation) -> new CountryMenu(clickPlayer, country.getContinent(), selectedPlotDifficulty)); // Set click event for previous page item - getMenu().getSlot(45).setClickHandler((clickPlayer, clickInformation) -> { - if (hasPreviousPage()) { + if (hasPreviousPage()) { + getMenu().getSlot(45).setClickHandler((clickPlayer, clickInformation) -> { previousPage(); clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); - } - }); + }); + } // Set click event for next page item - getMenu().getSlot(53).setClickHandler((clickPlayer, clickInformation) -> { - if (!hasNextPage()) return; - nextPage(); - clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); - }); - - for (Map.Entry entry : CompanionMenu.getFooterItems(45, getMenuPlayer(), player -> new CountryMenu(player, country.getContinent())).entrySet()) { - getMenu().getSlot(entry.getKey()).setClickHandler(entry.getValue().clickHandler); + if (hasNextPage()) { + getMenu().getSlot(53).setClickHandler((clickPlayer, clickInformation) -> { + nextPage(); + clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); + }); } + Map footerItems = CompanionMenu.getFooterItems(45, getMenuPlayer(), player -> new CountryMenu(player, country.getContinent())); + footerItems.forEach((index, footerItem) -> getMenu().getSlot(index).setClickHandler(footerItem.clickHandler())); + // Set click event for plots difficulty item getMenu().getSlot(6).setClickHandler(((clickPlayer, clickInformation) -> { selectedPlotDifficulty = CompanionMenu.clickEventPlotDifficulty(selectedPlotDifficulty, clickPlayer, getMenu()); @@ -134,14 +102,16 @@ public static boolean generateRandomPlot(Player player, @NotNull List getValidCityProjects(PlotDifficulty selectedPlotDifficulty, Player player, Country country) { - return CityProject.getCityProjects(country, true).stream().filter(test -> { - if (test instanceof CityProject project) { - var pd = selectedPlotDifficulty; - try { - if (pd == null) pd = Plot.getPlotDifficultyForBuilder(project.getID(), Builder.byUUID(player.getUniqueId())).get(); - if (pd == null) pd = PlotDifficulty.EASY; - return project.isVisible() && project.getOpenPlotsForPlayer(project.getID(), pd) > 0; - } catch (SQLException | ExecutionException | InterruptedException e) { - sqlError(player, e); - } - } else { - return false; + public static @NotNull @Unmodifiable List getValidCityProjects(PlotDifficulty selectedPlotDifficulty, Player player, @NotNull Country country) { + return DataProvider.CITY_PROJECT.getByCountryCode(country.getCode(), true).stream().filter(test -> { + if (!(test instanceof CityProject project)) return false; + var pd = selectedPlotDifficulty; + try { + if (pd == null) pd = Plot.getPlotDifficultyForBuilder(project, Builder.byUUID(player.getUniqueId())).get(); + if (pd == null) pd = PlotDifficulty.EASY; + + return project.isVisible() && !DataProvider.PLOT.getPlots(project, pd, Status.unclaimed).isEmpty(); + } catch (ExecutionException | InterruptedException e) { + sqlError(player, e); } return false; }).toList(); @@ -170,7 +138,7 @@ public static List getValidCityProjects(PlotDifficulty selectedPlot @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(Component.empty()).build()) + .item(Utils.DEFAULT_ITEM) .pattern("001111001") .pattern(Utils.EMPTY_MASK) .pattern(Utils.EMPTY_MASK) @@ -182,7 +150,7 @@ protected Mask getMask() { @Override protected List getSource() { - if (projects == null) projects = CityProject.getCityProjects(country, true); + if (projects == null) projects = DataProvider.CITY_PROJECT.getByCountryCode(country.getCode(), true); return projects; } @@ -191,12 +159,7 @@ protected void setPaginatedMenuItemsAsync(@NotNull List source) { List cities = source.stream().map(l -> (CityProject) l).toList(); int slot = 9; for (CityProject city : cities) { - try { - getMenu().getSlot(slot).setItem(city.getItem(getMenuPlayer(), selectedPlotDifficulty)); - } catch (SQLException e) { - Utils.logSqlException(e); - getMenu().getSlot(slot).setItem(MenuItems.errorItem(getMenuPlayer())); - } + getMenu().getSlot(slot).setItem(city.getItem(getMenuPlayer(), selectedPlotDifficulty)); slot++; } } @@ -215,24 +178,24 @@ protected void setPaginatedItemClickEventsAsync(@NotNull List source) { clickPlayer.closeInventory(); Builder builder = Builder.byUUID(clickPlayer.getUniqueId()); - int cityID = city.getID(); try { - PlotDifficulty plotDifficultyForCity = selectedPlotDifficulty != null ? selectedPlotDifficulty : Plot.getPlotDifficultyForBuilder(cityID, builder).get(); - if (plotDifficultyForCity == null || Plot.getPlots(cityID, plotDifficultyForCity, Status.unclaimed).isEmpty()) { + PlotDifficulty plotDifficultyForCity = selectedPlotDifficulty != null ? selectedPlotDifficulty : Plot.getPlotDifficultyForBuilder(city, builder).get(); + List unclaimedPlots = DataProvider.PLOT.getPlots(city, plotDifficultyForCity, Status.unclaimed); + if (unclaimedPlots.isEmpty()) { clickPlayer.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(clickPlayer, LangPaths.Message.Error.NO_PLOTS_LEFT))); clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.ERROR_SOUND, 1, 1); return; } - if (selectedPlotDifficulty != null && PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.ENABLE_SCORE_REQUIREMENT) && !Plot.hasPlotDifficultyScoreRequirement(builder, selectedPlotDifficulty)) { + if (selectedPlotDifficulty != null && PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.ENABLE_SCORE_REQUIREMENT) && !DataProvider.DIFFICULTY.builderMeetsRequirements(builder, selectedPlotDifficulty)) { clickPlayer.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(clickPlayer, LangPaths.Message.Error.PLAYER_NEEDS_HIGHER_SCORE))); clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.ERROR_SOUND, 1, 1); return; } - new DefaultPlotGenerator(cityID, plotDifficultyForCity, builder); - } catch (SQLException | ExecutionException | InterruptedException ex) { + new DefaultPlotGenerator(city, plotDifficultyForCity, builder); + } catch (ExecutionException | InterruptedException ex) { sqlError(clickPlayer, ex); } }); diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CompanionMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CompanionMenu.java index d950def03..72d40fa5b 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CompanionMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CompanionMenu.java @@ -1,40 +1,16 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus.companion; -import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.menus.BuilderUtilitiesMenu; import com.alpsbte.plotsystem.core.menus.PlayerPlotsMenu; import com.alpsbte.plotsystem.core.menus.PlotActionsMenu; import com.alpsbte.plotsystem.core.menus.SettingsMenu; import com.alpsbte.plotsystem.core.menus.tutorial.TutorialsMenu; import com.alpsbte.plotsystem.core.system.Builder; -import com.alpsbte.plotsystem.core.system.Country; +import com.alpsbte.plotsystem.core.system.Difficulty; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Continent; @@ -44,13 +20,14 @@ import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import com.alpsbte.plotsystem.utils.items.BaseItems; -import com.alpsbte.plotsystem.utils.items.CustomHeads; import com.alpsbte.plotsystem.utils.items.MenuItems; +import net.kyori.adventure.text.TextComponent; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.ipvp.canvas.Menu; +import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -59,13 +36,18 @@ import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class CompanionMenu { - private CompanionMenu() {} + private CompanionMenu() {throw new IllegalStateException("Utility class");} + public static boolean hasContinentView() { - return Arrays.stream(Continent.values()).map(continent -> Country.getCountries(continent).size()).filter(count -> count > 0).count() > 1; + // TODO: make this run async + return Arrays.stream(Continent.values()).map(continent -> DataProvider.COUNTRY.getCountriesByContinent(continent).size()).filter(count -> count > 0).count() > 1; } /** @@ -77,7 +59,8 @@ public static void open(Player player) { if (hasContinentView()) { new ContinentMenu(player); } else { - Optional continent = Arrays.stream(Continent.values()).filter(c -> !Country.getCountries(c).isEmpty()).findFirst(); + // TODO: make this run async + Optional continent = Arrays.stream(Continent.values()).filter(c -> !DataProvider.COUNTRY.getCountriesByContinent(c).isEmpty()).findFirst(); if (continent.isEmpty()) { player.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(player, LangPaths.Message.Error.ERROR_OCCURRED))); @@ -96,7 +79,7 @@ public static void open(Player player) { * @param returnToMenu a lambda to call when needing to return to current menu * @return FooterItems indexed by slot number */ - public static Map getFooterItems(int startingSlot, Player player, Consumer returnToMenu) { + public static @NotNull Map getFooterItems(int startingSlot, Player player, Consumer returnToMenu) { HashMap items = new HashMap<>(); // Set builder utilities menu item items.put(startingSlot + 5, new FooterItem(BuilderUtilitiesMenu.getMenuItem(player), (clickPlayer, clickInformation) -> new BuilderUtilitiesMenu(clickPlayer))); @@ -116,18 +99,13 @@ public static Map getFooterItems(int startingSlot, Player p final int i_ = i; - Plot plot = builder.getPlot(Slot.values()[i]); - items.put(startingSlot + 1 + i, new FooterItem(builder.getPlotMenuItem(plot, Slot.values()[i].ordinal(), player), (clickPlayer, clickInformation) -> { + Plot plot = builder.getSlot(Slot.values()[i]); + ItemStack slotItem = getPlotMenuItem(plot, i, player); + items.put(startingSlot + 1 + i, new FooterItem(slotItem, (clickPlayer, clickInformation) -> { if (plot == null) return; - try { - new PlotActionsMenu(clickPlayer, builder.getPlot(Slot.values()[i_])); - } catch (SQLException ex) { - clickPlayer.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(clickPlayer, LangPaths.Message.Error.ERROR_OCCURRED))); - clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.ERROR_SOUND, 1, 1); - PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while opening the plot actions menu!"), ex); - } + new PlotActionsMenu(clickPlayer, builder.getSlot(Slot.values()[i_])); })); - } catch (NullPointerException | SQLException ex) { + } catch (NullPointerException ex) { PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while placing player slot items!"), ex); items.put(startingSlot + 1 + i, new FooterItem(MenuItems.errorItem(player))); } @@ -142,31 +120,32 @@ public static ItemStack getDifficultyItem(Player player, PlotDifficulty selected if (selectedPlotDifficulty != null) { switch (selectedPlotDifficulty) { case EASY: - item = AlpsHeadUtils.getCustomHead(CustomHeads.GREEN_CONCRETE.getId()); break; + item = BaseItems.DIFFICULTY_EASY.getItem(); break; case MEDIUM: - item = AlpsHeadUtils.getCustomHead(CustomHeads.YELLOW_CONCRETE.getId()); break; + item = BaseItems.DIFFICULTY_MEDIUM.getItem(); break; case HARD: - item = AlpsHeadUtils.getCustomHead(CustomHeads.RED_CONCRETE.getId()); break; + item = BaseItems.DIFFICULTY_HARD.getItem(); break; default: break; } - } else item = AlpsHeadUtils.getCustomHead(CustomHeads.WHITE_CONCRETE.getId()); - - try { - return new ItemBuilder(item) - .setName(text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.PLOT_DIFFICULTY), AQUA).decoration(BOLD, true)) - .setLore(new LoreBuilder() - .emptyLine() - .addLines(selectedPlotDifficulty != null ? Utils.ItemUtils.getFormattedDifficulty(selectedPlotDifficulty) : text(LangUtil.getInstance().get(player, LangPaths.Difficulty.AUTOMATIC), WHITE).decoration(BOLD, true), - selectedPlotDifficulty != null ? text(LangUtil.getInstance().get(player, LangPaths.Difficulty.SCORE_MULTIPLIER) + ": ", GRAY).append(text("x" + Plot.getMultiplierByDifficulty(selectedPlotDifficulty), WHITE)) : empty()) - .emptyLine() - .addLine(text(LangUtil.getInstance().get(player, LangPaths.MenuDescription.PLOT_DIFFICULTY), GRAY)) - .build()) - .build(); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - return MenuItems.errorItem(player); + } else item = BaseItems.DIFFICULTY_AUTOMATIC.getItem(); + + Optional difficulty = DataProvider.DIFFICULTY.getDifficultyByEnum(selectedPlotDifficulty); + if (difficulty.isEmpty() && selectedPlotDifficulty != null) { + PlotSystem.getPlugin().getComponentLogger().error(text("No database entry for difficulty " + selectedPlotDifficulty.name() + " was found!")); } + double scoreMultiplier = difficulty.map(Difficulty::getMultiplier).orElse(0.0); + + return new ItemBuilder(item) + .setName(text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.PLOT_DIFFICULTY), AQUA).decoration(BOLD, true)) + .setLore(new LoreBuilder() + .emptyLine() + .addLines(selectedPlotDifficulty != null ? Utils.ItemUtils.getFormattedDifficulty(selectedPlotDifficulty, player) : text(LangUtil.getInstance().get(player, LangPaths.Difficulty.AUTOMATIC), WHITE).decoration(BOLD, true), + selectedPlotDifficulty != null ? text(LangUtil.getInstance().get(player, LangPaths.Difficulty.SCORE_MULTIPLIER) + ": ", GRAY).append(text("x" + scoreMultiplier, WHITE)) : empty()) + .emptyLine() + .addLine(text(LangUtil.getInstance().get(player, LangPaths.MenuDescription.PLOT_DIFFICULTY), GRAY)) + .build()) + .build(); } /** @@ -208,18 +187,38 @@ public static void clickEventTutorialItem(Menu menu) { }); } - public static class FooterItem { - public final ItemStack item; - public final org.ipvp.canvas.slot.Slot.ClickHandler clickHandler; + public static ItemStack getPlotMenuItem(Plot plot, int slotIndex, Player langPlayer) { + String nameText = LangUtil.getInstance().get(langPlayer, LangPaths.MenuTitle.SLOT).toUpperCase() + " " + (slotIndex + 1); + ItemStack baseItem = plot == null ? BaseItems.PLOT_SLOT_EMPTY.getItem().clone() : BaseItems.PLOT_SLOT_FILLED.getItem().clone(); + baseItem.setAmount(1 + slotIndex); + ArrayList lore; - FooterItem(ItemStack item, org.ipvp.canvas.slot.Slot.ClickHandler clickHandler) { - this.item = item; - this.clickHandler = clickHandler; + if (plot == null) { + TextComponent slotDescriptionComp = text(LangUtil.getInstance().get(langPlayer, LangPaths.MenuDescription.SLOT), GRAY); + lore = new LoreBuilder() + .addLine(slotDescriptionComp) + .build(); + } else { + String plotIdText = LangUtil.getInstance().get(langPlayer, LangPaths.Plot.ID); + String plotCityText = LangUtil.getInstance().get(langPlayer, LangPaths.Plot.CITY); + String plotDifficultyText = LangUtil.getInstance().get(langPlayer, LangPaths.Plot.DIFFICULTY); + String statusText = LangUtil.getInstance().get(langPlayer, LangPaths.Database.STATUS + "." + plot.getStatus().name() + ".name"); + + TextComponent statusComp = text(LangUtil.getInstance().get(langPlayer, LangPaths.Plot.STATUS) + ": ", GOLD) + .decoration(BOLD, true) + .append(text(statusText, GRAY)); + lore = new LoreBuilder() + .addLines(text(plotIdText + ": ", GRAY).append(text(plot.getId(), WHITE)), + text(plotCityText + ": ", GRAY).append(text(plot.getCityProject().getName(langPlayer), WHITE)), + text(plotDifficultyText + ": ", GRAY).append(text(plot.getDifficulty().name().charAt(0) + plot.getDifficulty().name().substring(1).toLowerCase(), WHITE)), + empty(), + statusComp) + .build(); } - FooterItem(ItemStack item) { - this.item = item; - this.clickHandler = null; - } + return new ItemBuilder(baseItem) + .setName(text(nameText, GOLD).decoration(BOLD, true)) + .setLore(lore) + .build(); } } \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/companion/ContinentMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/companion/ContinentMenu.java index 9ab39aa10..381dbe734 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/companion/ContinentMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/companion/ContinentMenu.java @@ -1,39 +1,12 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus.companion; -import com.alpsbte.alpslib.utils.item.ItemBuilder; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.menus.AbstractMenu; -import com.alpsbte.plotsystem.core.system.Country; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Continent; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import com.alpsbte.plotsystem.utils.items.MenuItems; -import net.kyori.adventure.text.Component; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.ipvp.canvas.mask.BinaryMask; import org.ipvp.canvas.mask.Mask; @@ -60,9 +33,8 @@ public class ContinentMenu extends AbstractMenu { protected void setPreviewItems() { getMenu().getSlot(0).setItem(MenuItems.getRandomItem(getMenuPlayer())); // Set random selection item - for (Map.Entry entry : CompanionMenu.getFooterItems(9 * 4, getMenuPlayer(), ContinentMenu::new).entrySet()) { - getMenu().getSlot(entry.getKey()).setItem(entry.getValue().item); - } + Map footerItems = CompanionMenu.getFooterItems(9 * 4, getMenuPlayer(), ContinentMenu::new); + footerItems.forEach((index, footerItem) -> getMenu().getSlot(index).setItem(footerItem.item())); super.setPreviewItems(); } @@ -79,7 +51,7 @@ protected void setItemClickEventsAsync() { List layout2 = new java.util.ArrayList<>(layout.values().stream().toList()); while (!layout2.isEmpty()) { var rndContinent = layout2.get(Utils.getRandom().nextInt(layout2.size())); - var successful = CountryMenu.generateRandomPlot(clickPlayer, Country.getCountries(rndContinent), null); + var successful = CountryMenu.generateRandomPlot(clickPlayer, DataProvider.COUNTRY.getCountriesByContinent(rndContinent), null); if (successful) { return; } else { @@ -92,19 +64,18 @@ protected void setItemClickEventsAsync() { getMenu().getSlot(continent.getKey()).setClickHandler((clickPlayer, clickInfo) -> new CountryMenu(clickPlayer, continent.getValue())); } - for (Map.Entry entry : CompanionMenu.getFooterItems(9 * 4, getMenuPlayer(), ContinentMenu::new).entrySet()) { - getMenu().getSlot(entry.getKey()).setClickHandler(entry.getValue().clickHandler); - } + Map footerItems = CompanionMenu.getFooterItems(9 * 4, getMenuPlayer(), ContinentMenu::new); + footerItems.forEach((index, footerItem) -> getMenu().getSlot(index).setClickHandler(footerItem.clickHandler())); } @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(Component.empty()).build()) + .item(Utils.DEFAULT_ITEM) .pattern("011111111") .pattern("010101010") .pattern("111101111") - .pattern("111111111") + .pattern(Utils.FULL_MASK) .pattern("100010001") .build(); } diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CountryMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CountryMenu.java index 4dab2b33a..91e500a78 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CountryMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/companion/CountryMenu.java @@ -1,37 +1,13 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus.companion; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.menus.AbstractMenu; import com.alpsbte.plotsystem.core.menus.tutorial.TutorialsMenu; import com.alpsbte.plotsystem.core.system.CityProject; import com.alpsbte.plotsystem.core.system.Country; -import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Continent; import com.alpsbte.plotsystem.utils.enums.PlotDifficulty; @@ -40,27 +16,29 @@ import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import com.alpsbte.plotsystem.utils.items.MenuItems; -import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.ipvp.canvas.mask.BinaryMask; import org.ipvp.canvas.mask.Mask; import org.jetbrains.annotations.NotNull; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Map; -import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class CountryMenu extends AbstractMenu { private List countryProjects; private final Continent selectedContinent; - private PlotDifficulty selectedPlotDifficulty = null; + private PlotDifficulty selectedPlotDifficulty = PlotDifficulty.EASY; CountryMenu(Player player, @NotNull Continent continent) { super(6, LangUtil.getInstance().get(player, continent.langPath) + " → " + LangUtil.getInstance().get(player, LangPaths.MenuTitle.COMPANION_SELECT_COUNTRY), player); @@ -81,11 +59,10 @@ protected void setPreviewItems() { // Set tutorial item getMenu().getSlot(7).setItem(PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.TUTORIAL_ENABLE) ? - TutorialsMenu.getTutorialItem(getMenuPlayer()) : new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(empty()).build()); + TutorialsMenu.getTutorialItem(getMenuPlayer()) : Utils.DEFAULT_ITEM); - for (Map.Entry entry : CompanionMenu.getFooterItems(45, getMenuPlayer(), player -> new CountryMenu(player, selectedContinent)).entrySet()) { - getMenu().getSlot(entry.getKey()).setItem(entry.getValue().item); - } + Map footerItems = CompanionMenu.getFooterItems(45, getMenuPlayer(), player -> new CountryMenu(player, selectedContinent)); + footerItems.forEach((index, footerItem) -> getMenu().getSlot(index).setItem(footerItem.item())); super.setPreviewItems(); } @@ -93,10 +70,8 @@ protected void setPreviewItems() { @Override protected void setMenuItemsAsync() { // Set city project items - try { - countryProjects = Country.getCountries(selectedContinent); - setCountryItems(); - } catch (SQLException ex) {Utils.logSqlException(ex);} + countryProjects = DataProvider.COUNTRY.getCountriesByContinent(selectedContinent); + setCountryItems(); } @Override @@ -106,10 +81,14 @@ protected void setItemClickEventsAsync() { // Set click event for plots difficulty item getMenu().getSlot(6).setClickHandler((clickPlayer, clickInformation) -> { - selectedPlotDifficulty = CompanionMenu.clickEventPlotDifficulty(selectedPlotDifficulty, clickPlayer, getMenu()); - try { - setCountryItems(); - } catch (SQLException ex) {Utils.logSqlException(ex);} + selectedPlotDifficulty = (selectedPlotDifficulty == null ? + PlotDifficulty.values()[0] : selectedPlotDifficulty.ordinal() != PlotDifficulty.values().length - 1 ? + PlotDifficulty.values()[selectedPlotDifficulty.ordinal() + 1] : null); + + getMenu().getSlot(6).setItem(CompanionMenu.getDifficultyItem(getMenuPlayer(), selectedPlotDifficulty)); + clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.DONE_SOUND, 1, 1); + + setCountryItems(); }); CompanionMenu.clickEventTutorialItem(getMenu()); @@ -124,9 +103,8 @@ protected void setItemClickEventsAsync() { getMenu().getSlot(startingSlot + i).setClickHandler((clickPlayer, clickInformation) -> new CityProjectMenu(clickPlayer, country, selectedPlotDifficulty)); } - for (Map.Entry entry : CompanionMenu.getFooterItems(45, getMenuPlayer(), player -> new CountryMenu(player, selectedContinent)).entrySet()) { - getMenu().getSlot(entry.getKey()).setClickHandler(entry.getValue().clickHandler); - } + Map footerItems = CompanionMenu.getFooterItems(45, getMenuPlayer(), player -> new CountryMenu(player, selectedContinent)); + footerItems.forEach((index, footerItem) -> getMenu().getSlot(index).setClickHandler(footerItem.clickHandler())); } public static boolean generateRandomPlot(Player clickPlayer, @NotNull List countryProjects, PlotDifficulty selectedPlotDifficulty) { @@ -141,7 +119,7 @@ public static boolean generateRandomPlot(Player clickPlayer, @NotNull List cities = country.getCityProjects(); - int plotsOpen = Plot.getPlots(cities, Status.unclaimed).size(); - int plotsInProgress = Plot.getPlots(cities, Status.unfinished, Status.unreviewed).size(); - int plotsCompleted = Plot.getPlots(cities, Status.completed).size(); - int plotsUnclaimed = Plot.getPlots(cities, Status.unclaimed).size(); + int plotsOpen = DataProvider.PLOT.getPlots(cities, Status.unclaimed).size(); + int plotsInProgress = DataProvider.PLOT.getPlots(cities, Status.unfinished, Status.unreviewed).size(); + int plotsCompleted = DataProvider.PLOT.getPlots(cities, Status.completed).size(); + int plotsUnclaimed = DataProvider.PLOT.getPlots(cities, Status.unclaimed).size(); getMenu().getSlot(startingSlot + countryProjects.indexOf(country)).setItem(new ItemBuilder(item) - .setName(text(country.getName(), AQUA).decoration(BOLD, true)) + .setName(text(country.getName(getMenuPlayer()), AQUA).decoration(BOLD, true)) .setLore(new LoreBuilder() .addLine(text(cities.size(), GOLD).append(text(" " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.CityProject.CITIES), GRAY))) .emptyLine() diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/companion/FooterItem.java b/src/main/java/com/alpsbte/plotsystem/core/menus/companion/FooterItem.java new file mode 100644 index 000000000..1ef6480c5 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/companion/FooterItem.java @@ -0,0 +1,11 @@ +package com.alpsbte.plotsystem.core.menus.companion; + +import org.bukkit.inventory.ItemStack; +import org.ipvp.canvas.slot.Slot; + +public record FooterItem(ItemStack item, Slot.ClickHandler clickHandler) { + + FooterItem(ItemStack item) { + this(item, null); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewItems.java b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewItems.java new file mode 100644 index 000000000..e4e5c5ca8 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewItems.java @@ -0,0 +1,67 @@ +package com.alpsbte.plotsystem.core.menus.review; + +import com.alpsbte.alpslib.utils.item.ItemBuilder; +import com.alpsbte.alpslib.utils.item.LoreBuilder; +import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import com.alpsbte.plotsystem.utils.items.BaseItems; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; +import static net.kyori.adventure.text.format.NamedTextColor.YELLOW; +import static net.kyori.adventure.text.format.TextDecoration.BOLD; + +public class ReviewItems { + public static ItemStack getReviewInfoItem(Player player) { + String points = LangUtil.getInstance().get(player, LangPaths.MenuTitle.REVIEW_POINTS); + + return new ItemBuilder(BaseItems.REVIEW_INFO.getItem()) + .setName(text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.INFORMATION), AQUA).decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLines(true, LangUtil.getInstance().get(player, LangPaths.MenuDescription.INFORMATION)) + .emptyLine() + .addLines(text(points + " <= 0: ", WHITE).append(text(LangUtil.getInstance().get(player, LangPaths.Review.ABANDONED), RED)), + text(points + " <= 8: ", WHITE).append(text(LangUtil.getInstance().get(player, LangPaths.Review.REJECTED), YELLOW)), + text(points + " > 8: ", WHITE).append(text(LangUtil.getInstance().get(player, LangPaths.Review.ACCEPTED), GREEN))) + .build()) + .build(); + } + + public static ItemStack getPlotInfoItem(Player player, Plot plot) { + String plotOwner; + String city; + String country; + String difficulty; + Player plotOwnerPlayer; + + plotOwner = plot.getPlotOwner().getName(); + city = plot.getCityProject().getName(player); + country = plot.getCityProject().getCountry().getName(player); + difficulty = plot.getDifficulty().name().charAt(0) + plot.getDifficulty().name().substring(1).toLowerCase(); + + plotOwnerPlayer = plot.getPlotOwner().getPlayer(); + + return new ItemBuilder(BaseItems.REVIEW_INFO_PLOT.getItem()) + .setName(text(LangUtil.getInstance().get(player, LangPaths.Review.REVIEW_PLOT)) + .color(AQUA) + .decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(text(LangUtil.getInstance().get(player, LangPaths.Plot.ID) + ": ", GRAY).append(text(plot.getId(), WHITE))) + .emptyLine() + .addLines(text(LangUtil.getInstance().get(player, LangPaths.Plot.OWNER) + ": ", GRAY).append(text(plotOwner, WHITE)), + text(LangUtil.getInstance().get(player, LangPaths.Plot.CITY) + ": ", GRAY).append(text(city, WHITE)), + text(LangUtil.getInstance().get(player, LangPaths.Plot.COUNTRY) + ": ", GRAY).append(text(country, WHITE)), + text(LangUtil.getInstance().get(player, LangPaths.Plot.DIFFICULTY) + ": ", GRAY).append(text(difficulty, WHITE))) + .emptyLine() + .addLine(text(LangUtil.getInstance().get(player, LangPaths.Review.PLAYER_LANGUAGE) + ": ", GRAY).append(text(LangUtil.getInstance().get(plotOwnerPlayer, "lang.name"), WHITE))) + .build()) + .build(); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewMenu.java new file mode 100644 index 000000000..b16691d31 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewMenu.java @@ -0,0 +1,205 @@ +package com.alpsbte.plotsystem.core.menus.review; + +import com.alpsbte.alpslib.utils.item.ItemBuilder; +import com.alpsbte.alpslib.utils.item.LegacyLoreBuilder; +import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.menus.AbstractPaginatedMenu; +import com.alpsbte.plotsystem.core.menus.PlotActionsMenu; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.CityProject; +import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.enums.Status; +import com.alpsbte.plotsystem.utils.io.ConfigPaths; +import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import com.alpsbte.plotsystem.utils.items.BaseItems; +import com.alpsbte.plotsystem.utils.items.MenuItems; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.ipvp.canvas.mask.BinaryMask; +import org.ipvp.canvas.mask.Mask; +import org.jetbrains.annotations.NotNull; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import static java.time.temporal.ChronoUnit.DAYS; + +public class ReviewMenu extends AbstractPaginatedMenu { + private List cityProjects = new ArrayList<>(); + private CityProject filteredCityProject = null; + + public ReviewMenu(Player player) { + super(6, 4, LangUtil.getInstance().get(player, LangPaths.Review.MANAGE_AND_REVIEW_PLOTS), player); + } + + @Override + protected List getSource() { + List plots = new ArrayList<>(); + cityProjects = DataProvider.BUILD_TEAM.getReviewerCities(getMenuPlayer().getUniqueId()); + + // Get plots based on city filter + if (filteredCityProject != null) { + plots.addAll(DataProvider.PLOT.getPlots(List.of(filteredCityProject), Status.unreviewed)); + plots.addAll(DataProvider.PLOT.getPlots(List.of(filteredCityProject), Status.unfinished)); + } else { + plots.addAll(DataProvider.PLOT.getPlots(cityProjects, Status.unreviewed)); + plots.addAll(DataProvider.PLOT.getPlots(cityProjects, Status.unfinished)); + } + + return plots; + } + + @Override + protected void setPreviewItems() { + // Set close item + getMenu().getSlot(49).setItem(MenuItems.closeMenuItem(getMenuPlayer())); + + super.setPreviewItems(); + } + + @Override + protected void setPaginatedMenuItemsAsync(List source) { + // Set filter item + getMenu().getSlot(7).setItem(getFilterItem(getMenuPlayer())); + + // Set unreviewed and unfinished plot items + List plots = getFilteredPlots(source); + for (int i = 0; i < plots.size(); i++) { + Plot plot = plots.get(i); + List lines = new ArrayList<>(); + lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.ID) + ": §f" + plot.getId()); + lines.add(""); + lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.OWNER) + ": §f" + plot.getPlotOwner().getName()); + if (!plot.getPlotMembers().isEmpty()) { + lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.MEMBERS) + ": §f" + plot.getPlotMembers().stream().map(Builder::getName).collect(Collectors.joining(", "))); + } + lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.CITY) + ": §f" + plot.getCityProject().getName(getMenuPlayer())); + lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.COUNTRY) + ": §f" + plot.getCityProject().getCountry().getName(getMenuPlayer())); + lines.add("§7" + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Plot.DIFFICULTY) + ": §f" + plot.getDifficulty().name().charAt(0) + plot.getDifficulty().name().substring(1).toLowerCase()); + lines.add(""); + + if (plot.getStatus() == Status.unfinished) { + long inactivityIntervalDays = PlotSystem.getPlugin().getConfig().getLong(ConfigPaths.INACTIVITY_INTERVAL); + long rejectedInactivityIntervalDays = (PlotSystem.getPlugin().getConfig().getLong(ConfigPaths.REJECTED_INACTIVITY_INTERVAL) != -1) ? PlotSystem.getPlugin().getConfig().getLong(ConfigPaths.REJECTED_INACTIVITY_INTERVAL) : inactivityIntervalDays; + long interval = plot.isRejected() ? rejectedInactivityIntervalDays : inactivityIntervalDays; + if (interval > -1) lines.add(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.ABANDONED_IN_DAYS, String.valueOf(DAYS.between(LocalDate.now(), plot.getLastActivity().plusDays(interval))))); + + } + + getMenu().getSlot(i + 9).setItem(new ItemBuilder(plot.getStatus() == Status.unfinished ? Material.MAP : Material.FILLED_MAP, 1) + .setName("§b§l" + LangUtil.getInstance().get(getMenuPlayer(), plot.getStatus() == Status.unfinished ? LangPaths.Review.MANAGE_PLOT : LangPaths.Review.REVIEW_PLOT)) + .setLore(lines) + .build()); + } + + // Set previous page item + getMenu().getSlot(46).setItem(hasPreviousPage() ? MenuItems.previousPageItem(getMenuPlayer()) : Utils.DEFAULT_ITEM); + + // Set next page item + getMenu().getSlot(52).setItem(hasNextPage() ? MenuItems.nextPageItem(getMenuPlayer()) : Utils.DEFAULT_ITEM); + } + + @Override + protected void setPaginatedItemClickEventsAsync(List source) { + // Set click event for unreviewed and unfinished plot items + List plots = getFilteredPlots(source); + for (int i = 0; i < plots.size(); i++) { + Plot plot = plots.get(i); + getMenu().getSlot(i + 9).setClickHandler((player, info) -> { + if (plot.getStatus() == Status.unfinished) { + new PlotActionsMenu(getMenuPlayer(), plot); + return; + } + + player.performCommand("review " + plot.getId()); + }); + } + + // Set click event for previous page item + if (hasPreviousPage()) { + getMenu().getSlot(46).setClickHandler((clickPlayer, clickInformation) -> { + previousPage(); + clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); + }); + } + + // Set click event for next page item + if (hasNextPage()) { + getMenu().getSlot(52).setClickHandler((clickPlayer, clickInformation) -> { + nextPage(); + clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); + }); + } + } + + @Override + protected void setItemClickEventsAsync() { + // Set click event for filter item + getMenu().getSlot(7).setClickHandler((clickPlayer, clickInformation) -> { + clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); + if (cityProjects.isEmpty()) return; + + if (filteredCityProject == null) { + filteredCityProject = cityProjects.getFirst(); + } else { + int index = cityProjects.indexOf(filteredCityProject); + filteredCityProject = index + 1 >= cityProjects.size() ? null : cityProjects.get(index + 1); + } + + reloadMenuAsync(false); + }); + + // Set click event for close item + getMenu().getSlot(49).setClickHandler((clickPlayer, clickInformation) -> clickPlayer.closeInventory()); + } + + @Override + protected Mask getMask() { + return BinaryMask.builder(getMenu()) + .item(Utils.DEFAULT_ITEM) + .pattern(Utils.FULL_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern("111101111") + .build(); + } + + private List getFilteredPlots(@NotNull List plots) { + return plots.stream().map(p -> (Plot) p).toList(); + } + + private ItemStack getFilterItem(Player langPlayer) { + LegacyLoreBuilder LegacyLoreBuilder = new LegacyLoreBuilder(); + LegacyLoreBuilder.addLine((filteredCityProject == null ? "§b§l> §f§l" : "§7") + LangUtil.getInstance().get(langPlayer, LangPaths.MenuDescription.FILTER)); + LegacyLoreBuilder.emptyLine(); + + cityProjects.forEach(c -> { + if (filteredCityProject != null && filteredCityProject.getId().equals(c.getId())) { + LegacyLoreBuilder.addLine("§b§l> §f§l" + filteredCityProject.getName(langPlayer)); + } else LegacyLoreBuilder.addLine("§7" + c.getName(langPlayer)); + }); + + return new ItemBuilder(MenuItems.filterItem(getMenuPlayer())) + .setLore(LegacyLoreBuilder.build()) + .setEnchanted(filteredCityProject != null) + .build(); + } + + /** + * @return Menu item + */ + public static ItemStack getMenuItem(Player player) { + return new ItemBuilder(BaseItems.REVIEW_ITEM.getItem()) + .setName("§b§l" + LangUtil.getInstance().get(player, LangPaths.MenuTitle.REVIEW_PLOTS) + " §7(" + LangUtil.getInstance().get(player, LangPaths.Note.Action.RIGHT_CLICK) + ")") + .setEnchanted(true) + .build(); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotMenu.java new file mode 100644 index 000000000..595bb507d --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotMenu.java @@ -0,0 +1,295 @@ +package com.alpsbte.plotsystem.core.menus.review; + +import com.alpsbte.alpslib.utils.item.ItemBuilder; +import com.alpsbte.alpslib.utils.item.LoreBuilder; +import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.menus.AbstractMenu; +import com.alpsbte.plotsystem.core.menus.PlotActionsMenu; +import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.core.system.review.ReviewRating; +import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.enums.Status; +import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import com.alpsbte.plotsystem.utils.items.BaseItems; +import com.alpsbte.plotsystem.utils.items.MenuItems; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.enchantments.Enchantment; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemFlag; +import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; +import org.ipvp.canvas.mask.BinaryMask; +import org.ipvp.canvas.mask.Mask; + +import java.util.List; +import java.util.Objects; + +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.YELLOW; +import static net.kyori.adventure.text.format.TextDecoration.BOLD; + +public class ReviewPlotMenu extends AbstractMenu { + private final Plot plot; + private final ReviewRating rating; + + boolean sentWarning = false; + + public ReviewPlotMenu(Player player, Plot plot, ReviewRating rating) { + super(6, LangUtil.getInstance().get(player, LangPaths.MenuTitle.REVIEW_PLOT, Integer.toString(plot.getId())), player); + this.plot = plot; + this.rating = rating; + } + + public ReviewPlotMenu(Player player, Plot plot) { + this(player, plot, + new ReviewRating(0, 0, List.of(), DataProvider.REVIEW.getBuildTeamToggleCriteria(plot.getCityProject().getBuildTeam().getId()))); + } + + @Override + protected void setPreviewItems() { + getMenu().getSlot(4).setItem(MenuItems.loadingItem(Material.MAP, getMenuPlayer())); + + getMenu().getSlot(19).setItem(getAccuracyItem()); + getMenu().getSlot(28).setItem(getBlockPaletteItem()); + + super.setPreviewItems(); + } + + @Override + protected void setMenuItemsAsync() { + // Set plot information item + getMenu().getSlot(4).setItem(ReviewItems.getPlotInfoItem(getMenuPlayer(), plot)); + + // Set review information item + getMenu().getSlot(7).setItem(ReviewItems.getReviewInfoItem(getMenuPlayer())); + + // Set back item + getMenu().getSlot(48).setItem(MenuItems.backMenuItem(getMenuPlayer())); + + // Set next item + getMenu().getSlot(50).setItem(MenuItems.continueMenuItem(getMenuPlayer())); + + // Set point items + for (int row = 0; row < 2; row++) { + int selectedPoints = row == 0 ? rating.getAccuracyPoints() : rating.getBlockPalettePoints(); + for (int col = 0; col < 6; col++) { + ItemStack item; + switch (col) { + case 0 -> item = getZeroPointItem(); + case 1 -> item = getOnePointItem(); + case 2 -> item = getTwoPointItem(); + case 3 -> item = getThreePointItem(); + case 4 -> item = getFourPointItem(); + default -> item = getFivePointItem(); + } + + if (selectedPoints == col) { + ItemMeta itemMeta = item.getItemMeta(); + Objects.requireNonNull(itemMeta).addEnchant(Enchantment.POWER, 1, true); + item.setItemMeta(itemMeta); + item.addItemFlags(ItemFlag.HIDE_ENCHANTS); + } else { + item.removeEnchantment(Enchantment.POWER); + } + + getMenu().getSlot(20 + col + (9 * row)).setItem(item); + } + } + } + + @Override + protected void setItemClickEventsAsync() { + // Set click event for back item + getMenu().getSlot(48).setClickHandler((clickPlayer, clickInformation) -> { + clickPlayer.closeInventory(); + new ReviewMenu(clickPlayer); + }); + + // Set click event for plot info item + getMenu().getSlot(4).setClickHandler((clickPlayer, clickInformation) -> { + clickPlayer.closeInventory(); + new PlotActionsMenu(clickPlayer, plot); + }); + + // Set click event for submit item + getMenu().getSlot(50).setClickHandler((clickPlayer, clickInformation) + -> Bukkit.getScheduler().runTaskAsynchronously(PlotSystem.getPlugin(), () -> { + int totalRating = rating.getAccuracyPoints() + rating.getBlockPalettePoints(); + if (totalRating == 0 && !sentWarning) { + clickPlayer.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_WILL_GET_ABANDONED))); + clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.CREATE_PLOT_SOUND, 1, 1); + sentWarning = true; + return; + } else if (totalRating == 0) { + plot.setStatus(Status.unfinished); + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + clickPlayer.closeInventory(); + clickPlayer.performCommand("plot abandon " + plot.getId()); + }); + return; + } + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + clickPlayer.closeInventory(); + new ReviewPlotTogglesMenu(clickPlayer, plot, rating); + }); + })); + + // Set click event for point selection items + for (int col = 0; col < 6; col++) { + for (int row = 0; row < 2; row++) { + int slot = 20 + col + (9 * row); + int captureRow = row; // need to assign separate variables so that they can be captured by the lambda + int points = col; + ItemMeta meta = getMenu().getSlot(slot).getItem(getMenuPlayer()).getItemMeta(); + getMenu().getSlot(slot).setClickHandler((clickPlayer, clickInformation) -> { + for (int j = 0; j < 6; j++) { + ItemStack previousItem = getMenu().getSlot(20 + j + (9 * captureRow)).getItem(clickPlayer); + if (previousItem == null || !previousItem.getItemMeta().hasEnchant(Enchantment.POWER)) continue; + + ItemMeta metaPrevious = previousItem.getItemMeta(); + assert metaPrevious != null; + metaPrevious.removeEnchant(Enchantment.POWER); + previousItem.setItemMeta(metaPrevious); + getMenu().getSlot(20 + j + (9 * captureRow)).setItem(previousItem); + } + + assert meta != null; + meta.addEnchant(Enchantment.POWER, 1, true); + clickPlayer.playSound(clickPlayer.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); + + ItemStack newItem = getMenu().getSlot(slot).getItem(clickPlayer); + newItem.setItemMeta(meta); + newItem.addItemFlags(ItemFlag.HIDE_ENCHANTS); + getMenu().getSlot(slot).setItem(newItem); + sentWarning = false; + + if (captureRow == 0) rating.setAccuracyPoints(points); + else rating.setBlockPalettePoints(points); + }); + } + } + } + + @Override + protected Mask getMask() { + return BinaryMask.builder(getMenu()) + .item(Utils.DEFAULT_ITEM) + .pattern("111101111") + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern("111010111") + .build(); + } + + // --- Category Items --- + private ItemStack getAccuracyItem() { + return new ItemBuilder(BaseItems.REVIEW_ACCURACY.getItem()) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.ACCURACY)) + .color(GREEN) + .decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLines(true, LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.ACCURACY_DESC)) + .build()) + .build(); + } + + private ItemStack getBlockPaletteItem() { + return new ItemBuilder(BaseItems.REVIEW_BLOCK_PALETTE.getItem()) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.BLOCK_PALETTE)) + .color(GREEN) + .decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLines(true, LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.Criteria.BLOCK_PALETTE_DESC)) + .build()) + .build(); + } + + // --- Point Items --- + private ItemStack getZeroPointItem() { + return new ItemBuilder(BaseItems.REVIEW_POINT_ZERO.getItem()) + .setName(text("0 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS)) + .color(GRAY) + .decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) + .build()) + .build(); + } + + private ItemStack getOnePointItem() { + return new ItemBuilder(BaseItems.REVIEW_POINT_ONE.getItem()) + .setName(text("1 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINT)) + .color(RED) + .decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) + .build()) + .build(); + } + + private ItemStack getTwoPointItem() { + ItemStack item = BaseItems.REVIEW_POINT_TWO.getItem(); + item.setAmount(2); + + return new ItemBuilder(item) + .setName(text("2 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS)) + .color(GOLD) + .decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) + .build()) + .build(); + } + + private ItemStack getThreePointItem() { + ItemStack item = BaseItems.REVIEW_POINT_THREE.getItem(); + item.setAmount(3); + + return new ItemBuilder(item) + .setName(text("3 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS)) + .color(YELLOW) + .decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) + .build()) + .build(); + } + + private ItemStack getFourPointItem() { + ItemStack item = BaseItems.REVIEW_POINT_FOUR.getItem(); + item.setAmount(4); + + return new ItemBuilder(item) + .setName(text("4 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS)) + .color(DARK_GREEN) + .decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) + .build()) + .build(); + } + + private ItemStack getFivePointItem() { + ItemStack item = BaseItems.REVIEW_POINT_FIVE.getItem(); + item.setAmount(5); + + return new ItemBuilder(item) + .setName(text("5 " + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.REVIEW_POINTS)) + .color(GREEN) + .decoration(BOLD, true)) + .setLore(new LoreBuilder() + .addLine(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.REVIEW_POINTS)) + .build()) + .build(); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java new file mode 100644 index 000000000..91e949de3 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/review/ReviewPlotTogglesMenu.java @@ -0,0 +1,267 @@ +package com.alpsbte.plotsystem.core.menus.review; + +import com.alpsbte.alpslib.utils.item.ItemBuilder; +import com.alpsbte.alpslib.utils.item.LoreBuilder; +import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.menus.AbstractMenu; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; +import com.alpsbte.plotsystem.core.system.review.PlotReview; +import com.alpsbte.plotsystem.core.system.review.ReviewRating; +import com.alpsbte.plotsystem.core.system.review.ToggleCriteria; +import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.utils.chat.ChatInput; +import com.alpsbte.plotsystem.utils.chat.PlayerFeedbackChatInput; +import com.alpsbte.plotsystem.utils.enums.Status; +import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import com.alpsbte.plotsystem.utils.items.BaseItems; +import com.alpsbte.plotsystem.utils.items.MenuItems; +import com.sk89q.worldedit.WorldEditException; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.NamedTextColor; +import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.ipvp.canvas.mask.BinaryMask; +import org.ipvp.canvas.mask.Mask; +import org.jetbrains.annotations.NotNull; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import static net.kyori.adventure.text.Component.text; + +public class ReviewPlotTogglesMenu extends AbstractMenu { + private final Plot plot; + private final ReviewRating rating; + private List buildTeamCriteria = new ArrayList<>(); + + public ReviewPlotTogglesMenu(Player player, @NotNull Plot plot, ReviewRating rating) { + super(6, LangUtil.getInstance().get(player, LangPaths.MenuTitle.REVIEW_PLOT, Integer.toString(plot.getId())), player); + this.plot = plot; + this.rating = rating; + } + + @Override + protected void setMenuItemsAsync() { + // Set plot information item + getMenu().getSlot(4).setItem(ReviewItems.getPlotInfoItem(getMenuPlayer(), plot)); + + // Set review information item + getMenu().getSlot(7).setItem(ReviewItems.getReviewInfoItem(getMenuPlayer())); + + // Set toggle items + buildTeamCriteria = DataProvider.REVIEW.getBuildTeamToggleCriteria(plot.getCityProject().getBuildTeam().getId()); + for (int i = 0; i < Math.min(buildTeamCriteria.size(), 36); i++) { + ToggleCriteria criteria = buildTeamCriteria.get(i); + boolean isChecked = rating.getCheckedToggles().stream() + .anyMatch(t -> t.criteriaName().equals(criteria.criteriaName())); + getMenu().getSlot(9 + i).setItem(getToggleItem(criteria, isChecked)); + } + + // Set back item + getMenu().getSlot(48).setItem(MenuItems.backMenuItem(getMenuPlayer())); + + // Set submit item + getMenu().getSlot(50).setItem(getSubmitItem()); + } + + @Override + protected void setItemClickEventsAsync() { + // Set click event for back item + getMenu().getSlot(48).setClickHandler(((player, clickInformation) -> { + player.closeInventory(); + new ReviewPlotMenu(player, plot, rating); + })); + + // Set click event for submit item + getMenu().getSlot(50).setClickHandler(((player, clickInformation) -> submitReview())); + + // Set click event for toggle items + for (int i = 0; i < Math.min(buildTeamCriteria.size(), 36); i++) { + int finalI = i; + getMenu().getSlot(9 + i).setClickHandler(((player, clickInformation) -> { + ToggleCriteria clickedCriteria = buildTeamCriteria.get(finalI); + boolean isChecked = rating.getCheckedToggles().stream().anyMatch(t -> t.criteriaName().equals(clickedCriteria.criteriaName())); + rating.setToggleCriteria(clickedCriteria, !isChecked); + + getMenu().getSlot(9 + finalI).setItem(getToggleItem(clickedCriteria, !isChecked)); + getMenu().getSlot(50).setItem(getSubmitItem()); // update submit item + + player.playSound(player.getLocation(), Utils.SoundUtils.INVENTORY_CLICK_SOUND, 1, 1); + })); + } + } + + @Override + protected Mask getMask() { + return BinaryMask.builder(getMenu()) + .item(Utils.DEFAULT_ITEM) + .pattern("111101111") + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern("111010111") + .build(); + } + + private void submitReview() { + boolean isRejected = rating.isRejected(); + int totalRating = rating.getTotalRating(); + + double scoreMultiplier = DataProvider.DIFFICULTY.getDifficultyByEnum(plot.getDifficulty()).orElseThrow().getMultiplier(); + int score = (int) Math.floor(totalRating * scoreMultiplier); + + PlotReview review = DataProvider.REVIEW.createReview(plot, rating, score, getMenuPlayer().getUniqueId()); + if (review == null) { + getMenuPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Error.ERROR_OCCURRED))); + return; + } + + Component reviewerConfirmationMessage; + if (!isRejected) { + reviewerConfirmationMessage = Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_MARKED_REVIEWED, Integer.toString(plot.getId()), getParticipantsString())); + if(!acceptPlot(review.getScore(), review.getSplitScore())) return; + } else { + reviewerConfirmationMessage = Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_REJECTED, Integer.toString(plot.getId()), getParticipantsString())); + PlotUtils.Actions.undoSubmit(plot); + } + + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + for (Player player : plot.getWorld().getBukkitWorld().getPlayers()) { + player.teleport(Utils.getSpawnLocation()); + } + + // Delete plot world after reviewing + if (!isRejected && plot.getPlotType().hasOnePlotPerWorld()) + plot.getWorld().deleteWorld(); + + getMenuPlayer().sendMessage(reviewerConfirmationMessage); + getMenuPlayer().playSound(getMenuPlayer().getLocation(), Utils.SoundUtils.FINISH_PLOT_SOUND, 1f, 1f); + + + ChatInput.awaitChatInput.put(getMenuPlayer().getUniqueId(), + new PlayerFeedbackChatInput(getMenuPlayer().getUniqueId(), plot.getLatestReview().orElseThrow())); + PlayerFeedbackChatInput.sendChatInputMessage(getMenuPlayer()); + }); + } + + private String getParticipantsString() { + if (plot.getPlotMembers().isEmpty()) { + return plot.getPlotOwner().getName(); + } else { + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < plot.getPlotMembers().size(); i++) { + sb.append(i == plot.getPlotMembers().size() - 1 ? + plot.getPlotMembers().get(i).getName() : + plot.getPlotMembers().get(i).getName() + ", "); + } + return sb.toString(); + } + } + + private boolean acceptPlot(int score, int splitScore) { + getMenuPlayer().sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.SAVING_PLOT))); + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + try { + if (!PlotUtils.savePlotAsSchematic(plot)) { + getMenuPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Error.ERROR_OCCURRED))); + PlotSystem.getPlugin().getComponentLogger().warn(text("Could not save finished plot schematic (ID: " + plot.getId() + ")!")); + } + } catch (IOException | WorldEditException ex) { + PlotSystem.getPlugin().getComponentLogger().error(text("Could not save finished plot schematic (ID: " + plot.getId() + ")!"), ex); + } + }); + + plot.setStatus(Status.completed); + + // Remove Plot from Owner + if (!plot.getPlotOwner().setSlot(plot.getPlotOwner().getSlotByPlotId(plot.getId()), -1)) return false; + + if (plot.getPlotMembers().isEmpty()) { + // Plot was made alone + // Builder gets 100% of score + return plot.getPlotOwner().addScore(score); + } else { + // Plot was made in a group + // Score gets split between all participants + if (!plot.getPlotOwner().addScore(splitScore)) return false; + + for (Builder builder : plot.getPlotMembers()) { + // Score gets split between all participants + if (!builder.addScore(splitScore)) return false; + + // Remove Slot from Member + if (!builder.setSlot(builder.getSlotByPlotId(plot.getId()), -1)) return false; + } + } + return true; + } + + private ItemStack getToggleItem(@NotNull ToggleCriteria criteria, boolean checked) { + Player p = getMenuPlayer(); + ItemStack baseItem = checked + ? BaseItems.REVIEW_TOGGLE_CHECKED.getItem() + : criteria.isOptional() ? BaseItems.REVIEW_TOGGLE_OPTIONAL.getItem() : BaseItems.REVIEW_TOGGLE_REQUIRED.getItem(); + return new ItemBuilder(baseItem) + .setName(text(criteria.getDisplayName(p))) + .setLore(new LoreBuilder() + .addLine(criteria.isOptional() + ? text(LangUtil.getInstance().get(p, LangPaths.Note.OPTIONAL), NamedTextColor.GRAY).decoration(TextDecoration.BOLD, true) + : text(LangUtil.getInstance().get(p, LangPaths.Note.REQUIRED), NamedTextColor.GOLD).decoration(TextDecoration.BOLD, true)) + .emptyLine() + .addLine(text(LangUtil.getInstance().get(p, LangPaths.Note.Action.CLICK_TO_TOGGLE), NamedTextColor.GRAY)) + .build()) + .build(); + } + + private ItemStack getSubmitItem() { + int totalToggles = buildTeamCriteria.size(); + int checkedToggles = rating.getCheckedToggles().size(); + double togglePercentage = (double) checkedToggles / totalToggles * 100; + int togglePoints = rating.getTogglePoints(); + int totalPoints = rating.getTotalRating(); + + String accuracyPointsText = LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.ACCURACY_POINTS); + String blockPalettePointsText = LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.BLOCK_PALETTE_POINTS); + String togglesPointsText = LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.TOGGLE_POINTS); + String totalPointsText = LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Review.TOTAL_POINTS); + + boolean willReject = rating.isRejected(); + + TextComponent resultNotice; + if (willReject) { + resultNotice = text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_WILL_BE_REJECTED), NamedTextColor.YELLOW); + } else { + resultNotice = text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.Message.Info.PLOT_WILL_BE_ACCEPTED), NamedTextColor.GREEN); + } + + return new ItemBuilder(BaseItems.REVIEW_SUBMIT.getItem()) + .setName(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.SUBMIT), NamedTextColor.GREEN).decoration(TextDecoration.BOLD, true)) + .setLore(new LoreBuilder() + .addLine(text(LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.SUBMIT_REVIEW), NamedTextColor.GRAY), true) + .emptyLine() + .addLine(text( accuracyPointsText + ": ", NamedTextColor.GRAY) + .append(text(rating.getAccuracyPoints(), NamedTextColor.WHITE))) + .addLine(text( blockPalettePointsText + ": ", NamedTextColor.GRAY) + .append(text(rating.getBlockPalettePoints(), NamedTextColor.WHITE))) + .addLine(text( togglesPointsText + ": ", NamedTextColor.GRAY) + .append(text(togglePoints, NamedTextColor.WHITE)) + .append(text(" (" + checkedToggles + "/" + totalToggles + " → " + String.format("%.02f", togglePercentage) + "%)", NamedTextColor.DARK_GRAY))) + .addLine(text("-----", NamedTextColor.DARK_GRAY)) + .addLine(text(totalPointsText + ": ", NamedTextColor.GRAY) + .append(text(totalPoints, NamedTextColor.GOLD))) + .emptyLine() + .addLine(resultNotice) + .build()) + .build(); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/tutorial/TutorialStagesMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/tutorial/TutorialStagesMenu.java index 3a3200cc3..e7aaf7454 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/tutorial/TutorialStagesMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/tutorial/TutorialStagesMenu.java @@ -1,31 +1,8 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus.tutorial; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LegacyLoreBuilder; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.menus.AbstractMenu; import com.alpsbte.plotsystem.core.system.plot.TutorialPlot; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; @@ -37,7 +14,6 @@ import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import com.alpsbte.plotsystem.utils.items.MenuItems; -import net.kyori.adventure.text.Component; import net.md_5.bungee.api.ChatColor; import org.bukkit.Material; import org.bukkit.Sound; @@ -46,9 +22,12 @@ import org.ipvp.canvas.mask.BinaryMask; import org.ipvp.canvas.mask.Mask; -import java.sql.SQLException; - -import static net.md_5.bungee.api.ChatColor.*; +import static net.md_5.bungee.api.ChatColor.AQUA; +import static net.md_5.bungee.api.ChatColor.BOLD; +import static net.md_5.bungee.api.ChatColor.GREEN; +import static net.md_5.bungee.api.ChatColor.RED; +import static net.md_5.bungee.api.ChatColor.WHITE; +import static net.md_5.bungee.api.ChatColor.YELLOW; public class TutorialStagesMenu extends AbstractMenu { private static final int TOTAL_STAGES_ROWS = 2; @@ -125,13 +104,11 @@ protected void setPreviewItems() { @Override protected void setMenuItemsAsync() { - try { - plot = TutorialPlot.getPlot(getMenuPlayer().getUniqueId().toString(), tutorialId); - if (plot != null) { - playerHighestStage = plot.getStageID(); - isTutorialCompleted = plot.isCompleted(); - } - } catch (SQLException ex) {Utils.logSqlException(ex);} + plot = DataProvider.TUTORIAL_PLOT.getByTutorialId(tutorialId, getMenuPlayer().getUniqueId().toString()).orElse(null); + if (plot != null) { + playerHighestStage = plot.getStageID(); + isTutorialCompleted = plot.isComplete(); + } // Set tutorial stats item ItemBuilder tutorialItem = new ItemBuilder(Material.valueOf(tutorialItemName)); @@ -180,7 +157,7 @@ protected void setItemClickEventsAsync() { @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE).setName(Component.empty()).build()) + .item(Utils.DEFAULT_ITEM) .pattern("111101111") .pattern(Utils.EMPTY_MASK) .pattern(Utils.EMPTY_MASK) diff --git a/src/main/java/com/alpsbte/plotsystem/core/menus/tutorial/TutorialsMenu.java b/src/main/java/com/alpsbte/plotsystem/core/menus/tutorial/TutorialsMenu.java index acc00cd93..04e270690 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/menus/tutorial/TutorialsMenu.java +++ b/src/main/java/com/alpsbte/plotsystem/core/menus/tutorial/TutorialsMenu.java @@ -1,33 +1,10 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.menus.tutorial; import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.menus.AbstractMenu; import com.alpsbte.plotsystem.core.system.plot.TutorialPlot; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; @@ -38,9 +15,8 @@ import com.alpsbte.plotsystem.utils.io.ConfigUtil; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.alpsbte.plotsystem.utils.items.CustomHeads; +import com.alpsbte.plotsystem.utils.items.BaseItems; import com.alpsbte.plotsystem.utils.items.MenuItems; -import net.kyori.adventure.text.Component; import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.entity.Player; @@ -49,10 +25,14 @@ import org.ipvp.canvas.mask.BinaryMask; import org.ipvp.canvas.mask.Mask; -import java.sql.SQLException; - import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; +import static net.kyori.adventure.text.format.NamedTextColor.YELLOW; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class TutorialsMenu extends AbstractMenu { @@ -91,23 +71,18 @@ protected void setPreviewItems() { @Override protected void setMenuItemsAsync() { // Set tutorial items - try { - plot = TutorialPlot.getPlot(getMenuPlayer().getUniqueId().toString(), TutorialCategory.BEGINNER.getId()); - // TutorialPlot beginnerTutorial = getPlotById(TutorialCategory.BEGINNER.getId()); - if (plot != null) isBeginnerTutorialCompleted = plot.isCompleted(); - - // Set beginner tutorial item - getMenu().getSlot(22).setItem(getTutorialItem(TutorialCategory.BEGINNER.getId(), beginnerTutorialItemName, - LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.TUTORIAL_BEGINNER), - LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.TUTORIAL_BEGINNER)) - ); - - // Set back item - if (!PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.TUTORIAL_REQUIRE_BEGINNER_TUTORIAL) || isBeginnerTutorialCompleted) - getMenu().getSlot(49).setItem(MenuItems.backMenuItem(getMenuPlayer())); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + plot = DataProvider.TUTORIAL_PLOT.getByTutorialId(TutorialCategory.BEGINNER.getId(), getMenuPlayer().getUniqueId().toString()).orElse(null); + if (plot != null) isBeginnerTutorialCompleted = plot.isComplete(); + + // Set beginner tutorial item + getMenu().getSlot(22).setItem(getTutorialItem(TutorialCategory.BEGINNER.getId(), beginnerTutorialItemName, + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuTitle.TUTORIAL_BEGINNER), + LangUtil.getInstance().get(getMenuPlayer(), LangPaths.MenuDescription.TUTORIAL_BEGINNER)) + ); + + // Set back item + getMenu().getSlot(49).setItem(!PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.TUTORIAL_REQUIRE_BEGINNER_TUTORIAL) + || isBeginnerTutorialCompleted ? MenuItems.backMenuItem( getMenuPlayer()) : Utils.DEFAULT_ITEM); } @Override @@ -130,13 +105,13 @@ protected void setItemClickEventsAsync() { @Override protected Mask getMask() { return BinaryMask.builder(getMenu()) - .item(new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE).setName(Component.empty()).build()) + .item(Utils.DEFAULT_ITEM) .pattern("111101111") - .pattern("000000000") - .pattern("000000000") - .pattern("000000000") - .pattern("000000000") - .pattern("111111111") + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.EMPTY_MASK) + .pattern(Utils.FULL_MASK) .build(); } @@ -149,9 +124,8 @@ protected Mask getMask() { private void setTutorialClickEvent(int tutorialId, ClickType clickType) { if (tutorialId >= 0 && tutorialId < TutorialCategory.values().length) { if (clickType == ClickType.LEFT) { - // TutorialPlot plot = getPlotById(tutorialId); try { - if (plot == null || !plot.isCompleted()) { + if (plot == null || !plot.isComplete()) { getMenuPlayer().closeInventory(); if (!AbstractTutorial.loadTutorial(getMenuPlayer(), tutorialId)) { if (AbstractTutorial.getActiveTutorial(getMenuPlayer().getUniqueId()) != null) { @@ -176,15 +150,15 @@ private void setTutorialClickEvent(int tutorialId, ClickType clickType) { getMenuPlayer().playSound(getMenuPlayer().getLocation(), Sound.ENTITY_ITEM_FRAME_ADD_ITEM, 0.8f, 0.8f); } - private ItemStack getTutorialItem(int tutorialId, String itemName, String title, String desc) throws SQLException { + private ItemStack getTutorialItem(int tutorialId, String itemName, String title, String desc) { return (tutorialId != TutorialCategory.BEGINNER.getId()) ? getAdvancedTutorialItem(getMenuPlayer()) : constructTutorialItem(getMenuPlayer(), tutorialId, plot, new ItemStack(Material.valueOf(itemName)), title, desc); } - private static ItemStack constructTutorialItem(Player player, int tutorialId, TutorialPlot plot, ItemStack itemStack, String title, String desc) throws SQLException { + private static ItemStack constructTutorialItem(Player player, int tutorialId, TutorialPlot plot, ItemStack itemStack, String title, String desc) { // Create tutorial item lore int highestPlotStage = plot != null ? plot.getStageID() : 0; - boolean isPlotCompleted = plot != null && plot.isCompleted(); + boolean isPlotCompleted = plot != null && plot.isComplete(); LoreBuilder loreBuilder = new LoreBuilder() .addLine(text(desc, GRAY), true) .emptyLine() @@ -215,7 +189,7 @@ private static ItemStack getAdvancedTutorialItem(Player player) { } public static ItemStack getTutorialItem(Player player) { - return new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.WORKBENCH.getId())) + return new ItemBuilder(BaseItems.TUTORIAL_ITEM.getItem()) .setName(text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.TUTORIALS), AQUA, BOLD)) .setLore(new LoreBuilder().addLine(LangUtil.getInstance().get(player, LangPaths.MenuDescription.TUTORIALS), true).build()) .build(); diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/BuildTeam.java b/src/main/java/com/alpsbte/plotsystem/core/system/BuildTeam.java index 3ad21d422..743cdbde9 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/BuildTeam.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/BuildTeam.java @@ -1,147 +1,70 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2022, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system; -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; +import com.alpsbte.plotsystem.core.database.DataProvider; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import java.util.UUID; - -import static net.kyori.adventure.text.Component.text; +import java.util.Optional; public class BuildTeam { - private final int ID; + private final int id; private String name; + private final List cityProjects; + private final List reviewers; + + @Contract(pure = true) + public BuildTeam(int id, String name, List cities, List reviewers) { + this.id = id; + this.name = name; + this.cityProjects = cities; + this.reviewers = reviewers; + } - private BuildTeam(int ID) throws SQLException { - this.ID = ID; - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT name FROM plotsystem_buildteams WHERE id = ?") - .setValue(ID).executeQuery()) { - - if (rs.next()) this.name = rs.getString(1); - DatabaseConnection.closeResultSet(rs); - } + public BuildTeam(int id, String name) { + this(id, name, new ArrayList<>(), new ArrayList<>()); } - public int getID() { - return ID; + public int getId() { + return id; } public String getName() { return name; } - public List getCountries() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT country_id FROM plotsystem_buildteam_has_countries WHERE buildteam_id = ?") - .setValue(ID).executeQuery()) { - - List countries = new ArrayList<>(); - while (rs.next()) countries.add(new Country(rs.getInt(1))); - DatabaseConnection.closeResultSet(rs); - return countries; - } + public List getCityProjects() { + return cityProjects; } - public List getReviewers() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT builder_uuid FROM plotsystem_builder_is_reviewer WHERE buildteam_id = ?") - .setValue(ID).executeQuery()) { - - List builders = new ArrayList<>(); - while (rs.next()) builders.add(Builder.byUUID(UUID.fromString(rs.getString(1)))); - DatabaseConnection.closeResultSet(rs); - return builders; - } + public List getReviewers() { + return reviewers; } - public static List getBuildTeamsByReviewer(UUID reviewerUUID) throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT buildteam_id FROM plotsystem_builder_is_reviewer WHERE builder_uuid = ?") - .setValue(reviewerUUID.toString()).executeQuery()) { - - List buildTeams = new ArrayList<>(); - while (rs.next()) buildTeams.add(new BuildTeam(rs.getInt(1))); - DatabaseConnection.closeResultSet(rs); - return buildTeams; + public boolean setName(String newName) { + if (DataProvider.BUILD_TEAM.setBuildTeamName(id, newName)) { + this.name = newName; + return true; } + return false; } - public static List getBuildTeams() { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_buildteams").executeQuery()) { - List buildTeams = new ArrayList<>(); - while (rs.next()) buildTeams.add(new BuildTeam(rs.getInt(1))); - DatabaseConnection.closeResultSet(rs); - return buildTeams; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + public boolean removeReviewer(String reviewerUUID) { + Optional removeReviewer = reviewers.stream().filter(r -> r.getUUID().toString().equals(reviewerUUID)).findFirst(); + if (removeReviewer.isEmpty()) return false; + if (DataProvider.BUILD_TEAM.removeReviewer(id, reviewerUUID)) { + this.reviewers.remove(removeReviewer.get()); + return true; } - return new ArrayList<>(); - } - - public static void addBuildTeam(String name) throws SQLException { - int id = DatabaseConnection.getTableID("plotsystem_buildteams"); - DatabaseConnection.createStatement("INSERT INTO plotsystem_buildteams (id, name) VALUES (?, ?)") - .setValue(id) - .setValue(name).executeUpdate(); - } - - public static void removeBuildTeam(int serverID) throws SQLException { - DatabaseConnection.createStatement("DELETE FROM plotsystem_buildteams WHERE id = ?") - .setValue(serverID).executeUpdate(); - } - - public static void setBuildTeamName(int id, String newName) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_buildteams SET name = ? WHERE id = ?") - .setValue(newName) - .setValue(id).executeUpdate(); - } - - public static void addCountry(int id, int countryID) throws SQLException { - DatabaseConnection.createStatement("INSERT plotsystem_buildteam_has_countries SET country_id = ?, buildteam_id = ?") - .setValue(countryID) - .setValue(id).executeUpdate(); - } - - public static void removeCountry(int id, int countryID) throws SQLException { - DatabaseConnection.createStatement("DELETE FROM plotsystem_buildteam_has_countries WHERE country_id = ? AND buildteam_id = ?") - .setValue(countryID) - .setValue(id).executeUpdate(); + return false; } - public static void addReviewer(int id, String reviewerUUID) throws SQLException { - DatabaseConnection.createStatement("INSERT plotsystem_builder_is_reviewer SET builder_uuid = ?, buildteam_id = ?") - .setValue(reviewerUUID) - .setValue(id).executeUpdate(); - } - - public static void removeReviewer(int id, String reviewerUUID) throws SQLException { - DatabaseConnection.createStatement("DELETE FROM plotsystem_builder_is_reviewer WHERE builder_uuid = ? AND buildteam_id = ?") - .setValue(reviewerUUID) - .setValue(id).executeUpdate(); + public boolean addReviewer(@NotNull Builder reviewer) { + if (DataProvider.BUILD_TEAM.addReviewer(id, reviewer.getUUID().toString())) { + this.reviewers.add(reviewer); + return true; + } + return false; } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/Builder.java b/src/main/java/com/alpsbte/plotsystem/core/system/Builder.java index 0cdb3ed25..62c8809b6 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/Builder.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/Builder.java @@ -1,467 +1,139 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system; -import com.alpsbte.alpslib.hologram.DecentHologramDisplay; -import com.alpsbte.alpslib.utils.item.ItemBuilder; -import com.alpsbte.alpslib.utils.item.LoreBuilder; import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; -import com.alpsbte.plotsystem.core.holograms.PlotsLeaderboard; -import com.alpsbte.plotsystem.core.holograms.ScoreLeaderboard; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.utils.PlotType; import com.alpsbte.plotsystem.utils.enums.Slot; -import com.alpsbte.plotsystem.utils.io.LangPaths; -import com.alpsbte.plotsystem.utils.io.LangUtil; -import net.kyori.adventure.text.TextComponent; -import net.kyori.adventure.text.format.NamedTextColor; -import net.kyori.adventure.text.format.TextDecoration; +import com.alpsbte.plotsystem.utils.io.ConfigPaths; import org.bukkit.Bukkit; -import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.*; -import java.util.stream.Collectors; -import static net.kyori.adventure.text.Component.empty; -import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.GRAY; -import static net.kyori.adventure.text.format.NamedTextColor.WHITE; +import java.util.UUID; public class Builder { - - public static final HashMap builders = new HashMap<>(); - private final UUID uuid; - public PlotType plotType; - - private Builder(UUID UUID) { - this.uuid = UUID; - } - - public static Builder byUUID(UUID uuid) { - if (builders.containsKey(uuid)) - return builders.get(uuid); - - Builder builder = new Builder(uuid); - builders.put(uuid, builder); - - return builders.get(uuid); - } - + private String name; + private int score; + private int firstSlot; + private int secondSlot; + private int thirdSlot; + private int plotType; + + public Builder(UUID uniqueId, String name, int score, int firstSlot, int secondSlot, int thirdSlot, int plotType) { + this.uuid = uniqueId; + this.name = name; + this.score = score; + this.firstSlot = firstSlot; + this.secondSlot = secondSlot; + this.thirdSlot = thirdSlot; + this.plotType = plotType; - public Player getPlayer() { - return Bukkit.getPlayer(uuid); + boolean inspirationModeDisabled = PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DISABLE_CITY_INSPIRATION_MODE); // TODO remove or improve when CIM is working again + if (inspirationModeDisabled && plotType == 2) this.plotType = 1; } public java.util.UUID getUUID() { return uuid; } - public boolean isOnline() {return Bukkit.getPlayer(uuid) != null;} - - public String getName() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT name FROM plotsystem_builders WHERE uuid = ?") - .setValue(getUUID().toString()).executeQuery()) { - - if (rs.next()) { - String s = rs.getString(1); - DatabaseConnection.closeResultSet(rs); - return s; - } - - DatabaseConnection.closeResultSet(rs); - - return getPlayer() != null ? getPlayer().getName() : ""; - } + public String getName() { + return name; } - public int getScore() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT score FROM plotsystem_builders WHERE uuid = ?") - .setValue(getUUID().toString()).executeQuery()) { - - if (rs.next()) { - int i = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return i; - } - - DatabaseConnection.closeResultSet(rs); - return 0; + public boolean setName(String name) { + if (DataProvider.BUILDER.setName(this.uuid, name)) { + this.name = name; + return true; } + return false; } - public int getCompletedBuilds() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT completed_plots FROM plotsystem_builders WHERE uuid = ?") - .setValue(getUUID().toString()).executeQuery()) { - - if (rs.next()) { - int i = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return i; - } - - DatabaseConnection.closeResultSet(rs); - return 0; - } + public int getScore() { + return score; } - public Slot getFreeSlot() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT first_slot, second_slot, third_slot FROM plotsystem_builders WHERE uuid = ?") - .setValue(getUUID().toString()).executeQuery()) { - - if (rs.next()) { - for (int i = 1; i <= 3; i++) { - if (rs.getString(i) == null) { - DatabaseConnection.closeResultSet(rs); - return Slot.values()[i - 1]; - } - } - } - - DatabaseConnection.closeResultSet(rs); - return null; - } - } - - public Plot getPlot(Slot slot) throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT " + slot.name().toLowerCase() + " FROM plotsystem_builders WHERE uuid = ?") - .setValue(getUUID().toString()).executeQuery()) { - - int plotID = -1; - if (rs.next()) plotID = rs.getInt(1); - - boolean boo = rs.wasNull(); - DatabaseConnection.closeResultSet(rs); - - return boo ? null : new Plot(plotID); + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public boolean addScore(int score) { + if (DataProvider.BUILDER.addScore(this.uuid, score)) { + this.score = this.score + score; + return true; } + return false; } - public ItemStack getPlotMenuItem(Plot plot, int slotIndex, Player langPlayer) throws SQLException { - String nameText = LangUtil.getInstance().get(getPlayer(), LangPaths.MenuTitle.SLOT).toUpperCase() + " " + (slotIndex + 1); - TextComponent statusComp = text(LangUtil.getInstance().get(langPlayer, LangPaths.Plot.STATUS) + ": ", GRAY); - TextComponent slotDescriptionComp = text(LangUtil.getInstance().get(langPlayer, LangPaths.MenuDescription.SLOT), GRAY); - - Material itemMaterial = Material.MAP; - ArrayList lore = new LoreBuilder() - .addLines(slotDescriptionComp, - empty(), - statusComp.append(text("Unassigned", WHITE))) - .build(); - - if (plot != null) { - itemMaterial = Material.FILLED_MAP; - String plotIdText = LangUtil.getInstance().get(langPlayer, LangPaths.Plot.ID); - String plotCityText = LangUtil.getInstance().get(langPlayer, LangPaths.Plot.CITY); - String plotDifficultyText = LangUtil.getInstance().get(langPlayer, LangPaths.Plot.DIFFICULTY); - String plotStatusText = plot.getStatus().name(); - lore = new LoreBuilder() - .addLines(text(plotIdText + ": ", GRAY).append(text(plot.getID(), WHITE)), - text(plotCityText + ": ", GRAY).append(text(plot.getCity().getName(), WHITE)), - text(plotDifficultyText + ": ", GRAY).append(text(plot.getDifficulty().name().charAt(0) + plot.getDifficulty().name().substring(1).toLowerCase(), WHITE)), - empty(), - statusComp.append(text(plotStatusText.substring(0, 1).toUpperCase() + plotStatusText.substring(1), WHITE))) - .build(); - } - - return new ItemBuilder(itemMaterial, 1 + slotIndex) - .setName(text(nameText, NamedTextColor.GOLD).decoration(TextDecoration.BOLD, true)) - .setLore(lore) - .build(); - } - - public void addScore(int score) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_builders SET score = ? WHERE uuid = ?") - .setValue(getScore() + score).setValue(getUUID().toString()) - .executeUpdate(); - - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> DecentHologramDisplay.activeDisplays.stream() - .filter(leaderboard -> leaderboard instanceof ScoreLeaderboard).findFirst().ifPresent(DecentHologramDisplay::reloadAll)); - } - - public void addCompletedBuild(int amount) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_builders SET completed_plots = ? WHERE uuid = ?") - .setValue(getCompletedBuilds() + amount).setValue(getUUID().toString()) - .executeUpdate(); - - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> DecentHologramDisplay.activeDisplays.stream() - .filter(leaderboard -> leaderboard instanceof PlotsLeaderboard).findFirst().ifPresent(DecentHologramDisplay::reloadAll)); - } - - public void setPlot(int plotID, Slot slot) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_builders SET " + slot.name().toLowerCase() + " = ? WHERE uuid = ?") - .setValue(plotID).setValue(getUUID().toString()) - .executeUpdate(); - } - - public void removePlot(Slot slot) throws SQLException { - if (slot != null) { // If not null, plot is already removed from player slot - DatabaseConnection.createStatement("UPDATE plotsystem_builders SET " + slot.name().toLowerCase() + " = DEFAULT(first_slot) WHERE uuid = ?") - .setValue(getUUID().toString()) - .executeUpdate(); - } - } - - public static Builder getBuilderByName(String name) throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT uuid FROM plotsystem_builders WHERE name = ?") - .setValue(name).executeQuery()) { - - if (rs.next()) { - String s = rs.getString(1); - DatabaseConnection.closeResultSet(rs); - return Builder.byUUID(UUID.fromString(s)); - } - - DatabaseConnection.closeResultSet(rs); - return null; + public Plot getSlot(Slot slot) { + if (slot == Slot.FIRST && firstSlot != -1) { + return DataProvider.PLOT.getPlotById(firstSlot); + } else if (slot == Slot.SECOND && secondSlot != -1) { + return DataProvider.PLOT.getPlotById(secondSlot); + } else if (slot == Slot.THIRD && thirdSlot != -1) { + return DataProvider.PLOT.getPlotById(thirdSlot); } + return null; } - private static String getBuildersByScoreQuery(ScoreLeaderboard.LeaderboardTimeframe sortBy, int limit) { - String minimumDate = null; - switch (sortBy) { - case DAILY: - minimumDate = "(NOW() - INTERVAL 1 DAY)"; - break; - case WEEKLY: - minimumDate = "(NOW() - INTERVAL 1 WEEK)"; - break; - case MONTHLY: - minimumDate = "(NOW() - INTERVAL 1 MONTH)"; - break; - case YEARLY: - minimumDate = "(NOW() - INTERVAL 1 YEAR)"; - break; - default: - // no limits - break; - } - - // get plot id, owner username, owner uuid, score & date - // sort by score & limit (if set above) by timeframe - return "SELECT plots.id, builders.name, plots.owner_uuid, SUM(plots.score) AS score, reviews.review_date FROM plotsystem_plots AS plots\n" + - "INNER JOIN plotsystem_reviews AS reviews ON plots.review_id = reviews.id\n" + - "INNER JOIN plotsystem_builders AS builders ON builders.uuid = plots.owner_uuid\n" + - (minimumDate != null - ? "WHERE reviews.review_date BETWEEN " + minimumDate + " AND NOW()\n" - : "") + - "GROUP BY plots.owner_uuid \n" + - "ORDER BY score DESC, builders.name\n" + - (limit > 0 ? "LIMIT " + limit : ""); + public Slot getSlot(Plot plot) { + return DataProvider.BUILDER.getSlot(this.uuid, plot.getId()); } - public static int getBuilderScore(UUID uuid, ScoreLeaderboard.LeaderboardTimeframe sortBy) throws SQLException { - String query = getBuildersByScoreQuery(sortBy, 0); - - try (ResultSet rs = DatabaseConnection.createStatement(query).executeQuery()) { - boolean found = false; - int score = 0; - while (rs.next() && !found) { - if (rs.getString(3).equals(uuid.toString())) { - found = true; - score = rs.getInt(4); - } + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public boolean setSlot(Slot slot, int plotId) { + if (DataProvider.BUILDER.setSlot(this.uuid, plotId, slot)) { + switch (slot) { + case FIRST -> firstSlot = plotId; + case SECOND -> secondSlot = plotId; + default -> thirdSlot = plotId; } - - if (!found) score = -1; - - DatabaseConnection.closeResultSet(rs); - return score; + return true; } + return false; } - public static int getBuilderScorePosition(UUID uuid, ScoreLeaderboard.LeaderboardTimeframe sortBy) throws SQLException { - String query = getBuildersByScoreQuery(sortBy, 0); - - try (ResultSet rs = DatabaseConnection.createStatement(query).executeQuery()) { - boolean found = false; - int position = 0; - while (rs.next() && !found) { - position++; - if (rs.getString(3).equals(uuid.toString())) { - found = true; - } - } - - if (!found) position = -1; - - DatabaseConnection.closeResultSet(rs); - return position; - } + public PlotType getPlotType() { + return PlotType.byId(plotType); } - public static int getBuildersInSort(ScoreLeaderboard.LeaderboardTimeframe sortBy) throws SQLException { - String query = "SELECT COUNT(*) FROM (" + getBuildersByScoreQuery(sortBy, 0) + ") results"; - - try (ResultSet rs = DatabaseConnection.createStatement(query).executeQuery()) { - rs.next(); - int position = rs.getInt(1); - - DatabaseConnection.closeResultSet(rs); - return position; + public boolean setPlotType(PlotType plotType) { + if (DataProvider.BUILDER.setPlotType(this.uuid, plotType.getId())) { + this.plotType = plotType.getId(); + return true; } + return false; } - public static class DatabaseEntry { - private final K key; - private final V value; - - DatabaseEntry(K k, V v) { - this.key = k; - this.value = v; - } - - public K getKey() { - return key; - } - - public V getValue() { - return value; - } + public Player getPlayer() { + return Bukkit.getPlayer(uuid); } - public static List> getBuildersByScore(ScoreLeaderboard.LeaderboardTimeframe sortBy) throws SQLException { - String query = getBuildersByScoreQuery(sortBy, 10); - - try (ResultSet rs = DatabaseConnection.createStatement(query).executeQuery()) { - ArrayList> lines = new ArrayList<>(); - - while (rs.next()) { - lines.add(new DatabaseEntry<>(rs.getString(2), rs.getInt(4))); - } - - DatabaseConnection.closeResultSet(rs); - return lines; - } + public boolean isOnline() { + return getPlayer() != null; } - public static List> getBuildersByCompletedBuilds(int limit) throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT name, completed_plots FROM plotsystem_builders ORDER BY completed_plots DESC LIMIT ?") - .setValue(limit).executeQuery()) { - - ArrayList> results = new ArrayList<>(); - while (rs.next()) { - results.add(new DatabaseEntry<>(rs.getString(1), rs.getInt(2))); - } - - DatabaseConnection.closeResultSet(rs); - return results; - } + public int getCompletedBuildsCount() { + return DataProvider.BUILDER.getCompletedBuildsCount(uuid); } - public Slot getSlot(Plot plot) throws SQLException { - for (Slot slot : Slot.values()) { - Plot slotPlot = getPlot(slot); - if (slotPlot != null && slotPlot.getID() == plot.getID()) { - return slot; - } - } - return null; + public Slot getFreeSlot() { + return DataProvider.BUILDER.getFreeSlot(uuid); } - public PlotType getPlotTypeSetting() { - if (plotType != null) - return plotType; - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT setting_plot_type FROM plotsystem_builders WHERE uuid = ?") - .setValue(getUUID().toString()).executeQuery()) { - - if (rs.next()) { - int id = rs.getInt(1); - this.plotType = PlotType.byId(id); - DatabaseConnection.closeResultSet(rs); - - return plotType; - } - DatabaseConnection.closeResultSet(rs); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while getting language setting from database"), ex); + public Slot getSlotByPlotId(int plotId) { + if (firstSlot == plotId) { + return Slot.FIRST; + } else if (secondSlot == plotId) { + return Slot.SECOND; + } else if (thirdSlot == plotId) { + return Slot.THIRD; } return null; } - public void setPlotTypeSetting(PlotType plotType) { - try { - if (plotType == null) { - DatabaseConnection.createStatement("UPDATE plotsystem_builders SET setting_plot_type = DEFAULT(setting_plot_type) WHERE uuid = ?") - .setValue(getUUID().toString()).executeUpdate(); - } else { - DatabaseConnection.createStatement("UPDATE plotsystem_builders SET setting_plot_type = ? WHERE uuid = ?") - .setValue(plotType.getId()).setValue(getUUID().toString()) - .executeUpdate(); - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while getting language setting from database"), ex); - } - - this.plotType = plotType; - } - - public Reviewer getAsReviewer() throws SQLException { - return new Reviewer(getUUID()); - } - - public boolean isReviewer() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT COUNT(builder_uuid) FROM plotsystem_builder_is_reviewer WHERE builder_uuid = ?") - .setValue(getUUID().toString()).executeQuery()) { - - int count = 0; - if (rs.next()) count = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return count > 0; - } + public static Builder byUUID(UUID uuid) { + return DataProvider.BUILDER.getBuilderByUUID(uuid); } - public static class Reviewer { - private final List buildTeams; - - public Reviewer(UUID reviewerUUID) throws SQLException { - this.buildTeams = BuildTeam.getBuildTeamsByReviewer(reviewerUUID); - } - - public List getCountries() { - Set countries = new HashSet<>(); - buildTeams.forEach(b -> { - try { - countries.addAll(b.getCountries().stream().map(Country::getID).collect(Collectors.toList())); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - }); - - return countries.stream().map(c -> { - try { - return new Country(c); - } catch (SQLException ex) {PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex);} - return null; - }).collect(Collectors.toList()); - } + public static Builder byName(String name) { + return DataProvider.BUILDER.getBuilderByName(name); } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/CityProject.java b/src/main/java/com/alpsbte/plotsystem/core/system/CityProject.java index f322f23c2..4bde770d1 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/CityProject.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/CityProject.java @@ -1,33 +1,8 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.PlotDifficulty; @@ -35,82 +10,118 @@ import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import com.alpsbte.plotsystem.utils.items.MenuItems; +import net.kyori.adventure.text.TextComponent; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import org.jetbrains.annotations.NotNull; -import java.sql.ResultSet; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutionException; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class CityProject { + private final String id; + private final String countryCode; + private String serverName; + private boolean isVisible; + private int buildTeamId; + + public CityProject(String id, String countryCode, String serverName, boolean isVisible, int buildTeamId) { + this.id = id; + this.countryCode = countryCode; + this.serverName = serverName; + this.isVisible = isVisible; + this.buildTeamId = buildTeamId; + } - private final int ID; - private int countryID; + public String getId() { + return id; + } - private String name; - private String description; - private boolean visible; + public Country getCountry() { + // city project objects will never be created with an id of a country that does not exist as this would throw a sql exception first + return DataProvider.COUNTRY.getCountryByCode(countryCode).orElseThrow(); + } - public CityProject(int ID) throws SQLException { - this.ID = ID; + public String getServerName() { + return serverName; + } - try (ResultSet rs = DatabaseConnection.createStatement("SELECT country_id, name, description, visible FROM plotsystem_city_projects WHERE id = ?") - .setValue(this.ID).executeQuery()) { + public boolean setServer(String serverName) { + if (DataProvider.CITY_PROJECT.setServer(id, serverName)) { + this.serverName = serverName; + return true; + } + return false; + } - if (rs.next()) { - this.countryID = rs.getInt(1); - this.name = rs.getString(2); - this.description = rs.getString(3); - this.visible = rs.getInt(4) == 1; - } + public boolean isVisible() { + return isVisible; + } - DatabaseConnection.closeResultSet(rs); + public boolean setVisible(boolean isVisible) { + if (DataProvider.CITY_PROJECT.setVisibility(id, isVisible)) { + this.isVisible = isVisible; + return true; } + return false; } - public int getID() { - return ID; + public String getName(Player player) { + return LangUtil.getInstance().get(player, LangPaths.Database.CITY_PROJECT + "." + id + ".name"); } - public Country getCountry() throws SQLException { - return new Country(countryID); + public String getDescription(Player player) { + return LangUtil.getInstance().get(player, LangPaths.Database.CITY_PROJECT + "." + id + ".description"); } - public String getName() { - return name; + public BuildTeam getBuildTeam() { + return DataProvider.BUILD_TEAM.getBuildTeam(buildTeamId).orElseThrow(); } - public String getDescription() { - return description; + public boolean setBuildTeam(int buildTeamId) { + if (DataProvider.CITY_PROJECT.setBuildTeam(id, buildTeamId)) { + this.buildTeamId = buildTeamId; + return true; + } + return false; } - public boolean isVisible() { - return visible; + public List getDescriptionComponents(Player player) { + ArrayList descriptionLines = new ArrayList<>(); + for (String line : getDescription(player).split("%newline%")) descriptionLines.add(text(line, GRAY)); + return descriptionLines; } - public ItemStack getItem(Player player, PlotDifficulty selectedPlotDifficulty) throws SQLException { - ItemStack cpItem = getCountry().getHead(); + public ItemStack getItem(Player player, PlotDifficulty selectedPlotDifficulty) { + ItemStack cpItem = getCountry().getCountryItem(); try { - PlotDifficulty cpPlotDifficulty = selectedPlotDifficulty != null ? - selectedPlotDifficulty : Plot.getPlotDifficultyForBuilder(getID(), Builder.byUUID(player.getUniqueId())).get(); - - int plotsOpen = Plot.getPlots(getID(), Status.unclaimed).size(); - int plotsInProgress = Plot.getPlots(getID(), Status.unfinished, Status.unreviewed).size(); - int plotsCompleted = Plot.getPlots(getID(), Status.completed).size(); - int plotsUnclaimed = cpPlotDifficulty != null ? Plot.getPlots(getID(), cpPlotDifficulty, Status.unclaimed).size() : 0; - int plotsOpenForPlayer = cpPlotDifficulty != null && plotsUnclaimed != 0 ? getOpenPlotsForPlayer(getID(), cpPlotDifficulty) : 0; + PlotDifficulty plotDifficulty = selectedPlotDifficulty != null ? + selectedPlotDifficulty : Plot.getPlotDifficultyForBuilder(this, Builder.byUUID(player.getUniqueId())).get(); + + int plotsOpen = DataProvider.PLOT.getPlots(this, Status.unclaimed).size(); + int plotsInProgress = DataProvider.PLOT.getPlots(this, Status.unfinished, Status.unreviewed).size(); + int plotsCompleted = DataProvider.PLOT.getPlots(this, Status.completed).size(); + int plotsUnclaimed = plotDifficulty != null + ? DataProvider.PLOT.getPlots(this, plotDifficulty, Status.unclaimed).size() + : 0; + int plotsOpenForPlayer = plotDifficulty != null && plotsUnclaimed != 0 + ? DataProvider.PLOT.getPlots(this, plotDifficulty, Status.unclaimed).size() + : 0; return new ItemBuilder(cpItem) - .setName(text(getName(), AQUA).decoration(BOLD, true)) + .setName(text(getName(player), AQUA).decoration(BOLD, true)) .setLore(new LoreBuilder() - .addLines(true, getDescription()) + .addLines(getDescriptionComponents(player)) .emptyLine() .addLine(text(plotsOpen, GOLD) .append(text(" " + LangUtil.getInstance().get(player, LangPaths.CityProject.PROJECT_OPEN) + " ", GRAY)) @@ -123,75 +134,14 @@ public ItemStack getItem(Player player, PlotDifficulty selectedPlotDifficulty) t .append(text(" " + LangUtil.getInstance().get(player, LangPaths.CityProject.PROJECT_COMPLETED), GRAY))) .emptyLine() .addLine(plotsUnclaimed != 0 - ? Utils.ItemUtils.getFormattedDifficulty(cpPlotDifficulty) + ? Utils.ItemUtils.getFormattedDifficulty(plotDifficulty, player) : text(LangUtil.getInstance().get(player, LangPaths.CityProject.PROJECT_NO_PLOTS_AVAILABLE), WHITE).decoration(BOLD, true)) .build()) .build(); - } catch (SQLException | ExecutionException | InterruptedException ex) { + } catch (ExecutionException | InterruptedException ex) { Utils.logSqlException(ex); Thread.currentThread().interrupt(); return MenuItems.errorItem(player); } } - - public static @NotNull List getCityProjects(Country country, boolean onlyVisible) { - // if country is not null, only get country's city projects, otherwise load all - DatabaseConnection.StatementBuilder statement = DatabaseConnection.createStatement("SELECT id FROM plotsystem_city_projects " + (country == null ? "" : "WHERE country_id = ?") + " ORDER BY country_id"); - if (country != null) statement.setValue(country.getID()); - - try (ResultSet rs = statement.executeQuery()) { - List cityProjects = new ArrayList<>(); - while (rs.next()) { - CityProject city = new CityProject(rs.getInt(1)); - if (city.isVisible() || !onlyVisible) cityProjects.add(city); - } - - DatabaseConnection.closeResultSet(rs); - return cityProjects; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - return new ArrayList<>(); - } - - public int getOpenPlotsForPlayer(int plotID, PlotDifficulty plotDifficulty) throws SQLException { - return Plot.getPlots(plotID, plotDifficulty, Status.unclaimed).size(); - } - - - public static @NotNull List getCityProjects(boolean onlyVisible) { - return getCityProjects(null, onlyVisible); - } - - public static void addCityProject(@NotNull Country country, String name) throws SQLException { - DatabaseConnection.createStatement("INSERT INTO plotsystem_city_projects (id, name, country_id, description, visible) VALUES (?, ?, ?, ?, ?)") - .setValue(DatabaseConnection.getTableID("plotsystem_city_projects")) - .setValue(name) - .setValue(country.getID()) - .setValue("") - .setValue(true).executeUpdate(); - } - - public static void removeCityProject(int id) throws SQLException { - DatabaseConnection.createStatement("DELETE FROM plotsystem_city_projects WHERE id = ?") - .setValue(id).executeUpdate(); - } - - public static void setCityProjectName(int id, String newName) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_city_projects SET name = ? WHERE id = ?") - .setValue(newName) - .setValue(id).executeUpdate(); - } - - public static void setCityProjectDescription(int id, String description) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_city_projects SET description = ? WHERE id = ?") - .setValue(description) - .setValue(id).executeUpdate(); - } - - public static void setCityProjectVisibility(int id, boolean isEnabled) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_city_projects SET visible = ? WHERE id = ?") - .setValue(isEnabled ? 1 : 0) - .setValue(id).executeUpdate(); - } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/Country.java b/src/main/java/com/alpsbte/plotsystem/core/system/Country.java index 4a4b10767..ca7717860 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/Country.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/Country.java @@ -1,156 +1,54 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system; -import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; +import com.alpsbte.alpslib.utils.item.ItemUtils; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.utils.enums.Continent; +import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; import java.util.List; -import static net.kyori.adventure.text.Component.text; - public class Country { - private final int ID; - private int serverID; - - private String name; - private String headID; - - private String continent; - - public Country(int ID) throws SQLException { - this.ID = ID; - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT server_id, name, head_id, continent FROM plotsystem_countries WHERE id = ?") - .setValue(this.ID).executeQuery()) { + private final String code; - if (rs.next()) { - this.serverID = rs.getInt(1); - this.name = rs.getString(2); - this.headID = rs.getString(3); - this.continent = rs.getString(4); - } + private String material; + private String customModelData; - DatabaseConnection.closeResultSet(rs); - } - } - - public int getID() { - return ID; - } + private final Continent continent; - public Server getServer() throws SQLException { - return new Server(serverID); + public Country(String code, Continent continent, String material, String customModelData) { + this.code = code; + this.continent = continent; + this.material = material; + this.customModelData = customModelData; } - public String getName() { - return name; - } + public String getCode() {return code;} - public ItemStack getHead() { - return AlpsHeadUtils.getCustomHead(headID); - } + public Continent getContinent() {return continent;} - /** - * Get city projects that are inside this country - *

- * Might be a good idea to put this in CityProject but could work in both classes - * - * @return CityProjects inside this country - */ public List getCityProjects() { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_city_projects WHERE country_id = ?").setValue(getID()).executeQuery()) { - List cityProjects = new ArrayList<>(); - while (rs.next()) { - cityProjects.add(new CityProject(rs.getInt(1))); - } - - DatabaseConnection.closeResultSet(rs); - return cityProjects; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - return new ArrayList<>(); + return DataProvider.CITY_PROJECT.getByCountryCode(code, true); } - public Continent getContinent() { - return Continent.fromDatabase(continent); + public String getName(Player player) { + return LangUtil.getInstance().get(player, LangPaths.Database.COUNTRY + "." + code + ".name"); } - public static List getCountries() { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_countries ORDER BY server_id").executeQuery()) { - List countries = new ArrayList<>(); - while (rs.next()) { - countries.add(new Country(rs.getInt(1))); - } - - DatabaseConnection.closeResultSet(rs); - return countries; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + public boolean setMaterialAndModelData(String material, @Nullable String customModelData) { + if (DataProvider.COUNTRY.setMaterialAndCustomModelData(code, material, customModelData)) { + this.material = material; + this.customModelData = customModelData; + return true; } - return new ArrayList<>(); - } - - public static List getCountries(Continent continent) { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_countries WHERE continent = ? ORDER BY server_id").setValue(continent.databaseEnum).executeQuery()) { - List countries = new ArrayList<>(); - while (rs.next()) { - countries.add(new Country(rs.getInt(1))); - } - - DatabaseConnection.closeResultSet(rs); - return countries; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - return new ArrayList<>(); - } - - public static void addCountry(int serverID, String name, Continent continent) throws SQLException { - DatabaseConnection.createStatement("INSERT INTO plotsystem_countries (id, name, server_id, continent) VALUES (?, ?, ?, ?)") - .setValue(DatabaseConnection.getTableID("plotsystem_countries")) - .setValue(name) - .setValue(serverID).setValue(continent.databaseEnum).executeUpdate(); - } - - public static void removeCountry(int countryID) throws SQLException { - DatabaseConnection.createStatement("DELETE FROM plotsystem_countries WHERE id = ?") - .setValue(countryID).executeUpdate(); + return false; } - public static void setHeadID(int countryID, int headID) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_countries SET head_id = ? WHERE id = ?") - .setValue(headID) - .setValue(countryID).executeUpdate(); + public ItemStack getCountryItem() { + return ItemUtils.getConfiguredItem(material, customModelData); } } \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/Difficulty.java b/src/main/java/com/alpsbte/plotsystem/core/system/Difficulty.java index 31cb81dd8..65e9a2939 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/Difficulty.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/Difficulty.java @@ -1,67 +1,33 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system; -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.utils.enums.PlotDifficulty; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import static net.kyori.adventure.text.Component.text; +import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import org.bukkit.entity.Player; public class Difficulty { - private final int ID; + private final String ID; + private final PlotDifficulty difficulty; - private PlotDifficulty difficulty; private double multiplier; private int scoreRequirement; - public Difficulty(int ID) throws SQLException { - this.ID = ID; - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT name, multiplier, score_requirment FROM plotsystem_difficulties WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - this.difficulty = PlotDifficulty.valueOf(rs.getString(1)); - this.multiplier = rs.getDouble(2); - this.scoreRequirement = rs.getInt(3); - } - - DatabaseConnection.closeResultSet(rs); - } + public Difficulty(PlotDifficulty difficulty, String id, double multiplier, int scoreRequirement) { + this.difficulty = difficulty; + this.ID = id; + this.multiplier = multiplier; + this.scoreRequirement = scoreRequirement; } - public int getID() { + public String getID() { return ID; } + public String getName(Player player) { + return LangUtil.getInstance().get(player, LangPaths.Database.DIFFICULTY + "." + ID + ".name"); + } + public PlotDifficulty getDifficulty() { return difficulty; } @@ -74,29 +40,19 @@ public int getScoreRequirement() { return scoreRequirement; } - public static List getDifficulties() { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_difficulties").executeQuery()) { - List difficulties = new ArrayList<>(); - while (rs.next()) { - difficulties.add(new Difficulty(rs.getInt(1))); - } - - DatabaseConnection.closeResultSet(rs); - - return difficulties; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); + public boolean setMultiplier(double multiplier) { + if (DataProvider.DIFFICULTY.setMultiplier(ID, multiplier)) { + this.multiplier = multiplier; + return true; } - return new ArrayList<>(); + return false; } - public static void setMultiplier(int difficultyID, double multiplier) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_difficulties SET multiplier = ? WHERE id = ?") - .setValue(multiplier).setValue(difficultyID).executeUpdate(); - } - - public static void setScoreRequirement(int difficultyID, int scoreRequirement) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_difficulties SET score_requirment = ? WHERE id = ?") - .setValue(scoreRequirement).setValue(difficultyID).executeUpdate(); + public boolean setScoreRequirement(int scoreRequirement) { + if (DataProvider.DIFFICULTY.setScoreRequirement(ID, scoreRequirement)) { + this.scoreRequirement = scoreRequirement; + return true; + } + return false; } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/FTPConfiguration.java b/src/main/java/com/alpsbte/plotsystem/core/system/FTPConfiguration.java deleted file mode 100644 index 3877fcb55..000000000 --- a/src/main/java/com/alpsbte/plotsystem/core/system/FTPConfiguration.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.core.system; - -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; - -import java.io.File; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import static net.kyori.adventure.text.Component.text; - -public class FTPConfiguration { - private final int ID; - - private String schematicPath; - private String address; - private int port; - private boolean isSFTP; - private String username; - private String password; - - public FTPConfiguration(int ID) throws SQLException { - this.ID = ID; - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT schematics_path, address, port, isSFTP, username, password FROM plotsystem_ftp_configurations WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - this.schematicPath = rs.getString(1); - this.address = rs.getString(2); - this.port = rs.getInt(3); - this.isSFTP = rs.getBoolean(4); - this.username = rs.getString(5); - this.password = rs.getString(6); - } - - DatabaseConnection.closeResultSet(rs); - } - } - - public int getID() { - return ID; - } - - public String getSchematicPath() { - if (schematicPath != null) { - schematicPath = !schematicPath.startsWith("/") ? File.separator + schematicPath : schematicPath; - schematicPath = schematicPath.endsWith("/") ? schematicPath.substring(0, schematicPath.length() - 1) : schematicPath; - } - return schematicPath; - } - - public String getAddress() { - return address; - } - - public int getPort() { - return port; - } - - public boolean isSFTP() { - return isSFTP; - } - - public String getUsername() { - return username; - } - - public String getPassword() { - return password; - } - - public static List getFTPConfigurations() { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_ftp_configurations").executeQuery()) { - List ftpConfigurations = new ArrayList<>(); - while (rs.next()) { - ftpConfigurations.add(new FTPConfiguration(rs.getInt(1))); - } - - DatabaseConnection.closeResultSet(rs); - - return ftpConfigurations; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - return new ArrayList<>(); - } - - public static void addFTPConfiguration(String address, int port, boolean isSFTP, String username, String password) throws SQLException { - DatabaseConnection.createStatement("INSERT INTO plotsystem_ftp_configurations (id, address, port, isSFTP, username, password) VALUES (?, ?, ?, ?, ?, ?)") - .setValue(DatabaseConnection.getTableID("plotsystem_ftp_configurations")) - .setValue(address).setValue(port).setValue(isSFTP ? 1 : 0).setValue(username).setValue(password).executeUpdate(); - } - - public static void removeFTPConfiguration(int ID) throws SQLException { - if (getFTPConfigurations().stream().anyMatch(ftp -> ftp.getID() == ID)) { - DatabaseConnection.createStatement("DELETE FROM plotsystem_ftp_configurations WHERE id = ?") - .setValue(ID).executeUpdate(); - } - } - - public static void setSchematicPath(int ID, String path) throws SQLException { - if (getFTPConfigurations().stream().anyMatch(ftp -> ftp.getID() == ID)) { - DatabaseConnection.createStatement("UPDATE plotsystem_ftp_configurations SET schematics_path = ? WHERE id = ?") - .setValue(path).setValue(ID).executeUpdate(); - } - } -} diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/Payout.java b/src/main/java/com/alpsbte/plotsystem/core/system/Payout.java deleted file mode 100644 index dcf183ca9..000000000 --- a/src/main/java/com/alpsbte/plotsystem/core/system/Payout.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021-2022, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.core.system; - -import com.alpsbte.plotsystem.core.database.DatabaseConnection; -import com.alpsbte.plotsystem.core.holograms.ScoreLeaderboard; - -import java.sql.ResultSet; -import java.sql.SQLException; - -public class Payout { - private final int id; - private final ScoreLeaderboard.LeaderboardTimeframe timeframe; - private final int position; - private final String payoutAmount; - - private Payout(int id, ScoreLeaderboard.LeaderboardTimeframe timeframe, int position, String payoutAmount) { - this.id = id; - this.timeframe = timeframe; - this.position = position; - this.payoutAmount = payoutAmount; - } - - public static Payout getPayout(ScoreLeaderboard.LeaderboardTimeframe timeframe, int position) throws SQLException { - if (timeframe == ScoreLeaderboard.LeaderboardTimeframe.LIFETIME) { - throw new IllegalArgumentException("Invalid option LIFETIME"); - } - if (position < 1 || position > 10) { - throw new IllegalArgumentException("Illegal position " + position); - } - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT id, timeframe, position, payout_amount FROM plotsystem_payouts WHERE timeframe = ? AND position = ?") - .setValue(timeframe.name()).setValue(position).executeQuery()) { - Payout instance = null; - - if (rs.next()) { - instance = new Payout(rs.getInt(1), ScoreLeaderboard.LeaderboardTimeframe.valueOf(rs.getString(2)), rs.getInt(3), rs.getString(4)); - } - - DatabaseConnection.closeResultSet(rs); - return instance; - } - } - - public int getId() { - return id; - } - - public ScoreLeaderboard.LeaderboardTimeframe getTimeframe() { - return timeframe; - } - - public int getPosition() { - return position; - } - - public String getPayoutAmount() { - return payoutAmount; - } -} \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/Review.java b/src/main/java/com/alpsbte/plotsystem/core/system/Review.java deleted file mode 100644 index 14ac2d589..000000000 --- a/src/main/java/com/alpsbte/plotsystem/core/system/Review.java +++ /dev/null @@ -1,257 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.core.system; - -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; -import com.alpsbte.plotsystem.core.system.plot.Plot; -import com.alpsbte.plotsystem.utils.enums.Category; -import com.alpsbte.plotsystem.utils.enums.Status; -import com.alpsbte.plotsystem.utils.io.FTPManager; -import org.bukkit.Bukkit; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Files; -import java.sql.Date; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.time.LocalDate; -import java.util.UUID; - -import static net.kyori.adventure.text.Component.text; - -public class Review { - private final int reviewID; - - public Review(int reviewID) { - this.reviewID = reviewID; - } - - public Review(int plotID, UUID reviewer, String rating) throws SQLException { - this.reviewID = DatabaseConnection.getTableID("plotsystem_reviews"); - - DatabaseConnection.createStatement("INSERT INTO plotsystem_reviews (id, reviewer_uuid, rating, review_date, feedback) VALUES (?, ?, ?, ?, ?)") - .setValue(this.reviewID) - .setValue(reviewer.toString()) - .setValue(rating) - .setValue(java.sql.Date.valueOf(java.time.LocalDate.now())) - .setValue("No Feedback") - .executeUpdate(); - - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET review_id = ? WHERE id = ?") - .setValue(this.reviewID) - .setValue(plotID) - .executeUpdate(); - } - - public int getReviewID() { - return reviewID; - } - - public int getPlotID() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_plots WHERE review_id = ?") - .setValue(this.reviewID).executeQuery()) { - - if (rs.next()) { - int i = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return i; - } - - DatabaseConnection.closeResultSet(rs); - return 0; - } - } - - public Builder getReviewer() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT reviewer_uuid FROM plotsystem_reviews WHERE id = ?") - .setValue(this.reviewID).executeQuery()) { - - if (rs.next()) { - String s = rs.getString(1); - DatabaseConnection.closeResultSet(rs); - return Builder.byUUID(UUID.fromString(s)); - } - - DatabaseConnection.closeResultSet(rs); - return null; - } - } - - public int getRating(Category category) throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT rating FROM plotsystem_reviews WHERE id = ?") - .setValue(this.reviewID).executeQuery()) { - - if (rs.next()) { - String[] scoreAsString = rs.getString("rating").split(","); - DatabaseConnection.closeResultSet(rs); - - switch (category) { - case ACCURACY: - return Integer.parseInt(scoreAsString[0]); - case BLOCKPALETTE: - return Integer.parseInt(scoreAsString[1]); - case DETAILING: - return Integer.parseInt(scoreAsString[2]); - case TECHNIQUE: - return Integer.parseInt(scoreAsString[3]); - case ALL: - return Integer.parseInt(scoreAsString[0]) + Integer.parseInt(scoreAsString[1]) + Integer.parseInt(scoreAsString[2]) + Integer.parseInt(scoreAsString[3]); - default: - return 0; - } - } - - DatabaseConnection.closeResultSet(rs); - return 0; - } - } - - public String getFeedback() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT feedback FROM plotsystem_reviews WHERE id = ?") - .setValue(this.reviewID).executeQuery()) { - - if (rs.next()) { - String s = rs.getString(1); - DatabaseConnection.closeResultSet(rs); - return s; - } - - DatabaseConnection.closeResultSet(rs); - return null; - } - } - - public Date getReviewDate() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT review_date FROM plotsystem_reviews WHERE id = ?") - .setValue(this.reviewID).executeQuery()) { - - if (rs.next()) { - Date d = rs.getDate(1); - DatabaseConnection.closeResultSet(rs); - return d; - } - - DatabaseConnection.closeResultSet(rs); - return null; - } - } - - public void setReviewer(UUID reviewer) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_reviews SET reviewer_uuid = ? WHERE id = ?") - .setValue(reviewer.toString()).setValue(this.reviewID).executeUpdate(); - } - - public void setRating(String ratingFormat) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_reviews SET rating = ? WHERE id = ?") - .setValue(ratingFormat).setValue(this.reviewID).executeUpdate(); - } - - public void setFeedback(String feedback) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_reviews SET feedback = ? WHERE id = ?") - .setValue(feedback).setValue(this.reviewID).executeUpdate(); - } - - public void setFeedbackSent(boolean isSent) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_reviews SET sent = ? WHERE id = ?") - .setValue(isSent ? 1 : 0).setValue(this.reviewID).executeUpdate(); - } - - public void setReviewDate() throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_reviews SET review_date = ? WHERE id = ?") - .setValue(Date.valueOf(LocalDate.now())).setValue(this.reviewID).executeUpdate(); - } - - public boolean isFeedbackSent() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT sent FROM plotsystem_reviews WHERE id = ?") - .setValue(this.reviewID).executeQuery()) { - - if (rs.next()) { - int i = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return i != 0; - } - - DatabaseConnection.closeResultSet(rs); - return false; - } - } - - public static void undoReview(Review review) { - Bukkit.getScheduler().runTaskAsynchronously(PlotSystem.getPlugin(), () -> { - try { - Plot plot = new Plot(review.getPlotID()); - - for (Builder member : plot.getPlotMembers()) { - member.addScore(-plot.getSharedScore()); - member.addCompletedBuild(-1); - - if (member.getFreeSlot() != null) { - member.setPlot(plot.getID(), member.getFreeSlot()); - } - } - - plot.getPlotOwner().addScore(-plot.getSharedScore()); - plot.getPlotOwner().addCompletedBuild(-1); - plot.setTotalScore(-1); - plot.setStatus(Status.unreviewed); - plot.setPasted(false); - - if (plot.getPlotOwner().getFreeSlot() != null) { - plot.getPlotOwner().setPlot(plot.getID(), plot.getPlotOwner().getFreeSlot()); - } - - int cityId = plot.getCity().getID(); - Server plotServer = plot.getCity().getCountry().getServer(); - boolean hasFTPConfiguration = plotServer.getFTPConfiguration() != null; - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { - plot.getWorld().loadWorld(); - - try { - Files.deleteIfExists(plot.getCompletedSchematic().toPath()); - - if (hasFTPConfiguration) { - FTPManager.deleteSchematic(FTPManager.getFTPUrl(plotServer, cityId), plot.getID() + ".schem"); - FTPManager.deleteSchematic(FTPManager.getFTPUrl(plotServer, cityId), plot.getID() + ".schematic"); - } - } catch (IOException | SQLException | URISyntaxException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while undoing review!"), ex); - } - - plot.getWorld().unloadWorld(true); - }); - - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET review_id = DEFAULT(review_id) WHERE id = ?") - .setValue(review.getPlotID()).executeUpdate(); - - DatabaseConnection.createStatement("DELETE FROM plotsystem_reviews WHERE id = ?") - .setValue(review.reviewID).executeUpdate(); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while undoing review!"), ex); - } - }); - } -} diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/Server.java b/src/main/java/com/alpsbte/plotsystem/core/system/Server.java deleted file mode 100644 index d45c10ce9..000000000 --- a/src/main/java/com/alpsbte/plotsystem/core/system/Server.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.core.system; - -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; - -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.List; - -import static net.kyori.adventure.text.Component.text; - -public class Server { - private final int ID; - private int ftpConfigurationID; - - private String name; - - public Server(int ID) throws SQLException { - this.ID = ID; - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT ftp_configuration_id, name FROM plotsystem_servers WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - this.ftpConfigurationID = rs.getInt(1); - if (rs.wasNull()) this.ftpConfigurationID = -1; - - this.name = rs.getString(2); - } - - DatabaseConnection.closeResultSet(rs); - } - } - - public int getID() { - return ID; - } - - public String getName() { - return name; - } - - public FTPConfiguration getFTPConfiguration() throws SQLException { - return ftpConfigurationID != -1 ? new FTPConfiguration(ftpConfigurationID) : null; - } - - public static List getServers() { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_servers").executeQuery()) { - List servers = new ArrayList<>(); - while (rs.next()) { - servers.add(new Server(rs.getInt(1))); - } - - DatabaseConnection.closeResultSet(rs); - - return servers; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - return new ArrayList<>(); - } - - public static Server addServer(String name) throws SQLException { - int id = DatabaseConnection.getTableID("plotsystem_servers"); - DatabaseConnection.createStatement("INSERT INTO plotsystem_servers (id, name) VALUES (?, ?)") - .setValue(id) - .setValue(name).executeUpdate(); - return new Server(id); - } - - public static void removeServer(int serverID) throws SQLException { - DatabaseConnection.createStatement("DELETE FROM plotsystem_servers WHERE id = ?") - .setValue(serverID).executeUpdate(); - } - - public static void setFTP(int serverID, int ftpID) throws SQLException { - if (ftpID != -1) { - DatabaseConnection.createStatement("UPDATE plotsystem_servers SET ftp_configuration_id = ? WHERE id = ?") - .setValue(ftpID) - .setValue(serverID).executeUpdate(); - } else { - DatabaseConnection.createStatement("UPDATE plotsystem_servers SET ftp_configuration_id = DEFAULT WHERE id = ?") - .setValue(serverID).executeUpdate(); - } - } -} diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/AbstractPlot.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/AbstractPlot.java index 9a68d350a..a88643c97 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/AbstractPlot.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/AbstractPlot.java @@ -1,138 +1,116 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021-2022, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot; import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.utils.PlotPermissions; import com.alpsbte.plotsystem.core.system.plot.utils.PlotType; -import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.conversion.CoordinateConversion; import com.alpsbte.plotsystem.utils.conversion.projection.OutOfProjectionBoundsException; import com.alpsbte.plotsystem.utils.enums.Status; -import com.fastasyncworldedit.core.FaweAPI; import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; -import com.sk89q.worldedit.regions.CuboidRegion; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.io.File; +import java.io.ByteArrayInputStream; import java.io.IOException; -import java.sql.SQLException; +import java.time.LocalDate; import java.util.ArrayList; -import java.util.Date; import java.util.List; +import java.util.UUID; import static net.kyori.adventure.text.Component.text; public abstract class AbstractPlot { - public static final double PLOT_VERSION = 3; + public static final double PLOT_VERSION = 4; + public static final ClipboardFormat CLIPBOARD_FORMAT = BuiltInClipboardFormat.FAST_V2; + public static final double LEGACY_VERSION_THRESHOLD = 3; + private final int id; - protected final int ID; protected Builder plotOwner; protected OnePlotWorld onePlotWorld; protected PlotPermissions plotPermissions; protected PlotType plotType; - protected double plotVersion = -1; + protected double plotVersion; protected List outline; protected List blockOutline; - public AbstractPlot(int id) { - this.ID = id; + protected AbstractPlot(int id, UUID plotOwnerUUID) { + this.id = id; + this.plotOwner = plotOwnerUUID != null ? DataProvider.BUILDER.getBuilderByUUID(plotOwnerUUID) : null; } /** * @return plot id */ - public int getID() { - return ID; + public int getId() { + return id; } /** * @return builder who has claimed the plot - * @throws SQLException SQL database exception */ - public abstract Builder getPlotOwner() throws SQLException; + public Builder getPlotOwner() { + return plotOwner; + } + + /** + * sets the plot owner of the current plot + * @param plotOwner uuid of player + * @return if true, the execution was successful + */ + public abstract boolean setPlotOwner(@Nullable Builder plotOwner); /** * @return plot world, can be one or city plot world */ - public abstract T getWorld() throws SQLException; + public abstract T getWorld(); /** * @return the outline of the plot which contains all corner points of the polygon */ - public abstract List getOutline() throws SQLException, IOException; + public abstract List getOutline(); /** * @return last date on which the plot owner teleported to the plot - * @throws SQLException SQL database exception */ - public abstract Date getLastActivity() throws SQLException; + public abstract LocalDate getLastActivity(); /** * Sets the last activity to the current date and time * * @param setNull if true, set last activity to null - * @throws SQLException SQL database exception */ - public abstract void setLastActivity(boolean setNull) throws SQLException; + public abstract boolean setLastActivity(boolean setNull); - public abstract Status getStatus() throws SQLException; + public abstract Status getStatus(); - public abstract void setStatus(@NotNull Status status) throws SQLException; + public abstract boolean setStatus(@NotNull Status status); /** * Returns the plot type the player has selected when creating the plot * * @return the plot type - * @throws SQLException SQL database exception */ - public abstract PlotType getPlotType() throws SQLException; + public abstract PlotType getPlotType(); public abstract double getVersion(); - protected abstract File getSchematicFile(String fileName); - /** * @return schematic file with outlines only */ - public abstract File getOutlinesSchematic(); - - /** - * @return schematic file with environment only - */ - public abstract File getEnvironmentSchematic(); - + public abstract byte[] getInitialSchematicBytes(); /** * Returns geographic coordinates in numeric format @@ -160,19 +138,23 @@ public String getGeoCoordinates() throws IOException { * @see com.alpsbte.plotsystem.utils.conversion.CoordinateConversion#convertFromGeo(double, double) */ public BlockVector3 getCoordinates() throws IOException { - Clipboard clipboard = FaweAPI.load(getOutlinesSchematic()); - if (clipboard != null) return clipboard.getOrigin(); + ByteArrayInputStream inputStream = new ByteArrayInputStream(getInitialSchematicBytes()); + try (ClipboardReader reader = CLIPBOARD_FORMAT.getReader(inputStream)) { + Clipboard clipboard = reader.read(); + if (clipboard != null) return clipboard.getOrigin(); + } return null; } public BlockVector3 getCenter() { - try { - Clipboard clipboard = FaweAPI.load(getOutlinesSchematic()); + ByteArrayInputStream inputStream = new ByteArrayInputStream(getInitialSchematicBytes()); + try (ClipboardReader reader = CLIPBOARD_FORMAT.getReader(inputStream)){ + Clipboard clipboard = reader.read(); if (clipboard != null) { Vector3 clipboardCenter = clipboard.getRegion().getCenter(); return BlockVector3.at(clipboardCenter.x(), this.getWorld().getPlotHeightCentered(), clipboardCenter.z()); } - } catch (IOException | SQLException ex) { + } catch (IOException ex) { PlotSystem.getPlugin().getComponentLogger().error(text("Failed to load schematic file to clipboard!"), ex); } return null; @@ -181,7 +163,7 @@ public BlockVector3 getCenter() { /** * @return plot permission manager to add or remove build rights */ - public PlotPermissions getPermissions() throws SQLException { + public PlotPermissions getPermissions() { if (plotPermissions == null) plotPermissions = new PlotPermissions(getWorld()); return plotPermissions; } @@ -198,18 +180,13 @@ public String getGoogleEarthLink() throws IOException { return "https://earth.google.com/web/@" + getGeoCoordinates() + ",0a,1000d,20y,-0h,0t,0r"; } - protected List getOutlinePoints(String outlinePoints) throws SQLException, IOException { + protected List getOutlinePoints(String outlinePoints) { List locations = new ArrayList<>(); - if (outlinePoints == null) { - CuboidRegion plotRegion = PlotUtils.getPlotAsRegion(this); - if (plotRegion != null) locations.addAll(plotRegion.polygonize(4)); - } else { - String[] list = outlinePoints.split("\\|"); - - for (String s : list) { - String[] locs = s.split(","); - locations.add(BlockVector2.at(Double.parseDouble(locs[0]), Double.parseDouble(locs[1]))); - } + String[] list = outlinePoints.split("\\|"); + + for (String s : list) { + String[] locs = s.split(","); + locations.add(BlockVector2.at(Double.parseDouble(locs[0]), Double.parseDouble(locs[1]))); } this.outline = locations; return locations; @@ -218,23 +195,23 @@ protected List getOutlinePoints(String outlinePoints) throws SQLEx /** * @return the outline of the polygon with one point per Block */ - public final List getBlockOutline() throws SQLException, IOException { + public final List getBlockOutline() { if (this.blockOutline != null) return this.blockOutline; List points = new ArrayList<>(); - List outline = getOutline(); + List correctOutline = getOutline(); - for (int i = 0; i < outline.size() - 1; i++) { - BlockVector2 b1 = outline.get(i); - BlockVector2 b2 = outline.get(i + 1); + for (int i = 0; i < correctOutline.size() - 1; i++) { + BlockVector2 b1 = correctOutline.get(i); + BlockVector2 b2 = correctOutline.get(i + 1); int distance = (int) b1.distance(b2); points.addAll(Utils.getLineBetweenPoints(b1, b2, distance)); } - BlockVector2 first = outline.get(0); - BlockVector2 last = outline.get(outline.size() - 1); + BlockVector2 first = correctOutline.getFirst(); + BlockVector2 last = correctOutline.getLast(); points.addAll(Utils.getLineBetweenPoints(last, first, (int) first.distance(last))); this.blockOutline = points; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/Plot.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/Plot.java index 2d4c298a7..eaee46977 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/Plot.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/Plot.java @@ -1,629 +1,223 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot; import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.CityProject; -import com.alpsbte.plotsystem.core.system.Country; -import com.alpsbte.plotsystem.core.system.Review; import com.alpsbte.plotsystem.core.system.plot.utils.PlotType; -import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; import com.alpsbte.plotsystem.core.system.plot.world.CityPlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; -import com.alpsbte.plotsystem.utils.Utils; +import com.alpsbte.plotsystem.core.system.review.PlotReview; import com.alpsbte.plotsystem.utils.enums.PlotDifficulty; import com.alpsbte.plotsystem.utils.enums.Slot; import com.alpsbte.plotsystem.utils.enums.Status; import com.alpsbte.plotsystem.utils.io.ConfigPaths; -import com.alpsbte.plotsystem.utils.io.FTPManager; import com.sk89q.worldedit.math.BlockVector2; -import com.sk89q.worldedit.math.BlockVector3; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.nio.file.Paths; -import java.sql.ResultSet; -import java.sql.SQLException; import java.time.LocalDate; -import java.util.ArrayList; -import java.util.Date; import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; -import java.util.stream.Collectors; - -import static net.kyori.adventure.text.Component.text; public class Plot extends AbstractPlot { - private CityProject city; + private final CityProject cityProject; + private final PlotDifficulty difficulty; + private Status status; + private final String outlineBounds; + private LocalDate lastActivity; + private final List members; + private CityPlotWorld cityPlotWorld; - public Plot(int id) { - super(id); + public Plot( + int id, CityProject cityProject, PlotDifficulty difficulty, UUID ownerUUID, Status status, + String outlineBounds, LocalDate lastActivity, double version, PlotType type, List members) { + super(id, ownerUUID); + this.cityProject = cityProject; + this.difficulty = difficulty; + this.status = status; + this.outlineBounds = outlineBounds; + this.lastActivity = lastActivity; + this.plotVersion = version; + this.plotType = type; + this.members = members; } - public CityProject getCity() throws SQLException { - if (this.city != null) - return this.city; - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT city_project_id FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - int i = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - CityProject cityProject = new CityProject(i); - - this.city = cityProject; - - return cityProject; - } - - DatabaseConnection.closeResultSet(rs); - return null; - } - } - - public PlotDifficulty getDifficulty() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT difficulty_id FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - int i = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return PlotDifficulty.values()[i - 1]; - } - - DatabaseConnection.closeResultSet(rs); - return null; - } + @Override + public Status getStatus() { + return status; } @Override - public Builder getPlotOwner() throws SQLException { - if (plotOwner != null) - return plotOwner; - - if (getStatus() != Status.unclaimed) { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT owner_uuid FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - String s = rs.getString(1); - DatabaseConnection.closeResultSet(rs); - - plotOwner = Builder.byUUID(UUID.fromString(s)); - - return plotOwner; - } - - DatabaseConnection.closeResultSet(rs); - } + public boolean setStatus(@NotNull Status status) { + if (DataProvider.PLOT.setStatus(getId(), status)) { + this.status = status; + return true; } - return null; + return false; } - public void setPlotOwner(String UUID) throws SQLException { - if (UUID == null) { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET owner_uuid = DEFAULT(owner_uuid) WHERE id = ?") - .setValue(this.ID).executeUpdate(); - } else { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET owner_uuid = ? WHERE id = ?") - .setValue(UUID).setValue(this.ID).executeUpdate(); - } - - plotOwner = null; + public CityProject getCityProject() { + return cityProject; } - public List getPlotMembers() throws SQLException { - List builders = new ArrayList<>(); - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT member_uuids FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - String members = rs.getString(1); - if (!rs.wasNull()) { - String[] uuidMembers = members.split(","); - - for (String uuid : uuidMembers) { - builders.add(Builder.byUUID(UUID.fromString(uuid))); - } - } - } - - DatabaseConnection.closeResultSet(rs); - } - return builders; + public PlotDifficulty getDifficulty() { + return difficulty; } - public void setPlotMembers(@NotNull List plotMembers) throws SQLException { - // Convert plot member list to string - String plotMemberAsString = plotMembers.stream().map(member -> member.getUUID().toString()).collect(Collectors.joining(",")); - - if (!plotMembers.isEmpty()) { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET member_uuids = ? WHERE id = ?") - .setValue(plotMemberAsString).setValue(this.ID).executeUpdate(); - } else { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET member_uuids = DEFAULT(member_uuids) WHERE id = ?") - .setValue(this.ID).executeUpdate(); + @Override + public boolean setPlotOwner(@Nullable Builder plotOwner) { + if (DataProvider.PLOT.setPlotOwner(getId(), plotOwner == null ? null : plotOwner.getUUID())) { + this.plotOwner = plotOwner; + return true; } + return false; } - @SuppressWarnings("unchecked") @Override - public T getWorld() { - try { - if (getVersion() <= 2 || getPlotType().hasOnePlotPerWorld()) { - if (onePlotWorld == null) onePlotWorld = new OnePlotWorld(this); - return (T) onePlotWorld; - } else { - if (cityPlotWorld == null) cityPlotWorld = new CityPlotWorld(this); - return (T) cityPlotWorld; - } - } catch (SQLException ex) {Utils.logSqlException(ex);} - return null; + public double getVersion() { + return plotVersion; } @Override - public List getOutline() throws SQLException, IOException { + public List getOutline() { if (outline != null) return this.outline; - try (ResultSet rs = DatabaseConnection.createStatement("SELECT outline FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - List pointVectors = new ArrayList<>(); - if (rs.next()) { - String points = rs.getString(1); - pointVectors = getOutlinePoints((rs.wasNull() || points.isEmpty() || getVersion() <= 2) ? null : points); - } - - DatabaseConnection.closeResultSet(rs); - return pointVectors; - } + List pointVectors; + pointVectors = getOutlinePoints(outlineBounds.isEmpty() ? "" : outlineBounds); + return pointVectors; } @Override - public Date getLastActivity() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT last_activity FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - Date d = rs.getDate(1); - DatabaseConnection.closeResultSet(rs); - return d; - } - - DatabaseConnection.closeResultSet(rs); - - return null; - } + public LocalDate getLastActivity() { + return lastActivity; } @Override - public void setLastActivity(boolean setNull) throws SQLException { - if (setNull) { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET last_activity = DEFAULT(last_activity) WHERE id = ?") - .setValue(this.ID).executeUpdate(); - } else { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET last_activity = ? WHERE id = ?") - .setValue(java.sql.Date.valueOf(LocalDate.now())).setValue(this.ID).executeUpdate(); + public boolean setLastActivity(boolean setNull) { + LocalDate activityDate = setNull ? null : LocalDate.now(); + if (DataProvider.PLOT.setLastActivity(getId(), activityDate)) { + this.lastActivity = activityDate; + return true; } + return false; } - @Override - public Status getStatus() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT status FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - String s = rs.getString(1); - DatabaseConnection.closeResultSet(rs); - return Status.valueOf(s); - } - - DatabaseConnection.closeResultSet(rs); - return null; - } + public List getPlotMembers() { + return members; } @Override - public void setStatus(@NotNull Status status) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET status = ? WHERE id = ?") - .setValue(status.name()).setValue(this.ID).executeUpdate(); - } - - public int getTotalScore() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT score FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - int score = rs.getInt(1); - if (!rs.wasNull()) { - DatabaseConnection.closeResultSet(rs); - return score; - } - } - - DatabaseConnection.closeResultSet(rs); - - return -1; - } - } - - public void setTotalScore(int score) throws SQLException { - if (score == -1) { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET score = DEFAULT(score) WHERE id = ?") - .setValue(this.ID).executeUpdate(); - } else { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET score = ? WHERE id = ?") - .setValue(score).setValue(this.ID).executeUpdate(); - } + public PlotType getPlotType() { + return plotType; } - public int getSharedScore() throws SQLException { - int score = getTotalScore(); - if (score != -1 && !getPlotMembers().isEmpty()) { - return (int) Math.floor(score / (getPlotMembers().size() + 1d)); + public boolean setPlotType(PlotType type) { + if (DataProvider.PLOT.setPlotType(getId(), type)) { + this.plotType = type; + return true; } - return score; + return false; } + @SuppressWarnings("unchecked") @Override - public PlotType getPlotType() throws SQLException { - if (plotType != null) return plotType; - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT type FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - int typeId = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - - plotType = PlotType.byId(typeId); - return plotType; - } - - DatabaseConnection.closeResultSet(rs); - return null; + public T getWorld() { + if (getVersion() <= 2 || getPlotType().hasOnePlotPerWorld()) { + if (onePlotWorld == null) onePlotWorld = new OnePlotWorld(this); + return (T) onePlotWorld; + } else { + if (cityPlotWorld == null) cityPlotWorld = new CityPlotWorld(this); + return (T) cityPlotWorld; } } - public void setPlotType(@NotNull PlotType type) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET type = ? WHERE id = ?") - .setValue(type.ordinal()).setValue(this.ID).executeUpdate(); - plotType = type; - } - - @Override - public double getVersion() { - if (plotVersion != -1) return plotVersion; - - try (ResultSet rs = DatabaseConnection.createStatement("SELECT version FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - double version = rs.getDouble(1); - if (!rs.wasNull()) { - plotVersion = version; - } else { - plotVersion = 2; // Plot version was implemented since v3, so we assume that the plot is v2. - } - - DatabaseConnection.closeResultSet(rs); - return plotVersion; - } - - DatabaseConnection.closeResultSet(rs); - } catch (SQLException ex) {Utils.logSqlException(ex);} - return PLOT_VERSION; - } - @Override - public File getOutlinesSchematic() { - return getSchematicFile(String.valueOf(getID())); + public byte[] getInitialSchematicBytes() { + return DataProvider.PLOT.getInitialSchematic(getId()); } - @Override - public File getEnvironmentSchematic() { - return getSchematicFile(getID() + "-env"); + public byte[] getCompletedSchematic() { + return DataProvider.PLOT.getCompletedSchematic(getId()); } - @Override - protected File getSchematicFile(String fileName) { - try { - return CompletableFuture.supplyAsync(() -> { - try { - File file = Paths.get(PlotUtils.getDefaultSchematicPath(), String.valueOf(getCity().getCountry().getServer().getID()), String.valueOf(getCity().getID()), fileName + PlotUtils.SCHEM_ENDING).toFile(); - - if (!file.exists()) { - // if .schem doesn't exist, it looks for old .schematic format for backwards compatibility - file = Paths.get(PlotUtils.getDefaultSchematicPath(), String.valueOf(getCity().getCountry().getServer().getID()), String.valueOf(getCity().getID()), fileName + PlotUtils.SCHEMATIC_ENDING).toFile(); - } - - if (!file.exists() && getCity().getCountry().getServer().getFTPConfiguration() != null && !FTPManager.downloadSchematic(FTPManager.getFTPUrl(getCity().getCountry().getServer(), getCity().getID()), file)) { - file = Paths.get(PlotUtils.getDefaultSchematicPath(), String.valueOf(getCity().getCountry().getServer().getID()), String.valueOf(getCity().getID()), fileName + PlotUtils.SCHEM_ENDING).toFile(); - FTPManager.downloadSchematic(FTPManager.getFTPUrl(getCity().getCountry().getServer(), getCity().getID()), file); - } - - return file; - } catch (SQLException | URISyntaxException ex) {Utils.logSqlException(ex);} - return null; - }).get(); - } catch (InterruptedException | ExecutionException ex) { - Thread.currentThread().interrupt(); - return null; - } + public List getReviewHistory() { + return DataProvider.REVIEW.getPlotReviewHistory(getId()); } - public File getCompletedSchematic() { - try { - File file = Paths.get(PlotUtils.getDefaultSchematicPath(), String.valueOf(getCity().getCountry().getServer().getID()), "finishedSchematics", String.valueOf(getCity().getID()), getID() + PlotUtils.SCHEM_ENDING).toFile(); - if (!file.exists()) { - // if .schem doesn't exist, it looks for old .schematic format for backwards compatibility - file = Paths.get(PlotUtils.getDefaultSchematicPath(), String.valueOf(getCity().getCountry().getServer().getID()), "finishedSchematics", String.valueOf(getCity().getID()), getID() + PlotUtils.SCHEMATIC_ENDING).toFile(); - } - return file; - } catch (SQLException ex) {Utils.logSqlException(ex);} - return null; + public Optional getLatestReview() { + return DataProvider.REVIEW.getLatestReview(getId()); } - @Override - public BlockVector3 getCenter() { - try { - if (getVersion() >= 3) { - return super.getCenter(); - } else return BlockVector3.at(PlotWorld.PLOT_SIZE / 2d, this.getWorld().getPlotHeightCentered(), PlotWorld.PLOT_SIZE / 2d); - } catch (IOException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("Failed to load schematic file to clipboard!"), ex); - } - return null; + public boolean isReviewed() { + return getLatestReview().isPresent(); } - public Slot getSlot() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT first_slot, second_slot, third_slot FROM plotsystem_builders WHERE uuid = ?") - .setValue(this.getPlotOwner().getUUID().toString()).executeQuery()) { - - if (rs.next()) { - for (int i = 1; i <= 3; i++) { - int slot = rs.getInt(i); - if (!rs.wasNull() && slot == getID()) { - DatabaseConnection.closeResultSet(rs); - return Slot.values()[i - 1]; - } - } - } - - DatabaseConnection.closeResultSet(rs); - - return null; - } - } - - public Review getReview() throws SQLException { - if (getStatus() == Status.completed || isRejected()) { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT review_id FROM plotsystem_plots WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - int i = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return new Review(i); - } - - DatabaseConnection.closeResultSet(rs); - } - } - return null; + public boolean isRejected() { + return (getStatus() == Status.unfinished || getStatus() == Status.unreviewed) && isReviewed(); } - public void setPasted(boolean pasted) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET pasted = ? WHERE id = ?") - .setValue(pasted).setValue(this.ID).executeUpdate(); + public boolean setPasted(boolean pasted) { + return DataProvider.PLOT.setPasted(getId(), pasted); } - public void addPlotMember(Builder member) throws SQLException { - List members = getPlotMembers(); - if (members.size() < 3 && members.stream().noneMatch(m -> m.getUUID().equals(member.getUUID()))) { + public boolean addPlotMember(Builder member) { + List plotMembers = getPlotMembers(); + if (plotMembers.size() < 3 && plotMembers.stream().noneMatch(m -> m.getUUID().equals(member.getUUID()))) { Slot slot = member.getFreeSlot(); if (slot != null) { - members.add(member); - setPlotMembers(members); - - member.setPlot(this.ID, slot); - getPermissions().addBuilderPerms(member.getUUID()); + plotMembers.add(member); + if (DataProvider.PLOT.addPlotMember(getId(), member)) { + if (!member.setSlot(slot, getId())) return false; + getPermissions().addBuilderPerms(member.getUUID()); + return true; + } } } + return false; } - public void removePlotMember(Builder member) throws SQLException { - List members = getPlotMembers(); - if (!members.isEmpty() && members.stream().anyMatch(m -> m.getUUID().equals(member.getUUID()))) { - members.remove(members.stream().filter(m -> m.getUUID().equals(member.getUUID())).findFirst().orElse(null)); - setPlotMembers(members); - - Slot slot = member.getSlot(this); - if (slot != null) { - member.removePlot(slot); + public boolean removePlotMember(Builder member) { + List plotMembers = getPlotMembers(); + if (!plotMembers.isEmpty() && plotMembers.contains(member)) { + plotMembers.remove(member); + if (DataProvider.PLOT.removePlotMember(getId(), member)) { + Slot slot = member.getSlotByPlotId(getId()); + if (slot != null && !member.setSlot(slot, -1)) return false; + if (getWorld().isWorldGenerated()) getPermissions().removeBuilderPerms(member.getUUID()); + return true; } - if (getWorld().isWorldGenerated()) getPermissions().removeBuilderPerms(member.getUUID()); - } - } - - public boolean isReviewed() throws SQLException { - return getReview() != null; - } - - public boolean isRejected() throws SQLException { - return (getStatus() == Status.unfinished || getStatus() == Status.unreviewed) && getTotalScore() != -1; // -1 == null - } - - - public static @NotNull List getPlots() throws SQLException { - return listPlots(DatabaseConnection.createStatement("SELECT id FROM plotsystem_plots").executeQuery()); - } - - public static @NotNull List getPlots(Status... statuses) throws SQLException { - ResultSet rs = DatabaseConnection.createStatement(getStatusQuery("", statuses)).executeQuery(); - return listPlots(rs); - } - - public static @NotNull List getPlots(@NotNull Builder builder) throws SQLException { - List plots = listPlots(DatabaseConnection.createStatement("SELECT id FROM plotsystem_plots WHERE owner_uuid = '" + builder.getUUID() + "' ORDER BY CAST(status AS CHAR)").executeQuery()); - plots.addAll(listPlots(DatabaseConnection.createStatement("SELECT id FROM plotsystem_plots WHERE INSTR(member_uuids, '" + builder.getUUID() + "') > 0 ORDER BY CAST(status AS CHAR)").executeQuery())); - return plots; - } - - public static @NotNull List getPlots(@NotNull Builder builder, Status... statuses) throws SQLException { - List plots = listPlots(DatabaseConnection.createStatement(getStatusQuery(" AND owner_uuid = '" + builder.getUUID().toString() + "'", statuses)).executeQuery()); - plots.addAll(getPlotsAsMember(builder, statuses)); - return plots; - } - - public static @NotNull List getPlots(@NotNull List countries, Status status) throws SQLException { - List cities = new ArrayList<>(); - countries.forEach(c -> cities.addAll(c.getCityProjects())); - return getPlots(cities, status); - } - - // Temporary fix to receive plots of builder as member - private static @NotNull List getPlotsAsMember(Builder builder, Status @NotNull ... status) throws SQLException { - List plots = new ArrayList<>(); - for (Status stat : status) { - plots.addAll(listPlots(DatabaseConnection.createStatement("SELECT id FROM plotsystem_plots WHERE status = '" + stat.name() + "' AND INSTR(member_uuids, '" + builder.getUUID() + "') > 0 ORDER BY CAST(status AS CHAR)").executeQuery())); - } - return plots; - } - - public static @NotNull List getPlots(int cityID, Status... statuses) throws SQLException { - return listPlots(DatabaseConnection.createStatement(getStatusQuery(" AND city_project_id = '" + cityID + "'", statuses)).executeQuery()); - } - - public static @NotNull List getPlots(@NotNull List cities, Status... statuses) throws SQLException { - if (cities.isEmpty()) { - return new ArrayList<>(); - } - StringBuilder query = new StringBuilder(" AND (city_project_id = "); - - for (int i = 0; i < cities.size(); i++) { - query.append(cities.get(i).getID()); - query.append((i != cities.size() - 1) ? " OR city_project_id = " : ")"); - } - - return listPlots(DatabaseConnection.createStatement(getStatusQuery(query.toString(), statuses)).executeQuery()); - } - - public static @NotNull List getPlots(int cityID, @NotNull PlotDifficulty plotDifficulty, @NotNull Status status) throws SQLException { - return listPlots(DatabaseConnection.createStatement("SELECT id FROM plotsystem_plots WHERE city_project_id = ? AND difficulty_id = ? AND status = ?") - .setValue(cityID) - .setValue(plotDifficulty.ordinal() + 1) - .setValue(status.name()) - .executeQuery()); - } - - private static @NotNull String getStatusQuery(String additionalQuery, Status @NotNull ... statuses) { - StringBuilder query = new StringBuilder("SELECT id FROM plotsystem_plots WHERE status = "); - - for (int i = 0; i < statuses.length; i++) { - query.append("'").append(statuses[i].name()).append("'").append(additionalQuery); - query.append((i != statuses.length - 1) ? " OR status = " : ""); - } - return query.toString(); - } - - private static @NotNull List listPlots(@NotNull ResultSet rs) throws SQLException { - List plots = new ArrayList<>(); - - while (rs.next()) { - plots.add(new Plot(rs.getInt(1))); - } - - DatabaseConnection.closeResultSet(rs); - return plots; - } - - public static double getMultiplierByDifficulty(@NotNull PlotDifficulty plotDifficulty) throws SQLException { - ResultSet rs = DatabaseConnection.createStatement("SELECT multiplier FROM plotsystem_difficulties WHERE id = ?") - .setValue(plotDifficulty.ordinal() + 1).executeQuery(); - - if (rs.next()) { - double d = rs.getDouble(1); - DatabaseConnection.closeResultSet(rs); - return d; - } - - DatabaseConnection.closeResultSet(rs); - return 1; - } - - public static int getScoreRequirementByDifficulty(PlotDifficulty plotDifficulty) throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT score_requirment FROM plotsystem_difficulties WHERE id = ?") - .setValue(plotDifficulty.ordinal() + 1).executeQuery()) { - - if (rs.next()) { - int i = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return i; - } - - DatabaseConnection.closeResultSet(rs); - return 0; } + return false; } - public static boolean hasPlotDifficultyScoreRequirement(@NotNull Builder builder, PlotDifficulty plotDifficulty) throws SQLException { + public static boolean meetsPlotDifficultyScoreRequirement(@NotNull Builder builder, PlotDifficulty plotDifficulty) { int playerScore = builder.getScore(); - int scoreRequirement = Plot.getScoreRequirementByDifficulty(plotDifficulty); + int scoreRequirement = DataProvider.DIFFICULTY.getDifficultyByEnum(plotDifficulty).orElseThrow().getScoreRequirement(); return playerScore >= scoreRequirement; } - public static @NotNull CompletableFuture getPlotDifficultyForBuilder(int cityID, Builder builder) throws SQLException { + public static CompletableFuture getPlotDifficultyForBuilder(CityProject city, Builder builder) { // Check if plot difficulties are available - boolean easyHasPlots = false; - boolean mediumHasPlots = false; - boolean hardHasPlots = false; - if (!getPlots(cityID, PlotDifficulty.EASY, Status.unclaimed).isEmpty()) easyHasPlots = true; - if (!getPlots(cityID, PlotDifficulty.MEDIUM, Status.unclaimed).isEmpty()) mediumHasPlots = true; - if (!getPlots(cityID, PlotDifficulty.HARD, Status.unclaimed).isEmpty()) hardHasPlots = true; + boolean easyHasPlots = false, mediumHasPlots = false, hardHasPlots = false; + if (!DataProvider.PLOT.getPlots(city, PlotDifficulty.EASY, Status.unclaimed).isEmpty()) easyHasPlots = true; + if (!DataProvider.PLOT.getPlots(city, PlotDifficulty.MEDIUM, Status.unclaimed).isEmpty()) mediumHasPlots = true; + if (!DataProvider.PLOT.getPlots(city, PlotDifficulty.HARD, Status.unclaimed).isEmpty()) hardHasPlots = true; - if (hardHasPlots && hasPlotDifficultyScoreRequirement(builder, PlotDifficulty.HARD)) { // Return hard + if (hardHasPlots && meetsPlotDifficultyScoreRequirement(builder, PlotDifficulty.HARD)) { // Return hard return CompletableFuture.completedFuture(PlotDifficulty.HARD); - } else if (mediumHasPlots && hasPlotDifficultyScoreRequirement(builder, PlotDifficulty.MEDIUM)) { // Return medium + } else if (mediumHasPlots && meetsPlotDifficultyScoreRequirement(builder, PlotDifficulty.MEDIUM)) { // Return medium return CompletableFuture.completedFuture(PlotDifficulty.MEDIUM); - } else if (easyHasPlots && hasPlotDifficultyScoreRequirement(builder, PlotDifficulty.EASY)) { // Return easy + } else if (easyHasPlots && meetsPlotDifficultyScoreRequirement(builder, PlotDifficulty.EASY)) { // Return easy return CompletableFuture.completedFuture(PlotDifficulty.EASY); - } else if (mediumHasPlots && hasPlotDifficultyScoreRequirement(builder, PlotDifficulty.HARD)) { // If hard has no plots return medium + } else if (mediumHasPlots && meetsPlotDifficultyScoreRequirement(builder, PlotDifficulty.HARD)) { // If hard has no plots return medium return CompletableFuture.completedFuture(PlotDifficulty.EASY); - } else if (easyHasPlots && hasPlotDifficultyScoreRequirement(builder, PlotDifficulty.MEDIUM)) { // If medium has no plots return easy + } else if (easyHasPlots && meetsPlotDifficultyScoreRequirement(builder, PlotDifficulty.MEDIUM)) { // If medium has no plots return easy return CompletableFuture.completedFuture(PlotDifficulty.MEDIUM); } else if (!PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.ENABLE_SCORE_REQUIREMENT)) { // If score requirement is disabled get plot from any available difficulty if (easyHasPlots) { diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/TutorialPlot.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/TutorialPlot.java index b0c5320c0..17e3b3da5 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/TutorialPlot.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/TutorialPlot.java @@ -1,113 +1,64 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot; import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.utils.PlotType; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; -import com.alpsbte.plotsystem.core.system.tutorial.TutorialDataModel; import com.alpsbte.plotsystem.utils.enums.Status; +import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.ConfigUtil; import com.alpsbte.plotsystem.utils.io.TutorialPaths; import com.sk89q.worldedit.math.BlockVector2; import org.apache.commons.io.FileUtils; import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -import java.io.*; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Paths; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.*; +import java.util.List; +import java.util.Objects; +import java.util.UUID; import static net.kyori.adventure.text.Component.text; -public class TutorialPlot extends AbstractPlot implements TutorialDataModel { - private int tutorialId = -1; - private final FileConfiguration tutorialConfig; - - public TutorialPlot(int id) throws SQLException { - super(id); - tutorialConfig = ConfigUtil.getTutorialInstance().configs[getTutorialID()]; - } +public class TutorialPlot extends AbstractPlot { + private final int tutorialId; + private final UUID uuid; + private int stageId; + private boolean isComplete; + private final LocalDate lastStageActivity; - @Override - public UUID getPlayerUUID() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT player_uuid FROM plotsystem_plots_tutorial WHERE id = ?") - .setValue(this.ID).executeQuery()) { + private int currentSchematicId; + private final FileConfiguration tutorialConfig; - if (rs.next()) { - String uuid = rs.getString(1); - DatabaseConnection.closeResultSet(rs); - return UUID.fromString(uuid); - } + public TutorialPlot(int plotId, int tutorialId, String uuid, int stageId, boolean isComplete, LocalDate lastStageActivity) { + super(plotId, UUID.fromString(uuid)); + this.tutorialId = tutorialId; + this.uuid = UUID.fromString(uuid); + this.stageId = stageId; + this.isComplete = isComplete; + this.lastStageActivity = lastStageActivity; - DatabaseConnection.closeResultSet(rs); - } - return null; + tutorialConfig = ConfigUtil.getTutorialInstance().configs[tutorialId]; } - @Override - public int getTutorialID() throws SQLException { - if (tutorialId != -1) return tutorialId; - try (ResultSet rs = DatabaseConnection.createStatement("SELECT tutorial_id FROM plotsystem_plots_tutorial WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - int id = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - tutorialId = id; - } - - DatabaseConnection.closeResultSet(rs); - } + public int getTutorialID() { return tutorialId; } - @Override - public int getStageID() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT stage_id FROM plotsystem_plots_tutorial WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - int stage = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return stage; - } + public UUID getUUID() { + return uuid; + } - DatabaseConnection.closeResultSet(rs); - } - return -1; + public int getStageID() { + return stageId; } /** @@ -116,158 +67,72 @@ public int getStageID() throws SQLException { * * @param stageID stage id, 0 is the first stage */ - public void setStageID(int stageID) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_plots_tutorial SET stage_id = ? WHERE id = ?") - .setValue(stageID).setValue(this.ID).executeUpdate(); - setLastStageCompletionDate(Timestamp.valueOf(LocalDateTime.now())); - } - - @Override - public boolean isCompleted() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT is_completed FROM plotsystem_plots_tutorial WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - int isCompleted = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - return isCompleted == 1; - } - - DatabaseConnection.closeResultSet(rs); + public boolean setStageID(int stageID) { + if (DataProvider.TUTORIAL_PLOT.setStageId(tutorialId, uuid.toString(), stageID)) { + this.stageId = stageID; + return true; } return false; } - /** - * Sets the completed status of the tutorial and updates the completion date. - */ - public void setCompleted() throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_plots_tutorial SET is_completed = ? WHERE id = ?") - .setValue(1).setValue(this.ID).executeUpdate(); - setCompletionDate(Timestamp.valueOf(LocalDateTime.now())); - } - - @Override - public Date getCreationDate() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT create_date FROM plotsystem_plots_tutorial WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - Date d = rs.getDate(1); - DatabaseConnection.closeResultSet(rs); - return d; - } - - DatabaseConnection.closeResultSet(rs); - } - return null; - } - - @Override - public Date getLastStageCompletionDate() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT last_stage_complete_date FROM plotsystem_plots_tutorial WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - Date d = rs.getDate(1); - DatabaseConnection.closeResultSet(rs); - return d; - } - - DatabaseConnection.closeResultSet(rs); - } - return null; + public boolean isComplete() { + return isComplete; } /** - * Sets the date when the last stage was completed. - * - * @param date date of the last stage completion + * Sets the completed status of the tutorial and updates the completion date. */ - private void setLastStageCompletionDate(Date date) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_plots_tutorial SET last_stage_complete_date = ? WHERE id = ?") - .setValue(date).setValue(this.ID).executeUpdate(); - } - - @Override - public Date getCompletionDate() throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT complete_date FROM plotsystem_plots_tutorial WHERE id = ?") - .setValue(this.ID).executeQuery()) { - - if (rs.next()) { - Date d = rs.getDate(1); - DatabaseConnection.closeResultSet(rs); - return d; - } - - DatabaseConnection.closeResultSet(rs); + public boolean setComplete() { + if (DataProvider.TUTORIAL_PLOT.setComplete(tutorialId, uuid.toString())) { + this.isComplete = true; + return true; } - return null; + return false; } - /** - * Sets the date when the tutorial was completed. - * - * @param date date of the completion - */ - private void setCompletionDate(Date date) throws SQLException { - DatabaseConnection.createStatement("UPDATE plotsystem_plots_tutorial SET complete_date = ? WHERE id = ?") - .setValue(date).setValue(this.ID).executeUpdate(); + @Override + public Builder getPlotOwner() { + return Builder.byUUID(uuid); } @Override - public Builder getPlotOwner() throws SQLException { - if (plotOwner != null) return plotOwner; - plotOwner = Builder.byUUID(getPlayerUUID()); - return plotOwner; + public boolean setPlotOwner(@Nullable Builder plotOwner) { + // Not needed for tutorial plots, as the value is initialized during database entry creation. + return true; } @Override @SuppressWarnings("unchecked") - public T getWorld() throws SQLException { - try { - if (onePlotWorld == null) onePlotWorld = new OnePlotWorld(this); - return (T) onePlotWorld; - } catch (SQLException ex) {PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex);} - return null; + public T getWorld() { + if (onePlotWorld == null) onePlotWorld = new OnePlotWorld(this); + return (T) onePlotWorld; } @Override - public List getOutline() throws SQLException, IOException { + public List getOutline() { String plotOutlines = tutorialConfig.getString(TutorialPaths.Beginner.PLOT_OUTLINES); - return getOutlinePoints(plotOutlines); + return getOutlinePoints(plotOutlines == null ? "" : plotOutlines); } - /** - * @deprecated Use {@link TutorialDataModel#getLastStageCompletionDate()} instead. - */ @Override - public Date getLastActivity() throws SQLException { - return getLastStageCompletionDate(); // Temporary to fix backwards compatibility + public LocalDate getLastActivity() { + return lastStageActivity; } - /** - * @deprecated Use {@link TutorialPlot#setLastStageCompletionDate(Date)} instead. - */ @Override - public void setLastActivity(boolean setNull) throws SQLException { - setLastStageCompletionDate(java.sql.Date.valueOf(LocalDate.now())); // Temporary to fix backwards compatibility + public boolean setLastActivity(boolean setNull) { + return true; } - /** - * @deprecated Use {@link TutorialDataModel#isCompleted()} instead. - */ @Override - public Status getStatus() throws SQLException { - return isCompleted() ? Status.completed : Status.unfinished; // Temporary to fix backwards compatibility + public Status getStatus() { + return isComplete ? Status.completed : Status.unfinished; } - /** - * @deprecated Use {@link TutorialPlot#setCompleted()} instead. - */ @Override - public void setStatus(@NotNull Status status) throws SQLException { - if (status == Status.completed) setCompleted(); // Temporary to fix backwards compatibility + public boolean setStatus(@NotNull Status status) { + if (status == Status.completed) return setComplete(); + return false; } @Override @@ -277,110 +142,34 @@ public PlotType getPlotType() { @Override public double getVersion() { - return 3; + return AbstractPlot.PLOT_VERSION; } @Override - protected File getSchematicFile(String fileName) { - File newSchem = Paths.get(PlotUtils.getDefaultSchematicPath(), "tutorials", fileName + ".schem").toFile(); - if (newSchem.exists()) return newSchem; - File oldSchem = Paths.get(PlotUtils.getDefaultSchematicPath(), "tutorials", fileName + ".schematic").toFile(); - if (oldSchem.exists()) return oldSchem; - + public byte[] getInitialSchematicBytes() { + File schematic; + String fileName = getTutorialID() + "-" + currentSchematicId + ".schem"; + schematic = Paths.get(PlotUtils.getDefaultSchematicPath(), "tutorials", fileName).toFile(); try { - FileUtils.copyInputStreamToFile(Objects.requireNonNull(PlotSystem.getPlugin().getResource("tutorial/schematics/" + fileName + ".schematic.gz")), oldSchem); + if (!schematic.exists()) FileUtils.copyInputStreamToFile(Objects.requireNonNull(PlotSystem.getPlugin() + .getResource("tutorial/schematics/" + fileName + ".gz")), schematic); + return Files.readAllBytes(schematic.toPath()); } catch (IOException ex) { PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while copying the schematic file!"), ex); } - return oldSchem; + return new byte[0]; } - public File getOutlinesSchematic(int schematicId) { - try { - return getSchematicFile(getTutorialID() + "-" + schematicId); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - return null; - } + public void setTutorialSchematic(int schematicId) { + currentSchematicId = schematicId; } - @Override - public File getOutlinesSchematic() { - return getOutlinesSchematic(0); + public static boolean isInProgress(int tutorialId, @NotNull UUID playerUUID) { + TutorialPlot plot = DataProvider.TUTORIAL_PLOT.getByTutorialId(tutorialId, playerUUID.toString()).orElse(null); + return plot == null || !plot.isComplete(); } - @Override - public File getEnvironmentSchematic() { - try { - return getSchematicFile(getTutorialID() + "-env"); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - return null; - } - } - - - /** - * Adds a new tutorial plot to the database. - * - * @param UUID uuid of the player - * @param tutorialId id of the tutorial - * @return the new tutorial plot - */ - public static TutorialPlot addTutorialPlot(String UUID, int tutorialId) throws SQLException { - DatabaseConnection.createStatement("INSERT INTO plotsystem_plots_tutorial (player_uuid, tutorial_id) VALUES (?, ?)") - .setValue(UUID).setValue(tutorialId).executeUpdate(); - return getPlot(UUID, tutorialId); - } - - /** - * Gets a tutorial plot from the database. - * - * @param UUID uuid of the player - * @param tutorialId id of the tutorial - * @return the tutorial plot - */ - public static TutorialPlot getPlot(String UUID, int tutorialId) throws SQLException { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT id FROM plotsystem_plots_tutorial WHERE player_uuid = ? AND tutorial_id = ?") - .setValue(UUID).setValue(tutorialId).executeQuery()) { - - if (rs.next()) { - int id = rs.getInt(1); - DatabaseConnection.closeResultSet(rs); - - return new TutorialPlot(id); - } - - DatabaseConnection.closeResultSet(rs); - } - return null; - } - - /** - * Gets all tutorials from the player. - * - * @param builderUUID uuid of the player - * @return list of tutorials - */ - public static List getPlots(UUID builderUUID) throws SQLException { - return listPlots(DatabaseConnection.createStatement("SELECT id FROM plotsystem_plots_tutorial WHERE player_uuid = ?") - .setValue(builderUUID.toString()).executeQuery()); - } - - public static boolean isPlotCompleted(Player player, int tutorialId) throws SQLException { - TutorialPlot plot = TutorialPlot.getPlot(player.getUniqueId().toString(), tutorialId); - if (plot == null) return false; - return plot.isCompleted(); - } - - private static List listPlots(ResultSet rs) throws SQLException { - List plots = new ArrayList<>(); - - while (rs.next()) { - plots.add(new TutorialPlot(rs.getInt(1))); - } - - DatabaseConnection.closeResultSet(rs); - return plots; + public static boolean isRequiredAndInProgress(int tutorialId, UUID playerUUID) { + return PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.TUTORIAL_ENABLE) && PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.TUTORIAL_REQUIRE_BEGINNER_TUTORIAL) && isInProgress(tutorialId, playerUUID); } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java index 236e1be39..5b4ec0cdc 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/AbstractPlotGenerator.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.generator; import com.alpsbte.plotsystem.PlotSystem; @@ -33,18 +9,18 @@ import com.alpsbte.plotsystem.core.system.plot.world.CityPlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; +import com.alpsbte.plotsystem.utils.DependencyManager; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.ConfigUtil; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.fastasyncworldedit.core.FaweAPI; import com.sk89q.worldedit.EditSession; import com.sk89q.worldedit.WorldEdit; -import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; import com.sk89q.worldedit.function.mask.BlockTypeMask; import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.mask.RegionMask; @@ -72,9 +48,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.File; +import java.io.ByteArrayInputStream; import java.io.IOException; -import java.sql.SQLException; import java.util.HashSet; import java.util.List; import java.util.Objects; @@ -94,8 +69,8 @@ public abstract class AbstractPlotGenerator { * @param plot - plot which should be generated * @param builder - builder of the plot */ - public AbstractPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builder) throws SQLException { - this(plot, builder, builder.getPlotTypeSetting()); + protected AbstractPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builder) { + this(plot, builder, builder.getPlotType()); } /** @@ -105,7 +80,7 @@ public AbstractPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builde * @param builder - builder of the plot * @param plotType - type of the plot */ - public AbstractPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builder, @NotNull PlotType plotType) throws SQLException { + protected AbstractPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builder, @NotNull PlotType plotType) { this(plot, builder, plotType, plot.getVersion() <= 2 || plotType.hasOnePlotPerWorld() ? new OnePlotWorld(plot) : new CityPlotWorld((Plot) plot)); } @@ -129,17 +104,12 @@ private AbstractPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder build if (plotType.hasOnePlotPerWorld() || !world.isWorldGenerated()) { new PlotWorldGenerator(world.getWorldName()); } else if (!world.isWorldLoaded() && !world.loadWorld()) throw new Exception("Could not load world"); - generateOutlines(plot.getOutlinesSchematic(), plot.getVersion() >= 3 ? plot.getEnvironmentSchematic() : null); + generateOutlines(); createPlotProtection(); } catch (Exception ex) { exception = ex; } - - try { - this.onComplete(exception != null, false); - } catch (SQLException ex) { - exception = ex; - } + this.onComplete(exception != null, false); if (exception != null) { PlotUtils.Actions.abandonPlot(plot); @@ -159,23 +129,21 @@ private AbstractPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder build /** * Generates plot schematic and outlines - * - * @param plotSchematic - plot schematic file - * @param environmentSchematic - environment schematic file */ - protected void generateOutlines(@NotNull File plotSchematic, @Nullable File environmentSchematic) throws IOException, WorldEditException, SQLException { - Mask airMask = new BlockTypeMask(BukkitAdapter.adapt(world.getBukkitWorld()), BlockTypes.AIR); - if (plotVersion >= 3 && plotType.hasEnvironment() && environmentSchematic != null && environmentSchematic.exists()) { - pasteSchematic(airMask, environmentSchematic, world, false); + protected void generateOutlines() throws IOException { + if (plotVersion >= 3 && plotType.hasEnvironment()) { + pasteSchematic(null, plot.getInitialSchematicBytes(), world, false, false); + } else { + Mask airMask = new BlockTypeMask(BukkitAdapter.adapt(world.getBukkitWorld()), BlockTypes.AIR); + pasteSchematic(airMask, PlotUtils.getOutlinesSchematicBytes(plot, world.getBukkitWorld()), world, true, false); } - pasteSchematic(airMask, plotSchematic, world, true); } /** * Creates plot protection */ - protected void createPlotProtection() throws StorageException, SQLException, IOException { + protected void createPlotProtection() throws StorageException { RegionContainer regionContainer = WorldGuard.getInstance().getPlatform().getRegionContainer(); RegionManager regionManager = regionContainer.get(BukkitAdapter.adapt(world.getBukkitWorld())); @@ -194,7 +162,6 @@ protected void createPlotProtection() throws StorageException, SQLException, IOE DefaultDomain owner = protectedBuildRegion.getOwners(); owner.addPlayer(builder.getUUID()); protectedBuildRegion.setOwners(owner); - protectedRegion.setOwners(owner); // Set protected build region permissions setBuildRegionPermissions(protectedBuildRegion); @@ -216,10 +183,10 @@ protected void createPlotProtection() throws StorageException, SQLException, IOE * * @param region build region */ - protected void setBuildRegionPermissions(ProtectedRegion region) { + protected void setBuildRegionPermissions(@NotNull ProtectedRegion region) { region.setFlag(Flags.BUILD, StateFlag.State.ALLOW); region.setFlag(Flags.BUILD.getRegionGroupFlag(), RegionGroup.OWNERS); - if (PlotSystem.DependencyManager.isWorldGuardExtraFlagsEnabled()) + if (DependencyManager.isWorldGuardExtraFlagsEnabled()) region.setFlag(new StateFlag("worldedit", true, RegionGroup.OWNERS), StateFlag.State.ALLOW); } @@ -228,9 +195,7 @@ protected void setBuildRegionPermissions(ProtectedRegion region) { * * @param region plot region */ - protected void setRegionPermissions(ProtectedRegion region) { - region.setFlag(Flags.BUILD, StateFlag.State.DENY); - region.setFlag(Flags.BUILD.getRegionGroupFlag(), RegionGroup.ALL); + protected void setRegionPermissions(@NotNull ProtectedRegion region) { region.setFlag(Flags.ENTRY, StateFlag.State.ALLOW); region.setFlag(Flags.ENTRY.getRegionGroupFlag(), RegionGroup.ALL); @@ -245,7 +210,7 @@ protected void setRegionPermissions(ProtectedRegion region) { * @param config commands.yml config * @return list of blocked commands */ - protected List getBlockedCommands(FileConfiguration config) { + protected List getBlockedCommands(@NotNull FileConfiguration config) { List blockedCommands = config.getStringList(ConfigPaths.BLOCKED_COMMANDS_BUILDERS); blockedCommands.removeIf(c -> c.equals("/cmd1")); return blockedCommands; @@ -256,9 +221,8 @@ protected List getBlockedCommands(FileConfiguration config) { * * @param failed - true if generation has failed * @param unloadWorld - try to unload world after generation - * @throws SQLException - caused by a database exception */ - protected void onComplete(boolean failed, boolean unloadWorld) throws SQLException { + protected void onComplete(boolean failed, boolean unloadWorld) { // Unload plot world if it is not needed anymore if (unloadWorld) world.unloadWorld(false); } @@ -299,26 +263,45 @@ public Builder getBuilder() { * @param schematicFile - plot/environment schematic file * @param world - world to paste in * @param clearArea - clears the plot area with air before pasting + * @param offset - offset for the paste operation */ - public static void pasteSchematic(@Nullable Mask pasteMask, File schematicFile, PlotWorld world, boolean clearArea) throws IOException, WorldEditException, SQLException { - if (world.loadWorld()) { - World weWorld = new BukkitWorld(world.getBukkitWorld()); - try (EditSession editSession = WorldEdit.getInstance().newEditSession(BukkitAdapter.adapt(world.getBukkitWorld()))) { - if (clearArea) { - Polygonal2DRegion polyRegion = new Polygonal2DRegion(weWorld, world.getPlot().getOutline(), 0, PlotWorld.MAX_WORLD_HEIGHT); - editSession.setMask(new RegionMask(polyRegion)); - editSession.setBlocks((Region) polyRegion, Objects.requireNonNull(BlockTypes.AIR).getDefaultState()); - } - } + public static void pasteSchematic(@Nullable Mask pasteMask, byte[] schematicFile, @NotNull PlotWorld world, boolean clearArea, boolean offset) throws IOException { + // load world + if (!world.loadWorld()) return; + World weWorld = new BukkitWorld(world.getBukkitWorld()); + + // set outline region with air + if (clearArea) { try (EditSession editSession = WorldEdit.getInstance().newEditSession(BukkitAdapter.adapt(world.getBukkitWorld()))) { - if (pasteMask != null) editSession.setMask(pasteMask); - Clipboard clipboard = FaweAPI.load(schematicFile); - Operation clipboardHolder = new ClipboardHolder(clipboard) - .createPaste(editSession) - .to(BlockVector3.at(world.getPlot().getCenter().x(), world.getPlotHeight(), world.getPlot().getCenter().z())) - .build(); - Operations.complete(clipboardHolder); + Polygonal2DRegion polyRegion = new Polygonal2DRegion(weWorld, world.getPlot().getOutline(), 0, PlotWorld.MAX_WORLD_HEIGHT); + editSession.setMask(new RegionMask(polyRegion)); + editSession.setBlocks((Region) polyRegion, Objects.requireNonNull(BlockTypes.AIR).getDefaultState()); } } + + // load schematic + Clipboard clipboard; + ByteArrayInputStream inputStream = new ByteArrayInputStream(schematicFile); + try (ClipboardReader reader = AbstractPlot.CLIPBOARD_FORMAT.getReader(inputStream)) { + clipboard = reader.read(); + } + + int pasteY = world.getPlotHeight(); + + if (offset) { + BlockVector3 clipboardOrigin = clipboard.getOrigin(); + if (clipboardOrigin == null) clipboardOrigin = clipboard.getMinimumPoint(); + pasteY = world.getPlotHeight() - clipboard.getMinimumPoint().y() + clipboardOrigin.y(); + } + + // paste schematic + try (EditSession editSession = WorldEdit.getInstance().newEditSession(BukkitAdapter.adapt(world.getBukkitWorld()))) { + if (pasteMask != null) editSession.setMask(pasteMask); + Operation clipboardHolder = new ClipboardHolder(clipboard) + .createPaste(editSession) + .to(BlockVector3.at(world.getPlot().getCenter().x(), pasteY, world.getPlot().getCenter().z())) + .build(); + Operations.complete(clipboardHolder); + } } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java index e13114dfd..617777f98 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/DefaultPlotGenerator.java @@ -1,31 +1,9 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.generator; import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.CityProject; import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.utils.PlotType; @@ -37,12 +15,13 @@ import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import com.sk89q.worldedit.WorldEditException; +import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldedit.function.mask.BlockTypeMask; +import com.sk89q.worldedit.function.mask.Mask; +import com.sk89q.worldedit.world.block.BlockTypes; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.io.File; import java.io.IOException; -import java.sql.SQLException; import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; @@ -53,47 +32,52 @@ public class DefaultPlotGenerator extends AbstractPlotGenerator { public static final Map playerPlotGenerationHistory = new HashMap<>(); - public DefaultPlotGenerator(int cityID, PlotDifficulty plotDifficulty, Builder builder) throws SQLException { - this(Plot.getPlots(cityID, plotDifficulty, Status.unclaimed).get(Utils.getRandom().nextInt(Plot.getPlots(cityID, plotDifficulty, Status.unclaimed).size())), builder); + public DefaultPlotGenerator(CityProject city, PlotDifficulty plotDifficulty, Builder builder) { + this(DataProvider.PLOT.getPlots(city, plotDifficulty, Status.unclaimed).get(Utils.getRandom().nextInt(DataProvider.PLOT.getPlots(city, plotDifficulty, Status.unclaimed).size())), builder); } - public DefaultPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builder) throws SQLException { + public DefaultPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builder) { super(plot, builder); } - public DefaultPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builder, PlotType plotType) throws SQLException { + public DefaultPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builder, PlotType plotType) { super(plot, builder, plotType); } @Override protected boolean init() { - try { - if (getBuilder().getFreeSlot() != null) { - if (DefaultPlotGenerator.playerPlotGenerationHistory.containsKey(getBuilder().getUUID())) { - if (DefaultPlotGenerator.playerPlotGenerationHistory.get(getBuilder().getUUID()).isBefore(LocalDateTime.now().minusSeconds(10))) { - DefaultPlotGenerator.playerPlotGenerationHistory.remove(getBuilder().getUUID()); - } else { - getBuilder().getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(getBuilder().getPlayer(), LangPaths.Message.Error.PLEASE_WAIT))); - getBuilder().getPlayer().playSound(getBuilder().getPlayer().getLocation(), Utils.SoundUtils.ERROR_SOUND, 1, 1); - return false; - } + if (getBuilder().getFreeSlot() != null) { + if (DefaultPlotGenerator.playerPlotGenerationHistory.containsKey(getBuilder().getUUID())) { + if (DefaultPlotGenerator.playerPlotGenerationHistory.get(getBuilder().getUUID()).isBefore(LocalDateTime.now().minusSeconds(10))) { + DefaultPlotGenerator.playerPlotGenerationHistory.remove(getBuilder().getUUID()); + } else { + getBuilder().getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(getBuilder().getPlayer(), LangPaths.Message.Error.PLEASE_WAIT))); + getBuilder().getPlayer().playSound(getBuilder().getPlayer().getLocation(), Utils.SoundUtils.ERROR_SOUND, 1, 1); + return false; } - - DefaultPlotGenerator.playerPlotGenerationHistory.put(getBuilder().getUUID(), LocalDateTime.now()); - getBuilder().getPlayer().sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getBuilder().getPlayer(), LangPaths.Message.Info.CREATING_PLOT))); - getBuilder().getPlayer().playSound(getBuilder().getPlayer().getLocation(), Utils.SoundUtils.CREATE_PLOT_SOUND, 1, 1); - return true; - } else { - getBuilder().getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(getBuilder().getPlayer(), LangPaths.Message.Error.ALL_SLOTS_OCCUPIED))); - getBuilder().getPlayer().playSound(getBuilder().getPlayer().getLocation(), Utils.SoundUtils.ERROR_SOUND, 1, 1); } - } catch (SQLException ex) {Utils.logSqlException(ex);} + + DefaultPlotGenerator.playerPlotGenerationHistory.put(getBuilder().getUUID(), LocalDateTime.now()); + getBuilder().getPlayer().sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(getBuilder().getPlayer(), LangPaths.Message.Info.CREATING_PLOT))); + getBuilder().getPlayer().playSound(getBuilder().getPlayer().getLocation(), Utils.SoundUtils.CREATE_PLOT_SOUND, 1, 1); + return true; + } else { + getBuilder().getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(getBuilder().getPlayer(), LangPaths.Message.Error.ALL_SLOTS_OCCUPIED))); + getBuilder().getPlayer().playSound(getBuilder().getPlayer().getLocation(), Utils.SoundUtils.ERROR_SOUND, 1, 1); + } return false; } @Override - protected void generateOutlines(@NotNull File plotSchematic, @Nullable File environmentSchematic) throws IOException, WorldEditException, SQLException { - super.generateOutlines(plotSchematic, environmentSchematic); + protected void generateOutlines() throws IOException, WorldEditException { + if (plot instanceof Plot) { + byte[] completedSchematic = ((Plot) plot).getCompletedSchematic(); + if (completedSchematic != null) { + PlotSystem.getPlugin().getComponentLogger().info("Found completed schematic, pasting only that."); + Mask airMask = new BlockTypeMask(BukkitAdapter.adapt(world.getBukkitWorld()), BlockTypes.AIR); + pasteSchematic(airMask, completedSchematic, world, false, true); + } else super.generateOutlines(); + } else super.generateOutlines(); // If the player is playing in his own world, then additionally generate the plot in the city world if (PlotWorld.isOnePlotWorld(world.getWorldName()) && plotVersion >= 3 && plot.getStatus() != Status.completed) { @@ -108,7 +92,7 @@ protected boolean init() { protected void createPlotProtection() {} @Override - protected void onComplete(boolean failed, boolean unloadWorld) throws SQLException { + protected void onComplete(boolean failed, boolean unloadWorld) { super.onComplete(true, true); } @@ -121,18 +105,17 @@ protected void onException(Throwable ex) { } @Override - protected void onComplete(boolean failed, boolean unloadWorld) throws SQLException { + protected void onComplete(boolean failed, boolean unloadWorld) { super.onComplete(failed, false); + if (failed) return; - if (!failed) { - getBuilder().setPlot(plot.getID(), getBuilder().getFreeSlot()); - plot.setStatus(Status.unfinished); - ((Plot) plot).setPlotType(plotType); - ((Plot) plot).setPlotOwner(getBuilder().getPlayer().getUniqueId().toString()); - PlotUtils.Cache.clearCache(getBuilder().getUUID()); + if (!getBuilder().setSlot(getBuilder().getFreeSlot(), plot.getId())) return; + if (!plot.setStatus(Status.unfinished)) return; + if (!((Plot) plot).setPlotType(plotType)) return; + if (!plot.setPlotOwner(getBuilder())) return; - plot.getWorld().teleportPlayer(getBuilder().getPlayer()); - LangUtil.getInstance().broadcast(LangPaths.Message.Info.CREATED_NEW_PLOT, plot.getPlotOwner().getName()); - } + PlotUtils.Cache.clearCache(getBuilder().getUUID()); + plot.getWorld().teleportPlayer(getBuilder().getPlayer()); + LangUtil.getInstance().broadcast(LangPaths.Message.Info.CREATED_NEW_PLOT, getBuilder().getName()); } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/PlotWorldGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/PlotWorldGenerator.java index 15e10d5f5..6dbd2041d 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/PlotWorldGenerator.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/PlotWorldGenerator.java @@ -1,32 +1,7 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.generator; import com.alpsbte.plotsystem.PlotSystem; -import com.onarandombox.MultiverseCore.api.MVWorldManager; -import com.onarandombox.MultiverseCore.api.MultiverseWorld; +import com.alpsbte.plotsystem.utils.DependencyManager; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.protection.flags.Flags; @@ -36,8 +11,19 @@ import com.sk89q.worldguard.protection.managers.storage.StorageException; import com.sk89q.worldguard.protection.regions.GlobalProtectedRegion; import com.sk89q.worldguard.protection.regions.RegionContainer; -import org.bukkit.*; +import org.bukkit.Bukkit; +import org.bukkit.Difficulty; +import org.bukkit.GameMode; +import org.bukkit.GameRule; +import org.bukkit.World; +import org.bukkit.WorldCreator; +import org.bukkit.WorldType; +import org.bukkit.entity.SpawnCategory; import org.bukkit.generator.ChunkGenerator; +import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld; +import org.mvplugins.multiverse.core.world.WorldManager; +import org.mvplugins.multiverse.core.world.options.ImportWorldOptions; +import org.mvplugins.multiverse.external.vavr.control.Option; import javax.annotation.Nonnull; import java.util.Objects; @@ -46,7 +32,7 @@ import static net.kyori.adventure.text.Component.text; public class PlotWorldGenerator { - private final MVWorldManager worldManager = PlotSystem.DependencyManager.getMultiverseCore().getMVWorldManager(); + private final WorldManager worldManager = DependencyManager.getMultiverseCore().getWorldManager(); private WorldCreator worldCreator; private final String worldName; @@ -74,9 +60,13 @@ protected void generateWorld() { protected void createMultiverseWorld() throws Exception { // Check if world creator is configured and add new world to multiverse world manager if (worldCreator != null) { - if (!worldManager.isMVWorld(worldName)) - worldManager.addWorld(worldName, environment, null, worldType, false, - "VoidGen:{\"caves\":false,\"decoration\":false,\"mobs\":false,\"structures\":false}", false); + if (!worldManager.isLoadedWorld(worldName)) { + worldManager.importWorld(ImportWorldOptions.worldName(worldName) + .environment(environment) + .generator("VoidGen:{\"caves\":false,\"decoration\":false,\"mobs\":false,\"structures\":false}") + .useSpawnAdjust(false) + ); + } } else { throw new Exception("World Creator is not configured"); } @@ -84,7 +74,12 @@ protected void createMultiverseWorld() throws Exception { protected void configureWorld() { World bukkitWorld = Bukkit.getWorld(worldName); - MultiverseWorld mvWorld = worldManager.getMVWorld(bukkitWorld); + Option mvWorld = worldManager.getLoadedWorld(worldName); + + if (mvWorld.isEmpty()) { + PlotSystem.getPlugin().getComponentLogger().warn(text("Multiverse world" + worldName + " is not loaded! Skipping world configuration...")); + return; + } // Set world time to midday assert bukkitWorld != null; @@ -98,16 +93,18 @@ protected void configureWorld() { bukkitWorld.setGameRule(GameRule.KEEP_INVENTORY, true); bukkitWorld.setGameRule(GameRule.DO_MOB_SPAWNING, false); bukkitWorld.setGameRule(GameRule.ANNOUNCE_ADVANCEMENTS, false); + bukkitWorld.setGameRule(GameRule.DO_TILE_DROPS, false); + bukkitWorld.setGameRule(GameRule.DO_MOB_LOOT, false); // Configure multiverse world - mvWorld.setAllowFlight(true); - mvWorld.setGameMode(GameMode.CREATIVE); - mvWorld.setEnableWeather(false); - mvWorld.setDifficulty(Difficulty.PEACEFUL); - mvWorld.setAllowAnimalSpawn(false); - mvWorld.setAllowMonsterSpawn(false); - mvWorld.setAutoLoad(false); - mvWorld.setKeepSpawnInMemory(false); + mvWorld.get().setAllowFlight(true); + mvWorld.get().setGameMode(GameMode.CREATIVE); + mvWorld.get().setAllowWeather(false); + mvWorld.get().setDifficulty(Difficulty.PEACEFUL); + mvWorld.get().getEntitySpawnConfig().getSpawnCategoryConfig(SpawnCategory.ANIMAL).setSpawn(false); + mvWorld.get().getEntitySpawnConfig().getSpawnCategoryConfig(SpawnCategory.MONSTER).setSpawn(false); + mvWorld.get().setAutoLoad(false); + mvWorld.get().setKeepSpawnInMemory(false); worldManager.saveWorldsConfig(); } @@ -125,7 +122,7 @@ protected void createGlobalProtection() throws StorageException { globalRegion.setFlag(Flags.PASSTHROUGH.getRegionGroupFlag(), RegionGroup.ALL); globalRegion.setFlag(Flags.TNT, StateFlag.State.DENY); globalRegion.setFlag(Flags.TNT.getRegionGroupFlag(), RegionGroup.ALL); - if (PlotSystem.DependencyManager.isWorldGuardExtraFlagsEnabled()) + if (DependencyManager.isWorldGuardExtraFlagsEnabled()) globalRegion.setFlag(new StateFlag("worldedit", true, RegionGroup.ALL), StateFlag.State.DENY); if (regionManager.hasRegion(regionName)) regionManager.removeRegion(regionName); diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/TutorialPlotGenerator.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/TutorialPlotGenerator.java index 9d9737ae8..b5662f253 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/TutorialPlotGenerator.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/generator/TutorialPlotGenerator.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.generator; import com.alpsbte.plotsystem.PlotSystem; @@ -29,6 +5,7 @@ import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.TutorialPlot; import com.alpsbte.plotsystem.core.system.plot.utils.PlotType; +import com.alpsbte.plotsystem.utils.DependencyManager; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldguard.WorldGuard; @@ -40,7 +17,6 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; -import java.sql.SQLException; import java.util.Objects; import static net.kyori.adventure.text.Component.text; @@ -49,7 +25,7 @@ public class TutorialPlotGenerator extends AbstractPlotGenerator { private boolean buildingEnabled = false; private boolean worldEditEnabled = false; - public TutorialPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builder) throws SQLException { + public TutorialPlotGenerator(@NotNull AbstractPlot plot, @NotNull Builder builder) { super(plot, builder, PlotType.TUTORIAL); } @@ -58,16 +34,17 @@ protected boolean init() { return true; } - public void generateOutlines(int schematicId) throws SQLException, IOException, WorldEditException { - generateOutlines(((TutorialPlot) plot).getOutlinesSchematic(schematicId), null); + public void generateOutlines(int schematicId) throws IOException, WorldEditException { + ((TutorialPlot) plot).setTutorialSchematic(schematicId); + generateOutlines(); } @Override - protected void setBuildRegionPermissions(ProtectedRegion region) { + protected void setBuildRegionPermissions(@NotNull ProtectedRegion region) { region.setFlag(Flags.BUILD, isBuildingEnabled() ? StateFlag.State.ALLOW : StateFlag.State.DENY); region.setFlag(Flags.BUILD.getRegionGroupFlag(), RegionGroup.OWNERS); - if (PlotSystem.DependencyManager.isWorldGuardExtraFlagsEnabled()) + if (DependencyManager.isWorldGuardExtraFlagsEnabled()) region.setFlag(new StateFlag("worldedit", false, RegionGroup.OWNERS), isWorldEditEnabled() ? StateFlag.State.ALLOW : StateFlag.State.DENY); try { @@ -78,7 +55,7 @@ protected void setBuildRegionPermissions(ProtectedRegion region) { } @Override - protected void onComplete(boolean failed, boolean unloadWorld) throws SQLException { + protected void onComplete(boolean failed, boolean unloadWorld) { super.onComplete(failed, false); } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotPermissions.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotPermissions.java index 9c85edd18..e0cf41e86 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotPermissions.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotPermissions.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021-2022, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.utils; import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; @@ -37,21 +13,18 @@ public PlotPermissions(PlotWorld world) { } public PlotPermissions addBuilderPerms(UUID builder) { - if (world.getProtectedRegion() != null) world.getProtectedRegion().getOwners().addPlayer(builder); world.getProtectedBuildRegion().getOwners().addPlayer(builder); PlotUtils.Cache.clearCache(builder); return this; } public PlotPermissions removeBuilderPerms(UUID builder) { - if (world.getProtectedRegion() != null) world.getProtectedRegion().getOwners().removePlayer(builder); world.getProtectedBuildRegion().getOwners().removePlayer(builder); PlotUtils.Cache.clearCache(builder); return this; } public void clearAllPerms() { - if (world.getProtectedRegion() != null) world.getProtectedRegion().getOwners().removeAll(); world.getProtectedBuildRegion().getOwners().removeAll(); } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotType.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotType.java index 15b7b5a72..645a3cb23 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotType.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotType.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.utils; public enum PlotType { diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java index c33d62104..9588b1484 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/utils/PlotUtils.java @@ -1,34 +1,9 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.utils; import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.database.DatabaseConnection; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.CityProject; -import com.alpsbte.plotsystem.core.system.Server; import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.TutorialPlot; @@ -36,31 +11,36 @@ import com.alpsbte.plotsystem.core.system.plot.world.CityPlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.OnePlotWorld; import com.alpsbte.plotsystem.core.system.plot.world.PlotWorld; +import com.alpsbte.plotsystem.core.system.review.PlotReview; +import com.alpsbte.plotsystem.core.system.review.ReviewNotification; +import com.alpsbte.plotsystem.utils.DependencyManager; import com.alpsbte.plotsystem.utils.ShortLink; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.enums.Status; import com.alpsbte.plotsystem.utils.io.ConfigPaths; -import com.alpsbte.plotsystem.utils.io.FTPManager; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import com.github.fierioziy.particlenativeapi.api.ParticleNativeAPI; -import com.github.fierioziy.particlenativeapi.api.Particles_1_8; +import com.github.fierioziy.particlenativeapi.api.Particles_1_13; import com.github.fierioziy.particlenativeapi.plugin.ParticleNativePlugin; import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitWorld; import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard; -import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat; -import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; +import com.sk89q.worldedit.function.mask.BlockTypeMask; +import com.sk89q.worldedit.function.mask.Mask; import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.Vector3; +import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.regions.CuboidRegion; import com.sk89q.worldedit.regions.Polygonal2DRegion; +import com.sk89q.worldedit.world.block.BlockTypes; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.regions.ProtectedRegion; @@ -73,35 +53,41 @@ import org.bukkit.World; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitTask; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileOutputStream; import java.io.IOException; import java.math.RoundingMode; import java.net.URISyntaxException; -import java.nio.file.Files; import java.nio.file.Paths; -import java.sql.ResultSet; -import java.sql.SQLException; import java.text.DecimalFormat; -import java.util.*; +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.UUID; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionException; import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; public final class PlotUtils { - - public static final String SCHEM_ENDING = ".schem"; - public static final String SCHEMATIC_ENDING = ".schematic"; - private PlotUtils() {} private static final String MSG_LINE = "--------------------------"; + public static final Map plotReminder = new HashMap<>(); /** * Returns the plot that the player is currently standing on or next to. @@ -111,20 +97,48 @@ private PlotUtils() {} * @return the current plot of the player */ @Nullable - public static AbstractPlot getCurrentPlot(@NotNull Builder builder, Status... statuses) throws SQLException { + public static AbstractPlot getCurrentPlot(@NotNull Builder builder, Status... statuses) { + boolean dev = PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.DEV_MODE); + if (dev) { + PlotSystem.getPlugin().getComponentLogger().info(text( + "getCurrentPlot: enter | player=" + (builder.isOnline() ? builder.getPlayer().getName() : builder.getUUID()) + + ", statuses=" + (statuses == null ? "null" : java.util.Arrays.toString(statuses)) + )); + } + if (builder.isOnline()) { String worldName = builder.getPlayer().getWorld().getName(); + if (dev) PlotSystem.getPlugin().getComponentLogger().info(text("getCurrentPlot: worldName=" + worldName)); if (PlotWorld.isOnePlotWorld(worldName)) { - int id = Integer.parseInt(worldName.substring(2)); - AbstractPlot plot = worldName.toLowerCase(Locale.ROOT).startsWith("p-") ? new Plot(id) : new TutorialPlot(id); - if (statuses == null) return plot; - for (Status status : statuses) if (status == plot.getStatus()) return plot; - return null; + if (dev) PlotSystem.getPlugin().getComponentLogger().info(text("getCurrentPlot: detected OnePlotWorld")); + try { + int id = Integer.parseInt(worldName.substring(2)); + AbstractPlot plot = worldName.toLowerCase(Locale.ROOT).startsWith("p-") + ? DataProvider.PLOT.getPlotById(id) + : DataProvider.TUTORIAL_PLOT.getById(id).orElse(null); + if (dev) PlotSystem.getPlugin().getComponentLogger().info(text("getCurrentPlot: one-plot id=" + id + ", resolved=" + (plot == null ? "null" : (plot.getClass().getSimpleName() + "#" + plot.getId() + " status=" + plot.getStatus())))); + + if (plot == null) return null; + if (statuses == null || statuses.length == 0) return plot; + for (Status status : statuses) if (status == plot.getStatus()) return plot; + if (dev) PlotSystem.getPlugin().getComponentLogger().info(text("getCurrentPlot: status filter did not match for plot #" + plot.getId())); + return null; + } catch (NumberFormatException ex) { + if (dev) PlotSystem.getPlugin().getComponentLogger().warn(text("getCurrentPlot: failed to parse plot id from worldName=" + worldName), ex); + return null; + } } else if (PlotWorld.isCityPlotWorld(worldName)) { - int cityID = Integer.parseInt(worldName.substring(2)); - List plots = Plot.getPlots(cityID, statuses); + if (dev) PlotSystem.getPlugin().getComponentLogger().info(text("getCurrentPlot: detected CityPlotWorld")); + String cityID = worldName.substring(2); + Optional city = DataProvider.CITY_PROJECT.getById(cityID); + if (city.isEmpty()) { + if (dev) PlotSystem.getPlugin().getComponentLogger().warn(text("getCurrentPlot: city not found for id=" + cityID)); + return null; + } + List plots = DataProvider.PLOT.getPlots(city.get(), statuses); + if (dev) PlotSystem.getPlugin().getComponentLogger().info(text("getCurrentPlot: candidate plots in city=" + city.get().getName(builder.isOnline() ? builder.getPlayer() : null) + ", count=" + plots.size())); if (plots.isEmpty()) return null; if (plots.size() == 1) return plots.getFirst(); @@ -132,177 +146,179 @@ public static AbstractPlot getCurrentPlot(@NotNull Builder builder, Status... st Location playerLoc = builder.getPlayer().getLocation().clone(); Vector3 playerVector = Vector3.at(playerLoc.getX(), playerLoc.getY(), playerLoc.getZ()); - double distance = 100000000; + double distance = Double.MAX_VALUE; Plot chosenPlot = plots.getFirst(); - for (Plot plot : plots) - if (plot.getPlotType() == PlotType.CITY_INSPIRATION_MODE && plot.getCenter().withY((int) playerVector.y()).distance(playerVector.toBlockPoint()) < distance) { - distance = plot.getCenter().distance(playerVector.toBlockPoint()); + for (Plot plot : plots) { + if (plot.getPlotType() != PlotType.CITY_INSPIRATION_MODE) continue; + BlockVector3 plotCenter = plot.getCenter(); + double currentDistance = plotCenter.withY((int) playerVector.y()).distance(playerVector.toBlockPoint()); + if (dev) PlotSystem.getPlugin().getComponentLogger().info(text("getCurrentPlot: candidate #" + plot.getId() + " center=" + plotCenter + " distance=" + currentDistance)); + if (currentDistance < distance) { + distance = currentDistance; chosenPlot = plot; } + } + if (dev) PlotSystem.getPlugin().getComponentLogger().info(text("getCurrentPlot: chosen plot id=" + chosenPlot.getId() + ", distance=" + distance)); return chosenPlot; + } else { + if (dev) PlotSystem.getPlugin().getComponentLogger().info(text("getCurrentPlot: world is not a plot world")); } + } else if (dev) { + PlotSystem.getPlugin().getComponentLogger().info(text("getCurrentPlot: builder is offline")); } return null; } - public static boolean isPlayerOnPlot(@NotNull AbstractPlot plot, Player player) throws SQLException { + public static boolean isPlayerOnPlot(@NotNull AbstractPlot plot, Player player) { if (plot.getWorld().isWorldLoaded() && plot.getWorld().getBukkitWorld().getPlayers().contains(player)) { Location playerLoc = player.getLocation(); - return plot.getWorld().getProtectedRegion().contains(Vector3.toBlockPoint(playerLoc.getX(), playerLoc.getY(), playerLoc.getZ())); + ProtectedRegion protectedRegion = plot.getWorld().getProtectedRegion(); + return protectedRegion == null || protectedRegion.contains(Vector3.toBlockPoint(playerLoc.getX(), playerLoc.getY(), playerLoc.getZ())); } return false; } - public static @Nullable CuboidRegion getPlotAsRegion(@NotNull AbstractPlot plot) throws IOException, SQLException { - try (Clipboard clipboard = Objects.requireNonNull(ClipboardFormats.findByFile(plot.getOutlinesSchematic())).load(plot.getOutlinesSchematic())) { + public static @Nullable CuboidRegion getPlotAsRegion(@NotNull AbstractPlot plot) throws IOException { + Clipboard clipboard; + try (ClipboardReader reader = AbstractPlot.CLIPBOARD_FORMAT.getReader(new ByteArrayInputStream(plot.getInitialSchematicBytes()))) { + clipboard = reader.read(); + } + if (clipboard == null) return null; - if (clipboard != null) { - if (plot.getVersion() >= 3) { - return new CuboidRegion( - clipboard.getMinimumPoint().withY(plot.getWorld().getPlotHeight()), - clipboard.getMaximumPoint().withY(PlotWorld.MAX_WORLD_HEIGHT)); - } else { - BlockVector3 plotCenter = plot.getCenter(); + // No longer supported! + if (plot.getVersion() < 4) return null; - // Calculate min and max points of schematic - int regionCenterModX = clipboard.getRegion().getWidth() % 2 == 0 ? 1 : 0; - int regionCenterModZ = clipboard.getRegion().getLength() % 2 == 0 ? 1 : 0; - int outlinesClipboardCenterX = (int) Math.floor(clipboard.getRegion().getWidth() / 2d); - int outlinesClipboardCenterZ = (int) Math.floor(clipboard.getRegion().getLength() / 2d); - - BlockVector3 schematicMinPoint = BlockVector3.at( - plotCenter.x() - (outlinesClipboardCenterX - regionCenterModX), - PlotWorld.MIN_WORLD_HEIGHT, - plotCenter.z() - (outlinesClipboardCenterZ - regionCenterModZ) - ); - - BlockVector3 schematicMaxPoint = BlockVector3.at( - plotCenter.x() + outlinesClipboardCenterX, - PlotWorld.MAX_WORLD_HEIGHT, - plotCenter.z() + outlinesClipboardCenterZ - ); - - return new CuboidRegion(schematicMinPoint, schematicMaxPoint); - } - } - } - return null; + return new CuboidRegion( + clipboard.getMinimumPoint().withY(plot.getWorld().getPlotHeight()), + clipboard.getMaximumPoint().withY(PlotWorld.MAX_WORLD_HEIGHT)); } - public static boolean isPlotWorld(World world) { - return PlotSystem.DependencyManager.getMultiverseCore().getMVWorldManager().isMVWorld(world) && (PlotWorld.isOnePlotWorld(world.getName()) || PlotWorld.isCityPlotWorld(world.getName())); + public static boolean isPlotWorld(@NotNull World world) { + return DependencyManager.getMultiverseCore().getWorldManager().isLoadedWorld(world) && (PlotWorld.isOnePlotWorld(world.getName()) || PlotWorld.isCityPlotWorld(world.getName())); } + public static byte @Nullable [] getOutlinesSchematicBytes(@NotNull AbstractPlot plot, World world) throws IOException { + Clipboard clipboard; + ByteArrayInputStream inputStream = new ByteArrayInputStream(plot.getInitialSchematicBytes()); + try (ClipboardReader reader = AbstractPlot.CLIPBOARD_FORMAT.getReader(inputStream)) { + clipboard = reader.read(); + } + + Polygonal2DRegion region = new Polygonal2DRegion( + BukkitAdapter.adapt(world), + plot.getOutline(), + clipboard.getMinimumPoint().y(), + clipboard.getMaximumPoint().y() + ); + + BlockArrayClipboard newClipboard = new BlockArrayClipboard(region); + newClipboard.setOrigin(BlockVector3.at(region.getCenter().x(), region.getMinimumPoint().y(), region.getCenter().z())); + ForwardExtentCopy copy = new ForwardExtentCopy( + clipboard, + region, + newClipboard, + region.getMinimumPoint() + ); + + Operations.complete(copy); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try (ClipboardWriter writer = AbstractPlot.CLIPBOARD_FORMAT.getWriter(outputStream)) { + writer.write(newClipboard); + } + return outputStream.toByteArray(); + } public static @NotNull String getDefaultSchematicPath() { return Paths.get(PlotSystem.getPlugin().getDataFolder().getAbsolutePath(), "schematics") + File.separator; } - public static boolean savePlotAsSchematic(@NotNull Plot plot) throws IOException, SQLException, WorldEditException { - Clipboard clipboard = Objects.requireNonNull(ClipboardFormats.findByFile(plot.getOutlinesSchematic())).load(plot.getOutlinesSchematic()); - if (clipboard != null) { - CuboidRegion cuboidRegion = getPlotAsRegion(plot); - - if (cuboidRegion != null) { - // Get plot outline - List plotOutlines = plot.getOutline(); - - // Load finished plot region as cuboid region - if (plot.getWorld().loadWorld()) { - com.sk89q.worldedit.world.World world = new BukkitWorld(plot.getWorld().getBukkitWorld()); - Polygonal2DRegion region = new Polygonal2DRegion(world, plotOutlines, cuboidRegion.getMinimumPoint().y(), cuboidRegion.getMaximumPoint().y()); - - File finishedSchematicFile = getFinalFile(plot, region, cuboidRegion, clipboard); - if (finishedSchematicFile == null) return false; - - // Upload to FTP server - if (plot.getCity().getCountry().getServer().getFTPConfiguration() != null) { - CompletableFuture.supplyAsync(() -> { - try { - return FTPManager.uploadSchematic(FTPManager.getFTPUrl(plot.getCity().getCountry().getServer(), plot.getCity().getID()), finishedSchematicFile); - } catch (SQLException | URISyntaxException ex) { - Utils.logSqlException(ex); - } - return null; - }); - } - - // If plot was created in a void world, copy the result to the city world - if (plot.getPlotType() != PlotType.CITY_INSPIRATION_MODE && plot.getVersion() >= 3) { - AbstractPlotGenerator.pasteSchematic(null, plot.getCompletedSchematic(), new CityPlotWorld(plot), false); - } - return true; - } - } + public static boolean savePlotAsSchematic(@NotNull Plot plot) throws IOException, WorldEditException { + if (plot.getVersion() < 4) { + PlotSystem.getPlugin().getComponentLogger().error(text("Saving schematics of legacy plots is no longer allowed!")); + return false; } - return false; - } - private static @Nullable File getFinalFile(@NotNull Plot plot, Polygonal2DRegion region, CuboidRegion cuboidRegion, Clipboard clipboard) throws SQLException, IOException { - // Copy and write finished plot clipboard to schematic file - File finishedSchematicFile = Paths.get(PlotUtils.getDefaultSchematicPath(), - String.valueOf(plot.getCity().getCountry().getServer().getID()), - "finishedSchematics", String.valueOf(plot.getCity().getID()), plot.getID() + SCHEM_ENDING).toFile(); - - if (!finishedSchematicFile.exists()) { - boolean createdDirs = finishedSchematicFile.getParentFile().mkdirs(); - boolean createdFile = finishedSchematicFile.createNewFile(); - if ((!finishedSchematicFile.getParentFile().exists() && !createdDirs) || (!finishedSchematicFile.exists() && !createdFile)) { - return null; - } + Clipboard clipboard; + ByteArrayInputStream inputStream = new ByteArrayInputStream(plot.getInitialSchematicBytes()); + try (ClipboardReader reader = AbstractPlot.CLIPBOARD_FORMAT.getReader(inputStream)) { + clipboard = reader.read(); } + if (clipboard == null) return false; + + CuboidRegion cuboidRegion = getPlotAsRegion(plot); + if (cuboidRegion == null) return false; + BlockVector3 plotCenter = plot.getCenter(); + + // Get plot outline + List plotOutlines = plot.getOutline(); + + // Load finished plot region as cuboid region + if (!plot.getWorld().loadWorld()) return false; + com.sk89q.worldedit.world.World world = new BukkitWorld(plot.getWorld().getBukkitWorld()); + Polygonal2DRegion region = new Polygonal2DRegion(world, plotOutlines, cuboidRegion.getMinimumPoint().y(), cuboidRegion.getMaximumPoint().y()); + + // Copy and write finished plot clipboard to schematic + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); try (Clipboard cb = new BlockArrayClipboard(region)) { - if (plot.getVersion() >= 3) { - cb.setOrigin(BlockVector3.at(plot.getCenter().x(), cuboidRegion.getMinimumY(), (double) plot.getCenter().z())); - } else { - BlockVector3 terraCenter = plot.getCoordinates(); - cb.setOrigin(BlockVector3.at( - (double) terraCenter.x() - (double) clipboard.getMinimumPoint().x() + cuboidRegion.getMinimumPoint().x(), - (double) terraCenter.y() - (double) clipboard.getMinimumPoint().y() + cuboidRegion.getMinimumPoint().y(), - (double) terraCenter.z() - (double) clipboard.getMinimumPoint().z() + cuboidRegion.getMinimumPoint().z() - )); - } + cb.setOrigin(BlockVector3.at(plotCenter.x(), cuboidRegion.getMinimumY(), (double) plotCenter.z())); ForwardExtentCopy forwardExtentCopy = new ForwardExtentCopy(Objects.requireNonNull(region.getWorld()), region, cb, region.getMinimumPoint()); Operations.complete(forwardExtentCopy); - try (ClipboardWriter writer = BuiltInClipboardFormat.FAST_V2.getWriter(new FileOutputStream(finishedSchematicFile, false))) { - writer.write(cb); + try (ClipboardWriter writer = AbstractPlot.CLIPBOARD_FORMAT.getWriter(outputStream)) { + double initialY = clipboard.getRegion().getMinimumY(); + double offset = initialY - cuboidRegion.getMinimumY(); + writer.write(cb.transform(new AffineTransform().translate(Vector3.at(0, offset, 0)))); } } - return finishedSchematicFile; + + // Set Completed Schematic + boolean successful = DataProvider.PLOT.setCompletedSchematic(plot.getId(), outputStream.toByteArray()); + if (!successful) return false; + + // If plot was created in a void world, copy the result to the city world + if (plot.getPlotType() != PlotType.CITY_INSPIRATION_MODE) { + var cpw = new CityPlotWorld(plot); + Mask airMask = new BlockTypeMask(BukkitAdapter.adapt(cpw.getBukkitWorld()), BlockTypes.AIR); + AbstractPlotGenerator.pasteSchematic(airMask, outputStream.toByteArray(), cpw, false, true); + } + return true; } - public static @Nullable CompletableFuture convertTerraToPlotXZ(@NotNull AbstractPlot plot, double[] terraCoords) throws IOException, SQLException { + public static @Nullable CompletableFuture convertTerraToPlotXZ(@NotNull AbstractPlot plot, double[] terraCoords) throws IOException { // Load plot outlines schematic as clipboard - try (Clipboard clipboard = Objects.requireNonNull(ClipboardFormats.findByFile(plot.getOutlinesSchematic())).load(plot.getOutlinesSchematic())) { - - if (clipboard != null) { - // Calculate min and max points of schematic - CuboidRegion plotRegion = getPlotAsRegion(plot); - - if (plotRegion != null) { - // Convert terra schematic coordinates into relative plot schematic coordinates - double[] schematicCoords = { - terraCoords[0] - clipboard.getMinimumPoint().x(), - terraCoords[1] - clipboard.getMinimumPoint().z() - }; - - // Add additional plot sizes to relative plot schematic coordinates - double[] plotCoords = { - schematicCoords[0] + plotRegion.getMinimumPoint().x(), - schematicCoords[1] + plotRegion.getMinimumPoint().z() - }; - - // Return coordinates if they are in the schematic plot region - ProtectedRegion protectedPlotRegion = plot.getWorld().getProtectedRegion() != null ? plot.getWorld().getProtectedRegion() : plot.getWorld().getProtectedBuildRegion(); - if (protectedPlotRegion.contains(BlockVector3.at((int) plotCoords[0], plot.getWorld().getPlotHeightCentered(), (int) plotCoords[1]))) { - return CompletableFuture.completedFuture(plotCoords); - } - } - } + Clipboard clipboard; + ByteArrayInputStream inputStream = new ByteArrayInputStream(plot.getInitialSchematicBytes()); + try (ClipboardReader reader = AbstractPlot.CLIPBOARD_FORMAT.getReader(inputStream)) { + clipboard = reader.read(); + } + if (clipboard == null) return null; + + // Calculate min and max points of schematic + CuboidRegion plotRegion = getPlotAsRegion(plot); + if (plotRegion == null) return null; + + // Convert terra schematic coordinates into relative plot schematic coordinates + double[] schematicCoords = { + terraCoords[0] - clipboard.getMinimumPoint().x(), + terraCoords[1] - clipboard.getMinimumPoint().z() + }; + + // Add additional plot sizes to relative plot schematic coordinates + double[] plotCoords = { + schematicCoords[0] + plotRegion.getMinimumPoint().x(), + schematicCoords[1] + plotRegion.getMinimumPoint().z() + }; + + // Return coordinates if they are in the schematic plot region + ProtectedRegion protectedPlotRegion = plot.getWorld().getProtectedRegion() != null + ? plot.getWorld().getProtectedRegion() + : plot.getWorld().getProtectedBuildRegion(); + if (protectedPlotRegion.contains(BlockVector3.at((int) plotCoords[0], plot.getWorld().getPlotHeightCentered(), (int) plotCoords[1]))) { + return CompletableFuture.completedFuture(plotCoords); } return null; @@ -310,66 +326,50 @@ public static boolean savePlotAsSchematic(@NotNull Plot plot) throws IOException public static void checkPlotsForLastActivity() { Bukkit.getScheduler().runTaskTimerAsynchronously(PlotSystem.getPlugin(), () -> { - try { - List plots = Plot.getPlots(Status.unfinished); - FileConfiguration config = PlotSystem.getPlugin().getConfig(); - long millisInDays = config.getLong(ConfigPaths.INACTIVITY_INTERVAL) * 24 * 60 * 60 * 1000; // Remove all plots which have no activity for the last x days + List plots = DataProvider.PLOT.getPlots(Status.unfinished); + FileConfiguration config = PlotSystem.getPlugin().getConfig(); + long inactivityIntervalDays = config.getLong(ConfigPaths.INACTIVITY_INTERVAL); + long rejectedInactivityIntervalDays = (config.getLong(ConfigPaths.REJECTED_INACTIVITY_INTERVAL) != -1) ? config.getLong(ConfigPaths.REJECTED_INACTIVITY_INTERVAL) : inactivityIntervalDays; + if (inactivityIntervalDays == -2 && rejectedInactivityIntervalDays == -2) return; + for (Plot plot : plots) { + LocalDate lastActivity = plot.getLastActivity(); + long interval = plot.isRejected() ? rejectedInactivityIntervalDays : inactivityIntervalDays; + if (interval == -2 || lastActivity == null || lastActivity.plusDays(interval).isAfter(LocalDate.now())) continue; - for (Plot plot : plots) { - if (plot.getLastActivity() != null && plot.getLastActivity().getTime() < (new Date().getTime() - millisInDays)) { - Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { - if (Actions.abandonPlot(plot)) { - PlotSystem.getPlugin().getComponentLogger().info(text("Abandoned plot #" + plot.getID() + " due to inactivity!")); - } else { - PlotSystem.getPlugin().getComponentLogger().warn(text("An error occurred while abandoning plot #" + plot.getID() + " due to inactivity!")); - } - }); + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + if (Actions.abandonPlot(plot)) { + PlotSystem.getPlugin().getComponentLogger().info(text("Abandoned plot #" + plot.getId() + " due to inactivity!")); + } else { + PlotSystem.getPlugin().getComponentLogger().warn(text("An error occurred while abandoning plot #" + plot.getId() + " due to inactivity!")); } - } - } catch (SQLException ex) { - Utils.logSqlException(ex); + }); } }, 0L, 20 * 60 * 60L); // Check every hour } - public static void syncPlotSchematicFiles() { - FileConfiguration config = PlotSystem.getPlugin().getConfig(); - if (config.getBoolean(ConfigPaths.SYNC_FTP_FILES_ENABLE)) { - long interval = config.getLong(ConfigPaths.SYNC_FTP_FILES_INTERVAL); - - Bukkit.getScheduler().runTaskTimerAsynchronously(PlotSystem.getPlugin(), () -> CityProject.getCityProjects(false).forEach(c -> { - try { - if (c.getCountry().getServer().getFTPConfiguration() != null) { - List plots = Plot.getPlots(c.getID(), Status.unclaimed); - plots.forEach(Plot::getOutlinesSchematic); - } - } catch (SQLException ex) { - Utils.logSqlException(ex); - } - }), 0L, 20 * interval); + public static void informPlayerAboutUnfinishedPlots(@NotNull Player player, Builder builder) { + try { + List plots = Cache.getCachedInProgressPlots(builder); + if (plots.isEmpty()) return; + ChatFormatting.sendUnfinishedPlotReminderMessage(plots, player); + } catch (Exception ex) { + PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while trying to inform the player about his unfinished plots!"), ex); } } - public static boolean plotExists(int id) { - try (ResultSet rs = DatabaseConnection.createStatement("SELECT COUNT(id) FROM plotsystem_plots WHERE id = ?") - .setValue(id).executeQuery()) { - - if (rs.next() && rs.getInt(1) > 0) { - DatabaseConnection.closeResultSet(rs); - return true; - } - - DatabaseConnection.closeResultSet(rs); - } catch (SQLException ex) { - Utils.logSqlException(ex); - } - return false; + public static void startUnfinishedPlotReminderTimer(Player player) { + int interval = PlotSystem.getPlugin().getConfig().getInt(ConfigPaths.UNFINISHED_REMINDER_INTERVAL); + if (interval == -1) return; + plotReminder.put(player.getUniqueId(), Bukkit.getScheduler().runTaskTimerAsynchronously(PlotSystem.getPlugin(), + () -> informPlayerAboutUnfinishedPlots(player, Builder.byUUID(player.getUniqueId())), + 20L * 60 * interval, + 20L * 60 * interval)); } public static final class Actions { private Actions() {} - public static void submitPlot(@NotNull Plot plot) throws SQLException { + public static void submitPlot(@NotNull Plot plot) { plot.setStatus(Status.unreviewed); if (plot.getWorld().isWorldLoaded()) { @@ -386,7 +386,7 @@ public static void submitPlot(@NotNull Plot plot) throws SQLException { } } - public static void undoSubmit(@NotNull Plot plot) throws SQLException { + public static void undoSubmit(@NotNull Plot plot) { plot.setStatus(Status.unfinished); plot.getPermissions().addBuilderPerms(plot.getPlotOwner().getUUID()).save(); @@ -424,95 +424,64 @@ public static boolean abandonPlot(@NotNull AbstractPlot plot) { if (regionManager.hasRegion(world.getRegionName())) regionManager.removeRegion(world.getRegionName()); if (regionManager.hasRegion(world.getRegionName() + "-1")) regionManager.removeRegion(world.getRegionName() + "-1"); - AbstractPlotGenerator.pasteSchematic(null, plot.getOutlinesSchematic(), world, true); + AbstractPlotGenerator.pasteSchematic(null, getOutlinesSchematicBytes(plot, world.getBukkitWorld()), world, true, false); } else PlotSystem.getPlugin().getComponentLogger().warn(text("Region Manager is null!")); playersToTeleport.forEach(p -> p.teleport(Utils.getSpawnLocation())); if (plot.getWorld().isWorldLoaded()) plot.getWorld().unloadWorld(false); } } - } catch (SQLException | IOException | WorldEditException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("Failed to abandon plot with the ID " + plot.getID() + "!"), ex); + } catch (IOException | WorldEditException ex) { + PlotSystem.getPlugin().getComponentLogger().error(text("Failed to abandon plot with the ID " + plot.getId() + "!"), ex); return false; } - return updateDatabase(plot); - } - private static boolean updateDatabase(@NotNull AbstractPlot plot) { - try { - CompletableFuture.runAsync(() -> { - try { - if (plot.getPlotType() != PlotType.TUTORIAL) { - Plot dPlot = (Plot) plot; - if (dPlot.isReviewed()) { - DatabaseConnection.createStatement("UPDATE plotsystem_plots SET review_id = DEFAULT(review_id) WHERE id = ?") - .setValue(plot.getID()).executeUpdate(); - - DatabaseConnection.createStatement("DELETE FROM plotsystem_reviews WHERE id = ?") - .setValue(dPlot.getReview().getReviewID()).executeUpdate(); - } + CompletableFuture.runAsync(() -> { + if (plot.getPlotType() == PlotType.TUTORIAL) return; + Plot dPlot = (Plot) plot; + boolean successful; + successful = DataProvider.REVIEW.removeAllReviewsOfPlot(dPlot.getId()); - for (Builder builder : dPlot.getPlotMembers()) dPlot.removePlotMember(builder); + for (Builder builder : dPlot.getPlotMembers()) { + if (!successful) break; + successful = dPlot.removePlotMember(builder); + } - if (plot.getPlotOwner() != null) { - Cache.clearCache(plot.getPlotOwner().getUUID()); - plot.getPlotOwner().removePlot(dPlot.getSlot()); - } + if (successful && plot.getPlotOwner() != null) { + Cache.clearCache(plot.getPlotOwner().getUUID()); + successful = plot.getPlotOwner().setSlot(plot.getPlotOwner().getSlot(dPlot), -1); + } - dPlot.setPlotOwner(null); - dPlot.setLastActivity(true); - dPlot.setTotalScore(-1); - dPlot.setStatus(Status.unclaimed); - dPlot.setPlotType(PlotType.LOCAL_INSPIRATION_MODE); - } - } catch (SQLException ex) { - Utils.logSqlException(ex); - throw new CompletionException(ex); - } - }).join(); - } catch (CompletionException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("Failed to abandon plot with the ID " + plot.getID() + "!"), ex); - return false; - } + if (successful) { + successful = dPlot.setPlotOwner(null) + && dPlot.setLastActivity(true) + && dPlot.setStatus(Status.unclaimed) + && dPlot.setPlotType(PlotType.LOCAL_INSPIRATION_MODE); + } + + successful = successful && DataProvider.PLOT.setCompletedSchematic(plot.getId(), null); + + if (!successful) PlotSystem.getPlugin().getComponentLogger().error(text("Failed to abandon plot with the ID " + plot.getId() + "!")); + }); return true; } public static boolean deletePlot(Plot plot) { if (abandonPlot(plot)) { - try { - CompletableFuture.runAsync(() -> { - try { - Server plotServer = plot.getCity().getCountry().getServer(); - - Files.deleteIfExists(Paths.get(PlotUtils.getDefaultSchematicPath(), String.valueOf(plotServer.getID()), "finishedSchematics", String.valueOf(plot.getCity().getID()), plot.getID() + SCHEMATIC_ENDING)); - Files.deleteIfExists(Paths.get(PlotUtils.getDefaultSchematicPath(), String.valueOf(plotServer.getID()), String.valueOf(plot.getCity().getID()), plot.getID() + SCHEMATIC_ENDING)); - Files.deleteIfExists(Paths.get(PlotUtils.getDefaultSchematicPath(), String.valueOf(plotServer.getID()), String.valueOf(plot.getCity().getID()), plot.getID() + "-env" + SCHEMATIC_ENDING)); - - if (plotServer.getFTPConfiguration() != null) { - FTPManager.deleteSchematic(FTPManager.getFTPUrl(plotServer, plot.getCity().getID()), plot.getID() + SCHEMATIC_ENDING); - FTPManager.deleteSchematic(FTPManager.getFTPUrl(plotServer, plot.getCity().getID()).replaceFirst("finishedSchematics/", ""), plot.getID() + SCHEMATIC_ENDING); - FTPManager.deleteSchematic(FTPManager.getFTPUrl(plotServer, plot.getCity().getID()).replaceFirst("finishedSchematics/", ""), plot.getID() + "-env" + SCHEMATIC_ENDING); - } - - DatabaseConnection.createStatement("DELETE FROM plotsystem_plots WHERE id = ?") - .setValue(plot.getID()).executeUpdate(); - } catch (IOException | SQLException | URISyntaxException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text(ex.getMessage()), ex); - throw new CompletionException(ex); - } - }); - } catch (CompletionException ex) { - return false; - } + CompletableFuture.runAsync(() -> { + if (DataProvider.PLOT.deletePlot(plot.getId())) return; + PlotSystem.getPlugin().getComponentLogger().warn(text("Failed to abandon plot with the ID " + plot.getId() + "!")); + }); return true; } - PlotSystem.getPlugin().getComponentLogger().warn(text("Failed to delete plot with the ID " + plot.getID() + "!")); + PlotSystem.getPlugin().getComponentLogger().warn(text("Failed to abandon plot with the ID " + plot.getId() + "!")); return false; } } public static final class Cache { private Cache() {} + private static final HashMap> cachedInProgressPlots = new HashMap<>(); public static void clearCache() { @@ -525,12 +494,7 @@ public static void clearCache(UUID builderUUID) { public static List getCachedInProgressPlots(@NotNull Builder builder) { if (!cachedInProgressPlots.containsKey(builder.getUUID())) { - try { - cachedInProgressPlots.put(builder.getUUID(), Plot.getPlots(builder, Status.unfinished)); - } catch (SQLException ex) { - Utils.logSqlException(ex); - return new ArrayList<>(); - } + cachedInProgressPlots.put(builder.getUUID(), DataProvider.PLOT.getPlots(builder, Status.unfinished)); } return cachedInProgressPlots.get(builder.getUUID()); @@ -543,28 +507,29 @@ public static Map> getCachedInProgressPlots() { public static final class Effects { private Effects() {} + public static final int CACHE_UPDATE_TICKS = 20 * 60; private static int time; private static boolean particleAPIEnabled = false; - private static Particles_1_8 particles; + private static Particles_1_13 particles; public static void loadParticleNativeAPI() { - particleAPIEnabled = PlotSystem.DependencyManager.isParticleNativeAPIEnabled(); + particleAPIEnabled = DependencyManager.isParticleNativeAPIEnabled(); // get API ParticleNativeAPI api = ParticleNativePlugin.getAPI(); // choose particle list you want to use - particles = api.getParticles_1_8(); + particles = api.getParticles_1_13(); } public static void startTimer() { - if (PlotSystem.DependencyManager.isParticleNativeAPIEnabled()) + if (DependencyManager.isParticleNativeAPIEnabled()) loadParticleNativeAPI(); Bukkit.getScheduler().scheduleSyncDelayedTask(PlotSystem.getPlugin(), () -> { - if (PlotSystem.DependencyManager.isParticleNativeAPIEnabled()) + if (DependencyManager.isParticleNativeAPIEnabled()) loadParticleNativeAPI(); }, 20 * 10L); @@ -579,46 +544,43 @@ public static void tick() { } public static void showOutlines() { - try { - for (Player player : Bukkit.getOnlinePlayers()) { - Builder builder = Builder.byUUID(player.getUniqueId()); + for (Player player : Bukkit.getOnlinePlayers()) { + Builder builder = Builder.byUUID(player.getUniqueId()); - List plots = Cache.getCachedInProgressPlots(builder); - BlockVector2 playerPos2D = BlockVector2.at(player.getLocation().getX(), player.getLocation().getZ()); + List plots = Cache.getCachedInProgressPlots(builder); + BlockVector2 playerPos2D = BlockVector2.at(player.getLocation().getX(), player.getLocation().getZ()); - if (plots.isEmpty()) continue; + if (plots.isEmpty()) continue; - for (Plot plot : plots) { - if ((!plot.getWorld().getWorldName().equals(player.getWorld().getName())) || - (!plot.getPlotOwner().getPlotTypeSetting().hasEnvironment() || plot.getVersion() <= 2)) { - continue; - } + for (Plot plot : plots) { + if ((!plot.getWorld().getWorldName().equals(player.getWorld().getName())) || + (!plot.getPlotOwner().getPlotType().hasEnvironment() || plot.getVersion() <= 2)) { + continue; + } - List points = plot.getBlockOutline(); + List points = plot.getBlockOutline(); - for (BlockVector2 point : points) - if (point.distanceSq(playerPos2D) < 50 * 50) { - if (!particleAPIEnabled) { - player.spawnParticle(Particle.FLAME, point.x(), player.getLocation().getY() + 1, point.z(), 1, 0.0, 0.0, 0.0, 0); - } else { - Location loc = new Location(player.getWorld(), point.x(), player.getLocation().getY() + 1, point.z()); - // create a particle packet - Object packet = particles.FLAME().packet(true, loc); + for (BlockVector2 point : points) + if (point.distanceSq(playerPos2D) < 50 * 50) { + if (!particleAPIEnabled) { + player.spawnParticle(Particle.FLAME, point.x(), player.getLocation().getY() + 1, point.z(), 1, 0.0, 0.0, 0.0, 0); + } else { + Location loc = new Location(player.getWorld(), point.x(), player.getLocation().getY() + 1, point.z()); + // create a particle packet + Object packet = particles.FLAME().packet(true, loc); - // send this packet to player - particles.sendPacket(player, packet); - } + // send this packet to player + particles.sendPacket(player, packet); } - } + } } - } catch (SQLException | IOException ex) { - Utils.logSqlException(ex); } } } public static final class ChatFormatting { private ChatFormatting() {} + public static void sendLinkMessages(AbstractPlot plot, Player player) { Bukkit.getScheduler().runTaskAsynchronously(PlotSystem.getPlugin(), () -> { Component[] tc = new Component[3]; @@ -679,32 +641,31 @@ public static void sendLinkMessages(AbstractPlot plot, Player player) { } public static void sendGroupTipMessage(@NotNull Plot plot, Player player) { - try { - if (plot.getPlotMembers().isEmpty()) { - Component tc = text("» ", DARK_GRAY) - .append(text(LangUtil.getInstance().get(player, LangPaths.Note.Action.CLICK_TO_PLAY_WITH_FRIENDS), GRAY)) - .clickEvent(ClickEvent.runCommand("/plot members " + plot.getID())) - .hoverEvent(text(LangUtil.getInstance().get(player, LangPaths.Plot.MEMBERS))); - - player.sendMessage(tc); - player.sendMessage(text(MSG_LINE, DARK_GRAY)); - } - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text(ex.getMessage()), ex); + if (plot.getPlotMembers().isEmpty() && PlotSystem.getPlugin().getConfig().getBoolean(ConfigPaths.ENABLE_GROUP_SUPPORT)) { + Component tc = text("» ", DARK_GRAY) + .append(text(LangUtil.getInstance().get(player, LangPaths.Note.Action.CLICK_TO_PLAY_WITH_FRIENDS), GRAY)) + .clickEvent(ClickEvent.runCommand("/plot members " + plot.getId())) + .hoverEvent(text(LangUtil.getInstance().get(player, LangPaths.Plot.MEMBERS))); + + player.sendMessage(tc); + player.sendMessage(text(MSG_LINE, DARK_GRAY)); } } - public static void sendFeedbackMessage(@NotNull List plots, @NotNull Player player) { + public static void sendFeedbackMessage(@NotNull List notifications, @NotNull Player player) { player.sendMessage(text(MSG_LINE, DARK_GRAY)); - for (Plot plot : plots) { - player.sendMessage(text("» ", DARK_GRAY).append(text(LangUtil.getInstance().get(player, LangPaths.Message.Info.REVIEWED_PLOT, String.valueOf(plot.getID())), GREEN))); + for (ReviewNotification notification : notifications) { + PlotReview review = DataProvider.REVIEW.getReview(notification.reviewId()).orElseThrow(); + player.sendMessage(text("» ", DARK_GRAY).append(text(LangUtil.getInstance().get(player, LangPaths.Message.Info.REVIEWED_PLOT, String.valueOf(review.getPlot().getId())), GREEN))); Component tc = text(LangUtil.getInstance().get(player, LangPaths.Note.Action.CLICK_TO_SHOW_FEEDBACK), GOLD) - .clickEvent(ClickEvent.runCommand("/plot feedback " + plot.getID())) + .clickEvent(ClickEvent.runCommand("/plot feedback " + review.getPlot().getId())) .hoverEvent(text(LangUtil.getInstance().get(player, LangPaths.Plot.PLOT_NAME) + " " + LangUtil.getInstance().get(player, LangPaths.Review.FEEDBACK))); player.sendMessage(tc); - if (plots.size() != plots.indexOf(plot) + 1) { + DataProvider.REVIEW.removeReviewNotification(notification.reviewId(), notification.uuid()); + + if (notifications.size() != notifications.indexOf(notification) + 1) { player.sendMessage(empty()); } } @@ -728,7 +689,8 @@ public static void sendUnreviewedPlotsReminderMessage(@NotNull List plots, Component tc = text(LangUtil.getInstance().get(player, LangPaths.Note.Action.CLICK_TO_SHOW_OPEN_REVIEWS), GOLD) .clickEvent(ClickEvent.runCommand("/review")) - .hoverEvent(text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.SHOW_PLOTS))); + .hoverEvent(text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.SHOW_PLOTS))) + .appendNewline(); player.sendMessage(tc); } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/CityPlotWorld.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/CityPlotWorld.java index 177f4a319..d37dcccc1 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/CityPlotWorld.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/CityPlotWorld.java @@ -1,30 +1,6 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.world; -import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; import com.alpsbte.plotsystem.utils.Utils; @@ -32,53 +8,46 @@ import com.alpsbte.plotsystem.utils.io.LangUtil; import com.google.common.annotations.Beta; import com.sk89q.worldedit.extent.clipboard.Clipboard; -import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import java.io.ByteArrayInputStream; import java.io.IOException; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; -import java.util.Objects; - -import static net.kyori.adventure.text.Component.text; public class CityPlotWorld extends PlotWorld { - public CityPlotWorld(@NotNull Plot plot) throws SQLException { - super("C-" + plot.getCity().getID(), plot); + public CityPlotWorld(@NotNull Plot plot) { + super("C-" + plot.getCityProject().getId(), plot); } @Override public boolean teleportPlayer(@NotNull Player player) { if (super.teleportPlayer(player)) { - try { - player.playSound(player.getLocation(), Utils.SoundUtils.TELEPORT_SOUND, 1, 1); - player.setAllowFlight(true); - player.setFlying(true); + player.playSound(player.getLocation(), Utils.SoundUtils.TELEPORT_SOUND, 1, 1); + player.setAllowFlight(true); + player.setFlying(true); - if (getPlot() != null) { - player.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(player, LangPaths.Message.Info.TELEPORTING_PLOT, String.valueOf(getPlot().getID())))); + if (getPlot() != null) { + player.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(player, LangPaths.Message.Info.TELEPORTING_PLOT, String.valueOf(getPlot().getId())))); - Utils.updatePlayerInventorySlots(player); - PlotUtils.ChatFormatting.sendLinkMessages(getPlot(), player); + Utils.updatePlayerInventorySlots(player); + PlotUtils.ChatFormatting.sendLinkMessages(getPlot(), player); - if (getPlot().getPlotOwner().getUUID().equals(player.getUniqueId())) { - getPlot().setLastActivity(false); - } + if (getPlot().getPlotOwner().getUUID().equals(player.getUniqueId())) { + getPlot().setLastActivity(false); } - - return true; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); } + + return true; } return false; } @Override public String getRegionName() { - return super.getRegionName() + "-" + getPlot().getID(); + return super.getRegionName() + "-" + getPlot().getId(); } @@ -102,26 +71,28 @@ public int getPlotHeightCentered() throws IOException { */ @Beta public int getWorldHeight() throws IOException { - try (Clipboard clipboard = Objects.requireNonNull(ClipboardFormats.findByFile(getPlot().getOutlinesSchematic())).load(getPlot().getOutlinesSchematic())) { - - if (clipboard != null) { - int plotHeight = clipboard.getMinimumPoint().y(); - - /// Minimum building height for a plot (this should be configurable depending on minecraft build limit) - /// This is in the case that a plot is created at y level 300 where the max build limit is 318, - /// so you don't want builder to only be able to build for 18 blocks - int minBuildingHeight = 128; - - /// Negative y level of the current minecraft version (1.21) - /// Additional ground layer the plot use to save as schematic need to be included for plot's y-level - int groundLayer = 64; - - // Plots created outside of vanilla build limit or the build-able height is too small - if (plotHeight + groundLayer < MIN_WORLD_HEIGHT + groundLayer - || plotHeight + groundLayer + minBuildingHeight > MAX_WORLD_HEIGHT + groundLayer) - return 0; // throw new IOException("Plot height is out of range."); - return plotHeight; - } + Clipboard clipboard; + ByteArrayInputStream inputStream = new ByteArrayInputStream(getPlot().getInitialSchematicBytes()); + try (ClipboardReader reader = AbstractPlot.CLIPBOARD_FORMAT.getReader(inputStream)) { + clipboard = reader.read(); + } + if (clipboard != null) { + int plotHeight = clipboard.getMinimumPoint().y(); + + // Minimum building height for a plot (this should be configurable depending on minecraft build limit) + // This is in the case that a plot is created at y level 300 where the max build limit is 318, + // so you don't want builder to only be able to build for 18 blocks + int minBuildingHeight = 128; + + // Negative y level of the current minecraft version (1.21) + // Additional ground layer the plot use to save as schematic need to be included for plot's y-level + int groundLayer = 64; + + // Plots created outside of vanilla build limit or the build-able height is too small + if (plotHeight + groundLayer < MIN_WORLD_HEIGHT + groundLayer + || plotHeight + groundLayer + minBuildingHeight > MAX_WORLD_HEIGHT + groundLayer) + return 0; // throw new IOException("Plot height is out of range."); + return plotHeight; } throw new IOException("A Plot's Outline schematic fails to load, cannot get clipboard."); } @@ -131,7 +102,7 @@ public int getWorldHeight() throws IOException { * * @return a list of players located on the plot */ - public List getPlayersOnPlot() throws SQLException { + public List getPlayersOnPlot() { List players = new ArrayList<>(); if (getPlot() != null && getPlot().getWorld().isWorldLoaded() && !getPlot().getWorld().getBukkitWorld().getPlayers().isEmpty()) { for (Player player : getPlot().getWorld().getBukkitWorld().getPlayers()) { @@ -141,4 +112,4 @@ public List getPlayersOnPlot() throws SQLException { } return players; } -} +} \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/IWorld.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/IWorld.java index e03f75de2..bf5cf74ac 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/IWorld.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/IWorld.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021-2022, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.world; import com.alpsbte.plotsystem.core.system.plot.generator.AbstractPlotGenerator; @@ -33,7 +9,6 @@ import org.jetbrains.annotations.NotNull; import java.io.IOException; -import java.sql.SQLException; public interface IWorld { /** @@ -96,7 +71,7 @@ public interface IWorld { * @return the origin Y value * @throws IOException if the outline schematic fails to load */ - int getPlotHeight() throws IOException, SQLException; + int getPlotHeight() throws IOException; /** * Calculates the centered Y value in the plot world diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/OnePlotWorld.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/OnePlotWorld.java index e97b4a23a..2f439becf 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/OnePlotWorld.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/OnePlotWorld.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.world; import com.alpsbte.plotsystem.PlotSystem; @@ -30,29 +6,25 @@ import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.TutorialPlot; import com.alpsbte.plotsystem.core.system.plot.generator.AbstractPlotGenerator; +import com.alpsbte.plotsystem.core.system.plot.generator.DefaultPlotGenerator; import com.alpsbte.plotsystem.core.system.plot.generator.TutorialPlotGenerator; import com.alpsbte.plotsystem.core.system.plot.utils.PlotType; -import com.alpsbte.plotsystem.core.system.plot.generator.DefaultPlotGenerator; import com.alpsbte.plotsystem.core.system.plot.utils.PlotUtils; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.sk89q.worldedit.WorldEditException; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import java.io.File; import java.io.IOException; -import java.sql.SQLException; import static net.kyori.adventure.text.Component.text; public class OnePlotWorld extends PlotWorld { private final Builder plotOwner; - public OnePlotWorld(@NotNull AbstractPlot plot) throws SQLException { - super((plot instanceof TutorialPlot ? "T-" : "P-") + plot.getID(), plot); + public OnePlotWorld(@NotNull AbstractPlot plot) { + super((plot instanceof TutorialPlot ? "T-" : "P-") + plot.getId(), plot); this.plotOwner = plot.getPlotOwner(); } @@ -60,17 +32,12 @@ public OnePlotWorld(@NotNull AbstractPlot plot) throws SQLException { public boolean generateWorld(@NotNull Class generator) { if (isWorldGenerated()) return false; - try { - if (generator.isAssignableFrom(DefaultPlotGenerator.class)) { - new DefaultPlotGenerator(getPlot(), plotOwner); - } else if (generator.isAssignableFrom(TutorialPlotGenerator.class)) { - new TutorialPlotGenerator(getPlot(), plotOwner); - } else return false; - return true; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - return false; + if (generator.isAssignableFrom(DefaultPlotGenerator.class)) { + new DefaultPlotGenerator(getPlot(), plotOwner); + } else if (generator.isAssignableFrom(TutorialPlotGenerator.class)) { + new TutorialPlotGenerator(getPlot(), plotOwner); + } else return false; + return true; } @Override @@ -78,34 +45,24 @@ public boolean loadWorld() { if (getPlot() == null || isWorldGenerated()) return super.loadWorld(); // Generate plot if it doesn't exist - try { - if (getPlot().getPlotType() == PlotType.TUTORIAL || - !((Plot) getPlot()).getCompletedSchematic().exists()) - generateWorld(TutorialPlotGenerator.class); - - new DefaultPlotGenerator(getPlot(), plotOwner, getPlot().getPlotType()) { - @Override - protected void generateOutlines(@NotNull File plotSchematic, @Nullable File environmentSchematic) throws SQLException, IOException, WorldEditException { - super.generateOutlines(((Plot) getPlot()).getCompletedSchematic(), environmentSchematic); - } - - @Override - protected boolean init() { - return true; - } - - @Override - protected void onComplete(boolean failed, boolean unloadWorld) throws SQLException { - getPlot().getPermissions().clearAllPerms(); - super.onComplete(true, false); - } - }; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + if (getPlot().getPlotType() == PlotType.TUTORIAL || ((Plot) getPlot()).getCompletedSchematic() == null) + generateWorld(TutorialPlotGenerator.class); + + new DefaultPlotGenerator(getPlot(), plotOwner, getPlot().getPlotType()) { + @Override + protected boolean init() { + return true; + } + + @Override + protected void onComplete(boolean failed, boolean unloadWorld) { + getPlot().getPermissions().clearAllPerms(); + super.onComplete(true, false); + } + }; if (!isWorldGenerated() || !isWorldLoaded()) { - PlotSystem.getPlugin().getComponentLogger().warn(text("Could not regenerate world " + getWorldName() + " for plot " + getPlot().getID() + "!")); + PlotSystem.getPlugin().getComponentLogger().warn(text("Could not regenerate world " + getWorldName() + " for plot " + getPlot().getId() + "!")); return false; } return true; @@ -113,12 +70,8 @@ protected void onComplete(boolean failed, boolean unloadWorld) throws SQLExcepti @Override public boolean unloadWorld(boolean movePlayers) { - boolean isTutorialPlot = false; - try { - isTutorialPlot = getPlot().getPlotType() == PlotType.TUTORIAL; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + boolean isTutorialPlot; + isTutorialPlot = getPlot().getPlotType() == PlotType.TUTORIAL; if (getPlot() != null) { if (isTutorialPlot) return deleteWorld(); @@ -131,31 +84,26 @@ public boolean unloadWorld(boolean movePlayers) { public boolean teleportPlayer(@NotNull Player player) { if (!super.teleportPlayer(player)) return false; - try { - player.playSound(player.getLocation(), Utils.SoundUtils.TELEPORT_SOUND, 1, 1); - player.setAllowFlight(true); - player.setFlying(true); + player.playSound(player.getLocation(), Utils.SoundUtils.TELEPORT_SOUND, 1, 1); + player.setAllowFlight(true); + player.setFlying(true); - if (getPlot() == null) return true; - if (getPlot().getPlotType() != PlotType.TUTORIAL) { - player.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(player, LangPaths.Message.Info.TELEPORTING_PLOT, String.valueOf(getPlot().getID())))); - PlotUtils.ChatFormatting.sendLinkMessages(getPlot(), player); - } - Utils.updatePlayerInventorySlots(player); + if (getPlot() == null) return true; + if (getPlot().getPlotType() != PlotType.TUTORIAL) { + player.sendMessage(Utils.ChatUtils.getInfoFormat(LangUtil.getInstance().get(player, LangPaths.Message.Info.TELEPORTING_PLOT, String.valueOf(getPlot().getId())))); + PlotUtils.ChatFormatting.sendLinkMessages(getPlot(), player); + } + Utils.updatePlayerInventorySlots(player); - if (!getPlot().getPlotOwner().getUUID().equals(player.getUniqueId())) return true; - getPlot().setLastActivity(false); + if (!getPlot().getPlotOwner().getUUID().equals(player.getUniqueId())) return true; + getPlot().setLastActivity(false); - return true; - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } - return false; + return true; } @Override - public int getPlotHeight() throws IOException { - return getPlot().getVersion() >= 3 ? MIN_WORLD_HEIGHT : getPlotHeightCentered(); + public int getPlotHeight() { + return MIN_WORLD_HEIGHT; } @Override diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/PlotWorld.java b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/PlotWorld.java index b62db7ac7..873757563 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/PlotWorld.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/plot/world/PlotWorld.java @@ -1,39 +1,16 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.plot.world; +import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.plot.AbstractPlot; -import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.core.system.plot.TutorialPlot; import com.alpsbte.plotsystem.core.system.plot.generator.AbstractPlotGenerator; +import com.alpsbte.plotsystem.utils.DependencyManager; import com.alpsbte.plotsystem.utils.Utils; -import com.fastasyncworldedit.core.FaweAPI; -import com.onarandombox.MultiverseCore.MultiverseCore; import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.extent.clipboard.Clipboard; +import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.protection.managers.RegionManager; @@ -46,10 +23,12 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.mvplugins.multiverse.core.MultiverseCoreApi; +import org.mvplugins.multiverse.core.world.options.DeleteWorldOptions; +import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; -import java.sql.SQLException; import java.util.Locale; import static net.kyori.adventure.text.Component.text; @@ -59,7 +38,7 @@ public class PlotWorld implements IWorld { public static final int MAX_WORLD_HEIGHT = 256; public static final int MIN_WORLD_HEIGHT = 5; - private final MultiverseCore mvCore = PlotSystem.DependencyManager.getMultiverseCore(); + private final MultiverseCoreApi mvCore = DependencyManager.getMultiverseCore(); private final String worldName; private final AbstractPlot plot; @@ -81,10 +60,12 @@ public boolean regenWorld(@NotNull Class ge @Override public boolean deleteWorld() { if (isWorldGenerated() && loadWorld()) { - if (mvCore.getMVWorldManager().deleteWorld(getWorldName(), true, true) && mvCore.saveWorldConfig()) { + if (Boolean.TRUE.equals(mvCore.getWorldManager().getWorld(getWorldName()) + .map(world -> mvCore.getWorldManager().deleteWorld(DeleteWorldOptions.world(world)).isSuccess()) + .getOrElse(false)) && mvCore.getWorldManager().saveWorldsConfig().isSuccess()) { try { - File multiverseInventoriesConfig = new File(PlotSystem.DependencyManager.getMultiverseInventoriesConfigPath(getWorldName())); - File worldGuardConfig = new File(PlotSystem.DependencyManager.getWorldGuardConfigPath(getWorldName())); + File multiverseInventoriesConfig = new File(DependencyManager.getMultiverseInventoriesConfigPath(getWorldName())); + File worldGuardConfig = new File(DependencyManager.getWorldGuardConfigPath(getWorldName())); if (multiverseInventoriesConfig.exists()) FileUtils.deleteDirectory(multiverseInventoriesConfig); if (worldGuardConfig.exists()) FileUtils.deleteDirectory(worldGuardConfig); } catch (IOException ex) { @@ -102,7 +83,7 @@ public boolean loadWorld() { if (isWorldGenerated()) { if (isWorldLoaded()) { return true; - } else return mvCore.getMVWorldManager().loadWorld(getWorldName()) || isWorldLoaded(); + } else return mvCore.getWorldManager().loadWorld(getWorldName()).isSuccess() || isWorldLoaded(); } else PlotSystem.getPlugin().getComponentLogger().warn(text("Could not load world " + worldName + " because it is not generated!")); return false; } @@ -117,8 +98,7 @@ public boolean unloadWorld(boolean movePlayers) { } } - Bukkit.unloadWorld(getBukkitWorld(), true); - return !isWorldLoaded(); + return Bukkit.unloadWorld(getBukkitWorld(), true); } return true; } else PlotSystem.getPlugin().getComponentLogger().warn(text("Could not unload world " + worldName + " because it is not generated!")); @@ -145,7 +125,7 @@ public Location getSpawnPoint(BlockVector3 plotVector) { } // Set spawn point 1 block above the highest block at the spawn location - spawnLocation.setY(getBukkitWorld().getHighestBlockYAt((int) spawnLocation.getX(), (int) spawnLocation.getZ()) + 1); + spawnLocation.setY(getBukkitWorld().getHighestBlockYAt((int) spawnLocation.getX(), (int) spawnLocation.getZ()) + 1d); return spawnLocation; } return null; @@ -159,7 +139,11 @@ public int getPlotHeight() throws IOException { @Override public int getPlotHeightCentered() throws IOException { if (plot != null) { - Clipboard clipboard = FaweAPI.load(plot.getOutlinesSchematic()); + Clipboard clipboard; + ByteArrayInputStream inputStream = new ByteArrayInputStream(plot.getInitialSchematicBytes()); + try (ClipboardReader reader = AbstractPlot.CLIPBOARD_FORMAT.getReader(inputStream)) { + clipboard = reader.read(); + } if (clipboard != null) { return (int) clipboard.getRegion().getCenter().y() - clipboard.getMinimumPoint().y(); } @@ -199,10 +183,10 @@ public boolean isWorldLoaded() { @Override public boolean isWorldGenerated() { - return mvCore.getMVWorldManager().getMVWorld(worldName) != null || mvCore.getMVWorldManager().getUnloadedWorlds().contains(worldName); + return mvCore.getWorldManager().getWorld(worldName).isDefined(); } - private ProtectedRegion getRegion(String regionName) { + private @Nullable ProtectedRegion getRegion(String regionName) { RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer(); if (loadWorld()) { RegionManager regionManager = container.get(BukkitAdapter.adapt(getBukkitWorld())); @@ -222,7 +206,7 @@ public AbstractPlot getPlot() { * @param worldName - the name of the world * @return - true if the world is a plot world */ - public static boolean isOnePlotWorld(String worldName) { + public static boolean isOnePlotWorld(@NotNull String worldName) { return worldName.toLowerCase(Locale.ROOT).startsWith("p-") || worldName.toLowerCase(Locale.ROOT).startsWith("t-"); } @@ -230,7 +214,7 @@ public static boolean isOnePlotWorld(String worldName) { * @param worldName - the name of the world * @return - true if the world is a city plot world */ - public static boolean isCityPlotWorld(String worldName) { + public static boolean isCityPlotWorld(@NotNull String worldName) { return worldName.toLowerCase(Locale.ROOT).startsWith("c-"); } @@ -239,17 +223,14 @@ public static boolean isCityPlotWorld(String worldName) { * It won't return the CityPlotWorld class because there is no use case without a plot. * * @param worldName - name of the world - * @param - OnePlotWorld or PlotWorld * @return - plot world */ - public static T getPlotWorldByName(String worldName) { + public static @Nullable PlotWorld getPlotWorldByName(String worldName) { if (isOnePlotWorld(worldName) || isCityPlotWorld(worldName)) { - int id = Integer.parseInt(worldName.substring(2)); - try { - return worldName.toLowerCase().startsWith("t-") ? new TutorialPlot(id).getWorld() : new Plot(id).getWorld(); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + Integer id = AlpsUtils.tryParseInt(worldName.substring(2)); + if (id == null) return new PlotWorld(worldName, null); + AbstractPlot plot = worldName.toLowerCase().startsWith("t-") ? DataProvider.TUTORIAL_PLOT.getById(id).orElse(null) : DataProvider.PLOT.getPlotById(id); + return plot == null ? null : plot.getWorld(); } return null; } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/review/BuildTeamToggleCriteria.java b/src/main/java/com/alpsbte/plotsystem/core/system/review/BuildTeamToggleCriteria.java new file mode 100644 index 000000000..9bcba6ad9 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/system/review/BuildTeamToggleCriteria.java @@ -0,0 +1,4 @@ +package com.alpsbte.plotsystem.core.system.review; + +public record BuildTeamToggleCriteria(int buildTeamId, ToggleCriteria criteria) { +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/review/PlotReview.java b/src/main/java/com/alpsbte/plotsystem/core/system/review/PlotReview.java new file mode 100644 index 000000000..bc58723cd --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/system/review/PlotReview.java @@ -0,0 +1,112 @@ +package com.alpsbte.plotsystem.core.system.review; + +import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.system.Builder; +import com.alpsbte.plotsystem.core.system.plot.Plot; +import com.alpsbte.plotsystem.utils.enums.Slot; +import com.alpsbte.plotsystem.utils.enums.Status; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public class PlotReview { + private final int reviewId; + private final Plot plot; + private final ReviewRating rating; + private final int score; + private final int splitScore; + private final UUID reviewedBy; + @Nullable + private String feedback; + + public PlotReview(int reviewId, int plotId, ReviewRating rating, int score, @Nullable String feedback, UUID reviewedBy) { + this(reviewId, DataProvider.PLOT.getPlotById(plotId), rating, score, feedback, reviewedBy); + } + + public PlotReview(int reviewId, Plot plot, ReviewRating rating, int score, @Nullable String feedback, UUID reviewedBy) { + this.reviewId = reviewId; + this.plot = plot; + this.rating = rating; + this.score = score; + this.splitScore = plot.getPlotMembers().isEmpty() ? -1 : (int) Math.floor(score / (plot.getPlotMembers().size() + 1d)); + this.feedback = feedback; + this.reviewedBy = reviewedBy; + } + + public int getReviewId() { + return reviewId; + } + + public ReviewRating getRating() { + return rating; + } + + public int getScore() { + return score; + } + + public int getSplitScore() {return splitScore;} + + public @Nullable String getFeedback() { + return feedback; + } + + public Plot getPlot() { + return plot; + } + + public Builder getReviewer() { + return DataProvider.BUILDER.getBuilderByUUID(reviewedBy); + } + + public UUID getReviewerUUID() { + return reviewedBy; + } + + public boolean updateFeedback(String feedback) { + if (DataProvider.REVIEW.updateFeedback(reviewId, feedback)) { + this.feedback = feedback; + return true; + } + return false; + } + + public boolean undoReview() { + // remove owner score and remove plot from slot + if (!plot.getPlotOwner().addScore(splitScore == -1 ? -score : -splitScore)) return false; + + Slot slot = plot.getPlotOwner().getSlotByPlotId(plot.getId()); // get slot if plot is still in slots (rejected) + if (slot == null) slot = plot.getPlotOwner().getFreeSlot(); // get new slot otherwise (completed) + if (slot == null) return false; + + if (!plot.getPlotOwner().setSlot(slot, plot.getId())) return false; + + // remove members score and remove plot from slot + for (Builder member : plot.getPlotMembers()) { + if (!member.addScore(-splitScore)) return false; + + Slot memberSlot = member.getSlotByPlotId(plot.getId()); + if (memberSlot == null) memberSlot = member.getFreeSlot(); + if (memberSlot == null || member.setSlot(memberSlot, plot.getId())) return false; + } + + boolean successful = true; + if (!plot.setStatus(Status.unreviewed)) { + successful = false; + PlotSystem.getPlugin().getComponentLogger().error("Failed to set plot status to unreviewed while undoing review for plot ID {}", plot.getId()); + } + + if (!plot.setPasted(false)) { + successful = false; + PlotSystem.getPlugin().getComponentLogger().error("Failed to set plot pasted status to false while undoing review for plot ID {}", plot.getId()); + } + + if (!DataProvider.REVIEW.removeReview(reviewId)) { + successful = false; + PlotSystem.getPlugin().getComponentLogger().error("Failed to remove plot review with ID {} from database!", reviewId); + } + + return successful; + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/review/ReviewNotification.java b/src/main/java/com/alpsbte/plotsystem/core/system/review/ReviewNotification.java new file mode 100644 index 000000000..4944c9008 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/system/review/ReviewNotification.java @@ -0,0 +1,5 @@ +package com.alpsbte.plotsystem.core.system.review; + +import java.util.UUID; + +public record ReviewNotification(int reviewId, UUID uuid) {} diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/review/ReviewRating.java b/src/main/java/com/alpsbte/plotsystem/core/system/review/ReviewRating.java new file mode 100644 index 000000000..e21aee217 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/system/review/ReviewRating.java @@ -0,0 +1,97 @@ +package com.alpsbte.plotsystem.core.system.review; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ReviewRating { + private int accuracyPoints; + private int blockPalettePoints; + private final List checkedToggles = new ArrayList<>(); + private final List uncheckedToggles = new ArrayList<>(); + + public ReviewRating(int accuracyPoints, int blockPalettePoints, List checkedToggles, List uncheckedToggles) { + this.accuracyPoints = accuracyPoints; + this.blockPalettePoints = blockPalettePoints; + this.checkedToggles.addAll(checkedToggles); + this.uncheckedToggles.addAll(uncheckedToggles); + } + + public ReviewRating(int accuracyPoints, int blockPalettePoints, Map toggles) { + this.accuracyPoints = accuracyPoints; + this.blockPalettePoints = blockPalettePoints; + + for (ToggleCriteria criteria : toggles.keySet()) { + if (toggles.get(criteria)) this.checkedToggles.add(criteria); + else this.uncheckedToggles.add(criteria); + } + } + + public int getAccuracyPoints() { + return accuracyPoints; + } + + public void setAccuracyPoints(int points) { + accuracyPoints = points; + } + + public int getBlockPalettePoints() { + return blockPalettePoints; + } + + public void setBlockPalettePoints(int points) { + blockPalettePoints = points; + } + + public List getCheckedToggles() { + return checkedToggles; + } + + public List getUncheckedToggles() { + return uncheckedToggles; + } + + public Map getAllToggles() { + HashMap allToggles = new HashMap<>(); + for (ToggleCriteria checked : checkedToggles) allToggles.put(checked, true); + for (ToggleCriteria unchecked : uncheckedToggles) allToggles.put(unchecked, false); + + return allToggles; + } + + public void setToggleCriteria(ToggleCriteria criteria, boolean isToggled) { + if (isToggled) { + checkedToggles.add(criteria); + uncheckedToggles.remove(criteria); + } else { + uncheckedToggles.add(criteria); + checkedToggles.remove(criteria); + } + } + + public int getTogglePoints() { + return (int) Math.floor(((double) checkedToggles.size() / (checkedToggles.size() + uncheckedToggles.size())) * 10); + } + + public int getTotalRating() { + return accuracyPoints + blockPalettePoints + getTogglePoints(); + } + + public boolean isRejected() { + // a plot is rejected if either of the point sliders are 0 + if (accuracyPoints == 0 || blockPalettePoints == 0) return true; + + for (ToggleCriteria unchecked : uncheckedToggles) { + // a plot is also rejected if any of the required toggles are not checked + if (!unchecked.isOptional()) return true; + } + + // a plot is also rejected if the total rating is less than or equal to 8 + return getTotalRating() <= 8; + } + + public String getRatingDatabaseString() { + return accuracyPoints + "," + blockPalettePoints; + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/review/ToggleCriteria.java b/src/main/java/com/alpsbte/plotsystem/core/system/review/ToggleCriteria.java new file mode 100644 index 000000000..4659374c9 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/core/system/review/ToggleCriteria.java @@ -0,0 +1,12 @@ +package com.alpsbte.plotsystem.core.system.review; + +import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import org.bukkit.entity.Player; + +public record ToggleCriteria(String criteriaName, boolean isOptional) { + + public String getDisplayName(Player player) { + return LangUtil.getInstance().get(player, LangPaths.Database.TOGGLE_CRITERIA + "." + criteriaName); + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractPlotTutorial.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractPlotTutorial.java index fabfbe0ba..c6b6fcab2 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractPlotTutorial.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractPlotTutorial.java @@ -1,31 +1,9 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.PlotSystem; +import com.alpsbte.plotsystem.core.database.DataProvider; +import com.alpsbte.plotsystem.core.database.providers.TutorialPlotProvider; import com.alpsbte.plotsystem.core.system.Builder; import com.alpsbte.plotsystem.core.system.plot.TutorialPlot; import com.alpsbte.plotsystem.core.system.plot.generator.TutorialPlotGenerator; @@ -37,7 +15,6 @@ import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.sk89q.worldedit.WorldEditException; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; @@ -47,42 +24,60 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; -import java.sql.SQLException; +import java.util.Optional; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.Sound; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.WHITE; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public abstract class AbstractPlotTutorial extends AbstractTutorial implements PlotTutorial { - protected TutorialPlot plot; + protected TutorialPlot tutorialPlot; private TutorialPlotGenerator plotGenerator; private boolean isPasteSchematic; - protected AbstractPlotTutorial(Player player, int tutorialId, int stageId) throws SQLException { - // TODO: Performance improvements base constructor - super(player, getPlot(player, tutorialId), tutorialId, stageId == -1 ? getPlot(player, tutorialId).getStageID() : stageId); + protected AbstractPlotTutorial(Player player, int tutorialId, int stageId) { + super(player, tutorialId, stageId); - plot = (TutorialPlot) tutorialDataModel; + CompletableFuture.runAsync(() -> { + String playerUUID = player.getUniqueId().toString(); + Optional plot = DataProvider.TUTORIAL_PLOT.getByTutorialId(tutorialId, playerUUID); + if (plot.isEmpty() && DataProvider.TUTORIAL_PLOT.add(tutorialId, playerUUID)) { + tutorialPlot = DataProvider.TUTORIAL_PLOT.getByTutorialId(tutorialId, playerUUID).orElse(null); + } else { + tutorialPlot = plot.orElse(null); + } - // Check if tutorial plot is null - if (plot == null) { - PlotSystem.getPlugin().getComponentLogger().error(text("Could not load tutorial. Plot is null!")); - return; - } + // Check if tutorial plot is null + if (tutorialPlot == null) { + PlotSystem.getPlugin().getComponentLogger().error(text("Could not load tutorial. Plot is null!")); + return; + } - // Initialize tutorial worlds and stages - initTutorial(); + Bukkit.getScheduler().runTask(PlotSystem.getPlugin(), () -> { + // Initialize tutorial worlds and stages + initTutorial(); - // Start the tutorial - nextStage(); + // Start the tutorial + nextStage(); + }); + }).exceptionally(ex -> { + PlotSystem.getPlugin().getComponentLogger().error(text("Could not load tutorial."), ex); + return null; + }); } @Override protected TutorialNPC initNpc() { return new TutorialNPC( - "ps-tutorial-" + plot.getID(), + "ps-tutorial-" + tutorialPlot.getId(), ChatColor.GOLD + ChatColor.BOLD.toString() + PlotSystem.getPlugin().getConfig().getString(ConfigPaths.TUTORIAL_NPC_NAME), ChatColor.GRAY + "(" + LangUtil.getInstance().get(getPlayer(), LangPaths.Note.Action.RIGHT_CLICK) + ")", PlotSystem.getPlugin().getConfig().getString(ConfigPaths.TUTORIAL_NPC_TEXTURE), @@ -96,14 +91,10 @@ public void setStage(int stageId) { } @Override - public void onPlotSchematicPaste(UUID playerUUID, int schematicId) { + public void onPlotSchematicPaste(UUID playerUUID, int schematicId) throws IOException { if (!getPlayerUUID().toString().equals(playerUUID.toString())) return; - try { - if (plotGenerator != null && plot.getWorld().isWorldGenerated() && plot.getWorld().isWorldLoaded()) { - plotGenerator.generateOutlines(schematicId); - } - } catch (SQLException | IOException | WorldEditException ex) { - onException(ex); + if (plotGenerator != null && tutorialPlot.getWorld().isWorldGenerated() && tutorialPlot.getWorld().isWorldLoaded()) { + plotGenerator.generateOutlines(schematicId); } } @@ -118,14 +109,21 @@ public void onPlotPermissionChange(UUID playerUUID, boolean isBuildingAllowed, b @Override protected AbstractStage getStage() throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { - return getStages().get(getCurrentStage()).getDeclaredConstructor(Player.class, TutorialPlot.class).newInstance(getPlayer(), plot); + return getStages().get(getCurrentStage()).getDeclaredConstructor(Player.class, TutorialPlot.class).newInstance(getPlayer(), tutorialPlot); } @Override protected void prepareStage(PrepareStageAction action) { Bukkit.getScheduler().runTaskLater(PlotSystem.getPlugin(), () -> { // paste initial schematic outlines of stage - if (isPasteSchematic) onPlotSchematicPaste(getPlayerUUID(), ((AbstractPlotStage) currentStage).getInitSchematicId()); + if (isPasteSchematic) { + try { + onPlotSchematicPaste(getPlayerUUID(), ((AbstractPlotStage) currentStage).getInitSchematicId()); + } catch (IOException ex) { + onException(ex); + return; + } + } isPasteSchematic = false; // Send a new stage unlocked message to the player @@ -140,12 +138,12 @@ protected void prepareStage(PrepareStageAction action) { @Override public void saveTutorial(int stageId) { Bukkit.getScheduler().runTaskAsynchronously(PlotSystem.getPlugin(), () -> { - try { - if (stageId >= stages.size()) { - if (!plot.isCompleted()) plot.setCompleted(); - } else if (stageId > plot.getStageID()) plot.setStageID(stageId); - } catch (SQLException ex) { - onException(ex); + if (stageId >= stages.size()) { + if (!tutorialPlot.isComplete()) tutorialPlot.setComplete(); + } else if (stageId > tutorialPlot.getStageID()) { + if (!tutorialPlot.setStageID(stageId)) { + PlotSystem.getPlugin().getComponentLogger().error("Could not save tutorial progress for tutorial plot #{}!", tutorialPlot.getId()); + } } }); } @@ -153,15 +151,16 @@ public void saveTutorial(int stageId) { @Override public void onSwitchWorld(UUID playerUUID, int tutorialWorldIndex) { if (!getPlayerUUID().toString().equals(playerUUID.toString())) return; - try { - if (tutorialWorldIndex == 1 && (plotGenerator == null || !plotGenerator.getPlot().getWorld().isWorldGenerated())) { - plotGenerator = new TutorialPlotGenerator(plot, Builder.byUUID(playerUUID)); + if (tutorialWorldIndex == 1 && (plotGenerator == null || !plotGenerator.getPlot().getWorld().isWorldGenerated())) { + plotGenerator = new TutorialPlotGenerator(tutorialPlot, Builder.byUUID(playerUUID)); + try { onPlotSchematicPaste(playerUUID, ((AbstractPlotStage) currentStage).getInitSchematicId()); + } catch (IOException ex) { + onException(ex); + return; } - super.onSwitchWorld(playerUUID, tutorialWorldIndex); - } catch (SQLException ex) { - onException(ex); } + super.onSwitchWorld(playerUUID, tutorialWorldIndex); } @Override @@ -177,11 +176,10 @@ public void onTutorialComplete(UUID playerUUID) { public void onTutorialStop(UUID playerUUID) { if (!getPlayerUUID().toString().equals(playerUUID.toString())) return; super.onTutorialStop(playerUUID); - try { - if (plot != null) plot.getWorld().deleteWorld(); - } catch (SQLException ex) { - onException(ex); - } + if (tutorialPlot != null) tutorialPlot.getWorld().deleteWorld(); + int index = TutorialPlotProvider.tutorialPlots.get(tutorialPlot); + TutorialPlotProvider.tutorialPlots.remove(tutorialPlot); + TutorialPlotProvider.freeTutorialPlotIds.add(index); } @Override @@ -190,22 +188,6 @@ public void onException(Exception ex) { super.onException(ex); } - /** - * Gets the tutorial plot for a player with a specific tutorial id. - * If player has not started the tutorial yet, a new plot will be created. - * - * @param player the player to get the plot for. - * @param tutorialId the tutorial id. - * @return the tutorial plot. - * @throws SQLException if a SQL error occurs. - */ - private static TutorialPlot getPlot(Player player, int tutorialId) throws SQLException { - Builder builder = Builder.byUUID(player.getUniqueId()); - TutorialPlot plot = TutorialPlot.getPlot(builder.getUUID().toString(), tutorialId); - if (plot == null) plot = TutorialPlot.addTutorialPlot(builder.getUUID().toString(), tutorialId); - return plot; - } - /** * Sends a message to the player when a new stage is unlocked. * diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractTutorial.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractTutorial.java index cae4b01e3..124e03a12 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractTutorial.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractTutorial.java @@ -1,41 +1,22 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial; import com.alpsbte.alpslib.hologram.DecentHologramDisplay; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.core.system.tutorial.stage.AbstractStage; import com.alpsbte.plotsystem.core.system.tutorial.stage.StageTimeline; -import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialNPC; import com.alpsbte.plotsystem.core.system.tutorial.stage.TutorialWorld; -import org.bukkit.*; +import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialNPC; +import org.bukkit.Bukkit; +import org.bukkit.World; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; import java.lang.reflect.InvocationTargetException; -import java.util.*; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; import static net.kyori.adventure.text.Component.text; @@ -79,7 +60,6 @@ protected interface PrepareStageAction { private static final long PLAYER_INTERACTION_COOLDOWN = 1000; // The cooldown for player interactions in milliseconds - protected final TutorialDataModel tutorialDataModel; private final int tutorialId; private final UUID playerUUID; private final Player player; @@ -135,11 +115,10 @@ protected interface PrepareStageAction { */ protected abstract void prepareStage(PrepareStageAction action); - protected AbstractTutorial(Player player, TutorialDataModel tutorialDataModel, int tutorialId, int stageId) { + protected AbstractTutorial(@NotNull Player player, int tutorialId, int stageId) { this.tutorialId = tutorialId; this.playerUUID = player.getUniqueId(); this.player = player; - this.tutorialDataModel = tutorialDataModel; if (stageId < 0) stageId = 0; currentStageIndex = stageId - 1; @@ -182,7 +161,7 @@ public List getActiveHolograms() { .filter(AbstractTutorialHologram.class::isInstance) .filter(holo -> holo.isVisible(playerUUID)) .map(h -> (AbstractTutorialHologram) h) - .collect(Collectors.toList()); + .toList(); } @Override @@ -224,10 +203,8 @@ protected void nextStage() { // Ge the timeline of the current stage stageTimeline = currentStage.getTimeline(); - prepareStage(() -> { - // Start tasks timeline - stageTimeline.StartTimeline(); - }); + // Start tasks timeline + prepareStage(stageTimeline::StartTimeline); } catch (Exception ex) { onException(ex); } @@ -248,6 +225,7 @@ public void onSwitchWorld(UUID playerUUID, int tutorialWorldIndex) { currentWorldIndex = tutorialWorldIndex; TutorialWorld world = worlds.get(tutorialWorldIndex); + if (world == null) return; player.teleport(world.getPlayerSpawnLocation()); if (npc.getNpc() != null) { npc.move(player, world.getNpcSpawnLocation()); @@ -271,7 +249,7 @@ public void onException(Exception ex) { PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while processing tutorial!"), ex); // Send player back to hub after 3 seconds if an error occurred - Bukkit.getScheduler().runTaskLater(PlotSystem.getPlugin(), () -> onTutorialStop(player.getUniqueId()), 20 * 3); + Bukkit.getScheduler().runTaskLater(PlotSystem.getPlugin(), () -> onTutorialStop(player.getUniqueId()), 20L * 3); } /** @@ -283,16 +261,6 @@ public List> getStages() { return stages; } - /** - * Gets all registered worlds of the tutorial. - * - * @return list of all worlds - */ - public List getWorlds() { - return worlds; - } - - /** * Gets all active tutorials currently being run by a player. * @@ -336,7 +304,7 @@ public static boolean isPlayerIsOnInteractCoolDown(UUID playerUUID) { * @return true if the tutorial was loaded successfully, otherwise false */ public static boolean loadTutorial(Player player, int tutorialId) { - return loadTutorialByStage(player, tutorialId, -1); + return loadTutorialByStage(player, tutorialId, 0); } /** diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractTutorialHologram.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractTutorialHologram.java index 449af3664..c0bf920a0 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractTutorialHologram.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/AbstractTutorialHologram.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial; import com.alpsbte.alpslib.hologram.DecentHologramDisplay; @@ -35,7 +11,10 @@ import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; public abstract class AbstractTutorialHologram extends DecentHologramDisplay { protected static final String READ_EMOJI = "✅"; @@ -48,9 +27,9 @@ public interface ClickAction { void onClick(@NotNull HologramClickEvent clickEvent); } - private final static int MAX_HOLOGRAM_LENGTH = 48; // The maximum length of a line in the hologram - private final static String HOLOGRAM_LINE_BREAKER = "%newline%"; - private final static String EMPTY_TAG = "&f"; + private static final int MAX_HOLOGRAM_LENGTH = 48; // The maximum length of a line in the hologram + private static final String HOLOGRAM_LINE_BREAKER = "%newline%"; + private static final String EMPTY_TAG = "&f"; protected final Player player; protected final int holoId; @@ -63,7 +42,7 @@ public interface ClickAction { private ClickAction markAsReadClickAction; private boolean isMarkAsReadClicked = false; - public AbstractTutorialHologram(Player player, int tutorialId, int holoId, String content, int readMoreId) { + protected AbstractTutorialHologram(@NotNull Player player, int tutorialId, int holoId, String content, int readMoreId) { super("ps-tutorial-" + tutorialId + "-" + holoId, null, true); this.holoId = holoId; this.player = player; @@ -108,7 +87,7 @@ public AbstractTutorialHologram(Player player, int tutorialId, int holoId, Strin protected abstract String getMarkAsReadClickedActionText(); @Override - public void create(Player player) { + public void create(@NotNull Player player) { setLocation(new Location(player.getWorld(), vectorPos.getX(), vectorPos.getY(), vectorPos.getZ())); super.create(player); } @@ -124,7 +103,7 @@ public String getTitle(UUID playerUUID) { } @Override - public boolean hasViewPermission(UUID uuid) { + public boolean hasViewPermission(@NotNull UUID uuid) { return player.getUniqueId().toString().equals(uuid.toString()); } @@ -162,7 +141,7 @@ public void reload(UUID playerUUID) { if (readMoreId == -1 && markAsReadClickAction == null) return; setClickListener(clickEvent -> { if (!isMarkAsReadClicked && markAsReadClickAction != null) { - HologramLine line = clickEvent.getPage().getLines().get(clickEvent.getPage().getLines().size() - 1); + HologramLine line = clickEvent.getPage().getLines().getLast(); line.setText(getMarkAsReadClickedActionText()); clickEvent.getHologram().update(player); markAsReadClickAction.onClick(clickEvent); diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/BeginnerTutorial.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/BeginnerTutorial.java index 9c6f13587..a95943035 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/BeginnerTutorial.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/BeginnerTutorial.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial; import com.alpsbte.alpslib.utils.AlpsUtils; @@ -40,44 +16,62 @@ import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.message.ChatMessageTask; import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; import com.alpsbte.plotsystem.utils.Utils; -import com.alpsbte.plotsystem.utils.io.*; +import com.alpsbte.plotsystem.utils.io.ConfigPaths; +import com.alpsbte.plotsystem.utils.io.ConfigUtil; +import com.alpsbte.plotsystem.utils.io.LangPaths; +import com.alpsbte.plotsystem.utils.io.LangUtil; +import com.alpsbte.plotsystem.utils.io.TutorialPaths; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.HoverEvent; -import org.bukkit.*; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Material; +import org.bukkit.World; import org.bukkit.block.data.BlockData; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; import org.bukkit.util.Vector; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.annotations.Unmodifiable; import java.io.IOException; -import java.sql.SQLException; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; -import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.*; +import static com.alpsbte.alpslib.utils.AlpsUtils.deserialize; +import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.Delay; import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.Sound; +import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.TEXT_CLICK_HIGHLIGHT; +import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.TEXT_HIGHLIGHT_END; +import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.TEXT_HIGHLIGHT_START; +import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.getDocumentationLinks; +import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.setBlockAt; import static net.kyori.adventure.text.Component.text; -import static com.alpsbte.alpslib.utils.AlpsUtils.deserialize; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class BeginnerTutorial extends AbstractPlotTutorial { - public BeginnerTutorial(Player player, int stageId) throws SQLException { + public BeginnerTutorial(Player player, int stageId) { super(player, TutorialCategory.BEGINNER.getId(), stageId); } @Override protected List initWorlds() { - try { - return Arrays.asList( - new TutorialWorld(getId(), 0, Utils.getSpawnLocation().getWorld().getName()), - new TutorialWorld(getId(), 1, plot.getWorld().getWorldName()), - new TutorialWorld(getId(), 2, Utils.getSpawnLocation().getWorld().getName()) - ); - } catch (SQLException ex) { - onException(ex); - } - return null; + return Arrays.asList( + new TutorialWorld(getId(), 0, Utils.getSpawnLocation().getWorld().getName()), + new TutorialWorld(getId(), 1, tutorialPlot.getWorld().getWorldName()), + new TutorialWorld(getId(), 2, Utils.getSpawnLocation().getWorld().getName()) + ); } @Override @@ -112,7 +106,7 @@ public void onTutorialComplete(UUID playerUUID) { Bukkit.getScheduler().runTaskLaterAsynchronously(PlotSystem.getPlugin(), () -> { sendTutorialCompletedTipMessage(getPlayer()); getPlayer().playSound(getPlayer().getLocation(), Utils.SoundUtils.NOTIFICATION_SOUND, 1f, 1f); - }, 20 * 7); + }, 20 * 7L); } private static class Stage1 extends AbstractPlotStage { @@ -139,8 +133,9 @@ protected List setTasks() { TEXT_HIGHLIGHT_END); } + @Contract(pure = true) @Override - protected List setHolograms() { + protected @Nullable List setHolograms() { return null; } @@ -148,7 +143,7 @@ protected List setHolograms() { public StageTimeline getTimeline() { return new StageTimeline(getPlayer()) .delay(Delay.TIMELINE_START) - .interactNPC(deserialize(getTasks().get(0))) + .interactNPC(deserialize(getTasks().getFirst())) .sendChatMessage(deserialize(getMessages().get(0)), Sound.NPC_TALK, true) .sendChatMessage(deserialize(getMessages().get(1)), Sound.NPC_TALK, true) .sendChatMessage(deserialize(getMessages().get(2)), Sound.NPC_TALK, true) @@ -188,8 +183,9 @@ protected List setTasks() { return LangUtil.getInstance().getList(getPlayer(), LangPaths.Tutorials.Beginner.STAGE2_TASKS); } + @Contract(pure = true) @Override - protected List setHolograms() { + protected @Nullable List setHolograms() { return null; } @@ -241,15 +237,16 @@ protected List setTasks() { TEXT_HIGHLIGHT_START + "/tpll" + TEXT_HIGHLIGHT_END); } + @Contract(" -> new") @Override - protected List setHolograms() { + protected @NotNull @Unmodifiable List setHolograms() { return Collections.singletonList( new PlotTutorialHologram(getPlayer(), getId(), 0, getMessages().get(4), 3) ); } @Override - public StageTimeline getTimeline() throws SQLException, IOException { + public StageTimeline getTimeline() throws IOException { return new StageTimeline(getPlayer()) .delay(Delay.TIMELINE_START) .sendChatMessage(deserialize(getMessages().get(0)), Sound.NPC_TALK, true) @@ -260,8 +257,8 @@ public StageTimeline getTimeline() throws SQLException, IOException { text(Stage2.GOOGLE_MAPS, GRAY), ClickEvent.openUrl(getPlot().getGoogleMapsLink())) }, Sound.NPC_TALK, false) .delay(Delay.TASK_START) - .createHolograms(getHolograms().get(0)) - .addTeleportEvent(deserialize(getTasks().get(0)), getPlotPoints(getPlot()), 1, (teleportPoint, isCorrect) -> { + .createHolograms(getHolograms().getFirst()) + .addTeleportEvent(deserialize(getTasks().getFirst()), getPlotPoints(getPlot()), 1, (teleportPoint, isCorrect) -> { if (isCorrect) { setBlockAt(getPlayer().getWorld(), teleportPoint, Material.LIME_CONCRETE_POWDER); getPlayer().playSound(new Location(getPlayer().getWorld(), teleportPoint.getBlockX(), teleportPoint.getBlockY(), teleportPoint.getBlockZ()), @@ -299,8 +296,9 @@ protected List setTasks() { TEXT_HIGHLIGHT_START + "//wand" + TEXT_HIGHLIGHT_END); } + @Contract(pure = true) @Override - protected List setHolograms() { + protected @Nullable List setHolograms() { return null; } @@ -311,15 +309,14 @@ public StageTimeline getTimeline() { .sendChatMessage(deserialize(getMessages().get(0)), Sound.NPC_TALK, true) .sendChatMessage(deserialize(getMessages().get(1)), Sound.NPC_TALK, false) .delay(Delay.TASK_START) - .addTask(new WandCmdEventTask(getPlayer(), deserialize(getTasks().get(0)))) + .addTask(new WandCmdEventTask(getPlayer(), deserialize(getTasks().getFirst()))) .delay(Delay.TASK_END) .sendChatMessage(deserialize(getMessages().get(2)), Sound.NPC_TALK, true); } } private static class Stage5 extends AbstractPlotStage { - private final static String BASE_BLOCK = ConfigUtil.getTutorialInstance().getBeginnerTutorial().getString(TutorialPaths.Beginner.BASE_BLOCK); - private final static int BASE_BLOCK_ID = ConfigUtil.getTutorialInstance().getBeginnerTutorial().getInt(TutorialPaths.Beginner.BASE_BLOCK_ID); + private static final List BASE_BLOCKS = ConfigUtil.getTutorialInstance().getBeginnerTutorial().getStringList(TutorialPaths.Beginner.BASE_BLOCKS); protected Stage5(Player player, TutorialPlot plot) { super(player, 1, plot, 1); @@ -341,16 +338,17 @@ public List setMessages() { @Override protected List setTasks() { return LangUtil.getInstance().getList(getPlayer(), LangPaths.Tutorials.Beginner.STAGE5_TASKS, - TEXT_HIGHLIGHT_START + "//line " + BASE_BLOCK.toLowerCase() + TEXT_HIGHLIGHT_END); + TEXT_HIGHLIGHT_START + "//line " + BASE_BLOCKS.getFirst() + TEXT_HIGHLIGHT_END); } + @Contract(pure = true) @Override - protected List setHolograms() { + protected @Nullable List setHolograms() { return null; } @Override - public StageTimeline getTimeline() throws SQLException { + public StageTimeline getTimeline() { List buildingPoints = getPlotPoints(getPlot()); // Map building points to lines @@ -370,7 +368,7 @@ public StageTimeline getTimeline() throws SQLException { }, Sound.NPC_TALK, false) .delay(Delay.TASK_START) .addTask(new PlotPermissionChangeTask(getPlayer(), false, true)) - .addTask(new LineCmdEventTask(getPlayer(), deserialize(getTasks().get(0)), BASE_BLOCK, BASE_BLOCK_ID, buildingLinePoints, ((minPoint, maxPoint) -> { + .addTask(new LineCmdEventTask(getPlayer(), deserialize(getTasks().getFirst()), BASE_BLOCKS, buildingLinePoints, ((minPoint, maxPoint) -> { if (minPoint != null && maxPoint != null) { buildingLinePoints.remove(minPoint); @@ -387,8 +385,8 @@ public StageTimeline getTimeline() throws SQLException { } private static class Stage6 extends AbstractPlotStage { - private final static int HEIGHT = ConfigUtil.getTutorialInstance().getBeginnerTutorial().getInt(TutorialPaths.Beginner.HEIGHT); - private final static int HEIGHT_OFFSET = ConfigUtil.getTutorialInstance().getBeginnerTutorial().getInt(TutorialPaths.Beginner.HEIGHT_OFFSET); + private static final int HEIGHT = ConfigUtil.getTutorialInstance().getBeginnerTutorial().getInt(TutorialPaths.Beginner.HEIGHT); + private static final int HEIGHT_OFFSET = ConfigUtil.getTutorialInstance().getBeginnerTutorial().getInt(TutorialPaths.Beginner.HEIGHT_OFFSET); protected Stage6(Player player, TutorialPlot plot) { super(player, 1, plot, 2); @@ -411,13 +409,14 @@ protected List setTasks() { return LangUtil.getInstance().getList(getPlayer(), LangPaths.Tutorials.Beginner.STAGE6_TASKS); } + @Contract(" -> new") @Override - protected List setHolograms() { + protected @NotNull @Unmodifiable List setHolograms() { return Collections.singletonList(new PlotTutorialHologram(getPlayer(), getId(), 13, getMessages().get(7), 4)); } @Override - public StageTimeline getTimeline() throws IOException { + public @NotNull StageTimeline getTimeline() throws IOException { StageTimeline stage = new StageTimeline(getPlayer()) .delay(Delay.TIMELINE_START) .sendChatMessage(deserialize(getMessages().get(0)), Sound.NPC_TALK, true) @@ -429,8 +428,8 @@ public StageTimeline getTimeline() throws IOException { text(Stage2.GOOGLE_EARTH, GRAY), ClickEvent.openUrl(getPlot().getGoogleEarthLink())) }, Sound.NPC_TALK, false) .delay(Delay.TASK_START) - .createHolograms(getHolograms().get(0)); - stage.addPlayerChatEvent(deserialize(getTasks().get(0)), HEIGHT, HEIGHT_OFFSET, 3, (isCorrect, attemptsLeft) -> { + .createHolograms(getHolograms().getFirst()); + stage.addPlayerChatEvent(deserialize(getTasks().getFirst()), HEIGHT, HEIGHT_OFFSET, 3, (isCorrect, attemptsLeft) -> { if (!isCorrect && attemptsLeft > 0) { ChatMessageTask.sendTaskMessage(getPlayer(), new Object[]{deserialize(getMessages().get(6))}, false); getPlayer().playSound(getPlayer().getLocation(), Sound.ASSIGNMENT_WRONG, 1f, 1f); @@ -485,13 +484,13 @@ public StageTimeline getTimeline() { .delay(Delay.TIMELINE_START) .addTask(new PlotSchematicPasteTask(getPlayer(), 3)).delay(1) .sendChatMessage(deserialize(getMessages().get(0)), Sound.NPC_TALK, true) - .createHolograms(deserialize(getTasks().get(0)), getHolograms().get(0), getHolograms().get(1)) + .createHolograms(deserialize(getTasks().getFirst()), getHolograms().get(0), getHolograms().get(1)) .delay(Delay.TASK_END) .deleteHolograms() .delay(2) .addTask(new PlotSchematicPasteTask(getPlayer(), 4)).delay(1) .sendChatMessage(deserialize(getMessages().get(3)), Sound.NPC_TALK, true) - .createHolograms(deserialize(getTasks().get(0)), getHolograms().get(2), getHolograms().get(3), getHolograms().get(4)) + .createHolograms(deserialize(getTasks().getFirst()), getHolograms().get(2), getHolograms().get(3), getHolograms().get(4)) .delay(Delay.TASK_END); } } @@ -533,7 +532,7 @@ public StageTimeline getTimeline() { .sendChatMessage(deserialize(getMessages().get(1)), Sound.NPC_TALK, true) .createHolograms(getHolograms().get(0), getHolograms().get(1)) .addTask(new PlotPermissionChangeTask(getPlayer(), true, false)) - .addTask(new BuildEventTask(getPlayer(), deserialize(getTasks().get(0)), getWindowBuildPoints(), (blockPos, isCorrect) -> { + .addTask(new BuildEventTask(getPlayer(), deserialize(getTasks().getFirst()), getWindowBuildPoints(), (blockPos, isCorrect) -> { if (isCorrect) { getPlayer().playSound(getPlayer().getLocation(), Sound.ASSIGNMENT_COMPLETED, 1f, 1f); } else { @@ -582,8 +581,8 @@ public StageTimeline getTimeline() { return new StageTimeline(getPlayer()) .delay(Delay.TIMELINE_START) .addTask(new PlotSchematicPasteTask(getPlayer(), 6)).delay(1) - .sendChatMessage(deserialize(getMessages().get(0)), Sound.NPC_TALK, true) - .createHolograms(deserialize(getTasks().get(0)), getHolograms().get(0), getHolograms().get(1), getHolograms().get(2)) + .sendChatMessage(deserialize(getMessages().getFirst()), Sound.NPC_TALK, true) + .createHolograms(deserialize(getTasks().getFirst()), getHolograms().get(0), getHolograms().get(1), getHolograms().get(2)) .delay(Delay.TASK_END); } } @@ -623,8 +622,8 @@ public StageTimeline getTimeline() { return new StageTimeline(getPlayer()) .delay(Delay.TIMELINE_START) .addTask(new PlotSchematicPasteTask(getPlayer(), 7)).delay(1) - .sendChatMessage(deserialize(getMessages().get(0)), Sound.NPC_TALK, true) - .createHolograms(deserialize(getTasks().get(0)), getHolograms().get(0), getHolograms().get(1)) + .sendChatMessage(deserialize(getMessages().getFirst()), Sound.NPC_TALK, true) + .createHolograms(deserialize(getTasks().getFirst()), getHolograms().get(0), getHolograms().get(1)) .delay(Delay.TASK_END) .deleteHolograms() .delay(2) @@ -647,7 +646,7 @@ public StageTimeline getTimeline() { * * @return list of building points as Vector */ - private static List getPlotPoints(TutorialPlot plot) throws SQLException { + private static List getPlotPoints(TutorialPlot plot) { // Read coordinates from config FileConfiguration config = ConfigUtil.getTutorialInstance().getBeginnerTutorial(); List plotPointsAsString = Arrays.asList( diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/PlotTutorial.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/PlotTutorial.java index 1467f52b3..261e52fcf 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/PlotTutorial.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/PlotTutorial.java @@ -1,29 +1,6 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial; +import java.io.IOException; import java.util.UUID; public interface PlotTutorial extends Tutorial { @@ -34,7 +11,7 @@ public interface PlotTutorial extends Tutorial { * @param playerUUID uuid of the player * @param schematicId The schematic id */ - void onPlotSchematicPaste(UUID playerUUID, int schematicId); + void onPlotSchematicPaste(UUID playerUUID, int schematicId) throws IOException; /** * This method is called when the building and WorldEdit permissions on the plot need to be changed. diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/Tutorial.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/Tutorial.java index ba52c30ac..f8bee326c 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/Tutorial.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/Tutorial.java @@ -1,32 +1,8 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial; import com.alpsbte.plotsystem.core.system.tutorial.stage.StageTimeline; -import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialNPC; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.AbstractTask; +import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialNPC; import org.bukkit.World; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.entity.Player; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialCategory.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialCategory.java index 52c3d1a96..cf4410937 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialCategory.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialCategory.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial; public enum TutorialCategory { diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialDataModel.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialDataModel.java deleted file mode 100644 index 57ce8c569..000000000 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialDataModel.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.core.system.tutorial; - -import java.sql.SQLException; -import java.util.Date; -import java.util.UUID; - -public interface TutorialDataModel { - /** - * Gets the ID of the individual tutorial from your storage system (database or config). - * - * @return id, negative if not set - */ - int getID(); - - /** - * Gets the UUID of the player who started the tutorial. The UUID is 36 characters long and contains 4 dashes. - * - * @return uuid of the player - */ - UUID getPlayerUUID() throws SQLException; - - /** - * The ID which is assigned to the tutorial. This ID is used to identify the tutorial in the system. - * - * @return tutorial id, negative if not set - */ - int getTutorialID() throws SQLException; - - /** - * Gets the highest stage id which the player has completed. The stage id starts at 0. - * - * @return stage id, negative if not set - */ - int getStageID() throws SQLException; - - /** - * Checks if the player has completed all stages of the tutorial. - * - * @return true if the player has completed the tutorial otherwise false - */ - boolean isCompleted() throws SQLException; - - /** - * Gets the date when the player created the tutorial. - * - * @return create date - */ - Date getCreationDate() throws SQLException; - - /** - * Gets the date when the player last completed a stage. - * - * @return last stage completion date - */ - Date getLastStageCompletionDate() throws SQLException; - - /** - * Gets the date when the player completed the tutorial. - * - * @return completion date - */ - Date getCompletionDate() throws SQLException; -} diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialEventListener.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialEventListener.java index 85f13d7f9..6a366c723 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialEventListener.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/TutorialEventListener.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events.EventTask; @@ -31,7 +7,10 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPlaceEvent; -import org.bukkit.event.player.*; +import org.bukkit.event.player.PlayerChangedWorldEvent; +import org.bukkit.event.player.PlayerCommandPreprocessEvent; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerTeleportEvent; import java.util.HashMap; import java.util.Map; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/AbstractPlotStage.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/AbstractPlotStage.java index 3c3113ca4..48e0c76d8 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/AbstractPlotStage.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/AbstractPlotStage.java @@ -1,28 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - - package com.alpsbte.plotsystem.core.system.tutorial.stage; import com.alpsbte.plotsystem.core.system.plot.TutorialPlot; @@ -33,7 +8,7 @@ public abstract class AbstractPlotStage extends AbstractStage { private final int initSchematicId; protected AbstractPlotStage(Player player, int initWorldIndex, TutorialPlot plot, int initSchematicId) { - super(player, plot.getID(), initWorldIndex); + super(player, plot.getId(), initWorldIndex); this.plot = plot; this.initSchematicId = initSchematicId; } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/AbstractStage.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/AbstractStage.java index 39d0f45d4..4b742d46b 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/AbstractStage.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/AbstractStage.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorialHologram; @@ -29,7 +5,6 @@ import org.bukkit.entity.Player; import java.io.IOException; -import java.sql.SQLException; import java.util.List; public abstract class AbstractStage { @@ -87,7 +62,7 @@ protected AbstractStage(Player player, int id, int initWorldIndex) { * * @return timeline */ - public abstract StageTimeline getTimeline() throws IOException, SQLException; + public abstract StageTimeline getTimeline() throws IOException; public Player getPlayer() { return player; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/StageTimeline.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/StageTimeline.java index 8f67fc13d..ae1fa2a97 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/StageTimeline.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/StageTimeline.java @@ -1,50 +1,33 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorialHologram; -import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.*; +import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.AbstractTask; +import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.DelayTask; +import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.TeleportTask; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events.ChatEventTask; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events.NpcInteractEventTask; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events.TeleportPointEventTask; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events.commands.ContinueCmdEventTask; +import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.message.ChatMessageTask; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.message.CreateHologramTask; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.message.DeleteHologramTask; -import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.message.ChatMessageTask; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import org.bukkit.Location; import org.bukkit.Sound; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitTask; import org.bukkit.util.Vector; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.UUID; public class StageTimeline implements TutorialTimeline { private static final Map activeTimelines = new HashMap<>(); @@ -258,18 +241,6 @@ public StageTimeline createHolograms(Component assignmentMessage, AbstractTutori return this; } - /** - * Adds a DeleteHologramTask to the timeline. - * Deletes a specific tutorial hologram from the stage. - * - * @param hologram hologram to delete from the current stage - * @see AbstractStage#getHolograms() - */ - public StageTimeline deleteHologram(AbstractTutorialHologram hologram) { - tasks.add(new DeleteHologramTask(player, Collections.singletonList(hologram))); - return this; - } - /** * Adds a DeleteHologramTask to the timeline. * Deletes all tutorial holograms from the current stage. diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/TutorialTimeline.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/TutorialTimeline.java index 302c75a3e..4e2ee5619 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/TutorialTimeline.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/TutorialTimeline.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.AbstractTask; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/TutorialWorld.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/TutorialWorld.java index e98255bdf..1cebad50d 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/TutorialWorld.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/TutorialWorld.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage; import com.alpsbte.plotsystem.PlotSystem; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/AbstractTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/AbstractTask.java index 7b24f31fc..bc3cef0da 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/AbstractTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/AbstractTask.java @@ -1,42 +1,13 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks; import com.alpsbte.plotsystem.core.system.tutorial.TutorialEventListener; -import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; import com.alpsbte.plotsystem.core.system.tutorial.stage.StageTimeline; +import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; public abstract class AbstractTask { - @FunctionalInterface - public interface TaskAction { - void performAction(T t); - } - @FunctionalInterface public interface BiTaskAction { void performAction(T t, R r); @@ -54,7 +25,7 @@ public interface BiTaskAction { * * @param player The player who is doing the task. */ - public AbstractTask(Player player) { + protected AbstractTask(Player player) { this(player, null, 0); } @@ -65,7 +36,7 @@ public AbstractTask(Player player) { * @param assignmentMessage The message which is displayed in the action bar and chat. * @param totalAssignments The total assignment progress which is needed to complete the task. */ - public AbstractTask(Player player, Component assignmentMessage, int totalAssignments) { + protected AbstractTask(Player player, Component assignmentMessage, int totalAssignments) { this.player = player; this.assignmentMessage = assignmentMessage; this.totalAssignments = totalAssignments; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/DelayTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/DelayTask.java index 42de838c7..a449dd98a 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/DelayTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/DelayTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks; import com.alpsbte.plotsystem.PlotSystem; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/PlotPermissionChangeTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/PlotPermissionChangeTask.java index 7a2512339..0cefab384 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/PlotPermissionChangeTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/PlotPermissionChangeTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/PlotSchematicPasteTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/PlotSchematicPasteTask.java index 496104c36..bc7e7e10e 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/PlotSchematicPasteTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/PlotSchematicPasteTask.java @@ -1,33 +1,11 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; import com.alpsbte.plotsystem.core.system.tutorial.PlotTutorial; import org.bukkit.entity.Player; +import java.io.IOException; + public class PlotSchematicPasteTask extends AbstractTask { private final int schematicId; @@ -39,7 +17,14 @@ public PlotSchematicPasteTask(Player player, int schematicId) { @Override public void performTask() { PlotTutorial tutorial = (PlotTutorial) AbstractTutorial.getActiveTutorial(player.getUniqueId()); - if (tutorial != null) tutorial.onPlotSchematicPaste(player.getUniqueId(), schematicId); + if (tutorial != null) { + try { + tutorial.onPlotSchematicPaste(player.getUniqueId(), schematicId); + } catch (IOException ex) { + tutorial.onException(ex); + return; + } + } setTaskDone(); } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/TeleportTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/TeleportTask.java index c9e02be79..650066b7b 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/TeleportTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/TeleportTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks; import com.alpsbte.plotsystem.PlotSystem; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/BuildEventTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/BuildEventTask.java index 53042d3b7..cf0c06d4e 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/BuildEventTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/BuildEventTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events; import com.alpsbte.plotsystem.PlotSystem; @@ -67,16 +43,15 @@ public void run() { @Override public void performEvent(Event event) { - if (event instanceof BlockPlaceEvent) { - BlockPlaceEvent buildEvent = (BlockPlaceEvent) event; + if (event instanceof BlockPlaceEvent buildEvent) { if (!buildEvent.canBuild()) return; Block placedBlock = buildEvent.getBlockPlaced(); Vector placedBlockVector = new Vector(placedBlock.getX(), placedBlock.getY(), placedBlock.getZ()); - for (Vector blockVector : blocksToBuild.keySet()) { - if (blockVector.equals(placedBlockVector)) { - if (placedBlock.getBlockData().matches(blocksToBuild.get(blockVector))) { - removeBlockToBuild(blockVector); + for (Map.Entry vectorBlock : blocksToBuild.entrySet()) { + if (vectorBlock.getKey().equals(placedBlockVector)) { + if (placedBlock.getBlockData().matches(vectorBlock.getValue())) { + removeBlockToBuild(vectorBlock.getKey()); return; } onPlacedBlockAction.performAction(placedBlockVector, false); diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/ChatEventTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/ChatEventTask.java index 078b7fd27..38be37736 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/ChatEventTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/ChatEventTask.java @@ -1,30 +1,5 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events; -import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.plotsystem.core.system.tutorial.TutorialEventListener; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.AbstractTask; import io.papermc.paper.event.player.AsyncChatEvent; @@ -32,6 +7,7 @@ import net.kyori.adventure.text.TextComponent; import org.bukkit.entity.Player; import org.bukkit.event.Event; +import org.jetbrains.annotations.NotNull; public class ChatEventTask extends AbstractTask implements EventTask { private final int expectedValue; @@ -56,14 +32,13 @@ public void performTask() { @Override public void performEvent(Event event) { - if (event instanceof AsyncChatEvent) { - AsyncChatEvent chatEvent = (AsyncChatEvent) event; + if (event instanceof AsyncChatEvent chatEvent) { chatEvent.setCancelled(true); - TextComponent message = (TextComponent) chatEvent.message(); - if (AlpsUtils.tryParseInt(message.content()) != null) { - int value = Integer.parseInt(message.content()); - if (value >= expectedValue - offset && value <= expectedValue + offset) { + int inputNum = getStartDigits(((TextComponent) chatEvent.message()).content()); + + if (inputNum != -1) { + if (inputNum >= expectedValue - offset && inputNum <= expectedValue + offset) { onChatAction.performAction(true, attemptsLeft); attemptsLeft = 0; } else { @@ -78,4 +53,20 @@ public void performEvent(Event event) { } } } + + private int getStartDigits(@NotNull String message) { + int i = 0; + StringBuilder digits = new StringBuilder("0"); + while (i < message.length()) { + if (Character.isDigit(message.charAt(i))) { + digits.append(message.charAt(i)); + } else if (i == 0) { + return -1; + } else { + break; + } + i++; + } + return Integer.parseInt(digits.toString()); + } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/EventTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/EventTask.java index b59e05dd8..df82d5c7c 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/EventTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/EventTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events; import org.bukkit.event.Event; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/NpcInteractEventTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/NpcInteractEventTask.java index 483bda5e7..4c2b8dc20 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/NpcInteractEventTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/NpcInteractEventTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/TeleportPointEventTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/TeleportPointEventTask.java index 4194c8e92..fb2a57366 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/TeleportPointEventTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/TeleportPointEventTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events; import com.alpsbte.plotsystem.PlotSystem; @@ -69,9 +45,7 @@ public void run() { @Override public void performEvent(Event event) { - if (event instanceof PlayerTeleportEvent) { - PlayerTeleportEvent teleportEvent = (PlayerTeleportEvent) event; - + if (event instanceof PlayerTeleportEvent teleportEvent) { if (teleportPoints.isEmpty()) return; Location teleportLoc = teleportEvent.getTo(); diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/AbstractCmdEventTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/AbstractCmdEventTask.java index ecfde9a16..5e5d99049 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/AbstractCmdEventTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/AbstractCmdEventTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events.commands; import com.alpsbte.plotsystem.core.system.tutorial.TutorialEventListener; @@ -40,11 +16,11 @@ public abstract class AbstractCmdEventTask extends AbstractTask implements Event private final boolean isCancelCmdEvent; - public AbstractCmdEventTask(Player player, String expectedCommand, Component assignmentMessage, int totalAssignments, boolean cancelCmdEvent) { + protected AbstractCmdEventTask(Player player, String expectedCommand, Component assignmentMessage, int totalAssignments, boolean cancelCmdEvent) { this(player, expectedCommand, null, assignmentMessage, totalAssignments, cancelCmdEvent); } - public AbstractCmdEventTask(Player player, String expectedCommand, String[] args1, Component assignmentMessage, int totalAssignments, boolean cancelCmdEvent) { + protected AbstractCmdEventTask(Player player, String expectedCommand, String[] args1, Component assignmentMessage, int totalAssignments, boolean cancelCmdEvent) { super(player, assignmentMessage, totalAssignments); this.expectedCommand = expectedCommand; this.args1 = args1; @@ -60,21 +36,18 @@ public void performTask() { @Override public void performEvent(Event event) { - if (event instanceof PlayerCommandPreprocessEvent) { - PlayerCommandPreprocessEvent cmdEvent = (PlayerCommandPreprocessEvent) event; - if (cmdEvent.getMessage().toLowerCase().startsWith(expectedCommand.toLowerCase())) { + if (event instanceof PlayerCommandPreprocessEvent cmdEvent && cmdEvent.getMessage().toLowerCase().startsWith(expectedCommand.toLowerCase())) { if (isCancelCmdEvent) cmdEvent.setCancelled(true); // Check if the expected args are used String[] args = cmdEvent.getMessage().toLowerCase().replaceFirst(expectedCommand.toLowerCase(), "").trim().split(" "); - if (args1 != null && args1.length > 0) { - if (args.length == 0 || Arrays.stream(args1).noneMatch(arg -> arg.equalsIgnoreCase(args[0]))) { + if (args1 != null && args1.length > 0 && (args.length == 0 || Arrays.stream(args1).noneMatch(arg -> arg.equalsIgnoreCase(args[0])))) { onCommand(false, args); return; } - } - onCommand(true, args); + + onCommand(true, args); } - } + } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/ContinueCmdEventTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/ContinueCmdEventTask.java index 74a7a3e33..ad897cd39 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/ContinueCmdEventTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/ContinueCmdEventTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events.commands; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/LineCmdEventTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/LineCmdEventTask.java index 048e9a733..199c92845 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/LineCmdEventTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/LineCmdEventTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events.commands; import com.alpsbte.plotsystem.PlotSystem; @@ -40,7 +16,9 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -53,8 +31,8 @@ public class LineCmdEventTask extends AbstractCmdEventTask { private Vector minPoint; private Vector maxPoint; - public LineCmdEventTask(Player player, Component assignmentMessage, String blockName, int blockId, Map linePoints, BiTaskAction lineCmdAction) { - super(player, "//line", new String[]{blockName, String.valueOf(blockId)}, assignmentMessage, linePoints.size(), true); + public LineCmdEventTask(Player player, Component assignmentMessage, @NotNull List blocks, @NotNull Map linePoints, BiTaskAction lineCmdAction) { + super(player, "//line", blocks.toArray(new String[0]), assignmentMessage, linePoints.size(), true); this.linePoints = linePoints; this.lineCmdAction = lineCmdAction; } @@ -83,8 +61,8 @@ protected void onCommand(boolean isValid, String[] args) { @Override public void performEvent(Event event) { - if (event instanceof PlayerInteractEvent) { - onPlayerInteractEvent((PlayerInteractEvent) event); + if (event instanceof PlayerInteractEvent playerInteractEvent) { + onPlayerInteractEvent(playerInteractEvent); } else super.performEvent(event); } @@ -108,11 +86,9 @@ private boolean isPointInLine(Vector point) { } private boolean drawLine() { - try { - EditSession editSession = WorldEdit.getInstance().newEditSession((new BukkitWorld(player.getWorld()))); + try (EditSession editSession = WorldEdit.getInstance().newEditSession((new BukkitWorld(player.getWorld())))) { editSession.drawLine(Objects.requireNonNull(BlockTypes.WHITE_WOOL).getDefaultState(), BlockVector3.at(minPoint.getX(), minPoint.getY(), minPoint.getZ()), BlockVector3.at(maxPoint.getX(), maxPoint.getY(), maxPoint.getZ()), 0, false); - editSession.close(); } catch (MaxChangedBlocksException ex) { PlotSystem.getPlugin().getComponentLogger().error(text("An error occurred while drawing line!"), ex); return false; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/WandCmdEventTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/WandCmdEventTask.java index a896b01c0..2126800ae 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/WandCmdEventTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/events/commands/WandCmdEventTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.events.commands; import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/ChatMessageTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/ChatMessageTask.java index 8c449f112..778172076 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/ChatMessageTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/ChatMessageTask.java @@ -1,32 +1,8 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.message; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; -import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.AbstractTask; +import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; import net.kyori.adventure.text.Component; @@ -34,9 +10,12 @@ import net.kyori.adventure.text.event.HoverEvent; import org.bukkit.Sound; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; -import static net.kyori.adventure.text.Component.*; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.Component.text; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; public class ChatMessageTask extends AbstractTask { private final Object[] messages; @@ -66,7 +45,7 @@ public boolean isWaitToContinue() { return isWaitToContinue; } - public static void sendTaskMessage(Player player, Object[] messages, boolean waitToContinue) { + public static void sendTaskMessage(@NotNull Player player, Object[] messages, boolean waitToContinue) { AbstractTutorial tutorial = AbstractTutorial.getActiveTutorial(player.getUniqueId()); if (tutorial == null || tutorial.getNPC() == null) return; @@ -75,12 +54,12 @@ public static void sendTaskMessage(Player player, Object[] messages, boolean wai player.sendMessage(text(tutorial.getNPC().getDisplayName() + " ") .append(TutorialUtils.CHAT_PREFIX_COMPONENT)); for (Object message : messages) { - if (message instanceof ClickableTaskMessage) { - player.sendMessage(((ClickableTaskMessage) message).getComponent()); - } else if (message instanceof Component) { - player.sendMessage(((Component) message).color(GRAY)); - } else if (message instanceof String) { - player.sendMessage(text((String) message).color(GRAY)); + if (message instanceof ClickableTaskMessage ctm) { + player.sendMessage(ctm.getComponent()); + } else if (message instanceof Component c) { + player.sendMessage(c.color(GRAY)); + } else if (message instanceof String s) { + player.sendMessage(text(s).color(GRAY)); } } @@ -90,7 +69,7 @@ public static void sendTaskMessage(Player player, Object[] messages, boolean wai LangUtil.getInstance().get(player, LangPaths.Note.Action.CLICK_TO_PROCEED))); } - public static Component getContinueButtonComponent(String text, String hoverText) { + public static @NotNull Component getContinueButtonComponent(String text, String hoverText) { return text("[", DARK_GRAY).append(text(text, GREEN).append(text("]", DARK_GRAY))) .hoverEvent(HoverEvent.showText(text(hoverText, GRAY))).clickEvent(ClickEvent.runCommand("/tutorial continue")); } @@ -101,12 +80,6 @@ public static class ClickableTaskMessage { private final Component hoverTextComponent; private final ClickEvent clickEvent; - public ClickableTaskMessage(String message, String hoverText, ClickEvent clickEvent) { - this.messageComponent = text(message); - this.hoverTextComponent = text(hoverText); - this.clickEvent = clickEvent; - } - public ClickableTaskMessage(Component messageComponent, Component hoverTextComponent, ClickEvent clickEvent) { this.messageComponent = messageComponent; this.hoverTextComponent = hoverTextComponent; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/CreateHologramTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/CreateHologramTask.java index f4b0325cb..faf9ad032 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/CreateHologramTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/CreateHologramTask.java @@ -1,32 +1,8 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.message; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorialHologram; -import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; import com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.AbstractTask; +import com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils; import eu.decentsoftware.holograms.event.HologramClickEvent; import net.kyori.adventure.text.Component; import org.bukkit.entity.Player; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/DeleteHologramTask.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/DeleteHologramTask.java index 55193d17c..cec5b9663 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/DeleteHologramTask.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/stage/tasks/message/DeleteHologramTask.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.stage.tasks.message; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPC.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPC.java index 87c97b007..a7a034480 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPC.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPC.java @@ -1,33 +1,9 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2024, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.utils; import de.oliver.fancynpcs.api.FancyNpcsPlugin; import de.oliver.fancynpcs.api.Npc; import de.oliver.fancynpcs.api.NpcData; -import de.oliver.fancynpcs.api.utils.SkinFetcher; +import de.oliver.fancynpcs.api.skins.SkinData; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; @@ -44,7 +20,7 @@ public class TutorialNPC { private final String id; private final String displayName; private final String interactionPrompt; - private final SkinFetcher.SkinData skin; + private final SkinData skin; private Npc npc; private TutorialNPCHologram hologram; @@ -61,7 +37,7 @@ public TutorialNPC(String npcId, String npcDisplayName, String npcInteractionPro this.id = npcId; this.displayName = npcDisplayName; this.interactionPrompt = npcInteractionPrompt; - this.skin = new SkinFetcher.SkinData(npcId, npcSknTexture, npcSkinSignature); + this.skin = new SkinData(npcId, SkinData.SkinVariant.AUTO, npcSknTexture, npcSkinSignature); } /** @@ -74,7 +50,7 @@ public void create(Location spawnPos) { NpcData npcData = new NpcData(id, UUID.randomUUID(), spawnPos); npc = FancyNpcsPlugin.get().getNpcAdapter().apply(npcData); - npc.getData().setSkin(skin); + npc.getData().setSkinData(skin); npc.getData().setDisplayName(EMPTY_TAG); npc.getData().setTurnToPlayer(true); npc.setSaveToFile(false); @@ -146,10 +122,6 @@ public TutorialNPCHologram getHologram() { return hologram; } - public String getId() { - return id; - } - public String getDisplayName() { return displayName; } @@ -157,8 +129,4 @@ public String getDisplayName() { public String getInteractionPrompt() { return interactionPrompt; } - - public SkinFetcher.SkinData getSkin() { - return skin; - } } diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPCHologram.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPCHologram.java index b0c6595d9..9b7058f50 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPCHologram.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPCHologram.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2024, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.utils; import com.alpsbte.alpslib.hologram.DecentHologramDisplay; @@ -32,10 +8,10 @@ import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; -import java.util.UUID; -import java.util.List; -import java.util.Collections; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; public class TutorialNPCHologram extends DecentHologramDisplay { private static final double NPC_HOLOGRAM_Y = 2.3; diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPCTurnTracker.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPCTurnTracker.java index d50e8b547..fb451c33e 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPCTurnTracker.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialNPCTurnTracker.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2024, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.utils; import com.alpsbte.plotsystem.core.system.tutorial.AbstractTutorial; @@ -29,7 +5,7 @@ import org.bukkit.Location; public class TutorialNPCTurnTracker implements Runnable { - public static int turnToPlayerDistance = FancyNpcsPlugin.get().getFancyNpcConfig().getTurnToPlayerDistance();; + public static final int turnToPlayerDistance = FancyNpcsPlugin.get().getFancyNpcConfig().getTurnToPlayerDistance(); @Override public void run() { diff --git a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialUtils.java b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialUtils.java index d99374d7c..3896e5674 100644 --- a/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialUtils.java +++ b/src/main/java/com/alpsbte/plotsystem/core/system/tutorial/utils/TutorialUtils.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.core.system.tutorial.utils; import net.kyori.adventure.text.Component; @@ -35,13 +11,16 @@ import java.util.List; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; public class TutorialUtils { - public static String TEXT_HIGHLIGHT_START = "", TEXT_HIGHLIGHT_END = ""; - public static String TEXT_CLICK_HIGHLIGHT = ""; + public static final String TEXT_HIGHLIGHT_START = ""; + public static final String TEXT_HIGHLIGHT_END = ""; + public static final String TEXT_CLICK_HIGHLIGHT = ""; - public static Component CHAT_PREFIX_COMPONENT = text("»", DARK_GRAY) + public static final Component CHAT_PREFIX_COMPONENT = text("»", DARK_GRAY) .append(text(" ", GRAY)); public static Component CHAT_TASK_PREFIX_COMPONENT = text("[", DARK_GRAY) .append(text("Tutorial", GOLD).append(text("] ", DARK_GRAY))); diff --git a/src/main/java/com/alpsbte/plotsystem/utils/DependencyManager.java b/src/main/java/com/alpsbte/plotsystem/utils/DependencyManager.java new file mode 100644 index 000000000..e348266e8 --- /dev/null +++ b/src/main/java/com/alpsbte/plotsystem/utils/DependencyManager.java @@ -0,0 +1,58 @@ +package com.alpsbte.plotsystem.utils; + +import com.alpsbte.plotsystem.PlotSystem; +import com.sk89q.worldguard.bukkit.WorldGuardPlugin; +import org.bukkit.Bukkit; +import org.jetbrains.annotations.NotNull; +import org.mvplugins.multiverse.core.MultiverseCoreApi; + +import java.util.Objects; + +public class DependencyManager { + private DependencyManager() {} + + /** + * @return True if ParticleNativeAPI is present + */ + public static boolean isParticleNativeAPIEnabled() { + return PlotSystem.getPlugin().getServer().getPluginManager().isPluginEnabled("ParticleNativeAPI"); + } + + public static boolean isMultiverseInventoriesEnabled() { + return PlotSystem.getPlugin().getServer().getPluginManager().isPluginEnabled("Multiverse-Inventories"); + } + + public static boolean isWorldGuardExtraFlagsEnabled() { + return PlotSystem.getPlugin().getServer().getPluginManager().isPluginEnabled("WorldGuardExtraFlags"); + } + + /** + * @param worldName Name of the world + * @return Config path for the world + */ + public static @NotNull String getMultiverseInventoriesConfigPath(String worldName) { + return DependencyManager.isMultiverseInventoriesEnabled() ? Objects.requireNonNull(Bukkit.getPluginManager().getPlugin("Multiverse-Inventories")).getDataFolder() + "/worlds/" + worldName : ""; + } + + /** + * @return Multiverse-Core instance + */ + public static MultiverseCoreApi getMultiverseCore() { + return MultiverseCoreApi.get(); + } + + /** + * @return World Guard instance + */ + public static WorldGuardPlugin getWorldGuard() { + return WorldGuardPlugin.inst(); + } + + /** + * @param worldName Name of the world + * @return Config path for the world + */ + public static @NotNull String getWorldGuardConfigPath(String worldName) { + return Objects.requireNonNull(Bukkit.getPluginManager().getPlugin("WorldGuard")).getDataFolder() + "/worlds/" + worldName; + } +} diff --git a/src/main/java/com/alpsbte/plotsystem/utils/PacketListener.java b/src/main/java/com/alpsbte/plotsystem/utils/PacketListener.java deleted file mode 100644 index debff2020..000000000 --- a/src/main/java/com/alpsbte/plotsystem/utils/PacketListener.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.utils; - -import com.alpsbte.plotsystem.PlotSystem; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.ListenerPriority; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketEvent; - -public class PacketListener { - public PacketListener() { - ProtocolManager protocolManager = PlotSystem.DependencyManager.getProtocolManager(); - if (protocolManager != null) { - // Update inventory slots of player after changing client game settings - protocolManager.addPacketListener(new PacketAdapter(PlotSystem.getPlugin(), - ListenerPriority.LOWEST, PacketType.Play.Client.SETTINGS) { - @Override - public void onPacketReceiving(PacketEvent event) { - Utils.updatePlayerInventorySlots(event.getPlayer()); - } - }); - } - } -} diff --git a/src/main/java/com/alpsbte/plotsystem/utils/PlotMemberInvitation.java b/src/main/java/com/alpsbte/plotsystem/utils/PlotMemberInvitation.java index 9fe5455ae..89b5aaa9c 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/PlotMemberInvitation.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/PlotMemberInvitation.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils; import com.alpsbte.alpslib.utils.AlpsUtils; @@ -36,7 +12,6 @@ import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitScheduler; -import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -44,7 +19,10 @@ import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.TEXT_HIGHLIGHT_START; import static net.kyori.adventure.text.Component.empty; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class PlotMemberInvitation { @@ -56,7 +34,7 @@ public class PlotMemberInvitation { private final BukkitScheduler scheduler = PlotSystem.getPlugin().getServer().getScheduler(); private int taskID; - public PlotMemberInvitation(Player invitee, Plot plot) throws SQLException { + public PlotMemberInvitation(Player invitee, Plot plot) { this.invitee = invitee; this.plot = plot; @@ -87,21 +65,19 @@ public PlotMemberInvitation(Player invitee, Plot plot) throws SQLException { PlotMemberInvitation invitation = this; taskID = scheduler.scheduleSyncDelayedTask(PlotSystem.getPlugin(), () -> { invitationsList.remove(invitation); - try { - invitee.sendMessage(Utils.ChatUtils.getAlertFormat(AlpsUtils.deserialize(LangUtil.getInstance().get(invitee, - LangPaths.Message.Error.PLAYER_INVITE_EXPIRED, TEXT_HIGHLIGHT_START + plot.getPlotOwner().getName() + TEXT_HIGHLIGHT_END)))); - plot.getPlotOwner().getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(AlpsUtils.deserialize(LangUtil.getInstance().get(plot.getPlotOwner().getPlayer(), - LangPaths.Message.Error.PLAYER_INVITE_TO_EXPIRED, TEXT_HIGHLIGHT_START + invitee.getName() + TEXT_HIGHLIGHT_END)))); - } catch (SQLException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); - } + invitee.sendMessage(Utils.ChatUtils.getAlertFormat(AlpsUtils.deserialize(LangUtil.getInstance().get(invitee, + LangPaths.Message.Error.PLAYER_INVITE_EXPIRED, TEXT_HIGHLIGHT_START + plot.getPlotOwner().getName() + TEXT_HIGHLIGHT_END)))); + plot.getPlotOwner().getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(AlpsUtils.deserialize(LangUtil.getInstance().get(plot.getPlotOwner().getPlayer(), + LangPaths.Message.Error.PLAYER_INVITE_TO_EXPIRED, TEXT_HIGHLIGHT_START + invitee.getName() + TEXT_HIGHLIGHT_END)))); }, 20 * 30); } - public void acceptInvite() throws SQLException { + public void acceptInvite() { Builder builder = Builder.byUUID(invitee.getUniqueId()); if (builder.getFreeSlot() != null) { - plot.addPlotMember(Builder.byUUID(invitee.getUniqueId())); + if (!plot.addPlotMember(Builder.byUUID(invitee.getUniqueId()))) { + PlotSystem.getPlugin().getComponentLogger().error("Failed to add plot member {} to plot #{}!", invitee.getName(), plot.getId()); + } // Messages Receiver invitee.sendMessage(Utils.ChatUtils.getInfoFormat(AlpsUtils.deserialize(LangUtil.getInstance().get(invitee, @@ -117,7 +93,7 @@ public void acceptInvite() throws SQLException { } } - public void rejectInvite() throws SQLException { + public void rejectInvite() { invitee.sendMessage(Utils.ChatUtils.getInfoFormat(AlpsUtils.deserialize(LangUtil.getInstance().get(invitee, LangPaths.Message.Info.PLAYER_INVITE_REJECTED, TEXT_HIGHLIGHT_START + plot.getPlotOwner().getName() + TEXT_HIGHLIGHT_END)))); plot.getPlotOwner().getPlayer().sendMessage(Utils.ChatUtils.getAlertFormat(AlpsUtils.deserialize(LangUtil.getInstance().get(plot.getPlotOwner().getPlayer(), diff --git a/src/main/java/com/alpsbte/plotsystem/utils/ShortLink.java b/src/main/java/com/alpsbte/plotsystem/utils/ShortLink.java index 3881bcda9..cb429c3e9 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/ShortLink.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/ShortLink.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils; import com.alpsbte.plotsystem.PlotSystem; diff --git a/src/main/java/com/alpsbte/plotsystem/utils/Utils.java b/src/main/java/com/alpsbte/plotsystem/utils/Utils.java index ee74b6e02..d2f9dbaf2 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/Utils.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/Utils.java @@ -1,42 +1,18 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils; +import com.alpsbte.alpslib.io.database.SqlHelper; import com.alpsbte.alpslib.utils.AlpsUtils; import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; +import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.menus.ReviewMenu; import com.alpsbte.plotsystem.core.menus.companion.CompanionMenu; +import com.alpsbte.plotsystem.core.menus.review.ReviewMenu; import com.alpsbte.plotsystem.core.system.plot.Plot; import com.alpsbte.plotsystem.utils.chat.ChatInput; import com.alpsbte.plotsystem.utils.enums.PlotDifficulty; import com.alpsbte.plotsystem.utils.io.ConfigPaths; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; -import com.alpsbte.plotsystem.utils.items.CustomHeads; -import com.onarandombox.MultiverseCore.api.MultiverseWorld; import com.sk89q.worldedit.math.BlockVector2; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.TextComponent; @@ -45,6 +21,7 @@ import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import org.bukkit.Bukkit; import org.bukkit.Location; +import org.bukkit.Material; import org.bukkit.Sound; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; @@ -53,10 +30,13 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.mvplugins.multiverse.core.world.LoadedMultiverseWorld; +import org.mvplugins.multiverse.external.vavr.control.Option; import java.sql.SQLException; import java.time.LocalDateTime; import java.util.HashSet; +import java.util.Locale; import java.util.Objects; import java.util.Random; import java.util.Set; @@ -64,7 +44,14 @@ import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.TEXT_HIGHLIGHT_END; import static com.alpsbte.plotsystem.core.system.tutorial.utils.TutorialUtils.TEXT_HIGHLIGHT_START; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.DARK_RED; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.GREEN; +import static net.kyori.adventure.text.format.NamedTextColor.RED; +import static net.kyori.adventure.text.format.NamedTextColor.YELLOW; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class Utils { @@ -72,6 +59,8 @@ private Utils() {} private static Random random; public static final String EMPTY_MASK = "000000000"; + public static final String FULL_MASK = "111111111"; + public static final ItemStack DEFAULT_ITEM = new ItemBuilder(Material.GRAY_STAINED_GLASS_PANE, 1).setName(Component.empty()).build(); // Spawn Location public static Location getSpawnLocation() { @@ -79,14 +68,14 @@ public static Location getSpawnLocation() { if (!Objects.requireNonNull(config.getString(ConfigPaths.SPAWN_WORLD)).equalsIgnoreCase("default")) { try { - MultiverseWorld spawnWorld = PlotSystem.DependencyManager.getMultiverseCore().getMVWorldManager().getMVWorld(config.getString(ConfigPaths.SPAWN_WORLD)); - return spawnWorld.getSpawnLocation(); + Option spawnWorld = DependencyManager.getMultiverseCore().getWorldManager().getLoadedWorld(config.getString(ConfigPaths.SPAWN_WORLD)); + return spawnWorld.get().getSpawnLocation(); } catch (Exception ignore) { PlotSystem.getPlugin().getComponentLogger().warn(text("Could not find %s in multiverse config!"), ConfigPaths.SPAWN_WORLD); } } - return PlotSystem.DependencyManager.getMultiverseCore().getMVWorldManager().getSpawnWorld().getSpawnLocation(); + return DependencyManager.getMultiverseCore().getWorldManager().getDefaultWorld().get().getSpawnLocation(); } public static void updatePlayerInventorySlots(Player player) { @@ -99,9 +88,24 @@ public static void updatePlayerInventorySlots(Player player) { }); } + public static ItemStack getConfiguredItem(@NotNull String material, Object customModelData) { + ItemStack base; + if (material.startsWith("head(") && material.endsWith(")")) { + String headId = material.substring(material.indexOf("(") + 1, material.lastIndexOf(")")); + base = AlpsHeadUtils.getCustomHead(headId); + } else { + Material mat = Material.getMaterial(material.toUpperCase(Locale.ROOT)); + base = new ItemStack(mat == null ? Material.BARRIER : mat); + } + ItemBuilder builder = new ItemBuilder(base); + if (customModelData != null) builder.setItemModel(customModelData); + + return builder.build(); + } public static class SoundUtils { private SoundUtils() {} + public static final Sound TELEPORT_SOUND = Sound.ENTITY_ENDERMAN_TELEPORT; public static final Sound ERROR_SOUND = Sound.ENTITY_ITEM_BREAK; public static final Sound CREATE_PLOT_SOUND = Sound.ENTITY_EXPERIENCE_ORB_PICKUP; @@ -115,6 +119,7 @@ private SoundUtils() {} public static class ChatUtils { private ChatUtils() {} + public static void setChatFormat(String infoPrefix, String alertPrefix) { ChatUtils.infoPrefix = AlpsUtils.deserialize(infoPrefix); ChatUtils.alertPrefix = AlpsUtils.deserialize(alertPrefix); @@ -175,8 +180,8 @@ private ItemUtils() {} @Contract(pure = true) public static @NotNull String getActionFormat(String action) {return "§8§l> §c" + action;} - public static @NotNull Component getColoredPointsComponent(int points) { - return switch (points) { + public static @NotNull Component getColoredPointsComponent(int points, int maxPoints) { + return switch ((int) ((double) points / maxPoints * 5)) { case 0 -> text(points, GRAY); case 1 -> text(points, DARK_RED); case 2 -> text(points, GOLD); @@ -186,19 +191,15 @@ private ItemUtils() {} }; } - public static @NotNull TextComponent getFormattedDifficulty(@NotNull PlotDifficulty plotDifficulty) { + public static @NotNull TextComponent getFormattedDifficulty(@NotNull PlotDifficulty plotDifficulty, Player player) { return switch (plotDifficulty) { - case EASY -> text("Easy", GREEN).decoration(BOLD, true); - case MEDIUM -> text("Medium", GOLD).decoration(BOLD, true); - case HARD -> text("Hard", RED).decoration(BOLD, true); + case EASY -> text(LangUtil.getInstance().get(player, LangPaths.Database.DIFFICULTY + ".easy.name"), GREEN).decoration(BOLD, true); + case MEDIUM -> text(LangUtil.getInstance().get(player, LangPaths.Database.DIFFICULTY + ".medium.name"), GOLD).decoration(BOLD, true); + case HARD -> text(LangUtil.getInstance().get(player, LangPaths.Database.DIFFICULTY + ".hard.name"), RED).decoration(BOLD, true); }; } } - public static void registerCustomHeads() { - for (CustomHeads head : CustomHeads.values()) AlpsHeadUtils.registerCustomHead(head.getId()); - } - public static @NotNull Set getLineBetweenPoints(@NotNull BlockVector2 point1, @NotNull BlockVector2 point2, int pointsInLine) { double p1X = point1.x(); double p1Z = point1.z(); @@ -220,6 +221,23 @@ public static void logSqlException(Exception ex) { PlotSystem.getPlugin().getComponentLogger().error(text("A SQL error occurred!"), ex); } + public static @Nullable T handleSqlException(@Nullable T defaultValue, @NotNull SqlHelper.SQLCheckedSupplier supplier) { + try { + return supplier.get(); + } catch (SQLException e) { + logSqlException(e); + return defaultValue; + } + } + + public static void handleSqlException(@NotNull SqlHelper.SQLRunnable supplier) { + try { + supplier.get(); + } catch (SQLException e) { + logSqlException(e); + } + } + public static Random getRandom() { if (random == null) { random = new Random(); @@ -227,7 +245,8 @@ public static Random getRandom() { return random; } - public static boolean isOwnerOrReviewer(CommandSender sender, @Nullable Player player, Plot plot) throws SQLException { + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public static boolean isOwnerOrReviewer(CommandSender sender, @Nullable Player player, Plot plot) { boolean hasPermission = sender.hasPermission("plotsystem.review") || (player != null && Objects.requireNonNull(plot).getPlotOwner().getUUID().equals(player.getUniqueId())); if (!hasPermission) { sender.sendMessage(Utils.ChatUtils.getAlertFormat(LangUtil.getInstance().get(sender, LangPaths.Message.Error.PLAYER_IS_NOT_ALLOWED))); diff --git a/src/main/java/com/alpsbte/plotsystem/utils/chat/ChatInput.java b/src/main/java/com/alpsbte/plotsystem/utils/chat/ChatInput.java index cc0353487..9fe30bf0b 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/chat/ChatInput.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/chat/ChatInput.java @@ -1,31 +1,9 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.chat; import java.time.LocalDateTime; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; public interface ChatInput { Map awaitChatInput = new HashMap<>(); diff --git a/src/main/java/com/alpsbte/plotsystem/utils/chat/PlayerFeedbackChatInput.java b/src/main/java/com/alpsbte/plotsystem/utils/chat/PlayerFeedbackChatInput.java index c48807f91..46a8385f1 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/chat/PlayerFeedbackChatInput.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/chat/PlayerFeedbackChatInput.java @@ -1,30 +1,6 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.chat; -import com.alpsbte.plotsystem.core.system.Review; +import com.alpsbte.plotsystem.core.system.review.PlotReview; import com.alpsbte.plotsystem.utils.Utils; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; @@ -35,13 +11,13 @@ import java.util.UUID; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; public class PlayerFeedbackChatInput implements ChatInput { private final LocalDateTime dateTime; - private final Review review; + private final PlotReview review; - public PlayerFeedbackChatInput(UUID playerUUID, Review review) { + public PlayerFeedbackChatInput(UUID playerUUID, PlotReview review) { this.dateTime = LocalDateTime.now(); this.review = review; awaitChatInput.put(playerUUID, this); @@ -52,7 +28,7 @@ public LocalDateTime getDateTime() { return dateTime; } - public Review getReview() { + public PlotReview getReview() { return review; } diff --git a/src/main/java/com/alpsbte/plotsystem/utils/chat/PlayerInviteeChatInput.java b/src/main/java/com/alpsbte/plotsystem/utils/chat/PlayerInviteeChatInput.java index 29183ca95..54de173d4 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/chat/PlayerInviteeChatInput.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/chat/PlayerInviteeChatInput.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.chat; import com.alpsbte.plotsystem.core.system.plot.Plot; @@ -35,7 +11,7 @@ import java.util.UUID; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; public class PlayerInviteeChatInput implements ChatInput { private final LocalDateTime dateTime; diff --git a/src/main/java/com/alpsbte/plotsystem/utils/conversion/CoordinateConversion.java b/src/main/java/com/alpsbte/plotsystem/utils/conversion/CoordinateConversion.java index 374a737b4..28d77c8da 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/conversion/CoordinateConversion.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/conversion/CoordinateConversion.java @@ -1,33 +1,9 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.conversion; import com.alpsbte.plotsystem.utils.conversion.projection.GeographicProjection; -import com.alpsbte.plotsystem.utils.conversion.projection.ScaleProjectionTransform; import com.alpsbte.plotsystem.utils.conversion.projection.OffsetProjectionTransform; import com.alpsbte.plotsystem.utils.conversion.projection.OutOfProjectionBoundsException; +import com.alpsbte.plotsystem.utils.conversion.projection.ScaleProjectionTransform; import java.text.DecimalFormat; import java.text.DecimalFormatSymbols; diff --git a/src/main/java/com/alpsbte/plotsystem/utils/conversion/MathUtils.java b/src/main/java/com/alpsbte/plotsystem/utils/conversion/MathUtils.java index 82f5fe8a4..2ce39ee50 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/conversion/MathUtils.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/conversion/MathUtils.java @@ -1,37 +1,35 @@ package com.alpsbte.plotsystem.utils.conversion; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; + public class MathUtils { /** * Square root of 3 */ public static final double ROOT3 = Math.sqrt(3); - /** - * Two times pi - */ - public static final double TAU = 2 * Math.PI; - - /** * Converts geographic latitude and longitude coordinates to spherical coordinates on a sphere of radius 1. * * @param geo - geographic coordinates as a double array of length 2, {longitude, latitude}, in degrees * @return the corresponding spherical coordinates in radians: {longitude, colatitude} */ - public static double[] geo2Spherical(double[] geo) { + @Contract("_ -> new") + public static double @NotNull [] geo2Spherical(double @NotNull [] geo) { double lambda = Math.toRadians(geo[0]); double phi = Math.toRadians(90 - geo[1]); return new double[]{lambda, phi}; } - /** * Converts spherical coordinates to geographic coordinates on a sphere of radius 1. * * @param spherical - spherical coordinates in radians as a double array of length 2: {longitude, colatitude} * @return the corresponding geographic coordinates in degrees: {longitude, latitude} */ - public static double[] spherical2Geo(double[] spherical) { + @Contract("_ -> new") + public static double @NotNull [] spherical2Geo(double @NotNull [] spherical) { double lon = Math.toDegrees(spherical[0]); double lat = 90 - Math.toDegrees(spherical[1]); return new double[]{lon, lat}; @@ -44,7 +42,8 @@ public static double[] spherical2Geo(double[] spherical) { * @param spherical - spherical coordinates in radians as a double array of length 2: {longitude, colatitude} * @return the corresponding Cartesian coordinates: {x, y, z} */ - public static double[] spherical2Cartesian(double[] spherical) { + @Contract("_ -> new") + public static double @NotNull [] spherical2Cartesian(double @NotNull [] spherical) { double sinphi = Math.sin(spherical[1]); double x = sinphi * Math.cos(spherical[0]); double y = sinphi * Math.sin(spherical[0]); @@ -58,7 +57,8 @@ public static double[] spherical2Cartesian(double[] spherical) { * @param cartesian - Cartesian coordinates as double array of length 3: {x, y, z} * @return the spherical coordinates of the corresponding normalized vector */ - public static double[] cartesian2Spherical(double[] cartesian) { + @Contract("_ -> new") + public static double @NotNull [] cartesian2Spherical(double @NotNull [] cartesian) { double lambda = Math.atan2(cartesian[1], cartesian[0]); double phi = Math.atan2(Math.sqrt(cartesian[0] * cartesian[0] + cartesian[1] * cartesian[1]), cartesian[2]); return new double[]{lambda, phi}; @@ -66,14 +66,15 @@ public static double[] cartesian2Spherical(double[] cartesian) { /** - * TODO produceZYZRotationMatrix javadoc + * Generates a Z\-Y\-Z Euler rotation matrix for angles a, b, c (in radians). * - * @param a - * @param b - * @param c - * @return + * @param a rotation about the Z\-axis (first Z rotation) in radians + * @param b rotation about the Y\-axis (tilt, beta) in radians + * @param c rotation about the Z\-axis (second Z rotation) in radians + * @return a new 3x3 rotation matrix as double[][] in format matrix[row][col] + * corresponding to the composition Rz(a) * Ry(b) * Rz(c) */ - public static double[][] produceZYZRotationMatrix(double a, double b, double c) { + public static double[] @NotNull [] produceZYZRotationMatrix(double a, double b, double c) { double sina = Math.sin(a); double cosa = Math.cos(a); @@ -106,7 +107,8 @@ public static double[][] produceZYZRotationMatrix(double a, double b, double c) * @param vector - the vector as double array of length n * @return the result of the multiplication as an array of double on length n */ - public static double[] matVecProdD(double[][] matrix, double[] vector) { + @Contract(pure = true) + public static double @NotNull [] matVecProdD(double[][] matrix, double @NotNull [] vector) { double[] result = new double[vector.length]; for (int i = 0; i < result.length; i++) { for (int j = 0; j < matrix[i].length; j++) { diff --git a/src/main/java/com/alpsbte/plotsystem/utils/enums/Category.java b/src/main/java/com/alpsbte/plotsystem/utils/enums/Category.java deleted file mode 100644 index 033a6bb88..000000000 --- a/src/main/java/com/alpsbte/plotsystem/utils/enums/Category.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.utils.enums; - -public enum Category { - ACCURACY, BLOCKPALETTE, DETAILING, TECHNIQUE, ALL -} diff --git a/src/main/java/com/alpsbte/plotsystem/utils/enums/Continent.java b/src/main/java/com/alpsbte/plotsystem/utils/enums/Continent.java index ee278f2f2..152f62ebc 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/enums/Continent.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/enums/Continent.java @@ -1,31 +1,8 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.enums; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; +import com.alpsbte.plotsystem.core.database.DataProvider; import com.alpsbte.plotsystem.core.system.Country; import com.alpsbte.plotsystem.utils.io.LangPaths; import com.alpsbte.plotsystem.utils.io.LangUtil; @@ -38,22 +15,22 @@ import java.util.Arrays; import java.util.List; -import static net.kyori.adventure.text.Component.*; +import static net.kyori.adventure.text.Component.text; public enum Continent { - EUROPE("europe", LangPaths.Continent.EUROPE), - ASIA("asia", LangPaths.Continent.ASIA), - AFRICA("africa", LangPaths.Continent.AFRICA), - OCEANIA("oceania", LangPaths.Continent.OCEANIA), - SOUTH_AMERICA("south america", LangPaths.Continent.SOUTH_AMERICA), - NORTH_AMERICA("north america", LangPaths.Continent.NORTH_AMERICA); + EUROPE("EU", LangPaths.Continent.EUROPE), + ASIA("AS", LangPaths.Continent.ASIA), + AFRICA("AF", LangPaths.Continent.AFRICA), + OCEANIA("OC", LangPaths.Continent.OCEANIA), + SOUTH_AMERICA("SA", LangPaths.Continent.SOUTH_AMERICA), + NORTH_AMERICA("NA", LangPaths.Continent.NORTH_AMERICA); public final String databaseEnum; public final String langPath; Continent(String databaseEnum, String langPath) { this.databaseEnum = databaseEnum; - // although LangPath.Continent keys match the enum name, you cannot get the value without reflection + // you cannot get the value from the database enum without reflection this.langPath = langPath; } @@ -68,7 +45,7 @@ public static Continent fromDatabase(String databaseEnum) { * @return Menu item */ public ItemStack getItem(Player player) { - List countries = Country.getCountries(this); + List countries = DataProvider.COUNTRY.getCountriesByContinent(this); return new ItemBuilder(Material.COMPASS) .setName(text(LangUtil.getInstance().get(player, langPath), NamedTextColor.YELLOW).decoration(TextDecoration.BOLD, true)) diff --git a/src/main/java/com/alpsbte/plotsystem/utils/enums/PlotDifficulty.java b/src/main/java/com/alpsbte/plotsystem/utils/enums/PlotDifficulty.java index e03b7fe10..1c8ef51f7 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/enums/PlotDifficulty.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/enums/PlotDifficulty.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.enums; public enum PlotDifficulty { diff --git a/src/main/java/com/alpsbte/plotsystem/utils/enums/Slot.java b/src/main/java/com/alpsbte/plotsystem/utils/enums/Slot.java index 5f9eb8039..df6516623 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/enums/Slot.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/enums/Slot.java @@ -1,29 +1,5 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.enums; public enum Slot { - first_slot, second_slot, third_slot + FIRST, SECOND, THIRD } diff --git a/src/main/java/com/alpsbte/plotsystem/utils/enums/Status.java b/src/main/java/com/alpsbte/plotsystem/utils/enums/Status.java index 30badd9c7..8d7ecf505 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/enums/Status.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/enums/Status.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2021, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.enums; public enum Status { diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigPaths.java b/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigPaths.java index 0cf838006..0f263ca17 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigPaths.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigPaths.java @@ -1,52 +1,18 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.io; public abstract class ConfigPaths { + private ConfigPaths() {throw new IllegalStateException("Utility class");} + // General Behaviour public static final String SPAWN_WORLD = "spawn-world"; - public static final String CHECK_FOR_UPDATES = "check-for-updates"; public static final String ENABLE_SCORE_REQUIREMENT = "enable-score-requirement"; public static final String DEV_MODE = "dev-mode"; public static final String INACTIVITY_INTERVAL = "inactivity-interval"; + public static final String REJECTED_INACTIVITY_INTERVAL = "rejected-inactivity-interval"; public static final String ENABLE_GROUP_SUPPORT = "enable-group-support"; - - private static final String SYNC_FTP_FILES = "sync-ftp-files."; - public static final String SYNC_FTP_FILES_ENABLE = SYNC_FTP_FILES + "sff-enable"; - public static final String SYNC_FTP_FILES_INTERVAL = SYNC_FTP_FILES + "sync-interval"; - - - // Database - private static final String DATABASE = "database."; - public static final String DATABASE_URL = DATABASE + "url"; - public static final String DATABASE_NAME = DATABASE + "dbname"; - public static final String DATABASE_USERNAME = DATABASE + "username"; - public static final String DATABASE_PASSWORD = DATABASE + "password"; - - + public static final String UNFINISHED_REMINDER_INTERVAL = "unfinished-reminder-interval"; + public static final String DISABLE_CITY_INSPIRATION_MODE = "disable-city-inspiration-mode"; // Leaderboards private static final String HOLOGRAMS = "holograms."; public static final String SCORE_LEADERBOARD = "score-leaderboard"; @@ -54,12 +20,6 @@ public abstract class ConfigPaths { public static final String SCORE_LEADERBOARD_X = HOLOGRAMS + SCORE_LEADERBOARD + ".sl-x"; public static final String SCORE_LEADERBOARD_Y = HOLOGRAMS + SCORE_LEADERBOARD + ".sl-y"; public static final String SCORE_LEADERBOARD_Z = HOLOGRAMS + SCORE_LEADERBOARD + ".sl-z"; - public static final String PLOTS_LEADERBOARD = "plots-leaderboard"; - public static final String PLOTS_LEADERBOARD_ENABLE = HOLOGRAMS + PLOTS_LEADERBOARD + ".pl-enable"; - public static final String PLOTS_LEADERBOARD_X = HOLOGRAMS + PLOTS_LEADERBOARD + ".pl-x"; - public static final String PLOTS_LEADERBOARD_Y = HOLOGRAMS + PLOTS_LEADERBOARD + ".pl-y"; - public static final String PLOTS_LEADERBOARD_Z = HOLOGRAMS + PLOTS_LEADERBOARD + ".pl-z"; - private static final String DISPLAY_OPTIONS = "display-options."; public static final String DISPLAY_OPTIONS_INTERVAL = DISPLAY_OPTIONS + "interval"; @@ -68,21 +28,15 @@ public abstract class ConfigPaths { public static final String DISPLAY_OPTIONS_SHOW_MONTHLY = DISPLAY_OPTIONS + "show-monthly"; public static final String DISPLAY_OPTIONS_SHOW_YEARLY = DISPLAY_OPTIONS + "show-yearly"; public static final String DISPLAY_OPTIONS_SHOW_LIFETIME = DISPLAY_OPTIONS + "show-lifetime"; - public static final String DISPLAY_OPTIONS_ACTION_BAR_ENABLE = DISPLAY_OPTIONS + "action-bar-enable"; - public static final String DISPLAY_OPTIONS_ACTION_BAR_RADIUS = DISPLAY_OPTIONS + "action-bar-radius"; - // FORMATTING private static final String CHAT_FORMAT = "chat-format."; public static final String CHAT_FORMAT_INFO_PREFIX = CHAT_FORMAT + "info-prefix"; public static final String CHAT_FORMAT_ALERT_PREFIX = CHAT_FORMAT + "alert-prefix"; - // COMMANDS public static final String EDITPLOT_ENABLED = "editplot-enabled"; public static final String BLOCKED_COMMANDS_BUILDERS = "blocked-commands-builders"; - public static final String ALLOWED_COMMANDS_NON_BUILDERS = "allowed-commands-non-builders"; - // SHORTLINKS private static final String SHORTLINK = "shortlink."; @@ -90,7 +44,6 @@ public abstract class ConfigPaths { public static final String SHORTLINK_APIKEY = SHORTLINK + "apikey"; public static final String SHORTLINK_HOST = SHORTLINK + "host"; - // TUTORIALS private static final String TUTORIALS = "tutorials."; public static final String TUTORIAL_ENABLE = TUTORIALS + "tutorial-enable"; diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigUtil.java b/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigUtil.java index d1830a2ea..bd606f35f 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigUtil.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/io/ConfigUtil.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.io; import com.alpsbte.alpslib.io.config.ConfigNotImplementedException; @@ -44,9 +20,9 @@ private ConfigUtil() {} public static void init() throws ConfigNotImplementedException { if (configUtilInstance == null) { configUtilInstance = new ConfigurationUtil(new ConfigurationUtil.ConfigFile[]{ - new ConfigurationUtil.ConfigFile(Paths.get("config.yml"), 3.0, true), + new ConfigurationUtil.ConfigFile(Paths.get("config.yml"), 4.2, true), new ConfigurationUtil.ConfigFile(Paths.get("commands.yml"), 1.1, false), - new ConfigurationUtil.ConfigFile(Paths.get("items.yml"), 1.2, false) + new ConfigurationUtil.ConfigFile(Paths.get("items.yml"), 1.3, false) }); } diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/FTPManager.java b/src/main/java/com/alpsbte/plotsystem/utils/io/FTPManager.java deleted file mode 100644 index f02a33917..000000000 --- a/src/main/java/com/alpsbte/plotsystem/utils/io/FTPManager.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.utils.io; - -import com.alpsbte.plotsystem.PlotSystem; -import com.alpsbte.plotsystem.core.system.Server; -import org.apache.commons.vfs2.*; -import org.apache.commons.vfs2.impl.StandardFileSystemManager; -import org.apache.commons.vfs2.provider.ftp.FtpFileSystemConfigBuilder; -import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder; - -import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; -import java.sql.SQLException; -import java.util.concurrent.CompletableFuture; - -import static net.kyori.adventure.text.Component.text; - -public class FTPManager { - - private static FileSystemOptions fileOptions; - - private final static String DEFAULT_SCHEMATIC_PATH_LINUX = "/var/lib/Plot-System/schematics"; - - static { - try { - fileOptions = new FileSystemOptions(); - SftpFileSystemConfigBuilder.getInstance().setStrictHostKeyChecking(fileOptions, "no"); - SftpFileSystemConfigBuilder.getInstance().setPreferredAuthentications(fileOptions, "password"); - SftpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(fileOptions, false); - - FtpFileSystemConfigBuilder.getInstance().setPassiveMode(fileOptions, true); - FtpFileSystemConfigBuilder.getInstance().setUserDirIsRoot(fileOptions, false); - } catch (FileSystemException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("Exception found with FileSystemManager!"), ex); - } - } - - public static String getFTPUrl(Server server, int cityID) throws SQLException, URISyntaxException { - String schematicsPath = server.getFTPConfiguration().getSchematicPath(); - return new URI(server.getFTPConfiguration().isSFTP() ? "sftp" : "ftp", - server.getFTPConfiguration().getUsername() + ":" + server.getFTPConfiguration().getPassword(), - server.getFTPConfiguration().getAddress(), - server.getFTPConfiguration().getPort(), - String.format("/%s/%s/%s/", schematicsPath == null ? DEFAULT_SCHEMATIC_PATH_LINUX : schematicsPath, "finishedSchematics", cityID), - null, - null).toString(); - } - - public static CompletableFuture uploadSchematic(String ftpURL, File schematic) { - try (StandardFileSystemManager fileManager = new StandardFileSystemManager()) { - fileManager.init(); - - // Get local schematic - FileObject localSchematic = fileManager.toFileObject(schematic); - - // Get remote path and create missing directories - FileObject remote = fileManager.resolveFile(ftpURL, fileOptions); - remote.createFolder(); - - // Create remote schematic and write to it - FileObject remoteSchematic = remote.resolveFile(schematic.getName()); - remoteSchematic.copyFrom(localSchematic, Selectors.SELECT_SELF); - - localSchematic.close(); - remoteSchematic.close(); - } catch (FileSystemException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("Exception found with FileSystemManager!"), ex); - } - return CompletableFuture.completedFuture(null); - } - - public static boolean downloadSchematic(String ftpURL, File schematic) { - boolean fileExists = false; - try (StandardFileSystemManager fileManager = new StandardFileSystemManager()) { - fileManager.init(); - - // Get local schematic - FileObject localSchematic = fileManager.toFileObject(schematic); - - // Get remote path - FileObject remote = fileManager.resolveFile(ftpURL.replaceFirst("finishedSchematics/", ""), fileOptions); - - // Get remote schematic and write it to local file - FileObject remoteSchematic = remote.resolveFile(schematic.getName()); - if (remoteSchematic.exists()) { - localSchematic.copyFrom(remoteSchematic, Selectors.SELECT_SELF); - fileExists = true; - } - - localSchematic.close(); - remoteSchematic.close(); - } catch (FileSystemException ex) { - PlotSystem.getPlugin().getComponentLogger().error(text("Exception found with FileSystemManager!"), ex); - } - return fileExists; - } - - public static void deleteSchematic(String ftpURL, String schematicName) throws FileSystemException { - try (StandardFileSystemManager fileManager = new StandardFileSystemManager()) { - fileManager.init(); - FileObject remote, remoteSchematic; - - remote = fileManager.resolveFile(ftpURL, fileOptions); - remoteSchematic = remote.resolveFile(schematicName); - if (remoteSchematic.exists()) { - remoteSchematic.delete(); - if (remote.getChildren().length == 0) { - remote.delete(); - } - } - } - } -} \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/LangPaths.java b/src/main/java/com/alpsbte/plotsystem/utils/io/LangPaths.java index 080b80359..fc27cd527 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/io/LangPaths.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/io/LangPaths.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.io; public abstract class LangPaths { @@ -43,8 +19,8 @@ private Plot() {} public static final String SCORE = PLOT_PREFIX + "score"; public static final String TOTAL_SCORE = PLOT_PREFIX + "total-score"; public static final String COMPLETED_PLOTS = PLOT_PREFIX + "completed-plots"; - public static final class GroupSystem { + private GroupSystem() {} private static final String GROUP_SYSTEM = PLOT_PREFIX + "group-system."; @@ -52,8 +28,8 @@ private GroupSystem() {} public static final String SHARED_BY_MEMBERS = GROUP_SYSTEM + "shared-by-members"; } } - public static final class CityProject { + private CityProject() {} private static final String CITY_PROJECT = "city-project."; public static final String CITIES = CITY_PROJECT + "cities"; @@ -64,15 +40,15 @@ private CityProject() {} public static final String PROJECT_NO_PLOTS_AVAILABLE = CITY_PROJECT + "no-plots-available"; public static final String FOR_YOUR_DIFFICULTY = CITY_PROJECT + "for-your-difficulty"; } - public static final class Country { + private Country() {} private static final String COUNTRY_PREFIX = "country."; public static final String COUNTRIES = COUNTRY_PREFIX + "countries"; } - public static final class Continent { + private Continent() {} private static final String CONTINENT_PREFIX = "continent."; @@ -83,20 +59,21 @@ private Continent() {} public static final String SOUTH_AMERICA = CONTINENT_PREFIX + "south-america"; public static final String NORTH_AMERICA = CONTINENT_PREFIX + "north-america"; } - public static final class Difficulty { + private Difficulty() {} private static final String DIFFICULTY_PREFIX = "difficulty."; public static final String AUTOMATIC = DIFFICULTY_PREFIX + "automatic"; public static final String SCORE_MULTIPLIER = DIFFICULTY_PREFIX + "score-multiplier"; } - public static final class MenuTitle { + private MenuTitle() {} private static final String MENU_TITLES = "menu-title."; public static final String CLOSE = MENU_TITLES + "close"; public static final String BACK = MENU_TITLES + "back"; + public static final String CONTINUE = MENU_TITLES + "continue"; public static final String NEXT_PAGE = MENU_TITLES + "next-page"; public static final String PREVIOUS_PAGE = MENU_TITLES + "previous-page"; public static final String ERROR = MENU_TITLES + "error"; @@ -140,8 +117,8 @@ private MenuTitle() {} public static final String TUTORIAL_BEGINNER = MENU_TITLES + "tutorial-beginner"; public static final String COMPANION_RANDOM = MENU_TITLES + "companion-random"; } - public static final class MenuDescription { + private MenuDescription() {} private static final String MENU_DESCRIPTIONS = "menu-description."; public static final String ERROR = MENU_DESCRIPTIONS + "error-desc"; @@ -175,8 +152,8 @@ private MenuDescription() {} public static final String TUTORIAL_BEGINNER = MENU_DESCRIPTIONS + "tutorial-beginner-desc"; public static final String COMPANION_RANDOM = MENU_DESCRIPTIONS + "companion-random-desc"; } - public static final class Review { + private Review() {} private static final String REVIEW_PREFIX = "review."; @@ -189,23 +166,23 @@ private Review() {} public static final String FEEDBACK = REVIEW_PREFIX + "feedback"; public static final String REVIEWER = REVIEW_PREFIX + "reviewer"; public static final String PLAYER_LANGUAGE = REVIEW_PREFIX + "player-language"; - + public static final String NO_FEEDBACK = REVIEW_PREFIX + "no-feedback"; + public static final String ACCURACY_POINTS = REVIEW_PREFIX + "accuracy-points"; + public static final String BLOCK_PALETTE_POINTS = REVIEW_PREFIX + "block-palette-points"; + public static final String TOGGLE_POINTS = REVIEW_PREFIX + "toggle-points"; + public static final String TOTAL_POINTS = REVIEW_PREFIX + "total-points"; + public static final String ABANDONED_IN_DAYS = REVIEW_PREFIX + "abandoned-in-days"; public static final class Criteria { private Criteria() {} - private static final String CRITERIA_PREFIX = REVIEW_PREFIX + "criteria."; public static final String ACCURACY = CRITERIA_PREFIX + "accuracy"; public static final String ACCURACY_DESC = CRITERIA_PREFIX + "accuracy-desc"; public static final String BLOCK_PALETTE = CRITERIA_PREFIX + "block-palette"; public static final String BLOCK_PALETTE_DESC = CRITERIA_PREFIX + "block-palette-desc"; - public static final String DETAILING = CRITERIA_PREFIX + "detailing"; - public static final String DETAILING_DESC = CRITERIA_PREFIX + "detailing-desc"; - public static final String TECHNIQUE = CRITERIA_PREFIX + "technique"; - public static final String TECHNIQUE_DESC = CRITERIA_PREFIX + "technique-desc"; } } - public static final class Note { + private Note() {} private static final String NOTES = "note."; public static final String TIP = NOTES + "tip"; @@ -213,10 +190,14 @@ private Note() {} public static final String WONT_BE_ABLE_CONTINUE_BUILDING = NOTES + "wont-be-able-continue-building"; public static final String SCORE_WILL_BE_SPLIT = NOTES + "score-will-be-split"; public static final String PLAYER_HAS_TO_BE_ONLINE = NOTES + "player-has-to-be-online"; - + public static final String OPTIONAL = NOTES + "optional"; + public static final String REQUIRED = NOTES + "required"; + public static final String CRITERIA_FULFILLED = NOTES + "criteria-fulfilled"; + public static final String CRITERIA_NOT_FULFILLED = NOTES + "criteria-not-fulfilled"; + public static final String LEGACY = NOTES + "legacy"; public static final class Action { - private Action() {} + private Action() {} private static final String ACTION_PREFIX = NOTES + "action."; public static final String READ = ACTION_PREFIX + "read"; public static final String READ_MORE = ACTION_PREFIX + "read-more"; @@ -239,6 +220,8 @@ private Action() {} public static final String CLICK_TO_SHOW_PLOTS = ACTION_PREFIX + "click-to-show-plots"; public static final String CLICK_TO_PLAY_WITH_FRIENDS = ACTION_PREFIX + "click-to-play-with-friends"; public static final String TUTORIAL_SHOW_STAGES = ACTION_PREFIX + "tutorial-show-stages"; + public static final String CLICK_TO_OPEN_PLOTS_MENUE = ACTION_PREFIX + "click-to-open-plots-menu"; + public static final String CLICK_TO_TOGGLE = ACTION_PREFIX + "click-to-toggle"; } } @@ -270,7 +253,10 @@ private Info() {} public static final String REMOVED_PLOT_MEMBER = INFO_PREFIX + "removed-plot-member"; public static final String LEFT_PLOT = INFO_PREFIX + "left-plot"; public static final String PLOT_WILL_GET_ABANDONED = INFO_PREFIX + "plot-will-get-abandoned-warning"; - public static final String PLOT_WILL_GET_REJECTED = INFO_PREFIX + "plot-will-get-rejected-warning"; + public static final String PLOT_WILL_BE_REJECTED = INFO_PREFIX + "plot-will-be-rejected"; + public static final String PLOT_WILL_BE_ACCEPTED = INFO_PREFIX + "plot-will-be-accepted"; + public static final String PLOTS_REVIEWED_SINGULAR = INFO_PREFIX + "plots-reviewed-singular"; + public static final String PLOTS_REVIEWED_PLURAL = INFO_PREFIX + "plots-reviewed-plural"; public static final String SAVING_PLOT = INFO_PREFIX + "saving-plot"; public static final String CREATING_PLOT = INFO_PREFIX + "creating-plot"; public static final String CREATED_NEW_PLOT = INFO_PREFIX + "created-new-plot"; @@ -288,7 +274,6 @@ private Info() {} public static final class Error { private Error() {} - private static final String ERROR_PREFIX = MESSAGE_PREFIX + "error."; public static final String PLOT_DOES_NOT_EXIST = ERROR_PREFIX + "plot-does-not-exist"; public static final String PLOT_EITHER_UNCLAIMED_OR_UNREVIEWED = ERROR_PREFIX + "plot-either-unclaimed-or-unreviewed"; @@ -299,9 +284,10 @@ private Error() {} public static final String CAN_ONLY_UNDO_SUBMISSIONS_UNREVIEWED_PLOTS = ERROR_PREFIX + "can-only-undo-submissions-unreviewed-plots"; public static final String CAN_ONLY_MANAGE_MEMBERS_UNFINISHED = ERROR_PREFIX + "can-only-manage-members-unfinished-plots"; public static final String CANNOT_TELEPORT_OUTSIDE_PLOT = ERROR_PREFIX + "cannot-teleport-outside-plot"; - public static final String CANNOT_UNDO_REVIEW = ERROR_PREFIX + "cannot-undo-review"; public static final String CANNOT_SEND_FEEDBACK = ERROR_PREFIX + "cannot-send-feedback"; public static final String CANNOT_REVIEW_OWN_PLOT = ERROR_PREFIX + "cannot-review-own-plot"; + public static final String CANNOT_MODIFY_LEGACY_PLOT = ERROR_PREFIX + "cannot-modify-legacy-plot"; + public static final String CANNOT_LOAD_LEGACY_PLOT = ERROR_PREFIX + "cannot-load-legacy-plot"; public static final String PLAYER_HAS_NO_PERMISSIONS = ERROR_PREFIX + "player-has-no-permissions"; public static final String PLAYER_HAS_NO_INVITATIONS = ERROR_PREFIX + "player-has-no-invitations"; @@ -316,6 +302,7 @@ private Error() {} public static final String PLAYER_INVITE_TO_REJECTED = ERROR_PREFIX + "player-invite-to-rejected"; public static final String PLAYER_NEEDS_TO_BE_ON_PLOT = ERROR_PREFIX + "player-needs-to-be-on-plot"; public static final String PLAYER_NEEDS_HIGHER_SCORE = ERROR_PREFIX + "player-needs-higher-score"; + public static final String PLAYER_MISSING_TUTORIAL = MESSAGE_PREFIX + "player-missing-tutorial"; public static final String ERROR_OCCURRED = ERROR_PREFIX + "error-occurred"; public static final String COMMAND_DISABLED = ERROR_PREFIX + "command-disabled"; @@ -325,6 +312,7 @@ private Error() {} public static final String CHAT_INPUT_EXPIRED = ERROR_PREFIX + "chat-input-expired"; public static final String TUTORIAL_DISABLED = ERROR_PREFIX + "tutorial-disabled"; public static final String TUTORIAL_ALREADY_RUNNING = ERROR_PREFIX + "tutorial-already-running"; + public static final String REVIEW_NOT_FOUND = ERROR_PREFIX + "review-not-found"; } } @@ -332,9 +320,6 @@ public static final class Leaderboards { private Leaderboards() {} private static final String LBS = "leaderboards."; public static final String PAGES = LBS + "pages."; - public static final String ACTIONBAR_POSITION = LBS + "actionbar-position"; - public static final String ACTIONBAR_PERCENTAGE = LBS + "actionbar-percentage"; - public static final String NOT_ON_LEADERBOARD = LBS + "not-on-leaderboard"; } public static final class Tutorials { @@ -409,5 +394,17 @@ private Beginner() {} public static final String STAGE10_MESSAGES = STAGE10 + "stage-10-messages"; public static final String STAGE10_TASKS = STAGE10 + "stage-10-tasks"; } + + } + + public static final class Database { + private Database() {} + + private static final String DATABASE_PREFIX = "database."; + public static final String CITY_PROJECT = DATABASE_PREFIX + "city-project"; + public static final String COUNTRY = DATABASE_PREFIX + "country"; + public static final String DIFFICULTY = DATABASE_PREFIX + "difficulty"; + public static final String STATUS = DATABASE_PREFIX + "status"; + public static final String TOGGLE_CRITERIA = DATABASE_PREFIX + "toggle-criteria"; } } \ No newline at end of file diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/LangUtil.java b/src/main/java/com/alpsbte/plotsystem/utils/io/LangUtil.java index e6ce80f00..a83f7f43d 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/io/LangUtil.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/io/LangUtil.java @@ -1,34 +1,10 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.io; import com.alpsbte.plotsystem.PlotSystem; import com.alpsbte.plotsystem.utils.Utils.ChatUtils; import li.cinnazeyy.langlibs.core.LangLibAPI; -import li.cinnazeyy.langlibs.core.language.Language; import li.cinnazeyy.langlibs.core.file.LanguageFile; +import li.cinnazeyy.langlibs.core.language.Language; import li.cinnazeyy.langlibs.core.language.LanguageUtil; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -41,14 +17,14 @@ public static void init() { if (langUtilInstance != null) return; Plugin plugin = PlotSystem.getPlugin(); LangLibAPI.register(plugin, new LanguageFile[]{ - new LanguageFile(plugin, 2.2, Language.en_GB), - new LanguageFile(plugin, 2.2, Language.de_DE, "de_AT", "de_CH"), - new LanguageFile(plugin, 2.3, Language.fr_FR, "fr_CA"), - new LanguageFile(plugin, 2.2, Language.pt_PT, "pt_BR"), - new LanguageFile(plugin, 2.2, Language.ko_KR), - new LanguageFile(plugin, 2.2, Language.ru_RU, "ba_RU", "tt_RU"), - new LanguageFile(plugin, 2.2, Language.zh_CN), - new LanguageFile(plugin, 2.3, Language.zh_TW, "zh_HK"), + new LanguageFile(plugin, 2.5, Language.en_GB), + new LanguageFile(plugin, 2.5, Language.de_DE, "de_AT", "de_CH"), + new LanguageFile(plugin, 2.5, Language.fr_FR, "fr_CA"), + new LanguageFile(plugin, 2.5, Language.pt_PT, "pt_BR"), + new LanguageFile(plugin, 2.5, Language.ko_KR), + new LanguageFile(plugin, 2.5, Language.ru_RU, "ba_RU", "tt_RU"), + new LanguageFile(plugin, 2.5, Language.zh_CN), + new LanguageFile(plugin, 2.5, Language.zh_TW, "zh_HK"), new LanguageFile(plugin, 1.0, Language.he_IL), }); langUtilInstance = new LangUtil(); diff --git a/src/main/java/com/alpsbte/plotsystem/utils/io/TutorialPaths.java b/src/main/java/com/alpsbte/plotsystem/utils/io/TutorialPaths.java index 2ef2191b6..f021f9f89 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/io/TutorialPaths.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/io/TutorialPaths.java @@ -1,27 +1,3 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.io; public abstract class TutorialPaths { @@ -33,8 +9,7 @@ public static final class Beginner { public static final String POINT_2 = TELEPORT_COORDINATES + "point-2"; public static final String POINT_3 = TELEPORT_COORDINATES + "point-3"; public static final String POINT_4 = TELEPORT_COORDINATES + "point-4"; - public static final String BASE_BLOCK = BEGINNER + "base-block"; - public static final String BASE_BLOCK_ID = BEGINNER + "base-block-id"; + public static final String BASE_BLOCKS = BEGINNER + "base-blocks"; public static final String HEIGHT = BEGINNER + "height"; public static final String HEIGHT_OFFSET = BEGINNER + "height-offset"; public static final String WINDOW_POINTS = BEGINNER + "window-points"; diff --git a/src/main/java/com/alpsbte/plotsystem/utils/items/BaseItems.java b/src/main/java/com/alpsbte/plotsystem/utils/items/BaseItems.java index fb12a46f3..e3c08e011 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/items/BaseItems.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/items/BaseItems.java @@ -1,52 +1,40 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.items; -import com.alpsbte.alpslib.utils.item.ItemBuilder; +import com.alpsbte.alpslib.utils.item.ItemUtils; import com.alpsbte.plotsystem.utils.io.ConfigUtil; import org.bukkit.Material; +import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; public enum BaseItems { COMPANION_ITEM("companion-item"), - LEADERBOARD_PLOT("leaderboard-plot"), LEADERBOARD_SCORE("leaderboard-score"), PLOT_UNFINISHED("plot-unfinished"), PLOT_UNREVIEWED("plot-unreviewed"), PLOT_COMPLETED("plot-completed"), + PLOT_TYPE("plot-type"), + PLOT_FOCUS_MODE("plot-focus-mode"), + PLOT_CITY_INSPIRATION_MODE("plot-city-inspiration-mode"), + PLOT_SLOT_EMPTY("plot-slot-empty"), + PLOT_SLOT_FILLED("plot-slot-filled"), + PLOT_SUBMIT("plot-submit"), + PLOT_UNDO_SUBMIT("plot-undo-submit"), + PLOT_ABANDON("plot-abandon"), + PLOT_TELEPORT("plot-teleport"), MENU_ERROR("menu-error"), MENU_CLOSE("menu-close"), + MENU_BACK("menu-back"), + MENU_NEXT("menu-next"), + MENU_ADD("menu-add"), + MENU_REMOVE("menu-remove"), REVIEW_ITEM("review-item"), REVIEW_ACCURACY("review-accuracy"), REVIEW_BLOCK_PALETTE("review-block-palette"), - REVIEW_DETAILING("review-detailing"), - REVIEW_TECHNIQUE("review-technique"), REVIEW_POINT_ZERO("review-point-zero"), REVIEW_POINT_ONE("review-point-one"), REVIEW_POINT_TWO("review-point-two"), @@ -54,23 +42,41 @@ public enum BaseItems { REVIEW_POINT_FOUR("review-point-four"), REVIEW_POINT_FIVE("review-point-five"), REVIEW_SUBMIT("review-submit"), - REVIEW_CANCEL("review-cancel"), + REVIEW_INFO("review-info"), REVIEW_INFO_PLOT("review-info-plot"), + REVIEW_TOGGLE_OPTIONAL("review-toggle-optional"), + REVIEW_TOGGLE_REQUIRED("review-toggle-required"), + REVIEW_TOGGLE_CHECKED("review-toggle-checked"), + REVIEW_FEEDBACK("review-feedback"), + REVIEW_SCORE("review-score"), + BUILDER_UTILITIES("builder-utilities"), + FILTER_ITEM("filter-item"), SETTINGS_ITEM("settings-item"), - RANDOM_PLOT_ITEM("random-plot-item"); + RANDOM_PLOT_ITEM("random-plot-item"), + + DIFFICULTY_AUTOMATIC("difficulty-automatic"), + DIFFICULTY_EASY("difficulty-easy"), + DIFFICULTY_MEDIUM("difficulty-medium"), + DIFFICULTY_HARD("difficulty-hard"), + + TUTORIAL_ITEM("tutorial-item"), + + LANGUAGE_ITEM("language-item"); final ItemStack itemStack; BaseItems(String configPath) { String materialString = ConfigUtil.getInstance().configs[2].getString(configPath + ".material"); - Material material = Material.getMaterial(materialString == null ? "" : materialString, false); - material = material == null ? Material.BARRIER : material; + materialString = materialString == null ? Material.BARRIER.name() : materialString; + Object customModelData = ConfigUtil.getInstance().configs[2].get(configPath + ".modelId"); + itemStack = ItemUtils.getConfiguredItem(materialString, customModelData); - itemStack = new ItemBuilder(material).setItemModel(ConfigUtil.getInstance().configs[2].get(configPath + ".modelId")).build(); + itemStack.getItemMeta().setAttributeModifiers(null); + itemStack.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_ENCHANTS); } - public ItemStack getItem() { - return itemStack; + public @NotNull ItemStack getItem() { + return itemStack.clone(); } } diff --git a/src/main/java/com/alpsbte/plotsystem/utils/items/CustomHeads.java b/src/main/java/com/alpsbte/plotsystem/utils/items/CustomHeads.java deleted file mode 100644 index 36fbfc5ef..000000000 --- a/src/main/java/com/alpsbte/plotsystem/utils/items/CustomHeads.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2023, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alpsbte.plotsystem.utils.items; - -public enum CustomHeads { - WHITE_CONCRETE("8614"), - GREEN_CONCRETE("8621"), - YELLOW_CONCRETE("8613"), - RED_CONCRETE("8616"), - WORKBENCH("24180"), - ADD_BUTTON("9237"), - REMOVE_BUTTON("9243"), - BACK_BUTTON("9226"), - NEXT_BUTTON("9223"), - PREVIOUS_BUTTON("9226"), - INFO_BUTTON("46488"), - GLOBE_HEAD("49973"), - PLOT_TYPE_BUTTON("4159"), - FOCUS_MODE_BUTTON("38199"), - CITY_INSPIRATION_MODE_BUTTON("38094"); - - final String id; - - CustomHeads(String id) { - this.id = id; - } - - public String getId() { - return id; - } -} diff --git a/src/main/java/com/alpsbte/plotsystem/utils/items/MenuItems.java b/src/main/java/com/alpsbte/plotsystem/utils/items/MenuItems.java index 6a8087b1e..f52b8ee4f 100644 --- a/src/main/java/com/alpsbte/plotsystem/utils/items/MenuItems.java +++ b/src/main/java/com/alpsbte/plotsystem/utils/items/MenuItems.java @@ -1,30 +1,5 @@ -/* - * The MIT License (MIT) - * - * Copyright © 2025, Alps BTE - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - package com.alpsbte.plotsystem.utils.items; -import com.alpsbte.alpslib.utils.head.AlpsHeadUtils; import com.alpsbte.alpslib.utils.item.ItemBuilder; import com.alpsbte.alpslib.utils.item.LoreBuilder; import com.alpsbte.plotsystem.utils.io.LangPaths; @@ -34,7 +9,10 @@ import org.bukkit.inventory.ItemStack; import static net.kyori.adventure.text.Component.text; -import static net.kyori.adventure.text.format.NamedTextColor.*; +import static net.kyori.adventure.text.format.NamedTextColor.AQUA; +import static net.kyori.adventure.text.format.NamedTextColor.GOLD; +import static net.kyori.adventure.text.format.NamedTextColor.GRAY; +import static net.kyori.adventure.text.format.NamedTextColor.RED; import static net.kyori.adventure.text.format.TextDecoration.BOLD; public class MenuItems { @@ -47,19 +25,25 @@ public static ItemStack closeMenuItem(Player player) { } public static ItemStack backMenuItem(Player player) { - return new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.BACK_BUTTON.getId())) + return new ItemBuilder(BaseItems.MENU_BACK.getItem()) .setName(text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.BACK), GOLD, BOLD)) .build(); } + public static ItemStack continueMenuItem(Player player) { + return new ItemBuilder(BaseItems.MENU_NEXT.getItem()) + .setName(text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.CONTINUE), GOLD, BOLD)) + .build(); + } + public static ItemStack nextPageItem(Player player) { - return new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.NEXT_BUTTON.getId())) + return new ItemBuilder(BaseItems.MENU_NEXT.getItem()) .setName(text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.NEXT_PAGE), GOLD, BOLD)) .build(); } public static ItemStack previousPageItem(Player player) { - return new ItemBuilder(AlpsHeadUtils.getCustomHead(CustomHeads.PREVIOUS_BUTTON.getId())) + return new ItemBuilder(BaseItems.MENU_BACK.getItem()) .setName(text(LangUtil.getInstance().get(player, LangPaths.MenuTitle.PREVIOUS_PAGE), GOLD, BOLD)) .build(); } @@ -86,7 +70,7 @@ public static ItemStack loadingItem(ItemStack itemStack, Player player) { } public static ItemStack filterItem(Player langPlayer) { - return new ItemBuilder(Material.HOPPER, 1) + return new ItemBuilder(BaseItems.FILTER_ITEM.getItem()) .setName(text(LangUtil.getInstance().get(langPlayer, LangPaths.MenuTitle.FILTER_BY_COUNTRY), GOLD, BOLD)) .build(); } diff --git a/src/main/resources/DATABASE.sql b/src/main/resources/DATABASE.sql new file mode 100644 index 000000000..2ab7ca16c --- /dev/null +++ b/src/main/resources/DATABASE.sql @@ -0,0 +1,228 @@ +-- System Info +CREATE TABLE IF NOT EXISTS system_info +( + system_id INT NOT NULL AUTO_INCREMENT, + db_version DOUBLE NOT NULL, + current_plot_version DOUBLE NOT NULL, + last_update TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + description TEXT NULL, + PRIMARY KEY (system_id) +); + +-- Build Team +CREATE TABLE IF NOT EXISTS build_team +( + build_team_id INT NOT NULL AUTO_INCREMENT, + name VARCHAR(255) NOT NULL, + api_key VARCHAR(255) NULL UNIQUE, + api_create_date DATETIME NULL, + PRIMARY KEY (build_team_id) +); + +-- Server +CREATE TABLE IF NOT EXISTS server +( + build_team_id INT NOT NULL, + server_name VARCHAR(255) NOT NULL UNIQUE, + PRIMARY KEY (build_team_id, server_name), + FOREIGN KEY (build_team_id) REFERENCES build_team (build_team_id) + ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- Countries +CREATE TABLE IF NOT EXISTS country +( + country_code VARCHAR(2) NOT NULL, + continent ENUM ('EU','AS','AF','OC','SA','NA') NOT NULL, + material VARCHAR(255) NOT NULL, + custom_model_data VARCHAR(255) NULL, + PRIMARY KEY (country_code) +); + +-- City Projects +CREATE TABLE IF NOT EXISTS city_project +( + city_project_id VARCHAR(255) NOT NULL, + build_team_id INT NOT NULL, + country_code VARCHAR(2) NOT NULL, + server_name VARCHAR(255) NOT NULL, + is_visible BOOLEAN NOT NULL DEFAULT 1, + PRIMARY KEY (city_project_id), + FOREIGN KEY (build_team_id) REFERENCES build_team (build_team_id) + ON DELETE RESTRICT ON UPDATE CASCADE, + FOREIGN KEY (country_code) REFERENCES country (country_code) + ON DELETE RESTRICT ON UPDATE CASCADE, + FOREIGN KEY (server_name) REFERENCES server (server_name) + ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- Builders +CREATE TABLE IF NOT EXISTS builder +( + uuid VARCHAR(36) NOT NULL, + name VARCHAR(255) NOT NULL UNIQUE, + score INT NOT NULL DEFAULT 0, + first_slot INT NULL, + second_slot INT NULL, + third_slot INT NULL, + plot_type INT NOT NULL, + PRIMARY KEY (uuid) +); + +-- Difficulty +CREATE TABLE IF NOT EXISTS plot_difficulty +( + difficulty_id VARCHAR(255) NOT NULL, + multiplier DECIMAL(4, 2) DEFAULT 1.00, + score_requirement INT NOT NULL DEFAULT 0, + PRIMARY KEY (difficulty_id), + CHECK ( multiplier > 0 ), + CHECK ( score_requirement >= 0 ) +); + +-- Plot +CREATE TABLE IF NOT EXISTS plot +( + plot_id INT NOT NULL AUTO_INCREMENT, + city_project_id VARCHAR(255) NOT NULL, + difficulty_id VARCHAR(255) NOT NULL, + owner_uuid VARCHAR(36) NULL, + status ENUM ('unclaimed','unfinished','unreviewed','completed') NOT NULL DEFAULT 'unclaimed', + outline_bounds TEXT NOT NULL, + initial_schematic MEDIUMBLOB NOT NULL, + complete_schematic MEDIUMBLOB NULL, + last_activity_date DATETIME NULL, + is_pasted BOOLEAN NOT NULL DEFAULT 0, + mc_version VARCHAR(8) NULL, + plot_version DOUBLE NOT NULL, + plot_type INT NULL, + created_by VARCHAR(36) NOT NULL, + create_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (plot_id), + FOREIGN KEY (city_project_id) REFERENCES city_project (city_project_id) + ON DELETE RESTRICT ON UPDATE CASCADE, + FOREIGN KEY (difficulty_id) REFERENCES plot_difficulty (difficulty_id) + ON DELETE RESTRICT ON UPDATE CASCADE, + FOREIGN KEY (owner_uuid) REFERENCES builder (uuid) + ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- Tutorial +CREATE TABLE IF NOT EXISTS tutorial +( + tutorial_id INT NOT NULL, + uuid VARCHAR(36) NOT NULL, + stage_id INT NOT NULL DEFAULT 0, + is_complete BOOLEAN NOT NULL DEFAULT 0, + first_stage_start_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + last_stage_complete_date DATETIME NULL, + PRIMARY KEY (tutorial_id, uuid) +); + +-- Review +CREATE TABLE IF NOT EXISTS plot_review +( + review_id INT NOT NULL AUTO_INCREMENT, + plot_id INT NOT NULL, + rating VARCHAR(7) NOT NULL, + score INT NOT NULL DEFAULT 0, + feedback VARCHAR(512) NULL, + reviewed_by VARCHAR(36) NOT NULL, + review_date DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (review_id), + FOREIGN KEY (plot_id) REFERENCES plot (plot_id) + ON DELETE CASCADE ON UPDATE CASCADE +); + +-- Toggle Criteria +CREATE TABLE IF NOT EXISTS review_toggle_criteria +( + criteria_name VARCHAR(255) NOT NULL, + is_optional BOOLEAN NOT NULL, + PRIMARY KEY (criteria_name) +); + +-- Build team uses toggle criteria +CREATE TABLE IF NOT EXISTS build_team_uses_toggle_criteria +( + build_team_id INT NOT NULL, + criteria_name VARCHAR(255) NOT NULL, + PRIMARY KEY (build_team_id, criteria_name), + FOREIGN KEY (build_team_id) REFERENCES build_team (build_team_id) + ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (criteria_name) REFERENCES review_toggle_criteria (criteria_name) + ON DELETE CASCADE ON UPDATE CASCADE +); + +-- Review contains toggle criteria +CREATE TABLE IF NOT EXISTS review_contains_toggle_criteria +( + review_id INT NOT NULL, + criteria_name VARCHAR(255) NOT NULL, + is_checked BOOLEAN NOT NULL, + PRIMARY KEY (review_id, criteria_name), + FOREIGN KEY (review_id) REFERENCES plot_review (review_id) + ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (criteria_name) REFERENCES review_toggle_criteria (criteria_name) + ON DELETE CASCADE ON UPDATE CASCADE +); + +-- Build team has reviewer +CREATE TABLE IF NOT EXISTS build_team_has_reviewer +( + build_team_id INT NOT NULL, + uuid VARCHAR(36) NOT NULL, + PRIMARY KEY (build_team_id, uuid), + FOREIGN KEY (build_team_id) REFERENCES build_team (build_team_id) + ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (uuid) REFERENCES builder (uuid) + ON DELETE CASCADE ON UPDATE CASCADE +); + +-- Builder is plot member +CREATE TABLE IF NOT EXISTS builder_is_plot_member +( + plot_id INT NOT NULL, + uuid VARCHAR(36) NOT NULL, + PRIMARY KEY (plot_id, uuid), + FOREIGN KEY (plot_id) REFERENCES plot (plot_id) + ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (uuid) REFERENCES builder (uuid) + ON DELETE CASCADE ON UPDATE CASCADE +); + +-- Builder has review notification +CREATE TABLE IF NOT EXISTS builder_has_review_notification +( + review_id INT NOT NULL, + uuid VARCHAR(36) NOT NULL, + PRIMARY KEY (review_id, uuid), + FOREIGN KEY (review_id) REFERENCES plot_review (review_id) + ON DELETE CASCADE ON UPDATE CASCADE, + FOREIGN KEY (uuid) REFERENCES builder (uuid) + ON DELETE CASCADE ON UPDATE CASCADE +); + +-- Insert initial system info +INSERT INTO system_info (system_id, db_version, current_plot_version, description) +SELECT 1, 2.0, 4.0, 'Initial database schema for Plot-System v5.0' +FROM DUAL +WHERE NOT EXISTS (SELECT 1 FROM system_info); + +-- Insert initial review toggle criterias +INSERT INTO review_toggle_criteria (criteria_name, is_optional) +VALUES ('built_on_outlines', 0), + ('correct_amount_windows_doors', 0), + ('correct_facade_colour', 0), + ('correct_height', 0), + ('correct_roof_colour', 1), + ('correct_roof_shape', 0), + ('correct_window_type', 1), + ('windows_blacked_out', 0) +ON DUPLICATE KEY UPDATE criteria_name = VALUES(criteria_name); + +INSERT INTO plot_difficulty (difficulty_id, multiplier) +VALUES ('EASY', 1.0), + ('MEDIUM', 1.5), + ('HARD', 2) +ON DUPLICATE KEY UPDATE difficulty_id = VALUES(difficulty_id); \ No newline at end of file diff --git a/src/main/resources/commands.yml b/src/main/resources/commands.yml index 084fd4760..8f59bd111 100644 --- a/src/main/resources/commands.yml +++ b/src/main/resources/commands.yml @@ -2,8 +2,8 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/Plot-System/wiki/commands.yml +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot # ----------------------------------------------------- # Allow /editplot on plots for reviewers diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 69f4eeb95..1ef962434 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -2,13 +2,10 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/Plot-System/wiki/config.yml +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot # ----------------------------------------------------- -# Keep updated about newer versions -check-for-updates: true - # Enables special dev tools and features for development # NOTE: Do not change if you do not know what you are doing dev-mode: false @@ -21,20 +18,25 @@ spawn-world: default # Prevents beginners from generating difficult plots enable-score-requirement: true -# Automatic synchronisation of schematic files from SFTP/FTP servers -# [interval] -> default: 3600 seconds (1 hour) -sync-ftp-files: - sff-enable: false - sync-interval: 3600 - -# How many days of inactivity it will take before a claimed plot is automatically abandoned +# How many days of inactivity it will take before a claimed plot is automatically abandoned, -2 disables it inactivity-interval: 14 +# How many days of inactivity it will take before a rejected plots are automatically abandoned +# Use -1 to use the normal inactivity-interval, -2 disables it +rejected-inactivity-interval: -1 + # Enable or disable the Group System, that allows users to invite other Builders as members of their plot, # allowing them to build together. # NOTE: Score will be split by all participating members enable-group-support: true +# After how many minutes a player receives a reminder to finish his plot. +# Will be repeated every x minutes; It uses the unfinished-plots string, set it to -1 to disable +unfinished-reminder-interval: 20 + +# Disable the City Inspiration Mode (Beta) CIM completely for new plots (Temporary Config Setting) +disable-city-inspiration-mode: false + # ----------------------------------------------------- # | Supported databases: MariaDB & MySQL # ----------------------------------------------------- @@ -43,11 +45,15 @@ database: dbname: plotsystem username: plotsystem password: minecraft + max-lifetime: 1800000 # 30 minutes + connection-timeout: 30000 # 30 seconds + keepalive-time: 120000 # 2 minutes + maximum-pool-size: 10 # Maximum number of connections in the pool # ----------------------------------------------------- # | Leaderboards: Shows top plot and build scores / Are placed in the spawn world -# | NOTE: Requires the HolographicDisplays plugin to work +# | NOTE: Requires the DecentHolograms plugin to work # ----------------------------------------------------- holograms: # Displays the top 10 builders with the highest score @@ -56,12 +62,6 @@ holograms: sl-x: 0 sl-y: 0 sl-z: 0 - # Displays the top 10 players with the most completed plots - plots-leaderboard: - pl-enable: false - pl-x: 0 - pl-y: 0 - pl-z: 0 # Switch score-leaderboard between different time stamps # [interval] -> default: 15 seconds @@ -72,8 +72,6 @@ display-options: show-monthly: true show-yearly: false show-lifetime: false - action-bar-enable: true - action-bar-radius: 30 # ----------------------------------------------------- @@ -106,4 +104,4 @@ tutorials: # NOTE: Do not change -config-version: 3.0 \ No newline at end of file +config-version: 4.2 \ No newline at end of file diff --git a/src/main/resources/items.yml b/src/main/resources/items.yml index 0c448b40d..8185b795a 100644 --- a/src/main/resources/items.yml +++ b/src/main/resources/items.yml @@ -1,3 +1,10 @@ +# ----------------------------------------------------- +# | Plot System - by Alps BTE +# ----------------------------------------------------- +# | [Github Repo] https://github.com/AlpsBTE/PlotSystem +# | [Documentation] https://github.com/AlpsBTE/Plot-System/wiki/items.yml +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot +# ----------------------------------------------------- companion-item: material: NETHER_STAR modelId: '' @@ -18,6 +25,34 @@ plot-unreviewed: plot-completed: material: GREEN_WOOL modelId: '' +plot-type: + material: head(4159) + modelId: '' +plot-focus-mode: + material: head(38199) + modelId: '' +plot-city-inspiration-mode: + material: head(38094) + modelId: '' +plot-slot-empty: + material: MAP + modelId: '' +plot-slot-filled: + material: FILLED_MAP + modelId: '' +plot-submit: + material: NAME_TAG + modelId: '' +plot-undo-submit: + material: FIRE_CHARGE + modelId: '' +plot-abandon: + material: BARRIER + modelId: '' +plot-teleport: + material: COMPASS + modelId: '' + menu-error: material: BARRIER @@ -25,6 +60,18 @@ menu-error: menu-close: material: BARRIER modelId: '' +menu-back: + material: head(9226) + modelId: '' +menu-next: + material: head(9223) + modelId: '' +menu-add: + material: head(9237) + modelId: '' +menu-remove: + material: head(9243) + modelId: '' review-item: material: BOOK @@ -35,11 +82,14 @@ review-accuracy: review-block-palette: material: PAINTING modelId: '' -review-detailing: - material: ENDER_EYE +review-toggle-optional: + material: FIREWORK_STAR + modelId: '' +review-toggle-required: + material: FIRE_CHARGE modelId: '' -review-technique: - material: WOODEN_AXE +review-toggle-checked: + material: SLIME_BALL modelId: '' review-point-zero: material: LIGHT_GRAY_WOOL @@ -60,20 +110,57 @@ review-point-five: material: LIME_WOOL modelId: '' review-submit: - material: GREEN_CONCRETE + material: FIREWORK_ROCKET modelId: '' review-cancel: material: RED_CONCRETE modelId: '' +review-info: + material: head(46488) + modelId: '' review-info-plot: material: MAP modelId: '' +review-feedback: + material: WRITABLE_BOOK + modelId: '' +review-score: + material: NETHER_STAR + modelId: '' +builder-utilities: + material: GOLDEN_AXE + modelId: '' +filter-item: + material: HOPPER + modelId: '' settings-item: material: COMPARATOR modelId: '' random-plot-item: - material: COMPARATOR + material: MAGMA_CREAM + modelId: '' + +difficulty-automatic: + material: head(8614) modelId: '' +difficulty-easy: + material: head(8621) + modelId: '' +difficulty-medium: + material: head(8613) + modelId: '' +difficulty-hard: + material: head(8616) + modelId: '' + +tutorial-item: + material: head(24180) + modelId: '' + +language-item: + material: head(49973) + modelId: '' + # NOTE: Do not change -config-version: 1.2 \ No newline at end of file +config-version: 1.3 \ No newline at end of file diff --git a/src/main/resources/lang/de_DE.yml b/src/main/resources/lang/de_DE.yml index 76d857ffa..3bee8124b 100644 --- a/src/main/resources/lang/de_DE.yml +++ b/src/main/resources/lang/de_DE.yml @@ -2,8 +2,9 @@ #| Plot System - by Alps BTE #----------------------------------------------------- #| [Github Repo] https://github.com/AlpsBTE/PlotSystem -#| [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -#| [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +#| [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +#| [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot +#| [Localisation Platform] https://crowdin.com/project/alps-bte-plot-system #| #| [Formatting] Use %newline% for a newline #| [Formatting] Words that are wrapped in the {number} tag are replaced afterward @@ -68,6 +69,7 @@ difficulty: menu-title: close: 'Schließen' back: 'Zurück' + continue: 'Weiter' next-page: 'Nächste Seite' previous-page: 'Vorherige Seite' error: 'Fehler' @@ -157,15 +159,17 @@ review: feedback: "Feedback" reviewer: "Reviewer" player-language: "Spielersprache" + no-feedback: "No feedback" + accuracy-points: "Accuracy points" + block-palette-points: "Block palette points" + toggle-points: "Toggle points" + total-points: "Total points" + abandoned-in-days: "§6Wird in §6{0} Tagen gelöscht" criteria: accuracy: "Genauigkeit" accuracy-desc: "Wie akkurat ist das Gebäude?%newline%%newline%- Sieht aus wie in RL%newline%- Korrekte Umrisse%newline%- Korrekte Höhen%newline%- Ist vollständig" block-palette: "Block-Palette" block-palette-desc: "Wie viele und wie kreativ werden verschiedene Blöcke verwendet?%newline%%newline%- Wahl der Blockfarben/Texturen%newline%- Randomisierte Blöcke" - detailing: "Detaillierung" - detailing-desc: "Wie viele Details hat das Gebäude?%newline%%newline%- Dachdetails%newline%- Details an den Fassaden%newline%- Köpfe und Banner" - technique: "Technik" - technique-desc: "Welche Bautechniken wurden verwendet und wie kreativ sind sie?%newline%%newline%- World-Edit%newline%- Spezialblöcke" #----------------------------------------------------- #| Notes #----------------------------------------------------- @@ -175,6 +179,11 @@ note: wont-be-able-continue-building: "Du wirst auf diesem Plot nicht weiterbauen können!" score-will-be-split: "Die Punkte werden bei der Bewertung auf alle Mitglieder aufgeteilt!" player-has-to-be-online: "Spieler muss online sein!" + optional: "Optional" + required: "Required" + criteria-fulfilled: "Fulfilled" + criteria-not-fulfilled: "Not fulfilled" + legacy: "LEGACY" action: read: 'Gelesen' read-more: 'Mehr lesen' @@ -197,6 +206,8 @@ note: click-to-show-plots: "§6Klicke hier, §aum deine Plots anzuzeigen..." click-to-play-with-friends: "§7Willst du mit deinen Freunden spielen? §6Klicke hier..." tutorial-show-stages: 'Stages Anzeigen' + click-to-open-plots-menu: 'Klicke hier, um das Plot Menü zu öffnen...' + click-to-toggle: "Click to toggle..." #----------------------------------------------------- #| Messages #----------------------------------------------------- @@ -209,7 +220,7 @@ message: plot-marked-as-reviewed: "§aPlot §6#{0}§a von §6{1}§a wurde als geprüft markiert!" plot-rejected: "§aPlot §6#{0}§a von §6{1}§a wurde abgelehnt!" undid-submission: "§aDie Einreichung des Plots §6#{0}§a wurde rückgängig gemacht!" - undid-review: "§aDie Bewertung des Plots §6#{0}§a von §6#{1}§a wurde rückgängig gemacht!" + undid-review: "§aDie Bewertung des Plots §6#{0}§a von §6{1}§a wurde rückgängig gemacht!" reviewed-plot: "§aDein Plot §6#{0}§a wurde bewertet!" unreviewed-plot: "§aEs gibt §6{0}§a unbewerteten Plot!" unreviewed-plots: "§aEs gibt §6{0}§a unbewertete Plots!" @@ -221,7 +232,10 @@ message: removed-plot-member: "§a§6{0}§a wurde vom Plot entfernt §6#{1}§a!" left-plot: "§aVerlasse Plot §6#{0}§a!" plot-will-get-abandoned-warning: "§c§lWARNING: §cDieser Plot wird automatisch aufgelassen werden!" - plot-will-get-rejected-warning: "§c§lWARNING: §cDieser Plot wird abgelehnt werden!" + plot-will-be-rejected: "Plot will be rejected!" + plot-will-be-accepted: "Plot will be accepted" + plots-reviewed-singular: "{0} plot has been reviewed!" + plots-reviewed-plural: "{0} plots have been reviewed!" saving-plot: "§aSpeichere Plot..." creating-plot: "§aErstelle neuen Plot..." created-new-plot: "§aEin neuer Plot§a wurde für §6{0}§a erstellt!" @@ -247,6 +261,8 @@ message: cannot-undo-review: "Du kannst eine Bewertung nicht rückgängig machen, wenn du sie nicht selbst erstellt hast!" cannot-send-feedback: "Du kannst auf einen Plot kein Feedback geben, wenn du ihn nicht selbst bewertet hast!" cannot-review-own-plot: "Du kannst deine eigenen Plots nicht bewerten!" + cannot-modify-legacy-plot: "Legacy plots cannot be modified!" + cannot-load-legacy-plot: "Legacy plots cannot be loaded!" player-has-no-permissions: "Du hast keine Berechtigung dafür!" player-has-no-invitations: "Du hast keine offenen Einladungen!" player-is-not-allowed: "Du bist dazu nicht berechtigt!" @@ -260,6 +276,7 @@ message: player-invite-to-rejected: '{0} hat deine Einladung abgelehnt.' player-needs-to-be-on-plot: "Um dies zu nutzen musst du auf einem Plot sein!" player-needs-higher-score: "Du benötigst einen höheren Punktestand, um in diesem Schwierigkeitsgrad zu bauen." + player-missing-tutorial: "Der Spieler muss zuerst das Tutorial abschließen, um hinzugefügt zu werden!" error-occurred: "Ein Fehler ist aufgetreten! Bitte versuche es erneut!" command-disabled: "Dieser Befehl ist deaktiviert!" no-plots-left: "Für diese Stadt gibt es keine freien Plots mehr. Bitte wähle einen anderen Ort." @@ -268,6 +285,7 @@ message: chat-input-expired: "Die Eingabe ist abgelaufen." tutorial-disabled: 'Tutorials sind auf diesem Server deaktiviert.' tutorial-already-running: "Du hast bereits ein Tutorial am Laufen! Schließe dieses ab, bevor du ein neues beginnst." + review-not-found: "Review could not be found!" leaderboards: pages: DAILY: "Heute" @@ -388,5 +406,46 @@ tutorials: - 'Frohes Bauen! ☺' stage-10-tasks: - 'Lies alle Tipps auf dem Plot und markiere sie als gelesen.' +# ----------------------------------------------------- +# | Database +# ----------------------------------------------------- +database: + city-project: + example-city: + name: 'Beispiel Stadt' + description: 'Eine Beschreibung' + country: + AT: + name: 'Österreich' + CH: + name: 'Schweiz' + LI: + name: 'Liechtenstein' + difficulty: + easy: + name: 'Easy' + medium: + name: 'Medium' + hard: + name: 'Hard' + status: + unclaimed: + name: 'Unclaimed' + unfinished: + name: 'Unfinished' + unreviewed: + name: 'Unreviewed' + completed: + name: 'Completed' + toggle-criteria: + built_on_outlines: 'Built on outlines' + correct_height: 'Correct building height' + correct_facade_colour: 'Correct building colour' + correct_roof_colour: 'Correct roof colour' + correct_roof_shape: 'Correct roof shape' + correct_amount_windows_doors: 'Correct amount of windows and doors' + correct_window_type: 'Correct window types' + windows_blacked_out: 'All windows blacked out' + #NOTE: Do not change -config-version: 2.2 +config-version: 2.5 \ No newline at end of file diff --git a/src/main/resources/lang/en_GB.yml b/src/main/resources/lang/en_GB.yml index bd6325dbf..7ace968fe 100644 --- a/src/main/resources/lang/en_GB.yml +++ b/src/main/resources/lang/en_GB.yml @@ -2,8 +2,9 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot +# | [Localisation Platform] https://crowdin.com/project/alps-bte-plot-system # | # | [Formatting] Use %newline% for a newline # | [Formatting] Words that are wrapped in the {number} tag are replaced afterward @@ -68,6 +69,7 @@ difficulty: menu-title: close: 'Close' back: 'Back' + continue: 'Continue' next-page: 'Next Page' previous-page: 'Previous Page' error: 'Error' @@ -157,15 +159,17 @@ review: feedback: "Feedback" reviewer: "Reviewer" player-language: "Player Language" + no-feedback: "No feedback" + accuracy-points: "Accuracy points" + block-palette-points: "Block palette points" + toggle-points: "Toggle points" + total-points: "Total points" + abandoned-in-days: "§6Abandoned in §6{0} days" criteria: accuracy: "Accuracy" accuracy-desc: "How accurate is the building?%newline%%newline%- Looks like in RL%newline%- Correct outlines%newline%- Correct height%newline%- Is completed" block-palette: "Block Palette" block-palette-desc: "How many different blocks are used and how creative are they?%newline%%newline%- Choice of blocks colours/textures%newline%- Random blocks" - detailing: "Detailing" - detailing-desc: "How much detail does the building have?%newline%%newline%- Roof details%newline%- Details on the facades%newline%- Heads and Banners" - technique: "Technique" - technique-desc: "What building techniques have been used and how creative are they?%newline%%newline%- World-Edit%newline%- Special Blocks" # ----------------------------------------------------- # | Notes # ----------------------------------------------------- @@ -175,6 +179,11 @@ note: wont-be-able-continue-building: "You wont be able to continue building on this plot!" score-will-be-split: "Score will be split between all members when reviewed!" player-has-to-be-online: "The player has to be online!" + optional: "Optional" + required: "Required" + criteria-fulfilled: "Fulfilled" + criteria-not-fulfilled: "Not fulfilled" + legacy: "LEGACY" action: read: 'Read' read-more: 'Read More' @@ -197,6 +206,8 @@ note: click-to-show-plots: "§6Click Here §ato show your plots..." click-to-play-with-friends: "§7Want to play with your friends? §6Click Here..." tutorial-show-stages: 'Show Stages' + click-to-open-plots-menu: 'Click to open the plots menu...' + click-to-toggle: "Click to toggle..." # ----------------------------------------------------- # | Messages # ----------------------------------------------------- @@ -209,7 +220,7 @@ message: plot-marked-as-reviewed: "§aPlot §6#{0}§a by §6{1}§a has been marked as reviewed!" plot-rejected: "§aPlot §6#{0}§a by §6{1}§a has been rejected!" undid-submission: "§aUndid submission of plot §6#{0}§a!" - undid-review: "§aUndid review of plot §6#{0}§a by §6#{1}§a!" + undid-review: "§aUndid review of plot §6#{0}§a by §6{1}§a!" reviewed-plot: "§aYour plot §6#{0}§a has been reviewed!" unreviewed-plot: "§aThere is §6{0}§a unreviewed plot!" unreviewed-plots: "§aThere are §6{0}§a unreviewed plots!" @@ -221,7 +232,10 @@ message: removed-plot-member: "§aRemoved §6{0}§a from plot §6#{1}§a!" left-plot: "§aLeft plot §6#{0}§a!" plot-will-get-abandoned-warning: "§c§lWARNING: §cThis plot will automatically get abandoned!" - plot-will-get-rejected-warning: "§c§lWARNING: §cThis plot will get rejected!" + plot-will-be-rejected: "Plot will be rejected!" + plot-will-be-accepted: "Plot will be accepted" + plots-reviewed-singular: "{0} plot has been reviewed!" + plots-reviewed-plural: "{0} plots have been reviewed!" saving-plot: "§aSaving plot..." creating-plot: "§aCreating new plot..." created-new-plot: "§aCreated new plot§a for §6{0}§a!" @@ -247,6 +261,8 @@ message: cannot-undo-review: "You cannot undo a review that you have not reviewed yourself!" cannot-send-feedback: "You cannot send feedback to a plot that you have not reviewed yourself!" cannot-review-own-plot: "You cannot review your own plot!" + cannot-modify-legacy-plot: "Legacy plots cannot be modified!" + cannot-load-legacy-plot: "Legacy plots cannot be loaded!" player-has-no-permissions: "You do not have permission to do this!" player-has-no-invitations: "You have no invitations!" player-is-not-allowed: "You are not allowed to do this!" @@ -260,6 +276,7 @@ message: player-invite-to-rejected: '{0} has rejected your invitation.' player-needs-to-be-on-plot: "You need to be on a plot in order to use this!" player-needs-higher-score: "You need a higher score to build in this difficulty level." + player-missing-tutorial: "The player must first complete the tutorial to be added to the plot!" error-occurred: "An error occurred! Please try again!" command-disabled: "This command is disabled!" no-plots-left: "This city project does not have any more plots left. Please select another project." @@ -268,6 +285,7 @@ message: chat-input-expired: "The chat input has expired." tutorial-disabled: 'Tutorials are disabled on this server.' tutorial-already-running: "You already have a tutorial running! Complete it before starting a new one." + review-not-found: "Review could not be found!" leaderboards: pages: DAILY: "Daily" @@ -388,5 +406,46 @@ tutorials: - 'Happy building! ☺' stage-10-tasks: - 'Read all tips on the plot and mark them as read.' +# ----------------------------------------------------- +# | Database +# ----------------------------------------------------- +database: + city-project: + example-city: + name: 'Example City' + description: 'Some description' + country: + AT: + name: 'Austria' + CH: + name: 'Switzerland' + LI: + name: 'Liechtenstein' + difficulty: + easy: + name: 'Easy' + medium: + name: 'Medium' + hard: + name: 'Hard' + status: + unclaimed: + name: 'Unclaimed' + unfinished: + name: 'Unfinished' + unreviewed: + name: 'Unreviewed' + completed: + name: 'Completed' + toggle-criteria: + built_on_outlines: 'Built on outlines' + correct_height: 'Correct building height' + correct_facade_colour: 'Correct building colour' + correct_roof_colour: 'Correct roof colour' + correct_roof_shape: 'Correct roof shape' + correct_amount_windows_doors: 'Correct amount of windows and doors' + correct_window_type: 'Correct window types' + windows_blacked_out: 'All windows blacked out' + # NOTE: Do not change -config-version: 2.2 +config-version: 2.5 \ No newline at end of file diff --git a/src/main/resources/lang/fr_FR.yml b/src/main/resources/lang/fr_FR.yml index d50ea3ca7..6f78c20bb 100644 --- a/src/main/resources/lang/fr_FR.yml +++ b/src/main/resources/lang/fr_FR.yml @@ -2,8 +2,9 @@ #| Plot System - by Alps BTE #----------------------------------------------------- #| [Github Repo] https://github.com/AlpsBTE/PlotSystem -#| [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -#| [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +#| [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +#| [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot +#| [Localisation Platform] https://crowdin.com/project/alps-bte-plot-system #| #| [Formatting] Use %newline% for a newline #| [Formatting] Words that are wrapped in the {number} tag are replaced afterward @@ -68,6 +69,7 @@ difficulty: menu-title: close: 'Fermer' back: 'Retour' + continue: 'Continue' next-page: 'Page Suivante' previous-page: 'Page Précédente' error: 'Erreur' @@ -157,15 +159,16 @@ review: feedback: "Commentaires" reviewer: "Relecteur" player-language: "Langage du joueur" + no-feedback: "No feedback" + accuracy-points: "Accuracy points" + block-palette-points: "Block palette points" + toggle-points: "Toggle points" + total-points: "Total points" criteria: accuracy: "Précision" accuracy-desc: "Quelle est la précision du bâtiment?%newline%%newline%- Ressemble à RL%newline%- Contours corrects%newline%- Hauteur correcte%newline%- Est terminé" block-palette: "palette de blocs" block-palette-desc: "Combien de blocs différents sont utilisés et à quel point sont-ils créatifs?%newline%%newline%- Choix des couleurs/textures des blocs%newline%- Blocs aléatoires" - detailing: "Détail" - detailing-desc: "Combien de détails le bâtiment a-t-il?%newline%%newline%- Détails du toit%newline%- Détails sur les façades%newline%- Têtes et bannières" - technique: "Technique" - technique-desc: "Quelles techniques de construction ont été utilisées et à quel point sont-elles créatives?%newline%%newline%- World-Edit%newline%- Blocs spéciaux" #----------------------------------------------------- #| Notes #----------------------------------------------------- @@ -175,6 +178,11 @@ note: wont-be-able-continue-building: "Vous ne pourrez plus continuer à construire sur ce terrain!" score-will-be-split: "Le score sera partagé entre tous les membres lors de la révision!" player-has-to-be-online: "Le joueur doit être en ligne!" + optional: "Optional" + required: "Required" + criteria-fulfilled: "Fulfilled" + criteria-not-fulfilled: "Not fulfilled" + legacy: "LEGACY" action: read: 'Lire' read-more: 'En savoir plus' @@ -197,6 +205,8 @@ note: click-to-show-plots: "§6Cliquez ici §apour afficher vos tracés..." click-to-play-with-friends: "§7Vous voulez jouer avec vos amis? §6Cliquez ici..." tutorial-show-stages: 'Montrer les étapes' + click-to-open-plots-menu: 'Cliquez pour ouvrir le menu des parcelles...' + click-to-toggle: "Click to toggle..." #----------------------------------------------------- #| Messages #----------------------------------------------------- @@ -209,7 +219,7 @@ message: plot-marked-as-reviewed: "§aLe terrain §6#{0}§a par §6{1}§a a été marqué comme révisé!" plot-rejected: "§aLe tracé §6#{0}§a par §6{1}§a a été rejeté!" undid-submission: "§aUndid soumission du complot §6#{0}§a!" - undid-review: "§aChangement les commentaires de la parcelle§6#{0}§a par §6#{1}§a!" + undid-review: "§aChangement les commentaires de la parcelle§6#{0}§a par §6{1}§a!" reviewed-plot: "§aVotre parcelle §6#{0}§a a été revue!" unreviewed-plot: "§aIl y a §6{0}§a un complot non révisé!" unreviewed-plots: "§aIl y a §6{0}§a des parcelles non revues!" @@ -221,7 +231,10 @@ message: removed-plot-member: "§aSupprimé §6{0}§a du tracé §6#{1}§a!" left-plot: "§aTracé de gauche §6#{0}§a!" plot-will-get-abandoned-warning: "§c§lATTENTION: §cCette parcelle sera automatiquement abandonnée!" - plot-will-get-rejected-warning: "§c§lATTENTION: §cCette parcelle sera rejetée!" + plot-will-be-rejected: "Plot will be rejected!" + plot-will-be-accepted: "Plot will be accepted" + plots-reviewed-singular: "{0} plot has been reviewed!" + plots-reviewed-plural: "{0} plots have been reviewed!" saving-plot: "§aEnregistrement de l'intrigue..." creating-plot: "§aCréation d'un nouveau tracé..." created-new-plot: "§aCréé un nouveau tracé§a pour §6{0}§a!" @@ -247,6 +260,8 @@ message: cannot-undo-review: "Vous ne pouvez pas annuler une révision que vous n'avez pas révisée vous-même!" cannot-send-feedback: "Vous ne pouvez pas envoyer de commentaires à un tracé que vous n'avez pas révisé vous-même!" cannot-review-own-plot: "Vous ne pouvez pas réviser votre propre intrigue!" + cannot-modify-legacy-plot: "Legacy plots cannot be modified!" + cannot-load-legacy-plot: "Legacy plots cannot be loaded!" player-has-no-permissions: "Vous n'avez pas la permission de faire ça!" player-has-no-invitations: "Vous n'avez aucune invitation!" player-is-not-allowed: "Vous n'êtes pas autorisé à faire ça!" @@ -260,6 +275,7 @@ message: player-invite-to-rejected: '{0} a rejeté votre invitation.' player-needs-to-be-on-plot: "Vous devez être sur un terrain pour pouvoir l'utiliser!" player-needs-higher-score: "Vous avez besoin d'un score plus élevé pour intégrer ce niveau de difficulté." + player-missing-tutorial: "Le joueur doit d'abord terminer le tutoriel pour être intégré à l'intrigue!" error-occurred: "Une erreur s'est produite! Veuillez réessayer!" command-disabled: "Cette commande est désactivée!" no-plots-left: "Ce projet de ville n'a plus de parcelles restantes. Veuillez sélectionner un autre projet." @@ -268,6 +284,7 @@ message: chat-input-expired: "La saisie du chat a expiré." tutorial-disabled: 'Les tutoriels sont désactivés sur ce serveur.' tutorial-already-running: "Vous avez déjà un tutoriel en cours ! Terminez-le avant d'en commencer un nouveau." + review-not-found: "Review could not be found!" leaderboards: pages: DAILY: "Quotidien" @@ -388,5 +405,46 @@ tutorials: - 'Bonne construction ! ☺' stage-10-tasks: - 'Lisez tous les conseils sur les parcelles et marquez-les comme lus.' +# ----------------------------------------------------- +# | Database +# ----------------------------------------------------- +database: + city-project: + example-city: + name: 'Example City' + description: 'Some description' + country: + AT: + name: 'Austria' + CH: + name: 'Switzerland' + LI: + name: 'Liechtenstein' + difficulty: + easy: + name: 'Easy' + medium: + name: 'Medium' + hard: + name: 'Hard' + status: + unclaimed: + name: 'Unclaimed' + unfinished: + name: 'Unfinished' + unreviewed: + name: 'Unreviewed' + completed: + name: 'Completed' + toggle-criteria: + built_on_outlines: 'Built on outlines' + correct_height: 'Correct building height' + correct_facade_colour: 'Correct building colour' + correct_roof_colour: 'Correct roof colour' + correct_roof_shape: 'Correct roof shape' + correct_amount_windows_doors: 'Correct amount of windows and doors' + correct_window_type: 'Correct window types' + windows_blacked_out: 'All windows blacked out' + #NOTE: Do not change -config-version: 2.3 \ No newline at end of file +config-version: 2.5 \ No newline at end of file diff --git a/src/main/resources/lang/he_IL.yml b/src/main/resources/lang/he_IL.yml index 7c5b0513c..e36261d4c 100644 --- a/src/main/resources/lang/he_IL.yml +++ b/src/main/resources/lang/he_IL.yml @@ -2,8 +2,9 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot +# | [Localisation Platform] https://crowdin.com/project/alps-bte-plot-system # | # | [Formatting] Use %newline% for a newline # | [Formatting] Words that are wrapped in the {number} tag are replaced afterward diff --git a/src/main/resources/lang/ko_KR.yml b/src/main/resources/lang/ko_KR.yml index 4b72f2b0b..fd271fe18 100644 --- a/src/main/resources/lang/ko_KR.yml +++ b/src/main/resources/lang/ko_KR.yml @@ -2,8 +2,9 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot +# | [Localisation Platform] https://crowdin.com/project/alps-bte-plot-system # | # | [Formatting] Use %newline% for a newline # | [Formatting] Words that are wrapped in the {number} tag are replaced afterward @@ -68,6 +69,7 @@ difficulty: menu-title: close: "닫기" back: "뒤로가기" + continue: 'Continue' next-page: "다음 페이지" previous-page: "이전 페이지" error: "에러" @@ -157,15 +159,16 @@ review: feedback: "피드백" reviewer: "검토자" player-language: "Player Language" + no-feedback: "No feedback" + accuracy-points: "Accuracy points" + block-palette-points: "Block palette points" + toggle-points: "Toggle points" + total-points: "Total points" criteria: accuracy: "정확도" accuracy-desc: "얼마나 정확하게 건축되었나요?%newline%%newline%- 현실과의 유사성%newline%- 올바른 외곽선%newline%- 올바른 높이%newline%- 완성도" block-palette: "블록 선정" block-palette-desc: "사용된 블록이 얼마나 다양하고 창의적인가요?%newline%%newline%- 사용된 블록의 색깔/질감%newline%- 블록의 무작위성" - detailing: "디테일" - detailing-desc: "건물의 디테일이 얼마나 잘 구현되어있나요?%newline%%newline%- 지붕 디테일%newline%- 건물 정면 디테일%newline%- 머리와 현수막의 사용" - technique: "기법" - technique-desc: "사용된 건축 기법들은 무엇이고 얼마나 창의적인가요?%newline%%newline%- 월드에딧%newline%- 특수 블록" # ----------------------------------------------------- # | Notes # ----------------------------------------------------- @@ -175,6 +178,11 @@ note: wont-be-able-continue-building: "더 이상 이 플롯에서 건축하실 수 없게 됩니다!" score-will-be-split: "리뷰된 후에는 플롯의 모든 멤버에게 점수가 배분될 것입니다." player-has-to-be-online: "해당 플레이어가 접속 중이어야 합니다!" + optional: "Optional" + required: "Required" + criteria-fulfilled: "Fulfilled" + criteria-not-fulfilled: "Not fulfilled" + legacy: "LEGACY" action: read: 'Read' read-more: 'Read More' @@ -197,6 +205,8 @@ note: click-to-show-plots: "§6여기§a를 클릭해 자신의 플롯들을 확인하세요!" click-to-play-with-friends: "§7친구와 플레이하시려면 §6여기§7를 클릭하세요!" tutorial-show-stages: 'Show Stages' + click-to-open-plots-menu: "클릭하여 플롯 메뉴 열기..." + click-to-toggle: "Click to toggle..." # ----------------------------------------------------- # | Messages # ----------------------------------------------------- @@ -221,7 +231,10 @@ message: removed-plot-member: "§6{0}§a님을 플롯 §6#{1}§a에서 제외하였습니다!" left-plot: "§a플롯 §6#{0}§a을 나갔습니다!" plot-will-get-abandoned-warning: "§c§l경고: §c이 플롯은 자동으로 버려질 것입니다!" - plot-will-get-rejected-warning: "§c§l경고: §c이 플롯은 거절될 것입니다!" + plot-will-be-rejected: "Plot will be rejected!" + plot-will-be-accepted: "Plot will be accepted" + plots-reviewed-singular: "{0} plot has been reviewed!" + plots-reviewed-plural: "{0} plots have been reviewed!" saving-plot: "§a플롯 저장 중..." creating-plot: "§a새로운 플롯 생성 중..." created-new-plot: "§6{0}§a님의 플롯을 생성하였습니다!" @@ -247,6 +260,8 @@ message: cannot-undo-review: "오직 자신의 리뷰만 취소할 수 있습니다!" cannot-send-feedback: "오직 자신이 리뷰한 플롯에만 피드백을 보낼 수 있습니다!" cannot-review-own-plot: "자신의 플롯은 검토할 수 없습니다!" + cannot-modify-legacy-plot: "Legacy plots cannot be modified!" + cannot-load-legacy-plot: "Legacy plots cannot be loaded!" player-has-no-permissions: "이 기능을 사용할 수 있는 권한이 없습니다!" player-has-no-invitations: "초대장이 없습니다!" player-is-not-allowed: "권한이 없습니다!" @@ -260,6 +275,7 @@ message: player-invite-to-rejected: '{0} has rejected your invitation.' player-needs-to-be-on-plot: "플롯에서만 사용할 수 있습니다!" player-needs-higher-score: "해당 난이도에서 건축하시려면 더 높은 점수가 필요합니다." + player-missing-tutorial: "플레이어는 먼저 튜토리얼을 완료해야 플롯에 추가할 수 있습니다!" error-occurred: "에러 발생! 다시 시도해주세요!" command-disabled: "비활성화된 커맨드입니다!" no-plots-left: "이 도시 프로젝트에 남아있는 플롯이 없습니다. 다른 프로젝트를 선택해주세요." @@ -268,6 +284,7 @@ message: chat-input-expired: "The chat input has expired." tutorial-disabled: 'Tutorials are disabled on this server.' tutorial-already-running: "You already have a tutorial running! Complete it before starting a new one." + review-not-found: "Review could not be found!" leaderboards: pages: DAILY: "Daily" @@ -388,5 +405,46 @@ tutorials: - 'Happy building! ☺' stage-10-tasks: - 'Read all tips on the plot and mark them as read.' +# ----------------------------------------------------- +# | Database +# ----------------------------------------------------- +database: + city-project: + example-city: + name: 'Example City' + description: 'Some description' + country: + AT: + name: 'Austria' + CH: + name: 'Switzerland' + LI: + name: 'Liechtenstein' + difficulty: + easy: + name: 'Easy' + medium: + name: 'Medium' + hard: + name: 'Hard' + status: + unclaimed: + name: 'Unclaimed' + unfinished: + name: 'Unfinished' + unreviewed: + name: 'Unreviewed' + completed: + name: 'Completed' + toggle-criteria: + built_on_outlines: 'Built on outlines' + correct_height: 'Correct building height' + correct_facade_colour: 'Correct building colour' + correct_roof_colour: 'Correct roof colour' + correct_roof_shape: 'Correct roof shape' + correct_amount_windows_doors: 'Correct amount of windows and doors' + correct_window_type: 'Correct window types' + windows_blacked_out: 'All windows blacked out' + # NOTE: Do not change -config-version: 2.2 +config-version: 2.5 \ No newline at end of file diff --git a/src/main/resources/lang/pt_PT.yml b/src/main/resources/lang/pt_PT.yml index 2d16775c7..4814dbbc0 100644 --- a/src/main/resources/lang/pt_PT.yml +++ b/src/main/resources/lang/pt_PT.yml @@ -2,8 +2,9 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot +# | [Localisation Platform] https://crowdin.com/project/alps-bte-plot-system # | # | [Formatting] Use %newline% for a newline # | [Formatting] Words that are wrapped in the {number} tag are replaced afterward @@ -68,6 +69,7 @@ difficulty: menu-title: close: "Fechar" back: "Voltar" + continue: 'Continue' next-page: "Próxima Página" previous-page: "Página Anterior" error: "Erro" @@ -157,15 +159,16 @@ review: feedback: "Feedback" reviewer: "Avaliador" player-language: "Player Language" + no-feedback: "No feedback" + accuracy-points: "Accuracy points" + block-palette-points: "Block palette points" + toggle-points: "Toggle points" + total-points: "Total points" criteria: accuracy: "Precisão" accuracy-desc: "Quão precisa é a construção?%newline%%newline%- Pare como na vida real%newline%- MArcação correta%newline%- Altura correta%newline%- Completa" block-palette: "Paleta de Blocos" block-palette-desc: "Quantos blocos diferentes são usados e quão criativos eles são?%newline%%newline%- Escolha de cores/texturas de blocos%newline%- Blocos aleatórios" - detailing: "Detalhamento" - detailing-desc: "Quão detalhada é a construção?%newline%%newline%- Detalhes do telhado%newline%- Detalhes na Fachada%newline%- Cabeças e estandartes" - technique: "Técnica" - technique-desc: "Quais técnicas de construção foram utilizadas e quão criativas elas são?%newline%%newline%- World-Edit%newline%- Blocos especiais" # ----------------------------------------------------- # | Notes # ----------------------------------------------------- @@ -175,6 +178,11 @@ note: wont-be-able-continue-building: "Você não poderá continuar construindo neste terreno!" score-will-be-split: "A pontuação será dividida entre todos os membros quando revisada!" player-has-to-be-online: "O jogador tem que estar online!" + optional: "Optional" + required: "Required" + criteria-fulfilled: "Fulfilled" + criteria-not-fulfilled: "Not fulfilled" + legacy: "LEGACY" action: read: 'Read' read-more: 'Read More' @@ -197,6 +205,8 @@ note: click-to-show-plots: "§6Clique aqui §apara mostrar seus terrenos..." click-to-play-with-friends: "§7Quer jogar com seus amigos? §6Clique aqui..." tutorial-show-stages: 'Show Stages' + click-to-open-plots-menu: 'Clique para abrir o menu de parcelas...' + click-to-toggle: "Click to toggle..." # ----------------------------------------------------- # | Messages # ----------------------------------------------------- @@ -209,7 +219,7 @@ message: plot-marked-as-reviewed: "§aTerreno §6#{0}§a por §6{1}§a foi marcado como avaliado!" plot-rejected: "§aTerreno §6#{0}§a por §6{1}§a foi rejeitado!Envie feedback usando §6/sendFeedback §a!" undid-submission: "§aEnvio do Terreno Desfeito §6#{0}§a!" - undid-review: "§aAvaliação do Terreno Desfeita §6#{0}§a por §6#{1}§a!" + undid-review: "§aAvaliação do Terreno Desfeita §6#{0}§a por §6{1}§a!" reviewed-plot: "§aSeu terreno §6#{0}§a foi avaliado!" unreviewed-plot: "§aExiste um §6{0}§a terreno não avaliado!" unreviewed-plots: "§aExistem §6{0}§a terrenos não avaliados!" @@ -221,7 +231,10 @@ message: removed-plot-member: "§aRemovido §6{0}§a do terreno §6#{1}§a!" left-plot: "§aDeixou o terreno §6#{0}§a!" plot-will-get-abandoned-warning: "§c§lAVISO: §cEsse terreno vai ser abandonado automaticamente!" - plot-will-get-rejected-warning: "§c§lAVISO: §cEsse terreno vai ser rejeitado!" + plot-will-be-rejected: "Plot will be rejected!" + plot-will-be-accepted: "Plot will be accepted" + plots-reviewed-singular: "{0} plot has been reviewed!" + plots-reviewed-plural: "{0} plots have been reviewed!" saving-plot: "§aSalvando terreno..." creating-plot: "§aCriando um novo terreno..." created-new-plot: "§aCriou novo terreno para §6{0}§a!" @@ -247,6 +260,8 @@ message: cannot-undo-review: "Você não pode desfazer uma avaliação que você mesmo não avaliou!" cannot-send-feedback: "Você não pode enviar feedback para um lote que você mesmo não avaliou!" cannot-review-own-plot: "Você não pode revisar seu próprio terreno!" + cannot-modify-legacy-plot: "Legacy plots cannot be modified!" + cannot-load-legacy-plot: "Legacy plots cannot be loaded!" player-has-no-permissions: "Você não tem permissão para fazer isso!" player-has-no-invitations: "Você não tem convites!" player-is-not-allowed: "Você não tem permissão para fazer isso!" @@ -260,6 +275,7 @@ message: player-invite-to-rejected: '{0} has rejected your invitation.' player-needs-to-be-on-plot: "Você precisa estar em um terreno para usar isso!" player-needs-higher-score: "Você precisa de uma pontuação mais alta para construir neste nível de dificuldade." + player-missing-tutorial: "O jogador tem de completar o tutorial primeiro, para ser adicionado ao enredo!" error-occurred: "Um erro ocorreu! Por favor, tente novamente!" command-disabled: "Este comando está desabilitado!" no-plots-left: "Este projeto da cidade não tem mais terrenos. Por favor, Selecione outro projeto." @@ -268,6 +284,7 @@ message: chat-input-expired: "The chat input has expired." tutorial-disabled: 'Tutorials are disabled on this server.' tutorial-already-running: "You already have a tutorial running! Complete it before starting a new one." + review-not-found: "Review could not be found!" leaderboards: pages: DAILY: "Daily" @@ -388,5 +405,46 @@ tutorials: - 'Happy building! ☺' stage-10-tasks: - 'Read all tips on the plot and mark them as read.' +# ----------------------------------------------------- +# | Database +# ----------------------------------------------------- +database: + city-project: + example-city: + name: 'Example City' + description: 'Some description' + country: + AT: + name: 'Austria' + CH: + name: 'Switzerland' + LI: + name: 'Liechtenstein' + difficulty: + easy: + name: 'Easy' + medium: + name: 'Medium' + hard: + name: 'Hard' + status: + unclaimed: + name: 'Unclaimed' + unfinished: + name: 'Unfinished' + unreviewed: + name: 'Unreviewed' + completed: + name: 'Completed' + toggle-criteria: + built_on_outlines: 'Built on outlines' + correct_height: 'Correct building height' + correct_facade_colour: 'Correct building colour' + correct_roof_colour: 'Correct roof colour' + correct_roof_shape: 'Correct roof shape' + correct_amount_windows_doors: 'Correct amount of windows and doors' + correct_window_type: 'Correct window types' + windows_blacked_out: 'All windows blacked out' + # NOTE: Do not change -config-version: 2.2 +config-version: 2.5 \ No newline at end of file diff --git a/src/main/resources/lang/ru_RU.yml b/src/main/resources/lang/ru_RU.yml index f6ee30751..9b4c5616d 100644 --- a/src/main/resources/lang/ru_RU.yml +++ b/src/main/resources/lang/ru_RU.yml @@ -2,8 +2,9 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot +# | [Localisation Platform] https://crowdin.com/project/alps-bte-plot-system # | # | [Formatting] Use %newline% for a newline # | [Formatting] Words that are wrapped in the {number} tag are replaced afterward @@ -68,6 +69,7 @@ difficulty: menu-title: close: "Закрыть" back: "Назад" + continue: 'Continue' next-page: "Следующая Страница" previous-page: "Предыдущая Страница" error: "Ошибка" @@ -157,15 +159,16 @@ review: feedback: "Отзыв" reviewer: "Оценщик" player-language: "Player Language" + no-feedback: "No feedback" + accuracy-points: "Accuracy points" + block-palette-points: "Block palette points" + toggle-points: "Toggle points" + total-points: "Total points" criteria: accuracy: "Точность Воссоздания" accuracy-desc: "Насколько точно исполнено здание?%newline%%newline%- Выглядит как в настоящей жизни%newline%- Правильные контуры%newline%- Правильная высота%newline%- Полностью завершен" block-palette: "Палитра Блоков" block-palette-desc: "Сколько различных блоков использовано и насколько они креативны??%newline%%newline%- Выбор цвета/текстуры блоков%newline%- Случайные блоки’" - detailing: "Детализация" - detailing-desc: "Насколько детализировано здание?%newline%%newline%- Детали крыши%newline%- Детали фасада%newline%- Головы и Баннеры" - technique: "Техника" - technique-desc: "Какие строительные техники были применены и насколько они креативны?%newline%%newline%- World-Edit%newline%- Специальные Блоки" # ----------------------------------------------------- # | Notes # ----------------------------------------------------- @@ -175,6 +178,11 @@ note: wont-be-able-continue-building: "Вы не сможете больше строить на этом участке!" score-will-be-split: "Общая Оценка будет разделена между всеми участниками после проверки!" player-has-to-be-online: "Игрок должен быть в сети!" + optional: "Optional" + required: "Required" + criteria-fulfilled: "Fulfilled" + criteria-not-fulfilled: "Not fulfilled" + legacy: "LEGACY" action: read: 'Read' read-more: 'Read More' @@ -197,6 +205,8 @@ note: click-to-show-plots: "§6Нажмите,чтобы показать ваши участки..." click-to-play-with-friends: "§7Хотите играть с друзьями? §6Нажмите здесь..." tutorial-show-stages: 'Show Stages' + click-to-open-plots-menu: "Нажмите, чтобы открыть меню участков..." + click-to-toggle: "Click to toggle..." # ----------------------------------------------------- # | Messages # ----------------------------------------------------- @@ -209,7 +219,7 @@ message: plot-marked-as-reviewed: "§aУчасток §6#{0}§a построенный §6{1}§aбыл помечена как оценённый!!" plot-rejected: "§aУчасток §6#{0}§a построенный §6{1}§a был отклонен!" undid-submission: "§aОтмена отправки участка §6#{0}§a!" - undid-review: "§aОтмена оценки участка §6#{0}§a построенным §6#{1}§a!" + undid-review: "§aОтмена оценки участка §6#{0}§a построенным §6{1}§a!" reviewed-plot: "§aВаш участок §6#{0}§a был оценён!" unreviewed-plot: "§aЕсть §6{0}§a неоценённый участок!" unreviewed-plots: "§aЕсть §6{0}§a неоценённые участки!!" @@ -221,7 +231,10 @@ message: removed-plot-member: "§6{0}§a §aудалён из участка§6#{1}§a!" left-plot: "§aПокинул участок §6#{0}§a!" plot-will-get-abandoned-warning: "§c§lВНИМАНИЕ: §cЭтот участок будет автоматически сброшен!" - plot-will-get-rejected-warning: "§c§lВНИМАНИЕ: §cЭтот участок будет отклонён!!" + plot-will-be-rejected: "Plot will be rejected!" + plot-will-be-accepted: "Plot will be accepted" + plots-reviewed-singular: "{0} plot has been reviewed!" + plots-reviewed-plural: "{0} plots have been reviewed!" saving-plot: "§aСохранение участка..." creating-plot: "§aСоздание нового участка..." created-new-plot: "§aСоздан новый участок§a для §6{0}§a!" @@ -247,6 +260,8 @@ message: cannot-undo-review: "Вы не можете отменить оценку которую выставляли не вы!" cannot-send-feedback: "Вы не можете отправить отзыв к участку который оценивали не вы!" cannot-review-own-plot: "Вы не можете оценить свой участок!" + cannot-modify-legacy-plot: "Legacy plots cannot be modified!" + cannot-load-legacy-plot: "Legacy plots cannot be loaded!" player-has-no-permissions: "У вас нет доступа для выполнения этого действия!" player-has-no-invitations: "У вас нет приглашений!" player-is-not-allowed: "Вам запрещено выполнение этого действия!" @@ -260,6 +275,7 @@ message: player-invite-to-rejected: '{0} has rejected your invitation.' player-needs-to-be-on-plot: "Вам нужно быть на участке чтобы использовать это!" player-needs-higher-score: "Вам нужна более высокая оценка чтобы строить на этом уровне сложности." + player-missing-tutorial: "Чтобы стать участником сюжета, игрок должен сначала пройти обучение!" error-occurred: "Произошла ошибка! Пожалуйста, попробуйте снова!" command-disabled: "Эта команда отключена!!" no-plots-left: "У этого градостроительного проекта больше не осталось участков. Пожалуйста, выберите другой проект." @@ -268,6 +284,7 @@ message: chat-input-expired: "The chat input has expired." tutorial-disabled: 'Tutorials are disabled on this server.' tutorial-already-running: "You already have a tutorial running! Complete it before starting a new one." + review-not-found: "Review could not be found!" leaderboards: pages: DAILY: "Daily" @@ -388,5 +405,46 @@ tutorials: - 'Happy building! ☺' stage-10-tasks: - 'Read all tips on the plot and mark them as read.' +# ----------------------------------------------------- +# | Database +# ----------------------------------------------------- +database: + city-project: + example-city: + name: 'Example City' + description: 'Some description' + country: + AT: + name: 'Austria' + CH: + name: 'Switzerland' + LI: + name: 'Liechtenstein' + difficulty: + easy: + name: 'Easy' + medium: + name: 'Medium' + hard: + name: 'Hard' + status: + unclaimed: + name: 'Unclaimed' + unfinished: + name: 'Unfinished' + unreviewed: + name: 'Unreviewed' + completed: + name: 'Completed' + toggle-criteria: + built_on_outlines: 'Built on outlines' + correct_height: 'Correct building height' + correct_facade_colour: 'Correct building colour' + correct_roof_colour: 'Correct roof colour' + correct_roof_shape: 'Correct roof shape' + correct_amount_windows_doors: 'Correct amount of windows and doors' + correct_window_type: 'Correct window types' + windows_blacked_out: 'All windows blacked out' + # NOTE: Do not change -config-version: 2.2 +config-version: 2.5 \ No newline at end of file diff --git a/src/main/resources/lang/zh_CN.yml b/src/main/resources/lang/zh_CN.yml index 4428f0c9e..202502a31 100644 --- a/src/main/resources/lang/zh_CN.yml +++ b/src/main/resources/lang/zh_CN.yml @@ -2,8 +2,9 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot +# | [Localisation Platform] https://crowdin.com/project/alps-bte-plot-system # | # | [Formatting] Use %newline% for a newline # | [Formatting] Words that are wrapped in the {number} tag are replaced afterward @@ -11,7 +12,6 @@ lang: name: "简体中文(中国大陆)" head-id: "23238" - # ----------------------------------------------------- # | Plot # ----------------------------------------------------- @@ -69,6 +69,7 @@ difficulty: menu-title: close: "关闭" back: "返回" + continue: 'Continue' next-page: "下一页" previous-page: "上一页" error: "错误" @@ -157,16 +158,17 @@ review: rejected: "驳回" feedback: "回馈" reviewer: "审核员" + no-feedback: "No feedback" + accuracy-points: "Accuracy points" + block-palette-points: "Block palette points" + toggle-points: "Toggle points" + total-points: "Total points" player-language: "Player Language" criteria: accuracy: "准确性" accuracy-desc: "建筑的精确度如何? %newline%%newline%- 看起来像在真实世界%newline%- 正确的轮廓%newline%- 正确的高度%newline%- 完成了" block-palette: "方块用色" block-palette-desc: "使用了多少个不同的方块,它们的创意如何? %newline%%newline%- 方块颜色/材质的选择%newline%- 随机方块" - detailing: "细节" - detailing-desc: "建筑有多少细节? %newline%%newline%- 屋顶细节%newline%- 外墙上的细节%newline%- 头颅和旗帜" - technique: "技巧" - technique-desc: "使用了什么建筑技巧,它们的创意如何? %newline%%newline%- World-Edit%newline%- 特殊方块" # ----------------------------------------------------- # | Notes # ----------------------------------------------------- @@ -176,6 +178,11 @@ note: wont-be-able-continue-building: "你将无法继续在此建地上进行建设! " score-will-be-split: "审核时积分将分配给所有成员! " player-has-to-be-online: "玩家必须上线! " + optional: "Optional" + required: "Required" + criteria-fulfilled: "Fulfilled" + criteria-not-fulfilled: "Not fulfilled" + legacy: "LEGACY" action: read: 'Read' read-more: 'Read More' @@ -198,6 +205,8 @@ note: click-to-show-plots: "§6点击此区 §a显示你的建地..." click-to-play-with-friends: "§7想和你的朋友一起玩吗? §6点击此区..." tutorial-show-stages: 'Show Stages' + click-to-open-plots-menu: "点击此区 显示你的建地..." + click-to-toggle: "Click to toggle..." # ----------------------------------------------------- # | Messages # ----------------------------------------------------- @@ -210,7 +219,7 @@ message: plot-marked-as-reviewed: "§a §6{1}§a 的建地 §6#{0}§a 已标记供审核! " plot-rejected: "§a §6{1}§a 的建地 §6#{0}§a 已被驳回!" undid-submission: "§a尚未提交的建地 §6#{0}§a! " - undid-review: "§a尚未审核的建地 §6#{0}§a by §6#{1}§a! " + undid-review: "§a尚未审核的建地 §6#{0}§a by §6{1}§a! " reviewed-plot: "§a你的建地 §6#{0}§a 已被审核! " unreviewed-plot: "§a有 §6{0}§a 处尚未审核的建地! " unreviewed-plots: "§a有 §6{0}§a 处尚未审核的建地! " @@ -222,7 +231,10 @@ message: removed-plot-member: "§a从建地 §6#{1}§a 移除 §6{0}§a! " left-plot: "§a剩余建地 §6#{0}§a! " plot-will-get-abandoned-warning: "§c§l警告: §c此建地将自动废弃! " - plot-will-get-rejected-warning: "§c§l警告: §c此建地将被驳回! " + plot-will-be-rejected: "Plot will be rejected!" + plot-will-be-accepted: "Plot will be accepted" + plots-reviewed-singular: "{0} plot has been reviewed!" + plots-reviewed-plural: "{0} plots have been reviewed!" saving-plot: "§a储存建地..." creating-plot: "§a创建新建地..." created-new-plot: "§a创建新建地§a 为 §6{0}§a! " @@ -248,6 +260,8 @@ message: cannot-undo-review: "你无法撤回你自己未审核过的审核! " cannot-send-feedback: "你无法发送你自己未审核过的回馈! " cannot-review-own-plot: "你无法审核你所有的建地! " + cannot-modify-legacy-plot: "Legacy plots cannot be modified!" + cannot-load-legacy-plot: "Legacy plots cannot be loaded!" player-has-no-permissions: "你没有权限做这个! " player-has-no-invitations: "你没有受到邀请! " player-is-not-allowed: "你不被允许做这个! " @@ -261,6 +275,7 @@ message: player-invite-to-rejected: '{0} has rejected your invitation.' player-needs-to-be-on-plot: "你需要在一个建地上才能使用它! " player-needs-higher-score: "你需要更高的积分来才能在这个难度度建设。" + player-missing-tutorial: "玩家必須先完成教學才能加入劇情!" error-occurred: "发生错误!请再次尝试!" command-disabled: "此命令已禁用!" no-plots-left: "此城市计画区没有剩余更多建地了。请选择其他计画区。" @@ -269,6 +284,7 @@ message: chat-input-expired: "The chat input has expired." tutorial-disabled: 'Tutorials are disabled on this server.' tutorial-already-running: "You already have a tutorial running! Complete it before starting a new one." + review-not-found: "Review could not be found!" leaderboards: pages: DAILY: "Daily" @@ -389,5 +405,46 @@ tutorials: - 'Happy building! ☺' stage-10-tasks: - 'Read all tips on the plot and mark them as read.' +# ----------------------------------------------------- +# | Database +# ----------------------------------------------------- +database: + city-project: + example-city: + name: 'Example City' + description: 'Some description' + country: + AT: + name: 'Austria' + CH: + name: 'Switzerland' + LI: + name: 'Liechtenstein' + difficulty: + easy: + name: 'Easy' + medium: + name: 'Medium' + hard: + name: 'Hard' + status: + unclaimed: + name: 'Unclaimed' + unfinished: + name: 'Unfinished' + unreviewed: + name: 'Unreviewed' + completed: + name: 'Completed' + toggle-criteria: + built_on_outlines: 'Built on outlines' + correct_height: 'Correct building height' + correct_facade_colour: 'Correct building colour' + correct_roof_colour: 'Correct roof colour' + correct_roof_shape: 'Correct roof shape' + correct_amount_windows_doors: 'Correct amount of windows and doors' + correct_window_type: 'Correct window types' + windows_blacked_out: 'All windows blacked out' + # NOTE: Do not change -config-version: 2.2 +config-version: 2.5 \ No newline at end of file diff --git a/src/main/resources/lang/zh_TW.yml b/src/main/resources/lang/zh_TW.yml index fc0b4681d..96d37700c 100644 --- a/src/main/resources/lang/zh_TW.yml +++ b/src/main/resources/lang/zh_TW.yml @@ -2,8 +2,9 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot +# | [Localisation Platform] https://crowdin.com/project/alps-bte-plot-system # | # | [Formatting] Use %newline% for a newline # | [Formatting] Words that are wrapped in the {number} tag are replaced afterward @@ -68,6 +69,7 @@ difficulty: menu-title: close: "關閉" back: "返回" + continue: 'Continue' next-page: "下一頁" previous-page: "上一頁" error: "錯誤" @@ -157,15 +159,16 @@ review: feedback: "評語" reviewer: "審核人" player-language: "玩家語言" + no-feedback: "No feedback" + accuracy-points: "Accuracy points" + block-palette-points: "Block palette points" + toggle-points: "Toggle points" + total-points: "Total points" criteria: accuracy: "準確性" accuracy-desc: "建築的精確度如何?%newline%%newline%- 看起來像在真實世界%newline%- 正確的輪廓%newline%- 正確的高度%newline%- 完成了" block-palette: "方塊用色" block-palette-desc: "使用了多少個不同的方塊,它們的創意如何?%newline%%newline%- 方塊顏色/紋理的選擇%newline%- 隨機方塊" - detailing: "細節" - detailing-desc: "建築有多少細節?%newline%%newline%- 屋頂細節%newline%- 立面上的細節%newline%- 頭顱和旗幟" - technique: "技巧" - technique-desc: "使用了什麼建築技巧,它們的創意如何?%newline%%newline%- World-Edit%newline%- 特殊方塊" # ----------------------------------------------------- # | Notes # ----------------------------------------------------- @@ -175,6 +178,11 @@ note: wont-be-able-continue-building: "你將無法繼續在此建地上進行建設!" score-will-be-split: "審核時積分將分配給全部的成員!" player-has-to-be-online: "玩家必須上線!" + optional: "Optional" + required: "Required" + criteria-fulfilled: "Fulfilled" + criteria-not-fulfilled: "Not fulfilled" + legacy: "LEGACY" action: read: '已讀' read-more: '閱讀更多' @@ -197,6 +205,8 @@ note: click-to-show-plots: "§6點擊此處§a顯示你的建地..." click-to-play-with-friends: "§7想和你的朋友一起玩嗎?§6點擊此處..." tutorial-show-stages: '顯示階段' + click-to-open-plots-menu: '點擊以開啟建地選單...' + click-to-toggle: "Click to toggle..." # ----------------------------------------------------- # | Messages # ----------------------------------------------------- @@ -209,7 +219,7 @@ message: plot-marked-as-reviewed: "§a§6{1}§a的建地§6#{0}§a已標記供審核!" plot-rejected: "§a§6{1}§a的建地§6#{0}§a已被否決!" undid-submission: "§a撤回了建地§6#{0}§a的提交!" - undid-review: "§a撤回了對§6#{1}§a建地§6#{0}§a的審核!" + undid-review: "§a撤回了對§6{1}§a建地§6#{0}§a的審核!" reviewed-plot: "§a你的建地§6#{0}§a已被審核!" unreviewed-plot: "§a有§6{0}§a處尚未審核的建地!" unreviewed-plots: "§a有§6{0}§a處尚未審核的建地!" @@ -221,7 +231,10 @@ message: removed-plot-member: "§a將§6{0}§a從建地§6#{1}§a中移除!" left-plot: "§a離開建地§6#{0}§a!" plot-will-get-abandoned-warning: "§c§l警告:§c此建地將自動被廢棄!" - plot-will-get-rejected-warning: "§c§l警告:§c此建地將被否決!" + plot-will-be-rejected: "Plot will be rejected!" + plot-will-be-accepted: "Plot will be accepted" + plots-reviewed-singular: "{0} plot has been reviewed!" + plots-reviewed-plural: "{0} plots have been reviewed!" saving-plot: "§a儲存建地..." creating-plot: "§a建立新建地..." created-new-plot: "§a為§6{0}§a建立了新建地§a!" @@ -247,6 +260,8 @@ message: cannot-undo-review: "你無法撤回未經你本人審核過的審核!" cannot-send-feedback: "你無法給未經你本人審核過建地的發送評語!" cannot-review-own-plot: "你無法審核你所有的建地!" + cannot-modify-legacy-plot: "Legacy plots cannot be modified!" + cannot-load-legacy-plot: "Legacy plots cannot be loaded!" player-has-no-permissions: "你沒有權限使用!" player-has-no-invitations: "你沒有受到邀請!" player-is-not-allowed: "你不被允許使用!" @@ -260,6 +275,7 @@ message: player-invite-to-rejected: '{0}否決了你的邀請。' player-needs-to-be-on-plot: "你需要在一個建地上才能使用它!" player-needs-higher-score: "你需要更高的積分來才能在這個難度下建設。" + player-missing-tutorial: "玩家必须先完成教程,才能加入剧情!" error-occurred: "發生錯誤!請再次嘗試!" command-disabled: "此指令已被禁用!" no-plots-left: "此城市計畫區沒有剩餘更多建地了。請選擇其他計畫區。" @@ -268,6 +284,7 @@ message: chat-input-expired: "聊天輸入過期了。" tutorial-disabled: '此伺服器的教學被停用了。' tutorial-already-running: "你已經有一個教學正在進行!在開始新的教學前請先將它完成。" + review-not-found: "Review could not be found!" leaderboards: pages: DAILY: "每日" @@ -388,5 +405,46 @@ tutorials: - '建築愉快!☺' stage-10-tasks: - '閱讀建地上全部的提示並將其標記為已讀。' +# ----------------------------------------------------- +# | Database +# ----------------------------------------------------- +database: + city-project: + example-city: + name: 'Example City' + description: 'Some description' + country: + AT: + name: 'Austria' + CH: + name: 'Switzerland' + LI: + name: 'Liechtenstein' + difficulty: + easy: + name: 'Easy' + medium: + name: 'Medium' + hard: + name: 'Hard' + status: + unclaimed: + name: 'Unclaimed' + unfinished: + name: 'Unfinished' + unreviewed: + name: 'Unreviewed' + completed: + name: 'Completed' + toggle-criteria: + built_on_outlines: 'Built on outlines' + correct_height: 'Correct building height' + correct_facade_colour: 'Correct building colour' + correct_roof_colour: 'Correct roof colour' + correct_roof_shape: 'Correct roof shape' + correct_amount_windows_doors: 'Correct amount of windows and doors' + correct_window_type: 'Correct window types' + windows_blacked_out: 'All windows blacked out' + # NOTE: Do not change -config-version: 2.3 +config-version: 2.5 \ No newline at end of file diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 0e8923cfc..a9a177fd9 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -1,10 +1,12 @@ main: com.alpsbte.plotsystem.PlotSystem -version: 4.1.3 +version: "${version}" api-version: "1.21" name: Plot-System -author: R3tuxn & Cinnazeyy -softdepend: [ LangLibs, FancyNpcs, VoidGen, FastAsyncWorldEdit, Multiverse-Core, WorldEdit, - DecentHolograms, WorldGuard, WorldGuardExtraFlags, HeadDatabase, ProtocolLib, ParticleNativeAPI ] +description: "${description}" +author: R3tuxn, Cinnazeyy & Zoriot +depend: [ LangLibs, FancyNpcs, VoidGen, FastAsyncWorldEdit, Multiverse-Core, + DecentHolograms, WorldGuard, HeadDatabase ] +softdepend: [ WorldGuardExtraFlags, ParticleNativeAPI ] commands: cancelchat: diff --git a/src/main/resources/tutorial/schematics/0-0.schem.gz b/src/main/resources/tutorial/schematics/0-0.schem.gz new file mode 100644 index 000000000..78364ddf0 Binary files /dev/null and b/src/main/resources/tutorial/schematics/0-0.schem.gz differ diff --git a/src/main/resources/tutorial/schematics/0-0.schematic.gz b/src/main/resources/tutorial/schematics/0-0.schematic.gz deleted file mode 100644 index 13cb7b602..000000000 Binary files a/src/main/resources/tutorial/schematics/0-0.schematic.gz and /dev/null differ diff --git a/src/main/resources/tutorial/schematics/0-1.schem.gz b/src/main/resources/tutorial/schematics/0-1.schem.gz new file mode 100644 index 000000000..7581db021 Binary files /dev/null and b/src/main/resources/tutorial/schematics/0-1.schem.gz differ diff --git a/src/main/resources/tutorial/schematics/0-1.schematic.gz b/src/main/resources/tutorial/schematics/0-1.schematic.gz deleted file mode 100644 index e8a88bdb7..000000000 Binary files a/src/main/resources/tutorial/schematics/0-1.schematic.gz and /dev/null differ diff --git a/src/main/resources/tutorial/schematics/0-2.schem.gz b/src/main/resources/tutorial/schematics/0-2.schem.gz new file mode 100644 index 000000000..8acd9b898 Binary files /dev/null and b/src/main/resources/tutorial/schematics/0-2.schem.gz differ diff --git a/src/main/resources/tutorial/schematics/0-2.schematic.gz b/src/main/resources/tutorial/schematics/0-2.schematic.gz deleted file mode 100644 index 70958bf0c..000000000 Binary files a/src/main/resources/tutorial/schematics/0-2.schematic.gz and /dev/null differ diff --git a/src/main/resources/tutorial/schematics/0-3.schem.gz b/src/main/resources/tutorial/schematics/0-3.schem.gz new file mode 100644 index 000000000..344e01ce2 Binary files /dev/null and b/src/main/resources/tutorial/schematics/0-3.schem.gz differ diff --git a/src/main/resources/tutorial/schematics/0-3.schematic.gz b/src/main/resources/tutorial/schematics/0-3.schematic.gz deleted file mode 100644 index 3b5fc4b85..000000000 Binary files a/src/main/resources/tutorial/schematics/0-3.schematic.gz and /dev/null differ diff --git a/src/main/resources/tutorial/schematics/0-4.schem.gz b/src/main/resources/tutorial/schematics/0-4.schem.gz new file mode 100644 index 000000000..6fd6401f4 Binary files /dev/null and b/src/main/resources/tutorial/schematics/0-4.schem.gz differ diff --git a/src/main/resources/tutorial/schematics/0-4.schematic.gz b/src/main/resources/tutorial/schematics/0-4.schematic.gz deleted file mode 100644 index ebdb75855..000000000 Binary files a/src/main/resources/tutorial/schematics/0-4.schematic.gz and /dev/null differ diff --git a/src/main/resources/tutorial/schematics/0-5.schem.gz b/src/main/resources/tutorial/schematics/0-5.schem.gz new file mode 100644 index 000000000..a78ff2cc6 Binary files /dev/null and b/src/main/resources/tutorial/schematics/0-5.schem.gz differ diff --git a/src/main/resources/tutorial/schematics/0-5.schematic.gz b/src/main/resources/tutorial/schematics/0-5.schematic.gz deleted file mode 100644 index e9c5a2378..000000000 Binary files a/src/main/resources/tutorial/schematics/0-5.schematic.gz and /dev/null differ diff --git a/src/main/resources/tutorial/schematics/0-6.schem.gz b/src/main/resources/tutorial/schematics/0-6.schem.gz new file mode 100644 index 000000000..e09f64a0d Binary files /dev/null and b/src/main/resources/tutorial/schematics/0-6.schem.gz differ diff --git a/src/main/resources/tutorial/schematics/0-6.schematic.gz b/src/main/resources/tutorial/schematics/0-6.schematic.gz deleted file mode 100644 index 97807ba33..000000000 Binary files a/src/main/resources/tutorial/schematics/0-6.schematic.gz and /dev/null differ diff --git a/src/main/resources/tutorial/schematics/0-7.schem.gz b/src/main/resources/tutorial/schematics/0-7.schem.gz new file mode 100644 index 000000000..483ddb65a Binary files /dev/null and b/src/main/resources/tutorial/schematics/0-7.schem.gz differ diff --git a/src/main/resources/tutorial/schematics/0-7.schematic.gz b/src/main/resources/tutorial/schematics/0-7.schematic.gz deleted file mode 100644 index b4a38d844..000000000 Binary files a/src/main/resources/tutorial/schematics/0-7.schematic.gz and /dev/null differ diff --git a/src/main/resources/tutorial/schematics/0-env.schematic.gz b/src/main/resources/tutorial/schematics/0-env.schematic.gz deleted file mode 100644 index 7ec81c299..000000000 Binary files a/src/main/resources/tutorial/schematics/0-env.schematic.gz and /dev/null differ diff --git a/src/main/resources/tutorial/tutorial_beginner.yml b/src/main/resources/tutorial/tutorial_beginner.yml index 8528b40ce..0a79569d3 100644 --- a/src/main/resources/tutorial/tutorial_beginner.yml +++ b/src/main/resources/tutorial/tutorial_beginner.yml @@ -2,8 +2,8 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot # | # | [Tutorial Config - Beginner] # | @@ -66,9 +66,8 @@ beginner: point-2: '3693367.0,-4531328.0' point-3: '3693370.0,-4531337.0' point-4: '3693357.0,-4531342.0' - # BaseBlock for the building outline - base-block: 'WHITE_WOOL' - base-block-id: 35 + # BaseBlocks for the building outline (multiple blocks or legacy id's are supported) + base-blocks: [ 'WHITE_WOOL', 'WHITE', '35', '35:0' ] # Height of the plot building, which must be calculated height: 7 height-offset: 1 diff --git a/src/main/resources/tutorial/tutorial_template.yml b/src/main/resources/tutorial/tutorial_template.yml index 69981a049..80514b195 100644 --- a/src/main/resources/tutorial/tutorial_template.yml +++ b/src/main/resources/tutorial/tutorial_template.yml @@ -2,8 +2,8 @@ # | Plot System - by Alps BTE # ----------------------------------------------------- # | [Github Repo] https://github.com/AlpsBTE/PlotSystem -# | [Config Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/Configuration -# | [Contacts - Discord] R3tuxn#7169, Cinnazeyy#2440 +# | [Documentation] https://github.com/AlpsBTE/PlotSystem/wiki/ +# | [Contacts - Discord] R3tuxn, Cinnazeyy & Zoriot # | # | [Tutorial Config - XYZ] # |