Compare commits

...
150 Commits
Author SHA1 Message Date
Andrew Wong 9e06b9f268 Release 2.7.10 2023-02-27 21:58:14 +11:00
Andrew Wong 4562bf23f6 Update libs 2023-02-27 21:57:49 +11:00
Andrew Wong 24edb01754 Refactor GeneralRegion#getOwner, #isOwner and #setOwner 2023-02-27 21:46:59 +11:00
Andrew Wong 2739bf6ad4 Fix javadocs for IFileManager 2023-02-27 21:41:28 +11:00
Andrew Wong 2ce84186ab Use Server#getOfflinePlayer in PlayerOfflinePlayerHelper 2023-02-27 21:39:48 +11:00
Andrew Wong 279fa001ea Only support 1.19.3 2023-02-27 11:56:41 +11:00
Andrew Wong b56d5320a6 Add support for 1.19.3 2022-12-15 16:25:06 +08:00
Andrew Wong 30665908b9 Bump to 2.7.10-SNAPSHOT 2022-12-09 16:53:03 +08:00
Andrew Wong 0fd384833a Bump version to 2.7.9 release 2022-12-09 16:45:57 +08:00
Andrew Wong 09634de4bf Fix BukkitSchedulerExecutor not having an injectable ctor 2022-12-07 12:13:34 +08:00
Andrew Wong 7fafee82a7 Minor cleanup 2022-12-07 11:59:37 +08:00
Andrew Wong 2899b2978c Rewrite SetownerCommand 2022-12-07 11:56:50 +08:00
Andrew Wong 7afcba79c9 Rewrite SetlandlordCommand 2022-12-07 11:53:44 +08:00
Andrew Wong 72084b38f8 Use OfflinePlayerHelper in MeCommand 2022-12-07 11:49:01 +08:00
Andrew Wong 6a291feedd Rewrite DelFriendCommand 2022-12-07 11:45:16 +08:00
Andrew Wong b85566882c Rewrite AddfriendCommand 2022-12-07 11:39:09 +08:00
Andrew Wong c14407e14b Add PaperPlatform 2022-12-07 01:23:12 +08:00
Andrew Wong ae9bd60d1b Fix typo 2022-09-14 21:25:04 +08:00
Andrew Wong c689c2fae0 Fix dependency versions for WG and WE, and add a section for FAWE 2022-09-14 21:24:48 +08:00
Andrew Wong 728cfb6dfa Add a compiling.md 2022-09-14 21:16:03 +08:00
Andrew Wong 3abb6c06e4 Update readme 2022-09-14 20:56:00 +08:00
Andrew Wong 51c11738af Prepare for snapshot development 2022-09-12 22:39:45 +08:00
Andrew Wong 172b5a99f1 Bump version to release 2022-09-12 22:21:28 +08:00
Andrew Wong 4c5d025e54 Add config option to toggle whether entities are forcefully cleared 2022-09-12 22:20:55 +08:00
Andrew Wong e93a2d04de Forcefully remove entities from FAWE/WE regions before schematic pasting 2022-09-12 22:12:18 +08:00
Andrew Wong af5980d555 Change the messages for update checking and report file manager loading failures 2022-09-12 17:58:09 +08:00
Andrew Wong 3f7249f4a1 Merge pull request #13 from cleonyc/dev/bleeding
Allow unrented event to use placeholders
2022-09-12 17:39:56 +08:00
Andrew Wong 73c6fc858e Update the logging methods to invoke conditionally 2022-09-12 17:37:47 +08:00
Andrew Wong 360c3e7e21 Use Suppliers when logging in the plugin adapters 2022-09-12 17:35:55 +08:00
Andrew Wong 73d0115b78 Actually fix the FAWE and WE handlers when pasting 2022-09-12 17:25:27 +08:00
Andrew Wong baf7eaabf1 Bump versions of WE and FAWE in the libs.toml 2022-09-11 00:50:36 +08:00
Andrew Wong ca8c0487a8 Fix origin setting so that the blocks paste properly 2022-09-11 00:44:47 +08:00
Andrew Wong 24156a03c4 Rewrite region saving and restoring in the adapters 2022-09-10 23:14:28 +08:00
Andrew Wong ec677766d2 Attempt to prevent duplicate signs from loading 2022-09-10 19:27:03 +08:00
Andrew Wong ef6c8fbf9d Only remove leashes, paintings and item frames 2022-09-10 17:54:48 +08:00
Andrew Wong 4f52fe9e6e Forcefully remvoe Entities in the region before pasting 2022-09-10 17:43:07 +08:00
Andrew Wong 3ebe5a6fa9 Use the WG converter to convert WG regions to WE ones 2022-09-10 17:02:29 +08:00
Andrew Wong 3cebe5d2c7 Fix NPE with sign deletion after worlededit operations 2022-09-10 14:59:35 +08:00
Andrew Wong c76415c4f3 Fix NPE when tabbing region restore 2022-09-10 12:47:45 +08:00
Andrew Wong b7bc02aef3 Compile against 1.19.2 and update the gradle wrapper 2022-09-07 15:31:33 +08:00
Cleo d75094e191 Remove unrenting section in eventCommandProfile 2022-07-07 13:51:02 -04:00
Cleo 4045914b48 Fix placeholders in unrented command event [#11] 2022-07-07 13:50:04 -04:00
Andrew Wong 1fac002ee0 Remove the Bukkit113 module and update the versioning url 2022-06-20 19:57:22 +08:00
Andrew Wong 64301e74e0 Bump version 2022-06-20 19:27:28 +08:00
Andrew Wong 5a5a7fc5ef Bump version 2022-06-20 19:25:42 +08:00
Andrew Wong b928caf0c2 Bump worldedit 2022-06-20 19:19:49 +08:00
Andrew Wong 111f629787 Update dependencies and add adapter for 1.19 2022-06-11 00:59:19 +08:00
Andrew Wong 718474ca95 Update gradle wrapper 2022-06-10 23:37:12 +08:00
Andrew Wong 93b9df3e54 Update gradle wrapper to 7.4.1 2022-03-24 18:48:03 +08:00
Andrew Wong bad983a0b8 Update worldedit and fawe adapters 2022-03-24 18:47:02 +08:00
Andrew Wong e2c8b06b68 Bump dependency versions 2022-03-24 16:30:02 +08:00
Andrew Wong 7249e39c02 bump version 2022-03-24 16:27:49 +08:00
Andrew Wong 9d9a58a170 bump to 2.7.6 2022-03-24 16:24:56 +08:00
Andrew Wong e64e884c2a Updates to the fawe module 2022-03-05 00:00:34 +08:00
Andrew Wong 6ad4ff9deb Shade in the provider for 1.18.1 2022-03-05 00:00:23 +08:00
Andrew Wong eec9806492 Add back support for 1.18.1 2022-03-04 23:08:43 +08:00
Andrew Wong 43b2ae8278 Fix bad website in plugin.yml 2022-03-04 22:54:40 +08:00
Andrew Wong 6d5a92e389 1.18.2 2022-03-04 22:48:39 +08:00
Andrew Wong 7d7a62ffa0 Bump gradle wrapper to 7.4 2022-03-03 17:41:52 +08:00
md5sha256 44456d87b6 Fix the sign error file extension 2022-01-25 05:49:47 +08:00
md5sha256 d92c710b27 bump version to snapshot 2022-01-25 05:49:35 +08:00
md5sha256 3dceaf98cd Bump version to 2.7.5 2022-01-25 05:35:08 +08:00
md5sha256 33c29a3756 Fix the fawe integration and do operations async when possible 2022-01-25 05:34:34 +08:00
md5sha256 771734360f add workflow 2022-01-16 23:24:28 +08:00
md5sha256 539e908d32 Initial work on fixing the deadlock in the fawe module 2022-01-16 21:45:11 +08:00
md5sha256 088471aa3c more project restructuring 2022-01-16 21:28:28 +08:00
md5sha256 5a95c95670 Fix gitignore and restructure project 2022-01-16 20:58:44 +08:00
md5sha256 5a5d627d51 Fix publishing 2022-01-16 15:26:54 +08:00
md5sha256 9b5434a4b2 Add type safe project acessors and version catalog 2022-01-16 14:40:19 +08:00
md5sha256 e13717950b Kotlin dsl 2022-01-16 12:05:39 +08:00
md5sha256 03ed2803bd Bump version to 2.7.3 2022-01-15 07:38:40 +08:00
md5sha256 b3f1225934 Deprecate the FAWE WG handler and fix fawe version parsing 2022-01-15 07:36:43 +08:00
md5sha256 68651899b7 Update the fawe module 2022-01-10 22:59:03 +08:00
md5sha256 4a7a4ca4ee Fix reobf 2022-01-10 22:34:35 +08:00
md5sha256 0d272c8fe9 Publish nms provider poms 2021-12-05 23:07:05 +08:00
md5sha256 6b2c905939 Parallel builds 2021-12-05 22:57:17 +08:00
md5sha256 7ab782799b Fix maven publish tasks 2021-12-05 22:57:03 +08:00
md5sha256 bea82eae88 Fix maven publish tasks 2021-12-05 22:56:37 +08:00
md5sha256 4ac0e045bd Add maven publish task 2021-12-05 18:22:41 +08:00
md5sha256 e5061b218e Java 17 and 1.18 2021-12-01 17:59:17 +08:00
md5sha256 40fdfba47d Fix silly typo in the buildscript 2021-11-18 22:16:36 +08:00
md5sha256 e9260cede6 Bump gradle wrapper version to 7.3 2021-11-18 22:14:56 +08:00
md5sha256 bb297c9ff1 Bump version 2021-11-16 15:28:14 +08:00
Andrew Wong 666742ad56 Merge pull request #2 from md5sha256/feature/purge 2021-11-16 15:25:54 +08:00
md5sha256 36eb8c3a5e Fix imports 2021-11-16 15:25:01 +08:00
Olzie-12 06a9f7b28e file management 2021-11-14 14:41:41 +00:00
md5sha256 e101780420 Fix compat for file manager 2021-11-11 13:31:09 +08:00
md5sha256 6abe99e807 Log sign warnings to the sign error logger 2021-11-09 19:06:02 +08:00
md5sha256 a1d18521ee Introduce interface for FileManager 2021-10-11 00:00:57 +08:00
md5sha256 363b416c59 Retain compat for FileManager 2021-10-10 03:48:12 +08:00
md5sha256 7bf516108b Rename AreaShop again and fix teleport feature 2021-10-09 22:22:53 +08:00
md5sha256 7567cb5fe4 Cleanup global features 2021-10-09 21:33:19 +08:00
md5sha256 d2ca54e8ea Fix signs not updating 2021-10-09 21:03:25 +08:00
md5sha256 e47cda4254 Fix plugin.yml 2021-10-09 17:44:01 +08:00
md5sha256 98d4c6a778 Fix relocations and cleanup DI for Economy and Permission 2021-10-09 17:40:10 +08:00
md5sha256 2a44dd29cc Fix relocations 2021-10-09 17:29:36 +08:00
md5sha256 c1665c33ff Finish cleaning up DI 2021-10-09 17:24:28 +08:00
md5sha256 2cdab9b6db Initial work on guice 2021-10-09 13:27:46 +08:00
md5sha256 72faf76619 Fix ClassCastException in RegionSign 2021-10-09 13:27:28 +08:00
md5sha256 ad66ce00b1 Actually register the sign listener 2021-10-09 02:00:38 +08:00
md5sha256 edc7126b87 Performance improvements to FileManager and various commands 2021-10-09 01:02:00 +08:00
md5sha256 a7f0ac248c Initial work on sign refactoring 2021-10-08 17:44:43 +08:00
md5sha256 675dee2cd3 Add sign error logger 2021-10-07 03:12:45 +08:00
md5sha256 c7226750ab Don't check for WG v5 2021-10-07 01:36:36 +08:00
md5sha256 2ecbb61053 Performance improvements for the teleport feature 2021-10-07 01:34:18 +08:00
md5sha256 fc132558a3 Add a BlockBehaviourHelper 2021-10-07 01:24:20 +08:00
md5sha256 b172413b62 Minor performance improvements 2021-10-07 00:11:09 +08:00
md5sha256 dcbb1f5896 Fix buildscripts and Java 16 support 2021-10-06 23:59:23 +08:00
md5sha256 6e3855c0c3 Remove legacy modules, remove use of ScriptEngine 2021-10-06 23:46:58 +08:00
md5sha256 27991d17a2 Gradle 2021-10-06 23:39:57 +08:00
md5sha256 159221d53d Initial work on updating to 1.17 2021-10-05 23:45:25 +08:00
dependabot[bot] 557d11dfb4 Bump checkstyle from 8.21 to 8.29
Bumps [checkstyle](https://github.com/checkstyle/checkstyle) from 8.21 to 8.29.
- [Release notes](https://github.com/checkstyle/checkstyle/releases)
- [Commits](https://github.com/checkstyle/checkstyle/compare/checkstyle-8.21...checkstyle-8.29)

Signed-off-by: dependabot[bot] <support@github.com>
2020-02-26 11:02:43 +01:00
Thijs Wiefferink b9547e2c67 Remove github action experiment 2019-08-16 18:22:19 +02:00
Thijs Wiefferink 221785ae55 Add test workflow maven build 2019-08-16 17:42:22 +02:00
Thijs Wiefferink 0d04676bce Fix including bukkit into the AreaShop jar 2019-06-23 22:27:35 +02:00
Thijs Wiefferink c8cd68c17b Fixup javadoc build 2019-06-23 22:07:34 +02:00
Thijs Wiefferink 539887449c pom.xml: build with craftbukkit 1.13 2019-06-23 21:59:04 +02:00
Thijs Wiefferink 4cda8a9292 Fix sign handling for 1.14
- Setup modules to load different classes for different Bukkit/Spigot versions
- Create BukkitHandler to get/set the sign facing and get the block it is attached to
- Fix `/as addsign` to use new sign methods
- Fix sign updates to use new sign methods
- Implement full forwards and backwards compatibility of the saved sign material type
    - On Bukkit 1.12 and lower all special wood types are translated to the standard sign
    - On Bukkit 1.13 the internal sign name is translated (and special wood types to the standard one)
    - On Bukkit 1.14 the signs of 1.13- are translated to the OAK variants
- Cleanup the .gitignore files inside of the module folders
2019-06-23 21:53:48 +02:00
Thijs Wiefferink fe131dc157 BuyRegion/RentRegion: fix %player% placeholders for selling/unrenting confirmation messages 2019-06-16 21:40:58 +02:00
Thijs Wiefferink 41ced9ee6c Update checkstyle from 7.6 to 8.21 2019-06-01 17:08:30 +02:00
Thijs Wiefferink 03de0ff252 default.yml: fix spelling mistake 2019-06-01 16:24:15 +02:00
Thijs Wiefferink b057271394 Fix permission check of /as rent, fix 'already bought' check of /as buy 2019-02-20 19:33:37 +01:00
Thijs Wiefferink d7cdff0b22 /as setteleport: fix check that hides it from /as help 2019-02-08 22:29:57 +01:00
Thijs Wiefferink 1035b6b41b Move event commands to a feature class, add two events
- Move eventCommandProfile code to a separate class
- Add AddingRegionEvent
- Add DeletingRegionEvent
- Cleanup a couple of duplicate code paths (merge RentRegion/BuyRegion branches)
2019-01-28 23:37:43 +01:00
Thijs Wiefferink e0bad7397c Refactoring based on SonarLint and Intellij IDEA inspections 2019-01-26 21:23:49 +01:00
Thijs Wiefferink b7124e8cdd Remove mcstats.org metrics class, I don't believe they will be online again 2019-01-26 20:11:26 +01:00
Thijs Wiefferink f0952c32c9 Update issue templates
Add 'NEW' label to issues created using the template
2019-01-13 22:26:54 +01:00
Thijs Wiefferink d3dfa86a65 Set version to 2.6.0 2019-01-13 17:34:50 +01:00
Thijs Wiefferink 8f73b8af3c documentation/release.md: add instructions for releasing a new version 2019-01-13 17:34:37 +01:00
Thijs Wiefferink 51b24c74b4 langHeader.yml: add the template used to generate the language file headers to the repository 2019-01-13 17:33:54 +01:00
Thijs Wiefferink 9beb1eb61b Move the changelog from the wiki to the repository 2019-01-13 17:33:09 +01:00
Thijs Wiefferink de5fdafca0 Pull translations from Transifex 2019-01-08 21:18:19 +01:00
Thijs Wiefferink 0aea914d20 Add FastAsyncWorldEdit support on Spigot 1.13
- FastAsyncWorldEdit now supported on Spigot 1.13
- Improved support for the beta-01 versions of WorldGuard and WorldEdit
- Resolves #436
2019-01-08 00:19:48 +01:00
Thijs Wiefferink b4efe7d5bf Add default labels to issue templates 2019-01-05 16:27:05 +01:00
Thijs Wiefferink ec7983e126 Fix handling of sign updates at places where they will pop off immediately
1. When placing back a missing sign it could be placed in the middle of the air
2. BlockPhysicsEvent would fire immediately (synchronously) breaking the sign
3. Sign update would break because the sign has not actually been placed
2019-01-01 19:32:34 +01:00
Thijs Wiefferink e45c353030 Fix detecting region by location when using WorldEdit 7 beta-2 or later
- The WorldEdit 7 beta-2 handler was inheriting a function from the handler of older version that uses the old Vector class
- Fixes #466
- Fixes #467
2019-01-01 19:30:16 +01:00
Thijs Wiefferink 44b1cb0fc8 /as add: fix setting player as landlord when he is an owner of the region
- Fixes #427
- Adds a debug message to check the behavior easily in the future
2018-12-28 17:11:48 +01:00
Thijs Wiefferink c7299fa56c Update Discord image to a widget image 2018-12-27 23:14:56 +01:00
pmme 12bf467714 Simplify WorldEdit 7 flushQueue vs. flushSession 2018-12-27 22:47:14 +01:00
Thijs Wiefferink 5b327db316 signs: instead of cancelling indirect break, remove the sign to prevent lagg 2018-12-27 19:44:30 +01:00
Thijs Wiefferink b4f33589a1 Cleanup old directory 2018-12-27 17:45:19 +01:00
Thijs Wiefferink 530c74ccd2 Add support for the WorldEdit vector refactor update
- Add WorldEdit and WorldGuard module that supports the new vector system
- WorldGuard/WordEdit dependencies are in the repository itself to make builds more reliable
- Change code that uses WorldEdit vectors to use Spigot vectors
- Rename all modules to areashop-[worldguard|worldedit]-<version>
- Change maven versions of internal modules to 'latest' to be less confusing
2018-12-27 17:42:24 +01:00
Thijs Wiefferink fa4857cbce Simplify code in the handler for WorldEdit 7 2018-12-27 15:00:53 +01:00
Thijs Wiefferink 93fd4e96cb Fix restoring schematics for the latest WorldEdit dev builds
- Fixes #447
- Thanks pmme and x1p for reporting the issue!
2018-10-28 17:58:09 +01:00
Thijs Wiefferink a6863ae782 Also put the Vault dependency into /dependencies
- Now it should be easy again to built AreaShop yourself, only need to run BuildTools for 1.13.0 and it should work
2018-10-28 01:15:12 +02:00
Thijs Wiefferink e5e2c4ca08 Fixup dependencies, use Bukkit/CraftBukkit 1.7.9 instead of 1.8
- 1.7.9 is the lowest supported version, so it is good to use that as base
2018-10-28 00:53:30 +02:00
Thijs Wiefferink b0341e2a3e Fix compatibility with 1.13 Material class
- Fixes sign handling to properly detect and store signs, fixes #440
- Fixes safe teleporting (also improves block detection, making it even safer)
2018-10-28 00:12:24 +02:00
Thijs Wiefferink c8e1ebb068 Change WorldGuard/WorldEdit/Bukkit dependencies to file links
- Fixes the issue that olders WorldEdit and Bukkit versions are not available on Maven anymore
- This speeds up the build a lot
2018-10-28 00:00:41 +02:00
Thijs Wiefferink 39c8eb5f73 Fix tab complete types for /as setduration 2018-10-22 23:44:31 +02:00
Thijs Wiefferink 2483cf1614 Try to add compatibility with the FAWE schematic format 2018-10-21 21:59:45 +02:00
173 changed files with 7901 additions and 5427 deletions

No files matched your search

+3
View File
@@ -1,6 +1,9 @@
---
name: Bug report
about: Report a problem in the plugin
title: ''
labels: 'NEW, Type: Bug'
assignees: ''
---
@@ -1,6 +1,9 @@
---
name: Feature request
about: Suggest an idea
title: ''
labels: 'NEW, Type: Feature'
assignees: ''
---
@@ -1,6 +1,9 @@
---
name: Support question
about: Ask help with the setup or usage of the plugin
title: ''
labels: 'NEW, Type: Support'
assignees: ''
---
+23
View File
@@ -0,0 +1,23 @@
name: Java CI with Gradle
on: [ push, pull_request ]
jobs:
build:
# Only run on PRs if the source branch is on someone else's repo
if: ${{ github.event_name != 'pull_request' || github.repository != github.event.pull_request.head.repo.full_name }}
strategy:
matrix:
os: ["ubuntu-latest", "windows-latest"]
runs-on: "${{ matrix.os }}"
steps:
- uses: actions/checkout@v2
- uses: gradle/wrapper-validation-action@v1.0.4
- name: Set up JDK 17
uses: actions/setup-java@v2
with:
java-version: '17'
distribution: 'zulu'
cache: 'gradle'
- name: Build with Gradle
run: ./gradlew clean build
+189 -20
View File
@@ -1,25 +1,194 @@
# Maven stuff
/target
.project
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.classpath
.settings/
.loadpath
# Created by https://www.toptal.com/developers/gitignore/api/macos,windows,intellij+all,gradle,maven
# Edit at https://www.toptal.com/developers/gitignore?templates=macos,windows,intellij+all,gradle,maven
# Locally stored "Eclipse launch configurations"
*.launch
### Intellij+all ###
# 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
# CMake
cmake-build-*/
# 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
# 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
### Intellij+all Patch ###
# Ignores the whole .idea folder and all .iml files
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
.idea/*
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
# IntelliJ IDEA
*.iml
.idea
dependency-reduced-pom.xml
modules.xml
.idea/misc.xml
*.ipr
desktop.ini
# Sonarlint plugin
.idea/sonarlint
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### 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
### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db
# Dump file
*.stackdump
# Folder config file
[Dd]esktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp
# Windows shortcuts
*.lnk
### Gradle ###
.gradle
build/
build-cache/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Cache of project
.gradletasknamecache
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
# gradle/wrapper/gradle-wrapper.properties
### Gradle Patch ###
**/build/
# End of https://www.toptal.com/developers/gitignore/api/macos,windows,intellij+all,gradle,maven
-1
View File
@@ -1 +0,0 @@
/target
+96
View File
@@ -0,0 +1,96 @@
plugins {
id("com.github.johnrengelman.shadow") version "7.1.2"
}
description = "AreaShop"
dependencies {
// Platform
compileOnlyApi(libs.spigot)
compileOnlyApi(libs.worldeditCore) {
exclude("com.google.guava", "guava")
}
compileOnlyApi(libs.worldeditBukkit) {
exclude("com.google.guava", "guava")
}
compileOnlyApi(libs.worldguardCore) {
exclude("com.google.guava", "guava")
}
compileOnlyApi(libs.worldguardBukkit) {
exclude("com.google.guava", "guava")
}
compileOnlyApi("com.github.MilkBowl:VaultAPI:1.7") {
exclude("com.google.guava", "guava")
}
// 3rd party libraries
implementation(libs.findbugs)
implementation("io.papermc:paperlib:1.0.7")
implementation("com.github.NLthijs48:InteractiveMessenger:e7749258ca")
implementation("com.github.NLthijs48:BukkitDo:819d51ec2b")
implementation("io.github.baked-libs:dough-data:1.0.3")
implementation("com.google.inject:guice:5.1.0") {
exclude("com.google.guava", "guava")
}
implementation("com.google.inject.extensions:guice-assistedinject:5.1.0") {
exclude("com.google.guava", "guava")
}
// Project submodules
implementation(projects.areashopInterface)
implementation(projects.areashopNms)
implementation(projects.adapters.platform.platformInterface)
implementation(projects.adapters.platform.paper)
// Adapters
runtimeOnly(projects.adapters.plugins.worldedit)
runtimeOnly(projects.adapters.plugins.worldguard)
runtimeOnly(projects.adapters.plugins.fastasyncworldedit)
runtimeOnly(project(":adapters:platform:bukkit-1-17", "reobf"))
runtimeOnly(project(":adapters:platform:bukkit-1-18", "reobf"))
runtimeOnly(project(":adapters:platform:bukkit-1-19", "reobf"))
}
repositories {
mavenCentral()
}
tasks {
processResources {
filesMatching("plugin.yml") {
expand("version" to project.version)
}
}
assemble {
dependsOn(shadowJar)
}
jar {
archiveClassifier.set("original")
}
java {
withSourcesJar()
}
val javaComponent = project.components["java"] as AdhocComponentWithVariants
javaComponent.withVariantsFromConfiguration(configurations["shadowRuntimeElements"]) {
skip()
}
shadowJar {
archiveClassifier.set("")
base {
archiveBaseName.set("AreaShop")
}
val base = "me.wiefferink.areashop.libraries"
relocate("me.wiefferink.interactivemessenger", "${base}.interactivemessenger")
relocate("me.wiefferink.bukkitdo", "${base}.bukkitdo")
relocate("io.papermc.lib", "${base}.paperlib")
relocate("io.github.bakedlibs.dough", "${base}.dough")
relocate("com.google.inject", "${base}.inject")
relocate("org.aopalliance", "${base}.aopalliance")
relocate("javax.annotation", "${base}.javax.annotation")
relocate("javax.inject", "${base}.javax.inject")
}
}
-280
View File
@@ -1,280 +0,0 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>areashop</artifactId>
<packaging>jar</packaging>
<name>AreaShop</name>
<version>2.5.0</version> <!-- Main plugin version -->
<parent>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-parent</artifactId>
<version>parent</version>
</parent>
<dependencies>
<!-- Bukkit, AreaShop aims to support 1.7.9+, but this is the lowest Bukkit version available from the Spigot repo, Bukkit repository is gone -->
<dependency>
<groupId>org.bukkit</groupId>
<artifactId>bukkit</artifactId>
<version>${bukkit.version}</version>
<type>jar</type>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<!-- InteractiveMessenger library -->
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>interactivemessenger</artifactId>
<version>1.1-SNAPSHOT</version>
</dependency>
<!-- BukkitDo library -->
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>bukkitdo</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-worldguard-5</artifactId>
<version>WorldGuard-5</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-worldguard-6</artifactId>
<version>WorldGuard-6</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-worldguard-6_1_3</artifactId>
<version>WorldGuard-6_1_3</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-worldguard-7</artifactId>
<version>WorldGuard-7</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-interface</artifactId>
<version>AreaShopInterface</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-worldedit-5</artifactId>
<version>WorldEdit-5</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-worldedit-6</artifactId>
<version>WorldEdit-6</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.wiefferink</groupId>
<artifactId>areashop-worldedit-7</artifactId>
<version>WorldEdit-7</version>
<type>jar</type>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.sk89q</groupId>
<artifactId>worldedit</artifactId>
<scope>system</scope>
<version>any</version>
<systemPath>${project.basedir}/../dependencies/worldedit-bukkit-7.0.0-beta-01.jar</systemPath>
</dependency>
<dependency>
<groupId>com.sk89q</groupId>
<artifactId>worldguard</artifactId>
<scope>system</scope>
<version>any</version>
<systemPath>${project.basedir}/../dependencies/worldguard-legacy-7.0.0-beta01.jar</systemPath>
</dependency>
<dependency>
<groupId>net.milkbowl.vault</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.4</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
<profiles>
<!-- Copy the jar file to a test server, activate by using -DcopyResult="/path/to/test/server" -->
<profile>
<id>test-locally</id>
<activation>
<property>
<name>copyResult</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<copy file="./target/${project.build.finalName}.jar"
tofile="${copyResult}\${project.build.finalName}.jar"/>
</target>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- Package the source files in a jar, activate by using -Dsources -->
<profile>
<id>package-sources</id>
<activation>
<property>
<name>sources</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
<!-- Produce javadoc files, activate by using -Djavadoc -->
<profile>
<id>generate-javadoc</id>
<activation>
<property>
<name>javadoc</name>
</property>
</activation>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<executions>
<execution>
<phase>package</phase>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<excludePackageNames>me.wiefferink.areashop.lib</excludePackageNames>
<destDir>${javadoc}</destDir>
<links>
<link>https://hub.spigotmc.org/javadocs/bukkit/</link>
<link>http://docs.sk89q.com/worldedit/apidocs/</link>
<link>http://docs.sk89q.com/worldguard/apidocs/</link>
</links>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
<build>
<directory>target</directory>
<finalName>AreaShop</finalName>
<resources>
<resource>
<targetPath>.</targetPath>
<filtering>true</filtering>
<directory>src/main/resources</directory>
<includes>
<include>plugin.yml</include>
<include>config.yml</include>
<include>hiddenConfig.yml</include>
<include>default.yml</include>
<include>README.md</include>
<include>lang/*.yml</include>
</includes>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<relocations>
<!-- Relocate messaging framework -->
<relocation>
<pattern>me.wiefferink.interactivemessenger</pattern>
<shadedPattern>me.wiefferink.areashop.shaded.interactivemessenger</shadedPattern>
</relocation>
<!-- Relocate BukkitDo -->
<relocation>
<pattern>me.wiefferink.bukkitdo</pattern>
<shadedPattern>me.wiefferink.areashop.shaded.bukkitdo</shadedPattern>
</relocation>
<!-- Relocate bstats -->
<relocation>
<pattern>org.bstats</pattern>
<shadedPattern>me.wiefferink.areashop.shaded.bstats</shadedPattern>
</relocation>
</relocations>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
</plugin>
</plugins>
</build>
</project>
@@ -1,22 +1,36 @@
package me.wiefferink.areashop;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Stage;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.managers.RegionManager;
import io.papermc.lib.PaperLib;
import me.wiefferink.areashop.adapters.platform.MinecraftPlatform;
import me.wiefferink.areashop.adapters.platform.paper.PaperPlatform;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.listeners.PlayerLoginLogoutListener;
import me.wiefferink.areashop.managers.CommandManager;
import me.wiefferink.areashop.managers.FeatureManager;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.FileManager;
import me.wiefferink.areashop.managers.Manager;
import me.wiefferink.areashop.managers.SignErrorLogger;
import me.wiefferink.areashop.managers.SignLinkerManager;
import me.wiefferink.areashop.tools.Analytics;
import me.wiefferink.areashop.modules.AreaShopModule;
import me.wiefferink.areashop.modules.BukkitModule;
import me.wiefferink.areashop.modules.DependencyModule;
import me.wiefferink.areashop.modules.PlatformModule;
import me.wiefferink.areashop.nms.NMS;
import me.wiefferink.areashop.tools.GithubUpdateCheck;
import me.wiefferink.areashop.tools.SimpleMessageBridge;
import me.wiefferink.areashop.tools.SpigotPlatform;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.bukkitdo.Do;
import me.wiefferink.interactivemessenger.processing.Message;
import me.wiefferink.interactivemessenger.source.LanguageManager;
import net.milkbowl.vault.economy.Economy;
import org.apache.commons.lang.StringUtils;
@@ -34,30 +48,37 @@ import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.bukkit.plugin.java.JavaPlugin;
import javax.annotation.Nonnull;
import java.io.File;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;
/**
* Main class for the AreaShop plugin.
* Contains methods to get parts of the plugins functionality and definitions for constants.
*/
public final class AreaShop extends JavaPlugin implements AreaShopInterface {
public final class AreaShop extends JavaPlugin implements AreaShopApi {
// Statically available instance
private static AreaShop instance = null;
// General variables
private Injector injector;
private WorldGuardPlugin worldGuard = null;
private WorldGuardInterface worldGuardInterface = null;
private WorldEditPlugin worldEdit = null;
private WorldEditInterface worldEditInterface = null;
private FileManager fileManager = null;
private NMS nms;
private MessageBridge messageBridge;
private IFileManager fileManager = null;
private LanguageManager languageManager = null;
private CommandManager commandManager = null;
private SignLinkerManager signLinkerManager = null;
private FeatureManager featureManager = null;
private SignManager signManager;
private SignErrorLogger signErrorLogger;
private Set<Manager> managers = null;
private boolean debug = false;
private List<String> chatprefix = null;
@@ -72,6 +93,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
public static final String defaultFile = "default.yml";
public static final String configFile = "config.yml";
public static final String configFileHidden = "hiddenConfig.yml";
public static final String signLogFile = "sign-errors.log";
public static final String versionFile = "versions";
// Euro tag for in the config
@@ -141,193 +163,152 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
/**
* Called on start or reload of the server.
*/
@Override
public void onEnable() {
AreaShop.instance = this;
Do.init(this);
managers = new HashSet<>();
boolean error = false;
messageBridge = new SimpleMessageBridge();
signErrorLogger = new SignErrorLogger(new File(getDataFolder(), signLogFile));
// Check if WorldGuard is present
String wgVersion = null;
String rawVersion = null;
int major = 0;
int minor = 0;
int fixes = 0;
Integer build = null;
Plugin plugin = getServer().getPluginManager().getPlugin("WorldGuard");
if(!(plugin instanceof WorldGuardPlugin) || !plugin.isEnabled()) {
error("WorldGuard plugin is not present or has not loaded correctly");
error = true;
} else {
worldGuard = (WorldGuardPlugin)plugin;
// Get correct WorldGuardInterface (handles things that changed version to version)
try {
rawVersion = worldGuard.getDescription().getVersion();
if(rawVersion.contains("-SNAPSHOT;")) {
String buildNumber = rawVersion.substring(rawVersion.indexOf("-SNAPSHOT;") + 10, rawVersion.length());
if(buildNumber.contains("-")) {
buildNumber = buildNumber.substring(0, buildNumber.indexOf("-"));
try {
build = Integer.parseInt(buildNumber);
} catch(NumberFormatException e) {
warn("Could not correctly parse the build of WorldGuard, raw version: " + rawVersion + ", buildNumber: " + buildNumber);
}
}
}
// Clear stuff from the version string that is not a number
String[] versionParts = rawVersion.split("\\.");
for(int i = 0; i < versionParts.length; i++) {
Pattern pattern = Pattern.compile("^\\d+");
Matcher matcher = pattern.matcher(versionParts[i]);
if(matcher.find()) {
versionParts[i] = matcher.group();
}
}
// Find major, minor and fix numbers
try {
if(versionParts.length > 0) {
major = Integer.parseInt(versionParts[0]);
}
if(versionParts.length > 1) {
minor = Integer.parseInt(versionParts[1]);
}
if(versionParts.length > 2) {
fixes = Integer.parseInt(versionParts[2]);
}
} catch(NumberFormatException e) {
warn("Something went wrong while parsing WorldGuard version number: " + rawVersion);
}
// Determine correct implementation to use
if(worldGuard.getDescription().getVersion().startsWith("5.")) {
wgVersion = "5";
} else if(major == 6 && minor == 1 && fixes < 3) {
wgVersion = "6";
} else if(major == 6) {
if(build != null && build == 1672) {
error = true;
error("Build 1672 of WorldGuard is broken, update to a later build or a stable version!");
} else if(build != null && build < 1672) {
wgVersion = "6";
} else {
wgVersion = "6_1_3";
}
} else {
wgVersion = "7";
}
} catch(Exception e) { // If version detection fails, at least try to load the latest version
wgVersion = "7";
}
// Load chosen implementation
try {
final Class<?> clazz = Class.forName("me.wiefferink.areashop.handlers.WorldGuardHandler" + wgVersion);
// Check if we have a NMSHandler class at that location.
if(WorldGuardInterface.class.isAssignableFrom(clazz)) { // Make sure it actually implements WorldGuardInterface
worldGuardInterface = (WorldGuardInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this); // Set our handler
}
} catch(final Exception e) {
error("Could not load the handler for WorldGuard (tried to load " + wgVersion + "), report this problem to the author:" + ExceptionUtils.getStackTrace(e));
error = true;
wgVersion = null;
}
// Setup NMS Impl
String rawServerVersion = Bukkit.getServer().getClass().getPackageName();
String[] split = rawServerVersion.split("\\.");
String serverVersion = split[3];
try {
Class<?> nmsImpl = Class.forName("me.wiefferink.areashop.adapters.platform." + serverVersion + ".NMSImpl");
this.nms = nmsImpl.asSubclass(NMS.class).getConstructor().newInstance();
} catch (ReflectiveOperationException ex) {
ex.printStackTrace();
error("Failed to initialize NMS implementation!");
shutdownOnError();
return;
}
// Check if WorldEdit is present
String weVersion = null;
plugin = getServer().getPluginManager().getPlugin("WorldEdit");
if(!(plugin instanceof WorldEditPlugin) || !plugin.isEnabled()) {
error("WorldEdit plugin is not present or has not loaded correctly");
error = true;
final MinecraftPlatform platform;
if (PaperLib.isPaper()) {
platform = new PaperPlatform(this);
info("Detected Paper; using the PaperPlatform impl");
} else {
worldEdit = (WorldEditPlugin)plugin;
// Get correct WorldEditInterface (handles things that changed version to version)
if(worldEdit.getDescription().getVersion().startsWith("5.")) {
weVersion = "5";
} else if(worldEdit.getDescription().getVersion().startsWith("6.")) {
weVersion = "6";
} else {
weVersion = "7";
}
try {
final Class<?> clazz = Class.forName("me.wiefferink.areashop.handlers.WorldEditHandler" + weVersion);
// Check if we have a NMSHandler class at that location.
if(WorldEditInterface.class.isAssignableFrom(clazz)) { // Make sure it actually implements WorldEditInterface
worldEditInterface = (WorldEditInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this); // Set our handler
}
} catch(final Exception e) {
error("Could not load the handler for WorldEdit (tried to load " + weVersion + "), report this problem to the author: " + ExceptionUtils.getStackTrace(e));
error = true;
weVersion = null;
}
platform = new SpigotPlatform(this);
info("Detected Spigot; using the SpigotPlatform impl");
}
final PlatformModule platformModule = new PlatformModule(platform, this.nms);
// Check if Vault is present
if(getServer().getPluginManager().getPlugin("Vault") == null) {
error("Vault plugin is not present or has not loaded correctly");
error = true;
shutdownOnError();
return;
}
// Find WorldEdit integration version to load
String weHandlerVersion;
Plugin plugin = getServer().getPluginManager().getPlugin("WorldEdit");
if(!(plugin instanceof WorldEditPlugin) || !plugin.isEnabled()) {
error("WorldEdit plugin is not present or has not loaded correctly");
return;
} else {
this.worldEdit = (WorldEditPlugin) plugin;
Plugin fawePlugin = getServer().getPluginManager().getPlugin("FastAsyncWorldEdit");
if (fawePlugin != null && fawePlugin.isEnabled()) {
weHandlerVersion = "FastAsyncWorldEditHandler";
info("Detected FastAsyncWorldEdit, using the fawe handler");
} else {
weHandlerVersion = "WorldEditHandler";
}
}
plugin = getServer().getPluginManager().getPlugin("WorldGuard");
if(!(plugin instanceof WorldGuardPlugin) || !plugin.isEnabled()) {
error("WorldGuard plugin is not present or has not loaded correctly");
shutdownOnError();
return;
} else {
this.worldGuard = (WorldGuardPlugin) plugin;
}
DependencyModule dependencyModule = new DependencyModule(this.worldEdit, this.worldGuard, getEconomy(), getPermissionProvider());
// Load WorldEdit
try {
Class<?> clazz = Class.forName("me.wiefferink.areashop.adapters.plugins." + weHandlerVersion);
if(WorldEditInterface.class.isAssignableFrom(clazz)) { // Make sure it actually implements WorldEditInterface
worldEditInterface = (WorldEditInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this); // Set our handler
}
} catch(Exception e) {
error("Could not load the handler for WorldEdit (tried to load " + weHandlerVersion + "), report this problem to the author: " + ExceptionUtils.getStackTrace(e));
shutdownOnError();
return;
}
// Load WorldGuard
try {
Class<?> clazz = Class.forName("me.wiefferink.areashop.adapters.plugins.WorldGuardHandler");
// Check if we have a NMSHandler class at that location.
if(WorldGuardInterface.class.isAssignableFrom(clazz)) { // Make sure it actually implements WorldGuardInterface
worldGuardInterface = (WorldGuardInterface)clazz.getConstructor(AreaShopInterface.class).newInstance(this); // Set our handler
}
} catch(Exception e) {
error("Could not load the handler for WorldGuard, report this problem to the author:" + ExceptionUtils.getStackTrace(e));
shutdownOnError();
return;
}
AreaShopModule asModule = new AreaShopModule(this, messageBridge, nms, worldEditInterface, worldGuardInterface, signErrorLogger, platformModule, dependencyModule);
injector = Guice.createInjector(Stage.PRODUCTION, new BukkitModule(getServer()), asModule);
// Load all data from files and check versions
fileManager = new FileManager();
managers.add(fileManager);
error = error | !fileManager.loadFiles(false);
// Print loaded version of WG and WE in debug
if(wgVersion != null) {
AreaShop.debug("Loaded WorldGuardHandler" + wgVersion + " (raw version: " + rawVersion + ", major:" + major + ", minor:" + minor + ", fixes:" + fixes + ", build:" + build + ")");
}
if(weVersion != null) {
AreaShop.debug("Loaded WorldEditHandler" + weVersion);
fileManager = injector.getInstance(IFileManager.class);
managers.add((FileManager) fileManager);
boolean loadFilesResult = fileManager.loadFiles(false);
if (!loadFilesResult) {
shutdownOnError();
return;
}
setupLanguageManager();
if(error) {
error("The plugin has not started, fix the errors listed above");
} else {
featureManager = new FeatureManager();
managers.add(featureManager);
featureManager = injector.getInstance(FeatureManager.class);
featureManager.initializeFeatures(injector);
managers.add(featureManager);
signManager = new SignManager();
managers.add(signManager);
// Register the event listeners
getServer().getPluginManager().registerEvents(new PlayerLoginLogoutListener(this), this);
// Register the event listeners
getServer().getPluginManager().registerEvents(new PlayerLoginLogoutListener(this, messageBridge), this);
setupTasks();
setupTasks();
// Startup the CommandManager (registers itself for the command)
commandManager = new CommandManager();
managers.add(commandManager);
// Startup the CommandManager (registers itself for the command)
commandManager = injector.getInstance(CommandManager.class);
managers.add(commandManager);
// Create a signLinkerManager
signLinkerManager = new SignLinkerManager();
managers.add(signLinkerManager);
// Create a signLinkerManager
signLinkerManager = injector.getInstance(SignLinkerManager.class);
managers.add(signLinkerManager);
// Enable Metrics if config allows it
if(getConfig().getBoolean("sendStats")) {
Analytics.start();
}
// Register dynamic permission (things declared in config)
registerDynamicPermissions();
// Register dynamic permission (things declared in config)
registerDynamicPermissions();
// Don't initialize the updatechecker if disabled in the config
if(getConfig().getBoolean("checkForUpdates")) {
githubUpdateCheck = new GithubUpdateCheck(
this,
"md5sha256",
"AreaShop"
).withVersionComparator((latestVersion, currentVersion) ->
!cleanVersion(latestVersion).equals(cleanVersion(currentVersion))
).checkUpdate(result -> {
AreaShop.debug("Update check result:", result);
if(!result.hasUpdate()) {
return;
}
// Don't initialize the updatechecker if disabled in the config
if(getConfig().getBoolean("checkForUpdates")) {
githubUpdateCheck = new GithubUpdateCheck(
AreaShop.getInstance(),
"NLThijs48",
"AreaShop"
).withVersionComparator((latestVersion, currentVersion) ->
!cleanVersion(latestVersion).equals(cleanVersion(currentVersion))
).checkUpdate((result) -> {
AreaShop.debug("Update check result:", result);
if(!result.hasUpdate()) {
return;
}
AreaShop.info("Update from AreaShop V" + cleanVersion(result.getCurrentVersion()) + " to AreaShop V" + cleanVersion(result.getLatestVersion()) + " available, get the latest version at https://www.spigotmc.org/resources/areashop.2991/");
for(Player player : Utils.getOnlinePlayers()) {
notifyUpdate(player);
}
});
}
AreaShop.info("Update from AreaShop V" + cleanVersion(result.getCurrentVersion()) + " to AreaShop V" + cleanVersion(result.getLatestVersion()) + " available, get the latest version at https://github.com/md5sha256/releases");
for(Player player : Utils.getOnlinePlayers()) {
notifyUpdate(player);
}
});
}
}
@@ -337,10 +318,15 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
*/
public void notifyUpdate(CommandSender sender) {
if(githubUpdateCheck != null && githubUpdateCheck.hasUpdate() && sender.hasPermission("areashop.notifyupdate")) {
AreaShop.getInstance().message(sender, "update-playerNotify", cleanVersion(githubUpdateCheck.getCurrentVersion()), cleanVersion(githubUpdateCheck.getLatestVersion()));
messageBridge.message(sender, "update-playerNotify", cleanVersion(githubUpdateCheck.getCurrentVersion()), cleanVersion(githubUpdateCheck.getLatestVersion()));
}
}
private void shutdownOnError() {
error("The plugin has not started, fix the errors listed above");
getServer().getPluginManager().disablePlugin(this);
}
/**
* Cleanup a version number.
* @param version Version to clean
@@ -365,6 +351,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
/**
* Called on shutdown or reload of the server.
*/
@Override
public void onDisable() {
Bukkit.getServer().getScheduler().cancelTasks(this);
@@ -373,24 +360,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
for(Manager manager : managers) {
manager.shutdown();
}
managers = null;
fileManager = null;
languageManager = null;
commandManager = null;
signLinkerManager = null;
featureManager = null;
// Cleanup plugins
worldGuard = null;
worldGuardInterface = null;
worldEdit = null;
worldEditInterface = null;
// Cleanup other stuff
chatprefix = null;
debug = false;
ready = false;
signErrorLogger.saveIfDirty();
HandlerList.unregisterAll(this);
}
@@ -439,10 +409,19 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
this.chatprefix = chatprefix;
}
public NMS getNms() {
return nms;
}
public SignErrorLogger getSignErrorLogger() {
return signErrorLogger;
}
/**
* Function to get the WorldGuard plugin.
* @return WorldGuardPlugin
*/
@Override
public WorldGuardPlugin getWorldGuard() {
return worldGuard;
}
@@ -455,6 +434,12 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
return this.worldGuardInterface;
}
@Nonnull
public SignManager getSignManager() {
return signManager;
}
/**
* Get the RegionManager.
* @param world World to get the RegionManager for
@@ -468,10 +453,16 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* Function to get the WorldEdit plugin.
* @return WorldEditPlugin
*/
@Override
public WorldEditPlugin getWorldEdit() {
return worldEdit;
}
@Override
public Plugin pluginInstance() {
return this;
}
/**
* Function to get WorldGuardInterface for version dependent things.
* @return WorldGuardInterface
@@ -492,6 +483,8 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* Function to get the CommandManager.
* @return the CommandManager
*/
@Nonnull
@Override
public CommandManager getCommandManager() {
return commandManager;
}
@@ -501,6 +494,8 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* Handles sign linking mode.
* @return The SignLinkerManager
*/
@Nonnull
@Override
public SignLinkerManager getSignlinkerManager() {
return signLinkerManager;
}
@@ -510,6 +505,8 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* Manages region specific features.
* @return The FeatureManager
*/
@Nonnull
@Override
public FeatureManager getFeatureManager() {
return featureManager;
}
@@ -518,9 +515,10 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* Function to get the Vault plugin.
* @return Economy
*/
public Economy getEconomy() {
@Deprecated
private Economy getEconomy() {
RegisteredServiceProvider<Economy> economy = getServer().getServicesManager().getRegistration(net.milkbowl.vault.economy.Economy.class);
if(economy == null || economy.getProvider() == null) {
if(economy == null) {
error("There is no economy provider to support Vault, make sure you installed an economy plugin");
return null;
}
@@ -531,9 +529,10 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* Get the Vault permissions provider.
* @return Vault permissions provider
*/
public net.milkbowl.vault.permission.Permission getPermissionProvider() {
@Deprecated
private net.milkbowl.vault.permission.Permission getPermissionProvider() {
RegisteredServiceProvider<net.milkbowl.vault.permission.Permission> permissionProvider = getServer().getServicesManager().getRegistration(net.milkbowl.vault.permission.Permission.class);
if (permissionProvider == null || permissionProvider.getProvider() == null) {
if (permissionProvider == null) {
return null;
}
return permissionProvider.getProvider();
@@ -566,7 +565,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* Method to get the FileManager (loads/save regions and can be used to get regions).
* @return The fileManager
*/
public FileManager getFileManager() {
public IFileManager getFileManager() {
return fileManager;
}
@@ -596,6 +595,13 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* Register all required tasks.
*/
private void setupTasks() {
long signLogTicks = Utils.millisToTicks(TimeUnit.MINUTES.toMillis(5));
Bukkit.getScheduler().runTaskTimerAsynchronously(this,
() -> signErrorLogger.saveIfDirty(),
signLogTicks,
signLogTicks);
// Rent expiration timer
long expirationCheck = Utils.millisToTicks(Utils.getDurationFromSecondsOrString("expiration.delay"));
final AreaShop finalPlugin = this;
@@ -671,26 +677,6 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
}
}
/**
* Send a message to a target without a prefix.
* @param target The target to send the message to
* @param key The key of the language string
* @param replacements The replacements to insert in the message
*/
public void messageNoPrefix(Object target, String key, Object... replacements) {
Message.fromKey(key).replacements(replacements).send(target);
}
/**
* Send a message to a target, prefixed by the default chat prefix.
* @param target The target to send the message to
* @param key The key of the language string
* @param replacements The replacements to insert in the message
*/
public void message(Object target, String key, Object... replacements) {
Message.fromKey(key).prefix().replacements(replacements).send(target);
}
/**
* Return the config.
@@ -714,16 +700,24 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* Non-static debug to use as implementation of the interface.
* @param message Object parts of the message that should be logged, toString() will be used
*/
@Override
public void debugI(Object... message) {
AreaShop.debug(StringUtils.join(message, " "));
}
@Override
public void debugI(Supplier<String> message) {
if (debug) {
info("Debug: " + message.get());
}
}
/**
* Print an information message to the console.
* @param message The message to print
*/
public static void info(Object... message) {
AreaShop.getInstance().getLogger().info(StringUtils.join(message, " "));
AreaShop.getInstance().getLogger().info(() -> StringUtils.join(message, " "));
}
/**
@@ -731,7 +725,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* @param message The message to print
*/
public static void warn(Object... message) {
AreaShop.getInstance().getLogger().warning(StringUtils.join(message, " "));
AreaShop.getInstance().getLogger().warning(() -> StringUtils.join(message, " "));
}
/**
@@ -739,7 +733,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
* @param message The message to print
*/
public static void error(Object... message) {
AreaShop.getInstance().getLogger().severe(StringUtils.join(message, " "));
AreaShop.getInstance().getLogger().severe(() -> StringUtils.join(message, " "));
}
/**
@@ -761,7 +755,7 @@ public final class AreaShop extends JavaPlugin implements AreaShopInterface {
fileManager.saveRequiredFilesAtOnce();
fileManager.loadFiles(true);
setupLanguageManager();
message(confirmationReceiver, "reload-reloading");
messageBridge.message(confirmationReceiver, "reload-reloading");
fileManager.checkRents();
fileManager.updateAllRegions(confirmationReceiver);
}
@@ -0,0 +1,39 @@
package me.wiefferink.areashop;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.interfaces.AreaShopInterface;
import me.wiefferink.areashop.managers.CommandManager;
import me.wiefferink.areashop.managers.FeatureManager;
import me.wiefferink.areashop.managers.SignLinkerManager;
import javax.annotation.Nonnull;
public interface AreaShopApi extends AreaShopInterface {
/**
* Function to get the CommandManager.
*
* @return the CommandManager
*/
@Nonnull CommandManager getCommandManager();
/**
* Get the SignLinkerManager.
* Handles sign linking mode.
*
* @return The SignLinkerManager
*/
@Nonnull SignLinkerManager getSignlinkerManager();
/**
* Get the FeatureManager.
* Manages region specific features.
*
* @return The FeatureManager
*/
@Nonnull FeatureManager getFeatureManager();
@Nonnull SignManager getSignManager();
}
@@ -0,0 +1,21 @@
package me.wiefferink.areashop;
public interface MessageBridge {
/**
* Send a message to a target without a prefix.
*
* @param target The target to send the message to
* @param key The key of the language string
* @param replacements The replacements to insert in the message
*/
void messageNoPrefix(Object target, String key, Object... replacements);
/**
* Send a message to a target, prefixed by the default chat prefix.
*
* @param target The target to send the message to
* @param key The key of the language string
* @param replacements The replacements to insert in the message
*/
void message(Object target, String key, Object... replacements);
}
@@ -2,18 +2,30 @@ package me.wiefferink.areashop.commands;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
import me.wiefferink.areashop.events.ask.BuyingRegionEvent;
import me.wiefferink.areashop.events.ask.RentingRegionEvent;
import me.wiefferink.areashop.events.notify.BoughtRegionEvent;
import me.wiefferink.areashop.events.notify.RentedRegionEvent;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldEditSelection;
import me.wiefferink.areashop.managers.FileManager;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionFactory;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.bukkitdo.Do;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
@@ -23,8 +35,20 @@ import java.util.TreeSet;
import java.util.UUID;
import java.util.stream.Collectors;
@Singleton
public class AddCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private AreaShop plugin;
@Inject
private WorldEditInterface worldEditInterface;
@Inject
private WorldGuardInterface worldGuardInterface;
@Inject
private RegionFactory regionFactory;
@Override
public String getCommandStart() {
return "areashop add";
@@ -53,12 +77,12 @@ public class AddCommand extends CommandAreaShop {
&& !sender.hasPermission("areashop.createbuy")
&& !sender.hasPermission("areashop.createbuy.member")
&& !sender.hasPermission("areashop.createbuy.owner")) {
plugin.message(sender, "add-noPermission");
messageBridge.message(sender, "add-noPermission");
return;
}
if(args.length < 2 || args[1] == null || (!"rent".equals(args[1].toLowerCase()) && !"buy".equals(args[1].toLowerCase()))) {
plugin.message(sender, "add-help");
if(args.length < 2 || args[1] == null || (!"rent".equalsIgnoreCase(args[1]) && !"buy".equalsIgnoreCase(args[1]))) {
messageBridge.message(sender, "add-help");
return;
}
Map<String, ProtectedRegion> regions = new HashMap<>();
@@ -69,18 +93,18 @@ public class AddCommand extends CommandAreaShop {
}
if(args.length == 2) {
if(player == null) {
plugin.message(sender, "cmd-weOnlyByPlayer");
messageBridge.message(sender, "cmd-weOnlyByPlayer");
return;
}
WorldEditSelection selection = plugin.getWorldEditHandler().getPlayerSelection(player);
WorldEditSelection selection = worldEditInterface.getPlayerSelection(player);
if(selection == null) {
plugin.message(player, "cmd-noSelection");
messageBridge.message(player, "cmd-noSelection");
return;
}
world = selection.getWorld();
regions = Utils.getWorldEditRegionsInSelection(selection).stream().collect(Collectors.toMap(ProtectedRegion::getId, region -> region));
if(regions.size() == 0) {
plugin.message(player, "cmd-noWERegionsFound");
if(regions.isEmpty()) {
messageBridge.message(player, "cmd-noWERegionsFound");
return;
}
} else {
@@ -88,7 +112,7 @@ public class AddCommand extends CommandAreaShop {
if(args.length == 4) {
world = Bukkit.getWorld(args[3]);
if(world == null) {
plugin.message(sender, "add-incorrectWorld", args[3]);
messageBridge.message(sender, "add-incorrectWorld", args[3]);
return;
}
} else {
@@ -96,32 +120,35 @@ public class AddCommand extends CommandAreaShop {
}
} else {
if(args.length < 4) {
plugin.message(sender, "add-specifyWorld");
messageBridge.message(sender, "add-specifyWorld");
return;
} else {
world = Bukkit.getWorld(args[3]);
if(world == null) {
plugin.message(sender, "add-incorrectWorld", args[3]);
messageBridge.message(sender, "add-incorrectWorld", args[3]);
return;
}
}
}
ProtectedRegion region = plugin.getRegionManager(world).getRegion(args[2]);
if(region == null) {
plugin.message(sender, "cmd-noRegion", args[2]);
messageBridge.message(sender, "cmd-noRegion", args[2]);
return;
}
regions.put(args[2], region);
}
final boolean isRent = "rent".equals(args[1].toLowerCase());
final boolean isRent = "rent".equalsIgnoreCase(args[1]);
final Player finalPlayer = player;
AreaShop.debug("Starting add task with " + regions.size() + " regions");
TreeSet<GeneralRegion> regionsSuccess = new TreeSet<>();
TreeSet<GeneralRegion> regionsAlready = new TreeSet<>();
TreeSet<GeneralRegion> regionsAlreadyOtherWorld = new TreeSet<>();
TreeSet<GeneralRegion> regionsRentCancelled = new TreeSet<>(); // Denied by an event listener
TreeSet<GeneralRegion> regionsBuyCancelled = new TreeSet<>(); // Denied by an event listener
TreeSet<String> namesBlacklisted = new TreeSet<>();
TreeSet<String> namesNoPermission = new TreeSet<>();
TreeSet<String> namesAddCancelled = new TreeSet<>(); // Denied by an event listener
Do.forAll(
plugin.getConfig().getInt("adding.regionsPerTick"),
regions.entrySet(),
@@ -129,22 +156,22 @@ public class AddCommand extends CommandAreaShop {
String regionName = regionEntry.getKey();
ProtectedRegion region = regionEntry.getValue();
// Determine if the player is an owner or member of the region
boolean isMember = finalPlayer != null && plugin.getWorldGuardHandler().containsMember(region, finalPlayer.getUniqueId());
boolean isOwner = finalPlayer != null && plugin.getWorldGuardHandler().containsMember(region, finalPlayer.getUniqueId());
boolean isMember = finalPlayer != null && worldGuardInterface.containsMember(region, finalPlayer.getUniqueId());
boolean isOwner = finalPlayer != null && worldGuardInterface.containsOwner(region, finalPlayer.getUniqueId());
String type;
if(isRent) {
type = "rent";
} else {
type = "buy";
}
FileManager.AddResult result = plugin.getFileManager().checkRegionAdd(sender, region, world, isRent ? GeneralRegion.RegionType.RENT : GeneralRegion.RegionType.BUY);
if(result == FileManager.AddResult.ALREADYADDED) {
IFileManager.AddResult result = plugin.getFileManager().checkRegionAdd(sender, region, world, isRent ? GeneralRegion.RegionType.RENT : GeneralRegion.RegionType.BUY);
if(result == IFileManager.AddResult.ALREADYADDED) {
regionsAlready.add(plugin.getFileManager().getRegion(regionName));
} else if(result == FileManager.AddResult.ALREADYADDEDOTHERWORLD) {
} else if(result == IFileManager.AddResult.ALREADYADDEDOTHERWORLD) {
regionsAlreadyOtherWorld.add(plugin.getFileManager().getRegion(regionName));
} else if(result == FileManager.AddResult.BLACKLISTED) {
} else if(result == IFileManager.AddResult.BLACKLISTED) {
namesBlacklisted.add(regionName);
} else if(result == FileManager.AddResult.NOPERMISSION) {
} else if(result == IFileManager.AddResult.NOPERMISSION) {
namesNoPermission.add(regionName);
} else {
// Check if the player should be landlord
@@ -152,91 +179,101 @@ public class AddCommand extends CommandAreaShop {
&& ((sender.hasPermission("areashop.create" + type + ".owner") && isOwner)
|| (sender.hasPermission("areashop.create" + type + ".member") && isMember)));
List<UUID> existing = new ArrayList<>();
existing.addAll(plugin.getWorldGuardHandler().getOwners(region).asUniqueIdList());
existing.addAll(plugin.getWorldGuardHandler().getMembers(region).asUniqueIdList());
existing.addAll(worldGuardInterface.getOwners(region).asUniqueIdList());
existing.addAll(worldGuardInterface.getMembers(region).asUniqueIdList());
AreaShop.debug("regionAddLandlordStatus:", regionName,
"landlord:", landlord,
"existing:", existing,
"isMember:", isMember,
"isOwner:", isOwner,
"createPermission:", sender.hasPermission("areashop.create" + type),
"ownerPermission:", sender.hasPermission("areashop.create" + type + ".owner"),
"memberPermission:", sender.hasPermission("areashop.create" + type + ".member"));
if(isRent) {
RentRegion rent = new RentRegion(regionName, world);
RentRegion rent = regionFactory.createRentRegion(regionName, world);
// Set landlord
if(landlord) {
rent.setLandlord(finalPlayer.getUniqueId(), finalPlayer.getName());
}
// Run commands
rent.runEventCommands(GeneralRegion.RegionEvent.CREATED, true);
plugin.getFileManager().addRent(rent);
AddingRegionEvent event = plugin.getFileManager().addRegion(rent);
if (event.isCancelled()) {
namesAddCancelled.add(rent.getName());
return;
}
rent.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
rent.update();
// Run commands
rent.runEventCommands(GeneralRegion.RegionEvent.CREATED, false);
// Add existing owners/members if any
if(!landlord && !existing.isEmpty()) {
// TODO also execute rent events to notify other plugins?
UUID rentBy = existing.remove(0);
OfflinePlayer rentByPlayer = Bukkit.getOfflinePlayer(rentBy);
// Run commands
rent.runEventCommands(GeneralRegion.RegionEvent.RENTED, true);
RentingRegionEvent rentingRegionEvent = new RentingRegionEvent(rent, rentByPlayer, false);
Bukkit.getPluginManager().callEvent(rentingRegionEvent);
if(rentingRegionEvent.isCancelled()) {
regionsRentCancelled.add(rent);
} else {
// Add values to the rent and send it to FileManager
rent.setRentedUntil(Calendar.getInstance().getTimeInMillis() + rent.getDuration());
rent.setRenter(rentBy);
rent.updateLastActiveTime();
// Add values to the rent and send it to FileManager
rent.setRentedUntil(Calendar.getInstance().getTimeInMillis() + rent.getDuration());
rent.setRenter(existing.remove(0));
rent.updateLastActiveTime();
// Fire schematic event and updated times extended
rent.handleSchematicEvent(GeneralRegion.RegionEvent.RENTED);
// Add others as friends
for(UUID friend : existing) {
rent.getFriendsFeature().addFriend(friend, null);
// Add others as friends
for(UUID friend : existing) {
rent.getFriendsFeature().addFriend(friend, null);
}
rent.notifyAndUpdate(new RentedRegionEvent(rent, false));
}
// Fire schematic event and updated times extended
rent.handleSchematicEvent(GeneralRegion.RegionEvent.RENTED);
// Notify about updates
rent.update();
rent.runEventCommands(GeneralRegion.RegionEvent.RENTED, false);
}
regionsSuccess.add(rent);
} else {
BuyRegion buy = new BuyRegion(regionName, world);
BuyRegion buy = regionFactory.createBuyRegion(regionName, world);
// Set landlord
if(landlord) {
buy.setLandlord(finalPlayer.getUniqueId(), finalPlayer.getName());
}
// Run commands
buy.runEventCommands(GeneralRegion.RegionEvent.CREATED, true);
plugin.getFileManager().addBuy(buy);
AddingRegionEvent event = plugin.getFileManager().addRegion(buy);
if (event.isCancelled()) {
namesAddCancelled.add(buy.getName());
return;
}
buy.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
buy.update();
// Run commands
buy.runEventCommands(GeneralRegion.RegionEvent.CREATED, false);
// Add existing owners/members if any
if(!landlord && !existing.isEmpty()) {
// TODO also execute buy events to notify for other plugins?
UUID buyBy = existing.remove(0);
OfflinePlayer buyByPlayer = Bukkit.getOfflinePlayer(buyBy);
// Run commands
buy.runEventCommands(GeneralRegion.RegionEvent.BOUGHT, true);
BuyingRegionEvent buyingRegionEvent = new BuyingRegionEvent(buy, buyByPlayer);
Bukkit.getPluginManager().callEvent(buyingRegionEvent);
if(buyingRegionEvent.isCancelled()) {
regionsBuyCancelled.add(buy);
} else {
// Set the owner
buy.setBuyer(buyBy);
buy.updateLastActiveTime();
// Set the owner
buy.setBuyer(existing.remove(0));
buy.updateLastActiveTime();
// Add others as friends
for(UUID friend : existing) {
buy.getFriendsFeature().addFriend(friend, null);
// Update everything
buy.handleSchematicEvent(GeneralRegion.RegionEvent.BOUGHT);
// Add others as friends
for (UUID friend : existing) {
buy.getFriendsFeature().addFriend(friend, null);
}
buy.notifyAndUpdate(new BoughtRegionEvent(buy));
}
// Notify about updates
buy.update();
// Update everything
buy.handleSchematicEvent(GeneralRegion.RegionEvent.BOUGHT);
// Run commands
buy.runEventCommands(GeneralRegion.RegionEvent.BOUGHT, false);
}
regionsSuccess.add(buy);
@@ -245,20 +282,29 @@ public class AddCommand extends CommandAreaShop {
},
() -> {
if(!regionsSuccess.isEmpty()) {
plugin.message(sender, "add-success", args[1], Utils.combinedMessage(regionsSuccess, "region"));
messageBridge.message(sender, "add-success", args[1], Utils.combinedMessage(regionsSuccess, "region"));
}
if(!regionsAlready.isEmpty()) {
plugin.message(sender, "add-failed", Utils.combinedMessage(regionsAlready, "region"));
messageBridge.message(sender, "add-failed", Utils.combinedMessage(regionsAlready, "region"));
}
if(!regionsAlreadyOtherWorld.isEmpty()) {
plugin.message(sender, "add-failedOtherWorld", Utils.combinedMessage(regionsAlreadyOtherWorld, "region"));
messageBridge.message(sender, "add-failedOtherWorld", Utils.combinedMessage(regionsAlreadyOtherWorld, "region"));
}
if(!regionsRentCancelled.isEmpty()) {
messageBridge.message(sender, "add-rentCancelled", Utils.combinedMessage(regionsRentCancelled, "region"));
}
if(!regionsBuyCancelled.isEmpty()) {
messageBridge.message(sender, "add-buyCancelled", Utils.combinedMessage(regionsBuyCancelled, "region"));
}
if(!namesBlacklisted.isEmpty()) {
plugin.message(sender, "add-blacklisted", Utils.createCommaSeparatedList(namesBlacklisted));
messageBridge.message(sender, "add-blacklisted", Utils.createCommaSeparatedList(namesBlacklisted));
}
if(!namesNoPermission.isEmpty()) {
plugin.message(sender, "add-noPermissionRegions", Utils.createCommaSeparatedList(namesNoPermission));
plugin.message(sender, "add-noPermissionOwnerMember");
messageBridge.message(sender, "add-noPermissionRegions", Utils.createCommaSeparatedList(namesNoPermission));
messageBridge.message(sender, "add-noPermissionOwnerMember");
}
if(!namesAddCancelled.isEmpty()) {
messageBridge.message(sender, "add-rentCancelled", Utils.createCommaSeparatedList(namesAddCancelled));
}
}
);
@@ -275,8 +321,7 @@ public class AddCommand extends CommandAreaShop {
result.add("buy");
}
} else if(toComplete == 3) {
if(sender instanceof Player) {
Player player = (Player)sender;
if(sender instanceof Player player) {
if(sender.hasPermission("areashop.createrent") || sender.hasPermission("areashop.createbuy")) {
for(ProtectedRegion region : plugin.getRegionManager(player.getWorld()).getRegions().values()) {
result.add(region.getId());
@@ -1,135 +1,142 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class AddfriendCommand extends CommandAreaShop {
@Override
public String getCommandStart() {
return "areashop addfriend";
}
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Inject
private Plugin plugin;
@Override
public String getHelp(CommandSender target) {
if(target.hasPermission("areashop.addfriendall") || target.hasPermission("areashop.addfriend")) {
return "help-addFriend";
}
return null;
}
@Inject
private OfflinePlayerHelper offlinePlayerHelper;
@SuppressWarnings("deprecation")
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.addfriend") && !sender.hasPermission("areashop.addfriendall")) {
plugin.message(sender, "addfriend-noPermission");
return;
}
@Inject
private BukkitSchedulerExecutor executor;
if(args.length < 2) {
plugin.message(sender, "addfriend-help");
return;
}
@Override
public String getCommandStart() {
return "areashop addfriend";
}
GeneralRegion region;
if(args.length <= 2) {
if(sender instanceof Player) {
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
region = regions.get(0);
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
region = plugin.getFileManager().getRegion(args[2]);
if(region == null) {
plugin.message(sender, "cmd-notRegistered", args[2]);
return;
}
}
if(sender.hasPermission("areashop.addfriendall")) {
if((region instanceof RentRegion && !((RentRegion)region).isRented())
|| (region instanceof BuyRegion && !((BuyRegion)region).isSold())) {
plugin.message(sender, "addfriend-noOwner", region);
return;
}
OfflinePlayer friend = Bukkit.getOfflinePlayer(args[1]);
if(friend.getLastPlayed() == 0 && !friend.isOnline() && !plugin.getConfig().getBoolean("addFriendNotExistingPlayers")) {
plugin.message(sender, "addfriend-notVisited", args[1], region);
return;
}
if(region.getFriendsFeature().getFriends().contains(friend.getUniqueId())) {
plugin.message(sender, "addfriend-alreadyAdded", friend.getName(), region);
return;
}
if(region.isOwner(friend.getUniqueId())) {
plugin.message(sender, "addfriend-self", friend.getName(), region);
return;
}
if(region.getFriendsFeature().addFriend(friend.getUniqueId(), sender)) {
region.update();
plugin.message(sender, "addfriend-successOther", friend.getName(), region);
}
} else {
if(sender.hasPermission("areashop.addfriend") && sender instanceof Player) {
if(region.isOwner((Player)sender)) {
OfflinePlayer friend = Bukkit.getOfflinePlayer(args[1]);
if(friend.getLastPlayed() == 0 && !friend.isOnline() && !plugin.getConfig().getBoolean("addFriendNotExistingPlayers")) {
plugin.message(sender, "addfriend-notVisited", args[1], region);
return;
}
if(region.getFriendsFeature().getFriends().contains(friend.getUniqueId())) {
plugin.message(sender, "addfriend-alreadyAdded", friend.getName(), region);
return;
}
if(region.isOwner(friend.getUniqueId())) {
plugin.message(sender, "addfriend-self", friend.getName(), region);
return;
}
@Override
public String getHelp(CommandSender target) {
if (target.hasPermission("areashop.addfriendall") || target.hasPermission("areashop.addfriend")) {
return "help-addFriend";
}
return null;
}
if(region.getFriendsFeature().addFriend(friend.getUniqueId(), sender)) {
region.update();
plugin.message(sender, "addfriend-success", friend.getName(), region);
}
} else {
plugin.message(sender, "addfriend-noPermissionOther", region);
}
} else {
plugin.message(sender, "addfriend-noPermission", region);
}
}
}
@Override
public void execute(CommandSender sender, String[] args) {
if (!sender.hasPermission("areashop.addfriend") && !sender.hasPermission("areashop.addfriendall")) {
messageBridge.message(sender, "addfriend-noPermission");
return;
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
for(Player player : Utils.getOnlinePlayers()) {
result.add(player.getName());
}
} else if(toComplete == 3) {
result.addAll(plugin.getFileManager().getRegionNames());
}
return result;
}
if (args.length < 2) {
messageBridge.message(sender, "addfriend-help");
return;
}
GeneralRegion region;
if (args.length == 2) {
if (sender instanceof Player player) {
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(player.getLocation());
if (regions.isEmpty()) {
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if (regions.size() > 1) {
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
region = regions.get(0);
}
} else {
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
region = fileManager.getRegion(args[2]);
if (region == null) {
messageBridge.message(sender, "cmd-notRegistered", args[2]);
return;
}
}
if (sender.hasPermission("areashop.addfriendall")) {
if ((region instanceof RentRegion rentRegion && !rentRegion.isRented())
|| (region instanceof BuyRegion buyRegion && !buyRegion.isSold())) {
messageBridge.message(sender, "addfriend-noOwner", region);
return;
}
this.offlinePlayerHelper.lookupOfflinePlayerAsync(args[1]).thenAcceptAsync(friend -> {
if (friend.hasPlayedBefore() && !friend.isOnline() && !plugin.getConfig().getBoolean("addFriendNotExistingPlayers")) {
messageBridge.message(sender, "addfriend-notVisited", args[1], region);
} else if (region.getFriendsFeature().getFriends().contains(friend.getUniqueId())) {
messageBridge.message(sender, "addfriend-alreadyAdded", friend.getName(), region);
} else if (region.isOwner(friend.getUniqueId())) {
messageBridge.message(sender, "addfriend-self", friend.getName(), region);
} else if (region.getFriendsFeature().addFriend(friend.getUniqueId(), sender)) {
region.update();
messageBridge.message(sender, "addfriend-successOther", friend.getName(), region);
}
}, this.executor);
return;
}
if (!sender.hasPermission("areashop.addfriend") || !(sender instanceof Player player)) {
messageBridge.message(sender, "addfriend-noPermission", region);
return;
}
if (!region.isOwner(player)) {
messageBridge.message(sender, "addfriend-noPermissionOther", region);
return;
}
this.offlinePlayerHelper.lookupOfflinePlayerAsync(args[1]).thenAcceptAsync(friend -> {
if (friend.getLastPlayed() == 0 && !friend.isOnline() && !plugin.getConfig().getBoolean("addFriendNotExistingPlayers")) {
messageBridge.message(sender, "addfriend-notVisited", args[1], region);
} else if (region.getFriendsFeature().getFriends().contains(friend.getUniqueId())) {
messageBridge.message(sender, "addfriend-alreadyAdded", friend.getName(), region);
} else if (region.isOwner(friend.getUniqueId())) {
messageBridge.message(sender, "addfriend-self", friend.getName(), region);
} else if (region.getFriendsFeature().addFriend(friend.getUniqueId(), sender)) {
region.update();
messageBridge.message(sender, "addfriend-success", friend.getName(), region);
}
}, this.executor);
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if (toComplete == 2) {
for (Player player : Utils.getOnlinePlayers()) {
result.add(player.getName());
}
} else if (toComplete == 3) {
result.addAll(fileManager.getRegionNames());
}
return result;
}
}
@@ -1,22 +1,39 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.features.signs.RegionSign;
import me.wiefferink.areashop.features.signs.SignsFeature;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.SignUtils;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.material.Sign;
import org.bukkit.plugin.Plugin;
import org.bukkit.util.BlockIterator;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
@Singleton
public class AddsignCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Inject
private SignManager signManager;
@Inject
private Plugin plugin;
@Override
public String getCommandStart() {
return "areashop addsign";
@@ -33,14 +50,13 @@ public class AddsignCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.addsign")) {
plugin.message(sender, "addsign-noPermission");
messageBridge.message(sender, "addsign-noPermission");
return;
}
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-onlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-onlyByPlayer");
return;
}
Player player = (Player)sender;
// Get the sign
Block block = null;
@@ -51,52 +67,52 @@ public class AddsignCommand extends CommandAreaShop {
block = next;
}
}
if(block == null || !(block.getType() == Material.WALL_SIGN || block.getType() == Material.SIGN_POST)) {
plugin.message(sender, "addsign-noSign");
if(block == null || !Materials.isSign(block.getType())) {
messageBridge.message(sender, "addsign-noSign");
return;
}
GeneralRegion region;
if(args.length > 1) {
// Get region by argument
region = plugin.getFileManager().getRegion(args[1]);
region = fileManager.getRegion(args[1]);
if(region == null) {
plugin.message(sender, "cmd-notRegistered", args[1]);
messageBridge.message(sender, "cmd-notRegistered", args[1]);
return;
}
} else {
// Get region by sign position
List<GeneralRegion> regions = Utils.getImportantRegions(block.getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "addsign-noRegions");
messageBridge.message(sender, "addsign-noRegions");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "addsign-couldNotDetect", regions.get(0).getName(), regions.get(1).getName());
messageBridge.message(sender, "addsign-couldNotDetect", regions.get(0).getName(), regions.get(1).getName());
return;
}
region = regions.get(0);
}
Sign sign = (Sign)block.getState().getData();
String profile = null;
if(args.length > 2) {
profile = args[2];
Set<String> profiles = plugin.getConfig().getConfigurationSection("signProfiles").getKeys(false);
if(!profiles.contains(profile)) {
plugin.message(sender, "addsign-wrongProfile", Utils.createCommaSeparatedList(profiles), region);
messageBridge.message(sender, "addsign-wrongProfile", Utils.createCommaSeparatedList(profiles), region);
return;
}
}
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if(regionSign != null) {
plugin.message(sender, "addsign-alreadyRegistered", regionSign.getRegion());
Optional<RegionSign> optionalRegionSign = signManager.signFromLocation(block.getLocation());
if(optionalRegionSign.isPresent()) {
RegionSign regionSign = optionalRegionSign.get();
messageBridge.message(sender, "addsign-alreadyRegistered", regionSign.getRegion());
return;
}
region.getSignsFeature().addSign(block.getLocation(), block.getType(), sign.getFacing(), profile);
region.getSignsFeature().addSign(block.getLocation(), block.getType(), SignUtils.getSignFacing(block), profile);
if(profile == null) {
plugin.message(sender, "addsign-success", region);
messageBridge.message(sender, "addsign-success", region);
} else {
plugin.message(sender, "addsign-successProfile", profile, region);
messageBridge.message(sender, "addsign-successProfile", profile, region);
}
region.update();
}
@@ -105,7 +121,7 @@ public class AddsignCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
List<String> result = new ArrayList<>();
if(toComplete == 2) {
result.addAll(plugin.getFileManager().getRegionNames());
result.addAll(fileManager.getRegionNames());
} else if(toComplete == 3) {
result.addAll(plugin.getConfig().getStringList("signProfiles"));
}
@@ -1,15 +1,28 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class BuyCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private Plugin plugin;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop buy";
@@ -26,18 +39,17 @@ public class BuyCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.buy")) {
plugin.message(sender, "buy-noPermission");
messageBridge.message(sender, "buy-noPermission");
return;
}
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-onlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-onlyByPlayer");
return;
}
Player player = (Player)sender;
if(args.length > 1 && args[1] != null) {
BuyRegion region = plugin.getFileManager().getBuy(args[1]);
BuyRegion region = fileManager.getBuy(args[1]);
if(region == null) {
plugin.message(player, "buy-notBuyable", args[1]);
messageBridge.message(player, "buy-notBuyable", args[1]);
} else {
region.buy(player);
}
@@ -45,9 +57,9 @@ public class BuyCommand extends CommandAreaShop {
// get the region by location
List<BuyRegion> regions = Utils.getImportantBuyRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
} else {
regions.get(0).buy(player);
}
@@ -58,7 +70,7 @@ public class BuyCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
for(BuyRegion region : plugin.getFileManager().getBuys()) {
for(BuyRegion region : fileManager.getBuysRef()) {
if(!region.isSold()) {
result.add(region.getName());
}
@@ -1,6 +1,5 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.interactivemessenger.processing.Message;
import org.apache.commons.lang.StringUtils;
import org.bukkit.command.Command;
@@ -16,11 +15,9 @@ import java.util.Map;
*/
public abstract class CommandAreaShop {
final AreaShop plugin = AreaShop.getInstance();
private final Map<String, CommandTime> lastUsed;
public CommandAreaShop() {
protected CommandAreaShop() {
lastUsed = new HashMap<>();
}
@@ -89,9 +86,9 @@ public abstract class CommandAreaShop {
return false;
}
private class CommandTime {
public String command;
public long time;
private static class CommandTime {
public final String command;
public final long time;
CommandTime(String command, long time) {
this.command = command;
@@ -1,6 +1,10 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.events.ask.DeletingRegionEvent;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldEditSelection;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
@@ -8,12 +12,22 @@ import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
@Singleton
public class DelCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private WorldEditInterface worldEditInterface;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop del";
@@ -34,76 +48,91 @@ public class DelCommand extends CommandAreaShop {
&& !sender.hasPermission("areashop.destroyrent")
&& !sender.hasPermission("areashop.destroyrent.landlord")) {
plugin.message(sender, "del-noPermission");
messageBridge.message(sender, "del-noPermission");
return;
}
if(args.length < 2) {
// Only players can have a selection
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-weOnlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-weOnlyByPlayer");
return;
}
Player player = (Player)sender;
WorldEditSelection selection = plugin.getWorldEditHandler().getPlayerSelection(player);
WorldEditSelection selection = worldEditInterface.getPlayerSelection(player);
if(selection == null) {
plugin.message(player, "cmd-noSelection");
messageBridge.message(player, "cmd-noSelection");
return;
}
List<GeneralRegion> regions = Utils.getRegionsInSelection(selection);
if(regions == null || regions.size() == 0) {
plugin.message(player, "cmd-noRegionsFound");
if(regions == null || regions.isEmpty()) {
messageBridge.message(player, "cmd-noRegionsFound");
return;
}
// Start removing the regions that he has permission for
ArrayList<String> namesSuccess = new ArrayList<>();
TreeSet<GeneralRegion> namesFailed = new TreeSet<>();
TreeSet<GeneralRegion> regionsFailed = new TreeSet<>();
TreeSet<GeneralRegion> regionsCancelled = new TreeSet<>();
for(GeneralRegion region : regions) {
boolean isLandlord = region.isLandlord(((Player)sender).getUniqueId());
if(region instanceof RentRegion) {
if(!sender.hasPermission("areashop.destroyrent") && !(isLandlord && sender.hasPermission("areashop.destroyrent.landlord"))) {
namesFailed.add(region);
} else {
plugin.getFileManager().removeRent((RentRegion)region, true);
namesSuccess.add(region.getName());
regionsFailed.add(region);
continue;
}
} else if(region instanceof BuyRegion) {
if(!sender.hasPermission("areashop.destroybuy") && !(isLandlord && sender.hasPermission("areashop.destroybuy.landlord"))) {
namesFailed.add(region);
} else {
plugin.getFileManager().removeBuy((BuyRegion)region, true);
namesSuccess.add(region.getName());
regionsFailed.add(region);
continue;
}
}
DeletingRegionEvent event = fileManager.deleteRegion(region, true);
if (event.isCancelled()) {
regionsCancelled.add(region);
} else {
namesSuccess.add(region.getName());
}
}
// send messages
if(namesSuccess.size() != 0) {
plugin.message(sender, "del-success", Utils.createCommaSeparatedList(namesSuccess));
// Send messages
if(!namesSuccess.isEmpty()) {
messageBridge.message(sender, "del-success", Utils.createCommaSeparatedList(namesSuccess));
}
if(namesFailed.size() != 0) {
plugin.message(sender, "del-failed", Utils.combinedMessage(namesFailed, "region"));
if(!regionsFailed.isEmpty()) {
messageBridge.message(sender, "del-failed", Utils.combinedMessage(regionsFailed, "region"));
}
if(!regionsCancelled.isEmpty()) {
messageBridge.message(sender, "del-cancelled", Utils.combinedMessage(regionsCancelled, "region"));
}
} else {
GeneralRegion region = plugin.getFileManager().getRegion(args[1]);
GeneralRegion region = fileManager.getRegion(args[1]);
if(region == null) {
plugin.message(sender, "cmd-notRegistered", args[1]);
messageBridge.message(sender, "cmd-notRegistered", args[1]);
return;
}
boolean isLandlord = sender instanceof Player && region.isLandlord(((Player)sender).getUniqueId());
if(region instanceof RentRegion) {
// Remove the rent if the player has permission
if(sender.hasPermission("areashop.destroyrent") || (isLandlord && sender.hasPermission("areashop.destroyrent.landlord"))) {
plugin.getFileManager().removeRent((RentRegion)region, true);
plugin.message(sender, "destroy-successRent", region);
DeletingRegionEvent event = fileManager.deleteRegion(region, true);
if (event.isCancelled()) {
messageBridge.message(sender, "general-cancelled", event.getReason());
} else {
messageBridge.message(sender, "destroy-successRent", region);
}
} else {
plugin.message(sender, "destroy-noPermissionRent", region);
messageBridge.message(sender, "destroy-noPermissionRent", region);
}
} else if(region instanceof BuyRegion) {
// Remove the buy if the player has permission
if(sender.hasPermission("areashop.destroybuy") || (isLandlord && sender.hasPermission("areashop.destroybuy.landlord"))) {
plugin.getFileManager().removeBuy((BuyRegion)region, true);
plugin.message(sender, "destroy-successBuy", region);
DeletingRegionEvent event = fileManager.deleteRegion(region, true);
if (event.isCancelled()) {
messageBridge.message(sender, "general-cancelled", event.getReason());
} else {
messageBridge.message(sender, "destroy-successBuy", region);
}
} else {
plugin.message(sender, "destroy-noPermissionBuy", region);
messageBridge.message(sender, "destroy-noPermissionBuy", region);
}
}
}
@@ -113,7 +142,7 @@ public class DelCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
List<String> result = new ArrayList<>();
if(toComplete == 2) {
result = plugin.getFileManager().getRegionNames();
result = fileManager.getRegionNames();
}
return result;
}
@@ -1,120 +1,137 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Singleton
public class DelfriendCommand extends CommandAreaShop {
@Override
public String getCommandStart() {
return "areashop delfriend";
}
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getHelp(CommandSender target) {
if(target.hasPermission("areashop.delfriendall") || target.hasPermission("areashop.delfriend")) {
return "help-delFriend";
}
return null;
}
@Inject
private OfflinePlayerHelper offlinePlayerHelper;
/**
* Check if a person can remove friends.
* @param person The person to check
* @param region The region to check for
* @return true if the person can remove friends, otherwise false
*/
public static boolean canUse(CommandSender person, GeneralRegion region) {
if(person.hasPermission("areashop.delfriendall")) {
return true;
}
if(person instanceof Player) {
Player player = (Player)person;
return region.isOwner(player) && player.hasPermission("areashop.delfriend");
}
return false;
}
@Inject
private BukkitSchedulerExecutor executor;
@SuppressWarnings("deprecation")
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.delfriend") && !sender.hasPermission("areashop.delfriendall")) {
plugin.message(sender, "delfriend-noPermission");
return;
}
if(args.length < 2) {
plugin.message(sender, "delfriend-help");
return;
}
GeneralRegion region;
if(args.length <= 2) {
if(sender instanceof Player) {
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
region = regions.get(0);
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
region = plugin.getFileManager().getRegion(args[2]);
if(region == null) {
plugin.message(sender, "cmd-notRegistered", args[2]);
return;
}
}
if(sender.hasPermission("areashop.delfriendall")) {
if((region instanceof RentRegion && !((RentRegion)region).isRented())
|| (region instanceof BuyRegion && !((BuyRegion)region).isSold())) {
plugin.message(sender, "delfriend-noOwner", region);
return;
}
OfflinePlayer friend = Bukkit.getOfflinePlayer(args[1]);
if(!region.getFriendsFeature().getFriends().contains(friend.getUniqueId())) {
plugin.message(sender, "delfriend-notAdded", friend.getName(), region);
return;
}
if(region.getFriendsFeature().deleteFriend(friend.getUniqueId(), sender)) {
region.update();
plugin.message(sender, "delfriend-successOther", friend.getName(), region);
}
} else {
if(sender.hasPermission("areashop.delfriend") && sender instanceof Player) {
if(region.isOwner((Player)sender)) {
OfflinePlayer friend = Bukkit.getOfflinePlayer(args[1]);
if(!region.getFriendsFeature().getFriends().contains(friend.getUniqueId())) {
plugin.message(sender, "delfriend-notAdded", friend.getName(), region);
return;
}
if(region.getFriendsFeature().deleteFriend(friend.getUniqueId(), sender)) {
region.update();
plugin.message(sender, "delfriend-success", friend.getName(), region);
}
} else {
plugin.message(sender, "delfriend-noPermissionOther", region);
}
} else {
plugin.message(sender, "delfriend-noPermission", region);
}
}
}
@Override
public String getCommandStart() {
return "areashop delfriend";
}
@Override
public String getHelp(CommandSender target) {
if (target.hasPermission("areashop.delfriendall") || target.hasPermission("areashop.delfriend")) {
return "help-delFriend";
}
return null;
}
/**
* Check if a person can remove friends.
*
* @param person The person to check
* @param region The region to check for
* @return true if the person can remove friends, otherwise false
*/
public static boolean canUse(CommandSender person, GeneralRegion region) {
if (person.hasPermission("areashop.delfriendall")) {
return true;
}
if (person instanceof Player player) {
return region.isOwner(player) && player.hasPermission("areashop.delfriend");
}
return false;
}
@Override
public void execute(CommandSender sender, String[] args) {
if (!sender.hasPermission("areashop.delfriend") && !sender.hasPermission("areashop.delfriendall")) {
messageBridge.message(sender, "delfriend-noPermission");
return;
}
if (args.length < 2) {
messageBridge.message(sender, "delfriend-help");
return;
}
GeneralRegion region;
if (args.length == 2) {
if (!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(player.getLocation());
if (regions.isEmpty()) {
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if (regions.size() > 1) {
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
region = regions.get(0);
}
} else {
region = fileManager.getRegion(args[2]);
if (region == null) {
messageBridge.message(sender, "cmd-notRegistered", args[2]);
return;
}
}
if (sender.hasPermission("areashop.delfriendall")) {
if ((region instanceof RentRegion rentRegion && !rentRegion.isRented())
|| (region instanceof BuyRegion buyRegion && !buyRegion.isSold())) {
messageBridge.message(sender, "delfriend-noOwner", region);
return;
}
this.offlinePlayerHelper.lookupOfflinePlayerAsync(args[1]).thenAcceptAsync(friend -> {
if (!region.getFriendsFeature().getFriends().contains(friend.getUniqueId())) {
messageBridge.message(sender, "delfriend-notAdded", friend.getName(), region);
return;
}
if (region.getFriendsFeature().deleteFriend(friend.getUniqueId(), sender)) {
region.update();
messageBridge.message(sender, "delfriend-successOther", friend.getName(), region);
}
}, this.executor);
return;
}
if (!sender.hasPermission("areashop.delfriend") || !(sender instanceof Player player)) {
messageBridge.message(sender, "delfriend-noPermission", region);
return;
}
if (!region.isOwner(player)) {
messageBridge.message(sender, "delfriend-noPermissionOther", region);
return;
}
this.offlinePlayerHelper.lookupOfflinePlayerAsync(args[1]).thenAcceptAsync(friend -> {
if (!region.getFriendsFeature().getFriends().contains(friend.getUniqueId())) {
messageBridge.message(sender, "delfriend-notAdded", friend.getName(), region);
} else if (region.getFriendsFeature().deleteFriend(friend.getUniqueId(), sender)) {
region.update();
messageBridge.message(sender, "delfriend-success", friend.getName(), region);
}
}, this.executor);
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
@@ -124,7 +141,7 @@ public class DelfriendCommand extends CommandAreaShop {
result.add(player.getName());
}
} else if(toComplete == 3) {
result.addAll(plugin.getFileManager().getRegionNames());
result.addAll(fileManager.getRegionNames());
}
return result;
}
@@ -1,18 +1,30 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.features.signs.RegionSign;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.features.signs.SignsFeature;
import me.wiefferink.areashop.tools.Materials;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.util.BlockIterator;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
@Singleton
public class DelsignCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private SignManager signManager;
@Override
public String getCommandStart() {
return "areashop delsign";
@@ -29,35 +41,37 @@ public class DelsignCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.delsign")) {
plugin.message(sender, "delsign-noPermission");
messageBridge.message(sender, "delsign-noPermission");
return;
}
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-onlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-onlyByPlayer");
return;
}
Player player = (Player)sender;
// Get the sign
Block block = null;
BlockIterator blockIterator = new BlockIterator(player, 100);
while(blockIterator.hasNext() && block == null) {
Block next = blockIterator.next();
if(next.getType() != Material.AIR) {
if(!next.getType().isAir()) {
block = next;
}
}
if(block == null || !(block.getType() == Material.WALL_SIGN || block.getType() == Material.SIGN_POST)) {
plugin.message(sender, "delsign-noSign");
if(block == null || !Materials.isSign(block.getType())) {
messageBridge.message(sender, "delsign-noSign");
return;
}
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if(regionSign == null) {
plugin.message(sender, "delsign-noRegion");
Optional<RegionSign> optionalSign = signManager.removeSign(block.getLocation());
if(optionalSign.isEmpty()) {
messageBridge.message(sender, "delsign-noRegion");
return;
}
plugin.message(sender, "delsign-success", regionSign.getRegion());
RegionSign regionSign = optionalSign.get();
messageBridge.message(sender, "delsign-success", regionSign.getRegion());
regionSign.remove();
// Sometimes the RegionSign data is corrupted. Forcefully set the block to air
block.setType(Material.AIR);
}
@Override
@@ -1,19 +1,34 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.RegionGroup;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.interactivemessenger.processing.Message;
import net.milkbowl.vault.economy.Economy;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
@Singleton
public class FindCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private Economy economy;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop find";
@@ -30,21 +45,20 @@ public class FindCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.find")) {
plugin.message(sender, "find-noPermission");
messageBridge.message(sender, "find-noPermission");
return;
}
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-onlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-onlyByPlayer");
return;
}
if(args.length <= 1 || args[1] == null || (!args[1].equalsIgnoreCase("buy") && !args[1].equalsIgnoreCase("rent"))) {
plugin.message(sender, "find-help");
messageBridge.message(sender, "find-help");
return;
}
Player player = (Player)sender;
double balance = 0.0;
if(plugin.getEconomy() != null) {
balance = plugin.getEconomy().getBalance(player);
if(economy != null) {
balance = economy.getBalance(player);
}
double maxPrice = 0;
boolean maxPriceSet = false;
@@ -55,23 +69,23 @@ public class FindCommand extends CommandAreaShop {
maxPrice = Double.parseDouble(args[2]);
maxPriceSet = true;
} catch(NumberFormatException e) {
plugin.message(sender, "find-wrongMaxPrice", args[2]);
messageBridge.message(sender, "find-wrongMaxPrice", args[2]);
return;
}
}
// Parse optional group argument
if(args.length >= 4) {
group = plugin.getFileManager().getGroup(args[3]);
group = fileManager.getGroup(args[3]);
if(group == null) {
plugin.message(sender, "find-wrongGroup", args[3]);
messageBridge.message(sender, "find-wrongGroup", args[3]);
return;
}
}
// Find buy regions
if(args[1].equalsIgnoreCase("buy")) {
List<BuyRegion> regions = plugin.getFileManager().getBuys();
List<BuyRegion> results = new ArrayList<>();
Collection<BuyRegion> regions = fileManager.getBuysRef();
List<BuyRegion> results = new LinkedList<>();
for(BuyRegion region : regions) {
if(!region.isSold()
&& ((region.getPrice() <= balance && !maxPriceSet) || (region.getPrice() <= maxPrice && maxPriceSet))
@@ -90,9 +104,9 @@ public class FindCommand extends CommandAreaShop {
// Teleport
if(maxPriceSet) {
plugin.message(player, "find-successMax", "buy", Utils.formatCurrency(maxPrice), onlyInGroup, region);
messageBridge.message(player, "find-successMax", "buy", Utils.formatCurrency(maxPrice), onlyInGroup, region);
} else {
plugin.message(player, "find-success", "buy", Utils.formatCurrency(balance), onlyInGroup, region);
messageBridge.message(player, "find-success", "buy", Utils.formatCurrency(balance), onlyInGroup, region);
}
region.getTeleportFeature().teleportPlayer(player, region.getBooleanSetting("general.findTeleportToSign"), false);
} else {
@@ -101,17 +115,17 @@ public class FindCommand extends CommandAreaShop {
onlyInGroup = Message.fromKey("find-onlyInGroup").replacements(args[3]);
}
if(maxPriceSet) {
plugin.message(player, "find-noneFoundMax", "buy", Utils.formatCurrency(maxPrice), onlyInGroup);
messageBridge.message(player, "find-noneFoundMax", "buy", Utils.formatCurrency(maxPrice), onlyInGroup);
} else {
plugin.message(player, "find-noneFound", "buy", Utils.formatCurrency(balance), onlyInGroup);
messageBridge.message(player, "find-noneFound", "buy", Utils.formatCurrency(balance), onlyInGroup);
}
}
}
// Find rental regions
else {
List<RentRegion> regions = plugin.getFileManager().getRents();
List<RentRegion> results = new ArrayList<>();
Collection<RentRegion> regions = fileManager.getRentsRef();
List<RentRegion> results = new LinkedList<>();
for(RentRegion region : regions) {
if(!region.isRented()
&& ((region.getPrice() <= balance && !maxPriceSet) || (region.getPrice() <= maxPrice && maxPriceSet))
@@ -130,9 +144,9 @@ public class FindCommand extends CommandAreaShop {
// Teleport
if(maxPriceSet) {
plugin.message(player, "find-successMax", "rent", Utils.formatCurrency(maxPrice), onlyInGroup, region);
messageBridge.message(player, "find-successMax", "rent", Utils.formatCurrency(maxPrice), onlyInGroup, region);
} else {
plugin.message(player, "find-success", "rent", Utils.formatCurrency(balance), onlyInGroup, region);
messageBridge.message(player, "find-success", "rent", Utils.formatCurrency(balance), onlyInGroup, region);
}
region.getTeleportFeature().teleportPlayer(player, region.getBooleanSetting("general.findTeleportToSign"), false);
} else {
@@ -141,9 +155,9 @@ public class FindCommand extends CommandAreaShop {
onlyInGroup = Message.fromKey("find-onlyInGroup").replacements(args[3]);
}
if(maxPriceSet) {
plugin.message(player, "find-noneFoundMax", "rent", Utils.formatCurrency(maxPrice), onlyInGroup);
messageBridge.message(player, "find-noneFoundMax", "rent", Utils.formatCurrency(maxPrice), onlyInGroup);
} else {
plugin.message(player, "find-noneFound", "rent", Utils.formatCurrency(balance), onlyInGroup);
messageBridge.message(player, "find-noneFound", "rent", Utils.formatCurrency(balance), onlyInGroup);
}
}
}
@@ -1,18 +1,35 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldEditSelection;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionFactory;
import me.wiefferink.areashop.regions.RegionGroup;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
@Singleton
public class GroupaddCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Inject
private RegionFactory regionFactory;
@Inject
private WorldEditInterface worldEditInterface;
@Override
public String getCommandStart() {
return "areashop groupadd";
@@ -29,32 +46,31 @@ public class GroupaddCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.groupadd")) {
plugin.message(sender, "groupadd-noPermission");
messageBridge.message(sender, "groupadd-noPermission");
return;
}
if(args.length < 2 || args[1] == null) {
plugin.message(sender, "groupadd-help");
messageBridge.message(sender, "groupadd-help");
return;
}
RegionGroup group = plugin.getFileManager().getGroup(args[1]);
RegionGroup group = fileManager.getGroup(args[1]);
if(group == null) {
group = new RegionGroup(plugin, args[1]);
plugin.getFileManager().addGroup(group);
group = regionFactory.createRegionGroup(args[1]);
fileManager.addGroup(group);
}
if(args.length == 2) {
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-weOnlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-weOnlyByPlayer");
return;
}
Player player = (Player)sender;
WorldEditSelection selection = plugin.getWorldEditHandler().getPlayerSelection(player);
WorldEditSelection selection = worldEditInterface.getPlayerSelection(player);
if(selection == null) {
plugin.message(player, "cmd-noSelection");
messageBridge.message(player, "cmd-noSelection");
return;
}
List<GeneralRegion> regions = Utils.getRegionsInSelection(selection);
if(regions.size() == 0) {
plugin.message(player, "cmd-noRegionsFound");
if(regions.isEmpty()) {
messageBridge.message(player, "cmd-noRegionsFound");
return;
}
TreeSet<GeneralRegion> regionsSuccess = new TreeSet<>();
@@ -66,25 +82,25 @@ public class GroupaddCommand extends CommandAreaShop {
regionsFailed.add(region);
}
}
if(regionsSuccess.size() != 0) {
plugin.message(player, "groupadd-weSuccess", group.getName(), Utils.combinedMessage(regionsSuccess, "region"));
if(!regionsSuccess.isEmpty()) {
messageBridge.message(player, "groupadd-weSuccess", group.getName(), Utils.combinedMessage(regionsSuccess, "region"));
}
if(regionsFailed.size() != 0) {
plugin.message(player, "groupadd-weFailed", group.getName(), Utils.combinedMessage(regionsFailed, "region"));
if(!regionsFailed.isEmpty()) {
messageBridge.message(player, "groupadd-weFailed", group.getName(), Utils.combinedMessage(regionsFailed, "region"));
}
// Update all regions, this does it in a task, updating them without lag
plugin.getFileManager().updateRegions(new ArrayList<>(regionsSuccess), player);
fileManager.updateRegions(new ArrayList<>(regionsSuccess), player);
} else {
GeneralRegion region = plugin.getFileManager().getRegion(args[2]);
GeneralRegion region = fileManager.getRegion(args[2]);
if(region == null) {
plugin.message(sender, "cmd-notRegistered", args[2]);
messageBridge.message(sender, "cmd-notRegistered", args[2]);
return;
}
if(group.addMember(region)) {
region.update();
plugin.message(sender, "groupadd-success", group.getName(), group.getMembers().size(), region);
messageBridge.message(sender, "groupadd-success", group.getName(), group.getMembers().size(), region);
} else {
plugin.message(sender, "groupadd-failed", group.getName(), region);
messageBridge.message(sender, "groupadd-failed", group.getName(), region);
}
}
}
@@ -93,9 +109,9 @@ public class GroupaddCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
List<String> result = new ArrayList<>();
if(toComplete == 2) {
result = plugin.getFileManager().getGroupNames();
result = fileManager.getGroupNames();
} else if(toComplete == 3) {
result = plugin.getFileManager().getRegionNames();
result = fileManager.getRegionNames();
}
return result;
}
@@ -1,18 +1,34 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldEditSelection;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionFactory;
import me.wiefferink.areashop.regions.RegionGroup;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeSet;
@Singleton
public class GroupdelCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Inject
private RegionFactory regionFactory;
@Inject
private WorldEditInterface worldEditInterface;
@Override
public String getCommandStart() {
return "areashop groupdel";
@@ -29,33 +45,32 @@ public class GroupdelCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.groupdel")) {
plugin.message(sender, "groupdel-noPermission");
messageBridge.message(sender, "groupdel-noPermission");
return;
}
if(args.length < 2 || args[1] == null) {
plugin.message(sender, "groupdel-help");
messageBridge.message(sender, "groupdel-help");
return;
}
RegionGroup group = plugin.getFileManager().getGroup(args[1]);
RegionGroup group = fileManager.getGroup(args[1]);
if(group == null) {
plugin.message(sender, "groupdel-wrongGroup", args[1]);
messageBridge.message(sender, "groupdel-wrongGroup", args[1]);
return;
}
if(args.length == 2) {
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-weOnlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-weOnlyByPlayer");
return;
}
Player player = (Player)sender;
WorldEditSelection selection = plugin.getWorldEditHandler().getPlayerSelection(player);
WorldEditSelection selection = worldEditInterface.getPlayerSelection(player);
if(selection == null) {
plugin.message(player, "cmd-noSelection");
messageBridge.message(player, "cmd-noSelection");
return;
}
List<GeneralRegion> regions = Utils.getRegionsInSelection(selection);
if(regions.size() == 0) {
plugin.message(player, "cmd-noRegionsFound");
if(regions.isEmpty()) {
messageBridge.message(player, "cmd-noRegionsFound");
return;
}
TreeSet<GeneralRegion> regionsSuccess = new TreeSet<>();
@@ -67,26 +82,26 @@ public class GroupdelCommand extends CommandAreaShop {
regionsFailed.add(region);
}
}
if(regionsSuccess.size() != 0) {
plugin.message(player, "groupdel-weSuccess", group.getName(), Utils.combinedMessage(regionsSuccess, "region"));
if(!regionsSuccess.isEmpty()) {
messageBridge.message(player, "groupdel-weSuccess", group.getName(), Utils.combinedMessage(regionsSuccess, "region"));
}
if(regionsFailed.size() != 0) {
plugin.message(player, "groupdel-weFailed", group.getName(), Utils.combinedMessage(regionsFailed, "region"));
if(!regionsFailed.isEmpty()) {
messageBridge.message(player, "groupdel-weFailed", group.getName(), Utils.combinedMessage(regionsFailed, "region"));
}
// Update all regions, this does it in a task, updating them without lag
plugin.getFileManager().updateRegions(new ArrayList<>(regionsSuccess), player);
fileManager.updateRegions(regionsSuccess, player);
group.saveRequired();
} else {
GeneralRegion region = plugin.getFileManager().getRegion(args[2]);
GeneralRegion region = fileManager.getRegion(args[2]);
if(region == null) {
plugin.message(sender, "cmd-notRegistered", args[2]);
messageBridge.message(sender, "cmd-notRegistered", args[2]);
return;
}
if(group.removeMember(region)) {
region.update();
plugin.message(sender, "groupdel-success", group.getName(), group.getMembers().size(), region);
messageBridge.message(sender, "groupdel-success", group.getName(), group.getMembers().size(), region);
} else {
plugin.message(sender, "groupdel-failed", group.getName(), region);
messageBridge.message(sender, "groupdel-failed", group.getName(), region);
}
}
}
@@ -95,9 +110,9 @@ public class GroupdelCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
List<String> result = new ArrayList<>();
if(toComplete == 2) {
result = plugin.getFileManager().getGroupNames();
result = fileManager.getGroupNames();
} else if(toComplete == 3) {
result = plugin.getFileManager().getRegionNames();
result = fileManager.getRegionNames();
}
return result;
}
@@ -1,15 +1,25 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.RegionGroup;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@Singleton
public class GroupinfoCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop groupinfo";
@@ -27,23 +37,23 @@ public class GroupinfoCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.groupinfo")) {
plugin.message(sender, "groupinfo-noPermission");
messageBridge.message(sender, "groupinfo-noPermission");
return;
}
if(args.length < 2 || args[1] == null) {
plugin.message(sender, "groupinfo-help");
messageBridge.message(sender, "groupinfo-help");
return;
}
RegionGroup group = plugin.getFileManager().getGroup(args[1]);
RegionGroup group = fileManager.getGroup(args[1]);
if(group == null) {
plugin.message(sender, "groupinfo-noGroup", args[1]);
messageBridge.message(sender, "groupinfo-noGroup", args[1]);
return;
}
Set<String> members = group.getMembers();
if(members.size() == 0) {
plugin.message(sender, "groupinfo-noMembers", group.getName());
if(members.isEmpty()) {
messageBridge.message(sender, "groupinfo-noMembers", group.getName());
} else {
plugin.message(sender, "groupinfo-members", group.getName(), Utils.createCommaSeparatedList(members));
messageBridge.message(sender, "groupinfo-members", group.getName(), Utils.createCommaSeparatedList(members));
}
}
@@ -51,7 +61,7 @@ public class GroupinfoCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
List<String> result = new ArrayList<>();
if(toComplete == 2) {
result = plugin.getFileManager().getGroupNames();
result = fileManager.getGroupNames();
}
return result;
}
@@ -1,13 +1,23 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class GrouplistCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop grouplist";
@@ -24,14 +34,14 @@ public class GrouplistCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.grouplist")) {
plugin.message(sender, "grouplist-noPermission");
messageBridge.message(sender, "grouplist-noPermission");
return;
}
List<String> groups = plugin.getFileManager().getGroupNames();
if(groups.size() == 0) {
plugin.message(sender, "grouplist-noGroups");
List<String> groups = fileManager.getGroupNames();
if(groups.isEmpty()) {
messageBridge.message(sender, "grouplist-noGroups");
} else {
plugin.message(sender, "grouplist-success", Utils.createCommaSeparatedList(groups));
messageBridge.message(sender, "grouplist-success", Utils.createCommaSeparatedList(groups));
}
}
@@ -1,9 +1,20 @@
package me.wiefferink.areashop.commands;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import me.wiefferink.areashop.managers.CommandManager;
import org.bukkit.command.CommandSender;
import javax.annotation.Nonnull;
public class HelpCommand extends CommandAreaShop {
private final CommandManager commandManager;
public HelpCommand(@Nonnull CommandManager commandManager) {
this.commandManager = commandManager;
}
@Override
public String getCommandStart() {
return "areashop help";
@@ -19,6 +30,6 @@ public class HelpCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
plugin.getCommandManager().showHelp(sender);
commandManager.showHelp(sender);
}
}
@@ -1,11 +1,17 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.regions.ImportJob;
import me.wiefferink.areashop.regions.ImportJobFactory;
import me.wiefferink.interactivemessenger.processing.Message;
import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class ImportCommand extends CommandAreaShop {
/* RegionGroup priority usage:
@@ -13,6 +19,10 @@ public class ImportCommand extends CommandAreaShop {
1: Settings from /worlds/<world>/config.yml
2: Settings from /worlds/<world>/parent-regions.yml (if their priority is set it is added to this value)
*/
@Inject
private MessageBridge messageBridge;
@Inject
private ImportJobFactory importJobFactory;
@Override
public String getCommandStart() {
@@ -27,26 +37,26 @@ public class ImportCommand extends CommandAreaShop {
return null;
}
// TODO
// - Landlord?
// - Friends
// - Region flags?
// - Settings from the 'permissions' section in RegionForSale/config.yml?
// TODO:
// - Landlord?
// - Friends
// - Region flags?
// - Settings from the 'permissions' section in RegionForSale/config.yml?
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.import")) {
plugin.message(sender, "import-noPermission");
messageBridge.message(sender, "import-noPermission");
return;
}
if(args.length < 2) {
plugin.message(sender, "import-help");
messageBridge.message(sender, "import-help");
return;
}
if(!"RegionForSale".equalsIgnoreCase(args[1])) {
plugin.message(sender, "import-wrongSource");
messageBridge.message(sender, "import-wrongSource");
return;
}
@@ -54,7 +64,7 @@ public class ImportCommand extends CommandAreaShop {
return;
}
ImportJob importJob = new ImportJob(sender);
importJobFactory.createImportJob(sender).execute();
}
@Override
@@ -1,15 +1,19 @@
package me.wiefferink.areashop.commands;
import io.github.bakedlibs.dough.blocks.BlockPosition;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionGroup;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.interactivemessenger.processing.Message;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
@@ -18,8 +22,14 @@ import java.util.Set;
// TODO fix '/as info' help message hitting replacement limit (improve depth tracking?)
// TODO add info about autoExtend
@Singleton
public class InfoCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop info";
@@ -50,7 +60,7 @@ public class InfoCommand extends CommandAreaShop {
try {
page = Integer.parseInt(pageInput);
} catch(NumberFormatException e) {
plugin.message(sender, "info-wrongPage", pageInput);
messageBridge.message(sender, "info-wrongPage", pageInput);
return;
}
}
@@ -58,7 +68,7 @@ public class InfoCommand extends CommandAreaShop {
regions.removeIf(generalRegion -> !filterGroup.isMember(generalRegion));
}
if(regions.isEmpty()) {
plugin.message(sender, "info-noRegions");
messageBridge.message(sender, "info-noRegions");
} else {
// First sort by type, then by name
regions.sort((one, two) -> {
@@ -74,7 +84,7 @@ public class InfoCommand extends CommandAreaShop {
if(filterGroup != null) {
limitedToGroup = Message.fromKey("info-limitedToGroup").replacements(filterGroup.getName());
}
plugin.message(sender, keyHeader, limitedToGroup);
messageBridge.message(sender, keyHeader, limitedToGroup);
// Page entries
int totalPages = (int)Math.ceil(regions.size() / (double)itemsPerPage); // Clip page to correct boundaries, not much need to tell the user
if(regions.size() == itemsPerPage + 1) { // 19 total items is mapped to 1 page of 19
@@ -101,7 +111,7 @@ public class InfoCommand extends CommandAreaShop {
state = "Reselling";
}
}
plugin.messageNoPrefix(sender, "info-entry" + state, region);
messageBridge.messageNoPrefix(sender, "info-entry" + state, region);
linesPrinted++;
}
Message footer = Message.empty();
@@ -113,9 +123,9 @@ public class InfoCommand extends CommandAreaShop {
}
// Page status
if(totalPages > 1) {
String pageString = "" + page;
StringBuilder pageString = new StringBuilder("" + page);
for(int i = pageString.length(); i < (totalPages + "").length(); i++) {
pageString = "0" + pageString;
pageString.insert(0, "0");
}
footer.append(Message.fromKey("info-pageStatus").replacements(page, totalPages));
if(page < totalPages) {
@@ -158,7 +168,7 @@ public class InfoCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.info")) {
plugin.message(sender, "info-noPermission");
messageBridge.message(sender, "info-noPermission");
return;
}
if(args.length > 1 && args[1] != null) {
@@ -167,9 +177,9 @@ public class InfoCommand extends CommandAreaShop {
Set<String> groupFilters = new HashSet<>(Arrays.asList("all", "rented", "forrent", "sold", "forsale", "reselling"));
if(groupFilters.contains(args[1].toLowerCase()) && args.length > 2) {
if(!Utils.isNumeric(args[2])) {
filterGroup = plugin.getFileManager().getGroup(args[2]);
filterGroup = fileManager.getGroup(args[2]);
if(filterGroup == null) {
plugin.message(sender, "info-noFiltergroup", args[2]);
messageBridge.message(sender, "info-noFiltergroup", args[2]);
return;
}
// Pass page number to args[2] if available
@@ -181,48 +191,48 @@ public class InfoCommand extends CommandAreaShop {
// All regions
if(args[1].equalsIgnoreCase("all")) {
showSortedPagedList(sender, plugin.getFileManager().getRegions(), filterGroup, "info-allHeader", (args.length > 2 ? args[2] : null), "info all");
showSortedPagedList(sender, new ArrayList<>(fileManager.getRegionsRef()), filterGroup, "info-allHeader", (args.length > 2 ? args[2] : null), "info all");
}
// Rented regions
else if(args[1].equalsIgnoreCase("rented")) {
List<RentRegion> regions = plugin.getFileManager().getRents();
List<RentRegion> regions = new ArrayList<>(fileManager.getRentsRef());
regions.removeIf(RentRegion::isAvailable);
showSortedPagedList(sender, regions, filterGroup, "info-rentedHeader", (args.length > 2 ? args[2] : null), "info rented");
}
// Forrent regions
else if(args[1].equalsIgnoreCase("forrent")) {
List<RentRegion> regions = plugin.getFileManager().getRents();
List<RentRegion> regions = new ArrayList<>(fileManager.getRentsRef());
regions.removeIf(RentRegion::isRented);
showSortedPagedList(sender, regions, filterGroup, "info-forrentHeader", (args.length > 2 ? args[2] : null), "info forrent");
}
// Sold regions
else if(args[1].equalsIgnoreCase("sold")) {
List<BuyRegion> regions = plugin.getFileManager().getBuys();
List<BuyRegion> regions = new ArrayList<>(fileManager.getBuysRef());
regions.removeIf(BuyRegion::isAvailable);
showSortedPagedList(sender, regions, filterGroup, "info-soldHeader", (args.length > 2 ? args[2] : null), "info sold");
}
// Forsale regions
else if(args[1].equalsIgnoreCase("forsale")) {
List<BuyRegion> regions = plugin.getFileManager().getBuys();
List<BuyRegion> regions = new ArrayList<>(fileManager.getBuysRef());
regions.removeIf(BuyRegion::isSold);
showSortedPagedList(sender, regions, filterGroup, "info-forsaleHeader", (args.length > 2 ? args[2] : null), "info forsale");
}
// Reselling regions
else if(args[1].equalsIgnoreCase("reselling")) {
List<BuyRegion> regions = plugin.getFileManager().getBuys();
List<BuyRegion> regions = new ArrayList<>(fileManager.getBuysRef());
regions.removeIf(region -> !region.isInResellingMode());
showSortedPagedList(sender, regions, filterGroup, "info-resellingHeader", (args.length > 2 ? args[2] : null), "info reselling");
}
// List of regions without a group
else if(args[1].equalsIgnoreCase("nogroup")) {
List<GeneralRegion> regions = plugin.getFileManager().getRegions();
for(RegionGroup group : plugin.getFileManager().getGroups()) {
List<GeneralRegion> regions = new ArrayList<>(fileManager.getRegionsRef());
for(RegionGroup group : fileManager.getGroups()) {
regions.removeAll(group.getMemberRegions());
}
if(regions.isEmpty()) {
plugin.message(sender, "info-nogroupNone");
messageBridge.message(sender, "info-nogroupNone");
} else {
showSortedPagedList(sender, regions, filterGroup, "info-nogroupHeader", (args.length > 2 ? args[2] : null), "info nogroup");
}
@@ -234,17 +244,17 @@ public class InfoCommand extends CommandAreaShop {
RentRegion rent = null;
BuyRegion buy = null;
if(args.length > 2) {
rent = plugin.getFileManager().getRent(args[2]);
buy = plugin.getFileManager().getBuy(args[2]);
rent = fileManager.getRent(args[2]);
buy = fileManager.getBuy(args[2]);
} else {
if(sender instanceof Player) {
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
if(regions.get(0) instanceof RentRegion) {
@@ -254,26 +264,26 @@ public class InfoCommand extends CommandAreaShop {
}
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
}
if(rent == null && buy == null) {
plugin.message(sender, "info-regionNotExisting", args[2]);
messageBridge.message(sender, "info-regionNotExisting", args[2]);
return;
}
if(rent != null) {
plugin.message(sender, "info-regionHeaderRent", rent);
messageBridge.message(sender, "info-regionHeaderRent", rent);
if(rent.isRented()) {
plugin.messageNoPrefix(sender, "info-regionRented", rent);
plugin.messageNoPrefix(sender, "info-regionExtending", rent);
messageBridge.messageNoPrefix(sender, "info-regionRented", rent);
messageBridge.messageNoPrefix(sender, "info-regionExtending", rent);
// Money back
if(UnrentCommand.canUse(sender, rent)) {
plugin.messageNoPrefix(sender, "info-regionMoneyBackRentClick", rent);
messageBridge.messageNoPrefix(sender, "info-regionMoneyBackRentClick", rent);
} else {
plugin.messageNoPrefix(sender, "info-regionMoneyBackRent", rent);
messageBridge.messageNoPrefix(sender, "info-regionMoneyBackRent", rent);
}
// Friends
if(!rent.getFriendsFeature().getFriendNames().isEmpty()) {
@@ -281,30 +291,30 @@ public class InfoCommand extends CommandAreaShop {
if(DelfriendCommand.canUse(sender, rent)) {
messagePart = "info-friendRemove";
}
plugin.messageNoPrefix(sender, "info-regionFriends", rent, Utils.combinedMessage(rent.getFriendsFeature().getFriendNames(), messagePart));
messageBridge.messageNoPrefix(sender, "info-regionFriends", rent, Utils.combinedMessage(rent.getFriendsFeature().getFriendNames(), messagePart));
}
} else {
plugin.messageNoPrefix(sender, "info-regionCanBeRented", rent);
messageBridge.messageNoPrefix(sender, "info-regionCanBeRented", rent);
}
if(rent.getLandlordName() != null) {
plugin.messageNoPrefix(sender, "info-regionLandlord", rent);
messageBridge.messageNoPrefix(sender, "info-regionLandlord", rent);
}
// Maximum extends
if(rent.getMaxExtends() != -1) {
if(rent.getMaxExtends() == 0) {
plugin.messageNoPrefix(sender, "info-regionNoExtending", rent);
messageBridge.messageNoPrefix(sender, "info-regionNoExtending", rent);
} else if(rent.isRented()) {
plugin.messageNoPrefix(sender, "info-regionExtendsLeft", rent);
messageBridge.messageNoPrefix(sender, "info-regionExtendsLeft", rent);
} else {
plugin.messageNoPrefix(sender, "info-regionMaxExtends", rent);
messageBridge.messageNoPrefix(sender, "info-regionMaxExtends", rent);
}
}
// If maxExtends is zero it does not make sense to show this message
if(rent.getMaxRentTime() != -1 && rent.getMaxExtends() != 0) {
plugin.messageNoPrefix(sender, "info-regionMaxRentTime", rent);
messageBridge.messageNoPrefix(sender, "info-regionMaxRentTime", rent);
}
if(rent.getInactiveTimeUntilUnrent() != -1) {
plugin.messageNoPrefix(sender, "info-regionInactiveUnrent", rent);
messageBridge.messageNoPrefix(sender, "info-regionInactiveUnrent", rent);
}
// Teleport
Message tp = Message.fromKey("info-prefix");
@@ -326,44 +336,44 @@ public class InfoCommand extends CommandAreaShop {
}
// Signs
List<String> signLocations = new ArrayList<>();
for(Location location : rent.getSignsFeature().getSignLocations()) {
signLocations.add(Message.fromKey("info-regionSignLocation").replacements(location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()).getPlain());
for(BlockPosition location : rent.getSignsFeature().signManager().allSignLocations()) {
signLocations.add(Message.fromKey("info-regionSignLocation").replacements(location.getWorld().getName(), location.getX(), location.getY(), location.getZ()).getPlain());
}
if(!signLocations.isEmpty()) {
plugin.messageNoPrefix(sender, "info-regionSigns", Utils.createCommaSeparatedList(signLocations));
messageBridge.messageNoPrefix(sender, "info-regionSigns", Utils.createCommaSeparatedList(signLocations));
}
// Groups
if(sender.hasPermission("areashop.groupinfo") && !rent.getGroupNames().isEmpty()) {
plugin.messageNoPrefix(sender, "info-regionGroups", Utils.createCommaSeparatedList(rent.getGroupNames()));
messageBridge.messageNoPrefix(sender, "info-regionGroups", Utils.createCommaSeparatedList(rent.getGroupNames()));
}
// Restoring
if(rent.isRestoreEnabled()) {
plugin.messageNoPrefix(sender, "info-regionRestoringRent", rent);
messageBridge.messageNoPrefix(sender, "info-regionRestoringRent", rent);
}
// Restrictions
if(!rent.isRented()) {
if(rent.restrictedToRegion()) {
plugin.messageNoPrefix(sender, "info-regionRestrictedRegionRent", rent);
messageBridge.messageNoPrefix(sender, "info-regionRestrictedRegionRent", rent);
} else if(rent.restrictedToWorld()) {
plugin.messageNoPrefix(sender, "info-regionRestrictedWorldRent", rent);
messageBridge.messageNoPrefix(sender, "info-regionRestrictedWorldRent", rent);
}
}
plugin.messageNoPrefix(sender, "info-regionFooterRent", rent);
messageBridge.messageNoPrefix(sender, "info-regionFooterRent", rent);
} else if(buy != null) {
plugin.message(sender, "info-regionHeaderBuy", buy);
messageBridge.message(sender, "info-regionHeaderBuy", buy);
if(buy.isSold()) {
if(buy.isInResellingMode()) {
plugin.messageNoPrefix(sender, "info-regionReselling", buy);
plugin.messageNoPrefix(sender, "info-regionReselPrice", buy);
messageBridge.messageNoPrefix(sender, "info-regionReselling", buy);
messageBridge.messageNoPrefix(sender, "info-regionReselPrice", buy);
} else {
plugin.messageNoPrefix(sender, "info-regionBought", buy);
messageBridge.messageNoPrefix(sender, "info-regionBought", buy);
}
// Money back
if(!buy.getBooleanSetting("buy.sellDisabled")) {
if (SellCommand.canUse(sender, buy)) {
plugin.messageNoPrefix(sender, "info-regionMoneyBackBuyClick", buy);
messageBridge.messageNoPrefix(sender, "info-regionMoneyBackBuyClick", buy);
} else {
plugin.messageNoPrefix(sender, "info-regionMoneyBackBuy", buy);
messageBridge.messageNoPrefix(sender, "info-regionMoneyBackBuy", buy);
}
}
// Friends
@@ -372,16 +382,16 @@ public class InfoCommand extends CommandAreaShop {
if(DelfriendCommand.canUse(sender, buy)) {
messagePart = "info-friendRemove";
}
plugin.messageNoPrefix(sender, "info-regionFriends", buy, Utils.combinedMessage(buy.getFriendsFeature().getFriendNames(), messagePart));
messageBridge.messageNoPrefix(sender, "info-regionFriends", buy, Utils.combinedMessage(buy.getFriendsFeature().getFriendNames(), messagePart));
}
} else {
plugin.messageNoPrefix(sender, "info-regionCanBeBought", buy);
messageBridge.messageNoPrefix(sender, "info-regionCanBeBought", buy);
}
if(buy.getLandlord() != null) {
plugin.messageNoPrefix(sender, "info-regionLandlord", buy);
messageBridge.messageNoPrefix(sender, "info-regionLandlord", buy);
}
if(buy.getInactiveTimeUntilSell() != -1) {
plugin.messageNoPrefix(sender, "info-regionInactiveSell", buy);
messageBridge.messageNoPrefix(sender, "info-regionInactiveSell", buy);
}
// Teleport
Message tp = Message.fromKey("info-prefix");
@@ -403,38 +413,38 @@ public class InfoCommand extends CommandAreaShop {
}
// Signs
List<String> signLocations = new ArrayList<>();
for(Location location : buy.getSignsFeature().getSignLocations()) {
signLocations.add(Message.fromKey("info-regionSignLocation").replacements(location.getWorld().getName(), location.getBlockX(), location.getBlockY(), location.getBlockZ()).getPlain());
for(BlockPosition location : buy.getSignsFeature().signManager().allSignLocations()) {
signLocations.add(Message.fromKey("info-regionSignLocation").replacements(location.getWorld().getName(), location.getX(), location.getY(), location.getZ()).getPlain());
}
if(!signLocations.isEmpty()) {
plugin.messageNoPrefix(sender, "info-regionSigns", Utils.createCommaSeparatedList(signLocations));
messageBridge.messageNoPrefix(sender, "info-regionSigns", Utils.createCommaSeparatedList(signLocations));
}
// Groups
if(sender.hasPermission("areashop.groupinfo") && !buy.getGroupNames().isEmpty()) {
plugin.messageNoPrefix(sender, "info-regionGroups", Utils.createCommaSeparatedList(buy.getGroupNames()));
messageBridge.messageNoPrefix(sender, "info-regionGroups", Utils.createCommaSeparatedList(buy.getGroupNames()));
}
// Restoring
if(buy.isRestoreEnabled()) {
plugin.messageNoPrefix(sender, "info-regionRestoringBuy", buy);
messageBridge.messageNoPrefix(sender, "info-regionRestoringBuy", buy);
}
// Restrictions
if(!buy.isSold()) {
if(buy.restrictedToRegion()) {
plugin.messageNoPrefix(sender, "info-regionRestrictedRegionBuy", buy);
messageBridge.messageNoPrefix(sender, "info-regionRestrictedRegionBuy", buy);
} else if(buy.restrictedToWorld()) {
plugin.messageNoPrefix(sender, "info-regionRestrictedWorldBuy", buy);
messageBridge.messageNoPrefix(sender, "info-regionRestrictedWorldBuy", buy);
}
}
plugin.messageNoPrefix(sender, "info-regionFooterBuy", buy);
messageBridge.messageNoPrefix(sender, "info-regionFooterBuy", buy);
}
} else {
plugin.message(sender, "info-regionHelp");
messageBridge.message(sender, "info-regionHelp");
}
} else {
plugin.message(sender, "info-help");
messageBridge.message(sender, "info-help");
}
} else {
plugin.message(sender, "info-help");
messageBridge.message(sender, "info-help");
}
}
@@ -449,8 +459,8 @@ public class InfoCommand extends CommandAreaShop {
result.add(player.getName());
}
} else if(start[2].equalsIgnoreCase("region")) {
result.addAll(plugin.getFileManager().getBuyNames());
result.addAll(plugin.getFileManager().getRentNames());
result.addAll(fileManager.getBuyNames());
result.addAll(fileManager.getRentNames());
}
}
return result;
@@ -1,5 +1,10 @@
package me.wiefferink.areashop.commands;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.SignLinkerManager;
import me.wiefferink.interactivemessenger.processing.Message;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
@@ -9,8 +14,16 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@Singleton
public class LinksignsCommand extends CommandAreaShop {
@Inject
private SignLinkerManager signLinkerManager;
@Inject
private AreaShop plugin;
@Inject
private MessageBridge messageBridge;
@Override
public String getCommandStart() {
return "areashop linksigns";
@@ -27,17 +40,16 @@ public class LinksignsCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.linksigns")) {
plugin.message(sender, "linksigns-noPermission");
messageBridge.message(sender, "linksigns-noPermission");
return;
}
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-onlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-onlyByPlayer");
return;
}
Player player = (Player)sender;
if(plugin.getSignlinkerManager().isInSignLinkMode(player)) {
plugin.getSignlinkerManager().exitSignLinkMode(player);
if(signLinkerManager.isInSignLinkMode(player)) {
signLinkerManager.exitSignLinkMode(player);
} else {
// Get the profile
String profile = null;
@@ -54,12 +66,12 @@ public class LinksignsCommand extends CommandAreaShop {
}
message.addAll(Message.fromKey("addsign-profile").replacements(p).get());
}
plugin.message(sender, "addsign-wrongProfile", Message.fromList(message));
messageBridge.message(sender, "addsign-wrongProfile", Message.fromList(message));
return;
}
}
}
plugin.getSignlinkerManager().enterSignLinkMode(player, profile);
signLinkerManager.enterSignLinkMode(player, profile);
}
}
@@ -1,21 +1,39 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
@Singleton
public class MeCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Inject
private OfflinePlayerHelper offlinePlayerHelper;
@Inject
private BukkitSchedulerExecutor executor;
@Override
public String getCommandStart() {
return "areashop me";
@@ -32,76 +50,77 @@ public class MeCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.me")) {
plugin.message(sender, "me-noPermission");
messageBridge.message(sender, "me-noPermission");
return;
}
OfflinePlayer player = null;
if(!(sender instanceof Player)) {
if(args.length <= 1) {
plugin.message(sender, "me-notAPlayer");
messageBridge.message(sender, "me-notAPlayer");
return;
}
} else {
player = (OfflinePlayer)sender;
}
if(args.length > 1) {
player = Bukkit.getOfflinePlayer(args[1]);
if(player == null) {
plugin.message(sender, "me-noPlayer", args[1]);
return;
}
}
if(player == null) {
// Lookup offline players async
this.offlinePlayerHelper.lookupOfflinePlayerAsync(args[1]).thenAcceptAsync(offlinePlayer -> {
if (!offlinePlayer.hasPlayedBefore()) {
messageBridge.message(sender, "me-noPlayer", args[1]);
} else {
sendMessageAboutRegions(sender, offlinePlayer);
}
}, this.executor);
return;
}
sendMessageAboutRegions(sender, player);
}
private void sendMessageAboutRegions(CommandSender sender, OfflinePlayer target) {
// Get the regions owned by the player
Set<RentRegion> rentRegions = new HashSet<>();
for(RentRegion region : plugin.getFileManager().getRents()) {
if(region.isOwner(player)) {
for(RentRegion region : fileManager.getRentsRef()) {
if(region.isOwner(target)) {
rentRegions.add(region);
}
}
Set<BuyRegion> buyRegions = new HashSet<>();
for(BuyRegion region : plugin.getFileManager().getBuys()) {
if(region.isOwner(player)) {
for(BuyRegion region : fileManager.getBuysRef()) {
if(region.isOwner(target)) {
buyRegions.add(region);
}
}
// Get the regions the player is added as friend
Set<GeneralRegion> friendRegions = new HashSet<>();
for(GeneralRegion region : plugin.getFileManager().getRegions()) {
if(region.getFriendsFeature().getFriends().contains(player.getUniqueId())) {
for(GeneralRegion region : fileManager.getRegionsRef()) {
if(region.getFriendsFeature().getFriends().contains(target.getUniqueId())) {
friendRegions.add(region);
}
}
// Send messages
boolean foundSome = !rentRegions.isEmpty() || !buyRegions.isEmpty() || !friendRegions.isEmpty();
if(foundSome) {
plugin.message(sender, "me-header", player.getName());
if(!foundSome) {
messageBridge.message(sender, "me-nothing", target.getName());
return;
}
messageBridge.message(sender, "me-header", target.getName());
if(!rentRegions.isEmpty()) {
for(RentRegion region : rentRegions) {
plugin.messageNoPrefix(sender, "me-rentLine", region);
messageBridge.messageNoPrefix(sender, "me-rentLine", region);
}
}
if(!buyRegions.isEmpty()) {
for(BuyRegion region : buyRegions) {
plugin.messageNoPrefix(sender, "me-buyLine", region);
messageBridge.messageNoPrefix(sender, "me-buyLine", region);
}
}
if(!friendRegions.isEmpty()) {
for(GeneralRegion region : friendRegions) {
plugin.messageNoPrefix(sender, "me-friendLine", region);
messageBridge.messageNoPrefix(sender, "me-friendLine", region);
}
}
if(!foundSome) {
plugin.message(sender, "me-nothing", player.getName());
} else {
plugin.messageNoPrefix(sender, "me-clickHint");
}
messageBridge.messageNoPrefix(sender, "me-clickHint");
}
@Override
@@ -1,5 +1,6 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.interactivemessenger.processing.Message;
import org.apache.commons.lang.StringUtils;
@@ -7,11 +8,17 @@ import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class MessageCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Override
public String getCommandStart() {
return "areashop message";
@@ -19,27 +26,25 @@ public class MessageCommand extends CommandAreaShop {
@Override
public String getHelp(CommandSender target) {
if(target.hasPermission("areashop.message")) {
return null; // Internal command, no need to show in the help list
}
// Internal command, no need to show in the help list
return null;
}
@Override
public void execute(final CommandSender sender, final String[] args) {
if(!sender.hasPermission("areashop.message")) {
plugin.message(sender, "message-noPermission");
messageBridge.message(sender, "message-noPermission");
return;
}
if(args.length < 3) {
plugin.message(sender, "message-help");
messageBridge.message(sender, "message-help");
return;
}
Player player = Bukkit.getPlayer(args[1]);
if(player == null) {
plugin.message(sender, "message-notOnline", args[1]);
messageBridge.message(sender, "message-notOnline", args[1]);
return;
}
@@ -1,9 +1,20 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class ReloadCommand extends CommandAreaShop {
@Inject
private AreaShop plugin;
@Inject
private MessageBridge messageBridge;
@Override
public String getCommandStart() {
return "areashop reload";
@@ -23,7 +34,7 @@ public class ReloadCommand extends CommandAreaShop {
// Reload the configuration files and update all region flags/signs
plugin.reload(sender);
} else {
plugin.message(sender, "reload-noPermission");
messageBridge.message(sender, "reload-noPermission");
}
}
}
@@ -1,15 +1,25 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class RentCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop rent";
@@ -26,18 +36,17 @@ public class RentCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.rent")) {
plugin.message(sender, "rent-noPermission");
messageBridge.message(sender, "rent-noPermission");
return;
}
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-onlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-onlyByPlayer");
return;
}
Player player = (Player)sender;
if(args.length > 1 && args[1] != null) {
RentRegion rent = plugin.getFileManager().getRent(args[1]);
RentRegion rent = fileManager.getRent(args[1]);
if(rent == null) {
plugin.message(sender, "rent-notRentable", args[1]);
messageBridge.message(sender, "rent-notRentable", args[1]);
} else {
rent.rent(player);
}
@@ -45,9 +54,9 @@ public class RentCommand extends CommandAreaShop {
// get the region by location
List<RentRegion> regions = Utils.getImportantRentRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
} else {
regions.get(0).rent(player);
}
@@ -58,7 +67,7 @@ public class RentCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
for(RentRegion region : plugin.getFileManager().getRents()) {
for(RentRegion region : fileManager.getRentsRef()) {
if(!region.isRented()) {
result.add(region.getName());
}
@@ -1,15 +1,25 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class ResellCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop resell";
@@ -26,24 +36,24 @@ public class ResellCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.resell") && !sender.hasPermission("areashop.resellall")) {
plugin.message(sender, "resell-noPermissionOther");
messageBridge.message(sender, "resell-noPermissionOther");
return;
}
if(args.length <= 1) {
plugin.message(sender, "resell-help");
messageBridge.message(sender, "resell-help");
return;
}
double price;
try {
price = Double.parseDouble(args[1]);
} catch(NumberFormatException e) {
plugin.message(sender, "resell-wrongPrice", args[1]);
messageBridge.message(sender, "resell-wrongPrice", args[1]);
return;
}
if(price < 0) {
plugin.message(sender, "resell-wrongPrice", args[1]);
messageBridge.message(sender, "resell-wrongPrice", args[1]);
return;
}
@@ -53,53 +63,53 @@ public class ResellCommand extends CommandAreaShop {
// get the region by location
List<BuyRegion> regions = Utils.getImportantBuyRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
buy = regions.get(0);
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
buy = plugin.getFileManager().getBuy(args[2]);
buy = fileManager.getBuy(args[2]);
if(buy == null) {
plugin.message(sender, "resell-notRegistered", args[2]);
messageBridge.message(sender, "resell-notRegistered", args[2]);
return;
}
}
if(buy == null) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
}
if(!buy.isSold()) {
plugin.message(sender, "resell-notBought", buy);
messageBridge.message(sender, "resell-notBought", buy);
return;
}
if(sender.hasPermission("areashop.resellall")) {
buy.enableReselling(price);
buy.update();
plugin.message(sender, "resell-success", buy);
messageBridge.message(sender, "resell-success", buy);
} else if(sender.hasPermission("areashop.resell") && sender instanceof Player) {
if(!buy.isOwner((Player)sender)) {
plugin.message(sender, "resell-noPermissionOther", buy);
messageBridge.message(sender, "resell-noPermissionOther", buy);
return;
}
if(buy.getBooleanSetting("buy.resellDisabled")) {
plugin.message(sender, "resell-disabled", buy);
messageBridge.message(sender, "resell-disabled", buy);
return;
}
buy.enableReselling(price);
buy.update();
plugin.message(sender, "resell-success", buy);
messageBridge.message(sender, "resell-success", buy);
} else {
plugin.message(sender, "resell-noPermission", buy);
messageBridge.message(sender, "resell-noPermission", buy);
}
}
@@ -107,7 +117,7 @@ public class ResellCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 3) {
for(BuyRegion region : plugin.getFileManager().getBuys()) {
for(BuyRegion region : fileManager.getBuysRef()) {
if(region.isSold() && !region.isInResellingMode()) {
result.add(region.getName());
}
@@ -1,17 +1,27 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@Singleton
public class SchematiceventCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop schemevent";
@@ -28,21 +38,21 @@ public class SchematiceventCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.schematicevents")) {
plugin.message(sender, "schemevent-noPermission");
messageBridge.message(sender, "schemevent-noPermission");
return;
}
if(args.length < 3 || args[1] == null || args[2] == null) {
plugin.message(sender, "schemevent-help");
messageBridge.message(sender, "schemevent-help");
return;
}
GeneralRegion region = plugin.getFileManager().getRegion(args[1]);
GeneralRegion region = fileManager.getRegion(args[1]);
if(region == null) {
plugin.message(sender, "cmd-notRegistered", args[1]);
messageBridge.message(sender, "cmd-notRegistered", args[1]);
return;
}
if(region.getRegion() == null) {
plugin.message(sender, "general-noRegion", region);
messageBridge.message(sender, "general-noRegion", region);
return;
}
GeneralRegion.RegionEvent event = null;
@@ -58,21 +68,21 @@ public class SchematiceventCommand extends CommandAreaShop {
for(GeneralRegion.RegionEvent value : GeneralRegion.RegionEvent.values()) {
values.add(value.getValue().toLowerCase());
}
plugin.message(sender, "schemevent-wrongEvent", args[2], Utils.createCommaSeparatedList(values), region);
messageBridge.message(sender, "schemevent-wrongEvent", args[2], Utils.createCommaSeparatedList(values), region);
return;
}
region.handleSchematicEvent(event);
region.update();
plugin.message(sender, "schemevent-success", args[2], region);
messageBridge.message(sender, "schemevent-success", args[2], region);
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
result.addAll(plugin.getFileManager().getRegionNames());
result.addAll(fileManager.getRegionNames());
} else if(toComplete == 3) {
GeneralRegion region = plugin.getFileManager().getRegion(start[2]);
GeneralRegion region = fileManager.getRegion(start[2]);
if(region != null) {
if(region instanceof RentRegion) {
result.addAll(Arrays.asList("created", "deleted", "rented", "unrented"));
@@ -1,16 +1,26 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class SellCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop sell";
@@ -34,8 +44,7 @@ public class SellCommand extends CommandAreaShop {
if(person.hasPermission("areashop.sell")) {
return true;
}
if(person instanceof Player) {
Player player = (Player)person;
if(person instanceof Player player) {
return region.isOwner(player) && person.hasPermission("areashop.sellown");
}
return false;
@@ -44,36 +53,36 @@ public class SellCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.sell") && !sender.hasPermission("areashop.sellown")) {
plugin.message(sender, "sell-noPermission");
messageBridge.message(sender, "sell-noPermission");
return;
}
BuyRegion buy;
if(args.length <= 1) {
if(sender instanceof Player) {
if(sender instanceof Player player) {
// get the region by location
List<BuyRegion> regions = Utils.getImportantBuyRegions(((Player)sender).getLocation());
List<BuyRegion> regions = Utils.getImportantBuyRegions((player).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
buy = regions.get(0);
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
buy = plugin.getFileManager().getBuy(args[1]);
buy = fileManager.getBuy(args[1]);
}
if(buy == null) {
plugin.message(sender, "sell-notRegistered");
messageBridge.message(sender, "sell-notRegistered");
return;
}
if(!buy.isSold()) {
plugin.message(sender, "sell-notBought", buy);
messageBridge.message(sender, "sell-notBought", buy);
return;
}
buy.sell(true, sender);
@@ -83,7 +92,7 @@ public class SellCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
for(BuyRegion region : plugin.getFileManager().getBuys()) {
for(BuyRegion region : fileManager.getBuysRef()) {
if(region.isSold()) {
result.add(region.getName());
}
@@ -1,15 +1,28 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class SetdurationCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Inject
private Plugin plugin;
@Override
public String getCommandStart() {
return "areashop setduration";
@@ -26,11 +39,11 @@ public class SetdurationCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.setduration") && (!sender.hasPermission("areashop.setduration.landlord") && sender instanceof Player)) {
plugin.message(sender, "setduration-noPermission");
messageBridge.message(sender, "setduration-noPermission");
return;
}
if(args.length < 3 || args[1] == null || args[2] == null) {
plugin.message(sender, "setduration-help");
messageBridge.message(sender, "setduration-help");
return;
}
int regionArgument = 3;
@@ -43,61 +56,61 @@ public class SetdurationCommand extends CommandAreaShop {
// get the region by location
List<RentRegion> regions = Utils.getImportantRentRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
rent = regions.get(0);
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
rent = plugin.getFileManager().getRent(args[regionArgument]);
rent = fileManager.getRent(args[regionArgument]);
}
if(rent == null) {
plugin.message(sender, "setduration-notRegistered", args[regionArgument]);
messageBridge.message(sender, "setduration-notRegistered", args[regionArgument]);
return;
}
if(!sender.hasPermission("areashop.setduration") && !(sender instanceof Player && rent.isLandlord(((Player)sender).getUniqueId()))) {
plugin.message(sender, "setduration-noLandlord", rent);
messageBridge.message(sender, "setduration-noLandlord", rent);
return;
}
if("default".equalsIgnoreCase(args[1]) || "reset".equalsIgnoreCase(args[1])) {
rent.setDuration(null);
rent.update();
plugin.message(sender, "setduration-successRemoved", rent);
messageBridge.message(sender, "setduration-successRemoved", rent);
return;
}
try {
Integer.parseInt(args[1]);
} catch(NumberFormatException e) {
plugin.message(sender, "setduration-wrongAmount", args[1], rent);
messageBridge.message(sender, "setduration-wrongAmount", args[1], rent);
return;
}
if(!Utils.checkTimeFormat(args[1] + " " + args[2])) {
plugin.message(sender, "setduration-wrongFormat", args[1] + " " + args[2], rent);
messageBridge.message(sender, "setduration-wrongFormat", args[1] + " " + args[2], rent);
return;
}
rent.setDuration(args[1] + " " + args[2]);
rent.update();
plugin.message(sender, "setduration-success", rent);
messageBridge.message(sender, "setduration-success", rent);
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
List<String> result = new ArrayList<>();
if(toComplete == 2) {
result = plugin.getFileManager().getRentNames();
} else if(toComplete == 4) {
if(toComplete == 3) {
result.addAll(plugin.getConfig().getStringList("minutes"));
result.addAll(plugin.getConfig().getStringList("hours"));
result.addAll(plugin.getConfig().getStringList("days"));
result.addAll(plugin.getConfig().getStringList("months"));
result.addAll(plugin.getConfig().getStringList("years"));
} else if(toComplete == 4) {
result = fileManager.getRentNames();
}
return result;
}
@@ -1,87 +1,100 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class SetlandlordCommand extends CommandAreaShop {
@Override
public String getCommandStart() {
return "areashop setlandlord";
}
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Inject
private OfflinePlayerHelper offlinePlayerHelper;
@Inject
private BukkitSchedulerExecutor executor;
@Override
public String getHelp(CommandSender target) {
if(target.hasPermission("areashop.setlandlord")) {
return "help-setlandlord";
}
return null;
}
@Override
public String getCommandStart() {
return "areashop setlandlord";
}
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.setlandlord")) {
plugin.message(sender, "setlandlord-noPermission");
return;
}
if(args.length < 2) {
plugin.message(sender, "setlandlord-help");
return;
}
@SuppressWarnings("deprecation")
OfflinePlayer player = Bukkit.getOfflinePlayer(args[1]);
GeneralRegion region;
if(args.length < 3) {
if(sender instanceof Player) {
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
region = regions.get(0);
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
region = plugin.getFileManager().getRegion(args[2]);
}
if(region == null) {
plugin.message(sender, "cmd-notRegistered", args[2]);
return;
}
String playerName = player.getName();
if(playerName == null || playerName.isEmpty()) {
playerName = args[1];
}
region.setLandlord(player.getUniqueId(), playerName);
region.update();
plugin.message(sender, "setlandlord-success", playerName, region);
}
@Override
public String getHelp(CommandSender target) {
if (target.hasPermission("areashop.setlandlord")) {
return "help-setlandlord";
}
return null;
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
for(Player player : Utils.getOnlinePlayers()) {
result.add(player.getName());
}
} else if(toComplete == 3) {
result.addAll(plugin.getFileManager().getRegionNames());
}
return result;
}
@Override
public void execute(CommandSender sender, String[] args) {
if (!sender.hasPermission("areashop.setlandlord")) {
messageBridge.message(sender, "setlandlord-noPermission");
return;
}
if (args.length < 2) {
messageBridge.message(sender, "setlandlord-help");
return;
}
GeneralRegion region;
if (args.length < 3) {
if (!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(player.getLocation());
if (regions.isEmpty()) {
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if (regions.size() > 1) {
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
region = regions.get(0);
}
} else {
region = fileManager.getRegion(args[2]);
}
if (region == null) {
messageBridge.message(sender, "cmd-notRegistered", args[2]);
return;
}
this.offlinePlayerHelper.lookupOfflinePlayerAsync(args[1]).thenAcceptAsync(offlinePlayer -> {
String playerName = offlinePlayer.getName();
if (playerName == null || playerName.isEmpty()) {
playerName = args[1];
}
region.setLandlord(offlinePlayer.getUniqueId(), playerName);
region.update();
messageBridge.message(sender, "setlandlord-success", playerName, region);
}, this.executor);
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if (toComplete == 2) {
for (Player player : Utils.getOnlinePlayers()) {
result.add(player.getName());
}
} else if (toComplete == 3) {
result.addAll(fileManager.getRegionNames());
}
return result;
}
}
@@ -1,128 +1,138 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;
@Singleton
public class SetownerCommand extends CommandAreaShop {
@Override
public String getCommandStart() {
return "areashop setowner";
}
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Inject
private OfflinePlayerHelper offlinePlayerHelper;
@Inject
private BukkitSchedulerExecutor executor;
@Override
public String getHelp(CommandSender target) {
if(target.hasPermission("areashop.setownerrent") || target.hasPermission("areashop.setownerbuy")) {
return "help-setowner";
}
return null;
}
@Override
public String getCommandStart() {
return "areashop setowner";
}
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.setownerrent") && !sender.hasPermission("areashop.setownerbuy")) {
plugin.message(sender, "setowner-noPermission");
return;
}
GeneralRegion region;
if(args.length < 2) {
plugin.message(sender, "setowner-help");
return;
}
if(args.length == 2) {
if(sender instanceof Player) {
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
region = regions.get(0);
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
region = plugin.getFileManager().getRegion(args[2]);
}
if(region == null) {
plugin.message(sender, "setowner-notRegistered");
return;
}
@Override
public String getHelp(CommandSender target) {
if (target.hasPermission("areashop.setownerrent") || target.hasPermission("areashop.setownerbuy")) {
return "help-setowner";
}
return null;
}
if(region instanceof RentRegion && !sender.hasPermission("areashop.setownerrent")) {
plugin.message(sender, "setowner-noPermissionRent", region);
return;
}
if(region instanceof BuyRegion && !sender.hasPermission("areashop.setownerbuy")) {
plugin.message(sender, "setowner-noPermissionBuy", region);
return;
}
@Override
public void execute(CommandSender sender, String[] args) {
if (!sender.hasPermission("areashop.setownerrent") && !sender.hasPermission("areashop.setownerbuy")) {
messageBridge.message(sender, "setowner-noPermission");
return;
}
GeneralRegion region;
if (args.length < 2) {
messageBridge.message(sender, "setowner-help");
return;
}
if (args.length == 2) {
if (!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(player.getLocation());
if (regions.isEmpty()) {
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if (regions.size() > 1) {
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
region = regions.get(0);
}
UUID uuid = null;
@SuppressWarnings("deprecation")
OfflinePlayer player = Bukkit.getOfflinePlayer(args[1]);
if(player != null) {
uuid = player.getUniqueId();
}
if(uuid == null) {
plugin.message(sender, "setowner-noPlayer", args[1], region);
return;
}
} else {
region = fileManager.getRegion(args[2]);
}
if (region == null) {
messageBridge.message(sender, "setowner-notRegistered");
return;
}
if(region instanceof RentRegion) {
RentRegion rent = (RentRegion)region;
if(rent.isRenter(uuid)) {
// extend
rent.setRentedUntil(rent.getRentedUntil() + rent.getDuration());
rent.setRenter(uuid);
plugin.message(sender, "setowner-succesRentExtend", region);
} else {
// change
if(!rent.isRented()) {
rent.setRentedUntil(Calendar.getInstance().getTimeInMillis() + rent.getDuration());
}
rent.setRenter(uuid);
plugin.message(sender, "setowner-succesRent", region);
}
}
if(region instanceof BuyRegion) {
BuyRegion buy = (BuyRegion)region;
buy.setBuyer(uuid);
plugin.message(sender, "setowner-succesBuy", region);
}
region.getFriendsFeature().deleteFriend(region.getOwner(), null);
region.update();
region.saveRequired();
}
if (region instanceof RentRegion && !sender.hasPermission("areashop.setownerrent")) {
messageBridge.message(sender, "setowner-noPermissionRent", region);
return;
}
if (region instanceof BuyRegion && !sender.hasPermission("areashop.setownerbuy")) {
messageBridge.message(sender, "setowner-noPermissionBuy", region);
return;
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
for(Player player : Utils.getOnlinePlayers()) {
result.add(player.getName());
}
} else if(toComplete == 3) {
result.addAll(plugin.getFileManager().getRegionNames());
}
return result;
}
this.offlinePlayerHelper.lookupUuidAsync(args[1]).thenAcceptAsync(optionalUuid -> {
if (optionalUuid.isEmpty()) {
messageBridge.message(sender, "setowner-noPlayer", args[1], region);
return;
}
final UUID uuid = optionalUuid.get();
if (region instanceof RentRegion rent) {
if (rent.isRenter(uuid)) {
// extend
rent.setRentedUntil(rent.getRentedUntil() + rent.getDuration());
rent.setRenter(uuid);
messageBridge.message(sender, "setowner-succesRentExtend", region);
} else {
// change
if (!rent.isRented()) {
rent.setRentedUntil(Calendar.getInstance().getTimeInMillis() + rent.getDuration());
}
rent.setRenter(uuid);
messageBridge.message(sender, "setowner-succesRent", region);
}
}
if (region instanceof BuyRegion buy) {
buy.setBuyer(uuid);
messageBridge.message(sender, "setowner-succesBuy", region);
}
region.getFriendsFeature().deleteFriend(region.getOwner(), null);
region.update();
region.saveRequired();
}, this.executor);
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if (toComplete == 2) {
for (Player player : Utils.getOnlinePlayers()) {
result.add(player.getName());
}
} else if (toComplete == 3) {
result.addAll(fileManager.getRegionNames());
}
return result;
}
}
@@ -1,5 +1,7 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
@@ -7,11 +9,19 @@ import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class SetpriceCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop setprice";
@@ -28,11 +38,11 @@ public class SetpriceCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.setprice") && (!sender.hasPermission("areashop.setprice.landlord") && sender instanceof Player)) {
plugin.message(sender, "setprice-noPermission");
messageBridge.message(sender, "setprice-noPermission");
return;
}
if(args.length < 2 || args[1] == null) {
plugin.message(sender, "setprice-help");
messageBridge.message(sender, "setprice-help");
return;
}
GeneralRegion region;
@@ -41,27 +51,27 @@ public class SetpriceCommand extends CommandAreaShop {
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
region = regions.get(0);
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
region = plugin.getFileManager().getRegion(args[2]);
region = fileManager.getRegion(args[2]);
}
if(region == null) {
plugin.message(sender, "setprice-notRegistered", args[2]);
messageBridge.message(sender, "setprice-notRegistered", args[2]);
return;
}
if(!sender.hasPermission("areashop.setprice") && !(sender instanceof Player && region.isLandlord(((Player)sender).getUniqueId()))) {
plugin.message(sender, "setprice-noLandlord", region);
messageBridge.message(sender, "setprice-noLandlord", region);
return;
}
if("default".equalsIgnoreCase(args[1]) || "reset".equalsIgnoreCase(args[1])) {
@@ -71,22 +81,22 @@ public class SetpriceCommand extends CommandAreaShop {
((BuyRegion)region).setPrice(null);
}
region.update();
plugin.message(sender, "setprice-successRemoved", region);
messageBridge.message(sender, "setprice-successRemoved", region);
return;
}
double price;
try {
price = Double.parseDouble(args[1]);
} catch(NumberFormatException e) {
plugin.message(sender, "setprice-wrongPrice", args[1], region);
messageBridge.message(sender, "setprice-wrongPrice", args[1], region);
return;
}
if(region instanceof RentRegion) {
((RentRegion)region).setPrice(price);
plugin.message(sender, "setprice-successRent", region);
messageBridge.message(sender, "setprice-successRent", region);
} else if(region instanceof BuyRegion) {
((BuyRegion)region).setPrice(price);
plugin.message(sender, "setprice-successBuy", region);
messageBridge.message(sender, "setprice-successBuy", region);
}
region.update();
}
@@ -95,7 +105,7 @@ public class SetpriceCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
List<String> result = new ArrayList<>();
if(toComplete == 3) {
result = plugin.getFileManager().getRegionNames();
result = fileManager.getRegionNames();
}
return result;
}
@@ -1,13 +1,28 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.plugin.Plugin;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class SetrestoreCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Inject
private Plugin plugin;
@Override
public String getCommandStart() {
return "areashop setrestore";
@@ -24,16 +39,16 @@ public class SetrestoreCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.setrestore")) {
plugin.message(sender, "setrestore-noPermission");
messageBridge.message(sender, "setrestore-noPermission");
return;
}
if(args.length <= 2 || args[1] == null || args[2] == null) {
plugin.message(sender, "setrestore-help");
messageBridge.message(sender, "setrestore-help");
return;
}
GeneralRegion region = plugin.getFileManager().getRegion(args[1]);
GeneralRegion region = fileManager.getRegion(args[1]);
if(region == null) {
plugin.message(sender, "setrestore-notRegistered", args[1]);
messageBridge.message(sender, "setrestore-notRegistered", args[1]);
return;
}
Boolean value = null;
@@ -49,9 +64,9 @@ public class SetrestoreCommand extends CommandAreaShop {
}
if(args.length > 3) {
region.setSchematicProfile(args[3]);
plugin.message(sender, "setrestore-successProfile", valueString, args[3], region);
messageBridge.message(sender, "setrestore-successProfile", valueString, args[3], region);
} else {
plugin.message(sender, "setrestore-success", valueString, region);
messageBridge.message(sender, "setrestore-success", valueString, region);
}
region.update();
}
@@ -60,13 +75,16 @@ public class SetrestoreCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
List<String> result = new ArrayList<>();
if(toComplete == 2) {
result = plugin.getFileManager().getRegionNames();
result = fileManager.getRegionNames();
} else if(toComplete == 3) {
result.add("true");
result.add("false");
result.add("general");
} else if(toComplete == 4) {
result.addAll(plugin.getConfig().getConfigurationSection("schematicProfiles").getKeys(false));
ConfigurationSection schemProfiles = fileManager.getConfig().getConfigurationSection("schematicProfiles");
if (schemProfiles != null) {
result.addAll(schemProfiles.getKeys(false));
}
}
return result;
}
@@ -1,6 +1,8 @@
package me.wiefferink.areashop.commands;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
@@ -8,11 +10,19 @@ import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class SetteleportCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop settp";
@@ -20,7 +30,7 @@ public class SetteleportCommand extends CommandAreaShop {
@Override
public String getHelp(CommandSender target) {
if(target.hasPermission("areashop.teleportall") || target.hasPermission("areashop.teleport")) {
if(target.hasPermission("areashop.setteleportall") || target.hasPermission("areashop.setteleport")) {
return "help-setteleport";
}
return null;
@@ -33,10 +43,9 @@ public class SetteleportCommand extends CommandAreaShop {
* @return true if the person can set the teleport location, otherwise false
*/
public static boolean canUse(CommandSender person, GeneralRegion region) {
if(!(person instanceof Player)) {
if(!(person instanceof Player player)) {
return false;
}
Player player = (Player)person;
return player.hasPermission("areashop.setteleportall")
|| region.isOwner(player) && player.hasPermission("areashop.setteleport");
}
@@ -44,35 +53,34 @@ public class SetteleportCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.setteleport") && !sender.hasPermission("areashop.setteleportall")) {
plugin.message(sender, "setteleport-noPermission");
messageBridge.message(sender, "setteleport-noPermission");
return;
}
if(!(sender instanceof Player)) {
plugin.message(sender, "onlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "onlyByPlayer");
return;
}
Player player = (Player)sender;
GeneralRegion region;
if(args.length < 2) {
// get the region by location
List<GeneralRegion> regions = Utils.getImportantRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
region = regions.get(0);
}
} else {
region = plugin.getFileManager().getRegion(args[1]);
region = fileManager.getRegion(args[1]);
}
boolean owner;
if(region == null) {
plugin.message(player, "setteleport-noRentOrBuy", args[1]);
messageBridge.message(player, "setteleport-noRentOrBuy", args[1]);
return;
}
if(region instanceof RentRegion) {
@@ -81,10 +89,10 @@ public class SetteleportCommand extends CommandAreaShop {
owner = player.getUniqueId().equals(((BuyRegion)region).getBuyer());
}
if(!player.hasPermission("areashop.setteleport")) {
plugin.message(player, "setteleport-noPermission", region);
messageBridge.message(player, "setteleport-noPermission", region);
return;
} else if(!owner && !player.hasPermission("areashop.setteleportall")) {
plugin.message(player, "setteleport-noPermissionOther", region);
messageBridge.message(player, "setteleport-noPermissionOther", region);
return;
}
@@ -92,23 +100,23 @@ public class SetteleportCommand extends CommandAreaShop {
if(args.length > 2 && args[2] != null && (args[2].equalsIgnoreCase("reset") || args[2].equalsIgnoreCase("yes") || args[2].equalsIgnoreCase("true"))) {
region.getTeleportFeature().setTeleport(null);
region.update();
plugin.message(player, "setteleport-reset", region);
messageBridge.message(player, "setteleport-reset", region);
return;
}
if(!player.hasPermission("areashop.setteleportoutsideregion") && (wgRegion == null || !wgRegion.contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()))) {
plugin.message(player, "setteleport-notInside", region);
messageBridge.message(player, "setteleport-notInside", region);
return;
}
region.getTeleportFeature().setTeleport(player.getLocation());
region.update();
plugin.message(player, "setteleport-success", region);
messageBridge.message(player, "setteleport-success", region);
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
result.addAll(plugin.getFileManager().getRegionNames());
result.addAll(fileManager.getRegionNames());
} else if(toComplete == 3) {
result.add("reset");
}
@@ -1,28 +1,48 @@
package me.wiefferink.areashop.commands;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldEditSelection;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionFactory;
import me.wiefferink.areashop.regions.RegionGroup;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.interactivemessenger.processing.Message;
import org.bukkit.Location;
import org.bukkit.block.BlockFace;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class StackCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Inject
private WorldEditInterface worldEditInterface;
@Inject
private WorldGuardInterface worldGuardInterface;
@Inject
private RegionFactory regionFactory;
@Inject
private Plugin plugin;
@Override
public String getCommandStart() {
return "areashop stack";
@@ -40,18 +60,17 @@ public class StackCommand extends CommandAreaShop {
public void execute(CommandSender sender, String[] args) {
// Check permission
if(!sender.hasPermission("areashop.stack")) {
plugin.message(sender, "stack-noPermission");
messageBridge.message(sender, "stack-noPermission");
return;
}
// Only from ingame
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-onlyByPlayer");
if(!(sender instanceof final Player player)) {
messageBridge.message(sender, "cmd-onlyByPlayer");
return;
}
final Player player = (Player)sender;
// Specify enough arguments
if(args.length < 5) {
plugin.message(sender, "stack-help");
messageBridge.message(sender, "stack-help");
return;
}
// Check amount
@@ -62,7 +81,7 @@ public class StackCommand extends CommandAreaShop {
// Incorrect number
}
if(tempAmount <= 0) {
plugin.message(player, "stack-wrongAmount", args[1]);
messageBridge.message(player, "stack-wrongAmount", args[1]);
return;
}
// Check gap
@@ -70,27 +89,27 @@ public class StackCommand extends CommandAreaShop {
try {
gap = Integer.parseInt(args[2]);
} catch(NumberFormatException e) {
plugin.message(player, "stack-wrongGap", args[2]);
messageBridge.message(player, "stack-wrongGap", args[2]);
return;
}
// Check region type
if(!"rent".equalsIgnoreCase(args[4]) && !"buy".equalsIgnoreCase(args[4])) {
plugin.message(sender, "stack-help");
messageBridge.message(sender, "stack-help");
return;
}
// Get WorldEdit selection
final WorldEditSelection selection = plugin.getWorldEditHandler().getPlayerSelection(player);
final WorldEditSelection selection = worldEditInterface.getPlayerSelection(player);
if(selection == null) {
plugin.message(player, "stack-noSelection");
messageBridge.message(player, "stack-noSelection");
return;
}
// Get or create group
RegionGroup group = null;
if(args.length > 5) {
group = plugin.getFileManager().getGroup(args[5]);
group = fileManager.getGroup(args[5]);
if(group == null) {
group = new RegionGroup(plugin, args[5]);
plugin.getFileManager().addGroup(group);
group = regionFactory.createRegionGroup(args[5]);
fileManager.addGroup(group);
}
}
// Get facing of the player (must be clearly one of the four directions to make sure it is no mistake)
@@ -101,10 +120,10 @@ public class StackCommand extends CommandAreaShop {
facing = BlockFace.UP;
}
if(!(facing == BlockFace.NORTH || facing == BlockFace.EAST || facing == BlockFace.SOUTH || facing == BlockFace.WEST || facing == BlockFace.UP || facing == BlockFace.DOWN)) {
plugin.message(player, "stack-unclearDirection", facing.toString().toLowerCase().replace('_', '-'));
messageBridge.message(player, "stack-unclearDirection", facing.toString().toLowerCase().replace('_', '-'));
return;
}
Vector shift = new BlockVector(0, 0, 0);
Vector shift = new Vector(0, 0, 0);
if(facing == BlockFace.SOUTH) {
shift = shift.setZ(-selection.getLength() - gap);
} else if(facing == BlockFace.WEST) {
@@ -138,8 +157,8 @@ public class StackCommand extends CommandAreaShop {
if(group != null) {
groupsMessage = Message.fromKey("stack-addToGroup").replacements(group.getName());
}
plugin.message(player, "stack-accepted", amount, type, gap, nameTemplate, groupsMessage);
plugin.message(player, "stack-addStart", amount, regionsPerTick * 20);
messageBridge.message(player, "stack-accepted", amount, type, gap, nameTemplate, groupsMessage);
messageBridge.message(player, "stack-addStart", amount, regionsPerTick * 20);
Location minimumLocation = selection.getMinimumLocation();
Vector minimumVector = new Vector(minimumLocation.getX(), minimumLocation.getY(), minimumLocation.getZ());
@@ -158,33 +177,16 @@ public class StackCommand extends CommandAreaShop {
current++;
if(current < amount) {
// Create the region name
String counterName = counter + "";
int minimumLength = plugin.getConfig().getInt("stackRegionNumberLength");
while(counterName.length() < minimumLength) {
counterName = "0" + counterName;
}
String regionName;
if(nameTemplate.contains("#")) {
regionName = nameTemplate.replace("#", counterName);
} else {
regionName = nameTemplate + counterName;
}
String regionName = countToName(nameTemplate, counter);
while(manager.getRegion(regionName) != null || AreaShop.getInstance().getFileManager().getRegion(regionName) != null) {
counter++;
counterName = counter + "";
minimumLength = plugin.getConfig().getInt("stackRegionNumberLength");
while(counterName.length() < minimumLength) {
counterName = "0" + counterName;
}
if(nameTemplate.contains("#")) {
regionName = nameTemplate.replace("#", counterName);
} else {
regionName = nameTemplate + counterName;
}
regionName = countToName(nameTemplate, counter);
}
// Add the region to WorldGuard (at startposition shifted by the number of this region times the blocks it should shift)
BlockVector minimum = new BlockVector(minimumVector.add(finalShift.multiply(current)));
BlockVector maximum = new BlockVector(maximumVector.add(finalShift.multiply(current)));
Vector minimum = minimumVector.clone().add(finalShift.clone().multiply(current));
Vector maximum = maximumVector.clone().add(finalShift.clone().multiply(current));
// Check for out of bounds
if(minimum.getBlockY() < 0) {
tooLow++;
@@ -193,30 +195,28 @@ public class StackCommand extends CommandAreaShop {
tooHigh++;
continue;
}
ProtectedCuboidRegion region = new ProtectedCuboidRegion(regionName, minimum, maximum);
ProtectedCuboidRegion region = worldGuardInterface.createCuboidRegion(regionName, minimum,maximum);
manager.addRegion(region);
// Add the region to AreaShop
GeneralRegion newRegion;
if(rentRegions) {
RentRegion rent = new RentRegion(regionName, selection.getWorld());
if(finalGroup != null) {
finalGroup.addMember(rent);
}
rent.runEventCommands(GeneralRegion.RegionEvent.CREATED, true);
plugin.getFileManager().addRent(rent);
rent.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
rent.runEventCommands(GeneralRegion.RegionEvent.CREATED, false);
rent.update();
newRegion = regionFactory.createRentRegion(regionName, selection.getWorld());
} else {
BuyRegion buy = new BuyRegion(regionName, selection.getWorld());
if(finalGroup != null) {
finalGroup.addMember(buy);
}
buy.runEventCommands(GeneralRegion.RegionEvent.CREATED, true);
plugin.getFileManager().addBuy(buy);
buy.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
buy.runEventCommands(GeneralRegion.RegionEvent.CREATED, false);
buy.update();
newRegion = regionFactory.createBuyRegion(regionName, selection.getWorld());
}
if(finalGroup != null) {
finalGroup.addMember(newRegion);
}
AddingRegionEvent event = fileManager.addRegion(newRegion);
if (event.isCancelled()) {
messageBridge.message(player, "general-cancelled", event.getReason());
continue;
}
newRegion.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
newRegion.update();
}
}
if(current >= amount) {
@@ -229,7 +229,7 @@ public class StackCommand extends CommandAreaShop {
if(tooLow > 0) {
wrong.append(Message.fromKey("stack-tooLow").replacements(tooLow));
}
plugin.message(player, "stack-addComplete", added, wrong);
messageBridge.message(player, "stack-addComplete", added, wrong);
}
this.cancel();
}
@@ -237,6 +237,26 @@ public class StackCommand extends CommandAreaShop {
}.runTaskTimer(plugin, 1, 1);
}
/**
* Build a name from a count, with the right length.
* @param template Template to put the name in (# to put the count there, otherwise count is appended)
* @param count Number to use
* @return name with prepended 0's
*/
private String countToName(String template, int count) {
StringBuilder counterName = new StringBuilder().append(count);
int minimumLength = plugin.getConfig().getInt("stackRegionNumberLength");
while(counterName.length() < minimumLength) {
counterName.insert(0, "0");
}
if(template.contains("#")) {
return template.replace("#", counterName);
} else {
return template + counterName;
}
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
List<String> result = new ArrayList<>();
@@ -244,7 +264,7 @@ public class StackCommand extends CommandAreaShop {
result.add("rent");
result.add("buy");
} else if(toComplete == 6) {
result.addAll(plugin.getFileManager().getGroupNames());
result.addAll(fileManager.getGroupNames());
}
return result;
}
@@ -1,15 +1,25 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class StopresellCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop stopresell";
@@ -26,7 +36,7 @@ public class StopresellCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.stopresell") && !sender.hasPermission("areashop.stopresellall")) {
plugin.message(sender, "stopresell-noPermissionOther");
messageBridge.message(sender, "stopresell-noPermissionOther");
return;
}
@@ -36,47 +46,47 @@ public class StopresellCommand extends CommandAreaShop {
// get the region by location
List<BuyRegion> regions = Utils.getImportantBuyRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
buy = regions.get(0);
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
buy = plugin.getFileManager().getBuy(args[1]);
buy = fileManager.getBuy(args[1]);
if(buy == null) {
plugin.message(sender, "stopresell-notRegistered", args[1]);
messageBridge.message(sender, "stopresell-notRegistered", args[1]);
return;
}
}
if(buy == null) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
}
if(!buy.isInResellingMode()) {
plugin.message(sender, "stopresell-notResell", buy);
messageBridge.message(sender, "stopresell-notResell", buy);
return;
}
if(sender.hasPermission("areashop.stopresellall")) {
buy.disableReselling();
buy.update();
plugin.message(sender, "stopresell-success", buy);
messageBridge.message(sender, "stopresell-success", buy);
} else if(sender.hasPermission("areashop.stopresell") && sender instanceof Player) {
if(buy.isOwner((Player)sender)) {
buy.disableReselling();
buy.update();
plugin.message(sender, "stopresell-success", buy);
messageBridge.message(sender, "stopresell-success", buy);
} else {
plugin.message(sender, "stopresell-noPermissionOther", buy);
messageBridge.message(sender, "stopresell-noPermissionOther", buy);
}
} else {
plugin.message(sender, "stopresell-noPermission", buy);
messageBridge.message(sender, "stopresell-noPermission", buy);
}
}
@@ -84,7 +94,7 @@ public class StopresellCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
for(BuyRegion region : plugin.getFileManager().getBuys()) {
for(BuyRegion region : fileManager.getBuysRef()) {
if(region.isSold() && region.isInResellingMode()) {
result.add(region.getName());
}
@@ -1,14 +1,24 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class TeleportCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop tp";
@@ -29,10 +39,9 @@ public class TeleportCommand extends CommandAreaShop {
* @return true if the person can teleport to it, otherwise false
*/
public static boolean canUse(CommandSender person, GeneralRegion region) {
if(!(person instanceof Player)) {
if(!(person instanceof Player player)) {
return false;
}
Player player = (Player)person;
return player.hasPermission("areashop.teleportall")
|| region.isOwner(player) && player.hasPermission("areashop.teleport")
|| region.isAvailable() && player.hasPermission("areashop.teleportavailable")
@@ -42,36 +51,36 @@ public class TeleportCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.teleport") && !sender.hasPermission("areashop.teleportall") && !sender.hasPermission("areashop.teleportavailable") && !sender.hasPermission("areashop.teleportavailablesign") && !sender.hasPermission("areashop.teleportsign") && !sender.hasPermission("areashop.teleportsignall") && !sender.hasPermission("areashop.teleportfriend") && !sender.hasPermission("teleportfriendsign")) {
plugin.message(sender, "teleport-noPermission");
messageBridge.message(sender, "teleport-noPermission");
return;
}
if(!(sender instanceof Player)) {
plugin.message(sender, "cmd-onlyByPlayer");
if(!(sender instanceof Player player)) {
messageBridge.message(sender, "cmd-onlyByPlayer");
return;
}
if(args.length <= 1 || args[1] == null) {
plugin.message(sender, "teleport-help");
messageBridge.message(sender, "teleport-help");
return;
}
Player player = (Player)sender;
GeneralRegion region = plugin.getFileManager().getRegion(args[1]);
GeneralRegion region = fileManager.getRegion(args[1]);
if(region == null) {
plugin.message(player, "teleport-noRentOrBuy", args[1]);
messageBridge.message(player, "teleport-noRentOrBuy", args[1]);
return;
}
if(args.length >= 3 && (args[2].equalsIgnoreCase("sign") || args[2].equalsIgnoreCase("yes") || args[2].equalsIgnoreCase("true"))) {
region.getTeleportFeature().teleportPlayer(player, true);
} else {
region.getTeleportFeature().teleportPlayer(player, false);
}
boolean toSign = args.length >= 3 && (
args[2].equalsIgnoreCase("sign")
|| args[2].equalsIgnoreCase("yes")
|| args[2].equalsIgnoreCase("true")
);
region.getTeleportFeature().teleportPlayer(player, toSign);
}
@Override
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
result.addAll(plugin.getFileManager().getRegionNames());
result.addAll(fileManager.getRegionNames());
} else if(toComplete == 3) {
result.add("sign");
}
@@ -1,16 +1,26 @@
package me.wiefferink.areashop.commands;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@Singleton
public class UnrentCommand extends CommandAreaShop {
@Inject
private MessageBridge messageBridge;
@Inject
private IFileManager fileManager;
@Override
public String getCommandStart() {
return "areashop unrent";
@@ -34,8 +44,7 @@ public class UnrentCommand extends CommandAreaShop {
if(person.hasPermission("areashop.unrent")) {
return true;
}
if(person instanceof Player) {
Player player = (Player)person;
if(person instanceof Player player) {
return region.isOwner(player) && person.hasPermission("areashop.unrentown");
}
return false;
@@ -44,7 +53,7 @@ public class UnrentCommand extends CommandAreaShop {
@Override
public void execute(CommandSender sender, String[] args) {
if(!sender.hasPermission("areashop.unrent") && !sender.hasPermission("areashop.unrentown")) {
plugin.message(sender, "unrent-noPermission");
messageBridge.message(sender, "unrent-noPermission");
return;
}
RentRegion rent;
@@ -53,27 +62,27 @@ public class UnrentCommand extends CommandAreaShop {
// get the region by location
List<RentRegion> regions = Utils.getImportantRentRegions(((Player)sender).getLocation());
if(regions.isEmpty()) {
plugin.message(sender, "cmd-noRegionsAtLocation");
messageBridge.message(sender, "cmd-noRegionsAtLocation");
return;
} else if(regions.size() > 1) {
plugin.message(sender, "cmd-moreRegionsAtLocation");
messageBridge.message(sender, "cmd-moreRegionsAtLocation");
return;
} else {
rent = regions.get(0);
}
} else {
plugin.message(sender, "cmd-automaticRegionOnlyByPlayer");
messageBridge.message(sender, "cmd-automaticRegionOnlyByPlayer");
return;
}
} else {
rent = plugin.getFileManager().getRent(args[1]);
rent = fileManager.getRent(args[1]);
}
if(rent == null) {
plugin.message(sender, "unrent-notRegistered");
messageBridge.message(sender, "unrent-notRegistered");
return;
}
if(!rent.isRented()) {
plugin.message(sender, "unrent-notRented", rent);
messageBridge.message(sender, "unrent-notRented", rent);
return;
}
rent.unRent(true, sender);
@@ -83,7 +92,7 @@ public class UnrentCommand extends CommandAreaShop {
public List<String> getTabCompleteList(int toComplete, String[] start, CommandSender sender) {
ArrayList<String> result = new ArrayList<>();
if(toComplete == 2) {
for(RentRegion region : plugin.getFileManager().getRents()) {
for(RentRegion region : fileManager.getRentsRef()) {
if(region.isRented()) {
result.add(region.getName());
}
@@ -16,6 +16,7 @@ public class RegionEvent<T> extends Event {
return handlers;
}
// Required by Bukkit/Spigot
public static HandlerList getHandlerList() {
return handlers;
}
@@ -0,0 +1,19 @@
package me.wiefferink.areashop.events.ask;
import me.wiefferink.areashop.events.CancellableRegionEvent;
import me.wiefferink.areashop.regions.GeneralRegion;
/**
* Broadcasted when a region has been added to AreaShop.
*/
public class AddingRegionEvent extends CancellableRegionEvent<GeneralRegion> {
/**
* Constructor.
* @param region The region that has been added
*/
public AddingRegionEvent(GeneralRegion region) {
super(region);
}
}
@@ -0,0 +1,19 @@
package me.wiefferink.areashop.events.ask;
import me.wiefferink.areashop.events.CancellableRegionEvent;
import me.wiefferink.areashop.regions.GeneralRegion;
/**
* Broadcasted when a region has been added to AreaShop.
*/
public class DeletingRegionEvent extends CancellableRegionEvent<GeneralRegion> {
/**
* Constructor.
* @param region The region that has been added
*/
public DeletingRegionEvent(GeneralRegion region) {
super(region);
}
}
@@ -0,0 +1,127 @@
package me.wiefferink.areashop.features;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
import me.wiefferink.areashop.events.ask.BuyingRegionEvent;
import me.wiefferink.areashop.events.ask.DeletingRegionEvent;
import me.wiefferink.areashop.events.ask.RentingRegionEvent;
import me.wiefferink.areashop.events.ask.ResellingRegionEvent;
import me.wiefferink.areashop.events.ask.SellingRegionEvent;
import me.wiefferink.areashop.events.ask.UnrentingRegionEvent;
import me.wiefferink.areashop.events.notify.AddedRegionEvent;
import me.wiefferink.areashop.events.notify.BoughtRegionEvent;
import me.wiefferink.areashop.events.notify.DeletedRegionEvent;
import me.wiefferink.areashop.events.notify.RentedRegionEvent;
import me.wiefferink.areashop.events.notify.ResoldRegionEvent;
import me.wiefferink.areashop.events.notify.SoldRegionEvent;
import me.wiefferink.areashop.events.notify.UnrentedRegionEvent;
import me.wiefferink.areashop.regions.GeneralRegion;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.List;
@Singleton
public class CommandsFeature extends RegionFeature {
@Inject
CommandsFeature(AreaShop plugin) {
super(plugin);
}
/**
* Run command for a certain event.
* @param region Region to execute the events for
* @param event The event
* @param before The 'before' or 'after' commands
*/
public void runEventCommands(GeneralRegion region, GeneralRegion.RegionEvent event, boolean before) {
ConfigurationSection eventCommandProfileSection = region.getConfigurationSectionSetting("general.eventCommandProfile", "eventCommandProfiles");
if(eventCommandProfileSection == null) {
return;
}
List<String> commands = eventCommandProfileSection.getStringList(event.getValue() + "." + (before ? "before" : "after"));
if(commands.isEmpty()) {
return;
}
region.runCommands(Bukkit.getConsoleSender(), commands);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void addingRegion(AddingRegionEvent event) {
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.CREATED, true);
}
@EventHandler
public void addedRegion(AddedRegionEvent event) {
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.CREATED, false);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void deletingRegion(DeletingRegionEvent event) {
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.DELETED, true);
}
@EventHandler
public void deletedRegion(DeletedRegionEvent event) {
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.DELETED, false);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void rentingRegion(RentingRegionEvent event) {
// Technically the rent can still be cancelled if the payment fails...
runEventCommands(event.getRegion(), event.isExtending() ? GeneralRegion.RegionEvent.EXTENDED : GeneralRegion.RegionEvent.RENTED, true);
}
@EventHandler
public void rentedRegion(RentedRegionEvent event) {
runEventCommands(event.getRegion(), event.hasExtended() ? GeneralRegion.RegionEvent.EXTENDED : GeneralRegion.RegionEvent.RENTED, false);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void buyingRegion(BuyingRegionEvent event) {
// Technically the buy can still be cancelled if the payment fails...
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.BOUGHT, true);
}
@EventHandler
public void boughtRegion(BoughtRegionEvent event) {
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.BOUGHT, false);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void resellingRegion(ResellingRegionEvent event) {
// Technically the resell can still be cancelled if the payment fails...
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.RESELL, true);
}
@EventHandler
public void resoldRegion(ResoldRegionEvent event) {
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.RESELL, false);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void sellingRegion(SellingRegionEvent event) {
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.SOLD, true);
}
@EventHandler
public void soldRegion(SoldRegionEvent event) {
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.SOLD, false);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void unrentingRegion(UnrentingRegionEvent event) {
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.UNRENTED, true);
}
@EventHandler
public void unrentedRegion(UnrentedRegionEvent event) {
runEventCommands(event.getRegion(), GeneralRegion.RegionEvent.UNRENTED, false);
}
}
@@ -19,8 +19,18 @@ import me.wiefferink.areashop.events.notify.UpdateRegionEvent;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.event.EventHandler;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class DebugFeature extends RegionFeature {
@Inject
DebugFeature(@Nonnull AreaShop plugin) {
super(plugin);
}
@EventHandler
public void buyingRegion(BuyingRegionEvent event) {
AreaShop.debug("BuyingRegionEvent: " + event.getPlayer().getName() + " is trying to buy " + event.getRegion().getName());
@@ -0,0 +1,19 @@
package me.wiefferink.areashop.features;
import me.wiefferink.areashop.features.signs.SignsFeature;
import me.wiefferink.areashop.regions.GeneralRegion;
import javax.annotation.Nonnull;
public interface FeatureFactory {
@Nonnull
SignsFeature createSignsFeature(@Nonnull GeneralRegion generalRegion);
@Nonnull
TeleportFeature createTeleportFeature(@Nonnull GeneralRegion generalRegion);
@Nonnull
FriendsFeature createFriendsFeature(@Nonnull GeneralRegion generalRegion);
}
@@ -1,5 +1,10 @@
package me.wiefferink.areashop.features;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.events.askandnotify.AddedFriendEvent;
import me.wiefferink.areashop.events.askandnotify.DeletedFriendEvent;
import me.wiefferink.areashop.regions.GeneralRegion;
@@ -7,6 +12,7 @@ import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.CommandSender;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
@@ -15,7 +21,12 @@ import java.util.UUID;
public class FriendsFeature extends RegionFeature {
public FriendsFeature(GeneralRegion region) {
@Inject
private MessageBridge messageBridge;
@AssistedInject
public FriendsFeature(@Nonnull AreaShop plugin, @Assisted @Nonnull GeneralRegion region) {
super(plugin);
setRegion(region);
}
@@ -30,7 +41,7 @@ public class FriendsFeature extends RegionFeature {
AddedFriendEvent event = new AddedFriendEvent(getRegion(), Bukkit.getOfflinePlayer(player), by);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
plugin.message(by, "general-cancelled", event.getReason(), this);
messageBridge.message(by, "general-cancelled", event.getReason(), this);
return false;
}
@@ -52,7 +63,7 @@ public class FriendsFeature extends RegionFeature {
DeletedFriendEvent event = new DeletedFriendEvent(getRegion(), Bukkit.getOfflinePlayer(player), by);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
plugin.message(by, "general-cancelled", event.getReason(), this);
messageBridge.message(by, "general-cancelled", event.getReason(), this);
return false;
}
@@ -2,16 +2,41 @@ package me.wiefferink.areashop.features;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.regions.GeneralRegion;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.event.HandlerList;
import org.bukkit.event.Listener;
public abstract class RegionFeature implements Listener {
public static final AreaShop plugin = AreaShop.getInstance();
import javax.annotation.Nonnull;
public YamlConfiguration config = plugin.getConfig();
/*
Possible future feature classes:
- RestrictedToRegion feature
- rent/buy restricted to the region itself
- RestrictedToWorld feature
- rent/buy restricted to the world of the region
- CountLimitsFeature:
- Check region limits
- TimeLimitsFeatures:
- maxExtends
- maxRentTime
- SchematicFeature
- save/load schematics
- CommandsFeature
- execute commands after extend/rent/etc
- LandlordFeature
- manage landlords
- ExpirationWarningsFeature
- sending rental expiration warnings
*/
public abstract class RegionFeature implements Listener {
protected final AreaShop plugin;
private GeneralRegion region;
protected RegionFeature(@Nonnull AreaShop plugin) {
this.plugin = plugin;
}
/**
* Set the region for this feature.
* @param region Feature region
@@ -1,35 +1,38 @@
package me.wiefferink.areashop.features;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.features.signs.RegionSign;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.areashop.tools.Value;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Tag;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Set;
public class TeleportFeature extends RegionFeature {
private static final ArrayList<Material> canSpawnIn = new ArrayList<>(Arrays.asList(Material.WOOD_DOOR, Material.WOODEN_DOOR, Material.SIGN_POST, Material.WALL_SIGN, Material.STONE_PLATE, Material.IRON_DOOR_BLOCK, Material.WOOD_PLATE, Material.TRAP_DOOR, Material.REDSTONE_LAMP_OFF, Material.REDSTONE_LAMP_ON, Material.DRAGON_EGG, Material.GOLD_PLATE, Material.IRON_PLATE));
private static final ArrayList<Material> cannotSpawnOn = new ArrayList<>(Arrays.asList(Material.PISTON_EXTENSION, Material.PISTON_MOVING_PIECE, Material.SIGN_POST, Material.WALL_SIGN, Material.STONE_PLATE, Material.IRON_DOOR_BLOCK, Material.WOOD_PLATE, Material.TRAP_DOOR, Material.REDSTONE_LAMP_OFF, Material.REDSTONE_LAMP_ON, Material.CACTUS, Material.IRON_FENCE, Material.FENCE_GATE, Material.THIN_GLASS, Material.NETHER_FENCE, Material.DRAGON_EGG, Material.GOLD_PLATE, Material.IRON_PLATE, Material.STAINED_GLASS_PANE));
private static final ArrayList<Material> cannotSpawnBeside = new ArrayList<>(Arrays.asList(Material.LAVA, Material.STATIONARY_LAVA, Material.CACTUS));
@Inject
private WorldGuardInterface worldGuardInterface;
public TeleportFeature() {
}
public TeleportFeature(GeneralRegion region) {
@AssistedInject
public TeleportFeature(@Nonnull AreaShop plugin, @Assisted @Nonnull GeneralRegion region) {
super(plugin);
setRegion(region);
}
@@ -154,7 +157,7 @@ public class TeleportFeature extends RegionFeature {
int maxTries = plugin.getConfig().getInt("maximumTries");
// Tracking of which sides to continue the search
boolean done = isSafe(safeLocation) && (blocksInRegion || !insideRegion);
boolean done = isSafe(safeLocation);
boolean northDone = false, eastDone = false, southDone = false, westDone = false, topDone = false, bottomDone = false;
boolean continueThisDirection;
@@ -361,7 +364,9 @@ public class TeleportFeature extends RegionFeature {
// Let the player look at the sign
Vector playerVector = safeLocation.toVector();
playerVector.setY(playerVector.getY() + player.getEyeHeight(true));
Vector signVector = getRegion().getSignsFeature().getSigns().get(0).getLocation().toVector().add(new Vector(0.5, 0.5, 0.5));
SignManager signManager = getRegion().getSignsFeature().signManager();
Iterator<RegionSign> iterator = signManager.allSigns().iterator();
Vector signVector = iterator.next().getLocation().toVector().add(new Vector(0.5, 0.5, 0.5));
Vector direction = playerVector.clone().subtract(signVector).normalize();
safeLocation.setYaw(180 - (float)Math.toDegrees(Math.atan2(direction.getX(), direction.getZ())));
safeLocation.setPitch(90 - (float)Math.toDegrees(Math.acos(direction.getY())));
@@ -410,18 +415,18 @@ public class TeleportFeature extends RegionFeature {
Block above = head.getRelative(BlockFace.UP);
// Check the block at the feet and head of the player
if((feet.getType().isSolid() && !canSpawnIn.contains(feet.getType())) || feet.isLiquid()) {
if((feet.getType().isSolid() && !canSpawnIn(feet.getType())) || feet.isLiquid()) {
return false;
} else if((head.getType().isSolid() && !canSpawnIn.contains(head.getType())) || head.isLiquid()) {
} else if((head.getType().isSolid() && !canSpawnIn(head.getType())) || head.isLiquid()) {
return false;
} else if(!below.getType().isSolid() || cannotSpawnOn.contains(below.getType()) || below.isLiquid()) {
} else if(!below.getType().isSolid() || cannotSpawnOn(below.getType()) || below.isLiquid()) {
return false;
} else if(above.isLiquid() || cannotSpawnBeside.contains(above.getType())) {
} else if(above.isLiquid() || cannotSpawnBeside(above.getType())) {
return false;
}
// Get all blocks around the player (below foot level, foot level, head level and above head level)
Set<Material> around = new HashSet<>();
Set<Material> around = EnumSet.noneOf(Material.class);
for(int y = 0; y <= 3; y++) {
for(int x = -1; x <= 1; x++) {
for(int z = -1; z <= 1; z++) {
@@ -437,13 +442,56 @@ public class TeleportFeature extends RegionFeature {
// Check the blocks around the player
for(Material material : around) {
if(cannotSpawnBeside.contains(material)) {
if(cannotSpawnBeside(material)) {
return false;
}
}
return true;
}
/**
* Check if a player can spawn in here.
* @param material Material to check (assumed that this is at the feet or head level)
* @return true when it is safe to spawn inside, otherwise false
*/
private static boolean canSpawnIn(Material material) {
return material == Material.DRAGON_EGG
|| Tag.DOORS.isTagged(material)
|| Tag.SIGNS.isTagged(material)
|| Tag.PRESSURE_PLATES.isTagged(material);
}
/**
* Check if a player can spawn on here.
* @param material Material to check (assumed that this is below the feet)
* @return true when it is safe to spawn on top of, otherwise false
*/
private static boolean cannotSpawnOn(Material material) {
return material == Material.CACTUS
|| material == Material.PISTON
|| material == Material.PISTON_HEAD
|| material == Material.MOVING_PISTON
|| material == Material.DRAGON_EGG
|| material == Material.MAGMA_BLOCK
|| material == Material.REDSTONE_LAMP
|| Tag.SIGNS.isTagged(material)
|| Tag.DOORS.isTagged(material)
|| Tag.FENCE_GATES.isTagged(material)
|| Tag.FENCES.isTagged(material)
|| material.name().contains("GLASS_PANE");
}
/**
* Check if a player can spawn next to it.
* @param material Material to check (assumed that this is somewhere around the player)
* @return true when it is safe to spawn next to, otherwise false
*/
private static boolean cannotSpawnBeside(Material material) {
return material == Material.LAVA
|| material == Material.FIRE
|| material == Material.MAGMA_BLOCK;
}
/**
* Get the start location of a safe teleport search.
* @param player The player to get it for
@@ -455,19 +503,21 @@ public class TeleportFeature extends RegionFeature {
ProtectedRegion worldguardRegion = getRegion().getRegion();
// Try to get sign location
List<RegionSign> signs = getRegion().getSignsFeature().getSigns();
boolean signAvailable = !signs.isEmpty();
Collection<RegionSign> signs = getRegion().getSignsFeature().signManager().allSigns();
if(toSign.get()) {
boolean signAvailable = !signs.isEmpty();
if(signAvailable) {
RegionSign firstSign = signs.iterator().next();
// Use the location 1 below the sign to prevent weird spawing above the sign
startLocation = signs.get(0).getLocation(); //.subtract(0.0, 1.0, 0.0);
startLocation = firstSign.getLocation(); //.subtract(0.0, 1.0, 0.0);
startLocation.setPitch(player.getLocation().getPitch());
startLocation.setYaw(player.getLocation().getYaw());
// Move player x blocks away from the sign
double distance = getRegion().getDoubleSetting("general.teleportSignDistance");
if(distance > 0) {
BlockFace facing = getRegion().getSignsFeature().getSigns().get(0).getFacing();
BlockFace facing = firstSign.getFacing();
Vector facingVector = new Vector(facing.getModX(), facing.getModY(), facing.getModZ())
.normalize()
.multiply(distance);
@@ -490,12 +540,14 @@ public class TeleportFeature extends RegionFeature {
// Calculate a default location
if(startLocation == null) {
// Set to block in the middle, y configured in the config
com.sk89q.worldedit.Vector middle = com.sk89q.worldedit.Vector.getMidpoint(worldguardRegion.getMaximumPoint(), worldguardRegion.getMinimumPoint());
Vector regionMin = worldGuardInterface.getMinimumPoint(worldguardRegion);
Vector regionMax = worldGuardInterface.getMaximumPoint(worldguardRegion);
Vector middle = regionMin.clone().midpoint(regionMax);
String configSetting = getRegion().getStringSetting("general.teleportLocationY");
if("bottom".equalsIgnoreCase(configSetting)) {
middle = middle.setY(worldguardRegion.getMinimumPoint().getBlockY());
middle = middle.setY(regionMin.getBlockY());
} else if("top".equalsIgnoreCase(configSetting)) {
middle = middle.setY(worldguardRegion.getMaximumPoint().getBlockY());
middle = middle.setY(regionMax.getBlockY());
} else if("middle".equalsIgnoreCase(configSetting)) {
middle = middle.setY(middle.getBlockY());
} else {
@@ -8,17 +8,31 @@ import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.events.notify.UpdateRegionEvent;
import me.wiefferink.areashop.interfaces.RegionAccessSet;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.interactivemessenger.processing.Message;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.EventHandler;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
@Singleton
public class WorldGuardRegionFlagsFeature extends RegionFeature {
@Inject
private WorldGuardInterface worldGuardInterface;
@Inject
private WorldGuardPlugin worldGuard;
@Inject
WorldGuardRegionFlagsFeature(@Nonnull AreaShop plugin) {
super(plugin);
}
@EventHandler
public void regionUpdate(UpdateRegionEvent event) {
@@ -42,7 +56,7 @@ public class WorldGuardRegionFlagsFeature extends RegionFeature {
// Region flags for all states
ConfigurationSection allFlags = flagProfileSection.getConfigurationSection("ALL");
if(allFlags != null) {
result = result && updateRegionFlags(region, allFlags);
result = updateRegionFlags(region, allFlags);
}
// Region flags for the current state
@@ -52,9 +66,8 @@ public class WorldGuardRegionFlagsFeature extends RegionFeature {
if(stateFlags == null && region.getState() == GeneralRegion.RegionState.RESELL) {
stateFlags = flagProfileSection.getConfigurationSection("resale");
}
if(stateFlags != null) {
result = result && updateRegionFlags(region, stateFlags);
result &= updateRegionFlags(region, stateFlags);
}
return result;
@@ -70,7 +83,6 @@ public class WorldGuardRegionFlagsFeature extends RegionFeature {
boolean result = true;
Set<String> flagNames = flags.getKeys(false);
WorldGuardPlugin worldGuard = plugin.getWorldGuard();
// Get the region
ProtectedRegion worldguardRegion = region.getRegion();
@@ -82,14 +94,14 @@ public class WorldGuardRegionFlagsFeature extends RegionFeature {
for(String flagName : flagNames) {
String value = Message.fromString(flags.getString(flagName)).replacements(region).getPlain();
// In the config normal Bukkit color codes are used, those only need to be translated on 5.X WorldGuard versions
if(plugin.getWorldGuard().getDescription().getVersion().startsWith("5.")) {
if(worldGuard.getDescription().getVersion().startsWith("5.")) {
value = translateBukkitToWorldGuardColors(value);
}
if(flagName.equalsIgnoreCase("members")) {
plugin.getWorldGuardHandler().setMembers(worldguardRegion, parseAccessSet(value));
worldGuardInterface.setMembers(worldguardRegion, parseAccessSet(value));
//AreaShop.debug(" Flag " + flagName + " set: " + members.toUserFriendlyString());
} else if(flagName.equalsIgnoreCase("owners")) {
plugin.getWorldGuardHandler().setOwners(worldguardRegion, parseAccessSet(value));
worldGuardInterface.setOwners(worldguardRegion, parseAccessSet(value));
//AreaShop.debug(" Flag " + flagName + " set: " + owners.toUserFriendlyString());
} else if(flagName.equalsIgnoreCase("priority")) {
try {
@@ -124,7 +136,7 @@ public class WorldGuardRegionFlagsFeature extends RegionFeature {
String flagSetting = null;
com.sk89q.worldguard.protection.flags.RegionGroup groupValue = null;
Flag<?> foundFlag = plugin.getWorldGuardHandler().fuzzyMatchFlag(flagName);
Flag<?> foundFlag = worldGuardInterface.fuzzyMatchFlag(flagName);
if(foundFlag == null) {
AreaShop.warn("Found wrong flag in flagProfiles section: " + flagName + ", check if that is the correct WorldGuard flag");
continue;
@@ -146,7 +158,7 @@ public class WorldGuardRegionFlagsFeature extends RegionFeature {
if(part.startsWith("g:")) {
if(part.length() > 2) {
try {
groupValue = plugin.getWorldGuardHandler().parseFlagGroupInput(groupFlag, part.substring(2));
groupValue = worldGuardInterface.parseFlagGroupInput(groupFlag, part.substring(2));
} catch(InvalidFlagFormat e) {
AreaShop.warn("Found wrong group value for flag " + flagName);
}
@@ -230,7 +242,7 @@ public class WorldGuardRegionFlagsFeature extends RegionFeature {
*/
private <V> void setFlag(ProtectedRegion region, Flag<V> flag, String value) throws InvalidFlagFormat {
V current = region.getFlag(flag);
V next = plugin.getWorldGuardHandler().parseFlagInput(flag, value);
V next = worldGuardInterface.parseFlagInput(flag, value);
if(!Objects.equals(current, next)) {
region.setFlag(flag, next);
@@ -1,8 +1,16 @@
package me.wiefferink.areashop.features.signs;
import com.google.common.base.Objects;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import io.github.bakedlibs.dough.blocks.BlockPosition;
import io.papermc.lib.PaperLib;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.managers.SignErrorLogger;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.SignUtils;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.interactivemessenger.processing.Message;
import org.bukkit.Bukkit;
@@ -10,11 +18,15 @@ import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.Sign;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.WallSign;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
@@ -23,14 +35,30 @@ import java.util.List;
*/
public class RegionSign {
private final BlockBehaviourHelper blockHelper;
private final SignErrorLogger errorLogger;
private final SignsFeature signsFeature;
private final String key;
public RegionSign(SignsFeature signsFeature, String key) {
@AssistedInject
RegionSign(
@Nonnull BlockBehaviourHelper blockBehaviourHelper,
@Nonnull SignErrorLogger signErrorLogger,
@Assisted @Nonnull SignsFeature signsFeature,
@Assisted @Nonnull String key
) {
this.blockHelper = blockBehaviourHelper;
this.errorLogger = signErrorLogger;
this.signsFeature = signsFeature;
this.key = key;
}
public BlockPosition getPosition() {
return new BlockPosition(getLocation());
}
/**
* Get the location of this sign.
* @return The location of this sign
@@ -67,11 +95,13 @@ public class RegionSign {
* Remove this sign from the region.
*/
public void remove() {
getLocation().getBlock().setType(Material.AIR);
signsFeature.getSignsRef().remove(getStringLocation());
SignsFeature.getAllSigns().remove(getStringLocation());
SignsFeature.getSignsByChunk().get(getStringChunk()).remove(this);
Location location = getLocation();
if (location != null && location.getWorld() != null) {
location.getBlock().setType(Material.AIR);
this.signsFeature.signManager().removeSign(this);
}
getRegion().setSetting("general.signs." + key, null);
// Remove the sign from the region's sign manager
}
/**
@@ -83,7 +113,7 @@ public class RegionSign {
}
/**
* Get the facing of the sign.
* Get the facing of the sign as saved in the config.
* @return BlockFace the sign faces, or null if unknown
*/
public BlockFace getFacing() {
@@ -95,15 +125,13 @@ public class RegionSign {
}
/**
* Get the material of the sign
* @return Material of the sign, normally {@link Material#WALL_SIGN} or {@link Material#SIGN_POST}, but could be something else or null.
* Get the material of the sign as saved in the config.
* @return Material of the sign,Material.AIR if none.
*/
public Material getMaterial() {
try {
return Material.valueOf(getRegion().getConfig().getString("general.signs." + key + ".signType"));
} catch(NullPointerException | IllegalArgumentException e) {
return null;
}
String name = getRegion().getConfig().getString("general.signs." + key + ".signType");
Material result = Materials.signNameToMaterial(name);
return result == null ? Material.AIR : result;
}
/**
@@ -145,37 +173,47 @@ public class RegionSign {
return true;
}
Sign signState = null;
// Place the sign back (with proper rotation and type) after it has been hidden or (indirectly) destroyed
if(block.getType() != Material.WALL_SIGN && block.getType() != Material.SIGN_POST) {
if(!Materials.isSign(block.getType())) {
Material signType = getMaterial();
if(signType != Material.WALL_SIGN && signType != Material.SIGN_POST) {
AreaShop.debug("Setting sign", key, "of region", getRegion().getName(), "failed, could not set sign block back");
if (!blockHelper.canPlace(block.getLocation(), Bukkit.createBlockData(signType))) {
errorLogger.submitWarning("Setting sign" + key + "of region" + getRegion().getName() + "failed, could not set sign block back");
this.remove();
return false;
}
block.setType(signType);
signState = (Sign)block.getState();
org.bukkit.material.Sign signData = (org.bukkit.material.Sign)signState.getData();
BlockFace signFace = getFacing();
if(signFace != null) {
signData.setFacingDirection(signFace);
signState.setData(signData);
// Don't do physics here, we first need to update the direction
block.setType(signType, false);
BlockState blockState = PaperLib.getBlockState(block, false).getState();
BlockData blockData = blockState.getBlockData();
if(blockData instanceof WallSign) {
((WallSign) blockData).setFacing(getFacing());
} else if(blockData instanceof org.bukkit.block.data.type.Sign) {
((org.bukkit.block.data.type.Sign) blockData).setRotation(getFacing());
} else {
errorLogger.submitWarning("Failed to update the facing direction of the sign at" + getStringLocation() + "to " + getFacing() + ", region:" + getRegion().getName());
return false;
}
block.setBlockData(blockData);
// Check if the sign has popped
if(!Materials.isSign(block.getType())) {
return false;
}
}
if(signState == null) {
signState = (Sign)block.getState();
}
// Save current rotation and type
org.bukkit.material.Sign signData = (org.bukkit.material.Sign)signState.getData();
if(!regionConfig.isString("general.signs." + key + ".signType")) {
getRegion().setSetting("general.signs." + key + ".signType", signState.getType().toString());
getRegion().setSetting("general.signs." + key + ".signType", block.getType().name());
}
if(!regionConfig.isString("general.signs." + key + ".facing")) {
getRegion().setSetting("general.signs." + key + ".facing", signData.getFacing().toString());
BlockFace signFacing = SignUtils.getSignFacing(block);
getRegion().setSetting("general.signs." + key + ".facing", signFacing == null ? null : signFacing.toString());
}
// Apply replacements and color and then set it on the sign
Sign signState = (Sign) PaperLib.getBlockState(block, false).getState();
for(int i = 0; i < signLines.length; i++) {
if(signLines[i] == null) {
signState.setLine(i, "");
@@ -185,7 +223,7 @@ public class RegionSign {
signLines[i] = Utils.applyColors(signLines[i]);
signState.setLine(i, signLines[i]);
}
signState.update();
signState.update(false, false);
return true;
}
@@ -198,11 +236,16 @@ public class RegionSign {
if(signConfig == null || !signConfig.isSet(getRegion().getState().getValue().toLowerCase())) {
return false;
}
ConfigurationSection stateConfig = signConfig.getConfigurationSection(getRegion().getState().getValue().toLowerCase());
if(stateConfig == null) {
return false;
}
// Check the lines for the timeleft tag
for(int i = 1; i <= 4; i++) {
String line = stateConfig.getString("line" + i);
if(line != null && !line.isEmpty() && line.contains(Message.VARIABLE_START + AreaShop.tagTimeLeft + Message.VARIABLE_END)) {
if(line != null && line.contains(Message.VARIABLE_START + AreaShop.tagTimeLeft + Message.VARIABLE_END)) {
return true;
}
}
@@ -0,0 +1,81 @@
package me.wiefferink.areashop.features.signs;
import io.github.bakedlibs.dough.blocks.BlockPosition;
import io.github.bakedlibs.dough.blocks.ChunkPosition;
import org.bukkit.Location;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
public class SignCache {
private final Map<Long, RegionSign> allSigns = new HashMap<>();
private final Map<Long, Collection<RegionSign>> signsByChunk = new HashMap<>();
public Optional<RegionSign> signAtLocation(long position) {
return Optional.ofNullable(this.allSigns.get(position));
}
public Collection<RegionSign> signsAtChunk(long position) {
return Collections.unmodifiableCollection(this.signsByChunk.getOrDefault(position, Collections.emptyList()));
}
public Collection<RegionSign> allSigns() {
return Collections.unmodifiableCollection(this.allSigns.values());
}
public Collection<BlockPosition> allSignLocations() {
Collection<BlockPosition> positions = new ArrayList<>(this.signsByChunk.size());
for (RegionSign sign : this.allSigns.values()) {
positions.add(sign.getPosition());
}
return positions;
}
public void addSign(RegionSign regionSign) {
BlockPosition blockPosition = regionSign.getPosition();
this.allSigns.put(blockPosition.getPosition(), regionSign);
ChunkPosition chunkPosition = new ChunkPosition(blockPosition.getChunk());
Collection<RegionSign> signs = this.signsByChunk.computeIfAbsent(chunkPosition.getPosition(), x -> new HashSet<>());
signs.add(regionSign);
}
public Optional<RegionSign> removeSign(Location location) {
return removeSign(new BlockPosition(location));
}
public Optional<RegionSign> removeSign(BlockPosition position) {
RegionSign removed = this.allSigns.remove(position.getPosition());
if (removed != null) {
Location location = position.toLocation();
this.signsByChunk.remove(new ChunkPosition(location).getPosition());
// Remove the sign from the region
}
return Optional.ofNullable(removed);
}
public void removeSign(RegionSign regionSign) {
BlockPosition blockPosition = regionSign.getPosition();
this.allSigns.remove(blockPosition.getPosition());
ChunkPosition chunkPosition = new ChunkPosition(blockPosition.getChunk());
long packedChunkPos = chunkPosition.getPosition();
Collection<RegionSign> signs = this.signsByChunk.get(packedChunkPos);
if (signs != null) {
signs.remove(regionSign);
if (signs.isEmpty()) {
this.signsByChunk.remove(packedChunkPos);
}
}
}
public void clear() {
this.allSigns.clear();
this.signsByChunk.clear();
}
}
@@ -0,0 +1,10 @@
package me.wiefferink.areashop.features.signs;
import javax.annotation.Nonnull;
public interface SignFactory {
@Nonnull RegionSign createRegionSign(@Nonnull SignsFeature signsFeature, @Nonnull String key);
}
@@ -0,0 +1,450 @@
package me.wiefferink.areashop.features.signs;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import io.github.bakedlibs.dough.blocks.ChunkPosition;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
import me.wiefferink.areashop.events.notify.UpdateRegionEvent;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.SignLinkerManager;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionFactory;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.SignUtils;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.bukkitdo.Do;
import org.bukkit.Chunk;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Optional;
import java.util.Set;
public class SignListener implements Listener {
private final BlockBehaviourHelper behaviourHelper;
private final AreaShop plugin;
private final MessageBridge messageBridge;
private final SignManager signManager;
private final SignLinkerManager signLinkerManager;
private final WorldGuardInterface worldGuardInterface;
private final RegionFactory regionFactory;
private final IFileManager fileManager;
public SignListener(
@Nonnull AreaShop plugin,
@Nonnull BlockBehaviourHelper behaviourHelper,
@Nonnull RegionFactory regionFactory,
@Nonnull MessageBridge messageBridge,
@Nonnull SignLinkerManager signLinkerManager,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull SignManager signManager,
@Nonnull IFileManager fileManager) {
this.fileManager = fileManager;
this.signManager = signManager;
this.signLinkerManager = signLinkerManager;
this.regionFactory = regionFactory;
this.behaviourHelper = behaviourHelper;
this.plugin = plugin;
this.worldGuardInterface = worldGuardInterface;
this.messageBridge = messageBridge;
}
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
public void regionUpdate(UpdateRegionEvent event) {
Optional<SignsFeature> signsFeature = event.getRegion().getFeature(SignsFeature.class);
signsFeature.map(SignsFeature::signManager).ifPresent(SignManager::update);
}
@EventHandler(priority = EventPriority.MONITOR)
public void onChunkLoad(ChunkLoadEvent event) {
Chunk chunk = event.getChunk();
Optional<SignCache> optional = this.signManager.getCacheForWorld(chunk.getWorld());
if (optional.isEmpty()) {
return;
}
final SignCache signCache = optional.get();
Collection<RegionSign> chunkSigns = new ArrayList<>(signCache.signsAtChunk(ChunkPosition.getAsLong(chunk.getX(), chunk.getZ())));
if(chunkSigns.isEmpty()) {
return;
}
Do.forAll(chunkSigns, RegionSign::update);
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onIndirectSignBreak(BlockPhysicsEvent event) {
// Check if the block is a sign
if(!Materials.isSign(event.getBlock().getType()) || behaviourHelper.isBlockValid(event.getBlock())) {
return;
}
// Check if the sign is really the same as a saved rent
final Optional<RegionSign> optionalSign = this.signManager.signFromLocation(event.getBlock().getLocation());
if(optionalSign.isEmpty()) {
return;
}
RegionSign regionSign = optionalSign.get();
// Remove the sign so that it does not fall on the floor as an item (next region update will place it back when possible)
AreaShop.debug("onIndirectSignBreak: Removed block of sign for", regionSign.getRegion().getName(), "at", regionSign.getStringLocation());
event.getBlock().setType(Material.AIR);
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.HIGH)
public void onSignBreak(BlockBreakEvent event) {
if(event.isCancelled()) {
return;
}
Block block = event.getBlock();
// Check if it is a sign
if(Materials.isSign(block.getType())) {
// Check if the rent sign is really the same as a saved rent
Optional<RegionSign> optional = signManager.signFromLocation(block.getLocation());
if(optional.isEmpty()) {
return;
}
RegionSign regionSign = optional.get();
// Remove the sign of the rental region if the player has permission
if(event.getPlayer().hasPermission("areashop.delsign")) {
signManager.removeSign(regionSign);
messageBridge.message(event.getPlayer(), "delsign-success", regionSign.getRegion());
} else { // Cancel the breaking of the sign
event.setCancelled(true);
messageBridge.message(event.getPlayer(), "delsign-noPermission", regionSign.getRegion());
}
}
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
public void onSignClick(PlayerInteractEvent event) {
Block block = event.getClickedBlock();
if (block == null) {
return;
}
// Only listen to left and right clicks on blocks
if (!(event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK)) {
return;
}
// Only care about clicking blocks
if(!Materials.isSign(block.getType())) {
return;
}
// Check if this sign belongs to a region
Optional<RegionSign> optional = signManager.signFromLocation(block.getLocation());
if(optional.isEmpty()) {
return;
}
RegionSign regionSign = optional.get();
// Ignore players that are in sign link mode (which will handle the event itself)
Player player = event.getPlayer();
if(signLinkerManager.isInSignLinkMode(player)) {
return;
}
// Get the clicktype
GeneralRegion.ClickType clickType = null;
if(player.isSneaking() && event.getAction() == Action.LEFT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.SHIFTLEFTCLICK;
} else if(!player.isSneaking() && event.getAction() == Action.LEFT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.LEFTCLICK;
} else if(player.isSneaking() && event.getAction() == Action.RIGHT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.SHIFTRIGHTCLICK;
} else if(!player.isSneaking() && event.getAction() == Action.RIGHT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.RIGHTCLICK;
}
boolean ran = regionSign.runSignCommands(player, clickType);
// Only cancel event if at least one command has been executed
event.setCancelled(ran);
}
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onSignChange(SignChangeEvent event) {
Player player = event.getPlayer();
if(!plugin.isReady()) {
messageBridge.message(player, "general-notReady");
return;
}
// Check if the sign is meant for this plugin
if(event.getLine(0).contains(plugin.getConfig().getString("signTags.rent"))) {
if(!player.hasPermission("areashop.createrent") && !player.hasPermission("areashop.createrent.member") && !player.hasPermission("areashop.createrent.owner")) {
messageBridge.message(player, "setup-noPermissionRent");
return;
}
// Get the other lines
String secondLine = event.getLine(1);
String thirdLine = event.getLine(2);
String fourthLine = event.getLine(3);
// Get the regionManager for accessing regions
RegionManager regionManager = plugin.getRegionManager(event.getPlayer().getWorld());
// If the secondLine does not contain a name try to find the region by location
if(secondLine == null || secondLine.isEmpty()) {
Set<ProtectedRegion> regions = worldGuardInterface.getApplicableRegionsSet(event.getBlock().getLocation());
if(regions != null) {
boolean first = true;
ProtectedRegion candidate = null;
for(ProtectedRegion pr : regions) {
if(first) {
candidate = pr;
first = false;
} else {
if(pr.getPriority() > candidate.getPriority()) {
candidate = pr;
} else if(pr.getParent() != null && pr.getParent().equals(candidate)) {
candidate = pr;
} else {
messageBridge.message(player, "setup-couldNotDetect", candidate.getId(), pr.getId());
return;
}
}
}
if(candidate != null) {
secondLine = candidate.getId();
}
}
}
boolean priceSet = fourthLine != null && !fourthLine.isEmpty();
boolean durationSet = thirdLine != null && !thirdLine.isEmpty();
// check if all the lines are correct
if(secondLine == null || secondLine.isEmpty()) {
messageBridge.message(player, "setup-noRegion");
return;
}
ProtectedRegion region = regionManager.getRegion(secondLine);
if(region == null) {
messageBridge.message(player, "cmd-noRegion", secondLine);
return;
}
IFileManager.AddResult addResult = fileManager.checkRegionAdd(player, regionManager.getRegion(secondLine), event.getPlayer().getWorld(), GeneralRegion.RegionType.RENT);
if(addResult == IFileManager.AddResult.BLACKLISTED) {
messageBridge.message(player, "setup-blacklisted", secondLine);
} else if(addResult == IFileManager.AddResult.ALREADYADDED) {
messageBridge.message(player, "setup-alreadyRentSign");
} else if(addResult == IFileManager.AddResult.ALREADYADDEDOTHERWORLD) {
messageBridge.message(player, "setup-alreadyOtherWorld");
} else if(addResult == IFileManager.AddResult.NOPERMISSION) {
messageBridge.message(player, "setup-noPermission", secondLine);
} else if(thirdLine != null && !thirdLine.isEmpty() && !Utils.checkTimeFormat(thirdLine)) {
messageBridge.message(player, "setup-wrongDuration");
} else {
double price = 0.0;
if(priceSet) {
// Check the fourth line
try {
price = Double.parseDouble(fourthLine);
} catch(NumberFormatException e) {
messageBridge.message(player, "setup-wrongPrice");
return;
}
}
// Add rent to the FileManager
final RentRegion rent = regionFactory.createRentRegion(secondLine, event.getPlayer().getWorld());
boolean isMember = worldGuardInterface.containsMember(rent.getRegion(), player.getUniqueId());
boolean isOwner = worldGuardInterface.containsOwner(rent.getRegion(), player.getUniqueId());
boolean landlord = (!player.hasPermission("areashop.createrent")
&& ((player.hasPermission("areashop.createrent.owner") && isOwner)
|| (player.hasPermission("areashop.createrent.member") && isMember)));
if(landlord) {
rent.setLandlord(player.getUniqueId(), player.getName());
}
if(priceSet) {
rent.setPrice(price);
}
if(durationSet) {
rent.setDuration(thirdLine);
}
rent.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), SignUtils.getSignFacing(event.getBlock()), null);
AddingRegionEvent addingRegionEvent = plugin.getFileManager().addRegion(rent);
if (addingRegionEvent.isCancelled()) {
messageBridge.message(player, "general-cancelled", addingRegionEvent.getReason());
return;
}
rent.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
messageBridge.message(player, "setup-rentSuccess", rent);
// Update the region after the event has written its lines
Do.sync(rent::update);
}
} else if(event.getLine(0).contains(plugin.getConfig().getString("signTags.buy"))) {
// Check for permission
if(!player.hasPermission("areashop.createbuy") && !player.hasPermission("areashop.createbuy.member") && !player.hasPermission("areashop.createbuy.owner")) {
messageBridge.message(player, "setup-noPermissionBuy");
return;
}
// Get the other lines
String secondLine = event.getLine(1);
String thirdLine = event.getLine(2);
// Get the regionManager for accessing regions
RegionManager regionManager = plugin.getRegionManager(event.getPlayer().getWorld());
// If the secondLine does not contain a name try to find the region by location
if(secondLine == null || secondLine.isEmpty()) {
Set<ProtectedRegion> regions = worldGuardInterface.getApplicableRegionsSet(event.getBlock().getLocation());
if(regions != null) {
boolean first = true;
ProtectedRegion candidate = null;
for(ProtectedRegion pr : regions) {
if(first) {
candidate = pr;
first = false;
} else {
if(pr.getPriority() > candidate.getPriority()) {
candidate = pr;
} else if(pr.getParent() != null && pr.getParent().equals(candidate)) {
candidate = pr;
} else {
messageBridge.message(player, "setup-couldNotDetect", candidate.getId(), pr.getId());
return;
}
}
}
if(candidate != null) {
secondLine = candidate.getId();
}
}
}
boolean priceSet = thirdLine != null && !thirdLine.isEmpty();
// Check if all the lines are correct
if(secondLine == null || secondLine.isEmpty()) {
messageBridge.message(player, "setup-noRegion");
return;
}
ProtectedRegion region = regionManager.getRegion(secondLine);
if(region == null) {
messageBridge.message(player, "cmd-noRegion", secondLine);
return;
}
IFileManager.AddResult addResult = plugin.getFileManager().checkRegionAdd(player, region, event.getPlayer().getWorld(), GeneralRegion.RegionType.BUY);
if(addResult == IFileManager.AddResult.BLACKLISTED) {
messageBridge.message(player, "setup-blacklisted", secondLine);
} else if(addResult == IFileManager.AddResult.ALREADYADDED) {
messageBridge.message(player, "setup-alreadyRentSign");
} else if(addResult == IFileManager.AddResult.ALREADYADDEDOTHERWORLD) {
messageBridge.message(player, "setup-alreadyOtherWorld");
} else if(addResult == IFileManager.AddResult.NOPERMISSION) {
messageBridge.message(player, "setup-noPermission", secondLine);
} else {
double price = 0.0;
if(priceSet) {
// Check the fourth line
try {
price = Double.parseDouble(thirdLine);
} catch(NumberFormatException e) {
messageBridge.message(player, "setup-wrongPrice");
return;
}
}
// Add buy to the FileManager
final BuyRegion buy = regionFactory.createBuyRegion(secondLine, event.getPlayer().getWorld());
boolean isMember = worldGuardInterface.containsMember(buy.getRegion(), player.getUniqueId());
boolean isOwner = worldGuardInterface.containsOwner(buy.getRegion(), player.getUniqueId());
boolean landlord = (!player.hasPermission("areashop.createbuy")
&& ((player.hasPermission("areashop.createbuy.owner") && isOwner)
|| (player.hasPermission("areashop.createbuy.member") && isMember)));
if(landlord) {
buy.setLandlord(player.getUniqueId(), player.getName());
}
if(priceSet) {
buy.setPrice(price);
}
buy.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), SignUtils.getSignFacing(event.getBlock()), null);
AddingRegionEvent addingRegionEvent = plugin.getFileManager().addRegion(buy);
if (addingRegionEvent.isCancelled()) {
messageBridge.message(player, "general-cancelled", addingRegionEvent.getReason());
return;
}
buy.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
messageBridge.message(player, "setup-buySuccess", buy);
// Update the region after the event has written its lines
Do.sync(buy::update);
}
} else if(event.getLine(0).contains(plugin.getConfig().getString("signTags.add"))) {
// Check for permission
if(!player.hasPermission("areashop.addsign")) {
messageBridge.message(player, "addsign-noPermission");
return;
}
// Get the other lines
String secondLine = event.getLine(1);
String thirdLine = event.getLine(2);
GeneralRegion region;
if(secondLine != null && !secondLine.isEmpty()) {
// Get region by secondLine of the sign
region = fileManager.getRegion(secondLine);
if(region == null) {
messageBridge.message(player, "addSign-notRegistered", secondLine);
return;
}
} else {
// Get region by sign position
List<GeneralRegion> regions = Utils.getImportantRegions(event.getBlock().getLocation());
if(regions.isEmpty()) {
messageBridge.message(player, "addsign-noRegions");
return;
} else if(regions.size() > 1) {
messageBridge.message(player, "addsign-couldNotDetectSign", regions.get(0).getName(), regions.get(1).getName());
return;
}
region = regions.get(0);
}
if(thirdLine == null || thirdLine.isEmpty()) {
region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), SignUtils.getSignFacing(event.getBlock()), null);
messageBridge.message(player, "addsign-success", region);
} else {
region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), SignUtils.getSignFacing(event.getBlock()), thirdLine);
messageBridge.message(player, "addsign-successProfile", thirdLine, region);
}
// Update the region later because this event will do it first
Do.sync(region::update);
}
}
}
@@ -0,0 +1,109 @@
package me.wiefferink.areashop.features.signs;
import io.github.bakedlibs.dough.blocks.BlockPosition;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.managers.Manager;
import org.bukkit.Location;
import org.bukkit.World;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
public class SignManager extends Manager {
private final Map<World, SignCache> signCacheMap = new HashMap<>();
public Collection<BlockPosition> allSignLocations() {
final Set<BlockPosition> set = new HashSet<>(signCacheMap.size());
for (SignCache signCache : signCacheMap.values()) {
set.addAll(signCache.allSignLocations());
}
return set;
}
public Collection<RegionSign> allSigns() {
final Set<RegionSign> signs = new HashSet<>(signCacheMap.size());
for (SignCache signCache : signCacheMap.values()) {
signs.addAll(signCache.allSigns());
}
return signs;
}
public SignCache cacheForWorld(World world) {
return this.signCacheMap.computeIfAbsent(world, x -> new SignCache());
}
public Optional<SignCache> getCacheForWorld(World world) {
return Optional.ofNullable(this.signCacheMap.get(world));
}
public Optional<RegionSign> signFromLocation(Location location) {
final World world = location.getWorld();
return getCacheForWorld(world)
.flatMap(cache -> cache.signAtLocation(BlockPosition.getAsLong(location)));
}
public void addSign(RegionSign regionSign) {
Location location = regionSign.getLocation();
cacheForWorld(location.getWorld()).addSign(regionSign);
}
public void removeSign(RegionSign regionSign) {
Location location = regionSign.getLocation();
if (location.getWorld() == null) {
return;
}
cacheForWorld(location.getWorld()).removeSign(regionSign);
}
public Optional<RegionSign> removeSign(Location location) {
if (location == null || location.getWorld() == null) {
return Optional.empty();
}
return getCacheForWorld(location.getWorld()).flatMap(cache -> cache.removeSign(location));
}
/**
* Update all signs connected to this region.
* @return true if all signs are updated correctly, false if one or more updates failed
*/
public boolean update() {
boolean result = true;
for (SignCache signCache : this.signCacheMap.values())
for(RegionSign sign : signCache.allSigns()) {
result &= sign.update();
}
return result;
}
/**
* Check if any of the signs need periodic updating.
* @return true if one or more of the signs need periodic updating, otherwise false
*/
public boolean needsPeriodicUpdate() {
boolean result = false;
for (SignCache signCache : this.signCacheMap.values()) {
for (RegionSign sign : signCache.allSigns()) {
if (result) {
break;
}
if (sign.needsPeriodicUpdate()) {
result = true;
break;
}
}
}
return result;
}
public void shutdown() {
this.signCacheMap.values().forEach(SignCache::clear);
this.signCacheMap.clear();
}
}
@@ -1,428 +1,55 @@
package me.wiefferink.areashop.features.signs;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import io.github.bakedlibs.dough.blocks.BlockPosition;
import io.github.bakedlibs.dough.blocks.ChunkPosition;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.events.notify.UpdateRegionEvent;
import me.wiefferink.areashop.features.RegionFeature;
import me.wiefferink.areashop.managers.FileManager;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.bukkitdo.Do;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.SignChangeEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.world.ChunkLoadEvent;
import java.util.ArrayList;
import java.util.Collections;
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class SignsFeature extends RegionFeature {
private static final Map<String, RegionSign> allSigns = Collections.synchronizedMap(new HashMap<>());
private static final Map<String, List<RegionSign>> signsByChunk = Collections.synchronizedMap(new HashMap<>());
private Map<String, RegionSign> signs;
public SignsFeature() {
}
private final SignManager internalSignManager = new SignManager();
private final SignManager globalSignManager;
private final SignFactory signFactory;
/**
* Constructor.
* @param region The region to bind to
*/
public SignsFeature(GeneralRegion region) {
@AssistedInject
SignsFeature(@Nonnull AreaShop plugin,
@Nonnull SignManager signManager,
@Nonnull SignFactory signFactory,
@Assisted @Nonnull GeneralRegion region
) {
super(plugin);
this.globalSignManager = signManager;
this.signFactory = signFactory;
setRegion(region);
signs = new HashMap<>();
// Setup current signs
ConfigurationSection signSection = region.getConfig().getConfigurationSection("general.signs");
if(signSection != null) {
for(String signKey : signSection.getKeys(false)) {
RegionSign sign = new RegionSign(this, signKey);
Location location = sign.getLocation();
if(location == null) {
AreaShop.warn("Sign with key " + signKey + " of region " + region.getName() + " does not have a proper location");
continue;
}
signs.put(sign.getStringLocation(), sign);
signsByChunk.computeIfAbsent(sign.getStringChunk(), key -> new ArrayList<>())
.add(sign);
}
allSigns.putAll(signs);
}
}
@Override
public void shutdown() {
// Deregister signs from the registry
if(signs != null) {
for(Map.Entry<String, RegionSign> entry : signs.entrySet()) {
allSigns.remove(entry.getKey());
signsByChunk.get(entry.getValue().getStringChunk()).remove(entry.getValue());
}
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onSignBreak(BlockBreakEvent event) {
if(event.isCancelled()) {
if (signSection == null) {
return;
}
Block block = event.getBlock();
// Check if it is a sign
if(block.getType() == Material.WALL_SIGN || block.getType() == Material.SIGN_POST) {
// Check if the rent sign is really the same as a saved rent
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if(regionSign == null) {
return;
for(String signKey : signSection.getKeys(false)) {
RegionSign sign = signFactory.createRegionSign(this, signKey);
Location location = sign.getLocation();
if(location == null) {
AreaShop.warn("Sign with key " + signKey + " of region " + region.getName() + " does not have a proper location");
continue;
}
// Remove the sign of the rental region if the player has permission
if(event.getPlayer().hasPermission("areashop.delsign")) {
regionSign.remove();
plugin.message(event.getPlayer(), "delsign-success", regionSign.getRegion());
} else { // Cancel the breaking of the sign
event.setCancelled(true);
plugin.message(event.getPlayer(), "delsign-noPermission", regionSign.getRegion());
}
}
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onIndirectSignBreak(BlockPhysicsEvent event) {
if(event.getBlock().getType() == Material.SIGN_POST || event.getBlock().getType() == Material.WALL_SIGN) {
// Check if the rent sign is really the same as a saved rent
if(SignsFeature.getSignByLocation(event.getBlock().getLocation()) != null) {
// Cancel the sign breaking, will create a floating sign but at least it is not disconnected/gone
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onSignClick(PlayerInteractEvent event) {
if(event.isCancelled()) {
return;
}
Block block = event.getClickedBlock();
// Check for clicking a sign and rightclicking
if((event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK)
&& (block.getType() == Material.SIGN_POST || block.getType() == Material.WALL_SIGN)) {
// Check if the rent sign is really the same as a saved rent
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if(regionSign == null) {
return;
}
Player player = event.getPlayer();
if(plugin.getSignlinkerManager().isInSignLinkMode(player)) {
return;
}
// Get the clicktype
GeneralRegion.ClickType clickType = null;
if(player.isSneaking() && event.getAction() == Action.LEFT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.SHIFTLEFTCLICK;
} else if(!player.isSneaking() && event.getAction() == Action.LEFT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.LEFTCLICK;
} else if(player.isSneaking() && event.getAction() == Action.RIGHT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.SHIFTRIGHTCLICK;
} else if(!player.isSneaking() && event.getAction() == Action.RIGHT_CLICK_BLOCK) {
clickType = GeneralRegion.ClickType.RIGHTCLICK;
}
// Run the commands
boolean ran = regionSign.runSignCommands(player, clickType);
// Only cancel event if at least one command has been executed
event.setCancelled(ran);
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onSignChange(SignChangeEvent event) {
if(event.isCancelled()) {
return;
}
Player player = event.getPlayer();
if(!plugin.isReady()) {
plugin.message(player, "general-notReady");
return;
}
// Check if the sign is meant for this plugin
if(event.getLine(0).contains(plugin.getConfig().getString("signTags.rent"))) {
if(!player.hasPermission("areashop.createrent") && !player.hasPermission("areashop.createrent.member") && !player.hasPermission("areashop.createrent.owner")) {
plugin.message(player, "setup-noPermissionRent");
return;
}
// Get the other lines
String secondLine = event.getLine(1);
String thirdLine = event.getLine(2);
String fourthLine = event.getLine(3);
// Get the regionManager for accessing regions
RegionManager regionManager = plugin.getRegionManager(event.getPlayer().getWorld());
// If the secondLine does not contain a name try to find the region by location
if(secondLine == null || secondLine.length() == 0) {
Set<ProtectedRegion> regions = plugin.getWorldGuardHandler().getApplicableRegionsSet(event.getBlock().getLocation());
if(regions != null) {
boolean first = true;
ProtectedRegion candidate = null;
for(ProtectedRegion pr : regions) {
if(first) {
candidate = pr;
first = false;
} else {
if(pr.getPriority() > candidate.getPriority()) {
candidate = pr;
} else if(pr.getPriority() < candidate.getPriority()) {
// Already got the correct one
} else if(pr.getParent() != null && pr.getParent().equals(candidate)) {
candidate = pr;
} else if(candidate.getParent() != null && candidate.getParent().equals(pr)) {
// Already got the correct one
} else {
plugin.message(player, "setup-couldNotDetect", candidate.getId(), pr.getId());
return;
}
}
}
if(candidate != null) {
secondLine = candidate.getId();
}
}
}
boolean priceSet = fourthLine != null && fourthLine.length() != 0;
boolean durationSet = thirdLine != null && thirdLine.length() != 0;
// check if all the lines are correct
if(secondLine == null || secondLine.length() == 0) {
plugin.message(player, "setup-noRegion");
return;
}
ProtectedRegion region = regionManager.getRegion(secondLine);
if(region == null) {
plugin.message(player, "cmd-noRegion", secondLine);
return;
}
FileManager.AddResult addResult = plugin.getFileManager().checkRegionAdd(player, regionManager.getRegion(secondLine), event.getPlayer().getWorld(), GeneralRegion.RegionType.RENT);
if(addResult == FileManager.AddResult.BLACKLISTED) {
plugin.message(player, "setup-blacklisted", secondLine);
} else if(addResult == FileManager.AddResult.ALREADYADDED) {
plugin.message(player, "setup-alreadyRentSign");
} else if(addResult == FileManager.AddResult.ALREADYADDEDOTHERWORLD) {
plugin.message(player, "setup-alreadyOtherWorld");
} else if(addResult == FileManager.AddResult.NOPERMISSION) {
plugin.message(player, "setup-noPermission", secondLine);
} else if(thirdLine != null && thirdLine.length() != 0 && !Utils.checkTimeFormat(thirdLine)) {
plugin.message(player, "setup-wrongDuration");
} else {
double price = 0.0;
if(priceSet) {
// Check the fourth line
try {
price = Double.parseDouble(fourthLine);
} catch(NumberFormatException e) {
plugin.message(player, "setup-wrongPrice");
return;
}
}
// Add rent to the FileManager
final RentRegion rent = new RentRegion(secondLine, event.getPlayer().getWorld());
boolean isMember = plugin.getWorldGuardHandler().containsMember(rent.getRegion(), player.getUniqueId());
boolean isOwner = plugin.getWorldGuardHandler().containsOwner(rent.getRegion(), player.getUniqueId());
boolean landlord = (!player.hasPermission("areashop.createrent")
&& ((player.hasPermission("areashop.createrent.owner") && isOwner)
|| (player.hasPermission("areashop.createrent.member") && isMember)));
if(landlord) {
rent.setLandlord(player.getUniqueId(), player.getName());
}
if(priceSet) {
rent.setPrice(price);
}
if(durationSet) {
rent.setDuration(thirdLine);
}
org.bukkit.material.Sign sign = (org.bukkit.material.Sign)event.getBlock().getState().getData();
rent.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), sign.getFacing(), null);
// Run commands
rent.runEventCommands(GeneralRegion.RegionEvent.CREATED, true);
plugin.getFileManager().addRent(rent);
rent.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
plugin.message(player, "setup-rentSuccess", rent);
// Update the region after the event has written its lines
Do.sync(rent::update);
// Run commands
rent.runEventCommands(GeneralRegion.RegionEvent.CREATED, false);
}
} else if(event.getLine(0).contains(plugin.getConfig().getString("signTags.buy"))) {
// Check for permission
if(!player.hasPermission("areashop.createbuy") && !player.hasPermission("areashop.createbuy.member") && !player.hasPermission("areashop.createbuy.owner")) {
plugin.message(player, "setup-noPermissionBuy");
return;
}
// Get the other lines
String secondLine = event.getLine(1);
String thirdLine = event.getLine(2);
// Get the regionManager for accessing regions
RegionManager regionManager = plugin.getRegionManager(event.getPlayer().getWorld());
// If the secondLine does not contain a name try to find the region by location
if(secondLine == null || secondLine.length() == 0) {
Set<ProtectedRegion> regions = plugin.getWorldGuardHandler().getApplicableRegionsSet(event.getBlock().getLocation());
if(regions != null) {
boolean first = true;
ProtectedRegion candidate = null;
for(ProtectedRegion pr : regions) {
if(first) {
candidate = pr;
first = false;
} else {
if(pr.getPriority() > candidate.getPriority()) {
candidate = pr;
} else if(pr.getPriority() < candidate.getPriority()) {
// Already got the correct one
} else if(pr.getParent() != null && pr.getParent().equals(candidate)) {
candidate = pr;
} else if(candidate.getParent() != null && candidate.getParent().equals(pr)) {
// Already got the correct one
} else {
plugin.message(player, "setup-couldNotDetect", candidate.getId(), pr.getId());
return;
}
}
}
if(candidate != null) {
secondLine = candidate.getId();
}
}
}
boolean priceSet = thirdLine != null && thirdLine.length() != 0;
// Check if all the lines are correct
if(secondLine == null || secondLine.length() == 0) {
plugin.message(player, "setup-noRegion");
return;
}
ProtectedRegion region = regionManager.getRegion(secondLine);
if(region == null) {
plugin.message(player, "cmd-noRegion", secondLine);
return;
}
FileManager.AddResult addResult = plugin.getFileManager().checkRegionAdd(player, region, event.getPlayer().getWorld(), GeneralRegion.RegionType.BUY);
if(addResult == FileManager.AddResult.BLACKLISTED) {
plugin.message(player, "setup-blacklisted", secondLine);
} else if(addResult == FileManager.AddResult.ALREADYADDED) {
plugin.message(player, "setup-alreadyRentSign");
} else if(addResult == FileManager.AddResult.ALREADYADDEDOTHERWORLD) {
plugin.message(player, "setup-alreadyOtherWorld");
} else if(addResult == FileManager.AddResult.NOPERMISSION) {
plugin.message(player, "setup-noPermission", secondLine);
} else {
double price = 0.0;
if(priceSet) {
// Check the fourth line
try {
price = Double.parseDouble(thirdLine);
} catch(NumberFormatException e) {
plugin.message(player, "setup-wrongPrice");
return;
}
}
// Add buy to the FileManager
final BuyRegion buy = new BuyRegion(secondLine, event.getPlayer().getWorld());
boolean isMember = plugin.getWorldGuardHandler().containsMember(buy.getRegion(), player.getUniqueId());
boolean isOwner = plugin.getWorldGuardHandler().containsOwner(buy.getRegion(), player.getUniqueId());
boolean landlord = (!player.hasPermission("areashop.createbuy")
&& ((player.hasPermission("areashop.createbuy.owner") && isOwner)
|| (player.hasPermission("areashop.createbuy.member") && isMember)));
if(landlord) {
buy.setLandlord(player.getUniqueId(), player.getName());
}
if(priceSet) {
buy.setPrice(price);
}
org.bukkit.material.Sign sign = (org.bukkit.material.Sign)event.getBlock().getState().getData();
buy.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), sign.getFacing(), null);
// Run commands
buy.runEventCommands(GeneralRegion.RegionEvent.CREATED, true);
plugin.getFileManager().addBuy(buy);
buy.handleSchematicEvent(GeneralRegion.RegionEvent.CREATED);
plugin.message(player, "setup-buySuccess", buy);
// Update the region after the event has written its lines
Do.sync(buy::update);
// Run commands
buy.runEventCommands(GeneralRegion.RegionEvent.CREATED, false);
}
} else if(event.getLine(0).contains(plugin.getConfig().getString("signTags.add"))) {
// Check for permission
if(!player.hasPermission("areashop.addsign")) {
plugin.message(player, "addsign-noPermission");
return;
}
// Get the other lines
String secondLine = event.getLine(1);
String thirdLine = event.getLine(2);
GeneralRegion region;
if(secondLine != null && secondLine.length() != 0) {
// Get region by secondLine of the sign
region = plugin.getFileManager().getRegion(secondLine);
if(region == null) {
plugin.message(player, "addSign-notRegistered", secondLine);
return;
}
} else {
// Get region by sign position
List<GeneralRegion> regions = Utils.getImportantRegions(event.getBlock().getLocation());
if(regions.isEmpty()) {
plugin.message(player, "addsign-noRegions");
return;
} else if(regions.size() > 1) {
plugin.message(player, "addsign-couldNotDetectSign", regions.get(0).getName(), regions.get(1).getName());
return;
}
region = regions.get(0);
}
org.bukkit.material.Sign sign = (org.bukkit.material.Sign)event.getBlock().getState().getData();
if(thirdLine == null || thirdLine.length() == 0) {
region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), sign.getFacing(), null);
plugin.message(player, "addsign-success", region);
} else {
region.getSignsFeature().addSign(event.getBlock().getLocation(), event.getBlock().getType(), sign.getFacing(), thirdLine);
plugin.message(player, "addsign-successProfile", thirdLine, region);
}
// Update the region later because this event will do it first
Do.sync(region::update);
this.globalSignManager.cacheForWorld(location.getWorld()).addSign(sign);
this.internalSignManager.addSign(sign);
}
}
@@ -444,106 +71,13 @@ public class SignsFeature extends RegionFeature {
return location.getWorld().getName() + ";" + (location.getBlockX() >> 4) + ";" + (location.getBlockZ() >> 4);
}
/**
* Convert a chunk to a string to use as map key.
* Use a Location argument to prevent chunk loading!
* @param chunk The location to get the key for
* @return A string to use in a map for a chunk
*/
public static String chunkToString(Chunk chunk) {
return chunk.getWorld().getName() + ";" + chunk.getX() + ";" + chunk.getZ();
@Override
public void shutdown() {
}
/**
* Get a sign by a location.
* @param location The location to get the sign for
* @return The RegionSign that is at the location, or null if none
*/
public static RegionSign getSignByLocation(Location location) {
return allSigns.get(locationToString(location));
}
/**
* Get the map with all signs.
* @return Map with all signs: locationString -&gt; RegionSign
*/
public static Map<String, RegionSign> getAllSigns() {
return allSigns;
}
/**
* Get the map with signs by chunk.
* @return Map with signs by chunk: chunkString -&gt; List&lt;RegionSign&gt;
*/
public static Map<String, List<RegionSign>> getSignsByChunk() {
return signsByChunk;
}
@EventHandler
public void regionUpdate(UpdateRegionEvent event) {
event.getRegion().getSignsFeature().update();
}
@EventHandler(priority = EventPriority.MONITOR)
public void onChunkLoad(ChunkLoadEvent event) {
List<RegionSign> chunkSigns = signsByChunk.get(chunkToString(event.getChunk()));
if(chunkSigns == null) {
return;
}
Do.forAll(chunkSigns, RegionSign::update);
}
/**
* Update all signs connected to this region.
* @return true if all signs are updated correctly, false if one or more updates failed
*/
public boolean update() {
boolean result = true;
for(RegionSign sign : signs.values()) {
result = result & sign.update();
}
return result;
}
/**
* Check if any of the signs need periodic updating.
* @return true if one or more of the signs need periodic updating, otherwise false
*/
public boolean needsPeriodicUpdate() {
boolean result = false;
for(RegionSign sign : signs.values()) {
result = result | sign.needsPeriodicUpdate();
}
return result;
}
/**
* Get the signs of this region.
* @return List of signs
*/
public List<RegionSign> getSigns() {
return Collections.unmodifiableList(new ArrayList<>(signs.values()));
}
/**
* Get the signs of this region.
* @return Map with signs: locationString -&gt; RegionSign
*/
Map<String, RegionSign> getSignsRef() {
return signs;
}
/**
* Get a list with all sign locations.
* @return A List with all sign locations
*/
public List<Location> getSignLocations() {
List<Location> result = new ArrayList<>();
for(RegionSign sign : signs.values()) {
result.add(sign.getLocation());
}
return result;
public SignManager signManager() {
return this.internalSignManager;
}
/**
@@ -562,39 +96,13 @@ public class SignsFeature extends RegionFeature {
getRegion().setSetting(signPath + "location", Utils.locationToConfig(location));
getRegion().setSetting(signPath + "facing", facing != null ? facing.name() : null);
getRegion().setSetting(signPath + "signType", signType != null ? signType.name() : null);
if(profile != null && profile.length() != 0) {
if(profile != null && !profile.isEmpty()) {
getRegion().setSetting(signPath + "profile", profile);
}
// Add to the map
RegionSign sign = new RegionSign(this, i + "");
signs.put(sign.getStringLocation(), sign);
allSigns.put(sign.getStringLocation(), sign);
signsByChunk.computeIfAbsent(sign.getStringChunk(), key -> new ArrayList<>())
.add(sign);
}
/**
* Checks if there is a sign from this region at the specified location.
* @param location Location to check
* @return true if this region has a sign at the location, otherwise false
*/
public boolean isSignOfRegion(Location location) {
Set<String> signs;
if(getRegion().getConfig().getConfigurationSection("general.signs") == null) {
return false;
}
signs = getRegion().getConfig().getConfigurationSection("general.signs").getKeys(false);
for(String sign : signs) {
Location signLocation = Utils.configToLocation(getRegion().getConfig().getConfigurationSection("general.signs." + sign + ".location"));
if(signLocation != null
&& signLocation.getWorld().equals(location.getWorld())
&& signLocation.getBlockX() == location.getBlockX()
&& signLocation.getBlockY() == location.getBlockY()
&& signLocation.getBlockZ() == location.getBlockZ()) {
return true;
}
}
return false;
RegionSign regionSign = this.signFactory.createRegionSign(this, String.valueOf(i));
this.globalSignManager.addSign(regionSign);
this.internalSignManager.addSign(regionSign);
}
}
@@ -0,0 +1,50 @@
package me.wiefferink.areashop.features.signs;
import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.SignLinkerManager;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.regions.RegionFactory;
import javax.annotation.Nonnull;
public class SignsModule extends AbstractModule {
@Override
protected void configure() {
bind(SignManager.class).asEagerSingleton();
install(new FactoryModuleBuilder().build(SignFactory.class));
}
@Provides
@Singleton
public SignListener provideSignListener(@Nonnull AreaShop plugin,
@Nonnull BlockBehaviourHelper behaviourHelper,
@Nonnull RegionFactory regionFactory,
@Nonnull MessageBridge messageBridge,
@Nonnull SignLinkerManager signLinkerManager,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull SignManager signManager,
@Nonnull IFileManager fileManager
) {
final SignListener signListener = new SignListener(
plugin,
behaviourHelper,
regionFactory,
messageBridge,
signLinkerManager,
worldGuardInterface,
signManager,
fileManager
);
plugin.getServer().getPluginManager().registerEvents(signListener, plugin);
return signListener;
}
}
@@ -1,769 +0,0 @@
/*
* Copyright 2011-2013 Tyler Blair. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ''AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and contributors and should not be interpreted as representing official policies,
* either expressed or implied, of anybody else.
*/
package me.wiefferink.areashop.lib;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;
import org.bukkit.scheduler.BukkitTask;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.UUID;
import java.util.logging.Level;
import java.util.zip.GZIPOutputStream;
public class Metrics {
/**
* The current revision number.
*/
private static final int REVISION = 7;
/**
* The base url of the metrics domain.
*/
private static final String BASE_URL = "http://report.mcstats.org";
/**
* The url used to report a server's status.
*/
private static final String REPORT_URL = "/plugin/%s";
/**
* Interval of time to ping (in minutes).
*/
private static final int PING_INTERVAL = 15;
/**
* The plugin this metrics submits for.
*/
private final Plugin plugin;
/**
* All of the custom graphs to submit to metrics.
*/
private final Set<Graph> graphs = Collections.synchronizedSet(new HashSet<Graph>());
/**
* The plugin configuration file.
*/
private final YamlConfiguration configuration;
/**
* The plugin configuration file.
*/
private final File configurationFile;
/**
* Unique server id.
*/
private final String guid;
/**
* Debug mode.
*/
private final boolean debug;
/**
* Lock for synchronization.
*/
private final Object optOutLock = new Object();
/**
* The scheduled task.
*/
private volatile BukkitTask task = null;
/**
* Constructor.
* @param plugin The plugin to report stats for
* @throws IOException When the plugin or configuration is wrong
*/
public Metrics(final Plugin plugin) throws IOException {
if(plugin == null) {
throw new IllegalArgumentException("Plugin cannot be null");
}
this.plugin = plugin;
// load the config
configurationFile = getConfigFile();
configuration = YamlConfiguration.loadConfiguration(configurationFile);
// add some defaults
configuration.addDefault("opt-out", false);
configuration.addDefault("guid", UUID.randomUUID().toString());
configuration.addDefault("debug", false);
// Do we need to create the file?
if(configuration.get("guid", null) == null) {
configuration.options().header("http://mcstats.org").copyDefaults(true);
configuration.save(configurationFile);
}
// Load the guid then
guid = configuration.getString("guid");
debug = configuration.getBoolean("debug", false);
}
/**
* Construct and create a Graph that can be used to separate specific plotters to their own graphs on the metrics
* website. Plotters can be added to the graph object returned.
* @param name The name of the graph
* @return Graph object created. Will never return NULL under normal circumstances unless bad parameters are given
*/
public Graph createGraph(final String name) {
if(name == null) {
throw new IllegalArgumentException("Graph name cannot be null");
}
// Construct the graph object
final Graph graph = new Graph(name);
// Now we can add our graph
graphs.add(graph);
// and return back
return graph;
}
/**
* Add a Graph object to BukkitMetrics that represents data for the plugin that should be sent to the backend.
* @param graph The name of the graph
*/
public void addGraph(final Graph graph) {
if(graph == null) {
throw new IllegalArgumentException("Graph cannot be null");
}
graphs.add(graph);
}
/**
* Start measuring statistics. This will immediately create an async repeating task as the plugin and send the
* initial data to the metrics backend, and then after that it will post in increments of PING_INTERVAL * 1200
* ticks.
* @return True if statistics measuring is running, otherwise false.
*/
public boolean start() {
synchronized(optOutLock) {
// Did we opt out?
if(isOptOut()) {
return false;
}
// Is metrics already running?
if(task != null) {
return true;
}
// Begin hitting the server with glorious data
task = plugin.getServer().getScheduler().runTaskTimerAsynchronously(plugin, new Runnable() {
private boolean firstPost = true;
public void run() {
try {
// This has to be synchronized or it can collide with the disable method.
synchronized(optOutLock) {
// Disable Task, if it is running and the server owner decided to opt-out
if(isOptOut() && task != null) {
task.cancel();
task = null;
// Tell all plotters to stop gathering information.
for(Graph graph : graphs) {
graph.onOptOut();
}
}
}
// We use the inverse of firstPost because if it is the first time we are posting,
// it is not a interval ping, so it evaluates to FALSE
// Each time thereafter it will evaluate to TRUE, i.e PING!
postPlugin(!firstPost);
// After the first post we set firstPost to false
// Each post thereafter will be a ping
firstPost = false;
} catch(IOException e) {
if(debug) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + e.getMessage());
}
}
}
}, 0, PING_INTERVAL * 1200);
return true;
}
}
/**
* If the server owner denied plugin metrics.
* @return true if metrics should be opted out of it
*/
public boolean isOptOut() {
synchronized(optOutLock) {
try {
// Reload the metrics file
configuration.load(getConfigFile());
} catch(IOException ex) {
if(debug) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
}
return true;
} catch(InvalidConfigurationException ex) {
if(debug) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
}
return true;
}
return configuration.getBoolean("opt-out", false);
}
}
/**
* Enables metrics for the server by setting "opt-out" to false in the config file and starting the metrics task.
* @throws IOException when saving the config file fails
*/
public void enable() throws IOException {
// This has to be synchronized or it can collide with the check in the task.
synchronized(optOutLock) {
// Check if the server owner has already set opt-out, if not, set it.
if(isOptOut()) {
configuration.set("opt-out", false);
configuration.save(configurationFile);
}
// Enable Task, if it is not running
if(task == null) {
start();
}
}
}
/**
* Disables metrics for the server by setting "opt-out" to true in the config file and canceling the metrics task.
* @throws IOException when saving the config file fails
*/
public void disable() throws IOException {
// This has to be synchronized or it can collide with the check in the task.
synchronized(optOutLock) {
// Check if the server owner has already set opt-out, if not, set it.
if(!isOptOut()) {
configuration.set("opt-out", true);
configuration.save(configurationFile);
}
// Disable Task, if it is running
if(task != null) {
task.cancel();
task = null;
}
}
}
/**
* Gets the File object of the config file that should be used to store data such as the GUID and opt-out status.
* @return the File object for the config file
*/
public File getConfigFile() {
// I believe the easiest way to get the base folder (e.g craftbukkit set via -P) for plugins to use
// is to abuse the plugin object we already have
// plugin.getDataFolder() => base/plugins/PluginA/
// pluginsFolder => base/plugins/
// The base is not necessarily relative to the startup directory.
File pluginsFolder = plugin.getDataFolder().getParentFile();
// return => base/plugins/PluginMetrics/config.yml
return new File(new File(pluginsFolder, "PluginMetrics"), "config.yml");
}
/**
* Gets the online player (backwards compatibility).
* @return online player amount
*/
private int getOnlinePlayers() {
try {
Method onlinePlayerMethod = Server.class.getMethod("getOnlinePlayers");
if(onlinePlayerMethod.getReturnType().equals(Collection.class)) {
return ((Collection<?>)onlinePlayerMethod.invoke(Bukkit.getServer())).size();
} else {
return ((Player[])onlinePlayerMethod.invoke(Bukkit.getServer())).length;
}
} catch(Exception ex) {
if(debug) {
Bukkit.getLogger().log(Level.INFO, "[Metrics] " + ex.getMessage());
}
}
return 0;
}
/**
* Generic method that posts a plugin to the metrics website.
*/
private void postPlugin(final boolean isPing) throws IOException {
// Server software specific section
PluginDescriptionFile description = plugin.getDescription();
String pluginName = description.getName();
boolean onlineMode = Bukkit.getServer().getOnlineMode(); // TRUE if online mode is enabled
String pluginVersion = description.getVersion();
String serverVersion = Bukkit.getVersion();
int playersOnline = this.getOnlinePlayers();
// END server software specific section -- all code below does not use any code outside of this class / Java
// Construct the post data
StringBuilder json = new StringBuilder(1024);
json.append('{');
// The plugin's description file containg all of the plugin data such as name, version, author, etc
appendJsonPair(json, "guid", guid);
appendJsonPair(json, "plugin_version", pluginVersion);
appendJsonPair(json, "server_version", serverVersion);
appendJsonPair(json, "players_online", Integer.toString(playersOnline));
// New data as of R6
String osname = System.getProperty("os.name");
String osarch = System.getProperty("os.arch");
String osversion = System.getProperty("os.version");
String javaVersion = System.getProperty("java.version");
int coreCount = Runtime.getRuntime().availableProcessors();
// normalize os arch .. amd64 -> x86_64
if(osarch.equals("amd64")) {
osarch = "x86_64";
}
appendJsonPair(json, "osname", osname);
appendJsonPair(json, "osarch", osarch);
appendJsonPair(json, "osversion", osversion);
appendJsonPair(json, "cores", Integer.toString(coreCount));
appendJsonPair(json, "auth_mode", onlineMode ? "1" : "0");
appendJsonPair(json, "java_version", javaVersion);
// If we're pinging, append it
if(isPing) {
appendJsonPair(json, "ping", "1");
}
if(graphs.size() > 0) {
synchronized(graphs) {
json.append(',');
json.append('"');
json.append("graphs");
json.append('"');
json.append(':');
json.append('{');
boolean firstGraph = true;
final Iterator<Graph> iter = graphs.iterator();
while(iter.hasNext()) {
Graph graph = iter.next();
StringBuilder graphJson = new StringBuilder();
graphJson.append('{');
for(Plotter plotter : graph.getPlotters()) {
appendJsonPair(graphJson, plotter.getColumnName(), Integer.toString(plotter.getValue()));
}
graphJson.append('}');
if(!firstGraph) {
json.append(',');
}
json.append(escapeJson(graph.getName()));
json.append(':');
json.append(graphJson);
firstGraph = false;
}
json.append('}');
}
}
// close json
json.append('}');
// Create the url
URL url = new URL(BASE_URL + String.format(REPORT_URL, urlEncode(pluginName)));
// Connect to the website
URLConnection connection;
// Mineshafter creates a socks proxy, so we can safely bypass it
// It does not reroute POST requests so we need to go around it
if(isMineshafterPresent()) {
connection = url.openConnection(Proxy.NO_PROXY);
} else {
connection = url.openConnection();
}
byte[] uncompressed = json.toString().getBytes();
byte[] compressed = gzip(json.toString());
// Headers
connection.addRequestProperty("User-Agent", "MCStats/" + REVISION);
connection.addRequestProperty("Content-Type", "application/json");
connection.addRequestProperty("Content-Encoding", "gzip");
connection.addRequestProperty("Content-Length", Integer.toString(compressed.length));
connection.addRequestProperty("Accept", "application/json");
connection.addRequestProperty("Connection", "close");
connection.setDoOutput(true);
if(debug) {
System.out.println("[Metrics] Prepared request for " + pluginName + " uncompressed=" + uncompressed.length + " compressed=" + compressed.length);
}
// Write the data
OutputStream os = connection.getOutputStream();
os.write(compressed);
os.flush();
// Now read the response
final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
String response = reader.readLine();
// close resources
os.close();
reader.close();
if(response == null || response.startsWith("ERR") || response.startsWith("7")) {
if(response == null) {
response = "null";
} else if(response.startsWith("7")) {
response = response.substring(response.startsWith("7,") ? 2 : 1);
}
throw new IOException(response);
} else {
// Is this the first update this hour?
if(response.equals("1") || response.contains("This is your first update this hour")) {
synchronized(graphs) {
final Iterator<Graph> iter = graphs.iterator();
while(iter.hasNext()) {
final Graph graph = iter.next();
for(Plotter plotter : graph.getPlotters()) {
plotter.reset();
}
}
}
}
}
}
/**
* GZip compress a string of bytes.
* @param input Content to gzip
* @return byte[] of the gzipped input
*/
public static byte[] gzip(String input) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
GZIPOutputStream gzos = null;
try {
gzos = new GZIPOutputStream(baos);
gzos.write(input.getBytes(StandardCharsets.UTF_8));
} catch(IOException e) {
e.printStackTrace();
} finally {
if(gzos != null) {
try {
gzos.close();
} catch(IOException ignore) {
// ignore
}
}
}
return baos.toByteArray();
}
/**
* Check if mineshafter is present. If it is, we need to bypass it to send POST requests
* @return true if mineshafter is installed on the server
*/
private boolean isMineshafterPresent() {
try {
Class.forName("mineshafter.MineServer");
return true;
} catch(Exception e) {
return false;
}
}
/**
* Appends a json encoded key/value pair to the given string builder.
*/
private static void appendJsonPair(StringBuilder json, String key, String value) throws UnsupportedEncodingException {
boolean isValueNumeric = false;
try {
if(value.equals("0") || !value.endsWith("0")) {
Double.parseDouble(value);
isValueNumeric = true;
}
} catch(NumberFormatException e) {
isValueNumeric = false;
}
if(json.charAt(json.length() - 1) != '{') {
json.append(',');
}
json.append(escapeJson(key));
json.append(':');
if(isValueNumeric) {
json.append(value);
} else {
json.append(escapeJson(value));
}
}
/**
* Escape a string to create a valid JSON string.
*/
private static String escapeJson(String text) {
StringBuilder builder = new StringBuilder();
builder.append('"');
for(int index = 0; index < text.length(); index++) {
char chr = text.charAt(index);
switch(chr) {
case '"':
case '\\':
builder.append('\\');
builder.append(chr);
break;
case '\b':
builder.append("\\b");
break;
case '\t':
builder.append("\\t");
break;
case '\n':
builder.append("\\n");
break;
case '\r':
builder.append("\\r");
break;
default:
if(chr < ' ') {
String t = "000" + Integer.toHexString(chr);
builder.append("\\u" + t.substring(t.length() - 4));
} else {
builder.append(chr);
}
break;
}
}
builder.append('"');
return builder.toString();
}
/**
* Encode text as UTF-8.
* @param text the text to encode
* @return the encoded text, as UTF-8
*/
private static String urlEncode(final String text) throws UnsupportedEncodingException {
return URLEncoder.encode(text, "UTF-8");
}
/**
* Represents a custom graph on the website.
*/
public static class Graph {
/**
* The graph's name, alphanumeric and spaces only :) If it does not comply to the above when submitted, it is
* rejected.
*/
private final String name;
/**
* The set of plotters that are contained within this graph.
*/
private final Set<Plotter> plotters = new LinkedHashSet<Plotter>();
private Graph(final String name) {
this.name = name;
}
/**
* Gets the graph's name.
* @return the Graph's name
*/
public String getName() {
return name;
}
/**
* Add a plotter to the graph, which will be used to plot entries.
* @param plotter the plotter to add to the graph
*/
public void addPlotter(final Plotter plotter) {
plotters.add(plotter);
}
/**
* Remove a plotter from the graph.
* @param plotter the plotter to remove from the graph
*/
public void removePlotter(final Plotter plotter) {
plotters.remove(plotter);
}
/**
* Gets an <b>unmodifiable</b> set of the plotter objects in the graph.
* @return an unmodifiable {@link java.util.Set} of the plotter objects
*/
public Set<Plotter> getPlotters() {
return Collections.unmodifiableSet(plotters);
}
@Override
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(final Object object) {
if(!(object instanceof Graph)) {
return false;
}
final Graph graph = (Graph)object;
return graph.name.equals(name);
}
/**
* Called when the server owner decides to opt-out of BukkitMetrics while the server is running.
*/
protected void onOptOut() {
}
}
/**
* Interface used to collect custom data for a plugin.
*/
public abstract static class Plotter {
/**
* The plot's name.
*/
private final String name;
/**
* Construct a plotter with the default plot name.
*/
public Plotter() {
this("Default");
}
/**
* Construct a plotter with a specific plot name.
* @param name the name of the plotter to use, which will show up on the website
*/
public Plotter(final String name) {
this.name = name;
}
/**
* Get the current value for the plotted point. Since this function defers to an external function it may or may
* not return immediately thus cannot be guaranteed to be thread friendly or safe. This function can be called
* from any thread so care should be taken when accessing resources that need to be synchronized.
* @return the current value for the point to be plotted.
*/
public abstract int getValue();
/**
* Get the column name for the plotted point.
* @return the plotted point's column name
*/
public String getColumnName() {
return name;
}
/**
* Called after the website graphs have been updated.
*/
public void reset() {
}
@Override
public int hashCode() {
return getColumnName().hashCode();
}
@Override
public boolean equals(final Object object) {
if(!(object instanceof Plotter)) {
return false;
}
final Plotter plotter = (Plotter)object;
return plotter.name.equals(name) && plotter.getValue() == getValue();
}
}
}
@@ -1,6 +1,7 @@
package me.wiefferink.areashop.listeners;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
@@ -15,6 +16,7 @@ import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerLoginEvent.Result;
import org.bukkit.event.player.PlayerQuitEvent;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;
@@ -22,14 +24,17 @@ import java.util.List;
* Notify region expiry and track activity time.
*/
public final class PlayerLoginLogoutListener implements Listener {
private final AreaShop plugin;
private final MessageBridge messageBridge;
/**
* Constructor.
* @param plugin The AreaShop plugin
*/
public PlayerLoginLogoutListener(AreaShop plugin) {
public PlayerLoginLogoutListener(@Nonnull AreaShop plugin, @Nonnull MessageBridge messageBridge) {
this.plugin = plugin;
this.messageBridge = messageBridge;
}
/**
@@ -53,7 +58,7 @@ public final class PlayerLoginLogoutListener implements Listener {
return false;
}
// Notify for rents that almost run out
for(RentRegion region : plugin.getFileManager().getRents()) {
for(RentRegion region : plugin.getFileManager().getRentsRef()) {
if(region.isRenter(player)) {
String warningSetting = region.getStringSetting("rent.warningOnLoginTime");
if(warningSetting == null || warningSetting.isEmpty()) {
@@ -62,13 +67,13 @@ public final class PlayerLoginLogoutListener implements Listener {
long warningTime = Utils.durationStringToLong(warningSetting);
if(region.getTimeLeft() < warningTime) {
// Send the warning message later to let it appear after general MOTD messages
AreaShop.getInstance().message(player, "rent-expireWarning", region);
messageBridge.message(player, "rent-expireWarning", region);
}
}
}
// Notify admins for plugin updates
AreaShop.getInstance().notifyUpdate(player);
this.plugin.notifyUpdate(player);
return false;
});
@@ -79,7 +84,7 @@ public final class PlayerLoginLogoutListener implements Listener {
}
List<GeneralRegion> regions = new ArrayList<>();
for(GeneralRegion region : plugin.getFileManager().getRegions()) {
for(GeneralRegion region : plugin.getFileManager().getRegionsRef()) {
if(region.isOwner(player)) {
regions.add(region);
}
@@ -122,7 +127,7 @@ public final class PlayerLoginLogoutListener implements Listener {
* @param player The player to update the active times for
*/
private void updateLastActive(Player player) {
for(GeneralRegion region : plugin.getFileManager().getRegions()) {
for(GeneralRegion region : plugin.getFileManager().getRegionsRef()) {
if(region.isOwner(player)) {
region.updateLastActiveTime();
}
@@ -1,5 +1,8 @@
package me.wiefferink.areashop.managers;
import com.google.inject.Injector;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.commands.AddCommand;
import me.wiefferink.areashop.commands.AddfriendCommand;
import me.wiefferink.areashop.commands.AddsignCommand;
@@ -39,52 +42,62 @@ import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
@Singleton
public class CommandManager extends Manager implements CommandExecutor, TabCompleter {
private final ArrayList<CommandAreaShop> commands;
private final List<CommandAreaShop> commands;
private final AreaShop plugin;
private final MessageBridge messageBridge;
/**
* Constructor.
*/
public CommandManager() {
commands = new ArrayList<>();
commands.add(new HelpCommand());
commands.add(new RentCommand());
commands.add(new UnrentCommand());
commands.add(new BuyCommand());
commands.add(new SellCommand());
commands.add(new MeCommand());
commands.add(new InfoCommand());
commands.add(new TeleportCommand());
commands.add(new SetteleportCommand());
commands.add(new AddfriendCommand());
commands.add(new DelfriendCommand());
commands.add(new FindCommand());
commands.add(new ResellCommand());
commands.add(new StopresellCommand());
commands.add(new SetrestoreCommand());
commands.add(new SetpriceCommand());
commands.add(new SetownerCommand());
commands.add(new SetdurationCommand());
commands.add(new ReloadCommand());
commands.add(new GroupaddCommand());
commands.add(new GroupdelCommand());
commands.add(new GrouplistCommand());
commands.add(new GroupinfoCommand());
commands.add(new SchematiceventCommand());
commands.add(new AddCommand());
commands.add(new DelCommand());
commands.add(new AddsignCommand());
commands.add(new DelsignCommand());
commands.add(new LinksignsCommand());
commands.add(new StackCommand());
commands.add(new SetlandlordCommand());
commands.add(new MessageCommand());
commands.add(new ImportCommand());
@Inject
CommandManager(@Nonnull AreaShop plugin, @Nonnull MessageBridge messageBridge, @Nonnull
Injector injector) {
this.plugin = plugin;
this.messageBridge = messageBridge;
commands = new ArrayList<>(34);
commands.add(new HelpCommand(this));
commands.add(injector.getInstance(RentCommand.class));
commands.add(injector.getInstance(UnrentCommand.class));
commands.add(injector.getInstance(BuyCommand.class));
commands.add(injector.getInstance(SellCommand.class));
commands.add(injector.getInstance(MeCommand.class));
commands.add(injector.getInstance(InfoCommand.class));
commands.add(injector.getInstance(TeleportCommand.class));
commands.add(injector.getInstance(SetteleportCommand.class));
commands.add(injector.getInstance(AddfriendCommand.class));
commands.add(injector.getInstance(DelfriendCommand.class));
commands.add(injector.getInstance(FindCommand.class));
commands.add(injector.getInstance(ResellCommand.class));
commands.add(injector.getInstance(StopresellCommand.class));
commands.add(injector.getInstance(SetrestoreCommand.class));
commands.add(injector.getInstance(SetpriceCommand.class));
commands.add(injector.getInstance(SetownerCommand.class));
commands.add(injector.getInstance(SetdurationCommand.class));
commands.add(injector.getInstance(ReloadCommand.class));
commands.add(injector.getInstance(GroupaddCommand.class));
commands.add(injector.getInstance(GroupdelCommand.class));
commands.add(injector.getInstance(GrouplistCommand.class));
commands.add(injector.getInstance(GroupinfoCommand.class));
commands.add(injector.getInstance(SchematiceventCommand.class));
commands.add(injector.getInstance(AddCommand.class));
commands.add(injector.getInstance(DelCommand.class));
commands.add(injector.getInstance(AddsignCommand.class));
commands.add(injector.getInstance(DelsignCommand.class));
commands.add(injector.getInstance(LinksignsCommand.class));
commands.add(injector.getInstance(StackCommand.class));
commands.add(injector.getInstance(SetlandlordCommand.class));
commands.add(injector.getInstance(MessageCommand.class));
commands.add(injector.getInstance(ImportCommand.class));
// Register commands in bukkit
plugin.getCommand("AreaShop").setExecutor(this);
@@ -95,7 +108,7 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl
* Get the list with AreaShop commands.
* @return The list with AreaShop commands
*/
public ArrayList<CommandAreaShop> getCommands() {
public List<CommandAreaShop> getCommands() {
return commands;
}
@@ -105,36 +118,38 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl
*/
public void showHelp(CommandSender target) {
if(!target.hasPermission("areashop.help")) {
plugin.message(target, "help-noPermission");
messageBridge.message(target, "help-noPermission");
return;
}
// Add all messages to a list
ArrayList<String> messages = new ArrayList<>();
plugin.message(target, "help-header");
plugin.message(target, "help-alias");
messageBridge.message(target, "help-header");
messageBridge.message(target, "help-alias");
for(CommandAreaShop command : commands) {
String help = command.getHelp(target);
if(help != null && help.length() != 0) {
if(help != null && !help.isEmpty()) {
messages.add(help);
}
}
// Send the messages to the target
for(String message : messages) {
plugin.messageNoPrefix(target, message);
messageBridge.messageNoPrefix(target, message);
}
}
@Override
public boolean onCommand(CommandSender sender, Command command, String alias, String[] args) {
if(!plugin.isReady()) {
plugin.message(sender, "general-notReady");
messageBridge.message(sender, "general-notReady");
return true;
}
// Redirect `/as info player <player>` to `/as me <player>`
if(args.length == 3 && "info".equals(args[0]) && "player".equals(args[1])) {
args[0] = "me";
args[1] = args[2];
}
// Execute command
boolean executed = false;
for(int i = 0; i < commands.size() && !executed; i++) {
@@ -143,16 +158,21 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl
executed = true;
}
}
if(!executed && args.length == 0) {
this.showHelp(sender);
} else if(!executed && args.length > 0) {
// Indicate that the '/as updaterents' and '/as updatebuys' commands are removed
if("updaterents".equalsIgnoreCase(args[0]) || "updatebuys".equalsIgnoreCase(args[0])) {
plugin.message(sender, "reload-updateCommandChanged");
// Show help
if (!executed) {
if (args.length == 0) {
this.showHelp(sender);
} else {
plugin.message(sender, "cmd-notValid");
// Indicate that the '/as updaterents' and '/as updatebuys' commands are removed
if("updaterents".equalsIgnoreCase(args[0]) || "updatebuys".equalsIgnoreCase(args[0])) {
messageBridge.message(sender, "reload-updateCommandChanged");
} else {
messageBridge.message(sender, "cmd-notValid");
}
}
}
return true;
}
@@ -181,7 +201,7 @@ public class CommandManager extends Manager implements CommandExecutor, TabCompl
}
}
// Filter and sort the results
if(result.size() > 0) {
if(!result.isEmpty()) {
SortedSet<String> set = new TreeSet<>();
for(String suggestion : result) {
if(suggestion.toLowerCase().startsWith(toCompletePrefix)) {
@@ -1,7 +1,11 @@
package me.wiefferink.areashop.managers;
import com.google.inject.Injector;
import com.google.inject.ProvisionException;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.features.CommandsFeature;
import me.wiefferink.areashop.features.DebugFeature;
import me.wiefferink.areashop.features.FeatureFactory;
import me.wiefferink.areashop.features.FriendsFeature;
import me.wiefferink.areashop.features.RegionFeature;
import me.wiefferink.areashop.features.TeleportFeature;
@@ -9,60 +13,65 @@ import me.wiefferink.areashop.features.WorldGuardRegionFlagsFeature;
import me.wiefferink.areashop.features.signs.SignsFeature;
import me.wiefferink.areashop.regions.GeneralRegion;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import javax.annotation.Nonnull;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
@Singleton
public class FeatureManager extends Manager {
// List of defined features
private static final Set<Class<? extends RegionFeature>> featureClasses = new HashSet<>(Arrays.asList(
DebugFeature.class,
SignsFeature.class,
FriendsFeature.class,
private static final Collection<Class<? extends RegionFeature>> globalFeatureClasses = Arrays.asList(
CommandsFeature.class,
WorldGuardRegionFlagsFeature.class,
TeleportFeature.class
));
DebugFeature.class
);
// One instance of each feature, registered for event handling
private final Set<RegionFeature> globalFeatures;
private final Map<Class<? extends RegionFeature>, Constructor<? extends RegionFeature>> regionFeatureConstructors;
private final Set<RegionFeature> globalFeatures = new HashSet<>();
private final Map<Class<? extends RegionFeature>, Function<GeneralRegion, ? extends RegionFeature>> regionFeatureConstructors = new HashMap<>();
/**
* Constructor.
*/
public FeatureManager() {
// Instantiate and register global features (one per type, for event handling)
globalFeatures = new HashSet<>();
for(Class<? extends RegionFeature> clazz : featureClasses) {
try {
Constructor<? extends RegionFeature> constructor = clazz.getConstructor();
try {
RegionFeature feature = constructor.newInstance();
feature.listen();
globalFeatures.add(feature);
} catch(InstantiationException | IllegalAccessException | InvocationTargetException | IllegalArgumentException e) {
AreaShop.error("Failed to instantiate global feature:", clazz, e);
}
} catch(NoSuchMethodException e) {
// Feature does not have a global part
}
}
@Inject
FeatureManager(@Nonnull FeatureFactory featureFactory) {
// Setup constructors for region specific features
regionFeatureConstructors = new HashMap<>();
for(Class<? extends RegionFeature> clazz : featureClasses) {
regionFeatureConstructors.put(SignsFeature.class, wrapInstantiator(SignsFeature.class, featureFactory::createSignsFeature));
regionFeatureConstructors.put(TeleportFeature.class, wrapInstantiator(TeleportFeature.class, featureFactory::createTeleportFeature));
regionFeatureConstructors.put(FriendsFeature.class, wrapInstantiator(FriendsFeature.class, featureFactory::createFriendsFeature));
}
public void initializeFeatures(@Nonnull Injector injector) {
// Instantiate and register global features (one per type, for event handling)
for(Class<? extends RegionFeature> clazz : globalFeatureClasses) {
try {
regionFeatureConstructors.put(clazz, clazz.getConstructor(GeneralRegion.class));
} catch(NoSuchMethodException | IllegalArgumentException e) {
// The feature does not have a region specific part
RegionFeature feature = injector.getInstance(clazz);
feature.listen();
globalFeatures.add(feature);
} catch(ProvisionException e) {
AreaShop.error("Failed to instantiate global feature:", clazz, e);
}
}
}
private <T extends RegionFeature> Function<GeneralRegion, T> wrapInstantiator(Class<T> clazz, Function<GeneralRegion, T> function
) {
return region -> {
try {
return function.apply(region);
} catch (Throwable e) {
AreaShop.error("Failed to instantiate feature", clazz, "for region", region, e, e.getCause());
return null;
}
};
}
@Override
public void shutdown() {
for(RegionFeature feature : globalFeatures) {
@@ -77,12 +86,7 @@ public class FeatureManager extends Manager {
* @return The feature class
*/
public RegionFeature getRegionFeature(GeneralRegion region, Class<? extends RegionFeature> featureClazz) {
try {
return regionFeatureConstructors.get(featureClazz).newInstance(region);
} catch(InstantiationException | InvocationTargetException | IllegalAccessException | IllegalArgumentException e) {
AreaShop.error("Failed to instanciate feature", featureClazz, "for region", region, e, e.getCause());
}
return null;
return regionFeatureConstructors.get(featureClazz).apply(region);
}
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,399 @@
package me.wiefferink.areashop.managers;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
import me.wiefferink.areashop.events.ask.DeletingRegionEvent;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionGroup;
import me.wiefferink.areashop.regions.RentRegion;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.List;
public interface IFileManager {
/**
* Get the folder where schematics are stored.
*
* @return The folder where schematics are stored
*/
String getSchematicFolder();
/**
* Get a group.
*
* @param name The name of the group to get (will be normalized)
* @return The group if found, otherwise null
*/
RegionGroup getGroup(String name);
/**
* Get all groups.
*
* @return Collection with all groups (safe to modify)
*/
Collection<RegionGroup> getGroups();
/**
* Get the default region settings as provided by the user (default.yml).
*
* @return YamlConfiguration with the settings (might miss settings, which should be filled in with {@link #getFallbackRegionSettings()})
*/
YamlConfiguration getRegionSettings();
/**
* Get the default regions settings as provided by AreaShop (default.yml).
*
* @return YamlConfiguration with the default settings
*/
YamlConfiguration getFallbackRegionSettings();
/**
* Get the config file (config.yml).
*
* @return YamlConfiguration with the settings of users, with fallback to the settings provided by AreaShop
*/
YamlConfiguration getConfig();
/**
* Get a region.
*
* @param name The name of the region to get (will be normalized)
* @return The region if found, otherwise null
*/
@Nullable
GeneralRegion getRegion(String name);
/**
* Get a rental region.
*
* @param name The name of the rental region (will be normalized)
* @return RentRegion if it could be found, otherwise null
*/
@Nullable
RentRegion getRent(String name);
/**
* Get a buy region.
*
* @param name The name of the buy region (will be normalized)
* @return BuyRegion if it could be found, otherwise null
*/
@Nullable
BuyRegion getBuy(String name);
/**
* Get all rental regions.
*
* @return List of all rental regions
*/
Collection<RentRegion> getRents();
/**
* Get all rental regions (readonly)
*
* @return Unmodifiable collection of all rental regions
*/
Collection<RentRegion> getRentsRef();
/**
* Get all buy regions.
*
* @return List of all buy regions
*/
List<BuyRegion> getBuys();
/**
* Get all buy regions (readonly)
* @return Unmodifiable collection of all buy regions
*/
Collection<BuyRegion> getBuysRef();
/**
* Get all regions.
*
* @return List of all regions (it is safe to modify the list)
*/
List<GeneralRegion> getRegions();
/**
* Get all regions (readonly)
*
* @return Unmodifiable collection of all regions
*/
Collection<GeneralRegion> getRegionsRef();
/**
* Get a list of names of all buy regions.
*
* @return A String list with all the names
*/
List<String> getBuyNames();
/**
* Get a list of names of all rent regions.
*
* @return A String list with all the names
*/
List<String> getRentNames();
/**
* Get a list of names of all regions.
*
* @return A String list with all the names
*/
List<String> getRegionNames();
/**
* Get a list of names of all groups.
*
* @return A String list with all the names
*/
List<String> getGroupNames();
/**
* Add a region to the list and mark it as to-be-saved.
*
* @param region Then region to add
* @return true when successful, otherwise false (denied by an event listener)
*/
AddingRegionEvent addRegion(GeneralRegion region);
/**
* Add a region to the list without saving it to disk (useful for loading at startup).
*
* @param region The region to add
* @return true when successful, otherwise false (denied by an event listener)
*/
AddingRegionEvent addRegionNoSave(GeneralRegion region);
/**
* Mark all RegionGroups that they should regenerate regions.
*/
void markGroupsAutoDirty();
/**
* Add a RegionGroup.
*
* @param group The RegionGroup to add
*/
void addGroup(RegionGroup group);
/**
* Check if a player can add a certain region as rent or buy region.
*
* @param sender The player/console that wants to add a region
* @param region The WorldGuard region to add
* @param world The world the ProtectedRegion is located in
* @param type The type the region should have in AreaShop
* @return The result if a player would want to add this region
*/
AddResult checkRegionAdd(CommandSender sender,
ProtectedRegion region,
World world,
GeneralRegion.RegionType type);
/**
* Remove a region from the list.
*
* @param region The region to remove
* @param giveMoneyBack use true to give money back to the player if someone is currently holding this region, otherwise false
* @return true if the region has been removed, false otherwise
*/
DeletingRegionEvent deleteRegion(GeneralRegion region, boolean giveMoneyBack);
/**
* Remove a group.
*
* @param group Group to remove
*/
void removeGroup(RegionGroup group);
/**
* Update all signs that need periodic updating.
*/
void performPeriodicSignUpdate();
/**
* Send out rent expire warnings.
*/
void sendRentExpireWarnings();
/**
* Update regions in a task to minimize lag.
*
* @param regions Regions to update
* @param confirmationReceiver The CommandSender that should be notified at completion
*/
void updateRegions(Collection<GeneralRegion> regions, CommandSender confirmationReceiver);
/**
* Update a list of regions.
*
* @param regions The list of regions to update.
*/
void updateRegions(Collection<GeneralRegion> regions);
/**
* Update all regions, happens in a task to minimize lag.
*/
void updateAllRegions();
/**
* Update all regions.
*
* @param confirmationReceiver Optional CommandSender that should receive progress messages
*/
void updateAllRegions(CommandSender confirmationReceiver);
/**
* Save the group file to disk.
*/
void saveGroupsIsRequired();
/**
* Check if saving the groups file is required.
*
* @return true if changes are made and saving is required, otherwise false
*/
boolean isSaveGroupsRequired();
/**
* Save the groups file to disk synchronously.
*/
void saveGroupsNow();
/**
* Save all region related files spread over time (low load).
*/
void saveRequiredFiles();
/**
* Save all region related files directly (only for cases like onDisable()).
*/
void saveRequiredFilesAtOnce();
/**
* Indicates that a/multiple WorldGuard regions need to be saved.
*
* @param worldName The world where the regions that should be saved is in
*/
void saveIsRequiredForRegionWorld(String worldName);
/**
* Save all worldGuard regions that need saving.
*/
void saveWorldGuardRegions();
/**
* Get the folder the region files are located in.
*
* @return The folder where the region.yml files are in
*/
String getRegionFolder();
/**
* Check if a region is on the adding blacklist.
*
* @param region The region name to check
* @return true if the region may not be added, otherwise false
*/
boolean isBlacklisted(String region);
/**
* Unrent regions that have no time left, regions to check per tick is in the config.
*/
void checkRents();
/**
* Check all regions and unrent/sell them if the player is inactive for too long.
*/
void checkForInactiveRegions();
/**
* Load the file with the versions, used to check if the other files need conversion.
*/
@SuppressWarnings("unchecked")
void loadVersions();
/**
* Save the versions file to disk.
*/
void saveVersions();
/**
* Load all files from disk.
*
* @param thisTick Load files in the current tick or a tick later
* @return true if the files are loaded correctly, otherwise false
*/
boolean loadFiles(boolean thisTick);
/**
* Load the default.yml file
*
* @return true if it has been loaded successfully, otherwise false
*/
boolean loadDefaultFile();
/**
* Load the default.yml file
*
* @return true if it has been loaded successfully, otherwise false
*/
boolean loadConfigFile();
/**
* Load the groups.yml file from disk
*
* @return true if succeeded, otherwise false
*/
boolean loadGroupsFile();
/**
* Load all region files.
*/
void loadRegionFiles();
/**
* Get the settings of a group.
*
* @param groupName Name of the group to get the settings from
* @return The settings of the group
*/
ConfigurationSection getGroupSettings(String groupName);
/**
* Set a setting for a group.
*
* @param group The group to set it for
* @param path The path to set
* @param setting The value to set
*/
void setGroupSetting(RegionGroup group, String path, Object setting);
// Enum for region types
public enum AddResult {
BLACKLISTED("blacklisted"),
NOPERMISSION("nopermission"),
ALREADYADDED("alreadyadded"),
ALREADYADDEDOTHERWORLD("alreadyaddedotherworld"),
SUCCESS("success");
private final String value;
AddResult(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
}
@@ -1,11 +1,7 @@
package me.wiefferink.areashop.managers;
import me.wiefferink.areashop.AreaShop;
public abstract class Manager {
final AreaShop plugin = AreaShop.getInstance();
/**
* Called at shutdown of the plugin.
*/
@@ -0,0 +1,79 @@
package me.wiefferink.areashop.managers;
import me.wiefferink.areashop.AreaShop;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
import java.sql.Date;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.StringJoiner;
import java.util.concurrent.atomic.AtomicBoolean;
public class SignErrorLogger {
public static final String PREFIX_WARN = "[Warning] [Sign Feature] ";
public static final DateFormat FORMAT = new SimpleDateFormat("MM/dd/yy HH:mm:ss");
private final List<String> cache = new LinkedList<>();
private final AtomicBoolean needsSaving = new AtomicBoolean(false);
private final File file;
public SignErrorLogger(File file) {
this.file = Objects.requireNonNull(file);
}
public void clearCache() {
synchronized (this.cache) {
this.cache.clear();
}
}
public SignErrorLogger submitWarning(String message) {
final String actual = FORMAT.format(Date.from(Instant.now())) + PREFIX_WARN + message;
synchronized (this.cache) {
this.cache.add(actual);
}
return this;
}
public void queueSave() {
this.needsSaving.set(true);
}
public void saveIfDirty() {
if (this.needsSaving.get()) {
save();
}
}
public synchronized void save() {
AreaShop.debugTask("[Sign Feature] Dumping sign errors to disk...");
final String[] copy;
synchronized (this.cache) {
copy = cache.toArray(new String[0]);
}
final StringJoiner joiner = new StringJoiner(System.lineSeparator());
for (String s : copy) {
joiner.add(s);
}
try (OutputStream os = new FileOutputStream(file);
OutputStreamWriter writer = new OutputStreamWriter(os, StandardCharsets.UTF_8)) {
writer.write(joiner.toString());
} catch (IOException ex) {
ex.printStackTrace();
AreaShop.error("Failed to update the sign error log!");
} finally {
AreaShop.debugTask("[Sign Feature] Error dump complete.");
}
}
}
@@ -1,8 +1,12 @@
package me.wiefferink.areashop.managers;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.features.signs.RegionSign;
import me.wiefferink.areashop.features.signs.SignsFeature;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.tools.Materials;
import me.wiefferink.areashop.tools.SignUtils;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
@@ -17,21 +21,31 @@ import org.bukkit.event.Listener;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.material.Sign;
import org.bukkit.util.BlockIterator;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
@Singleton
public class SignLinkerManager extends Manager implements Listener {
private final Map<UUID, SignLinker> signLinkers;
private boolean eventsRegistered;
public SignLinkerManager() {
@Inject
private AreaShop plugin;
@Inject
private SignManager signManager;
@Inject
private MessageBridge messageBridge;
SignLinkerManager() {
signLinkers = new HashMap<>();
eventsRegistered = false;
}
@@ -50,8 +64,8 @@ public class SignLinkerManager extends Manager implements Listener {
*/
public void enterSignLinkMode(Player player, String profile) {
signLinkers.put(player.getUniqueId(), new SignLinker(player, profile));
plugin.message(player, "linksigns-first");
plugin.message(player, "linksigns-next");
messageBridge.message(player, "linksigns-first");
messageBridge.message(player, "linksigns-next");
if(!eventsRegistered) {
eventsRegistered = true;
plugin.getServer().getPluginManager().registerEvents(this, plugin);
@@ -68,7 +82,7 @@ public class SignLinkerManager extends Manager implements Listener {
eventsRegistered = false;
HandlerList.unregisterAll(this);
}
plugin.message(player, "linksigns-stopped");
messageBridge.message(player, "linksigns-stopped");
}
/**
@@ -104,13 +118,13 @@ public class SignLinkerManager extends Manager implements Listener {
for(GeneralRegion region : regions) {
names.add(region.getName());
}
plugin.message(player, "linksigns-multipleRegions", Utils.createCommaSeparatedList(names));
plugin.message(player, "linksigns-multipleRegionsAdvice");
messageBridge.message(player, "linksigns-multipleRegions", Utils.createCommaSeparatedList(names));
messageBridge.message(player, "linksigns-multipleRegionsAdvice");
return;
}
}
// No regions found within the maximum range
plugin.message(player, "linksigns-noRegions");
messageBridge.message(player, "linksigns-noRegions");
} else if(event.getAction() == Action.LEFT_CLICK_AIR || event.getAction() == Action.LEFT_CLICK_BLOCK) {
Block block = null;
BlockIterator blockIterator = new BlockIterator(player, 100);
@@ -120,18 +134,18 @@ public class SignLinkerManager extends Manager implements Listener {
block = next;
}
}
if(block == null || !(block.getType() == Material.WALL_SIGN || block.getType() == Material.SIGN_POST)) {
plugin.message(player, "linksigns-noSign");
if(block == null || !Materials.isSign(block.getType())) {
messageBridge.message(player, "linksigns-noSign");
return;
}
RegionSign regionSign = SignsFeature.getSignByLocation(block.getLocation());
if(regionSign != null) {
plugin.message(player, "linksigns-alreadyRegistered", regionSign.getRegion());
Optional<RegionSign> optional = signManager.signFromLocation(block.getLocation());
if(optional.isPresent()) {
RegionSign regionSign = optional.get();
messageBridge.message(player, "linksigns-alreadyRegistered", regionSign.getRegion());
return;
}
Sign sign = (Sign)block.getState().getData();
linker.setSign(block.getLocation(), block.getType(), sign.getFacing());
linker.setSign(block.getLocation(), block.getType(), SignUtils.getSignFacing(block));
}
}
}
@@ -170,7 +184,7 @@ public class SignLinkerManager extends Manager implements Listener {
this.region = region;
hasRegion = true;
if(!isComplete()) {
plugin.message(linker, "linksigns-regionFound", region);
messageBridge.message(linker, "linksigns-regionFound", region);
}
finish();
}
@@ -181,7 +195,7 @@ public class SignLinkerManager extends Manager implements Listener {
this.facing = facing;
hasSign = true;
if(!isComplete()) {
plugin.message(linker, "linksigns-signFound", location.getBlockX(), location.getBlockY(), location.getBlockZ());
messageBridge.message(linker, "linksigns-signFound", location.getBlockX(), location.getBlockY(), location.getBlockZ());
}
finish();
}
@@ -190,14 +204,14 @@ public class SignLinkerManager extends Manager implements Listener {
if(isComplete()) {
region.getSignsFeature().addSign(location, type, facing, profile);
if(profile == null) {
plugin.message(linker, "addsign-success", region);
messageBridge.message(linker, "addsign-success", region);
} else {
plugin.message(linker, "addsign-successProfile", region, profile);
messageBridge.message(linker, "addsign-successProfile", region, profile);
}
region.update();
reset();
plugin.message(linker, "linksigns-next");
messageBridge.message(linker, "linksigns-next");
}
}
@@ -0,0 +1,74 @@
package me.wiefferink.areashop.modules;
import com.google.inject.AbstractModule;
import com.google.inject.Singleton;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.features.FeatureFactory;
import me.wiefferink.areashop.features.signs.SignsModule;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.CommandManager;
import me.wiefferink.areashop.managers.FeatureManager;
import me.wiefferink.areashop.managers.FileManager;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.managers.SignErrorLogger;
import me.wiefferink.areashop.managers.SignLinkerManager;
import me.wiefferink.areashop.nms.NMS;
import me.wiefferink.areashop.regions.ImportJobFactory;
import me.wiefferink.areashop.regions.RegionModule;
import me.wiefferink.areashop.tools.Utils;
import org.bukkit.plugin.Plugin;
import javax.annotation.Nonnull;
import java.util.Arrays;
public class AreaShopModule extends AbstractModule {
private final AreaShop instance;
private final WorldGuardInterface worldGuardInterface;
private final WorldEditInterface worldEditInterface;
private final NMS nms;
private final MessageBridge messageBridge;
private final SignErrorLogger signErrorLogger;
private final AbstractModule[] extras;
public AreaShopModule(@Nonnull AreaShop instance,
@Nonnull MessageBridge messageBridge,
@Nonnull NMS nms,
@Nonnull WorldEditInterface worldEditInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull SignErrorLogger signErrorLogger,
@Nonnull AbstractModule... extras
) {
this.instance = instance;
this.messageBridge = messageBridge;
this.nms = nms;
this.signErrorLogger = signErrorLogger;
this.worldEditInterface = worldEditInterface;
this.worldGuardInterface = worldGuardInterface;
this.extras = extras;
}
@Override
protected void configure() {
Arrays.stream(this.extras).forEach(this::install);
bind(Plugin.class).toInstance(this.instance);
bind(AreaShop.class).toInstance(this.instance);
bind(MessageBridge.class).toInstance(this.messageBridge);
bind(WorldGuardInterface.class).toInstance(this.worldGuardInterface);
bind(WorldEditInterface.class).toInstance(this.worldEditInterface);
bind(SignErrorLogger.class).toInstance(this.signErrorLogger);
// Setup managers
bind(IFileManager.class).to(FileManager.class).asEagerSingleton();
bind(FeatureManager.class).in(Singleton.class);
bind(CommandManager.class).in(Singleton.class);
bind(SignLinkerManager.class).in(Singleton.class);
install(new SignsModule());
install(new RegionModule());
install(new FactoryModuleBuilder().build(FeatureFactory.class));
install(new FactoryModuleBuilder().build(ImportJobFactory.class));
requestStaticInjection(Utils.class);
}
}
@@ -0,0 +1,34 @@
package me.wiefferink.areashop.modules;
import com.google.inject.AbstractModule;
import org.bukkit.Server;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.inventory.ItemFactory;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.ServicesManager;
import org.bukkit.scheduler.BukkitScheduler;
import org.bukkit.scoreboard.ScoreboardManager;
import javax.annotation.Nonnull;
public class BukkitModule extends AbstractModule {
private final Server server;
public BukkitModule(@Nonnull Server server) {
this.server = server;
}
@Override
protected void configure() {
bind(Server.class).toInstance(this.server);
bind(PluginManager.class).toInstance(this.server.getPluginManager());
bind(BukkitScheduler.class).toInstance(this.server.getScheduler());
bind(PluginManager.class).toInstance(this.server.getPluginManager());
bind(ServicesManager.class).toInstance(this.server.getServicesManager());
bind(ItemFactory.class).toInstance(this.server.getItemFactory());
bind(ConsoleCommandSender.class).toInstance(this.server.getConsoleSender());
bind(ScoreboardManager.class).toInstance(this.server.getScoreboardManager());
}
}
@@ -0,0 +1,37 @@
package me.wiefferink.areashop.modules;
import com.google.inject.AbstractModule;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.permission.Permission;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class DependencyModule extends AbstractModule {
private final WorldEditPlugin worldEditPlugin;
private final WorldGuardPlugin worldGuardPlugin;
private final Economy economy;
private final Permission permission;
public DependencyModule(@Nonnull WorldEditPlugin worldEditPlugin,
@Nonnull WorldGuardPlugin worldGuardPlugin,
@Nullable Economy economy,
@Nullable Permission permission
) {
this.worldEditPlugin = worldEditPlugin;
this.worldGuardPlugin = worldGuardPlugin;
this.economy = economy;
this.permission = permission;
}
@Override
protected void configure() {
bind(WorldEditPlugin.class).toInstance(this.worldEditPlugin);
bind(WorldGuardPlugin.class).toInstance(this.worldGuardPlugin);
bind(Economy.class).toInstance(this.economy);
bind(Permission.class).toInstance(this.permission);
}
}
@@ -0,0 +1,29 @@
package me.wiefferink.areashop.modules;
import com.google.inject.AbstractModule;
import me.wiefferink.areashop.adapters.platform.MinecraftPlatform;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import me.wiefferink.areashop.nms.BlockBehaviourHelper;
import me.wiefferink.areashop.nms.NMS;
import me.wiefferink.areashop.tools.BukkitSchedulerExecutor;
import org.jetbrains.annotations.NotNull;
public class PlatformModule extends AbstractModule {
private final MinecraftPlatform minecraftPlatform;
private final NMS nms;
public PlatformModule(@NotNull MinecraftPlatform platform,
@NotNull NMS nms) {
this.minecraftPlatform = platform;
this.nms = nms;
}
@Override
protected void configure() {
bind(MinecraftPlatform.class).toInstance(this.minecraftPlatform);
bind(OfflinePlayerHelper.class).toInstance(this.minecraftPlatform.offlinePlayerHelper());
bind(NMS.class).toInstance(this.nms);
bind(BlockBehaviourHelper.class).toInstance(this.nms.blockBehaviourHelper());
bind(BukkitSchedulerExecutor.class).asEagerSingleton();
}
}
@@ -1,5 +1,7 @@
package me.wiefferink.areashop.regions;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.events.ask.BuyingRegionEvent;
import me.wiefferink.areashop.events.ask.ResellingRegionEvent;
@@ -7,7 +9,11 @@ import me.wiefferink.areashop.events.ask.SellingRegionEvent;
import me.wiefferink.areashop.events.notify.BoughtRegionEvent;
import me.wiefferink.areashop.events.notify.ResoldRegionEvent;
import me.wiefferink.areashop.events.notify.SoldRegionEvent;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.FeatureManager;
import me.wiefferink.areashop.tools.Utils;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
@@ -16,17 +22,55 @@ import org.bukkit.command.CommandSender;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Calendar;
import java.util.UUID;
public class BuyRegion extends GeneralRegion {
public BuyRegion(YamlConfiguration config) {
super(config);
private final Economy economy;
@AssistedInject
BuyRegion(
@Nonnull AreaShop plugin,
@Nonnull FeatureManager featureManager,
@Nonnull WorldEditInterface worldEditInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nullable Economy economy,
@Assisted @Nonnull YamlConfiguration config
) {
super(plugin, featureManager, worldEditInterface, worldGuardInterface, config);
this.economy = economy;
}
public BuyRegion(String name, World world) {
super(name, world);
@AssistedInject
BuyRegion(
@Nonnull AreaShop plugin,
@Nonnull FeatureManager featureManager,
@Nonnull WorldEditInterface worldEditInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nullable Economy economy,
@Assisted @Nonnull String name,
@Assisted @Nonnull World world
) {
super(plugin, featureManager, worldEditInterface, worldGuardInterface, name, world);
this.economy = economy;
}
@Override
public boolean isOwner(UUID player) {
return isBuyer(player);
}
@Override
public UUID getOwner() {
return getBuyer();
}
@Override
public void setOwner(UUID player) {
setBuyer(player);
}
@Override
@@ -208,31 +252,20 @@ public class BuyRegion extends GeneralRegion {
@Override
public Object provideReplacement(String variable) {
switch(variable) {
case AreaShop.tagPrice:
return getFormattedPrice();
case AreaShop.tagRawPrice:
return getPrice();
case AreaShop.tagPlayerName:
return getPlayerName();
case AreaShop.tagPlayerUUID:
return getBuyer();
case AreaShop.tagResellPrice:
return getFormattedResellPrice();
case AreaShop.tagRawResellPrice:
return getResellPrice();
case AreaShop.tagMoneyBackAmount:
return getFormattedMoneyBackAmount();
case AreaShop.tagRawMoneyBackAmount:
return getMoneyBackAmount();
case AreaShop.tagMoneyBackPercentage:
return getMoneyBackPercentage() % 1.0 == 0.0 ? (int)getMoneyBackPercentage() : getMoneyBackPercentage();
case AreaShop.tagMaxInactiveTime:
return this.getFormattedInactiveTimeUntilSell();
default:
return super.provideReplacement(variable);
}
return switch (variable) {
case AreaShop.tagPrice -> getFormattedPrice();
case AreaShop.tagRawPrice -> getPrice();
case AreaShop.tagPlayerName -> getPlayerName();
case AreaShop.tagPlayerUUID -> getBuyer();
case AreaShop.tagResellPrice -> getFormattedResellPrice();
case AreaShop.tagRawResellPrice -> getResellPrice();
case AreaShop.tagMoneyBackAmount -> getFormattedMoneyBackAmount();
case AreaShop.tagRawMoneyBackAmount -> getMoneyBackAmount();
case AreaShop.tagMoneyBackPercentage ->
getMoneyBackPercentage() % 1.0 == 0.0 ? (int) getMoneyBackPercentage() : getMoneyBackPercentage();
case AreaShop.tagMaxInactiveTime -> this.getFormattedInactiveTimeUntilSell();
default -> super.provideReplacement(variable);
};
}
/**
@@ -259,189 +292,187 @@ public class BuyRegion extends GeneralRegion {
@SuppressWarnings("deprecation")
public boolean buy(OfflinePlayer offlinePlayer) {
// Check if the player has permission
if(plugin.hasPermission(offlinePlayer, "areashop.buy")) {
if(plugin.getEconomy() == null) {
message(offlinePlayer, "general-noEconomy");
if(!plugin.hasPermission(offlinePlayer, "areashop.buy")) {
message(offlinePlayer, "buy-noPermission");
return false;
}
if(economy == null) {
message(offlinePlayer, "general-noEconomy");
return false;
}
if(isInResellingMode()) {
if(!plugin.hasPermission(offlinePlayer, "areashop.buyresell")) {
message(offlinePlayer, "buy-noPermissionResell");
return false;
}
if(isInResellingMode()) {
if(!plugin.hasPermission(offlinePlayer, "areashop.buyresell")) {
message(offlinePlayer, "buy-noPermissionResell");
return false;
}
} else {
if(!plugin.hasPermission(offlinePlayer, "areashop.buynormal")) {
message(offlinePlayer, "buy-noPermissionNoResell");
return false;
}
}
if(getWorld() == null) {
message(offlinePlayer, "general-noWorld");
return false;
}
if(getRegion() == null) {
message(offlinePlayer, "general-noRegion");
return false;
}
if(!isSold() || (isInResellingMode() && !isBuyer(offlinePlayer))) {
boolean isResell = isInResellingMode();
// Only relevant if the player is online
Player player = offlinePlayer.getPlayer();
if(player != null) {
// Check if the players needs to be in the region for buying
if(restrictedToRegion() && (!player.getWorld().getName().equals(getWorldName())
|| !getRegion().contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()))) {
message(offlinePlayer, "buy-restrictedToRegion");
return false;
}
// Check if the players needs to be in the world for buying
if(restrictedToWorld() && !player.getWorld().getName().equals(getWorldName())) {
message(offlinePlayer, "buy-restrictedToWorld", player.getWorld().getName());
return false;
}
}
// Check region limits
LimitResult limitResult = this.limitsAllow(RegionType.BUY, offlinePlayer);
AreaShop.debug("LimitResult: " + limitResult.toString());
if(!limitResult.actionAllowed()) {
if(limitResult.getLimitingFactor() == LimitType.TOTAL) {
message(offlinePlayer, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
if(limitResult.getLimitingFactor() == LimitType.BUYS) {
message(offlinePlayer, "buy-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
// Should not be reached, but is safe like this
return false;
}
// Check if the player has enough money
if((!isResell && plugin.getEconomy().has(offlinePlayer, getWorldName(), getPrice())) || (isResell && plugin.getEconomy().has(offlinePlayer, getWorldName(), getResellPrice()))) {
UUID oldOwner = getBuyer();
if(isResell && oldOwner != null) {
// Broadcast and check event
ResellingRegionEvent event = new ResellingRegionEvent(this, offlinePlayer);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(offlinePlayer, "general-cancelled", event.getReason());
return false;
}
getFriendsFeature().clearFriends();
double resellPrice = getResellPrice();
// Transfer the money to the previous owner
EconomyResponse r = plugin.getEconomy().withdrawPlayer(offlinePlayer, getWorldName(), getResellPrice());
if(!r.transactionSuccess()) {
message(offlinePlayer, "buy-payError");
AreaShop.debug("Something went wrong with getting money from " + offlinePlayer.getName() + " while buying " + getName() + ": " + r.errorMessage);
return false;
}
r = null;
OfflinePlayer oldOwnerPlayer = Bukkit.getOfflinePlayer(oldOwner);
String oldOwnerName = getPlayerName();
if(oldOwnerPlayer != null && oldOwnerPlayer.getName() != null) {
r = plugin.getEconomy().depositPlayer(oldOwnerPlayer, getWorldName(), getResellPrice());
oldOwnerName = oldOwnerPlayer.getName();
} else if(oldOwnerName != null) {
r = plugin.getEconomy().depositPlayer(oldOwnerName, getWorldName(), getResellPrice());
}
if(r == null || !r.transactionSuccess()) {
AreaShop.warn("Something went wrong with paying '" + oldOwnerName + "' " + getFormattedPrice() + " for his resell of region " + getName() + " to " + offlinePlayer.getName());
}
// Resell is done, disable that now
disableReselling();
// Run commands
this.runEventCommands(RegionEvent.RESELL, true);
// Set the owner
setBuyer(offlinePlayer.getUniqueId());
updateLastActiveTime();
// Update everything
handleSchematicEvent(RegionEvent.RESELL);
// Notify about updates
this.notifyAndUpdate(new ResoldRegionEvent(this, oldOwner));
// Send message to the player
message(offlinePlayer, "buy-successResale", oldOwnerName);
Player seller = Bukkit.getPlayer(oldOwner);
if(seller != null) {
message(seller, "buy-successSeller", resellPrice);
}
// Run commands
this.runEventCommands(RegionEvent.RESELL, false);
} else {
// Broadcast and check event
BuyingRegionEvent event = new BuyingRegionEvent(this, offlinePlayer);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(offlinePlayer, "general-cancelled", event.getReason());
return false;
}
// Substract the money from the players balance
EconomyResponse r = plugin.getEconomy().withdrawPlayer(offlinePlayer, getWorldName(), getPrice());
if(!r.transactionSuccess()) {
message(offlinePlayer, "buy-payError");
return false;
}
// Optionally give money to the landlord
OfflinePlayer landlordPlayer = null;
if(getLandlord() != null) {
landlordPlayer = Bukkit.getOfflinePlayer(getLandlord());
}
String landlordName = getLandlordName();
if(landlordName != null) {
if(landlordPlayer != null && landlordPlayer.getName() != null) {
r = plugin.getEconomy().depositPlayer(landlordPlayer, getWorldName(), getPrice());
} else {
r = plugin.getEconomy().depositPlayer(landlordName, getWorldName(), getPrice());
}
if(r != null && !r.transactionSuccess()) {
AreaShop.warn("Something went wrong with paying '" + landlordName + "' " + getFormattedPrice() + " for his sell of region " + getName() + " to " + offlinePlayer.getName());
}
}
// Run commands
this.runEventCommands(RegionEvent.BOUGHT, true);
// Set the owner
setBuyer(offlinePlayer.getUniqueId());
updateLastActiveTime();
// Notify about updates
this.notifyAndUpdate(new BoughtRegionEvent(this));
// Update everything
handleSchematicEvent(RegionEvent.BOUGHT);
// Send message to the player
message(offlinePlayer, "buy-succes");
// Run commands
this.runEventCommands(RegionEvent.BOUGHT, false);
}
return true;
} else {
// Player has not enough money
if(isResell) {
message(offlinePlayer, "buy-lowMoneyResell", Utils.formatCurrency(plugin.getEconomy().getBalance(offlinePlayer, getWorldName())));
} else {
message(offlinePlayer, "buy-lowMoney", Utils.formatCurrency(plugin.getEconomy().getBalance(offlinePlayer, getWorldName())));
}
}
} else {
if(isBuyer(offlinePlayer)) {
message(offlinePlayer, "buy-yours");
} else {
message(offlinePlayer, "buy-someoneElse");
}
}
} else {
message(offlinePlayer, "buy-noPermission");
if(!plugin.hasPermission(offlinePlayer, "areashop.buynormal")) {
message(offlinePlayer, "buy-noPermissionNoResell");
return false;
}
}
return false;
if(getWorld() == null) {
message(offlinePlayer, "general-noWorld");
return false;
}
if(getRegion() == null) {
message(offlinePlayer, "general-noRegion");
return false;
}
if (isSold() && !(isInResellingMode() && !isBuyer(offlinePlayer))) {
if(isBuyer(offlinePlayer)) {
message(offlinePlayer, "buy-yours");
} else {
message(offlinePlayer, "buy-someoneElse");
}
return false;
}
boolean isResell = isInResellingMode();
// Only relevant if the player is online
Player player = offlinePlayer.getPlayer();
if(player != null) {
// Check if the players needs to be in the region for buying
if(restrictedToRegion() && (!player.getWorld().getName().equals(getWorldName())
|| !getRegion().contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()))) {
message(offlinePlayer, "buy-restrictedToRegion");
return false;
}
// Check if the players needs to be in the world for buying
if(restrictedToWorld() && !player.getWorld().getName().equals(getWorldName())) {
message(offlinePlayer, "buy-restrictedToWorld", player.getWorld().getName());
return false;
}
}
// Check region limits
LimitResult limitResult = this.limitsAllow(RegionType.BUY, offlinePlayer);
AreaShop.debug("LimitResult: " + limitResult.toString());
if(!limitResult.actionAllowed()) {
if(limitResult.getLimitingFactor() == LimitType.TOTAL) {
message(offlinePlayer, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
if(limitResult.getLimitingFactor() == LimitType.BUYS) {
message(offlinePlayer, "buy-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
// Should not be reached, but is safe like this
return false;
}
// Check if the player has enough money
if (isResell && !economy.has(offlinePlayer, getWorldName(), getResellPrice())) {
message(offlinePlayer, "buy-lowMoneyResell", Utils.formatCurrency(economy.getBalance(offlinePlayer, getWorldName())));
return false;
}
if (!isResell && !economy.has(offlinePlayer, getWorldName(), getPrice())) {
message(offlinePlayer, "buy-lowMoney", Utils.formatCurrency(economy.getBalance(offlinePlayer, getWorldName())));
return false;
}
UUID oldOwner = getBuyer();
if(isResell && oldOwner != null) {
// Broadcast and check event
ResellingRegionEvent event = new ResellingRegionEvent(this, offlinePlayer);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(offlinePlayer, "general-cancelled", event.getReason());
return false;
}
getFriendsFeature().clearFriends();
double resellPrice = getResellPrice();
// Transfer the money to the previous owner
EconomyResponse r = economy.withdrawPlayer(offlinePlayer, getWorldName(), getResellPrice());
if(!r.transactionSuccess()) {
message(offlinePlayer, "buy-payError");
AreaShop.debug("Something went wrong with getting money from " + offlinePlayer.getName() + " while buying " + getName() + ": " + r.errorMessage);
return false;
}
r = null;
OfflinePlayer oldOwnerPlayer = Bukkit.getOfflinePlayer(oldOwner);
String oldOwnerName = getPlayerName();
if(oldOwnerPlayer != null && oldOwnerPlayer.getName() != null) {
r = economy.depositPlayer(oldOwnerPlayer, getWorldName(), getResellPrice());
oldOwnerName = oldOwnerPlayer.getName();
} else if(oldOwnerName != null) {
r = economy.depositPlayer(oldOwnerName, getWorldName(), getResellPrice());
}
if(r == null || !r.transactionSuccess()) {
AreaShop.warn("Something went wrong with paying '" + oldOwnerName + "' " + getFormattedPrice() + " for his resell of region " + getName() + " to " + offlinePlayer.getName());
}
// Resell is done, disable that now
disableReselling();
// Set the owner
setBuyer(offlinePlayer.getUniqueId());
updateLastActiveTime();
// Update everything
handleSchematicEvent(RegionEvent.RESELL);
// Notify about updates
this.notifyAndUpdate(new ResoldRegionEvent(this, oldOwner));
// Send message to the player
message(offlinePlayer, "buy-successResale", oldOwnerName);
Player seller = Bukkit.getPlayer(oldOwner);
if(seller != null) {
message(seller, "buy-successSeller", resellPrice);
}
} else {
// Broadcast and check event
BuyingRegionEvent event = new BuyingRegionEvent(this, offlinePlayer);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(offlinePlayer, "general-cancelled", event.getReason());
return false;
}
// Substract the money from the players balance
EconomyResponse r = economy.withdrawPlayer(offlinePlayer, getWorldName(), getPrice());
if(!r.transactionSuccess()) {
message(offlinePlayer, "buy-payError");
return false;
}
// Optionally give money to the landlord
OfflinePlayer landlordPlayer = null;
if(getLandlord() != null) {
landlordPlayer = Bukkit.getOfflinePlayer(getLandlord());
}
String landlordName = getLandlordName();
if(landlordName != null) {
if(landlordPlayer != null && landlordPlayer.getName() != null) {
r = economy.depositPlayer(landlordPlayer, getWorldName(), getPrice());
} else {
r = economy.depositPlayer(landlordName, getWorldName(), getPrice());
}
if(r != null && !r.transactionSuccess()) {
AreaShop.warn("Something went wrong with paying '" + landlordName + "' " + getFormattedPrice() + " for his sell of region " + getName() + " to " + offlinePlayer.getName());
}
}
// Set the owner
setBuyer(offlinePlayer.getUniqueId());
updateLastActiveTime();
// Send message to the player
message(offlinePlayer, "buy-succes");
// Update everything
handleSchematicEvent(RegionEvent.BOUGHT);
// Notify about updates
this.notifyAndUpdate(new BoughtRegionEvent(this));
}
return true;
}
/**
@@ -452,7 +483,7 @@ public class BuyRegion extends GeneralRegion {
*/
@SuppressWarnings("deprecation")
public boolean sell(boolean giveMoneyBack, CommandSender executor) {
boolean own = executor instanceof Player && this.isBuyer((Player)executor);
boolean own = executor instanceof Player player && this.isBuyer(player);
if(executor != null) {
if(!executor.hasPermission("areashop.sell") && !own) {
message(executor, "sell-noPermissionOther");
@@ -471,7 +502,7 @@ public class BuyRegion extends GeneralRegion {
}
}
if(plugin.getEconomy() == null) {
if(economy == null) {
return false;
}
@@ -483,9 +514,6 @@ public class BuyRegion extends GeneralRegion {
return false;
}
// Run commands
this.runEventCommands(RegionEvent.SOLD, true);
disableReselling();
// Give part of the buying price back
double moneyBack = getMoneyBackAmount();
@@ -499,9 +527,9 @@ public class BuyRegion extends GeneralRegion {
EconomyResponse r;
if(landlordName != null) {
if(landlordPlayer != null && landlordPlayer.getName() != null) {
r = plugin.getEconomy().withdrawPlayer(landlordPlayer, getWorldName(), moneyBack);
r = economy.withdrawPlayer(landlordPlayer, getWorldName(), moneyBack);
} else {
r = plugin.getEconomy().withdrawPlayer(landlordName, getWorldName(), moneyBack);
r = economy.withdrawPlayer(landlordName, getWorldName(), moneyBack);
}
if(r == null || !r.transactionSuccess()) {
noPayBack = true;
@@ -510,14 +538,14 @@ public class BuyRegion extends GeneralRegion {
// Give back the money
OfflinePlayer player = Bukkit.getOfflinePlayer(getBuyer());
if(player != null && !noPayBack) {
if(player.hasPlayedBefore() && !noPayBack) {
EconomyResponse response = null;
boolean error = false;
try {
if(player.getName() != null) {
response = plugin.getEconomy().depositPlayer(player, getWorldName(), moneyBack);
response = economy.depositPlayer(player, getWorldName(), moneyBack);
} else if(getPlayerName() != null) {
response = plugin.getEconomy().depositPlayer(getPlayerName(), getWorldName(), moneyBack);
response = economy.depositPlayer(getPlayerName(), getWorldName(), moneyBack);
}
} catch(Exception e) {
error = true;
@@ -528,11 +556,12 @@ public class BuyRegion extends GeneralRegion {
}
}
message(executor, "sell-sold");
// Handle schematic save/restore (while %uuid% is still available)
handleSchematicEvent(RegionEvent.SOLD);
// Send message: before actual removal of the buyer so that it is still available for variables
message(executor, "sell-sold");
// Remove friends and the owner
getFriendsFeature().clearFriends();
UUID oldBuyer = getBuyer();
@@ -541,9 +570,6 @@ public class BuyRegion extends GeneralRegion {
// Notify about updates
this.notifyAndUpdate(new SoldRegionEvent(this, oldBuyer, Math.max(moneyBack, 0)));
// Run commands
this.runEventCommands(RegionEvent.SOLD, false);
return true;
}
@@ -1,7 +1,5 @@
package me.wiefferink.areashop.regions;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.BlockVector2D;
import com.sk89q.worldguard.protection.regions.ProtectedPolygonalRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import me.wiefferink.areashop.AreaShop;
@@ -12,7 +10,10 @@ import me.wiefferink.areashop.features.RegionFeature;
import me.wiefferink.areashop.features.TeleportFeature;
import me.wiefferink.areashop.features.signs.SignsFeature;
import me.wiefferink.areashop.interfaces.GeneralRegionInterface;
import me.wiefferink.areashop.managers.FileManager;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.FeatureManager;
import me.wiefferink.areashop.managers.IFileManager;
import me.wiefferink.areashop.tools.Utils;
import me.wiefferink.bukkitdo.Do;
import me.wiefferink.interactivemessenger.processing.Message;
@@ -27,23 +28,34 @@ import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import javax.annotation.Nonnull;
import java.awt.geom.Area;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public abstract class GeneralRegion implements GeneralRegionInterface, Comparable<GeneralRegion>, ReplacementProvider {
static final AreaShop plugin = AreaShop.getInstance();
final YamlConfiguration config;
protected final AreaShop plugin;
protected final FeatureManager featureManager;
protected final WorldEditInterface worldEditInterface;
protected final WorldGuardInterface worldGuardInterface;
protected final YamlConfiguration config;
private boolean saveRequired = false;
private boolean deleted = false;
private long volume = -1;
@@ -147,7 +159,17 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* Constructor, used to restore regions from disk at startup.
* @param config The configuration of the region
*/
public GeneralRegion(YamlConfiguration config) {
protected GeneralRegion(
@Nonnull AreaShop plugin,
@Nonnull FeatureManager featureManager,
@Nonnull WorldEditInterface worldEditInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull YamlConfiguration config
) {
this.plugin = plugin;
this.featureManager = featureManager;
this.worldEditInterface = worldEditInterface;
this.worldGuardInterface = worldGuardInterface;
this.config = config;
setup();
}
@@ -157,8 +179,17 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* @param name Name of the WorldGuard region that this region is attached to
* @param world The world of the WorldGuard region
*/
public GeneralRegion(String name, World world) {
config = new YamlConfiguration();
protected GeneralRegion(@Nonnull AreaShop plugin,
@Nonnull FeatureManager featureManager,
@Nonnull WorldEditInterface worldEditInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull String name,
@Nonnull World world) {
this.config = new YamlConfiguration();
this.plugin = plugin;
this.featureManager = featureManager;
this.worldGuardInterface = worldGuardInterface;
this.worldEditInterface = worldEditInterface;
setSetting("general.name", name);
setSetting("general.world", world.getName());
setSetting("general.type", getType().getValue().toLowerCase());
@@ -184,15 +215,16 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
/**
* Get a feature of this region.
* @param clazz The class of the feature to get
* @return The feature (either just instanciated or cached)
* @param <T> The feature to get
* @return The feature (either just instantiated or cached)
*/
public RegionFeature getFeature(Class<? extends RegionFeature> clazz) {
RegionFeature result = features.get(clazz);
if(result == null) {
result = plugin.getFeatureManager().getRegionFeature(this, clazz);
features.put(clazz, result);
}
return result;
public <T extends RegionFeature> T getOrCreateFeature(Class<T> clazz) {
RegionFeature result = features.computeIfAbsent(clazz, x -> featureManager.getRegionFeature(this, clazz));
return clazz.cast(result);
}
public <T extends RegionFeature> Optional<T> getFeature(Class<T> clazz) {
return Optional.ofNullable(clazz.cast(features.get(clazz)));
}
/**
@@ -200,7 +232,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* @return The FriendsFeature of this region
*/
public FriendsFeature getFriendsFeature() {
return (FriendsFeature)getFeature(FriendsFeature.class);
return getOrCreateFeature(FriendsFeature.class);
}
/**
@@ -208,7 +240,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* @return The SignsFeature of this region
*/
public SignsFeature getSignsFeature() {
return (SignsFeature)getFeature(SignsFeature.class);
return getOrCreateFeature(SignsFeature.class);
}
/**
@@ -216,7 +248,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* @return The TeleportFeature
*/
public TeleportFeature getTeleportFeature() {
return (TeleportFeature)getFeature(TeleportFeature.class);
return getOrCreateFeature(TeleportFeature.class);
}
// ABSTRACT
@@ -312,6 +344,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* Get the name of the region.
* @return The region name
*/
@Override
public String getName() {
return config.getString("general.name");
}
@@ -321,7 +354,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* @return The region name in lowercase
*/
public String getLowerCaseName() {
return getName().toLowerCase();
return getName().toLowerCase(Locale.ENGLISH);
}
/**
@@ -366,6 +399,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* Get the World of the region.
* @return The World where the region is located
*/
@Override
public World getWorld() {
return Bukkit.getWorld(getWorldName());
}
@@ -374,6 +408,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* Get the name of the world where the region is located.
* @return The name of the world of the region
*/
@Override
public String getWorldName() {
return getStringSetting("general.world");
}
@@ -382,7 +417,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* Get the FileManager from the plugin.
* @return The FileManager (responsible for saving/loading regions and getting them)
*/
public FileManager getFileManager() {
public IFileManager getFileManager() {
return plugin.getFileManager();
}
@@ -400,33 +435,18 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* @param player Player to check ownership for
* @return true if the player currently rents or buys this region
*/
public boolean isOwner(UUID player) {
return (this instanceof RentRegion && ((RentRegion)this).isRenter(player)) || (this instanceof BuyRegion && ((BuyRegion)this).isBuyer(player));
}
public abstract boolean isOwner(UUID player);
/**
* Get the player that is currently the owner of this region (either bought or rented it).
* @return The UUID of the owner of this region
*/
public UUID getOwner() {
if(this instanceof RentRegion) {
return ((RentRegion)this).getRenter();
} else {
return ((BuyRegion)this).getBuyer();
}
}
public abstract UUID getOwner();
/**
* Change the owner of the region.
* @param player The player that should be the owner
*/
public void setOwner(UUID player) {
if(this instanceof RentRegion) {
((RentRegion)this).setRenter(player);
} else {
((BuyRegion)this).setBuyer(player);
}
}
public abstract void setOwner(UUID player);
/**
* Get the landlord of this region (the player that receives any revenue from this region).
@@ -445,7 +465,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
if(landlordName != null && !landlordName.isEmpty()) {
@SuppressWarnings("deprecation")
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(landlordName);
if(offlinePlayer != null) {
if(offlinePlayer.hasPlayedBefore()) {
return offlinePlayer.getUniqueId();
}
}
@@ -458,7 +478,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
*/
public String getLandlordName() {
String result = Utils.toName(getLandlord());
if(result == null || result.isEmpty()) {
if(result.isEmpty()) {
result = config.getString("general.landlordName");
if(result == null || result.isEmpty()) {
result = null;
@@ -477,7 +497,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
setSetting("general.landlord", landlord.toString());
}
String properName = Utils.toName(landlord);
if(properName == null) {
if(properName.isBlank()) {
properName = name;
}
setSetting("general.landlordName", properName);
@@ -504,6 +524,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* Get the WorldGuard region associated with this AreaShop region.
* @return The ProtectedRegion of WorldGuard or null if the region does not exist anymore
*/
@Override
public ProtectedRegion getRegion() {
if(getWorld() == null
|| plugin.getWorldGuard() == null
@@ -514,37 +535,56 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
return plugin.getRegionManager(getWorld()).getRegion(getName());
}
/**
* Get the minimum corner of the region.
* @return Vector
*/
public Vector getMinimumPoint() {
return worldGuardInterface.getMinimumPoint(getRegion());
}
/**
* Get the maximum corner of the region.
* @return Vector
*/
public Vector getMaximumPoint() {
return worldGuardInterface.getMaximumPoint(getRegion());
}
/**
* Get the width of the region (x-axis).
* @return The width of the region (x-axis)
*/
@Override
public int getWidth() {
if(getRegion() == null) {
return 0;
}
return getRegion().getMaximumPoint().getBlockX() - getRegion().getMinimumPoint().getBlockX() + 1;
return getMaximumPoint().getBlockX() - getMinimumPoint().getBlockX() + 1;
}
/**
* Get the depth of the region (z-axis).
* @return The depth of the region (z-axis)
*/
@Override
public int getDepth() {
if(getRegion() == null) {
return 0;
}
return getRegion().getMaximumPoint().getBlockZ() - getRegion().getMinimumPoint().getBlockZ() + 1;
return getMaximumPoint().getBlockZ() - getMinimumPoint().getBlockZ() + 1;
}
/**
* Get the height of the region (y-axis).
* @return The height of the region (y-axis)
*/
@Override
public int getHeight() {
if(getRegion() == null) {
return 0;
}
return getRegion().getMaximumPoint().getBlockY() - getRegion().getMinimumPoint().getBlockY() + 1;
return getMaximumPoint().getBlockY() - getMinimumPoint().getBlockY() + 1;
}
/**
@@ -575,86 +615,96 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
@Override
public Object provideReplacement(String variable) {
switch(variable) {
switch (variable) {
// Basics
case AreaShop.tagRegionName:
case AreaShop.tagRegionName -> {
return getName();
case AreaShop.tagRegionType:
}
case AreaShop.tagRegionType -> {
return getType().getValue().toLowerCase();
case AreaShop.tagWorldName:
}
case AreaShop.tagWorldName -> {
return getWorldName();
case AreaShop.tagWidth:
}
case AreaShop.tagWidth -> {
return getWidth();
case AreaShop.tagDepth:
}
case AreaShop.tagDepth -> {
return getDepth();
case AreaShop.tagHeight:
}
case AreaShop.tagHeight -> {
return getHeight();
case AreaShop.tagFriends:
}
case AreaShop.tagFriends -> {
return Utils.createCommaSeparatedList(getFriendsFeature().getFriendNames());
case AreaShop.tagFriendsUUID:
}
case AreaShop.tagFriendsUUID -> {
return Utils.createCommaSeparatedList(getFriendsFeature().getFriends());
case AreaShop.tagLandlord:
}
case AreaShop.tagLandlord -> {
return getLandlordName();
case AreaShop.tagLandlordUUID:
}
case AreaShop.tagLandlordUUID -> {
return getLandlord();
case AreaShop.tagVolume:
}
case AreaShop.tagVolume -> {
return getVolume();
}
// Date/time
case AreaShop.tagEpoch:
case AreaShop.tagEpoch -> {
return Calendar.getInstance().getTimeInMillis();
case AreaShop.tagMillisecond:
}
case AreaShop.tagMillisecond -> {
return Calendar.getInstance().get(Calendar.MILLISECOND);
case AreaShop.tagSecond:
}
case AreaShop.tagSecond -> {
return Calendar.getInstance().get(Calendar.SECOND);
case AreaShop.tagMinute:
}
case AreaShop.tagMinute -> {
return Calendar.getInstance().get(Calendar.MINUTE);
case AreaShop.tagHour:
}
case AreaShop.tagHour -> {
return Calendar.getInstance().get(Calendar.HOUR_OF_DAY);
case AreaShop.tagDay:
}
case AreaShop.tagDay -> {
return Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
case AreaShop.tagMonth:
}
case AreaShop.tagMonth -> {
return Calendar.getInstance().get(Calendar.MONTH) + 1;
case AreaShop.tagYear:
}
case AreaShop.tagYear -> {
return Calendar.getInstance().get(Calendar.YEAR);
case AreaShop.tagDateTime:
}
case AreaShop.tagDateTime -> {
return new SimpleDateFormat(plugin.getConfig().getString("timeFormatChat")).format(Calendar.getInstance().getTime());
case AreaShop.tagDateTimeShort:
}
case AreaShop.tagDateTimeShort -> {
return new SimpleDateFormat(plugin.getConfig().getString("timeFormatSign")).format(Calendar.getInstance().getTime());
}
// Teleport locations
default:
default -> {
Location tp = getTeleportFeature().getTeleportLocation();
if(tp == null) {
if (tp == null) {
return null;
}
switch(variable) {
case AreaShop.tagTeleportBlockX:
return tp.getBlockX();
case AreaShop.tagTeleportBlockY:
return tp.getBlockY();
case AreaShop.tagTeleportBlockZ:
return tp.getBlockZ();
case AreaShop.tagTeleportX:
return tp.getX();
case AreaShop.tagTeleportY:
return tp.getY();
case AreaShop.tagTeleportZ:
return tp.getZ();
case AreaShop.tagTeleportPitch:
return tp.getPitch();
case AreaShop.tagTeleportYaw:
return tp.getYaw();
case AreaShop.tagTeleportPitchRound:
return Math.round(tp.getPitch());
case AreaShop.tagTeleportYawRound:
return Math.round(tp.getYaw());
case AreaShop.tagTeleportWorld:
return tp.getWorld().getName();
default:
return null;
}
return switch (variable) {
case AreaShop.tagTeleportBlockX -> tp.getBlockX();
case AreaShop.tagTeleportBlockY -> tp.getBlockY();
case AreaShop.tagTeleportBlockZ -> tp.getBlockZ();
case AreaShop.tagTeleportX -> tp.getX();
case AreaShop.tagTeleportY -> tp.getY();
case AreaShop.tagTeleportZ -> tp.getZ();
case AreaShop.tagTeleportPitch -> tp.getPitch();
case AreaShop.tagTeleportYaw -> tp.getYaw();
case AreaShop.tagTeleportPitchRound -> Math.round(tp.getPitch());
case AreaShop.tagTeleportYawRound -> Math.round(tp.getYaw());
case AreaShop.tagTeleportWorld -> tp.getWorld().getName();
default -> null;
};
}
}
}
@@ -708,7 +758,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* @return true if the signs of this region need periodic updating, otherwise false
*/
public boolean needsPeriodicUpdate() {
return !(isDeleted() || !(this instanceof RentRegion)) && getSignsFeature().needsPeriodicUpdate();
return !(isDeleted() || !(this instanceof RentRegion)) && getSignsFeature().signManager().needsPeriodicUpdate();
}
/**
@@ -743,19 +793,49 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
File saveFile = new File(plugin.getFileManager().getSchematicFolder() + File.separator + fileName);
// Create parent directories
File parent = saveFile.getParentFile();
if(parent != null && !parent.exists()) {
if(!parent.mkdirs()) {
AreaShop.warn("Did not save region " + getName() + ", schematic directory could not be created: " + saveFile.getAbsolutePath());
return false;
}
if(parent != null && !parent.exists() && !parent.mkdirs()) {
AreaShop.warn("Did not save region " + getName() + ", schematic directory could not be created: " + saveFile.getAbsolutePath());
return false;
}
boolean result = plugin.getWorldEditHandler().saveRegionBlocks(saveFile, this);
boolean result = worldEditInterface.saveRegionBlocks(saveFile, this);
if(result) {
AreaShop.debug("Saved schematic for region " + getName());
}
return true;
}
/**
* Save all blocks in a region for restoring later.
* @param fileName The name of the file to save to (extension and folder will be added)
* @return true if the region has been saved properly, otherwise false
*/
public CompletableFuture<Boolean> saveRegionBlocksAsync(String fileName) {
if (!worldEditInterface.supportsAsyncOperations()) {
return CompletableFuture.completedFuture(saveRegionBlocks(fileName));
}
// Check if the region is correct
ProtectedRegion region = getRegion();
if(region == null) {
AreaShop.debug("Region '" + getName() + "' does not exist in WorldGuard, save failed");
return CompletableFuture.completedFuture(false);
}
// The path to save the schematic
File saveFile = new File(plugin.getFileManager().getSchematicFolder() + File.separator + fileName);
// Create parent directories
File parent = saveFile.getParentFile();
if(parent != null && !parent.exists() && !parent.mkdirs()) {
AreaShop.warn("Did not save region " + getName() + ", schematic directory could not be created: " + saveFile.getAbsolutePath());
return CompletableFuture.completedFuture(false);
}
return worldEditInterface.saveRegionBlocksAsync(saveFile, this)
.thenApply(result -> {
if(Boolean.TRUE.equals(result)) {
AreaShop.debug("Saved schematic async for region " + getName());
}
return result;
});
}
/**
* Restore all blocks in a region for restoring later.
* @param fileName The name of the file to save to (extension and folder will be added)
@@ -768,24 +848,53 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
}
// The path to save the schematic
File restoreFile = new File(plugin.getFileManager().getSchematicFolder() + File.separator + fileName);
boolean result = plugin.getWorldEditHandler().restoreRegionBlocks(restoreFile, this);
boolean result = worldEditInterface.restoreRegionBlocks(restoreFile, this);
if(result) {
AreaShop.debug("Restored schematic for region " + getName());
// Workaround for signs inside the region in combination with async restore of plugins like AsyncWorldEdit and FastAsyncWorldEdit
Do.syncLater(10, getSignsFeature()::update);
Do.syncLater(10, getSignsFeature().signManager()::update);
}
return result;
}
/**
* Restore all blocks in a region for restoring later.
* @param fileName The name of the file to save to (extension and folder will be added)
* @return true if the region has been restored properly, otherwise false
*/
public CompletableFuture<Boolean> restoreRegionBlocksAsync(String fileName) {
if (!worldEditInterface.supportsAsyncOperations()) {
return CompletableFuture.completedFuture(restoreRegionBlocks(fileName));
}
if(getRegion() == null) {
AreaShop.debug("Region '" + getName() + "' does not exist in WorldGuard, restore failed");
return CompletableFuture.completedFuture(false);
}
// The path to save the schematic
File restoreFile = new File(plugin.getFileManager().getSchematicFolder() + File.separator + fileName);
return worldEditInterface.restoreRegionBlocksAsync(restoreFile, this)
.thenApply(result -> {
if(Boolean.TRUE.equals(result)) {
AreaShop.debug("Restored schematic async for region " + getName());
// Sync back to main
Do.syncLater(10, getSignsFeature().signManager()::update);
}
return result;
}
);
}
/**
* Reset all flags of the region.
*/
public void resetRegionFlags() {
ProtectedRegion region = getRegion();
if(region != null) {
region.setFlag(plugin.getWorldGuardHandler().fuzzyMatchFlag("greeting"), null);
region.setFlag(plugin.getWorldGuardHandler().fuzzyMatchFlag("farewell"), null);
region.setFlag(worldGuardInterface.fuzzyMatchFlag("greeting"), null);
region.setFlag(worldGuardInterface.fuzzyMatchFlag("farewell"), null);
}
}
@@ -857,7 +966,6 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
if(found) {
return result;
}
if(this.getFileManager().getRegionSettings().isString(path)) {
return this.getFileManager().getRegionSettings().getString(path).equalsIgnoreCase("true");
}
@@ -1184,12 +1292,12 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
int totalLimit = plugin.getConfig().getInt("limitGroups." + group + ".total");
int typeLimit = plugin.getConfig().getInt("limitGroups." + group + "." + typePath);
//AreaShop.debug("typeLimitOther="+typeLimit+", typePath="+typePath);
int totalCurrent = hasRegionsInLimitGroup(offlinePlayer, group, plugin.getFileManager().getRegions(), exclude);
int totalCurrent = hasRegionsInLimitGroup(offlinePlayer, group, plugin.getFileManager().getRegionsRef(), exclude);
int typeCurrent;
if(type == RegionType.RENT) {
typeCurrent = hasRegionsInLimitGroup(offlinePlayer, group, plugin.getFileManager().getRents(), exclude);
typeCurrent = hasRegionsInLimitGroup(offlinePlayer, group, plugin.getFileManager().getRentsRef(), exclude);
} else {
typeCurrent = hasRegionsInLimitGroup(offlinePlayer, group, plugin.getFileManager().getBuys(), exclude);
typeCurrent = hasRegionsInLimitGroup(offlinePlayer, group, plugin.getFileManager().getBuysRef(), exclude);
}
if(totalLimit == -1) {
totalLimit = Integer.MAX_VALUE;
@@ -1345,7 +1453,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
* @param exclude Exclude this region from the count
* @return The number of regions that the player has bought or rented matching the limit group (worlds and groups filters)
*/
public int hasRegionsInLimitGroup(OfflinePlayer player, String limitGroup, List<? extends GeneralRegion> regions, GeneralRegion exclude) {
public int hasRegionsInLimitGroup(OfflinePlayer player, String limitGroup, Collection<? extends GeneralRegion> regions, GeneralRegion exclude) {
int result = 0;
for(GeneralRegion region : regions) {
if(region.getBooleanSetting("general.countForLimits")
@@ -1366,8 +1474,8 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
public boolean matchesLimitGroup(String group) {
List<String> worlds = plugin.getConfig().getStringList("limitGroups." + group + ".worlds");
List<String> groups = plugin.getConfig().getStringList("limitGroups." + group + ".groups");
if((worlds == null || worlds.isEmpty() || worlds.contains(getWorldName()))) {
if(groups == null || groups.isEmpty()) {
if(worlds.isEmpty() || worlds.contains(getWorldName())) {
if(groups.isEmpty()) {
return true;
} else {
boolean inGroups = false;
@@ -1399,14 +1507,23 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
String save = profileSection.getString(type.getValue() + ".save");
String restore = profileSection.getString(type.getValue() + ".restore");
// Save the region if needed
if(save != null && save.length() != 0) {
boolean async = worldEditInterface.supportsAsyncOperations();
if(save != null && !save.isBlank()) {
save = Message.fromString(save).replacements(this).getSingle();
saveRegionBlocks(save);
if (async) {
saveRegionBlocksAsync(save);
} else {
saveRegionBlocks(save);
}
}
// Restore the region if needed
if(restore != null && restore.length() != 0) {
if(restore != null && !restore.isBlank()) {
restore = Message.fromString(restore).replacements(this).getSingle();
restoreRegionBlocks(restore);
if (async) {
restoreRegionBlocksAsync(restore);
} else {
restoreRegionBlocks(restore);
}
}
}
@@ -1423,7 +1540,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
}
for(String command : commands) {
if(command == null || command.length() == 0) {
if(command == null || command.isEmpty()) {
continue;
}
// It is not ideal we have to disable language replacements here, but otherwise giving language variables
@@ -1457,23 +1574,6 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
}
}
/**
* Run command for a certain event.
* @param event The event
* @param before The 'before' or 'after' commands
*/
public void runEventCommands(RegionEvent event, boolean before) {
ConfigurationSection eventCommandProfileSection = getConfigurationSectionSetting("general.eventCommandProfile", "eventCommandProfiles");
if(eventCommandProfileSection == null) {
return;
}
List<String> commands = eventCommandProfileSection.getStringList(event.getValue() + "." + (before ? "before" : "after"));
if(commands == null || commands.isEmpty()) {
return;
}
runCommands(Bukkit.getConsoleSender(), commands);
}
/**
* Get the volume of the region (number of blocks inside it).
* @return Number of blocks in the region
@@ -1495,8 +1595,8 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
// Use own calculation for polygon regions, as WorldGuard does not implement it and returns 0
ProtectedRegion region = getRegion();
if(region instanceof ProtectedPolygonalRegion) {
BlockVector min = region.getMinimumPoint();
BlockVector max = region.getMaximumPoint();
Vector min = getMinimumPoint();
Vector max = getMaximumPoint();
// Exact, but slow algorithm
if(getWidth() * getDepth() < 100) {
@@ -1512,7 +1612,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
}
// Estimate, but quick algorithm
else {
List<BlockVector2D> points = region.getPoints();
List<Vector> points = worldGuardInterface.getRegionPoints(region);
int numPoints = points.size();
if(numPoints < 3) {
return 0;
@@ -1527,7 +1627,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
x2 = points.get(i + 1).getBlockX();
z2 = points.get(i + 1).getBlockZ();
area = area + ((z1 + z2) * (x1 - x2));
area += ((z1 + z2) * (x1 - x2));
}
x1 = points.get(numPoints - 1).getBlockX();
@@ -1535,7 +1635,7 @@ public abstract class GeneralRegion implements GeneralRegionInterface, Comparabl
x2 = points.get(0).getBlockX();
z2 = points.get(0).getBlockZ();
area = area + ((z1 + z2) * (x1 - x2));
area += ((z1 + z2) * (x1 - x2));
area = Math.ceil(Math.abs(area) / 2);
return (long)(area * getHeight());
}
@@ -1,15 +1,17 @@
package me.wiefferink.areashop.commands;
package me.wiefferink.areashop.regions;
import com.google.common.base.Charsets;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.areashop.events.ask.AddingRegionEvent;
import me.wiefferink.areashop.features.signs.RegionSign;
import me.wiefferink.areashop.features.signs.SignsFeature;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RegionGroup;
import me.wiefferink.areashop.regions.RentRegion;
import me.wiefferink.areashop.features.signs.SignManager;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.IFileManager;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
@@ -19,33 +21,52 @@ import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import javax.annotation.Nonnull;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public class ImportJob {
private final AreaShop plugin;
private final IFileManager fileManager;
private final SignManager signManager;
private final WorldGuardInterface worldGuardInterface;
private final CommandSender sender;
private final MessageBridge messageBridge;
private final RegionFactory regionFactory;
/**
* Create and execute the import.
* @param sender CommandSender that should receive progress updates
*/
public ImportJob(CommandSender sender) {
@AssistedInject
ImportJob(
@Nonnull AreaShop plugin,
@Nonnull IFileManager fileManager,
@Nonnull SignManager signManager,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nonnull MessageBridge messageBridge,
@Nonnull RegionFactory regionFactory,
@Assisted @Nonnull CommandSender sender) {
this.regionFactory = regionFactory;
this.sender = sender;
this.plugin = AreaShop.getInstance();
execute();
this.plugin = plugin;
this.signManager = signManager;
this.fileManager = fileManager;
this.worldGuardInterface = worldGuardInterface;
this.messageBridge = messageBridge;
}
/**
* Execute the job.
*/
private void execute() {
public void execute() {
// Check for RegionForSale data
File regionForSaleFolder = new File(plugin.getDataFolder().getParentFile().getAbsolutePath(), "RegionForSale");
if(!regionForSaleFolder.exists()) {
@@ -69,8 +90,8 @@ public class ImportJob {
message("import-start");
// Group with settings for all imported regions
RegionGroup regionForSaleGroup = new RegionGroup(plugin, "RegionForSale");
plugin.getFileManager().addGroup(regionForSaleGroup);
RegionGroup regionForSaleGroup = regionFactory.createRegionGroup("RegionForSale");
fileManager.addGroup(regionForSaleGroup);
// Import /RegionForSale/config.yml settings
File regionForSaleConfigFile = new File(regionForSaleFolder.getAbsolutePath(), "config.yml");
@@ -148,11 +169,11 @@ public class ImportJob {
worldConfig = new YamlConfiguration();
} else {
// RegionGroup with all world settings
RegionGroup worldGroup = new RegionGroup(plugin, "RegionForSale-" + worldFolder.getName());
RegionGroup worldGroup = regionFactory.createRegionGroup("RegionForSale-" + worldFolder.getName());
importRegionSettings(worldConfig, worldGroup.getSettings(), null, false);
worldGroup.setSetting("priority", 1);
worldGroup.addWorld(worldFolder.getName());
plugin.getFileManager().addGroup(regionForSaleGroup);
fileManager.addGroup(regionForSaleGroup);
worldGroup.saveRequired();
}
@@ -184,7 +205,7 @@ public class ImportJob {
}
// Import parent region settings into a RegionGroup
RegionGroup parentRegionGroup = new RegionGroup(plugin, "RegionForSale-" + worldFolder.getName() + "-" + parentRegionName);
RegionGroup parentRegionGroup = regionFactory.createRegionGroup( "RegionForSale-" + worldFolder.getName() + "-" + parentRegionName);
importRegionSettings(parentRegionSection, parentRegionGroup.getSettings(), null, false);
parentRegionGroup.setSetting("priority", 2 + parentRegionSection.getLong("info.priority", 0));
parentRegionGroup.saveRequired();
@@ -196,7 +217,7 @@ public class ImportJob {
// Read and import regions
for(String regionKey : regions.getKeys(false)) {
GeneralRegion existingRegion = plugin.getFileManager().getRegion(regionKey);
GeneralRegion existingRegion = fileManager.getRegion(regionKey);
if(existingRegion != null) {
if(world.getName().equalsIgnoreCase(existingRegion.getWorldName())) {
messageNoPrefix("import-alreadyAdded", regionKey);
@@ -239,11 +260,14 @@ public class ImportJob {
// Create region
GeneralRegion region;
if(rentable || (owner != null && !isBought)) {
region = new RentRegion(regionKey, world);
plugin.getFileManager().addRent((RentRegion)region);
region = regionFactory.createRentRegion(regionKey, world);
} else {
region = new BuyRegion(regionKey, world);
plugin.getFileManager().addBuy((BuyRegion)region);
region = regionFactory.createBuyRegion(regionKey, world);
}
AddingRegionEvent event = plugin.getFileManager().addRegion(region);
if (event.isCancelled()) {
messageNoPrefix("general-cancelled", event.getReason());
continue;
}
// Import settings
@@ -255,16 +279,16 @@ public class ImportJob {
if(owner != null) {
@SuppressWarnings("deprecation")
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(owner);
if(offlinePlayer != null) {
if(offlinePlayer.hasPlayedBefore()) {
existing.add(offlinePlayer.getUniqueId());
}
}
for(UUID uuid : plugin.getWorldGuardHandler().getOwners(worldGuardRegion).asUniqueIdList()) {
for(UUID uuid : worldGuardInterface.getOwners(worldGuardRegion).asUniqueIdList()) {
if(!existing.contains(uuid)) {
existing.add(uuid);
}
}
for(UUID uuid : plugin.getWorldGuardHandler().getMembers(worldGuardRegion).asUniqueIdList()) {
for(UUID uuid : worldGuardInterface.getMembers(worldGuardRegion).asUniqueIdList()) {
if(!existing.contains(uuid)) {
existing.add(uuid);
}
@@ -286,9 +310,9 @@ public class ImportJob {
}
// Update all regions
plugin.getFileManager().updateAllRegions(sender);
fileManager.updateAllRegions(sender);
// Write all imported regions and settings to disk
plugin.getFileManager().saveRequiredFiles();
fileManager.saveRequiredFiles();
}
/**
@@ -330,7 +354,7 @@ public class ImportJob {
String buyPrice = from.getString("economic-settings.cost-per-unit.buy");
String sellPrice = from.getString("economic-settings.cost-per-unit.selling-price");
// TODO: There is no easy way to import this, setup eventCommandsProfile?
String taxes = from.getString("economic-settings.cost-per-unit.taxes");
// String taxes = from.getString("economic-settings.cost-per-unit.taxes");
// Determine unit and add that to the price
String unitSuffix = "";
@@ -369,8 +393,7 @@ public class ImportJob {
// Set rented until
if(from.isLong("info.last-withdrawal")
&& region instanceof RentRegion) {
RentRegion rentRegion = (RentRegion)region;
&& region instanceof RentRegion rentRegion) {
long lastWithdrawal = from.getLong("info.last-withdrawal");
// Because the rental duration is already imported into the region and its parents this should be correct
rentRegion.setRentedUntil(lastWithdrawal + rentRegion.getDuration());
@@ -395,8 +418,9 @@ public class ImportJob {
}
// Check if this location is already added to a region
RegionSign regionSign = SignsFeature.getSignByLocation(location);
if(regionSign != null) {
Optional<RegionSign> optionalRegionSign = signManager.signFromLocation(location);
if(optionalRegionSign.isPresent()) {
RegionSign regionSign = optionalRegionSign.get();
if(!regionSign.getRegion().equals(region)) {
message("import-signAlreadyAdded", region.getName(), signLocation, regionSign.getRegion().getName());
}
@@ -411,8 +435,8 @@ public class ImportJob {
}
private static class TimeUnit {
public long minutes;
public String identifier;
public final long minutes;
public final String identifier;
TimeUnit(long minutes, String identifier) {
this.minutes = minutes;
@@ -420,7 +444,7 @@ public class ImportJob {
}
}
private static final List<TimeUnit> timeUnitLookup = new ArrayList<TimeUnit>() {
private static final List<TimeUnit> timeUnitLookup = new ArrayList<>() {
{
add(new TimeUnit(60 * 24 * 30 * 12, "year"));
add(new TimeUnit(60 * 24 * 30, "month"));
@@ -455,10 +479,10 @@ public class ImportJob {
* @param replacements The replacements to insert in the message
*/
public void messageNoPrefix(String key, Object... replacements) {
plugin.messageNoPrefix(sender, key, replacements);
messageBridge.messageNoPrefix(sender, key, replacements);
if(!(sender instanceof ConsoleCommandSender)) {
plugin.messageNoPrefix(Bukkit.getConsoleSender(), key, replacements);
messageBridge.messageNoPrefix(Bukkit.getConsoleSender(), key, replacements);
}
}
@@ -468,10 +492,10 @@ public class ImportJob {
* @param replacements The replacements to insert in the message
*/
public void message(String key, Object... replacements) {
plugin.message(sender, key, replacements);
messageBridge.message(sender, key, replacements);
if(!(sender instanceof ConsoleCommandSender)) {
plugin.message(Bukkit.getConsoleSender(), key, replacements);
messageBridge.message(Bukkit.getConsoleSender(), key, replacements);
}
}
}
@@ -0,0 +1,11 @@
package me.wiefferink.areashop.regions;
import org.bukkit.command.CommandSender;
import javax.annotation.Nonnull;
public interface ImportJobFactory {
@Nonnull ImportJob createImportJob(@Nonnull CommandSender commandSender);
}
@@ -0,0 +1,20 @@
package me.wiefferink.areashop.regions;
import org.bukkit.World;
import org.bukkit.configuration.file.YamlConfiguration;
import javax.annotation.Nonnull;
public interface RegionFactory {
@Nonnull BuyRegion createBuyRegion(@Nonnull YamlConfiguration yamlConfiguration);
@Nonnull BuyRegion createBuyRegion(@Nonnull String name, @Nonnull World world);
@Nonnull RentRegion createRentRegion(@Nonnull YamlConfiguration yamlConfiguration);
@Nonnull RentRegion createRentRegion(@Nonnull String name, @Nonnull World world);
@Nonnull RegionGroup createRegionGroup(@Nonnull String name);
}
@@ -1,9 +1,13 @@
package me.wiefferink.areashop.regions;
import me.wiefferink.areashop.AreaShop;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import me.wiefferink.areashop.managers.IFileManager;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
@@ -11,7 +15,8 @@ import java.util.Set;
// TODO consider switching to saving lowercase regions
public class RegionGroup {
private final AreaShop plugin;
private final Plugin plugin;
private final IFileManager fileManager;
private final String name;
private final Set<String> regions;
private Set<String> autoRegions;
@@ -23,8 +28,10 @@ public class RegionGroup {
* @param plugin The AreaShop plugin
* @param name Name of the group, has to be unique
*/
public RegionGroup(AreaShop plugin, String name) {
@AssistedInject
RegionGroup(@Nonnull Plugin plugin, @Nonnull IFileManager fileManager, @Assisted String name) {
this.plugin = plugin;
this.fileManager = fileManager;
this.name = name;
this.autoDirty = true;
setSetting("name", name);
@@ -41,7 +48,7 @@ public class RegionGroup {
public Set<String> getAutoRegions() {
if(autoDirty) {
autoRegions = new HashSet<>();
for(GeneralRegion region : plugin.getFileManager().getRegions()) {
for(GeneralRegion region : fileManager.getRegionsRef()) {
if(worlds.contains(region.getWorldName())) {
autoRegions.add(region.getName());
}
@@ -148,8 +155,8 @@ public class RegionGroup {
*/
public Set<GeneralRegion> getMemberRegions() {
Set<GeneralRegion> result = new HashSet<>();
for(String name : getMembers()) {
result.add(plugin.getFileManager().getRegion(name));
for(String playerName : getMembers()) {
result.add(fileManager.getRegion(playerName));
}
return result;
}
@@ -192,7 +199,7 @@ public class RegionGroup {
* @return The ConfigurationSection with the settings of the group
*/
public ConfigurationSection getSettings() {
ConfigurationSection result = plugin.getFileManager().getGroupSettings(name);
ConfigurationSection result = fileManager.getGroupSettings(name);
if(result != null) {
return result;
} else {
@@ -206,20 +213,20 @@ public class RegionGroup {
* @param setting The value to set
*/
public void setSetting(String path, Object setting) {
plugin.getFileManager().setGroupSetting(this, path, setting);
fileManager.setGroupSetting(this, path, setting);
}
/**
* Indicates this file needs to be saved, will actually get saved later by a task.
*/
public void saveRequired() {
plugin.getFileManager().saveGroupsIsRequired();
fileManager.saveGroupsIsRequired();
}
/**
* Save the groups to disk now, normally saveRequired() is preferred because of performance.
*/
public void saveNow() {
plugin.getFileManager().saveGroupsNow();
fileManager.saveGroupsNow();
}
}
@@ -0,0 +1,12 @@
package me.wiefferink.areashop.regions;
import com.google.inject.AbstractModule;
import com.google.inject.assistedinject.FactoryModuleBuilder;
public class RegionModule extends AbstractModule {
@Override
protected void configure() {
install(new FactoryModuleBuilder().build(RegionFactory.class));
}
}
@@ -1,11 +1,17 @@
package me.wiefferink.areashop.regions;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.events.ask.RentingRegionEvent;
import me.wiefferink.areashop.events.ask.UnrentingRegionEvent;
import me.wiefferink.areashop.events.notify.RentedRegionEvent;
import me.wiefferink.areashop.events.notify.UnrentedRegionEvent;
import me.wiefferink.areashop.interfaces.WorldEditInterface;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.managers.FeatureManager;
import me.wiefferink.areashop.tools.Utils;
import net.milkbowl.vault.economy.Economy;
import net.milkbowl.vault.economy.EconomyResponse;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
@@ -15,6 +21,8 @@ import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
@@ -24,14 +32,25 @@ import java.util.UUID;
import static me.wiefferink.areashop.tools.Utils.millisToHumanFormat;
public class RentRegion extends GeneralRegion {
private long warningsDoneUntil = Calendar.getInstance().getTimeInMillis();
private long warningsDoneUntil = System.currentTimeMillis();
private final Economy economy;
/**
* Constructor.
* @param config All settings of this region
*/
public RentRegion(YamlConfiguration config) {
super(config);
@AssistedInject
RentRegion(
@Nonnull AreaShop plugin,
@Nonnull FeatureManager featureManager,
@Nonnull WorldEditInterface worldEditInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nullable Economy economy,
@Assisted @Nonnull YamlConfiguration config
) {
super(plugin, featureManager, worldEditInterface, worldGuardInterface, config);
this.economy = economy;
}
/**
@@ -39,8 +58,34 @@ public class RentRegion extends GeneralRegion {
* @param name The name of the region (correct casing)
* @param world The world of the WorldGuard region
*/
public RentRegion(String name, World world) {
super(name, world);
@AssistedInject
RentRegion(
@Nonnull AreaShop plugin,
@Nonnull FeatureManager featureManager,
@Nonnull WorldEditInterface worldEditInterface,
@Nonnull WorldGuardInterface worldGuardInterface,
@Nullable Economy economy,
@Assisted @Nonnull String name,
@Assisted @Nonnull World world
) {
super(plugin, featureManager, worldEditInterface, worldGuardInterface, name, world);
this.economy = economy;
}
@Override
public boolean isOwner(UUID player) {
return isRenter(player);
}
@Override
public UUID getOwner() {
return getRenter();
}
@Override
public void setOwner(UUID player) {
setRenter(player);
}
@Override
@@ -136,43 +181,28 @@ public class RentRegion extends GeneralRegion {
@Override
public Object provideReplacement(String variable) {
switch(variable) {
case AreaShop.tagPrice:
return getFormattedPrice();
case AreaShop.tagRawPrice:
return getPrice();
case AreaShop.tagDuration:
return getDurationString();
case AreaShop.tagPlayerName:
return getPlayerName();
case AreaShop.tagPlayerUUID:
return getRenter();
case AreaShop.tagRentedUntil:
return new SimpleDateFormat(plugin.getConfig().getString("timeFormatChat")).format(new Date(getRentedUntil()));
case AreaShop.tagRentedUntilShort:
return new SimpleDateFormat(plugin.getConfig().getString("timeFormatSign")).format(new Date(getRentedUntil()));
case AreaShop.tagTimeLeft:
return getTimeLeftString();
case AreaShop.tagMoneyBackAmount:
return getFormattedMoneyBackAmount();
case AreaShop.tagRawMoneyBackAmount:
return getMoneyBackAmount();
case AreaShop.tagMoneyBackPercentage:
return (getMoneyBackPercentage() % 1.0) == 0.0 ? (int)getMoneyBackPercentage() : getMoneyBackPercentage();
case AreaShop.tagTimesExtended:
return this.getTimesExtended();
case AreaShop.tagMaxExtends:
return this.getMaxExtends();
case AreaShop.tagExtendsLeft:
return getMaxExtends() - getTimesExtended();
case AreaShop.tagMaxRentTime:
return millisToHumanFormat(getMaxRentTime());
case AreaShop.tagMaxInactiveTime:
return this.getFormattedInactiveTimeUntilUnrent();
default:
return super.provideReplacement(variable);
}
return switch (variable) {
case AreaShop.tagPrice -> getFormattedPrice();
case AreaShop.tagRawPrice -> getPrice();
case AreaShop.tagDuration -> getDurationString();
case AreaShop.tagPlayerName -> getPlayerName();
case AreaShop.tagPlayerUUID -> getRenter();
case AreaShop.tagRentedUntil ->
new SimpleDateFormat(plugin.getConfig().getString("timeFormatChat")).format(new Date(getRentedUntil()));
case AreaShop.tagRentedUntilShort ->
new SimpleDateFormat(plugin.getConfig().getString("timeFormatSign")).format(new Date(getRentedUntil()));
case AreaShop.tagTimeLeft -> getTimeLeftString();
case AreaShop.tagMoneyBackAmount -> getFormattedMoneyBackAmount();
case AreaShop.tagRawMoneyBackAmount -> getMoneyBackAmount();
case AreaShop.tagMoneyBackPercentage ->
(getMoneyBackPercentage() % 1.0) == 0.0 ? (int) getMoneyBackPercentage() : getMoneyBackPercentage();
case AreaShop.tagTimesExtended -> this.getTimesExtended();
case AreaShop.tagMaxExtends -> this.getMaxExtends();
case AreaShop.tagExtendsLeft -> getMaxExtends() - getTimesExtended();
case AreaShop.tagMaxRentTime -> millisToHumanFormat(getMaxRentTime());
case AreaShop.tagMaxInactiveTime -> this.getFormattedInactiveTimeUntilUnrent();
default -> super.provideReplacement(variable);
};
}
/**
@@ -316,7 +346,7 @@ public class RentRegion extends GeneralRegion {
*/
public double getMoneyBackAmount() {
Long currentTime = Calendar.getInstance().getTimeInMillis();
Double timeLeft = (double)((getRentedUntil() - currentTime));
Double timeLeft = (double)(getRentedUntil() - currentTime);
double percentage = (getMoneyBackPercentage()) / 100.0;
Double timePeriod = (double)(getDuration());
double periods = timeLeft / timePeriod;
@@ -347,10 +377,8 @@ public class RentRegion extends GeneralRegion {
long now = Calendar.getInstance().getTimeInMillis();
if(!isDeleted() && isRented() && now > getRentedUntil()) {
// Extend rent if configured for that
if(getBooleanSetting("rent.autoExtend")) {
if(extend()) {
return false;
}
if(getBooleanSetting("rent.autoExtend") && extend()) {
return false;
}
// Send message to the player if online
@@ -430,204 +458,194 @@ public class RentRegion extends GeneralRegion {
* @return true if it succeeded and false if not
*/
public boolean rent(OfflinePlayer offlinePlayer) {
if(plugin.getEconomy() == null) {
if(economy == null) {
message(offlinePlayer, "general-noEconomy");
return false;
}
//Check if the player has permission
if(plugin.hasPermission(offlinePlayer, "areashop.rent")) {
if(getWorld() == null) {
message(offlinePlayer, "general-noWorld");
// Check if the player has permission
if(!plugin.hasPermission(offlinePlayer, "areashop.rent")) {
message(offlinePlayer, "rent-noPermission");
return false;
}
// Check location restrictions
if(getWorld() == null) {
message(offlinePlayer, "general-noWorld");
return false;
}
if(getRegion() == null) {
message(offlinePlayer, "general-noRegion");
return false;
}
boolean extend = false;
if(getRenter() != null && offlinePlayer.getUniqueId().equals(getRenter())) {
extend = true;
}
// Check if available or extending
if (isRented() && !extend) {
message(offlinePlayer, "rent-someoneElse");
return false;
}
// These checks are only relevant for online players doing the renting/buying themselves
Player player = offlinePlayer.getPlayer();
if(player != null) {
// Check if the players needs to be in the region for renting
if(restrictedToRegion() && (!player.getWorld().getName().equals(getWorldName())
|| !getRegion().contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()))) {
message(offlinePlayer, "rent-restrictedToRegion");
return false;
}
if(getRegion() == null) {
message(offlinePlayer, "general-noRegion");
// Check if the players needs to be in the world for renting
if(restrictedToWorld() && !player.getWorld().getName().equals(getWorldName())) {
message(offlinePlayer, "rent-restrictedToWorld", player.getWorld().getName());
return false;
}
boolean extend = false;
if(getRenter() != null && offlinePlayer.getUniqueId().equals(getRenter())) {
extend = true;
}
// Check region limits if this is not extending
if(!(extend && config.getBoolean("allowRegionExtendsWhenAboveLimits"))) {
LimitResult limitResult;
if(extend) {
limitResult = this.limitsAllow(RegionType.RENT, offlinePlayer, true);
} else {
limitResult = this.limitsAllow(RegionType.RENT, offlinePlayer);
}
// Check if the region is available for renting or if the player wants to extend the rent
if(!isRented() || extend) {
// These checks are only relevant for online players doing the renting/buying themselves
Player player = offlinePlayer.getPlayer();
if(player != null) {
// Check if the players needs to be in the region for renting
if(restrictedToRegion() && (!player.getWorld().getName().equals(getWorldName())
|| !getRegion().contains(player.getLocation().getBlockX(), player.getLocation().getBlockY(), player.getLocation().getBlockZ()))) {
message(offlinePlayer, "rent-restrictedToRegion");
return false;
}
// Check if the players needs to be in the world for renting
if(restrictedToWorld() && !player.getWorld().getName().equals(getWorldName())) {
message(offlinePlayer, "rent-restrictedToWorld", player.getWorld().getName());
return false;
}
AreaShop.debug("LimitResult: " + limitResult.toString());
if(!limitResult.actionAllowed()) {
if(limitResult.getLimitingFactor() == LimitType.TOTAL) {
message(offlinePlayer, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
// Check region limits if this is not extending
if(!(extend && config.getBoolean("allowRegionExtendsWhenAboveLimits"))) {
LimitResult limitResult;
if(extend) {
limitResult = this.limitsAllow(RegionType.RENT, offlinePlayer, true);
} else {
limitResult = this.limitsAllow(RegionType.RENT, offlinePlayer);
}
AreaShop.debug("LimitResult: " + limitResult.toString());
if(!limitResult.actionAllowed()) {
if(limitResult.getLimitingFactor() == LimitType.TOTAL) {
message(offlinePlayer, "total-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
if(limitResult.getLimitingFactor() == LimitType.RENTS) {
message(offlinePlayer, "rent-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
if(limitResult.getLimitingFactor() == LimitType.EXTEND) {
message(offlinePlayer, "rent-maximumExtend", limitResult.getMaximum(), limitResult.getCurrent() + 1, limitResult.getLimitingGroup());
return false;
}
return false;
}
if(limitResult.getLimitingFactor() == LimitType.RENTS) {
message(offlinePlayer, "rent-maximum", limitResult.getMaximum(), limitResult.getCurrent(), limitResult.getLimitingGroup());
return false;
}
// Check if the player can still extend this rent
if(extend && !plugin.hasPermission(offlinePlayer, "areashop.rentextendbypass")) {
if(getMaxExtends() >= 0 && getTimesExtended() >= getMaxExtends()) {
message(offlinePlayer, "rent-maxExtends");
return false;
}
if(limitResult.getLimitingFactor() == LimitType.EXTEND) {
message(offlinePlayer, "rent-maximumExtend", limitResult.getMaximum(), limitResult.getCurrent() + 1, limitResult.getLimitingGroup());
return false;
}
return false;
}
}
// Check if there is enough time left before hitting maxRentTime
boolean extendToMax = false;
double price = getPrice();
long timeNow = Calendar.getInstance().getTimeInMillis();
long timeRented = 0;
long maxRentTime = getMaxRentTime();
if(isRented()) {
timeRented = getRentedUntil() - timeNow;
}
if((timeRented + getDuration()) > (maxRentTime)
&& !plugin.hasPermission(offlinePlayer, "areashop.renttimebypass")
&& maxRentTime != -1) {
// Extend to the maximum instead of adding a full period
if(getBooleanSetting("rent.extendToFullWhenAboveMaxRentTime")) {
if(timeRented >= maxRentTime) {
message(offlinePlayer, "rent-alreadyAtFull");
return false;
} else {
long toRentPart = maxRentTime - timeRented;
extendToMax = true;
price = ((double)toRentPart) / getDuration() * price;
}
} else {
message(offlinePlayer, "rent-maxRentTime");
return false;
}
}
// Check if the player can still extend this rent
if(extend && !plugin.hasPermission(offlinePlayer, "areashop.rentextendbypass")) {
if(getMaxExtends() >= 0 && getTimesExtended() >= getMaxExtends()) {
message(offlinePlayer, "rent-maxExtends");
return false;
}
}
if(plugin.getEconomy().has(offlinePlayer, getWorldName(), price)) {
// Broadcast and check event
RentingRegionEvent event = new RentingRegionEvent(this, offlinePlayer, extend);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(offlinePlayer, "general-cancelled", event.getReason());
return false;
}
// Substract the money from the players balance
EconomyResponse r = plugin.getEconomy().withdrawPlayer(offlinePlayer, getWorldName(), price);
if(!r.transactionSuccess()) {
message(offlinePlayer, "rent-payError");
AreaShop.debug("Something went wrong with getting money from " + offlinePlayer.getName() + " while renting " + getName() + ": " + r.errorMessage);
return false;
}
// Optionally give money to the landlord
OfflinePlayer landlordPlayer = null;
if(getLandlord() != null) {
landlordPlayer = Bukkit.getOfflinePlayer(getLandlord());
}
String landlordName = getLandlordName();
if(landlordName != null) {
if(landlordPlayer != null && landlordPlayer.getName() != null) {
r = plugin.getEconomy().depositPlayer(landlordPlayer, getWorldName(), price);
} else {
r = plugin.getEconomy().depositPlayer(landlordName, getWorldName(), price);
}
if(r == null || !r.transactionSuccess()) {
AreaShop.warn("Something went wrong with paying '" + landlordName + "' " + Utils.formatCurrency(price) + " for his rent of region " + getName() + " to " + offlinePlayer.getName());
}
}
if(!extend) {
// Run commands
runEventCommands(RegionEvent.RENTED, true);
} else {
// Run commands
runEventCommands(RegionEvent.EXTENDED, true);
}
// Get the time until the region will be rented
Calendar calendar = Calendar.getInstance();
if(extendToMax) {
calendar.setTimeInMillis(calendar.getTimeInMillis() + getMaxRentTime());
} else if(extend) {
calendar.setTimeInMillis(getRentedUntil() + getDuration());
} else {
calendar.setTimeInMillis(calendar.getTimeInMillis() + getDuration());
}
// Add values to the rent and send it to FileManager
setRentedUntil(calendar.getTimeInMillis());
setRenter(offlinePlayer.getUniqueId());
updateLastActiveTime();
// Fire schematic event and updated times extended
if(!extend) {
this.handleSchematicEvent(RegionEvent.RENTED);
setTimesExtended(0);
} else {
setTimesExtended(getTimesExtended() + 1);
}
// Notify about updates
this.notifyAndUpdate(new RentedRegionEvent(this, extend));
// Send message to the player
if(extendToMax) {
message(offlinePlayer, "rent-extendedToMax");
} else if(extend) {
message(offlinePlayer, "rent-extended");
} else {
message(offlinePlayer, "rent-rented");
}
if(!extend) {
// Run commands
this.runEventCommands(RegionEvent.RENTED, false);
} else {
// Run commands
this.runEventCommands(RegionEvent.EXTENDED, false);
}
return true;
// Check if there is enough time left before hitting maxRentTime
boolean extendToMax = false;
double price = getPrice();
long timeNow = Calendar.getInstance().getTimeInMillis();
long timeRented = 0;
long maxRentTime = getMaxRentTime();
if(isRented()) {
timeRented = getRentedUntil() - timeNow;
}
if((timeRented + getDuration()) > (maxRentTime)
&& !plugin.hasPermission(offlinePlayer, "areashop.renttimebypass")
&& maxRentTime != -1) {
// Extend to the maximum instead of adding a full period
if(getBooleanSetting("rent.extendToFullWhenAboveMaxRentTime")) {
if(timeRented >= maxRentTime) {
message(offlinePlayer, "rent-alreadyAtFull");
return false;
} else {
// Player has not enough money
if(extend) {
message(offlinePlayer, "rent-lowMoneyExtend", Utils.formatCurrency(plugin.getEconomy().getBalance(offlinePlayer, getWorldName())));
} else {
message(offlinePlayer, "rent-lowMoneyRent", Utils.formatCurrency(plugin.getEconomy().getBalance(offlinePlayer, getWorldName())));
}
long toRentPart = maxRentTime - timeRented;
extendToMax = true;
price = ((double)toRentPart) / getDuration() * price;
}
} else {
message(offlinePlayer, "rent-someoneElse");
message(offlinePlayer, "rent-maxRentTime");
return false;
}
} else {
message(offlinePlayer, "rent-noPermission");
}
return false;
// Check if the player has enough money
if(!economy.has(offlinePlayer, getWorldName(), price)) {
if(extend) {
message(offlinePlayer, "rent-lowMoneyExtend", Utils.formatCurrency(economy.getBalance(offlinePlayer, getWorldName())));
} else {
message(offlinePlayer, "rent-lowMoneyRent", Utils.formatCurrency(economy.getBalance(offlinePlayer, getWorldName())));
}
return false;
}
// Broadcast and check event
RentingRegionEvent event = new RentingRegionEvent(this, offlinePlayer, extend);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(offlinePlayer, "general-cancelled", event.getReason());
return false;
}
// Substract the money from the players balance
EconomyResponse r = economy.withdrawPlayer(offlinePlayer, getWorldName(), price);
if(!r.transactionSuccess()) {
message(offlinePlayer, "rent-payError");
AreaShop.debug("Something went wrong with getting money from " + offlinePlayer.getName() + " while renting " + getName() + ": " + r.errorMessage);
return false;
}
// Optionally give money to the landlord
OfflinePlayer landlordPlayer = null;
if(getLandlord() != null) {
landlordPlayer = Bukkit.getOfflinePlayer(getLandlord());
}
String landlordName = getLandlordName();
if(landlordName != null) {
if(landlordPlayer != null && landlordPlayer.getName() != null) {
r = economy.depositPlayer(landlordPlayer, getWorldName(), price);
} else {
r = economy.depositPlayer(landlordName, getWorldName(), price);
}
if(r == null || !r.transactionSuccess()) {
AreaShop.warn("Something went wrong with paying '" + landlordName + "' " + Utils.formatCurrency(price) + " for his rent of region " + getName() + " to " + offlinePlayer.getName());
}
}
// Get the time until the region will be rented
Calendar calendar = Calendar.getInstance();
if(extendToMax) {
calendar.setTimeInMillis(calendar.getTimeInMillis() + getMaxRentTime());
} else if(extend) {
calendar.setTimeInMillis(getRentedUntil() + getDuration());
} else {
calendar.setTimeInMillis(calendar.getTimeInMillis() + getDuration());
}
// Add values to the rent and send it to FileManager
setRentedUntil(calendar.getTimeInMillis());
setRenter(offlinePlayer.getUniqueId());
updateLastActiveTime();
// Fire schematic event and updated times extended
if(!extend) {
this.handleSchematicEvent(RegionEvent.RENTED);
setTimesExtended(0);
} else {
setTimesExtended(getTimesExtended() + 1);
}
// Send message to the player
if(extendToMax) {
message(offlinePlayer, "rent-extendedToMax");
} else if(extend) {
message(offlinePlayer, "rent-extended");
} else {
message(offlinePlayer, "rent-rented");
}
// Notify about updates
this.notifyAndUpdate(new RentedRegionEvent(this, extend));
return true;
}
/**
@@ -650,20 +668,19 @@ public class RentRegion extends GeneralRegion {
}
}
if(plugin.getEconomy() == null) {
if(economy == null) {
return false;
}
// Broadcast and check event
UnrentingRegionEvent event = new UnrentingRegionEvent(this);
Bukkit.getPluginManager().callEvent(event);
if(event.isCancelled()) {
message(executor, "general-cancelled", event.getReason());
UnrentingRegionEvent unrentingRegionEvent = new UnrentingRegionEvent(this);
Bukkit.getPluginManager().callEvent(unrentingRegionEvent);
if(unrentingRegionEvent.isCancelled()) {
message(executor, "general-cancelled", unrentingRegionEvent.getReason());
return false;
}
// Run commands
this.runEventCommands(RegionEvent.UNRENTED, true);
// Do a payback
double moneyBack = getMoneyBackAmount();
if(moneyBack > 0 && giveMoneyBack) {
boolean noPayBack = false;
@@ -675,9 +692,9 @@ public class RentRegion extends GeneralRegion {
EconomyResponse r;
if(landlordName != null) {
if(landlordPlayer != null && landlordPlayer.getName() != null) {
r = plugin.getEconomy().withdrawPlayer(landlordPlayer, getWorldName(), moneyBack);
r = economy.withdrawPlayer(landlordPlayer, getWorldName(), moneyBack);
} else {
r = plugin.getEconomy().withdrawPlayer(landlordName, getWorldName(), moneyBack);
r = economy.withdrawPlayer(landlordName, getWorldName(), moneyBack);
}
if(r == null || !r.transactionSuccess()) {
noPayBack = true;
@@ -691,9 +708,9 @@ public class RentRegion extends GeneralRegion {
boolean error = false;
try {
if(player.getName() != null) {
r = plugin.getEconomy().depositPlayer(player, getWorldName(), moneyBack);
r = economy.depositPlayer(player, getWorldName(), moneyBack);
} else if(getPlayerName() != null) {
r = plugin.getEconomy().depositPlayer(getPlayerName(), getWorldName(), moneyBack);
r = economy.depositPlayer(getPlayerName(), getWorldName(), moneyBack);
}
} catch(Exception e) {
error = true;
@@ -704,25 +721,26 @@ public class RentRegion extends GeneralRegion {
}
}
// Send messages
message(executor, "unrent-unrented");
// Handle schematic save/restore (while %uuid% is still available)
handleSchematicEvent(RegionEvent.UNRENTED);
// Send message: before actual removal of the renter so that it is still available for variables
message(executor, "unrent-unrented");
// Remove friends, the owner and renteduntil values
getFriendsFeature().clearFriends();
UUID oldRenter = getRenter();
setRenter(null);
setRentedUntil(null);
setTimesExtended(-1);
removeLastActiveTime();
// Notify about updates
this.notifyAndUpdate(new UnrentedRegionEvent(this, oldRenter, Math.max(0, moneyBack)));
Bukkit.getPluginManager().callEvent(new UnrentedRegionEvent(this, oldRenter, Math.max(0, moneyBack)));
// Placed here so when event is passed, the player renting can still be accessed
setRenter(null);
// Update world (has to be after setting renter to null)
this.update();
// Run commands
this.runEventCommands(RegionEvent.UNRENTED, false);
return true;
}
@@ -1,147 +0,0 @@
package me.wiefferink.areashop.tools;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
import org.bstats.Metrics;
import java.util.HashMap;
public class Analytics {
/**
* Start analytics tracking.
*/
public static void start() {
// Legacy MCstats statistics (remove at some point)
try {
new me.wiefferink.areashop.lib.Metrics(AreaShop.getInstance()).start();
AreaShop.debug("Started mcstats.org statistics service");
} catch(Exception e) {
AreaShop.debug("Could not start mcstats.org statistics service");
}
// bStats statistics
try {
Metrics metrics = new Metrics(AreaShop.getInstance());
// Number of regions
metrics.addCustomChart(new Metrics.SingleLineChart("region_count") {
@Override
public int getValue() {
return AreaShop.getInstance().getFileManager().getRegions().size();
}
});
// Number of rental regions
metrics.addCustomChart(new Metrics.SingleLineChart("rental_region_count") {
@Override
public int getValue() {
return AreaShop.getInstance().getFileManager().getRents().size();
}
});
// Number of buy regions
metrics.addCustomChart(new Metrics.SingleLineChart("buy_region_count") {
@Override
public int getValue() {
return AreaShop.getInstance().getFileManager().getBuys().size();
}
});
// Language
metrics.addCustomChart(new Metrics.SimplePie("language") {
@Override
public String getValue() {
return AreaShop.getInstance().getConfig().getString("language");
}
});
// Pie with region states
metrics.addCustomChart(new Metrics.AdvancedPie("region_state") {
@Override
public HashMap<String, Integer> getValues(HashMap<String, Integer> result) {
RegionStateStats stats = getStateStats();
result.put("For Rent", stats.forrent);
result.put("Rented", stats.rented);
result.put("For Sale", stats.forsale);
result.put("Sold", stats.sold);
result.put("Reselling", stats.reselling);
return result;
}
});
// Time series of each region state
metrics.addCustomChart(new Metrics.SingleLineChart("forrent_region_count") {
@Override
public int getValue() {
return getStateStats().forrent;
}
});
metrics.addCustomChart(new Metrics.SingleLineChart("rented_region_count") {
@Override
public int getValue() {
return getStateStats().rented;
}
});
metrics.addCustomChart(new Metrics.SingleLineChart("forsale_region_count") {
@Override
public int getValue() {
return getStateStats().forsale;
}
});
metrics.addCustomChart(new Metrics.SingleLineChart("sold_region_count") {
@Override
public int getValue() {
return getStateStats().sold;
}
});
metrics.addCustomChart(new Metrics.SingleLineChart("reselling_region_count") {
@Override
public int getValue() {
return getStateStats().reselling;
}
});
// TODO track rent/buy/unrent/sell/resell actions (so that it can be reported per collection interval)
AreaShop.debug("Started bstats.org statistics service");
} catch(Exception e) {
AreaShop.debug("Could not start bstats.org statistics service");
}
}
private static class RegionStateStats {
int forrent = 0;
int forsale = 0;
int rented = 0;
int sold = 0;
int reselling = 0;
}
private static RegionStateStats getStateStats() {
RegionStateStats result = new RegionStateStats();
for(GeneralRegion region : AreaShop.getInstance().getFileManager().getRegions()) {
if(region instanceof RentRegion) {
RentRegion rent = (RentRegion)region;
if(rent.isAvailable()) {
result.forrent++;
} else {
result.rented++;
}
} else if(region instanceof BuyRegion) {
BuyRegion buy = (BuyRegion)region;
if(buy.isAvailable()) {
result.forsale++;
} else if(buy.isInResellingMode()) {
result.reselling++;
} else {
result.sold++;
}
}
}
return result;
}
}
@@ -0,0 +1,26 @@
package me.wiefferink.areashop.tools;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitScheduler;
import org.jetbrains.annotations.NotNull;
import javax.inject.Inject;
import java.util.concurrent.Executor;
public class BukkitSchedulerExecutor implements Executor {
private final Plugin plugin;
private final BukkitScheduler scheduler;
@Inject
public BukkitSchedulerExecutor(@NotNull Plugin plugin, @NotNull BukkitScheduler scheduler) {
this.plugin = plugin;
this.scheduler = scheduler;
}
@Override
public void execute(@NotNull Runnable command) {
this.scheduler.runTask(this.plugin, command);
}
}
@@ -49,8 +49,8 @@ public class GithubUpdateCheck {
this.author = author;
this.repository = repository;
this.currentVersion = plugin.getDescription().getVersion();
this.versionComparator = (latestVersion, currentVersion) ->
!latestVersion.equalsIgnoreCase(currentVersion);
this.versionComparator = (latest, current) ->
!latest.equalsIgnoreCase(current);
this.checking = false;
this.error = false;
@@ -0,0 +1,51 @@
package me.wiefferink.areashop.tools;
import org.bukkit.Material;
import org.bukkit.Tag;
public class Materials {
private Materials() {
}
/**
* Get material based on a sign material name.
* @param name Name of the sign material
* @return null if not a sign, otherwise the material matching the name (when the material is not available on the current minecraft version, it returns the base type)
*/
public static Material signNameToMaterial(String name) {
// Expected null case
if (!isSign(name)) {
return null;
}
try {
return Material.getMaterial(name);
} catch (IllegalArgumentException ex) {
ex.printStackTrace();
}
return null;
}
/**
* Check if a Material is a sign (of either the wall or floor type).
* @param material Material to check
* @return true if the given material is a sign
*/
public static boolean isSign(Material material) {
return Tag.SIGNS.isTagged(material);
}
/**
* Check if a Material is a sign (of either the wall or floor type).
* @param name String to check
* @return true if the given material is a sign
*/
public static boolean isSign(String name) {
try {
return isSign(Material.getMaterial(name));
} catch (IllegalArgumentException ex) {
return false;
}
}
}
@@ -0,0 +1,152 @@
package me.wiefferink.areashop.tools;
/**
* Parse math from a string
* Adapted from:
* https://stackoverflow.com/questions/3422673/how-to-evaluate-a-math-expression-given-in-string-form
*/
public final class OperandParser {
private final String str;
private OperandParser(final String str) {
this.str = str;
}
public static double parse(final String str) throws ParseException {
return new OperandParser(str).parse();
}
private int pos = -1, ch;
private void nextChar() {
ch = (++pos < str.length()) ? str.charAt(pos) : -1;
}
private boolean eat(int charToEat) {
while (ch == ' ') nextChar();
if (ch == charToEat) {
nextChar();
return true;
}
return false;
}
private double parse() throws ParseException {
nextChar();
double x = parseExpression();
if (pos < str.length())
{
throw new ParseException("Unexpected: " + (char) ch);
}
return x;
}
// Grammar:
// expression = term | expression `+` term | expression `-` term
// term = factor | term `*` factor | term `/` factor
// factor = `+` factor | `-` factor | `(` expression `)`
// | number | functionName factor | factor `^` factor
private double parseExpression() throws ParseException {
double x = parseTerm();
for (; ; ) {
if (eat('+')) {
// addition
x += parseTerm();
}
else if (eat('-')) {
// subtraction
x -= parseTerm();
}
else return x;
}
}
private double parseTerm() throws ParseException {
double x = parseFactor();
for (; ; ) {
if (eat('*')) {
// multiplication
x *= parseFactor();
}
else if (eat('/')) {
// division
x /= parseFactor();
}
else return x;
}
}
private double parseFactor() throws ParseException {
if (eat('+')) {
// unary plus
return parseFactor();
}
if (eat('-')) {
// unary minus
return -parseFactor();
}
double x;
int startPos = this.pos;
if (eat('(')) {
// parentheses
x = parseExpression();
eat(')');
} else if ((ch >= '0' && ch <= '9') || ch == '.') {
// numbers
while ((ch >= '0' && ch <= '9') || ch == '.') {
nextChar();
}
x = Double.parseDouble(str.substring(startPos, this.pos));
} else if (ch >= 'a' && ch <= 'z') {
// functions
while (ch >= 'a' && ch <= 'z') {
nextChar();
}
String func = str.substring(startPos, this.pos);
x = parseFactor();
x = switch (func) {
case "sqrt" -> Math.sqrt(x);
case "sin" -> Math.sin(Math.toRadians(x));
case "cos" -> Math.cos(Math.toRadians(x));
case "tan" -> Math.tan(Math.toRadians(x));
default -> throw new ParseException("Unknown function: " + func);
};
} else {
throw new ParseException("Unexpected: " + (char) ch);
}
if (eat('^')) {
// exponentiation
x = Math.pow(x, parseFactor());
}
return x;
}
public static class ParseException extends Exception {
public ParseException() {
}
public ParseException(String message) {
super(message);
}
public ParseException(String message, Throwable cause) {
super(message, cause);
}
public ParseException(Throwable cause) {
super(cause);
}
public ParseException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}
}
@@ -0,0 +1,97 @@
package me.wiefferink.areashop.tools;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.type.Sign;
import org.bukkit.block.data.type.WallSign;
/**
* Sign Utilities class
*/
public final class SignUtils {
private SignUtils() {
}
/**
* Get the {@link BlockFace} of a sign block
* If the passed {@link Block} is not an instance of either
* a {@link Sign} or {@link WallSign}, this method will return <code>null</code>
*
* @param block The sign
* @return Returns the {@link BlockFace} of the sign or <code>null</code>
*/
public static BlockFace getSignFacing(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if (blockData instanceof WallSign wallSign) {
return wallSign.getFacing();
} else if (blockData instanceof org.bukkit.block.data.type.Sign sign) {
return sign.getRotation();
}
return null;
}
/**
* Set the {@link BlockFace} in which the sign will face
* If the passed {@link Block} is not an instance of either
* a {@link Sign} or {@link WallSign}, this method will return <code>null</code>.
*
* @param block The sign block
* @param facing The new {@link BlockFace} the sign should face
* @return Returns <code>true</code> if the sign was successfully placed, <code>false</code> otherwise
*/
public static boolean setSignFacing(Block block, BlockFace facing) {
if (block == null || facing == null) {
return false;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if (blockData instanceof WallSign wallSign) {
wallSign.setFacing(facing);
} else if (blockData instanceof org.bukkit.block.data.type.Sign sign) {
sign.setRotation(facing);
} else {
return false;
}
block.setBlockData(blockData);
return true;
}
/**
* Get the {@link Block} which a given sign is attached to.
* This method will return <code>null</code> if the passed {@link Block}
* is not an instance of either a {@link Sign} or {@link WallSign}.
*
* @param block The sign {@link Block}
* @return Returns the block which the sign is attached to or null
*/
public static Block getSignAttachedTo(Block block) {
if (block == null) {
return null;
}
BlockState blockState = block.getState();
BlockData blockData = blockState.getBlockData();
if (blockData instanceof WallSign wallSign) {
return block.getRelative(wallSign.getFacing().getOppositeFace());
} else if (blockData instanceof Sign) {
return block.getRelative(BlockFace.DOWN);
}
return null;
}
}
@@ -0,0 +1,32 @@
package me.wiefferink.areashop.tools;
import com.google.inject.Singleton;
import me.wiefferink.areashop.MessageBridge;
import me.wiefferink.interactivemessenger.processing.Message;
@Singleton
public class SimpleMessageBridge implements MessageBridge {
/**
* Send a message to a target without a prefix.
* @param target The target to send the message to
* @param key The key of the language string
* @param replacements The replacements to insert in the message
*/
@Override
public void messageNoPrefix(Object target, String key, Object... replacements) {
Message.fromKey(key).replacements(replacements).send(target);
}
/**
* Send a message to a target, prefixed by the default chat prefix.
* @param target The target to send the message to
* @param key The key of the language string
* @param replacements The replacements to insert in the message
*/
@Override
public void message(Object target, String key, Object... replacements) {
Message.fromKey(key).prefix().replacements(replacements).send(target);
}
}
@@ -0,0 +1,42 @@
package me.wiefferink.areashop.tools;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
public class SpigotOfflinePlayerHelper implements OfflinePlayerHelper {
private final Plugin plugin;
public SpigotOfflinePlayerHelper(@NotNull Plugin plugin) {
this.plugin = plugin;
}
@Override
public CompletableFuture<Optional<UUID>> lookupUuidAsync(String username) {
return lookupOfflinePlayerAsync(username).thenApply(player -> {
if (player.hasPlayedBefore()) {
return Optional.of(player.getUniqueId());
}
return Optional.empty();
});
}
@Override
public CompletableFuture<OfflinePlayer> lookupOfflinePlayerAsync(String username) {
final CompletableFuture<OfflinePlayer> future = new CompletableFuture<>();
final Server server = this.plugin.getServer();
server.getScheduler().runTaskAsynchronously(this.plugin, () -> {
@SuppressWarnings("deprecation")
OfflinePlayer player = server.getOfflinePlayer(username);
future.complete(player);
});
return future;
}
}
@@ -0,0 +1,20 @@
package me.wiefferink.areashop.tools;
import me.wiefferink.areashop.adapters.platform.MinecraftPlatform;
import me.wiefferink.areashop.adapters.platform.OfflinePlayerHelper;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
public class SpigotPlatform implements MinecraftPlatform {
private final OfflinePlayerHelper offlinePlayerHelper;
public SpigotPlatform(@NotNull Plugin plugin) {
this.offlinePlayerHelper = new SpigotOfflinePlayerHelper(plugin);
}
@Override
public OfflinePlayerHelper offlinePlayerHelper() {
return this.offlinePlayerHelper;
}
}
@@ -1,10 +1,10 @@
package me.wiefferink.areashop.tools;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import me.wiefferink.areashop.AreaShop;
import me.wiefferink.areashop.interfaces.WorldEditSelection;
import me.wiefferink.areashop.interfaces.WorldGuardInterface;
import me.wiefferink.areashop.regions.BuyRegion;
import me.wiefferink.areashop.regions.GeneralRegion;
import me.wiefferink.areashop.regions.RentRegion;
@@ -21,10 +21,9 @@ import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.inject.Inject;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.RoundingMode;
@@ -45,6 +44,11 @@ public class Utils {
private Utils() {
}
@Inject
private static AreaShop plugin;
@Inject
private static WorldGuardInterface worldGuardInterface;
private static YamlConfiguration config;
private static Set<String> identifiers;
private static Set<String> seconds;
@@ -54,7 +58,6 @@ public class Utils {
private static Set<String> weeks;
private static Set<String> months;
private static Set<String> years;
private static ScriptEngine scriptEngine;
private static Map<Double, String> suffixes;
/**
@@ -265,7 +268,7 @@ public class Utils {
public static String millisToHumanFormat(long milliseconds) {
long timeLeft = milliseconds + 500;
// To seconds
timeLeft = timeLeft / 1000;
timeLeft /= 1000;
if(timeLeft <= 0) {
return Message.fromKey("timeleft-ended").getPlain();
} else if(timeLeft == 1) {
@@ -274,27 +277,27 @@ public class Utils {
return Message.fromKey("timeleft-seconds").replacements(timeLeft).getPlain();
}
// To minutes
timeLeft = timeLeft / 60;
timeLeft /= 60;
if(timeLeft <= 120) {
return Message.fromKey("timeleft-minutes").replacements(timeLeft).getPlain();
}
// To hours
timeLeft = timeLeft / 60;
timeLeft /= 60;
if(timeLeft <= 48) {
return Message.fromKey("timeleft-hours").replacements(timeLeft).getPlain();
}
// To days
timeLeft = timeLeft / 24;
timeLeft /= 24;
if(timeLeft <= 60) {
return Message.fromKey("timeleft-days").replacements(timeLeft).getPlain();
}
// To months
timeLeft = timeLeft / 30;
timeLeft /= 30;
if(timeLeft <= 24) {
return Message.fromKey("timeleft-months").replacements(timeLeft).getPlain();
}
// To years
timeLeft = timeLeft / 12;
timeLeft /= 12;
return Message.fromKey("timeleft-years").replacements(timeLeft).getPlain();
}
@@ -321,7 +324,7 @@ public class Utils {
public static List<GeneralRegion> getRegionsInSelection(WorldEditSelection selection) {
ArrayList<GeneralRegion> result = new ArrayList<>();
for(ProtectedRegion region : getWorldEditRegionsInSelection(selection)) {
GeneralRegion asRegion = AreaShop.getInstance().getFileManager().getRegion(region.getId());
GeneralRegion asRegion = plugin.getFileManager().getRegion(region.getId());
if(asRegion != null) {
result.add(asRegion);
}
@@ -346,13 +349,13 @@ public class Utils {
public static List<ProtectedRegion> getWorldEditRegionsInSelection(WorldEditSelection selection) {
// Get all regions inside or intersecting with the WorldEdit selection of the player
World world = selection.getWorld();
RegionManager regionManager = AreaShop.getInstance().getRegionManager(world);
RegionManager regionManager = plugin.getRegionManager(world);
ArrayList<ProtectedRegion> result = new ArrayList<>();
Location selectionMin = selection.getMinimumLocation();
Location selectionMax = selection.getMaximumLocation();
for(ProtectedRegion region : regionManager.getRegions().values()) {
BlockVector regionMin = region.getMinimumPoint();
BlockVector regionMax = region.getMaximumPoint();
Vector regionMin = worldGuardInterface.getMinimumPoint(region);
Vector regionMax = worldGuardInterface.getMaximumPoint(region);
if(
( // x part, resolves to true if the selection and region overlap anywhere on the x-axis
(regionMin.getBlockX() <= selectionMax.getBlockX() && regionMin.getBlockX() >= selectionMin.getBlockX())
@@ -385,7 +388,7 @@ public class Utils {
*/
public static List<ProtectedRegion> getImportantWorldEditRegions(Location location) {
List<ProtectedRegion> result = new ArrayList<>();
Set<ProtectedRegion> regions = AreaShop.getInstance().getWorldGuardHandler().getApplicableRegionsSet(location);
Set<ProtectedRegion> regions = worldGuardInterface.getApplicableRegionsSet(location);
if(regions != null) {
boolean first = true;
for(ProtectedRegion pr : regions) {
@@ -455,11 +458,11 @@ public class Utils {
*/
public static List<GeneralRegion> getImportantRegions(Location location, GeneralRegion.RegionType type) {
List<GeneralRegion> result = new ArrayList<>();
Set<ProtectedRegion> regions = AreaShop.getInstance().getWorldGuardHandler().getApplicableRegionsSet(location);
Set<ProtectedRegion> regions = worldGuardInterface.getApplicableRegionsSet(location);
if(regions != null) {
List<GeneralRegion> candidates = new ArrayList<>();
for(ProtectedRegion pr : regions) {
GeneralRegion region = AreaShop.getInstance().getFileManager().getRegion(pr.getId());
GeneralRegion region = plugin.getFileManager().getRegion(pr.getId());
if(region != null && (
(type == GeneralRegion.RegionType.RENT && region instanceof RentRegion)
|| (type == GeneralRegion.RegionType.BUY && region instanceof BuyRegion)
@@ -599,7 +602,7 @@ public class Utils {
public static long durationStringToLong(String duration) {
if(duration == null) {
return 0;
} else if(duration.equalsIgnoreCase("disabled") || duration.equalsIgnoreCase("unlimited") || duration.length() == 0) {
} else if(duration.equalsIgnoreCase("disabled") || duration.equalsIgnoreCase("unlimited") || duration.isEmpty()) {
return -1;
} else if(duration.indexOf(' ') == -1) {
return 0;
@@ -647,7 +650,7 @@ public class Utils {
if(config.isLong(path) || config.isInt(path)) {
long setting = config.getLong(path);
if(setting != -1) {
setting = setting * 1000;
setting *= 1000;
}
return setting;
} else {
@@ -665,7 +668,7 @@ public class Utils {
if(config.isLong(path) || config.isInt(path)) {
long setting = config.getLong(path);
if(setting != -1) {
setting = setting * 60 * 1000;
setting *= 60 * 1000;
}
return setting;
} else {
@@ -683,7 +686,7 @@ public class Utils {
try {
number = Long.parseLong(input);
if(number != -1) {
number = number * 60 * 1000;
number *= 60 * 1000;
}
return number;
} catch(NumberFormatException e) {
@@ -701,7 +704,7 @@ public class Utils {
try {
number = Long.parseLong(input);
if(number != -1) {
number = number * 1000;
number *= 1000;
}
return number;
} catch(NumberFormatException e) {
@@ -755,16 +758,11 @@ public class Utils {
return Double.parseDouble(input);
}
// Lazy init scriptEngine
if(scriptEngine == null) {
scriptEngine = new ScriptEngineManager().getEngineByName("JavaScript");
}
// Evaluate expression
Object result;
try {
result = scriptEngine.eval(input);
} catch(ScriptException e) {
result = OperandParser.parse(input);
} catch(OperandParser.ParseException e) {
AreaShop.warn("Price of region", region.getName(), "is set with an invalid expression: '" + input + "', exception:", ExceptionUtils.getStackTrace(e));
return 99999999999.0; // High fallback for safety
}
@@ -2,29 +2,29 @@ package me.wiefferink.areashop.tools;
public class Value<T> {
private T value;
private T content;
/**
* Create a container with a default value.
* @param value The value to set
* Create a container with a default content.
* @param content The content to set
*/
public Value(T value) {
this.value = value;
public Value(T content) {
this.content = content;
}
/**
* Get the stored value.
* @return The stored value
* Get the stored content.
* @return The stored content
*/
public T get() {
return value;
return content;
}
/**
* Set the value.
* @param value The new value
* Set the content.
* @param value The new content
*/
public void set(T value) {
this.value = value;
this.content = value;
}
}
+4
View File
@@ -121,6 +121,10 @@ debug: false
version: ${project.version}
# Maximum number of blocks to save to or restore from a .schemetic file.
maximumBlocks: 1000000
# Whether to forcefully clear "hanging" entities (painting, itemframes, etc.) on region restore
# Only enable this option if hanging entities at the destination aren't removed on restore normally
# If set to true, there may be a performance impact when performing region restores.
forceClearEntities: false
# Maximum number of locations the teleport function should check to find a safe spot.
maximumTries: 50000
+1 -1
View File
@@ -10,7 +10,7 @@ general:
# The y location within the region to start searching for safe teleport locations (x and z are in the middle of the region).
# Possible values: 'bottom', 'middle', 'top' or a number indicating an exact y coordinate.
teleportLocationY: bottom
# If true the teleportation algorithm only allows telportation to inside the region, otherwise it will expand
# If true the teleportation algorithm only allows teleportation to inside the region, otherwise it will expand
# a cube from the starting point to check for safe spots (then it could end outside of the region).
teleportIntoRegion: true
# Same as above, but then for when you teleport to the sign of a region instead of the region itself.
+7 -3
View File
@@ -414,6 +414,9 @@ add-success: "Added as %0%: [gray]%1%."
add-failed: "Already registered: [gray]%0%."
add-failedOtherWorld: "Already registered from another world: [gray]%0%."
add-blacklisted: "On the blacklist: [gray]%0%."
add-rentCancelled: "Rent cancelled: [gray]%0%."
add-buyCancelled: "Buy cancelled: [gray]%0%."
add-addCancelled: "Add cancelled: [gray]%0%."
add-specifyWorld: "Specify the world of the region when using from console."
add-incorrectWorld: "World '%0%' not found, try again (case-sensitive)."
add-noPermissionRegions: "No permission to add: [gray]%0%."
@@ -422,6 +425,7 @@ add-noPermissionOwnerMember: "[gray]You either are not a member/owner of these r
del-noPermission: "You don't have permission to remove regions."
del-success: "Removed regions: [gray]%0%."
del-failed: "No permission to remove or not registered: [gray]%0%."
del-cancelled: "Delete cancelled: [gray]%0%."
addsign-help: "/as addsign [region] [profile]."
addsign-noSign: "You are not looking at a sign."
@@ -615,7 +619,7 @@ greeting-resale: "%region% can be bought for %resellprice% from %player%."
update-playerNotify:
- "[darkgreen]Update from AreaShop V%0% to AreaShop V%1% available, get the latest version at "
- "[bold]Spigot[/bold]"
- " hover: %lang:action|Go to the Spigot AreaShop page|%"
- " link: https://www.spigotmc.org/resources/areashop.2991/"
- "[bold]Github[/bold]"
- " hover: %lang:action|Go to the AreaShop Github Releases|%"
- " link: https://github.com/md5sha256/releases"
- " (and leave a review)."
+3 -1
View File
@@ -1,6 +1,6 @@
# ╔═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
# ║ Language file of the AreaShop plugin created by NLThijs48, Github can be found at https://github.com/NLthijs48/AreaShop
# ║ Spanish language file, plugin version 2.5.0, 424/428 messages are translated (99%)
# ║ Spanish language file, plugin version 2.5.0, 426/428 messages are translated (100%)
# ║
# ║ This file will be overwritten at each startup/reload of the plugin, if you want to change anything then do the following:
# ║ 1: Make a copy of this file
@@ -138,6 +138,7 @@
"sell-sold": "La región %lang:region%, de %lang:player%, ha sido vendida."
"sell-noPermission": "No tienes permiso para vender regiones."
"sell-noPermissionOther": "No tienes permiso para vender regiones ajenas."
"sell-disabled": "La venta fue desactivada para esta región."
"reload-reloading": "Todos los archivos han sido recargados, comprobando alquileres y actualizando regiones..."
"reload-noPermission": "No tienes permiso para recargar los archivos de configuración."
"reload-updateCommandChanged": "Los comandos '/as updaterents' y '/as updatebuys' han sido borrados, '/as reload' actualizará las regiones. Puedes usar este comando en vez de los 2 primeros."
@@ -432,6 +433,7 @@
"resell-success": "%lang:region% está en modo reventa por %resellprice%."
"resell-noPermission": "No tienes permiso para cambiar tu región a modo reventa."
"resell-noPermissionOther": "No tienes permiso para cambiar las regiones a modo reventa."
"resell-disabled": "La reventa fue deshabilitada para esta región."
"stopresell-help": "/as stopresell [región], la región en la que estás se usará si no se especifican nombres."
"stopresell-notRegistered": "La región especificada no es válida: %0%."
"stopresell-notResell": "No puedes parar la reventa de %lang:region% porque no está en modo reventa."
+33 -1
View File
@@ -1,6 +1,6 @@
# ╔═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
# ║ Language file of the AreaShop plugin created by NLThijs48, Github can be found at https://github.com/NLthijs48/AreaShop
# ║ French language file, plugin version 2.5.0, 399/428 messages are translated (93%)
# ║ French language file, plugin version 2.5.0, 428/428 messages are translated (100%)
# ║
# ║ This file will be overwritten at each startup/reload of the plugin, if you want to change anything then do the following:
# ║ 1: Make a copy of this file
@@ -178,6 +178,10 @@
"info-pageNoPrevious":
- " [darkgray][bold]◄Précédent[/bold] "
- " hover: C'est déjà la premier page"
"info-pageNext":
- "[gold][bold]Suivant►[/bold]"
- "hover: %lang:action|Page suivante|%"
- "commande: /areashop "
"info-pageNoNext":
- " [darkgray][bold]Suivaznt►[/bold]"
- " hover: C'est déjà la dernière page"
@@ -290,6 +294,7 @@
"setduration-successRemoved": "La durée de location de %lang:region% a été supprimé, maintenant celle-ci utilisera le durée de location du group ou du fichier default.yml, nouvelle durée de location : %duration%."
"setup-noRegion": "Vous n'avez pas spécifié de région à la seconde ligne."
"setup-alreadyRentSign": "La région que vous avez spécifiée a déjà été ajoutée à AreaShop en tant qu'une région louable, ajoutez un panneau avec [as] sur le première ligne ou tapez '/as addsign'."
"setup-alreadyOtherWorld": "La région que vous avez spécifiée est déjà ajoutée à AreaShop dans un autre monde. Les régions de différents mondes ont toujours besoin de noms différents."
"setup-alreadyBuySign": "La région que vous avez spécifiée a déjà été ajoutée à AreaShop en tant qu'une région achetable, ajoutez un panneau avec [as] sur le première ligne ou tapez '/as addsign'."
"setup-noDuration": "A la troisième ligne, vous n'avez pas spécifié la durée de location de la région."
"setup-wrongDuration": "Le temps spécifié n'est pas au bon format. Exemple : 1 day."
@@ -368,6 +373,7 @@
"add-noPermission": "Vous n'avez pas la permission d'ajouter une région à AreaShop."
"add-success": "Ajoutée comme %0% : [gray]%1%."
"add-failed": "Déjà enregistré: [gray]%0%."
"add-failedOtherWorld": "Déjà inscrit d'un autre monde: [gray]%0%."
"add-blacklisted": "Dans la liste noir: [gray]%0%."
"add-specifyWorld": "Spécifiez le monde de la région lors de l'utilisation de la console."
"add-incorrectWorld": "Le monde '%0%' est introuvable, essayez de nouveau (attention à la casse)."
@@ -379,6 +385,7 @@
"addsign-help": "/as addsign [region] [profile]"
"addsign-noSign": "Vous ne regardez pas de panneau."
"addsign-noRegions": "Aucune région trouvée autour du panneau."
"addSign-notRegistered": "La région spécifiée n'est pas enregistrée dans AreaShop: %0% (elle doit d'abord être ajoutée à AreaShop avant qu'un signe puisse être ajouté)."
"addsign-couldNotDetect": "Plusieurs régions ont été trouvées à proximité du panneau. Spécifiez la région en argument supplémentaire (2 des régions trouvées: %lang:tRegion|%0%|% et %lang:tRegion|%1%|%)."
"addsign-couldNotDetectSign": "Plusieurs régions ont été trouvées à proximité du panneau. Spécifiez la région à la deuxième ligne (2 des régions trouvées: %lang:tRegion|%0%|% et %lang:tRegion|%1%|%)."
"addsign-wrongProfile": "Le profil spécifié n'existe pas, utilisez l'un de la liste suivante (Vérifiez la config): [gray]%0%."
@@ -428,6 +435,7 @@
"resell-success": "%lang:region% a été mise en revente avec succès pour un prix de %resellprice%."
"resell-noPermission": "Vous n'avez pas la permission de mettre votre région en revente."
"resell-noPermissionOther": "Vous n'avez pas la permission de mettre des régions en revente."
"resell-disabled": "La revente a été désactivée pour cette région."
"stopresell-help": "/as stropresell [région], la région où vous vous trouvez sera utilisée si vous ne spécifiez pas de région."
"stopresell-notRegistered": "La région spécifiée n'est pas enregistrée : %0%."
"stopresell-notResell": "Vous ne pouvez pas stopper la revente %lang:region% car elle n'est pas en mode revente."
@@ -486,6 +494,30 @@
"message-help": "/as message <joueur> <message...>"
"message-noPermission": "Vous n'avez pas la permission d'envoyer des messages AreaShop."
"message-notOnline": "%0% n'est pas connecté."
"import-help": "/as import RegionAVendre"
"import-wrongSource": "Spécifiez d'où vous voulez importer les données, les options: RegionAVendre"
"import-noPluginFolder": "Impossible de trouver le dossier %0%, êtes-vous sûr que vous importez de la bonne source?"
"import-noWorldsFolder": "Il n'y a pas de dossier 'plugins/RegionForSale/worlds' donc rien ne peut être importé."
"import-confirm": "Êtes-vous sûr de vouloir importer toutes les régions de RegionAVendre?"
"import-start": "Début de l'importation des données RegionAVendre :"
"import-doWorld": "[darkgreen][bold]► Monde %0% :"
"import-noBukkitWorld": "[red]Impossible de trouver le monde dans Bukkit."
"import-noRegionManager": "[red]Impossible d’obtenir RegionManager de WorldGuard, les régions sont-elles activées dans ce monde?"
"import-noRegions": "[red]Pas de fichier regions.yml trouvé."
"import-loadRegionsFailed": "[red]Impossible de charger regions.yml de : %0%"
"import-invalidRegionSection": "[red]Mauvaise section dans regions.yml : %0%."
"import-noWorldGuardRegion": "[red]La région de WorldGuard n'a pas été trouvée :%0%."
"import-noWorldGuardRegionParent": "[red]La région de WorldGuard pour la région parent n'a pas été trouvé : %0%"
"import-buyAndRent": "[gold] %0% peuvent être achetés et loués, seulement en ajoutant comme achat dans AreaShop (ne peuvent pas être les deux)."
"import-noBuyAndNoRent": "[red]%0% ne peut pas être acheté ni être loué sans importer."
"import-imported": "[green]%lang:tRegion|%0% importé."
"import-loadWorldConfigFailed": "[red} Chargement de world-specific config.yml échoué : %0%."
"import-improperParentRegion": "[red]Region parent %0% n'a pas de réglages lisible."
"import-alreadyAdded": "[red]Region '%0%' a déjà été ajoutée."
"import-alreadyAddedOtherWorld": "[red]Region '%0%' a déjà été ajoutée dans le monde %1%, les régions de différents mondes ne peuvent pas avoir le même nom dans AreaShop."
"import-invalidSignLocation": "[red]Echec d'importation de la pancarte de la région '%0%', location invalide '%1%'."
"import-signAlreadyAdded": "[red] Ignoré l'ajout de la pancarte à la location '%1%' de la région '%0%', il est déjà ajouté à la région '%2%'."
"import-moneyBackFailed": "[red] Échec de l'analyse du prix d'achat '%0%' et du prix de vente '%1%' pour définir le pourcentage de remboursement."
"confirm-rent":
- "%lang:prefix%Êtes-vous sur de vouloir louer %lang:tRegion|%0%|%?[break]"
- "[darkgreen][bold]►[reset] %lang:button|Cliquez ici pour louer %0%|%"
+9 -1
View File
@@ -1,6 +1,6 @@
# ╔═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════
# ║ Language file of the AreaShop plugin created by NLThijs48, Github can be found at https://github.com/NLthijs48/AreaShop
# ║ Russian language file, plugin version 2.5.0, 395/428 messages are translated (92%)
# ║ Russian language file, plugin version 2.5.0, 403/428 messages are translated (94%)
# ║
# ║ This file will be overwritten at each startup/reload of the plugin, if you want to change anything then do the following:
# ║ 1: Make a copy of this file
@@ -136,6 +136,7 @@
"sell-sold": "%lang:region% был продан %lang:player%."
"sell-noPermission": "У Вас нет прав для продажи региона."
"sell-noPermissionOther": "У Вас нет прав для продажи другого региона."
"sell-disabled": "Продажа была отключена для этого региона"
"reload-reloading": "Перезагружены все конфигурации и файлы регионов."
"reload-noPermission": "Недостаточно полномочий для того, чтобы перезагрузить конфиги плагина."
"reload-updateCommandChanged": "'/as updaterents' и '/as updatebuys' были удалены, '/as reload' теперь будет также обновлять регионы, используйте взамен эту команду."
@@ -283,6 +284,7 @@
"setduration-successRemoved": "Длительность аренды в %lang:region% было удалено, использование новой длительности аренды из группы или файла default.yml, новая длительность: %duration%."
"setup-noRegion": "Вы не указали регион на второй строке."
"setup-alreadyRentSign": "Регион уже добавлен в AreaShop в виде аренды региона, добавьте табличку с [as] на первой строке, или '/as addsign'."
"setup-alreadyOtherWorld": "Регион который ты выбрал уже добавлен в AreaShop в другом мире, регионы из разных миров должы иметь разные названия"
"setup-alreadyBuySign": "Регион уже добавлен в AreaShop в виде покупного региона, добавьте табличку с [as] на первой строке, или '/as addsign'."
"setup-noDuration": "Вы не указали, на сколько времени этот регион можно арендовать, сделайте это на третьей строчке."
"setup-wrongDuration": "Время указано не в правильном формате, например: 1 day."
@@ -361,6 +363,7 @@
"add-noPermission": "У вас нет разрешения добавлять регионы в AreaShop."
"add-success": "Добавлен в %0%: [gray]%1%."
"add-failed": "Уже зарегистрирован: [gray]%0%."
"add-failedOtherWorld": "Уже зарегистрирован в другом мире: [gray]"
"add-blacklisted": "Включен в черный список : [gray]%0%."
"add-specifyWorld": "Укажите мир региона при использовании из консоли."
"add-incorrectWorld": "Мир '%0%' не найден, попробуйте еще раз (с учетом регистра)."
@@ -372,6 +375,7 @@
"addsign-help": "/as addsign [регион] [профиль]."
"addsign-noSign": "Вы не смотрите на табличку."
"addsign-noRegions": "Не найдено регионов вокруг таблички."
"addSign-notRegistered": "Данный регион не зарегистрирован в AreaShop%0% (сначало нужно добавить регион в AreaShop прежде чем создавать табичку)"
"addsign-couldNotDetect": "Найдено несколько регионов вокруг таблички, укажите регион в качестве дополнительного аргумента (2 из регионов, которые были найдены: %lang:tRegion|%0%|% и %lang:tRegion|%1%|%)."
"addsign-couldNotDetectSign": "Найдено несколько регионов вокруг таблички, укажите регион на второй строке (2 из регионов, которые были найдены: %lang:tRegion|%0%|% и %lang:tRegion|%1%|%)."
"addsign-wrongProfile": "Указанный профиль не существует, используйте одно из следующих действий (проверьте конфиг.): [gray]%0%."
@@ -421,6 +425,7 @@
"resell-success": "%lang:region% был успешно выставлен в режим перепродажи за %resellprice%."
"resell-noPermission": "У Вас нет прав что бы установить ваш регион в режим перепродажи."
"resell-noPermissionOther": "У Вас нет прав что бы установить регион в режим перепродажи."
"resell-disabled": "Перепродажа была отключенна для этого региона"
"stopresell-help": "/as stopresell [имярегиона], если не указано имя, будет выбран регион в котором вы находитесь."
"stopresell-notRegistered": "Указанный регион не зарегистрирован: %0%."
"stopresell-notResell": "Вы не можете остановить перепродажу %lang:region% потому что регион не в режиме перепродажи."
@@ -479,6 +484,9 @@
"message-help": "/as message <игрок> <сообщение...>"
"message-noPermission": "У вас нет разрешения на отправку AreaShop сообщений."
"message-notOnline": "%0% не в сети."
"import-help": "/as import RegionForSale"
"import-confirm": "Вы действительно хотите импортировать все регионы из RegionForSale?"
"import-noWorldGuardRegion": "[red]WorldGuard регион не найден:"
"confirm-rent":
- "%lang:prefix%Вы уверены, что вы хотите арендовать %lang:tRegion|%0%|%?[break]"
- "[darkgreen][bold]►[reset] %lang:button|Нажмите, чтобы арендовать %0%|%"
Loaded 100 of 173 files, more files were not shown because too many files have changed in this diff. Show more