Compare commits
121 Commits
Author | SHA1 | Date |
---|---|---|
Johan | af02eb3f14 | |
Max Lee | 7dbc1ad5d3 | |
Phoenix616 | 9f4037c312 | |
Phoenix616 | b6b7a6bf43 | |
Phoenix616 | 60b10a83b6 | |
Phoenix616 | b54824052d | |
Johanmans10 | 8a26b15ea9 | |
Phoenix616 | 09170f6d51 | |
Phoenix616 | 488cd2e9d5 | |
Phoenix616 | 46d4f583ba | |
Phoenix616 | 7a73d66939 | |
Phoenix616 | 6f5b56d20a | |
Phoenix616 | b386cacb5e | |
Phoenix616 | df17fe7483 | |
Phoenix616 | d3f8abb80e | |
Phoenix616 | 2388da62a5 | |
Phoenix616 | 53aa75d9b4 | |
Phoenix616 | a413e86ccf | |
Phoenix616 | 0fcbcbbb11 | |
Phoenix616 | a9cb8096e6 | |
Phoenix616 | 17bd2a1fcb | |
Phoenix616 | d426492561 | |
Joo200 | f3cf4cd96e | |
Phoenix616 | 9bbd6028d0 | |
Phoenix616 | 2b36b7314f | |
Phoenix616 | 0b8fe80443 | |
Phoenix616 | 3ef02d05cd | |
Phoenix616 | 3a1885e2f3 | |
Phoenix616 | 54cc1ce842 | |
Phoenix616 | dc6aa21a91 | |
Phoenix616 | 6ba8e092b8 | |
Phoenix616 | 97ffc31d2b | |
Phoenix616 | ed642ccf3c | |
Phoenix616 | 999f596125 | |
Phoenix616 | 30ff61d14f | |
Phoenix616 | 978f1270f5 | |
Phoenix616 | 7203ec17cd | |
Max Lee | 6602be68e3 | |
Krakenied | 2fb82a2529 | |
Phoenix616 | 05ebe2d054 | |
Phoenix616 | 013a21159f | |
Phoenix616 | d52c329618 | |
Phoenix616 | b425dfb69f | |
Phoenix616 | 0a16ec1d08 | |
Phoenix616 | 362dd856d3 | |
Phoenix616 | 385672ecd4 | |
Phoenix616 | 92a013dd10 | |
Phoenix616 | 7a09c53bde | |
Phoenix616 | 93f14a330d | |
Phoenix616 | 199573df59 | |
Phoenix616 | a38f309453 | |
Phoenix616 | 02ef09c586 | |
Phoenix616 | aa7bfbb7ee | |
Phoenix616 | 7d92cb820d | |
Phoenix616 | 4de1f1e8c5 | |
Phoenix616 | 7ee8d07242 | |
Phoenix616 | 37c7b97fe8 | |
Phoenix616 | 0d8d37eb85 | |
Phoenix616 | e6a2d2f1c5 | |
Phoenix616 | ada8cf3ae8 | |
Phoenix616 | fbfe789bfa | |
Phoenix616 | f547995164 | |
Phoenix616 | d6673c8afd | |
Phoenix616 | f0661656a0 | |
Phoenix616 | 967a315ff8 | |
Phoenix616 | 59e82c7078 | |
Phoenix616 | 236c4b1b37 | |
Phoenix616 | 32879ad3cd | |
Phoenix616 | c15afb4d0b | |
Phoenix616 | 852f20a50e | |
Phoenix616 | e3ab44ae32 | |
Phoenix616 | 9233064273 | |
Phoenix616 | 93e2895645 | |
Phoenix616 | e99ae1eb1e | |
Felipe Foschiera | 9842f47f37 | |
Max Lee | 34df7e368a | |
Jonathan Leitschuh | 5066a21a5f | |
Phoenix616 | da3928b723 | |
Phoenix616 | d0af977212 | |
Phoenix616 | e3cd50cf75 | |
Phoenix616 | a78b925181 | |
Phoenix616 | 5b712f9ed5 | |
Phoenix616 | c54ed6b2f5 | |
Max Lee | f57d1b04a2 | |
Max Lee | 6b372883ac | |
Krakenied | fd969cd996 | |
Phoenix616 | fd0035a99c | |
Phoenix616 | 4285358910 | |
Phoenix616 | dc731919e3 | |
Phoenix616 | a112c50d55 | |
Phoenix616 | 4c7b018f8c | |
Krakenied | 2ebc2f285b | |
Phoenix616 | e40b5567b8 | |
Phoenix616 | 419527efaa | |
Phoenix616 | 99a609b423 | |
jeffry1829 | 5ec2ab61e5 | |
Phoenix616 | d1bbcfce47 | |
Phoenix616 | fa924f0212 | |
Phoenix616 | f9a0bf90a3 | |
Phoenix616 | 02dd167024 | |
Phoenix616 | 8655870077 | |
Phoenix616 | 01b7cddaa3 | |
Phoenix616 | 6962ae2590 | |
Phoenix616 | 03317c2c78 | |
Max Lee | a84cd7a2aa | |
TreyRuffy | bb7bd3415c | |
Phoenix616 | 4f8e7938e2 | |
Phoenix616 | 986a22fb73 | |
Phoenix616 | f7aa80e566 | |
Phoenix616 | d193812392 | |
Phoenix616 | 13b727c779 | |
Phoenix616 | 129663650f | |
Phoenix616 | d3cb06acc0 | |
Phoenix616 | 965d931978 | |
Phoenix616 | 1b85bda656 | |
Phoenix616 | 42a7cc4789 | |
Phoenix616 | a549b4ef51 | |
Phoenix616 | 988420992c | |
Phoenix616 | df2e4394c4 | |
Phoenix616 | 63f68d5444 | |
Phoenix616 | 6f4be10065 |
|
@ -2,5 +2,5 @@
|
|||
|
||||
github: Phoenix616
|
||||
custom: ['https://acrobot-paypal.phoenix616.dev', 'https://tip.phoenix616.dev']
|
||||
patreon: Phoenix616
|
||||
issuehunt: ChestShop-authors/ChestShop-3
|
||||
ko_fi: Phoenix616
|
||||
|
|
|
@ -1,54 +0,0 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: An error that happens in the plugin.
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### Plugin Version
|
||||
<!-- The full plugin version that you are running from /version ChestShop -->
|
||||
|
||||
|
||||
#### Plugin Config
|
||||
<!-- The full config.yml file of ChestShop. -->
|
||||
<details>
|
||||
<summary>Config</summary>
|
||||
|
||||
```yaml
|
||||
[Put the config here]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### Server Version
|
||||
<!-- The full server version that you are running from /version -->
|
||||
|
||||
|
||||
#### Server Log
|
||||
<!-- The full latest.log file, especially important if you have a stack trace -->
|
||||
<details>
|
||||
<summary>Log</summary>
|
||||
|
||||
```
|
||||
[Your log here]
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
#### What other plugins are you running?
|
||||
<!-- List of your plugins, ideally with the version -->
|
||||
|
||||
|
||||
#### What is happening?
|
||||
<!-- Explain what happens and what steps should be done to reproduce the issue. Ideally with pictures and the full error log! -->
|
||||
|
||||
|
||||
#### What did you expect to happen?
|
||||
<!-- Explain what you expected to happen after performing the previously described steps -->
|
||||
|
||||
|
||||
#### Additional context
|
||||
<!-- Add any other context or screenshots about the feature request here. -->
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
name: Bug report
|
||||
description: Report an error that happens in the plugin.
|
||||
labels: []
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
Please check if there are already similar issues open, also please test if your issue
|
||||
isn't already fixed by trying the latest development build: https://ci.minebench.de/job/ChestShop-3/
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What is happening?
|
||||
description: Explain what happens and what steps should be done to reproduce the issue. Ideally with pictures and the full error log!
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What did you expect to happen?
|
||||
description: Explain what you expected to happen after performing the previously described steps
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Plugin Version
|
||||
description: The full plugin version that you are running from `/version ChestShop`
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Plugin Config
|
||||
description: The full `config.yml` file of ChestShop.
|
||||
value: |
|
||||
<details>
|
||||
<summary>Config</summary>
|
||||
|
||||
```yaml
|
||||
[Put the config here]
|
||||
```
|
||||
|
||||
</details>
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Server Version
|
||||
description: The full server version that you are running from `/version`.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Server Log
|
||||
description: The full `latest.log` file, especially important if you have a stack trace
|
||||
value: |
|
||||
<details>
|
||||
<summary>Log</summary>
|
||||
|
||||
```
|
||||
[Your log here]
|
||||
```
|
||||
|
||||
</details>
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: What other plugins are you running?
|
||||
description: List of your plugins, ideally with the version
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Agreements
|
||||
description: Please agree to the following.
|
||||
options:
|
||||
- label: I have checked if there are already similar issues open.
|
||||
- label: I am running the latest development version available from https://ci.minebench.de/job/ChestShop-3/.
|
||||
- label: The version [has support](https://github.com/ChestShop-authors/ChestShop-3/security/policy#supported-versions) for this type of issue.
|
||||
- label: I have provided all requested information and agree to the terms of the [project's license](https://github.com/ChestShop-authors/ChestShop-3/blob/master/LICENSE)
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context or screenshots about the feature request here.
|
|
@ -1,24 +0,0 @@
|
|||
---
|
||||
name: Enhancement
|
||||
about: Request a feature or suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### Is your feature request related to a problem? Please describe.
|
||||
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when... -->
|
||||
|
||||
|
||||
#### Describe the solution you'd like
|
||||
<!-- A clear and concise description of what you want to happen. -->
|
||||
|
||||
|
||||
#### Describe alternatives you've considered
|
||||
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
|
||||
|
||||
|
||||
#### Additional context
|
||||
<!-- Add any other context or screenshots about the feature request here. -->
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
name: Enhancement
|
||||
description: Request a feature or suggest an idea for this project
|
||||
labels: [enhancement]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
Please check if there are already similar issues open, also please test if your request
|
||||
isn't already implemented by trying the latest development build: https://ci.minebench.de/job/ChestShop-3/
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Is your feature request related to a problem? Please describe.
|
||||
description: A clear and concise description of what the problem is. Ex. I'm always frustrated when...
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the solution you'd like
|
||||
description: A clear and concise description of what you want to happen.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe alternatives you've considered
|
||||
description: A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Agreements
|
||||
description: Please agree to the following.
|
||||
options:
|
||||
- label: I have checked if there are already similar issues open.
|
||||
required: true
|
||||
- label: I have checked that the latest build doesn't already implement the feature.
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context or screenshots about the feature request here.
|
|
@ -0,0 +1,21 @@
|
|||
name: Qodana
|
||||
on:
|
||||
workflow_dispatch:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
qodana:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: 'Qodana Scan'
|
||||
uses: JetBrains/qodana-action@v2022.3.4
|
||||
env:
|
||||
QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }}
|
||||
with:
|
||||
args: --baseline,.github/workflows/qodana/qodana.sarif.json
|
File diff suppressed because it is too large
Load Diff
|
@ -34,5 +34,7 @@ Links
|
|||
* [Forum Thread](http://forums.bukkit.org/threads/4150/)
|
||||
* [BukkitDev site](http://dev.bukkit.org/projects/chestshop/)
|
||||
* [SpigotMC site](https://www.spigotmc.org/resources/chestshop.51856/)
|
||||
* [Bug Tracker](http://dev.bukkit.org/server-mods/chestshop/tickets/?status=+)
|
||||
* [Bounties via IssueHunt](https://issuehunt.io/r/ChestShop-authors/ChestShop-3?tab=idle)
|
||||
* [Localization](https://crowdin.com/project/chestshop-3)
|
||||
* [Qodana code quality](https://qodana.cloud/projects/zxDG5/)
|
||||
* [Old bug Tracker](http://dev.bukkit.org/server-mods/chestshop/tickets/?status=+) (please use GitHub issues!)
|
||||
|
|
93
pom.xml
93
pom.xml
|
@ -6,7 +6,7 @@
|
|||
|
||||
<groupId>com.acrobot.chestshop</groupId>
|
||||
<artifactId>chestshop</artifactId>
|
||||
<version>3.12</version>
|
||||
<version>3.12.3-SNAPSHOT</version>
|
||||
<description>Chest-and-sign shop plugin for Bukkit</description>
|
||||
<name>ChestShop</name>
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
|||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>sk89q-repo</id>
|
||||
<url>http://maven.sk89q.com/repo/</url>
|
||||
<id>enginehub-repo</id>
|
||||
<url>https://maven.enginehub.org/repo/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>codemc-repo</id>
|
||||
|
@ -31,7 +31,7 @@
|
|||
</repository>
|
||||
<repository>
|
||||
<id>vault-repo</id>
|
||||
<url>http://nexus.hc.to/content/repositories/pub_releases/</url>
|
||||
<url>https://nexus.hc.to/content/repositories/pub_releases/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>minebench-repo</id>
|
||||
|
@ -41,14 +41,6 @@
|
|||
<id>local_repo</id>
|
||||
<url>file://${project.basedir}/repo/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>reserve-repo</id>
|
||||
<url>https://dl.bintray.com/theneweconomy/java/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>redprotect-repo</id>
|
||||
<url>https://raw.githubusercontent.com/FabioZumbi12/RedProtect/mvn-repo/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
|
@ -57,20 +49,28 @@
|
|||
<id>NyaaCat</id>
|
||||
<url>https://ci.nyaacat.com/maven/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>redprotect-repo</id>
|
||||
<url>https://raw.githubusercontent.com/FabioZumbi12/RedProtect/mvn-repo/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>adventure-repo</id>
|
||||
<url>https://s01.oss.sonatype.org/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.13.1</version>
|
||||
<version>4.13.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.j256.ormlite</groupId>
|
||||
<artifactId>ormlite-jdbc</artifactId>
|
||||
<version>5.1</version>
|
||||
<version>6.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -84,21 +84,21 @@
|
|||
<dependency>
|
||||
<groupId>de.themoep</groupId>
|
||||
<artifactId>minedown-adventure</artifactId>
|
||||
<version>1.7.0-SNAPSHOT</version>
|
||||
<version>1.7.2-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-platform-bukkit</artifactId>
|
||||
<version>4.0.0-SNAPSHOT</version>
|
||||
<version>4.3.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.kyori</groupId>
|
||||
<artifactId>adventure-text-serializer-gson</artifactId>
|
||||
<version>4.7.0</version>
|
||||
<version>4.14.0</version>
|
||||
<scope>compile</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -112,14 +112,14 @@
|
|||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-core</artifactId>
|
||||
<version>2.1</version>
|
||||
<version>2.17.2</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bstats</groupId>
|
||||
<artifactId>bstats-bukkit</artifactId>
|
||||
<version>1.7</version>
|
||||
<version>3.0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -157,7 +157,7 @@
|
|||
<dependency>
|
||||
<groupId>fr.xephi</groupId>
|
||||
<artifactId>authme</artifactId>
|
||||
<version>5.5.0-SNAPSHOT</version>
|
||||
<version>5.6.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
|
@ -220,6 +220,12 @@
|
|||
<artifactId>worldedit-core</artifactId>
|
||||
<version>7.0.0-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
@ -248,16 +254,22 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.github.jojodmo</groupId>
|
||||
<artifactId>ItemBridge</artifactId>
|
||||
<version>b0054538c1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>br.net.fabiozumbi12.RedProtect</groupId>
|
||||
<artifactId>RedProtect-Spigot</artifactId>
|
||||
<version>7.6.2</version>
|
||||
<version>7.7.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>br.net.fabiozumbi12.RedProtect</groupId>
|
||||
<artifactId>RedProtect-Core</artifactId>
|
||||
<version>7.6.2</version>
|
||||
<version>7.7.3</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -329,7 +341,7 @@
|
|||
<dependency>
|
||||
<groupId>net.tnemc</groupId>
|
||||
<artifactId>Reserve</artifactId>
|
||||
<version>0.1.0.10</version>
|
||||
<version>0.1.5.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -358,13 +370,14 @@
|
|||
<Distribution-Type>${buildType}</Distribution-Type>
|
||||
<Built-At>${maven.build.timestamp}</Built-At>
|
||||
<Build-Jdk>${java.runtime.version}</Build-Jdk>
|
||||
<paperweight-mappings-namespace>mojang</paperweight-mappings-namespace>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.1</version>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
|
@ -389,7 +402,6 @@
|
|||
<include>org.bstats:*</include>
|
||||
<include>net.gravitydevelopment.updater</include>
|
||||
<include>com.j256.ormlite</include>
|
||||
<include>org.apache.logging.log4j</include>
|
||||
<include>javax.persistence</include>
|
||||
</includes>
|
||||
</artifactSet>
|
||||
|
@ -449,6 +461,7 @@
|
|||
<build.number>${buildNumber}</build.number>
|
||||
<user.name>${buildType}</user.name>
|
||||
<bukkit.plugin.version>${project.version} ${buildDescription}</bukkit.plugin.version>
|
||||
<bukkit.dependency.version>1.20.5-R0.1-SNAPSHOT</bukkit.dependency.version>
|
||||
</properties>
|
||||
|
||||
<profiles>
|
||||
|
@ -456,20 +469,20 @@
|
|||
<id>default</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>!dontrundefault</name>
|
||||
<name>!testprofile</name>
|
||||
</property>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>paper-repo</id>
|
||||
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.destroystokyo.paper</groupId>
|
||||
<groupId>io.papermc.paper</groupId>
|
||||
<artifactId>paper-api</artifactId>
|
||||
<version>1.16.5-R0.1-SNAPSHOT</version>
|
||||
<version>${bukkit.dependency.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -477,6 +490,12 @@
|
|||
|
||||
<profile>
|
||||
<id>spigot</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>testprofile</name>
|
||||
<value>spigot</value>
|
||||
</property>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigotmc-repo</id>
|
||||
|
@ -487,13 +506,10 @@
|
|||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.13.2-R0.1-SNAPSHOT</version>
|
||||
<version>${bukkit.dependency.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<dontrundefault>true</dontrundefault>
|
||||
</properties>
|
||||
<build>
|
||||
<finalName>${project.name}-Spigot</finalName>
|
||||
<plugins>
|
||||
|
@ -511,10 +527,16 @@
|
|||
|
||||
<profile>
|
||||
<id>backwards</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>testprofile</name>
|
||||
<value>backwards</value>
|
||||
</property>
|
||||
</activation>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>paper-repo</id>
|
||||
<url>https://papermc.io/repo/repository/maven-public/</url>
|
||||
<url>https://repo.papermc.io/repository/maven-public/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<dependencies>
|
||||
|
@ -525,9 +547,6 @@
|
|||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<properties>
|
||||
<dontrundefault>true</dontrundefault>
|
||||
</properties>
|
||||
<build>
|
||||
<finalName>${project.name}-1.13.2</finalName>
|
||||
<plugins>
|
||||
|
|
|
@ -1,20 +1,21 @@
|
|||
package com.Acrobot.Breeze.Collection;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class SimpleCache<K, V> {
|
||||
private final LinkedHashMap<K, V> map;
|
||||
private final Map<K, V> map;
|
||||
|
||||
public SimpleCache(int cacheSize) {
|
||||
map = new LinkedHashMap<K, V>(cacheSize * 10/9, 0.7f, true) {
|
||||
map = Collections.synchronizedMap(new LinkedHashMap<K, V>(cacheSize * 10/9, 0.7f, true) {
|
||||
@Override
|
||||
protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
|
||||
return size() > cacheSize;
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public V put(K key, V value) {
|
||||
|
|
|
@ -126,7 +126,7 @@ public class Configuration {
|
|||
|
||||
return lastLine.isEmpty();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
Logger.getLogger("Configuration").log(Level.SEVERE, "Error while checking if file " + file.getName() + " ends with space", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package com.Acrobot.Breeze.Configuration;
|
||||
|
||||
import com.Acrobot.Breeze.Configuration.Annotations.ConfigurationComment;
|
||||
import com.Acrobot.Breeze.Configuration.Annotations.Parser;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -29,7 +30,7 @@ public class FieldParser {
|
|||
try {
|
||||
builder.append(field.getName()).append(": ").append(parser.parseToYAML(field.get(null)));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
Logger.getLogger("FieldParser").log(Level.SEVERE, "Error while parsing field", e);
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
package com.Acrobot.Breeze.Database;
|
||||
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
|
||||
|
@ -60,7 +64,7 @@ public class Database {
|
|||
try {
|
||||
table.create(fields);
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
Logger.getLogger("Database").log(Level.SEVERE, "Error while creating database from " + clazz.getName() + " (" + fields + ")", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ public class EntityParser {
|
|||
fields.add(convertToSQL(field));
|
||||
}
|
||||
|
||||
return fields.stream().collect(Collectors.joining(","));
|
||||
return String.join(",", fields);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package com.Acrobot.Breeze.Database;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* A class representing a Row in SQL query
|
||||
|
@ -85,21 +87,16 @@ public class Row {
|
|||
|
||||
try {
|
||||
object = clazz.newInstance();
|
||||
} catch (InstantiationException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InstantiationException | IllegalAccessException e) {
|
||||
Logger.getLogger("Row").log(Level.SEVERE, "Error while creating new instance of class " + clazz.getName() + " for row", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
for (Map.Entry<String, String> value : values.entrySet()) {
|
||||
try {
|
||||
clazz.getDeclaredField(value.getKey()).set(object, value.getValue());
|
||||
} catch (NoSuchFieldException ex) {
|
||||
ex.printStackTrace();
|
||||
} catch (IllegalAccessException ex) {
|
||||
ex.printStackTrace();
|
||||
} catch (NoSuchFieldException | IllegalAccessException ex) {
|
||||
Logger.getLogger("Row").log(Level.SEVERE, "Error while setting field " + value.getKey() + " to " + value.getValue() + " of class " + clazz.getName(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -132,7 +132,7 @@ public class Table {
|
|||
String statement;
|
||||
|
||||
if (condition == null || condition.isEmpty()) {
|
||||
String format = '\'' + row.getValues().stream().collect(Collectors.joining("', ")) + '\'';
|
||||
String format = '\'' + String.join("', ", row.getValues()) + '\'';
|
||||
statement = String.format(INSERT_VALUES, format);
|
||||
} else {
|
||||
String format = row.getKeysAndValues().entrySet().stream()
|
||||
|
|
|
@ -22,6 +22,10 @@ public class BlockUtil {
|
|||
* @return Is this block a sign?
|
||||
*/
|
||||
public static boolean isSign(Block block) {
|
||||
if (!isLoaded(block)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockData data = block.getBlockData();
|
||||
return data instanceof Sign || data instanceof WallSign;
|
||||
}
|
||||
|
@ -33,7 +37,7 @@ public class BlockUtil {
|
|||
* @return Is this block a chest?
|
||||
*/
|
||||
public static boolean isChest(Block block) {
|
||||
return block.getBlockData() instanceof org.bukkit.block.data.type.Chest;
|
||||
return BlockUtil.isLoaded(block) && block.getBlockData() instanceof org.bukkit.block.data.type.Chest;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -107,4 +111,14 @@ public class BlockUtil {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the chunk a block is in is loaded
|
||||
*
|
||||
* @param block The block to check
|
||||
* @return Whether or not the chunk is loaded
|
||||
*/
|
||||
public static boolean isLoaded(Block block) {
|
||||
return block.getWorld().isChunkLoaded(block.getX() >> 4, block.getZ() >> 4);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
package com.Acrobot.Breeze.Utils.Encoding;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* <p>Encodes and decodes to and from Base64 notation.</p>
|
||||
* <p>Homepage: <a href="http://iharder.net/base64">http://iharder.net/base64</a>.</p>
|
||||
|
@ -559,59 +563,31 @@ public class Base64 {
|
|||
throw new NullPointerException("Cannot serialize a null object.");
|
||||
} // end if: null
|
||||
|
||||
// Streams
|
||||
java.io.ByteArrayOutputStream baos = null;
|
||||
java.io.OutputStream b64os = null;
|
||||
java.util.zip.GZIPOutputStream gzos = null;
|
||||
java.io.ObjectOutputStream oos = null;
|
||||
|
||||
|
||||
try {
|
||||
// ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
|
||||
baos = new java.io.ByteArrayOutputStream();
|
||||
b64os = new Base64.OutputStream(baos, ENCODE | options);
|
||||
// ObjectOutputStream -> (GZIP) -> Base64 -> ByteArrayOutputStream
|
||||
try (java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
|
||||
java.io.OutputStream b64os = new Base64.OutputStream(baos, ENCODE | options)) {
|
||||
if ((options & GZIP) != 0) {
|
||||
// Gzip
|
||||
gzos = new java.util.zip.GZIPOutputStream(b64os);
|
||||
oos = new java.io.ObjectOutputStream(gzos);
|
||||
try (java.util.zip.GZIPOutputStream gzos = new java.util.zip.GZIPOutputStream(b64os);
|
||||
java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(gzos)){
|
||||
oos.writeObject(serializableObject);
|
||||
}
|
||||
} else {
|
||||
// Not gzipped
|
||||
oos = new java.io.ObjectOutputStream(b64os);
|
||||
try (java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(b64os)) {
|
||||
oos.writeObject(serializableObject);
|
||||
}
|
||||
}
|
||||
oos.writeObject(serializableObject);
|
||||
// Return value according to relevant encoding.
|
||||
try {
|
||||
return baos.toString(PREFERRED_ENCODING);
|
||||
} // end try
|
||||
catch (java.io.UnsupportedEncodingException uue) {
|
||||
// Fall back to some Java default
|
||||
return baos.toString();
|
||||
} // end catch
|
||||
} // end try
|
||||
catch (java.io.IOException e) {
|
||||
// Catch it and then throw it immediately so that
|
||||
// the finally{} block is called for cleanup.
|
||||
throw e;
|
||||
} // end catch
|
||||
finally {
|
||||
try {
|
||||
oos.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
gzos.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
b64os.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
baos.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} // end finally
|
||||
|
||||
// Return value according to relevant encoding.
|
||||
try {
|
||||
return new String(baos.toByteArray(), PREFERRED_ENCODING);
|
||||
} // end try
|
||||
catch (java.io.UnsupportedEncodingException uue) {
|
||||
// Fall back to some Java default
|
||||
return new String(baos.toByteArray());
|
||||
} // end catch
|
||||
|
||||
} // end encode
|
||||
|
||||
|
@ -635,7 +611,6 @@ public class Base64 {
|
|||
} catch (java.io.IOException ex) {
|
||||
assert false : ex.getMessage();
|
||||
} // end catch
|
||||
assert encoded != null;
|
||||
return encoded;
|
||||
} // end encodeBytes
|
||||
|
||||
|
@ -700,7 +675,6 @@ public class Base64 {
|
|||
} catch (java.io.IOException ex) {
|
||||
assert false : ex.getMessage();
|
||||
} // end catch
|
||||
assert encoded != null;
|
||||
return encoded;
|
||||
} // end encodeBytes
|
||||
|
||||
|
@ -810,40 +784,13 @@ public class Base64 {
|
|||
|
||||
// Compress?
|
||||
if ((options & GZIP) != 0) {
|
||||
java.io.ByteArrayOutputStream baos = null;
|
||||
java.util.zip.GZIPOutputStream gzos = null;
|
||||
Base64.OutputStream b64os = null;
|
||||
|
||||
try {
|
||||
// GZip -> Base64 -> ByteArray
|
||||
baos = new java.io.ByteArrayOutputStream();
|
||||
b64os = new Base64.OutputStream(baos, ENCODE | options);
|
||||
gzos = new java.util.zip.GZIPOutputStream(b64os);
|
||||
try (java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
|
||||
Base64.OutputStream b64os = new Base64.OutputStream(baos, ENCODE | options);
|
||||
java.util.zip.GZIPOutputStream gzos = new java.util.zip.GZIPOutputStream(b64os)) {
|
||||
|
||||
gzos.write(source, off, len);
|
||||
gzos.close();
|
||||
return baos.toByteArray();
|
||||
} // end try
|
||||
catch (java.io.IOException e) {
|
||||
// Catch it and then throw it immediately so that
|
||||
// the finally{} block is called for cleanup.
|
||||
throw e;
|
||||
} // end catch
|
||||
finally {
|
||||
try {
|
||||
gzos.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
b64os.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
baos.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} // end finally
|
||||
|
||||
return baos.toByteArray();
|
||||
} // end if: compress
|
||||
|
||||
// Else, don't compress. Better not to use streams at all then.
|
||||
|
@ -1162,20 +1109,16 @@ public class Base64 {
|
|||
// Check to see if it's gzip-compressed
|
||||
// GZIP Magic Two-Byte Number: 0x8b1f (35615)
|
||||
boolean dontGunzip = (options & DONT_GUNZIP) != 0;
|
||||
if ((bytes != null) && (bytes.length >= 4) && (!dontGunzip)) {
|
||||
if (bytes.length >= 4 && !dontGunzip) {
|
||||
|
||||
int head = (bytes[0] & 0xff) | ((bytes[1] << 8) & 0xff00);
|
||||
if (java.util.zip.GZIPInputStream.GZIP_MAGIC == head) {
|
||||
java.io.ByteArrayInputStream bais = null;
|
||||
java.util.zip.GZIPInputStream gzis = null;
|
||||
java.io.ByteArrayOutputStream baos = null;
|
||||
byte[] buffer = new byte[2048];
|
||||
int length = 0;
|
||||
|
||||
try {
|
||||
baos = new java.io.ByteArrayOutputStream();
|
||||
bais = new java.io.ByteArrayInputStream(bytes);
|
||||
gzis = new java.util.zip.GZIPInputStream(bais);
|
||||
try (java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
|
||||
java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(bytes);
|
||||
java.util.zip.GZIPInputStream gzis = new java.util.zip.GZIPInputStream(bais)) {
|
||||
|
||||
while ((length = gzis.read(buffer)) >= 0) {
|
||||
baos.write(buffer, 0, length);
|
||||
|
@ -1184,25 +1127,10 @@ public class Base64 {
|
|||
// No error? Get new bytes.
|
||||
bytes = baos.toByteArray();
|
||||
|
||||
} // end try
|
||||
catch (java.io.IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (java.io.IOException e) {
|
||||
Logger.getLogger("Base64").log(Level.SEVERE, "Unable to decode", e);
|
||||
// Just return originally-decoded bytes
|
||||
} // end catch
|
||||
finally {
|
||||
try {
|
||||
baos.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
gzis.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
bais.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} // end finally
|
||||
}
|
||||
|
||||
} // end if: gzipped
|
||||
} // end if: bytes.length >= 2
|
||||
|
@ -1252,55 +1180,30 @@ public class Base64 {
|
|||
// Decode and gunzip if necessary
|
||||
byte[] objBytes = decode(encodedObject, options);
|
||||
|
||||
java.io.ByteArrayInputStream bais = null;
|
||||
java.io.ObjectInputStream ois = null;
|
||||
Object obj = null;
|
||||
|
||||
try {
|
||||
bais = new java.io.ByteArrayInputStream(objBytes);
|
||||
try (java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(objBytes)) {
|
||||
|
||||
// If no custom class loader is provided, use Java's builtin OIS.
|
||||
if (loader == null) {
|
||||
ois = new java.io.ObjectInputStream(bais);
|
||||
try (java.io.ObjectInputStream ois = new java.io.ObjectInputStream(bais)) {
|
||||
return ois.readObject();
|
||||
} // end try
|
||||
} // end if: no loader provided
|
||||
|
||||
// Else make a customized object input stream that uses
|
||||
// the provided class loader.
|
||||
else {
|
||||
ois = new java.io.ObjectInputStream(bais) {
|
||||
try (java.io.ObjectInputStream ois = new java.io.ObjectInputStream(bais) {
|
||||
@Override
|
||||
public Class<?> resolveClass(java.io.ObjectStreamClass streamClass)
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
Class<?> c = Class.forName(streamClass.getName(), false, loader);
|
||||
if (c == null) {
|
||||
return super.resolveClass(streamClass);
|
||||
} else {
|
||||
return c; // Class loader knows of this class.
|
||||
} // end else: not null
|
||||
return Class.forName(streamClass.getName(), false, loader);
|
||||
} // end resolveClass
|
||||
}; // end ois
|
||||
}) { // end ois
|
||||
return ois.readObject();
|
||||
} // end try
|
||||
} // end else: no custom class loader
|
||||
|
||||
obj = ois.readObject();
|
||||
} // end try
|
||||
catch (java.io.IOException e) {
|
||||
throw e; // Catch and throw in order to execute finally{}
|
||||
} // end catch
|
||||
catch (java.lang.ClassNotFoundException e) {
|
||||
throw e; // Catch and throw in order to execute finally{}
|
||||
} // end catch
|
||||
finally {
|
||||
try {
|
||||
bais.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
try {
|
||||
ois.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} // end finally
|
||||
|
||||
return obj;
|
||||
} // end decodeObject
|
||||
|
||||
|
||||
|
@ -1325,17 +1228,10 @@ public class Base64 {
|
|||
throw new NullPointerException("Data to encode was null.");
|
||||
} // end iff
|
||||
|
||||
Base64.OutputStream bos = null;
|
||||
try {
|
||||
bos = new Base64.OutputStream(
|
||||
new java.io.FileOutputStream(filename), Base64.ENCODE);
|
||||
try (OutputStream bos = new OutputStream(
|
||||
new java.io.FileOutputStream(filename), Base64.ENCODE)) {
|
||||
bos.write(dataToEncode);
|
||||
} finally {
|
||||
try {
|
||||
bos.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} // end finally
|
||||
}
|
||||
|
||||
} // end encodeToFile
|
||||
|
||||
|
@ -1356,21 +1252,10 @@ public class Base64 {
|
|||
public static void decodeToFile(String dataToDecode, String filename)
|
||||
throws java.io.IOException {
|
||||
|
||||
Base64.OutputStream bos = null;
|
||||
try {
|
||||
bos = new Base64.OutputStream(
|
||||
new java.io.FileOutputStream(filename), Base64.DECODE);
|
||||
try (OutputStream bos = new OutputStream(
|
||||
new java.io.FileOutputStream(filename), Base64.DECODE)) {
|
||||
bos.write(dataToDecode.getBytes(PREFERRED_ENCODING));
|
||||
} // end try
|
||||
catch (java.io.IOException e) {
|
||||
throw e; // Catch and throw to execute finally{} block
|
||||
} // end catch: java.io.IOException
|
||||
finally {
|
||||
try {
|
||||
bos.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} // end finally
|
||||
}
|
||||
|
||||
} // end decodeToFile
|
||||
|
||||
|
@ -1393,24 +1278,22 @@ public class Base64 {
|
|||
throws java.io.IOException {
|
||||
|
||||
byte[] decodedData = null;
|
||||
Base64.InputStream bis = null;
|
||||
try {
|
||||
// Set up some useful variables
|
||||
java.io.File file = new java.io.File(filename);
|
||||
byte[] buffer = null;
|
||||
int length = 0;
|
||||
int numBytes = 0;
|
||||
// Set up some useful variables
|
||||
java.io.File file = new java.io.File(filename);
|
||||
byte[] buffer = null;
|
||||
int length = 0;
|
||||
int numBytes = 0;
|
||||
|
||||
// Check for size of file
|
||||
if (file.length() > Integer.MAX_VALUE) {
|
||||
throw new java.io.IOException("File is too big for this convenience method (" + file.length() + " bytes).");
|
||||
} // end if: file too big for int index
|
||||
buffer = new byte[(int) file.length()];
|
||||
// Check for size of file
|
||||
if (file.length() > Integer.MAX_VALUE) {
|
||||
throw new java.io.IOException("File is too big for this convenience method (" + file.length() + " bytes).");
|
||||
} // end if: file too big for int index
|
||||
buffer = new byte[(int) file.length()];
|
||||
|
||||
// Open a stream
|
||||
bis = new Base64.InputStream(
|
||||
new java.io.BufferedInputStream(
|
||||
new java.io.FileInputStream(file)), Base64.DECODE);
|
||||
// Open a stream
|
||||
try (Base64.InputStream bis = new Base64.InputStream(
|
||||
new java.io.BufferedInputStream(
|
||||
new java.io.FileInputStream(file)), Base64.DECODE)) {
|
||||
|
||||
// Read until done
|
||||
while ((numBytes = bis.read(buffer, length, 4096)) >= 0) {
|
||||
|
@ -1420,17 +1303,7 @@ public class Base64 {
|
|||
// Save in a variable to return
|
||||
decodedData = new byte[length];
|
||||
System.arraycopy(buffer, 0, decodedData, 0, length);
|
||||
|
||||
} // end try
|
||||
catch (java.io.IOException e) {
|
||||
throw e; // Catch and release to execute finally{}
|
||||
} // end catch: java.io.IOException
|
||||
finally {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} // end finally
|
||||
} // end try
|
||||
|
||||
return decodedData;
|
||||
} // end decodeFromFile
|
||||
|
@ -1454,18 +1327,16 @@ public class Base64 {
|
|||
throws java.io.IOException {
|
||||
|
||||
String encodedData = null;
|
||||
Base64.InputStream bis = null;
|
||||
try {
|
||||
// Set up some useful variables
|
||||
java.io.File file = new java.io.File(filename);
|
||||
byte[] buffer = new byte[Math.max((int) (file.length() * 1.4 + 1), 40)]; // Need max() for math on small files (v2.2.1); Need +1 for a few corner cases (v2.3.5)
|
||||
int length = 0;
|
||||
int numBytes = 0;
|
||||
// Set up some useful variables
|
||||
java.io.File file = new java.io.File(filename);
|
||||
byte[] buffer = new byte[Math.max((int) (file.length() * 1.4 + 1), 40)]; // Need max() for math on small files (v2.2.1); Need +1 for a few corner cases (v2.3.5)
|
||||
int length = 0;
|
||||
int numBytes = 0;
|
||||
|
||||
// Open a stream
|
||||
bis = new Base64.InputStream(
|
||||
// Open a stream
|
||||
try (Base64.InputStream bis = new Base64.InputStream(
|
||||
new java.io.BufferedInputStream(
|
||||
new java.io.FileInputStream(file)), Base64.ENCODE);
|
||||
new java.io.FileInputStream(file)), Base64.ENCODE)) {
|
||||
|
||||
// Read until done
|
||||
while ((numBytes = bis.read(buffer, length, 4096)) >= 0) {
|
||||
|
@ -1476,15 +1347,6 @@ public class Base64 {
|
|||
encodedData = new String(buffer, 0, length, Base64.PREFERRED_ENCODING);
|
||||
|
||||
} // end try
|
||||
catch (java.io.IOException e) {
|
||||
throw e; // Catch and release to execute finally{}
|
||||
} // end catch: java.io.IOException
|
||||
finally {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
} // end finally
|
||||
|
||||
return encodedData;
|
||||
} // end encodeFromFile
|
||||
|
@ -1501,21 +1363,10 @@ public class Base64 {
|
|||
throws java.io.IOException {
|
||||
|
||||
String encoded = Base64.encodeFromFile(infile);
|
||||
java.io.OutputStream out = null;
|
||||
try {
|
||||
out = new java.io.BufferedOutputStream(
|
||||
new java.io.FileOutputStream(outfile));
|
||||
out.write(encoded.getBytes("US-ASCII")); // Strict, 7-bit output.
|
||||
} // end try
|
||||
catch (java.io.IOException e) {
|
||||
throw e; // Catch and release to execute finally{}
|
||||
} // end catch
|
||||
finally {
|
||||
try {
|
||||
out.close();
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
} // end finally
|
||||
try (java.io.OutputStream out = new java.io.BufferedOutputStream(
|
||||
new java.io.FileOutputStream(outfile))) {
|
||||
out.write(encoded.getBytes(StandardCharsets.US_ASCII)); // Strict, 7-bit output.
|
||||
}
|
||||
} // end encodeFileToFile
|
||||
|
||||
|
||||
|
@ -1531,21 +1382,10 @@ public class Base64 {
|
|||
throws java.io.IOException {
|
||||
|
||||
byte[] decoded = Base64.decodeFromFile(infile);
|
||||
java.io.OutputStream out = null;
|
||||
try {
|
||||
out = new java.io.BufferedOutputStream(
|
||||
new java.io.FileOutputStream(outfile));
|
||||
try (java.io.OutputStream out = new java.io.BufferedOutputStream(
|
||||
new java.io.FileOutputStream(outfile))) {
|
||||
out.write(decoded);
|
||||
} // end try
|
||||
catch (java.io.IOException e) {
|
||||
throw e; // Catch and release to execute finally{}
|
||||
} // end catch
|
||||
finally {
|
||||
try {
|
||||
out.close();
|
||||
} catch (Exception ex) {
|
||||
}
|
||||
} // end finally
|
||||
}
|
||||
} // end decodeFileToFile
|
||||
|
||||
|
||||
|
|
|
@ -351,7 +351,7 @@ public class InventoryUtil {
|
|||
itemList.add(item.clone());
|
||||
}
|
||||
|
||||
return itemList.toArray(new ItemStack[itemList.size()]);
|
||||
return itemList.toArray(new ItemStack[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -413,7 +413,7 @@ public class InventoryUtil {
|
|||
stackedItems.add(item.clone());
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < Math.floor(item.getAmount() / maxStackSize); i++) {
|
||||
for (int i = 0; i < Math.floor((double) item.getAmount() / maxStackSize); i++) {
|
||||
ItemStack itemClone = item.clone();
|
||||
itemClone.setAmount(maxStackSize);
|
||||
stackedItems.add(itemClone);
|
||||
|
@ -424,6 +424,6 @@ public class InventoryUtil {
|
|||
stackedItems.add(rest);
|
||||
}
|
||||
}
|
||||
return stackedItems.toArray(new ItemStack[stackedItems.size()]);
|
||||
return stackedItems.toArray(new ItemStack[0]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ import org.yaml.snakeyaml.Yaml;
|
|||
import org.yaml.snakeyaml.nodes.Tag;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
@ -54,6 +53,23 @@ public class MaterialUtil {
|
|||
// 15 dashes fit on one sign line with the default resource pack:
|
||||
public static final int MAXIMUM_SIGN_WIDTH = (short) getMinecraftStringWidth("---------------");
|
||||
|
||||
private static final Map<String, String> ABBREVIATIONS = StringUtil.map(
|
||||
"Egg", "Eg",
|
||||
"Spawn", "Spaw",
|
||||
"Pottery", "Pot",
|
||||
"Heartbreak", "Heartbr",
|
||||
"Sherd", "Sher"
|
||||
);
|
||||
|
||||
private static final Map<String, String> UNIDIRECTIONAL_ABBREVIATIONS = StringUtil.map(
|
||||
"Endermite", "Endmite",
|
||||
"Endmite", "Endmit",
|
||||
"Wayfinder", "Wayfndr",
|
||||
"Wayfndr", "Wf",
|
||||
"Heartbr", "Hrtbr",
|
||||
"Hrtbr", "Hrtb"
|
||||
);
|
||||
|
||||
private static final SimpleCache<String, Material> MATERIAL_CACHE = new SimpleCache<>(Properties.CACHE_SIZE);
|
||||
|
||||
private static final Yaml YAML = new Yaml(new YamlBukkitConstructor(), new YamlRepresenter(), new DumperOptions());
|
||||
|
@ -146,7 +162,15 @@ public class MaterialUtil {
|
|||
* @return Material found
|
||||
*/
|
||||
public static Material getMaterial(String name) {
|
||||
String formatted = name.replaceAll("(?<!^)([A-Z1-9])", "_$1").replace(' ', '_').toUpperCase(Locale.ROOT);
|
||||
String replacedName = name;
|
||||
// revert unidirectional abbreviations
|
||||
List<Map.Entry<String, String>> abbreviations = new ArrayList<>(UNIDIRECTIONAL_ABBREVIATIONS.entrySet());
|
||||
for (int i = abbreviations.size() - 1; i >= 0; i--) {
|
||||
Map.Entry<String, String> entry = abbreviations.get(i);
|
||||
replacedName = replacedName.replaceAll(entry.getValue() + "(_|$)?", entry.getKey() + "$1");
|
||||
}
|
||||
|
||||
String formatted = name.replaceAll("(?<!^)(?>\\s?)([A-Z1-9])", "_$1").replace(' ', '_').toUpperCase(Locale.ROOT);
|
||||
|
||||
Material material = MATERIAL_CACHE.get(formatted);
|
||||
if (material != null) {
|
||||
|
@ -160,7 +184,7 @@ public class MaterialUtil {
|
|||
return material;
|
||||
}
|
||||
|
||||
material = new EnumParser<Material>().parse(name, Material.values());
|
||||
material = new EnumParser<Material>().parse(replacedName, Material.values());
|
||||
if (material != null) {
|
||||
MATERIAL_CACHE.put(formatted, material);
|
||||
}
|
||||
|
@ -264,17 +288,42 @@ public class MaterialUtil {
|
|||
* @return The name shortened to the max length
|
||||
*/
|
||||
public static String getShortenedName(String itemName, int maxWidth) {
|
||||
itemName = StringUtil.capitalizeFirstLetter(itemName.replace('_', ' '), ' ');
|
||||
int width = getMinecraftStringWidth(itemName);
|
||||
// Restore spaces in string that might be already be shortened
|
||||
String name = itemName.replaceAll("([a-z])([A-Z1-9])", "$1 $2");
|
||||
name = StringUtil.capitalizeFirstLetter(name.replace('_', ' '), ' ');
|
||||
int width = getMinecraftStringWidth(name);
|
||||
if (width <= maxWidth) {
|
||||
return itemName;
|
||||
return name;
|
||||
}
|
||||
String[] itemParts = itemName.split("[ \\-]");
|
||||
itemName = String.join("", itemParts);
|
||||
width = getMinecraftStringWidth(itemName);
|
||||
String[] itemParts = name.split("[ \\-]");
|
||||
String noSpaceName = String.join("", itemParts);
|
||||
width = getMinecraftStringWidth(noSpaceName);
|
||||
if (width <= maxWidth) {
|
||||
return itemName;
|
||||
return noSpaceName;
|
||||
}
|
||||
|
||||
// Abbreviate some terms manually
|
||||
for (Map.Entry<String, String> entry : ABBREVIATIONS.entrySet()) {
|
||||
name = name.replaceAll(entry.getKey() + "( |$)", entry.getValue() + "$1");
|
||||
itemParts = name.split("[ \\-]");
|
||||
noSpaceName = String.join("", itemParts);
|
||||
width = getMinecraftStringWidth(noSpaceName);
|
||||
if (width <= maxWidth) {
|
||||
return noSpaceName;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply unidirectional abbreviations if it still doesn't work
|
||||
for (Map.Entry<String, String> entry : UNIDIRECTIONAL_ABBREVIATIONS.entrySet()) {
|
||||
name = name.replaceAll(entry.getKey() + "( |$)", entry.getValue() + "$1");
|
||||
itemParts = name.split("[ \\-]");
|
||||
noSpaceName = String.join("", itemParts);
|
||||
width = getMinecraftStringWidth(noSpaceName);
|
||||
if (width <= maxWidth) {
|
||||
return noSpaceName;
|
||||
}
|
||||
}
|
||||
|
||||
int exceeding = width - maxWidth;
|
||||
int shortestIndex = 0;
|
||||
int longestIndex = 0;
|
||||
|
@ -402,17 +451,18 @@ public class MaterialUtil {
|
|||
|
||||
private static class EnumParser<E extends Enum<E>> {
|
||||
private E parse(String name, E[] values) {
|
||||
String formatted = name.replaceAll("(?<!^)(?>\\s?)([A-Z1-9])", "_$1").toUpperCase(Locale.ROOT).replace(' ', '_');
|
||||
try {
|
||||
return E.valueOf(values[0].getDeclaringClass(), name.toUpperCase(Locale.ROOT));
|
||||
return E.valueOf(values[0].getDeclaringClass(), formatted);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
E currentEnum = null;
|
||||
String[] typeParts = name.replaceAll("(?<!^)([A-Z1-9])", "_$1").toUpperCase(Locale.ROOT).split("[ _]");
|
||||
List<E> possibleEnums = new ArrayList<>();
|
||||
String[] typeParts = formatted.split("_");
|
||||
int length = Short.MAX_VALUE;
|
||||
for (E e : values) {
|
||||
String enumName = e.name();
|
||||
if (enumName.length() < length && enumName.startsWith(name)) {
|
||||
length = (short) enumName.length();
|
||||
currentEnum = e;
|
||||
if (enumName.length() < length && enumName.startsWith(formatted)) {
|
||||
length = enumName.length();
|
||||
possibleEnums.add(e);
|
||||
} else if (typeParts.length > 1) {
|
||||
String[] nameParts = enumName.split("_");
|
||||
if (typeParts.length == nameParts.length) {
|
||||
|
@ -424,13 +474,28 @@ public class MaterialUtil {
|
|||
}
|
||||
}
|
||||
if (matched) {
|
||||
currentEnum = e;
|
||||
break;
|
||||
possibleEnums.add(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return currentEnum;
|
||||
|
||||
if (possibleEnums.size() == 1) {
|
||||
return possibleEnums.get(0);
|
||||
} else if (possibleEnums.size() > 1) {
|
||||
int formattedLength = formatted.length();
|
||||
int closestDeviation = Short.MAX_VALUE;
|
||||
E closestEnum = null;
|
||||
for (E possibleEnum : possibleEnums) {
|
||||
int deviation = possibleEnum.name().length() - formattedLength;
|
||||
if (deviation < closestDeviation) {
|
||||
closestDeviation = deviation;
|
||||
closestEnum = possibleEnum;
|
||||
}
|
||||
}
|
||||
return closestEnum;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ import java.util.regex.Pattern;
|
|||
* @author bricefrisco
|
||||
*/
|
||||
public class QuantityUtil {
|
||||
private static final Pattern QUANTITY_LINE_WITH_COUNTER_PATTERN = Pattern.compile("^Q [1-9][0-9]{0,4} : C [0-9]{0,5}$");
|
||||
public static final Pattern QUANTITY_LINE_WITH_COUNTER_PATTERN = Pattern.compile("^Q [1-9][0-9]{0,4} : C [0-9]{1,5}$");
|
||||
|
||||
public static int parseQuantity(String quantityLine) throws IllegalArgumentException {
|
||||
if (quantityLineContainsCounter(quantityLine)) {
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package com.Acrobot.Breeze.Utils;
|
||||
|
||||
import org.apache.commons.lang.WordUtils;
|
||||
import org.bukkit.ChatColor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -22,9 +25,13 @@ public class StringUtil {
|
|||
if (string == null || string.isEmpty()) {
|
||||
return string;
|
||||
}
|
||||
char[] separators = new char[]{separator};
|
||||
|
||||
return WordUtils.capitalize(string.toLowerCase(Locale.ROOT), separators).replace(String.valueOf(separator), " ");
|
||||
// Split into words
|
||||
String[] words = string.toLowerCase(Locale.ROOT).split(String.valueOf(separator));
|
||||
// Capitalize every word and return joined string
|
||||
return Arrays.stream(words)
|
||||
.map(word -> word.substring(0, 1).toUpperCase(Locale.ROOT) + word.substring(1))
|
||||
.collect(Collectors.joining(" "));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -116,4 +123,52 @@ public class StringUtil {
|
|||
}
|
||||
return width;
|
||||
}
|
||||
|
||||
/**
|
||||
* Strip whitespace from the front and back
|
||||
* @param string The string to strip
|
||||
* @return The string with all whitespace from front and back stripped; returns null if input is null
|
||||
*/
|
||||
public static String strip(String string) {
|
||||
if (string == null)
|
||||
return null;
|
||||
// The result stripped string
|
||||
StringBuilder stripped = new StringBuilder();
|
||||
// The current white space which only gets added once we find a non-whitespace character
|
||||
StringBuilder cachedWhitespace = new StringBuilder();
|
||||
// Check each code point (not characters to support UTF16 properly)
|
||||
for (int codePoint : string.codePoints().toArray()) {
|
||||
// Check if it's a whitespace, so we know if we should add it
|
||||
if (!Character.isWhitespace(codePoint)) {
|
||||
// Check if we have cached whitespace, if so append it first and reset the cache
|
||||
if (cachedWhitespace.length() > 0) {
|
||||
stripped.append(cachedWhitespace);
|
||||
cachedWhitespace = new StringBuilder();
|
||||
}
|
||||
// Append current code point
|
||||
stripped.appendCodePoint(codePoint);
|
||||
} else if (stripped.length() > 0) {
|
||||
// If we already have some non-whitespace content in the final stripped
|
||||
// then cache the current whitespace as it wasn't at the start
|
||||
cachedWhitespace.appendCodePoint(codePoint);
|
||||
} // Otherwise, this was the start, and we don't need the cached whitespace
|
||||
}
|
||||
// Return the stripped string, without any whitespace from the end left
|
||||
return stripped.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a map from strings
|
||||
* @param values The values to add
|
||||
* @return The map
|
||||
*/
|
||||
public static Map<String, String> map(String... values) {
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
|
||||
for (int i = 0; i + 1 < values.length; i+=2) {
|
||||
map.put(values[i], values[i + 1]);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -66,6 +66,12 @@ import org.apache.logging.log4j.core.filter.AbstractFilter;
|
|||
import org.apache.logging.log4j.message.Message;
|
||||
|
||||
import org.bstats.bukkit.Metrics;
|
||||
import org.bstats.charts.AdvancedBarChart;
|
||||
import org.bstats.charts.DrilldownPie;
|
||||
import org.bstats.charts.MultiLineChart;
|
||||
import org.bstats.charts.SimpleBarChart;
|
||||
import org.bstats.charts.SimplePie;
|
||||
import org.bstats.charts.SingleLineChart;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Server;
|
||||
|
@ -83,8 +89,12 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.logging.FileHandler;
|
||||
import java.util.logging.Logger;
|
||||
|
@ -99,6 +109,9 @@ public class ChestShop extends JavaPlugin {
|
|||
private static ChestShop plugin;
|
||||
private static Server server;
|
||||
private static PluginDescriptionFile description;
|
||||
private static final ExecutorService executorService = Executors.newCachedThreadPool();
|
||||
|
||||
private static Metrics bStats;
|
||||
|
||||
private static BukkitAudiences audiences;
|
||||
|
||||
|
@ -106,6 +119,7 @@ public class ChestShop extends JavaPlugin {
|
|||
private static ItemDatabase itemDatabase;
|
||||
|
||||
private static Logger logger;
|
||||
private static Logger shopLogger;
|
||||
private FileHandler handler;
|
||||
|
||||
private List<PluginCommand> commands = new ArrayList<>();
|
||||
|
@ -113,6 +127,8 @@ public class ChestShop extends JavaPlugin {
|
|||
public ChestShop() {
|
||||
dataFolder = getDataFolder();
|
||||
logger = getLogger();
|
||||
shopLogger = Logger.getLogger("ChestShop Shops");
|
||||
shopLogger.setParent(logger);
|
||||
description = getDescription();
|
||||
server = getServer();
|
||||
plugin = this;
|
||||
|
@ -125,6 +141,7 @@ public class ChestShop extends JavaPlugin {
|
|||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
bStats = new Metrics(this, 1109);
|
||||
audiences = BukkitAudiences.create(this);
|
||||
turnOffDatabaseLogging();
|
||||
if (!handleMigrations()) {
|
||||
|
@ -152,20 +169,6 @@ public class ChestShop extends JavaPlugin {
|
|||
|
||||
registerPluginMessagingChannels();
|
||||
|
||||
if (Properties.LOG_TO_FILE) {
|
||||
File log = loadFile("ChestShop.log");
|
||||
|
||||
FileHandler handler = loadHandler(log.getAbsolutePath());
|
||||
handler.setFormatter(new FileFormatter());
|
||||
|
||||
this.handler = handler;
|
||||
logger.addHandler(handler);
|
||||
}
|
||||
|
||||
if (!Properties.LOG_TO_CONSOLE) {
|
||||
logger.setUseParentHandlers(false);
|
||||
}
|
||||
|
||||
startStatistics();
|
||||
startBuildNotificatier();
|
||||
startUpdater();
|
||||
|
@ -173,9 +176,11 @@ public class ChestShop extends JavaPlugin {
|
|||
|
||||
private void registerCommand(String name, CommandExecutor executor, Permission permission) {
|
||||
PluginCommand command = getCommand(name);
|
||||
command.setExecutor(executor);
|
||||
command.setPermission(permission.toString());
|
||||
commands.add(command);
|
||||
if (command != null) {
|
||||
command.setExecutor(executor);
|
||||
command.setPermission(permission.toString());
|
||||
commands.add(command);
|
||||
}
|
||||
}
|
||||
|
||||
public void loadConfig() {
|
||||
|
@ -186,6 +191,22 @@ public class ChestShop extends JavaPlugin {
|
|||
NameManager.load();
|
||||
|
||||
commands.forEach(c -> c.setPermissionMessage(Messages.ACCESS_DENIED.getTextWithPrefix(null)));
|
||||
|
||||
if (handler != null) {
|
||||
shopLogger.removeHandler(handler);
|
||||
}
|
||||
|
||||
if (Properties.LOG_TO_FILE) {
|
||||
if (handler == null) {
|
||||
File log = loadFile("ChestShop.log");
|
||||
|
||||
handler = loadHandler(log.getAbsolutePath());
|
||||
handler.setFormatter(new FileFormatter());
|
||||
}
|
||||
shopLogger.addHandler(handler);
|
||||
}
|
||||
|
||||
shopLogger.setUseParentHandlers(Properties.LOG_TO_CONSOLE);
|
||||
}
|
||||
|
||||
private void turnOffDatabaseLogging() {
|
||||
|
@ -238,7 +259,7 @@ public class ChestShop extends JavaPlugin {
|
|||
try {
|
||||
previousVersion.save(versionFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
getLogger().log(java.util.logging.Level.SEVERE, "Unable to save new database version " + Migrations.CURRENT_DATABASE_VERSION, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,7 +276,7 @@ public class ChestShop extends JavaPlugin {
|
|||
try {
|
||||
previousVersion.save(versionFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
getLogger().log(java.util.logging.Level.SEVERE, "Unable to save new database version " + newVersion, e);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -276,7 +297,7 @@ public class ChestShop extends JavaPlugin {
|
|||
|
||||
file.createNewFile();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
getBukkitLogger().log(java.util.logging.Level.SEVERE, "Unable to load file " + file.getName(), e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,14 +310,17 @@ public class ChestShop extends JavaPlugin {
|
|||
try {
|
||||
handler = new FileHandler(path, true);
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
getBukkitLogger().log(java.util.logging.Level.SEVERE, "Unable to load handler " + path, ex);
|
||||
}
|
||||
|
||||
return handler;
|
||||
}
|
||||
|
||||
public void onDisable() {
|
||||
getServer().getScheduler().cancelTasks(this);
|
||||
executorService.shutdown();
|
||||
try {
|
||||
executorService.awaitTermination(15, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException ignored) {}
|
||||
|
||||
Toggle.clearToggledPlayers();
|
||||
|
||||
|
@ -430,16 +454,21 @@ public class ChestShop extends JavaPlugin {
|
|||
}
|
||||
|
||||
private void startStatistics() {
|
||||
Metrics bStats = new Metrics(this, 1109);
|
||||
try {
|
||||
String dist = new JarFile(this.getFile()).getManifest().getMainAttributes().getValue("Distribution-Type");
|
||||
bStats.addCustomChart(new Metrics.SimplePie("distributionType", () -> dist));
|
||||
try (JarFile jarFile = new JarFile(this.getFile())) {
|
||||
String dist = jarFile.getManifest().getMainAttributes().getValue("Distribution-Type");
|
||||
bStats.addCustomChart(new SimplePie("distributionType", () -> dist));
|
||||
} catch (IOException ignored) {}
|
||||
|
||||
String serverVersion = getServer().getBukkitVersion().split("-")[0];
|
||||
bStats.addCustomChart(createStaticDrilldownStat("versionMcSelf", serverVersion, getDescription().getVersion()));
|
||||
bStats.addCustomChart(createStaticDrilldownStat("versionSelfMc", getDescription().getVersion(), serverVersion));
|
||||
|
||||
bStats.addCustomChart(createStaticDrilldownStat("serverTypeVersionSelf", getServer().getName(), getDescription().getVersion()));
|
||||
bStats.addCustomChart(createStaticDrilldownStat("versionSelfServerType", getDescription().getVersion(), getServer().getName()));
|
||||
|
||||
bStats.addCustomChart(createStaticDrilldownStat("versionMcServerType", serverVersion, getServer().getName()));
|
||||
bStats.addCustomChart(createStaticDrilldownStat("serverTypeVersionMc", getServer().getName(), serverVersion));
|
||||
|
||||
String javaVersion = System.getProperty("java.version");
|
||||
bStats.addCustomChart(createStaticDrilldownStat("versionJavaSelf", javaVersion, getDescription().getVersion()));
|
||||
bStats.addCustomChart(createStaticDrilldownStat("versionSelfJava", getDescription().getVersion(), javaVersion));
|
||||
|
@ -447,28 +476,43 @@ public class ChestShop extends JavaPlugin {
|
|||
bStats.addCustomChart(createStaticDrilldownStat("versionJavaMc", javaVersion, serverVersion));
|
||||
bStats.addCustomChart(createStaticDrilldownStat("versionMcJava", serverVersion, javaVersion));
|
||||
|
||||
bStats.addCustomChart(new Metrics.SingleLineChart("shopAccounts", NameManager::getAccountCount));
|
||||
bStats.addCustomChart(new Metrics.MultiLineChart("transactionCount", () -> ImmutableMap.of(
|
||||
bStats.addCustomChart(new SingleLineChart("shopAccounts", NameManager::getAccountCount));
|
||||
bStats.addCustomChart(new MultiLineChart("transactionCount", () -> ImmutableMap.of(
|
||||
"total", MetricsModule.getTotalTransactions(),
|
||||
"buy", MetricsModule.getBuyTransactions(),
|
||||
"sell", MetricsModule.getSellTransactions()
|
||||
)));
|
||||
bStats.addCustomChart(new Metrics.MultiLineChart("itemCount", () -> ImmutableMap.of(
|
||||
bStats.addCustomChart(new MultiLineChart("itemCount", () -> ImmutableMap.of(
|
||||
"total", MetricsModule.getTotalItemsCount(),
|
||||
"buy", MetricsModule.getSoldItemsCount(),
|
||||
"sell", MetricsModule.getBoughtItemsCount()
|
||||
)));
|
||||
|
||||
bStats.addCustomChart(new Metrics.SimplePie("includeSettingsInMetrics", () -> Properties.INCLUDE_SETTINGS_IN_METRICS ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("includeSettingsInMetrics", () -> Properties.INCLUDE_SETTINGS_IN_METRICS ? "enabled" : "disabled"));
|
||||
if (!Properties.INCLUDE_SETTINGS_IN_METRICS) return;
|
||||
|
||||
bStats.addCustomChart(new Metrics.AdvancedBarChart("pluginProperties", () -> {
|
||||
bStats.addCustomChart(new SimplePie("ensure-correct-playerid", () -> Properties.ENSURE_CORRECT_PLAYERID ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("allow-sign-chest-open", () -> Properties.ALLOW_SIGN_CHEST_OPEN ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("uses-server-economy-account", () -> !Properties.SERVER_ECONOMY_ACCOUNT.isEmpty() ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("uses-server-economy-account-uuid", () -> !Properties.SERVER_ECONOMY_ACCOUNT_UUID.equals(new UUID(0, 0)) ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("allow-partial-transactions", () -> Properties.ALLOW_PARTIAL_TRANSACTIONS ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("bungeecord-messages", () -> Properties.BUNGEECORD_MESSAGES ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("allow-multiple-shops-at-one-block", () -> Properties.ALLOW_MULTIPLE_SHOPS_AT_ONE_BLOCK ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("allow-partial-transactions", () -> Properties.ALLOW_PARTIAL_TRANSACTIONS ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("log-to-console", () -> Properties.LOG_TO_CONSOLE ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("log-to-file", () -> Properties.LOG_TO_FILE ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("auto-update", () -> !Properties.TURN_OFF_UPDATES ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("release-notifications", () -> !Properties.TURN_OFF_UPDATE_NOTIFIER ? "enabled" : "disabled"));
|
||||
bStats.addCustomChart(new SimplePie("dev-build-notifications", () -> !Properties.TURN_OFF_DEV_UPDATE_NOTIFIER ? "enabled" : "disabled"));
|
||||
|
||||
bStats.addCustomChart(new AdvancedBarChart("pluginProperties", () -> {
|
||||
Map<String, int[]> map = new LinkedHashMap<>();
|
||||
map.put("ensure-correct-playerid", getChartArray(Properties.ENSURE_CORRECT_PLAYERID));
|
||||
map.put("reverse-buttons", getChartArray(Properties.REVERSE_BUTTONS));
|
||||
map.put("shift-sells-in-stacks", getChartArray(Properties.SHIFT_SELLS_IN_STACKS));
|
||||
map.put("shift-sells-everything", getChartArray(Properties.SHIFT_SELLS_EVERYTHING));
|
||||
map.put("allow-sign-chest-open", getChartArray(!Properties.ALLOW_SIGN_CHEST_OPEN));
|
||||
map.put("sign-dying", getChartArray(!Properties.SIGN_DYING));
|
||||
map.put("remove-empty-shops", getChartArray(!Properties.REMOVE_EMPTY_SHOPS));
|
||||
map.put("remove-empty-chests", getChartArray(!Properties.REMOVE_EMPTY_CHESTS));
|
||||
map.put("uses-server-economy-account", getChartArray(!Properties.SERVER_ECONOMY_ACCOUNT.isEmpty()));
|
||||
|
@ -478,15 +522,18 @@ public class ChestShop extends JavaPlugin {
|
|||
map.put("bungeecord-messages", getChartArray(Properties.BUNGEECORD_MESSAGES));
|
||||
map.put("log-to-console", getChartArray(Properties.LOG_TO_CONSOLE));
|
||||
map.put("log-to-file", getChartArray(Properties.LOG_TO_FILE));
|
||||
map.put("auto-update", getChartArray(!Properties.TURN_OFF_UPDATES));
|
||||
map.put("release-notifications", getChartArray(!Properties.TURN_OFF_UPDATE_NOTIFIER));
|
||||
map.put("dev-build-notifications", getChartArray(!Properties.TURN_OFF_DEV_UPDATE_NOTIFIER));
|
||||
return map;
|
||||
}));
|
||||
bStats.addCustomChart(new Metrics.SimpleBarChart("shopContainers",
|
||||
bStats.addCustomChart(new SimpleBarChart("shopContainers",
|
||||
() -> Properties.SHOP_CONTAINERS.stream().map(Material::name).collect(Collectors.toMap(k -> k, k -> 1))));
|
||||
}
|
||||
|
||||
private Metrics.DrilldownPie createStaticDrilldownStat(String statId, String value1, String value2) {
|
||||
public static DrilldownPie createStaticDrilldownStat(String statId, String value1, String value2) {
|
||||
final Map<String, Map<String, Integer>> map = ImmutableMap.of(value1, ImmutableMap.of(value2, 1));
|
||||
return new Metrics.DrilldownPie(statId, () -> map);
|
||||
return new DrilldownPie(statId, () -> map);
|
||||
}
|
||||
|
||||
private int[] getChartArray(boolean value) {
|
||||
|
@ -498,10 +545,18 @@ public class ChestShop extends JavaPlugin {
|
|||
private void startUpdater() {
|
||||
if (Properties.TURN_OFF_UPDATES) {
|
||||
getLogger().info("Auto-updater is disabled. If you want the plugin to automatically download new releases then set 'TURN_OFF_UPDATES' to 'false' in your config.yml!");
|
||||
if (!Properties.TURN_OFF_UPDATE_NOTIFIER) {
|
||||
final Updater updater = new Updater(this, getPluginName().toLowerCase(Locale.ROOT), this.getFile(), Updater.UpdateType.NO_DOWNLOAD, true);
|
||||
runInAsyncThread(() -> {
|
||||
if (updater.getResult() == Updater.UpdateResult.UPDATE_AVAILABLE) {
|
||||
getLogger().info("There is a new version available: " + updater.getLatestName() + ". You can download it from https://modrinth.com/plugin/" + getPluginName().toLowerCase(Locale.ROOT));
|
||||
}
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
new Updater(this, PROJECT_BUKKITDEV_ID, this.getFile(), Updater.UpdateType.DEFAULT, true);
|
||||
new Updater(this, getPluginName().toLowerCase(Locale.ROOT), this.getFile(), Updater.UpdateType.DEFAULT, true);
|
||||
}
|
||||
|
||||
private static final String PROJECT_JENKINS_JOB_URL = "https://ci.minebench.de/job/ChestShop-3/";
|
||||
|
@ -524,10 +579,20 @@ public class ChestShop extends JavaPlugin {
|
|||
return dataFolder;
|
||||
}
|
||||
|
||||
public static Logger getShopLogger() {
|
||||
return shopLogger;
|
||||
}
|
||||
|
||||
public static Logger getBukkitLogger() {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public static void logDebug(String message) {
|
||||
if (Properties.DEBUG) {
|
||||
getBukkitLogger().info("[DEBUG] " + message);
|
||||
}
|
||||
}
|
||||
|
||||
public static Server getBukkitServer() {
|
||||
return server;
|
||||
}
|
||||
|
@ -548,6 +613,10 @@ public class ChestShop extends JavaPlugin {
|
|||
return plugin;
|
||||
}
|
||||
|
||||
public static Metrics getMetrics() {
|
||||
return bStats;
|
||||
}
|
||||
|
||||
public static BukkitAudiences getAudiences() {
|
||||
return audiences;
|
||||
}
|
||||
|
@ -587,4 +656,8 @@ public class ChestShop extends JavaPlugin {
|
|||
Bukkit.getOnlinePlayers().iterator().next().sendPluginMessage(plugin, "BungeeCord", out.toByteArray());
|
||||
}
|
||||
}
|
||||
|
||||
public static void runInAsyncThread(Runnable runnable) {
|
||||
executorService.submit(runnable);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.Acrobot.ChestShop.Commands;
|
||||
|
||||
import com.Acrobot.ChestShop.Configuration.Messages;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
|
@ -43,7 +43,7 @@ public class AccessToggle implements CommandExecutor {
|
|||
}
|
||||
|
||||
public static boolean setIgnoring(Player player, boolean ignoring) {
|
||||
Validate.notNull(player); // Make sure the player instance is not null, in case there are any errors in the code
|
||||
Preconditions.checkNotNull(player); // Make sure the player instance is not null, in case there are any errors in the code
|
||||
|
||||
if (ignoring) {
|
||||
toggledPlayers.add(player.getUniqueId());
|
||||
|
|
|
@ -48,17 +48,7 @@ public class ItemInfo implements CommandExecutor {
|
|||
}
|
||||
|
||||
iteminfo.send(sender);
|
||||
try {
|
||||
Map<String, String> replacementMap = ImmutableMap.of("item", ItemUtil.getName(item));
|
||||
if (!Properties.SHOWITEM_MESSAGE || !(sender instanceof Player)
|
||||
|| !MaterialUtil.Show.sendMessage((Player) sender, sender.getName(), Messages.iteminfo_fullname, false, new ItemStack[]{item}, replacementMap)) {
|
||||
Messages.iteminfo_fullname.send(sender, replacementMap);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
sender.sendMessage(ChatColor.RED + "Error while generating full name. Please contact an admin or take a look at the console/log!");
|
||||
ChestShop.getPlugin().getLogger().log(Level.SEVERE, "Error while generating full item name", e);
|
||||
return true;
|
||||
}
|
||||
if (!sendItemName(sender, item, Messages.iteminfo_fullname)) return true;
|
||||
|
||||
try {
|
||||
iteminfo_shopname.send(sender, "item", ItemUtil.getSignName(item));
|
||||
|
@ -73,4 +63,19 @@ public class ItemInfo implements CommandExecutor {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean sendItemName(CommandSender sender, ItemStack item, Messages.Message message) {
|
||||
try {
|
||||
Map<String, String> replacementMap = ImmutableMap.of("item", ItemUtil.getName(item));
|
||||
if (!Properties.SHOWITEM_MESSAGE || !(sender instanceof Player)
|
||||
|| !MaterialUtil.Show.sendMessage((Player) sender, sender.getName(), message, false, new ItemStack[]{item}, replacementMap)) {
|
||||
message.send(sender, replacementMap);
|
||||
}
|
||||
} catch (IllegalArgumentException e) {
|
||||
sender.sendMessage(ChatColor.RED + "Error while generating full name. Please contact an admin or take a look at the console/log!");
|
||||
ChestShop.getPlugin().getLogger().log(Level.SEVERE, "Error while generating full item name", e);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import org.bukkit.entity.Player;
|
|||
public class ShopInfo implements CommandExecutor {
|
||||
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
|
||||
if (sender instanceof Player) {
|
||||
Block target = ((Player) sender).getTargetBlock(5);
|
||||
Block target = ((Player) sender).getTargetBlockExact(5);
|
||||
if (target != null) {
|
||||
Sign sign = null;
|
||||
if (ChestShopSign.isValid(target)) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.Acrobot.ChestShop.Commands;
|
||||
|
||||
import com.Acrobot.ChestShop.Configuration.Messages;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import com.google.common.base.Preconditions;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.command.Command;
|
||||
|
@ -61,7 +61,7 @@ public class Toggle implements CommandExecutor {
|
|||
}
|
||||
|
||||
public static boolean setIgnoring(Player player, boolean ignoring) {
|
||||
Validate.notNull(player); // Make sure the player instance is not null, in case there are any errors in the code
|
||||
Preconditions.checkNotNull(player); // Make sure the player instance is not null, in case there are any errors in the code
|
||||
|
||||
if (ignoring) {
|
||||
toggledPlayers.add(player.getUniqueId());
|
||||
|
|
|
@ -34,6 +34,15 @@ public class Messages {
|
|||
public static Message iteminfo_repaircost;
|
||||
public static Message iteminfo_book;
|
||||
public static Message iteminfo_book_generation;
|
||||
public static Message iteminfo_leather_color;
|
||||
public static Message iteminfo_bundle_items;
|
||||
public static Message iteminfo_axolotl_variant;
|
||||
public static Message iteminfo_recipes;
|
||||
public static Message iteminfo_map_view;
|
||||
public static Message iteminfo_map_location;
|
||||
public static Message iteminfo_tropical_fish;
|
||||
public static Message iteminfo_crossbow_projectiles;
|
||||
public static Message iteminfo_crossbow_projectile;
|
||||
public static Message iteminfo_lore;
|
||||
|
||||
public static Message METRICS;
|
||||
|
@ -73,7 +82,9 @@ public class Messages {
|
|||
public static Message INVALID_SHOP_PRICE;
|
||||
public static Message INVALID_SHOP_QUANTITY;
|
||||
public static Message CANNOT_ACCESS_THE_CHEST;
|
||||
public static Message CANNOT_CHANGE_SIGN_BACKSIDE;
|
||||
|
||||
public static Message SELL_PRICE_HIGHER_THAN_BUY_PRICE;
|
||||
public static Message SELL_PRICE_ABOVE_MAX;
|
||||
public static Message SELL_PRICE_BELOW_MIN;
|
||||
public static Message BUY_PRICE_ABOVE_MAX;
|
||||
|
@ -190,7 +201,11 @@ public class Messages {
|
|||
public Component getComponent(CommandSender sender, boolean prefixSuffix, Map<String, String> replacementMap, String... replacements) {
|
||||
MineDown mineDown = new MineDown("%prefix" + getLang(sender));
|
||||
mineDown.placeholderSuffix("");
|
||||
mineDown.replace("prefix", prefixSuffix ? prefix.getLang(sender) : "");
|
||||
if (prefixSuffix) {
|
||||
mineDown.replace("prefix", MineDown.parse(prefix.getLang(sender)));
|
||||
} else {
|
||||
mineDown.replace("prefix", "");
|
||||
}
|
||||
mineDown.replace(replacementMap);
|
||||
mineDown.replace(replacements);
|
||||
return mineDown.toComponent();
|
||||
|
|
|
@ -43,9 +43,10 @@ public class Properties {
|
|||
if (o instanceof Material) {
|
||||
set.add((Material) o);
|
||||
} else if (o instanceof String) {
|
||||
try {
|
||||
set.add(Material.getMaterial(((String) o).toUpperCase(Locale.ROOT)));
|
||||
} catch (IllegalArgumentException e) {
|
||||
Material m = Material.getMaterial(((String) o).toUpperCase(Locale.ROOT));
|
||||
if (m != null) {
|
||||
set.add(m);
|
||||
} else {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, o + " is not a valid Material name in the config!");
|
||||
}
|
||||
}
|
||||
|
@ -102,10 +103,13 @@ public class Properties {
|
|||
@ConfigurationComment("Do you want to turn off the automatic updates of ChestShop?")
|
||||
public static boolean TURN_OFF_UPDATES = true;
|
||||
|
||||
@ConfigurationComment("Do you want to turn off the automatic notifications for releases?")
|
||||
public static boolean TURN_OFF_UPDATE_NOTIFIER = false;
|
||||
|
||||
@ConfigurationComment("Do you want to turn off the automatic notifications for new development builds?")
|
||||
public static boolean TURN_OFF_DEV_UPDATE_NOTIFIER = false;
|
||||
|
||||
@ConfigurationComment("Do you want to include some values of this config in the metrics? (This will not leak sensitive data but help in the development process)")
|
||||
@ConfigurationComment("Do you want to include some values of this config in the metrics? (This will not submit any sensitive data and helps in the development process)")
|
||||
public static boolean INCLUDE_SETTINGS_IN_METRICS = true;
|
||||
|
||||
@PrecededBySpace
|
||||
|
@ -119,6 +123,9 @@ public class Properties {
|
|||
@ConfigurationComment("Should the plugin try to use a language file that matches the client's locale setting?")
|
||||
public static boolean USE_CLIENT_LOCALE = true;
|
||||
|
||||
@ConfigurationComment("Should the plugin strip the colors from formatted price?")
|
||||
public static boolean STRIP_PRICE_COLORS = false;
|
||||
|
||||
@PrecededBySpace
|
||||
@ConfigurationComment("What containers are allowed to hold a shop? (Only blocks with inventories work!)")
|
||||
@Parser("MaterialSet")
|
||||
|
@ -152,6 +159,9 @@ public class Properties {
|
|||
@ConfigurationComment("Can shop's chest be opened by owner with right-clicking a shop's sign?")
|
||||
public static boolean ALLOW_SIGN_CHEST_OPEN = false;
|
||||
|
||||
@ConfigurationComment("If true and in 1.14+, the owner of a chest shop can click with a dye / ink sac to dye the sign.")
|
||||
public static boolean SIGN_DYING = true;
|
||||
|
||||
@ConfigurationComment("If true, when you left-click your own shop sign you won't open chest's inventory, but instead you will start destroying the sign.")
|
||||
public static boolean ALLOW_LEFT_CLICK_DESTROYING = true;
|
||||
|
||||
|
@ -180,10 +190,10 @@ public class Properties {
|
|||
public static UUID SERVER_ECONOMY_ACCOUNT_UUID = new UUID(0, 0);
|
||||
|
||||
@ConfigurationComment("Percent of the price that should go to the server's account. (100 = 100 percent)")
|
||||
public static int TAX_AMOUNT = 0;
|
||||
public static double TAX_AMOUNT = 0;
|
||||
|
||||
@ConfigurationComment("Percent of the price that should go to the server's account when buying from an Admin Shop.")
|
||||
public static int SERVER_TAX_AMOUNT = 0;
|
||||
public static double SERVER_TAX_AMOUNT = 0;
|
||||
|
||||
@ConfigurationComment("Amount of money player must pay to create a shop")
|
||||
public static BigDecimal SHOP_CREATION_PRICE = BigDecimal.valueOf(0);
|
||||
|
@ -198,8 +208,8 @@ public class Properties {
|
|||
public static boolean ENSURE_CORRECT_PLAYERID = true;
|
||||
|
||||
@ConfigurationComment("This regexp validates the name of the player. If the name doesn't match, the player will neither be able to create a valid shop sign, nor buy/sell from a shop.\n" +
|
||||
"Note for Bedrock support: If you have Floodgate on your server, you should set this regexp to ^\\\\*?\\\\w+$ and ENSURE_CORRECT_PLAYERID to false\n" +
|
||||
"If your Floodgate prefix is not *, change the first * in the regexp (the one before the question mark) to whatever your prefix is.")
|
||||
"Note for Bedrock support: If you have Floodgate on your server, you should set this regexp to ^\\\\.?\\\\w+$ and ENSURE_CORRECT_PLAYERID to false\n" +
|
||||
"If your Floodgate prefix is not a dot, then change the first . in the regexp (the one before the question mark) to whatever your prefix is.")
|
||||
public static String VALID_PLAYERNAME_REGEXP = "^\\w+$";
|
||||
|
||||
@PrecededBySpace
|
||||
|
@ -248,10 +258,10 @@ public class Properties {
|
|||
@ConfigurationComment("If true, plugin will log transactions in its own file")
|
||||
public static boolean LOG_TO_FILE = false;
|
||||
|
||||
@ConfigurationComment("Do you want ChestShop's messages to show up in console?")
|
||||
@ConfigurationComment("Do you want ChestShop's transaction messages to show up in console?")
|
||||
public static boolean LOG_TO_CONSOLE = true;
|
||||
|
||||
@ConfigurationComment("Should all shop removals be logged to the console?")
|
||||
@ConfigurationComment("Should all shop removals be logged?")
|
||||
public static boolean LOG_ALL_SHOP_REMOVALS = true;
|
||||
|
||||
@PrecededBySpace
|
||||
|
|
|
@ -48,7 +48,7 @@ public class AdminInventory implements Inventory {
|
|||
|
||||
@Override
|
||||
public ItemStack getItem(int i) {
|
||||
if (content.length < i) {
|
||||
if (content.length > i) {
|
||||
return content[i];
|
||||
}
|
||||
return null;
|
||||
|
@ -156,10 +156,12 @@ public class AdminInventory implements Inventory {
|
|||
public HashMap<Integer, ? extends ItemStack> all(ItemStack itemStack) {
|
||||
HashMap<Integer, ItemStack> items = new HashMap<Integer, ItemStack>();
|
||||
|
||||
ItemStack clone = itemStack.clone();
|
||||
clone.setAmount(Integer.MAX_VALUE);
|
||||
if (itemStack != null) {
|
||||
ItemStack clone = itemStack.clone();
|
||||
clone.setAmount(Integer.MAX_VALUE);
|
||||
|
||||
items.put(1, clone);
|
||||
items.put(1, clone);
|
||||
}
|
||||
|
||||
return items;
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import com.Acrobot.ChestShop.ChestShop;
|
|||
import com.j256.ormlite.dao.Dao;
|
||||
import com.j256.ormlite.dao.DaoManager;
|
||||
import com.j256.ormlite.dao.LruObjectCache;
|
||||
import com.j256.ormlite.db.SqliteDatabaseType;
|
||||
import com.j256.ormlite.jdbc.JdbcConnectionSource;
|
||||
import com.j256.ormlite.jdbc.db.SqliteDatabaseType;
|
||||
import com.j256.ormlite.support.ConnectionSource;
|
||||
import com.j256.ormlite.table.TableUtils;
|
||||
|
||||
|
|
|
@ -28,8 +28,6 @@ public class Migrations {
|
|||
public static int migrate(int currentVersion) {
|
||||
if (currentVersion != CURRENT_DATABASE_VERSION) {
|
||||
ChestShop.getBukkitLogger().info("Updating database...");
|
||||
} else {
|
||||
return CURRENT_DATABASE_VERSION;
|
||||
}
|
||||
|
||||
switch (currentVersion) {
|
||||
|
@ -67,7 +65,7 @@ public class Migrations {
|
|||
accounts.executeRaw("ALTER TABLE `accounts` ADD COLUMN lastSeenName VARCHAR");
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while migrating database to v2", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +111,7 @@ public class Migrations {
|
|||
}
|
||||
try {
|
||||
results.close();
|
||||
} catch (IOException e1) {
|
||||
} catch (Exception e1) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while closing results! " + e.getMessage());
|
||||
}
|
||||
ChestShop.getBukkitLogger().log(Level.INFO, success + " accounts successfully migrated. " + error + " accounts failed to migrate!");
|
||||
|
@ -122,7 +120,7 @@ public class Migrations {
|
|||
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while migrating database to v3", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -139,13 +137,13 @@ public class Migrations {
|
|||
try {
|
||||
items.executeRawNoArgs("INSERT INTO `items` (id, code) SELECT id, code uuid FROM `items-old`");
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while inserting items into new database while migrating to v4", e);
|
||||
}
|
||||
ChestShop.getBukkitLogger().log(Level.INFO, "Migration of items table finished in " + (System.currentTimeMillis() - start) / 1000.0 + "s!");
|
||||
|
||||
return true;
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while migrating database to v4", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,12 @@ package com.Acrobot.ChestShop;
|
|||
|
||||
import com.Acrobot.Breeze.Utils.MaterialUtil;
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Listeners.Economy.EconomyAdapter;
|
||||
import com.Acrobot.ChestShop.Listeners.Economy.Plugins.ReserveListener;
|
||||
import com.Acrobot.ChestShop.Listeners.Economy.Plugins.VaultListener;
|
||||
import com.Acrobot.ChestShop.Plugins.*;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.bstats.charts.DrilldownPie;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
|
@ -14,11 +17,19 @@ import org.bukkit.plugin.Plugin;
|
|||
import org.bukkit.plugin.PluginDescriptionFile;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
|
||||
import java.util.AbstractMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
*/
|
||||
public class Dependencies implements Listener {
|
||||
|
||||
private static final Map<String, String> versions = new HashMap<>();
|
||||
|
||||
public static void initializePlugins() {
|
||||
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||
|
||||
|
@ -58,17 +69,31 @@ public class Dependencies implements Listener {
|
|||
Plugin plugin = pluginManager.getPlugin(dependency);
|
||||
|
||||
if (plugin != null && plugin.isEnabled()) {
|
||||
loadPlugin(dependency, plugin);
|
||||
try {
|
||||
loadPlugin(dependency, plugin);
|
||||
} catch (Exception e) {
|
||||
plugin.getLogger().log(Level.WARNING, "Unable to hook into " + plugin.getName() + " " + plugin.getDescription().getVersion(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return loadEconomy();
|
||||
if (loadEconomy()) {
|
||||
Map<String, Map<String, Integer>> map = versions.entrySet().stream()
|
||||
.map(e -> new AbstractMap.SimpleEntry<String, Map<String, Integer>>(e.getKey(), ImmutableMap.of(e.getValue(), 1)))
|
||||
.collect(Collectors.toMap(
|
||||
AbstractMap.SimpleEntry::getKey,
|
||||
AbstractMap.SimpleEntry::getValue
|
||||
));
|
||||
ChestShop.getMetrics().addCustomChart(new DrilldownPie("dependencies", () -> map));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean loadEconomy() {
|
||||
String plugin = "none";
|
||||
|
||||
Listener economy = null;
|
||||
EconomyAdapter economy = null;
|
||||
|
||||
if(Bukkit.getPluginManager().getPlugin("Reserve") != null) {
|
||||
plugin = "Reserve";
|
||||
|
@ -85,6 +110,9 @@ public class Dependencies implements Listener {
|
|||
return false;
|
||||
}
|
||||
|
||||
ChestShop.getMetrics().addCustomChart(ChestShop.createStaticDrilldownStat("economyAdapter", plugin, Bukkit.getPluginManager().getPlugin(plugin).getDescription().getVersion()));
|
||||
ChestShop.getMetrics().addCustomChart(ChestShop.createStaticDrilldownStat("economyPlugin", economy.getProviderInfo().getName(), economy.getProviderInfo().getVersion()));
|
||||
|
||||
ChestShop.registerListener(economy);
|
||||
ChestShop.getBukkitLogger().info(plugin + " loaded!");
|
||||
return true;
|
||||
|
@ -174,6 +202,9 @@ public class Dependencies implements Listener {
|
|||
|
||||
listener = heroes;
|
||||
break;
|
||||
case ItemBridge:
|
||||
listener = new ItemBridge();
|
||||
break;
|
||||
case ShowItem:
|
||||
MaterialUtil.Show.initialize(plugin);
|
||||
break;
|
||||
|
@ -184,6 +215,7 @@ public class Dependencies implements Listener {
|
|||
}
|
||||
|
||||
PluginDescriptionFile description = plugin.getDescription();
|
||||
versions.put(description.getName(), description.getVersion());
|
||||
ChestShop.getBukkitLogger().info(description.getName() + " version " + description.getVersion() + " loaded.");
|
||||
}
|
||||
|
||||
|
@ -202,6 +234,8 @@ public class Dependencies implements Listener {
|
|||
|
||||
Heroes,
|
||||
|
||||
ItemBridge,
|
||||
|
||||
ShowItem
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ public class AccountQueryEvent extends Event {
|
|||
private static final HandlerList handlers = new HandlerList();
|
||||
private final String name;
|
||||
private Account account = null;
|
||||
private boolean searchOfflinePlayers = true;
|
||||
private boolean searchOfflinePlayers = false;
|
||||
|
||||
public AccountQueryEvent(String name) {
|
||||
this.name = name;
|
||||
|
@ -38,7 +38,8 @@ public class AccountQueryEvent extends Event {
|
|||
}
|
||||
|
||||
/**
|
||||
* Set whether or not offline player data should be searched (too)
|
||||
* Set whether or not offline player data should be searched (too).
|
||||
* This could lead to network lookups if the player by the name never joined the server!
|
||||
* @param searchOfflinePlayers Whether or not offline player data should be searched (too)
|
||||
*/
|
||||
public void searchOfflinePlayers(boolean searchOfflinePlayers) {
|
||||
|
|
|
@ -99,6 +99,13 @@ public class CurrencyAddEvent extends EconomicEvent {
|
|||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param target Account from which the currency is subtracted
|
||||
*/
|
||||
public void setTarget(UUID target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -76,6 +76,13 @@ public class CurrencyAmountEvent extends EconomicEvent {
|
|||
return account;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param account Account that is checked
|
||||
*/
|
||||
public void setAccount(UUID account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -103,9 +103,7 @@ public class CurrencyCheckEvent extends EconomicEvent {
|
|||
* Sets the account name
|
||||
*
|
||||
* @param account Account name
|
||||
* @deprecated The account should not be changed!
|
||||
*/
|
||||
@Deprecated
|
||||
public void setAccount(UUID account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.Acrobot.ChestShop.Events.Economy;
|
|||
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
@ -100,6 +99,13 @@ public class CurrencySubtractEvent extends EconomicEvent {
|
|||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param target Account from which the currency is subtracted
|
||||
*/
|
||||
public void setTarget(UUID target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
public HandlerList getHandlers() {
|
||||
return handlers;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package com.Acrobot.ChestShop.Events.Economy;
|
||||
|
||||
import com.Acrobot.ChestShop.Events.TransactionEvent;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
@ -25,26 +25,32 @@ public class CurrencyTransferEvent extends EconomicEvent {
|
|||
|
||||
private Direction direction;
|
||||
|
||||
private final TransactionEvent transactionEvent;
|
||||
|
||||
public CurrencyTransferEvent(BigDecimal amount, Player initiator, UUID partner, Direction direction) {
|
||||
this(amount, amount, initiator, partner, direction);
|
||||
}
|
||||
|
||||
public CurrencyTransferEvent(BigDecimal amountSent, BigDecimal amountReceived, Player initiator, UUID partner, Direction direction) {
|
||||
this(amountSent, amountReceived, initiator, partner, direction, null);
|
||||
}
|
||||
|
||||
|
||||
public CurrencyTransferEvent(BigDecimal amount, Player initiator, UUID partner, Direction direction, TransactionEvent transactionEvent) {
|
||||
this(amount, amount, initiator, partner, direction, transactionEvent);
|
||||
}
|
||||
|
||||
public CurrencyTransferEvent(BigDecimal amountSent, BigDecimal amountReceived, Player initiator, UUID partner, Direction direction, TransactionEvent transactionEvent) {
|
||||
this.amountSent = amountSent;
|
||||
this.amountReceived = amountReceived;
|
||||
this.initiator = initiator;
|
||||
|
||||
this.partner = partner;
|
||||
this.direction = direction;
|
||||
|
||||
this.transactionEvent = transactionEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {{@link #CurrencyTransferEvent(BigDecimal, Player, UUID, Direction)}
|
||||
*/
|
||||
@Deprecated
|
||||
public CurrencyTransferEvent(double amount, Player initiator, UUID partner, Direction direction) {
|
||||
this(BigDecimal.valueOf(amount), initiator, partner, direction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Amount of currency sent
|
||||
|
@ -150,6 +156,15 @@ public class CurrencyTransferEvent extends EconomicEvent {
|
|||
return direction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link TransactionEvent} associated with this currency transfer event.
|
||||
*
|
||||
* @return the transaction event.
|
||||
*/
|
||||
public TransactionEvent getTransactionEvent() {
|
||||
return transactionEvent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the player who initiated this transaction
|
||||
*
|
||||
|
@ -166,6 +181,15 @@ public class CurrencyTransferEvent extends EconomicEvent {
|
|||
return partner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the partner of the transaction
|
||||
*
|
||||
* @param partner the new partner of this transaction
|
||||
*/
|
||||
public void setPartner(UUID partner) {
|
||||
this.partner = partner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The world in which the transaction occurs
|
||||
*/
|
||||
|
|
|
@ -9,13 +9,24 @@ public class ItemStringQueryEvent extends Event {
|
|||
|
||||
private String itemString = null;
|
||||
private final ItemStack item;
|
||||
private final int maxWidth;
|
||||
|
||||
/**
|
||||
* Query the item string representation of a certain item with a certain length
|
||||
* @param item The item to query the string for
|
||||
*/
|
||||
public ItemStringQueryEvent(ItemStack item) {
|
||||
this(item, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the item string representation of a certain item with a certain length
|
||||
* @param item The item to query the string for
|
||||
* @param maxWidth The max width of the item string
|
||||
*/
|
||||
public ItemStringQueryEvent(ItemStack item, int maxWidth) {
|
||||
this.item = item;
|
||||
this.maxWidth = maxWidth;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -50,4 +61,12 @@ public class ItemStringQueryEvent extends Event {
|
|||
public void setItemString(String itemString) {
|
||||
this.itemString = itemString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max width that the result item string should have
|
||||
* @return The max width of the result item string
|
||||
*/
|
||||
public int getMaxWidth() {
|
||||
return maxWidth;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ public class BlockPlace implements Listener {
|
|||
if (!Security.canAccess(player, placed)) {
|
||||
Messages.ACCESS_DENIED.sendWithPrefix(event.getPlayer());
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
Block neighbor = uBlock.findNeighbor(placed);
|
||||
|
@ -65,10 +66,6 @@ public class BlockPlace implements Listener {
|
|||
public static void onHopperDropperPlace(BlockPlaceEvent event) {
|
||||
Block placed = event.getBlockPlaced();
|
||||
|
||||
if (placed.getType() != Material.HOPPER && placed.getType() != Material.DROPPER) {
|
||||
return;
|
||||
}
|
||||
|
||||
List<BlockFace> searchDirections = new ArrayList<>();
|
||||
switch (placed.getType()) {
|
||||
case HOPPER:
|
||||
|
@ -78,6 +75,8 @@ public class BlockPlace implements Listener {
|
|||
case DROPPER:
|
||||
searchDirections.add(((Directional) placed.getBlockData()).getFacing());
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
for (BlockFace face : searchDirections) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.Acrobot.ChestShop.Listeners.Block.Break;
|
||||
|
||||
import com.Acrobot.ChestShop.Configuration.Messages;
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Permission;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
|
@ -21,6 +22,7 @@ public class ChestBreak implements Listener {
|
|||
public static void onChestBreak(BlockBreakEvent event) {
|
||||
if (!canBeBroken(event.getBlock(), event.getPlayer())) {
|
||||
event.setCancelled(true);
|
||||
Messages.ACCESS_DENIED.sendWithPrefix(event.getPlayer());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -50,7 +52,7 @@ public class ChestBreak implements Listener {
|
|||
return true;
|
||||
}
|
||||
|
||||
Sign shopSign = uBlock.findAnyNearbyShopSign(block);
|
||||
Sign shopSign = uBlock.getConnectedSign(block);
|
||||
if (breaker != null) {
|
||||
return ChestShopSign.hasPermission(breaker, Permission.OTHER_NAME_DESTROY, shopSign);
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.Acrobot.ChestShop.Listeners.Block.Break;
|
|||
|
||||
import com.Acrobot.Breeze.Utils.BlockUtil;
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
import com.Acrobot.ChestShop.Configuration.Messages;
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Events.ShopDestroyedEvent;
|
||||
import com.Acrobot.ChestShop.Listeners.Block.Break.Attached.PhysicsBreak;
|
||||
|
@ -23,6 +24,7 @@ import org.bukkit.event.entity.EntityChangeBlockEvent;
|
|||
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||
import org.bukkit.metadata.FixedMetadataValue;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedList;
|
||||
|
@ -32,7 +34,6 @@ import static com.Acrobot.Breeze.Utils.ImplementationAdapter.getState;
|
|||
import static com.Acrobot.Breeze.Utils.BlockUtil.getAttachedBlock;
|
||||
import static com.Acrobot.Breeze.Utils.BlockUtil.isSign;
|
||||
import static com.Acrobot.ChestShop.Permission.OTHER_NAME_DESTROY;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -44,9 +45,9 @@ public class SignBreak implements Listener {
|
|||
public SignBreak() {
|
||||
try {
|
||||
Class.forName("com.destroystokyo.paper.event.block.BlockDestroyEvent");
|
||||
ChestShop.getPlugin().registerEvent((Listener) Class.forName("com.Acrobot.ChestShop.Listeners.Block.Break.Attached.PaperBlockDestroy").newInstance());
|
||||
ChestShop.getPlugin().registerEvent((Listener) Class.forName("com.Acrobot.ChestShop.Listeners.Block.Break.Attached.PaperBlockDestroy").getDeclaredConstructor().newInstance());
|
||||
ChestShop.getBukkitLogger().info("Using Paper's BlockDestroyEvent instead of the BlockPhysicsEvent!");
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException e) {
|
||||
} catch (ClassNotFoundException | IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
|
||||
ChestShop.getPlugin().registerEvent(new PhysicsBreak());
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +71,7 @@ public class SignBreak implements Listener {
|
|||
public static void onSignBreak(BlockBreakEvent event) {
|
||||
if (!canBlockBeBroken(event.getBlock(), event.getPlayer())) {
|
||||
event.setCancelled(true);
|
||||
Messages.ACCESS_DENIED.sendWithPrefix(event.getPlayer());
|
||||
if (isSign(event.getBlock())) {
|
||||
event.getBlock().getState().update();
|
||||
}
|
||||
|
@ -143,7 +145,7 @@ public class SignBreak implements Listener {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (Properties.TURN_OFF_SIGN_PROTECTION || canDestroyShop(breaker, sign.getLine(NAME_LINE))) {
|
||||
if (Properties.TURN_OFF_SIGN_PROTECTION || canDestroyShop(breaker, ChestShopSign.getOwner(sign))) {
|
||||
brokenBlocks.add(sign);
|
||||
} else {
|
||||
canBeBroken = false;
|
||||
|
|
|
@ -3,25 +3,38 @@ package com.Acrobot.ChestShop.Listeners.Block;
|
|||
import com.Acrobot.Breeze.Utils.BlockUtil;
|
||||
import com.Acrobot.Breeze.Utils.StringUtil;
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
import com.Acrobot.ChestShop.Configuration.Messages;
|
||||
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
|
||||
import com.Acrobot.ChestShop.Events.ShopCreatedEvent;
|
||||
import com.Acrobot.ChestShop.Listeners.Block.Break.SignBreak;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import com.Acrobot.ChestShop.UUIDs.NameManager;
|
||||
import com.Acrobot.ChestShop.Utils.uBlock;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.block.sign.Side;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.SignChangeEvent;
|
||||
|
||||
import static com.Acrobot.ChestShop.Permission.OTHER_NAME_DESTROY;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
*/
|
||||
public class SignCreate implements Listener {
|
||||
|
||||
private static boolean HAS_SIGN_SIDES;
|
||||
|
||||
static {
|
||||
try {
|
||||
SignChangeEvent.class.getMethod("getSide");
|
||||
HAS_SIGN_SIDES = true;
|
||||
} catch (NoSuchMethodException e) {
|
||||
HAS_SIGN_SIDES = false;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true)
|
||||
public static void onSignChange(SignChangeEvent event) {
|
||||
Block signBlock = event.getBlock();
|
||||
|
@ -32,15 +45,28 @@ public class SignCreate implements Listener {
|
|||
|
||||
Sign sign = (Sign) signBlock.getState();
|
||||
|
||||
if (ChestShopSign.isValid(sign) && !NameManager.canUseName(event.getPlayer(), OTHER_NAME_DESTROY, StringUtil.stripColourCodes(sign.getLine(NAME_LINE)))) {
|
||||
if (HAS_SIGN_SIDES && event.getSide() != Side.FRONT) {
|
||||
if (ChestShopSign.isValid(sign)) {
|
||||
event.setCancelled(true);
|
||||
Messages.CANNOT_CHANGE_SIGN_BACKSIDE.sendWithPrefix(event.getPlayer());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ChestShopSign.isValid(event.getLines()) && !NameManager.canUseName(event.getPlayer(), OTHER_NAME_DESTROY, ChestShopSign.getOwner(event.getLines()))) {
|
||||
event.setCancelled(true);
|
||||
sign.update();
|
||||
ChestShop.logDebug("Shop sign creation at " + sign.getLocation() + " by " + event.getPlayer().getName() + " was cancelled as they weren't able to create a shop for the account '" + ChestShopSign.getOwner(event.getLines()) + "'");
|
||||
return;
|
||||
}
|
||||
|
||||
String[] lines = StringUtil.stripColourCodes(event.getLines());
|
||||
|
||||
if (!ChestShopSign.isValidPreparedSign(lines)) {
|
||||
// Check if a valid shop already existed previously
|
||||
if (ChestShopSign.isValid(sign)) {
|
||||
SignBreak.sendShopDestroyedEvent(sign, event.getPlayer());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -50,6 +76,7 @@ public class SignCreate implements Listener {
|
|||
if (preEvent.getOutcome().shouldBreakSign()) {
|
||||
event.setCancelled(true);
|
||||
signBlock.breakNaturally();
|
||||
ChestShop.logDebug("Shop sign creation at " + sign.getLocation() + " by " + event.getPlayer().getName() + " was cancelled (creation outcome: " + preEvent.getOutcome() + ") and the sign broken");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -58,6 +85,7 @@ public class SignCreate implements Listener {
|
|||
}
|
||||
|
||||
if (preEvent.isCancelled()) {
|
||||
ChestShop.logDebug("Shop sign creation at " + sign.getLocation() + " by " + event.getPlayer().getName() + " was cancelled (creation outcome: " + preEvent.getOutcome() + ") and sign lines were set to " + String.join(", ", preEvent.getSignLines()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,8 @@ import java.math.BigDecimal;
|
|||
|
||||
public abstract class EconomyAdapter implements Listener {
|
||||
|
||||
public abstract ProviderInfo getProviderInfo();
|
||||
|
||||
public abstract void onAmountCheck(CurrencyAmountEvent event);
|
||||
|
||||
public abstract void onCurrencyCheck(CurrencyCheckEvent event);
|
||||
|
@ -74,4 +76,21 @@ public abstract class EconomyAdapter implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
public static class ProviderInfo {
|
||||
private final String name;
|
||||
private final String version;
|
||||
|
||||
public ProviderInfo(String name, String version) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.Acrobot.ChestShop.Listeners.Economy.Plugins;
|
||||
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Events.Economy.AccountCheckEvent;
|
||||
import com.Acrobot.ChestShop.Events.Economy.CurrencyAddEvent;
|
||||
import com.Acrobot.ChestShop.Events.Economy.CurrencyAmountEvent;
|
||||
|
@ -12,6 +13,7 @@ import com.Acrobot.ChestShop.Listeners.Economy.EconomyAdapter;
|
|||
import net.tnemc.core.Reserve;
|
||||
import net.tnemc.core.economy.EconomyAPI;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
@ -26,10 +28,15 @@ public class ReserveListener extends EconomyAdapter {
|
|||
|
||||
private static @Nullable EconomyAPI economyAPI;
|
||||
|
||||
public ReserveListener(EconomyAPI api) {
|
||||
public ReserveListener(@Nullable EconomyAPI api) {
|
||||
ReserveListener.economyAPI = api;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProviderInfo getProviderInfo() {
|
||||
return new ProviderInfo(economyAPI.name(), economyAPI.version());
|
||||
}
|
||||
|
||||
public static EconomyAPI getProvider() {
|
||||
return economyAPI;
|
||||
}
|
||||
|
@ -99,7 +106,8 @@ public class ReserveListener extends EconomyAdapter {
|
|||
}
|
||||
|
||||
if (provided()) {
|
||||
event.setFormattedAmount(economyAPI.format(event.getAmount()));
|
||||
String formatted = economyAPI.format(event.getAmount());
|
||||
event.setFormattedAmount(Properties.STRIP_PRICE_COLORS ? ChatColor.stripColor(formatted) : formatted);
|
||||
event.setHandled(true);
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +135,7 @@ public class ReserveListener extends EconomyAdapter {
|
|||
|
||||
@EventHandler
|
||||
public void onCurrencyHoldCheck(CurrencyHoldEvent event) {
|
||||
if (event.getAccount() == null || event.wasHandled() || !transactionCanFail() || event.canHold()) {
|
||||
if (!provided() || event.getAccount() == null || event.wasHandled() || !transactionCanFail() || event.canHold()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,16 +5,19 @@ import java.util.logging.Level;
|
|||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Listeners.Economy.EconomyAdapter;
|
||||
import net.milkbowl.vault.economy.Economy;
|
||||
import net.milkbowl.vault.economy.EconomyResponse;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.server.ServiceRegisterEvent;
|
||||
import org.bukkit.event.server.ServiceUnregisterEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredServiceProvider;
|
||||
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
|
@ -35,6 +38,7 @@ import com.Acrobot.ChestShop.Events.Economy.CurrencyTransferEvent;
|
|||
public class VaultListener extends EconomyAdapter {
|
||||
private RegisteredServiceProvider<Economy> rsp;
|
||||
private static Economy provider;
|
||||
private Plugin providingPlugin;
|
||||
|
||||
private VaultListener() {
|
||||
updateEconomyProvider();
|
||||
|
@ -45,6 +49,7 @@ public class VaultListener extends EconomyAdapter {
|
|||
|
||||
if (rsp != null) {
|
||||
provider = rsp.getProvider();
|
||||
providingPlugin = rsp.getPlugin();
|
||||
ChestShop.getBukkitLogger().log(Level.INFO, "Using " + provider.getName() + " as the Economy provider now.");
|
||||
}
|
||||
}
|
||||
|
@ -58,6 +63,11 @@ public class VaultListener extends EconomyAdapter {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProviderInfo getProviderInfo() {
|
||||
return new ProviderInfo(provider.getName(), providingPlugin.getDescription().getVersion());
|
||||
}
|
||||
|
||||
public static Economy getProvider() { return provider; }
|
||||
|
||||
public boolean transactionCanFail() {
|
||||
|
@ -172,7 +182,7 @@ public class VaultListener extends EconomyAdapter {
|
|||
}
|
||||
|
||||
String formatted = provider.format(event.getAmount().doubleValue());
|
||||
event.setFormattedAmount(formatted);
|
||||
event.setFormattedAmount(Properties.STRIP_PRICE_COLORS ? ChatColor.stripColor(formatted) : formatted);
|
||||
event.setHandled(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.Acrobot.ChestShop.Listeners.Economy;
|
||||
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
import com.Acrobot.ChestShop.Database.Account;
|
||||
import com.Acrobot.ChestShop.Events.Economy.*;
|
||||
import com.Acrobot.ChestShop.UUIDs.NameManager;
|
||||
|
@ -27,15 +26,12 @@ public class ServerAccountCorrector implements Listener {
|
|||
Account account = NameManager.getServerEconomyAccount();
|
||||
target = account != null ? account.getUuid() : null;
|
||||
|
||||
event.setHandled(true);
|
||||
if (target == null) {
|
||||
event.setHandled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
CurrencyAddEvent currencyAddEvent = new CurrencyAddEvent(event.getAmount(), target, event.getWorld());
|
||||
ChestShop.callEvent(currencyAddEvent);
|
||||
|
||||
event.setHandled(currencyAddEvent.wasHandled());
|
||||
event.setTarget(target);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
|
@ -49,15 +45,12 @@ public class ServerAccountCorrector implements Listener {
|
|||
Account account = NameManager.getServerEconomyAccount();
|
||||
target = account != null ? account.getUuid() : null;
|
||||
|
||||
event.setHandled(true);
|
||||
if (target == null) {
|
||||
event.setHandled(true);
|
||||
return;
|
||||
}
|
||||
|
||||
CurrencySubtractEvent currencySubtractEvent = new CurrencySubtractEvent(event.getAmount(), target, event.getWorld());
|
||||
ChestShop.callEvent(currencySubtractEvent);
|
||||
|
||||
event.setHandled(currencySubtractEvent.wasHandled());
|
||||
event.setTarget(target);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
|
@ -75,15 +68,7 @@ public class ServerAccountCorrector implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
CurrencyTransferEvent currencyTransferEvent = new CurrencyTransferEvent(
|
||||
event.getAmountSent(),
|
||||
event.getAmountReceived(),
|
||||
event.getInitiator(),
|
||||
partner,
|
||||
event.getDirection()
|
||||
);
|
||||
ChestShop.callEvent(currencyTransferEvent);
|
||||
event.setHandled(currencyTransferEvent.wasHandled());
|
||||
event.setPartner(partner);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
|
@ -102,10 +87,7 @@ public class ServerAccountCorrector implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
CurrencyCheckEvent currencyCheckEvent = new CurrencyCheckEvent(event.getAmount(), target, event.getWorld());
|
||||
ChestShop.callEvent(currencyCheckEvent);
|
||||
|
||||
event.hasEnough(currencyCheckEvent.hasEnough());
|
||||
event.setAccount(target);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
|
@ -116,8 +98,15 @@ public class ServerAccountCorrector implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
event.canHold(true);
|
||||
event.setAccount(null);
|
||||
Account account = NameManager.getServerEconomyAccount();
|
||||
target = account != null ? account.getUuid() : null;
|
||||
|
||||
if (target == null) {
|
||||
event.canHold(true);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setAccount(target);
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
|
@ -136,9 +125,6 @@ public class ServerAccountCorrector implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
CurrencyAmountEvent currencyAmountEvent = new CurrencyAmountEvent(target, event.getWorld());
|
||||
ChestShop.callEvent(currencyAmountEvent);
|
||||
|
||||
event.setAmount(currencyAmountEvent.getAmount());
|
||||
event.setAccount(target);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ import com.Acrobot.ChestShop.ChestShop;
|
|||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Events.Economy.CurrencyAddEvent;
|
||||
import com.Acrobot.ChestShop.Events.Economy.CurrencyTransferEvent;
|
||||
import com.Acrobot.ChestShop.Events.PreTransactionEvent;
|
||||
import com.Acrobot.ChestShop.Events.TransactionEvent;
|
||||
import com.Acrobot.ChestShop.Permission;
|
||||
import com.Acrobot.ChestShop.UUIDs.NameManager;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
@ -19,9 +17,11 @@ import java.util.UUID;
|
|||
* @author Acrobot
|
||||
*/
|
||||
public class TaxModule implements Listener {
|
||||
private static final String TAX_RECEIVED_MESSAGE = "Applied a tax of %1$f percent (%2$.2f) to the received amount for a resulting price of %3$.2f";
|
||||
private static final String TAX_SENT_MESSAGE = "Reduced buy price by tax of %1$f percent (%2$.2f) for a resulting price of %3$.2f as the buyer has the buy tax bypass permission";
|
||||
|
||||
private static float getTax(UUID partner) {
|
||||
float taxAmount = NameManager.isAdminShop(partner) || NameManager.isServerEconomyAccount(partner)
|
||||
private static double getTax(UUID partner) {
|
||||
double taxAmount = NameManager.isAdminShop(partner) || NameManager.isServerEconomyAccount(partner)
|
||||
? Properties.SERVER_TAX_AMOUNT : Properties.TAX_AMOUNT;
|
||||
|
||||
if (taxAmount == 0) {
|
||||
|
@ -31,7 +31,7 @@ public class TaxModule implements Listener {
|
|||
return taxAmount;
|
||||
}
|
||||
|
||||
private static BigDecimal getTaxAmount(BigDecimal price, float taxAmount) {
|
||||
private static BigDecimal getTaxAmount(BigDecimal price, double taxAmount) {
|
||||
return price.multiply(BigDecimal.valueOf(taxAmount)).divide(BigDecimal.valueOf(100), Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP);
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ public class TaxModule implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
float taxAmount = getTax(event.getPartner());
|
||||
double taxAmount = getTax(event.getPartner());
|
||||
if (taxAmount == 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -49,17 +49,28 @@ public class TaxModule implements Listener {
|
|||
if (!Permission.has(event.getInitiator(), event.getDirection() == CurrencyTransferEvent.Direction.PARTNER ? Permission.NO_BUY_TAX : Permission.NO_SELL_TAX)) {
|
||||
if (!NameManager.isServerEconomyAccount(event.getReceiver())) {
|
||||
BigDecimal tax = getTaxAmount(event.getAmountReceived(), taxAmount);
|
||||
event.setAmountReceived(event.getAmountReceived().subtract(tax));
|
||||
BigDecimal taxedAmount = event.getAmountReceived().subtract(tax);
|
||||
event.setAmountReceived(taxedAmount);
|
||||
if (NameManager.getServerEconomyAccount() != null) {
|
||||
ChestShop.callEvent(new CurrencyAddEvent(
|
||||
tax,
|
||||
NameManager.getServerEconomyAccount().getUuid(),
|
||||
event.getWorld()));
|
||||
}
|
||||
ChestShop.getShopLogger().info(String.format(TAX_RECEIVED_MESSAGE, taxAmount, tax, taxedAmount));
|
||||
}
|
||||
} else if (event.getDirection() == CurrencyTransferEvent.Direction.PARTNER && Permission.has(event.getInitiator(), Permission.NO_BUY_TAX)) {
|
||||
event.setAmountSent(event.getAmountSent().subtract(getTaxAmount(event.getAmountSent(), taxAmount)));
|
||||
event.setAmountReceived(event.getAmountReceived().subtract(getTaxAmount(event.getAmountReceived(), taxAmount)));
|
||||
// Reduce paid amount as the buyer has permission to not pay taxes
|
||||
BigDecimal taxSent = getTaxAmount(event.getAmountSent(), taxAmount);
|
||||
BigDecimal taxedSentAmount = event.getAmountSent().subtract(taxSent);
|
||||
event.setAmountSent(taxedSentAmount);
|
||||
ChestShop.getShopLogger().info(String.format(TAX_SENT_MESSAGE, taxAmount, taxSent, taxedSentAmount));
|
||||
|
||||
// Reduce the amount that the seller receives anyways even though tax wasn't paid as that shouldn't make a difference for the seller
|
||||
BigDecimal taxReceived = getTaxAmount(event.getAmountReceived(), taxAmount);
|
||||
BigDecimal taxedReceivedAmount = event.getAmountReceived().subtract(taxReceived);
|
||||
event.setAmountReceived(taxedReceivedAmount);
|
||||
ChestShop.getShopLogger().info(String.format(TAX_RECEIVED_MESSAGE, taxAmount, taxReceived, taxedReceivedAmount));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,15 +16,17 @@ public class GarbageTextListener implements Listener {
|
|||
public static void filterGarbage(SignChangeEvent event) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
String line = event.getLine(i);
|
||||
StringBuilder output = new StringBuilder(line.length());
|
||||
if (line != null) {
|
||||
StringBuilder output = new StringBuilder(line.length());
|
||||
|
||||
for (char character : line.toCharArray()) {
|
||||
if (character < 0xF700 || character > 0xF747) {
|
||||
output.append(character);
|
||||
for (char character : line.toCharArray()) {
|
||||
if (character < 0xF700 || character > 0xF747) {
|
||||
output.append(character);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
event.setLine(i, output.toString());
|
||||
event.setLine(i, output.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
package com.Acrobot.ChestShop.Listeners.Item;
|
||||
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Listeners.Modules.StockCounterModule;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.Hopper;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.inventory.InventoryMoveItemEvent;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
import static com.Acrobot.Breeze.Utils.ImplementationAdapter.getHolder;
|
||||
|
||||
|
@ -16,14 +20,15 @@ public class ItemMoveListener implements Listener {
|
|||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public static void onItemMove(InventoryMoveItemEvent event) {
|
||||
if (event.getSource() == null || getHolder(event.getDestination(), false) instanceof BlockState) {
|
||||
return;
|
||||
}
|
||||
InventoryHolder destinationHolder = getHolder(event.getDestination(), false);
|
||||
InventoryHolder sourceHolder = getHolder(event.getSource(), false);
|
||||
|
||||
if (!ChestShopSign.isShopBlock(getHolder(event.getSource(), false))) {
|
||||
return;
|
||||
if (!(destinationHolder instanceof BlockState) && ChestShopSign.isShopBlock(sourceHolder)) {
|
||||
event.setCancelled(true);
|
||||
} else if (Properties.USE_STOCK_COUNTER && ChestShopSign.isShopBlock(destinationHolder) && sourceHolder instanceof Hopper) {
|
||||
StockCounterModule.updateCounterOnItemMoveEvent(event.getItem(), destinationHolder);
|
||||
}
|
||||
|
||||
event.setCancelled(true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ public class ItemStringListener implements Listener {
|
|||
@EventHandler(priority = EventPriority.NORMAL)
|
||||
public static void calculateItemString(ItemStringQueryEvent event) {
|
||||
if (event.getItemString() == null) {
|
||||
event.setItemString(MaterialUtil.getName(event.getItem(), 0));
|
||||
event.setItemString(MaterialUtil.getName(event.getItem(), event.getMaxWidth()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,19 +1,30 @@
|
|||
package com.Acrobot.ChestShop.Listeners;
|
||||
|
||||
import com.Acrobot.Breeze.Utils.StringUtil;
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
import com.Acrobot.ChestShop.Commands.ItemInfo;
|
||||
import com.Acrobot.ChestShop.Events.ItemInfoEvent;
|
||||
import org.bukkit.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Color;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.AxolotlBucketMeta;
|
||||
import org.bukkit.inventory.meta.BookMeta;
|
||||
import org.bukkit.inventory.meta.BundleMeta;
|
||||
import org.bukkit.inventory.meta.CrossbowMeta;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.KnowledgeBookMeta;
|
||||
import org.bukkit.inventory.meta.LeatherArmorMeta;
|
||||
import org.bukkit.inventory.meta.MapMeta;
|
||||
import org.bukkit.inventory.meta.PotionMeta;
|
||||
import org.bukkit.inventory.meta.Repairable;
|
||||
import org.bukkit.potion.Potion;
|
||||
import org.bukkit.inventory.meta.TropicalFishBucketMeta;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
|
||||
import java.util.Map;
|
||||
|
@ -21,34 +32,99 @@ import java.util.Map;
|
|||
import static com.Acrobot.Breeze.Utils.NumberUtil.toRoman;
|
||||
import static com.Acrobot.Breeze.Utils.NumberUtil.toTime;
|
||||
import static com.Acrobot.Breeze.Utils.StringUtil.capitalizeFirstLetter;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_axolotl_variant;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_book;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_book_generation;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_bundle_items;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_crossbow_projectile;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_crossbow_projectiles;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_leather_color;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_lore;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_map_location;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_map_view;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_recipes;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_repaircost;
|
||||
import static com.Acrobot.ChestShop.Configuration.Messages.iteminfo_tropical_fish;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
*/
|
||||
public class ItemInfoListener implements Listener {
|
||||
|
||||
// Register version dependent listeners
|
||||
static {
|
||||
try {
|
||||
Class.forName("org.bukkit.inventory.meta.AxolotlBucketMeta");
|
||||
ChestShop.registerListener(new Listener() {
|
||||
@EventHandler
|
||||
public void addAxolotlInfo(ItemInfoEvent event) {
|
||||
if (event.getItem().hasItemMeta()) {
|
||||
ItemMeta meta = event.getItem().getItemMeta();
|
||||
if (meta instanceof AxolotlBucketMeta) {
|
||||
iteminfo_axolotl_variant.send(event.getSender(), "variant", capitalizeFirstLetter(((AxolotlBucketMeta) meta).getVariant().name(), '_'));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (ClassNotFoundException | NoClassDefFoundError ignored) {}
|
||||
try {
|
||||
Class.forName("org.bukkit.inventory.meta.BundleMeta");
|
||||
ChestShop.registerListener(new Listener() {
|
||||
@EventHandler
|
||||
public void addAxolotlInfo(ItemInfoEvent event) {
|
||||
if (event.getItem().hasItemMeta()) {
|
||||
ItemMeta meta = event.getItem().getItemMeta();
|
||||
if (meta instanceof BundleMeta) {
|
||||
iteminfo_bundle_items.send(event.getSender(), "itemcount", String.valueOf(((BundleMeta) meta).getItems().size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (ClassNotFoundException | NoClassDefFoundError ignored) {}
|
||||
try {
|
||||
Class.forName("org.bukkit.inventory.meta.CrossbowMeta");
|
||||
ChestShop.registerListener(new Listener() {
|
||||
@EventHandler
|
||||
public void addCrossBowInfo(ItemInfoEvent event) {
|
||||
if (event.getItem().hasItemMeta()) {
|
||||
ItemMeta meta = event.getItem().getItemMeta();
|
||||
if (meta instanceof CrossbowMeta && ((CrossbowMeta) meta).hasChargedProjectiles()) {
|
||||
iteminfo_crossbow_projectiles.send(event.getSender());
|
||||
for (ItemStack chargedProjectile : ((CrossbowMeta) meta).getChargedProjectiles()) {
|
||||
ItemInfo.sendItemName(event.getSender(), chargedProjectile, iteminfo_crossbow_projectile);
|
||||
ChestShop.callEvent(new ItemInfoEvent(event.getSender(), chargedProjectile));
|
||||
event.getSender().sendMessage(ChatColor.GRAY + "---");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (ClassNotFoundException | NoClassDefFoundError ignored) {}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void addRepairCost(ItemInfoEvent event) {
|
||||
ItemMeta meta = event.getItem().getItemMeta();
|
||||
if (meta instanceof Repairable && ((Repairable) meta).getRepairCost() > 0) {
|
||||
iteminfo_repaircost.send(event.getSender(), "cost", String.valueOf(((Repairable) meta).getRepairCost()));
|
||||
if (event.getItem().hasItemMeta()) {
|
||||
ItemMeta meta = event.getItem().getItemMeta();
|
||||
if (meta instanceof Repairable && ((Repairable) meta).getRepairCost() > 0) {
|
||||
iteminfo_repaircost.send(event.getSender(), "cost", String.valueOf(((Repairable) meta).getRepairCost()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void addEnchantment(ItemInfoEvent event) {
|
||||
ItemStack item = event.getItem();
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
CommandSender sender = event.getSender();
|
||||
|
||||
for (Map.Entry<Enchantment, Integer> enchantment : item.getEnchantments().entrySet()) {
|
||||
sender.sendMessage(ChatColor.AQUA + capitalizeFirstLetter(enchantment.getKey().getName(), '_') + ' ' + toRoman(enchantment.getValue()));
|
||||
}
|
||||
|
||||
if (!item.hasItemMeta()) {
|
||||
return;
|
||||
}
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (meta instanceof EnchantmentStorageMeta) {
|
||||
for (Map.Entry<Enchantment, Integer> enchantment : ((EnchantmentStorageMeta) meta).getStoredEnchants().entrySet()) {
|
||||
sender.sendMessage(ChatColor.YELLOW + capitalizeFirstLetter(enchantment.getKey().getName(), '_') + ' ' + toRoman(enchantment.getValue()));
|
||||
|
@ -56,49 +132,110 @@ public class ItemInfoListener implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void addLeatherColor(ItemInfoEvent event) {
|
||||
if (event.getItem().hasItemMeta()) {
|
||||
ItemMeta meta = event.getItem().getItemMeta();
|
||||
if (meta instanceof LeatherArmorMeta) {
|
||||
Color color = ((LeatherArmorMeta) meta).getColor();
|
||||
iteminfo_leather_color.send(event.getSender(),
|
||||
"colorred", String.valueOf(color.getRed()),
|
||||
"colorgreen", String.valueOf(color.getGreen()),
|
||||
"colorblue", String.valueOf(color.getBlue()),
|
||||
"colorhex", Integer.toHexString(color.asRGB())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void addRecipes(ItemInfoEvent event) {
|
||||
if (event.getItem().hasItemMeta()) {
|
||||
ItemMeta meta = event.getItem().getItemMeta();
|
||||
if (meta instanceof KnowledgeBookMeta && !((KnowledgeBookMeta) meta).getRecipes().isEmpty()) {
|
||||
iteminfo_recipes.send(event.getSender());
|
||||
for (NamespacedKey recipe : ((KnowledgeBookMeta) meta).getRecipes()) {
|
||||
event.getSender().sendMessage(ChatColor.GRAY + recipe.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void addTropicalFishInfo(ItemInfoEvent event) {
|
||||
if (event.getItem().hasItemMeta()) {
|
||||
ItemMeta meta = event.getItem().getItemMeta();
|
||||
if (meta instanceof TropicalFishBucketMeta && ((TropicalFishBucketMeta) meta).hasVariant()) {
|
||||
iteminfo_tropical_fish.send(event.getSender(),
|
||||
"pattern", capitalizeFirstLetter(((TropicalFishBucketMeta) meta).getPattern().name()),
|
||||
"patterncolor", capitalizeFirstLetter(((TropicalFishBucketMeta) meta).getPatternColor().name()),
|
||||
"bodycolor", capitalizeFirstLetter(((TropicalFishBucketMeta) meta).getBodyColor().name())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void addMapInfo(ItemInfoEvent event) {
|
||||
if (event.getItem().hasItemMeta()) {
|
||||
ItemMeta meta = event.getItem().getItemMeta();
|
||||
if (meta instanceof MapMeta) {
|
||||
if (((MapMeta) meta).getMapView() != null) {
|
||||
MapView mapView = ((MapMeta) meta).getMapView();
|
||||
iteminfo_map_view.send(event.getSender(),
|
||||
"id", String.valueOf(mapView.getId()),
|
||||
"x", String.valueOf(mapView.getCenterX()),
|
||||
"z", String.valueOf(mapView.getCenterZ()),
|
||||
"world", mapView.getWorld() != null ? String.valueOf(mapView.getWorld().getName()) : "unknown",
|
||||
"scale", capitalizeFirstLetter(mapView.getScale().name(), '_'),
|
||||
"locked", String.valueOf(mapView.isLocked())
|
||||
);
|
||||
}
|
||||
if (((MapMeta) meta).hasLocationName()) {
|
||||
iteminfo_map_location.send(event.getSender(), "location", String.valueOf(((MapMeta) meta).getLocationName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void addPotionInfo(ItemInfoEvent event) {
|
||||
ItemStack item = event.getItem();
|
||||
|
||||
if (item.getType() != Material.POTION || item.getDurability() == 0) {
|
||||
if (!item.hasItemMeta()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Potion potion;
|
||||
|
||||
try {
|
||||
potion = Potion.fromItemStack(item);
|
||||
} catch (IllegalArgumentException ex) {
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
if (!(meta instanceof PotionMeta)) {
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder message = new StringBuilder(50);
|
||||
|
||||
message.append(ChatColor.GRAY);
|
||||
|
||||
if (potion.getType() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (potion.isSplash()) {
|
||||
message.append("Splash ");
|
||||
}
|
||||
|
||||
message.append("Potion of ");
|
||||
message.append(capitalizeFirstLetter(potion.getType().name(), '_')).append(' ');
|
||||
message.append(toRoman(potion.getLevel()));
|
||||
PotionMeta potionMeta = (PotionMeta) meta;
|
||||
|
||||
CommandSender sender = event.getSender();
|
||||
|
||||
sender.sendMessage(message.toString());
|
||||
if (potionMeta.getBasePotionType() != null) {
|
||||
StringBuilder message = new StringBuilder(50);
|
||||
|
||||
for (PotionEffect effect : potion.getEffects()) {
|
||||
sender.sendMessage(ChatColor.DARK_GRAY + capitalizeFirstLetter(effect.getType().getName(), '_') + ' ' + toTime(effect.getDuration() / 20));
|
||||
message.append(ChatColor.GRAY);
|
||||
|
||||
message.append(capitalizeFirstLetter(item.getType().name(), '_')).append(" of ");
|
||||
message.append(capitalizeFirstLetter(potionMeta.getBasePotionType().getKey().getKey(), '_')).append(' ');
|
||||
|
||||
sender.sendMessage(message.toString());
|
||||
}
|
||||
|
||||
for (PotionEffect effect : potionMeta.getCustomEffects()) {
|
||||
sender.sendMessage(ChatColor.DARK_GRAY + capitalizeFirstLetter(effect.getType().getKey().getKey(), '_')
|
||||
+ ' ' + (effect.getAmplifier() + 1) + ' ' + toTime(effect.getDuration() / 20));
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void addBookInfo(ItemInfoEvent event) {
|
||||
if (!event.getItem().hasItemMeta()) {
|
||||
return;
|
||||
}
|
||||
ItemMeta meta = event.getItem().getItemMeta();
|
||||
if (meta instanceof BookMeta) {
|
||||
BookMeta book = (BookMeta) meta;
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.Acrobot.ChestShop.ChestShop;
|
|||
import com.Acrobot.ChestShop.Events.ChestShopReloadEvent;
|
||||
import com.Acrobot.ChestShop.Events.PreTransactionEvent;
|
||||
import com.Acrobot.ChestShop.Permission;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import com.Acrobot.ChestShop.UUIDs.NameManager;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -16,14 +17,15 @@ import java.io.IOException;
|
|||
import java.math.BigDecimal;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static com.Acrobot.ChestShop.Events.TransactionEvent.TransactionType.BUY;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.PRICE_LINE;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
*/
|
||||
public class DiscountModule implements Listener {
|
||||
private static final String DISCOUNT_MESSAGE = "Applied a discount of %1$f percent for a resulting price of %2$.2f";
|
||||
private YamlConfiguration config;
|
||||
private Set<String> groupList = new HashSet<String>();
|
||||
|
||||
|
@ -43,7 +45,7 @@ public class DiscountModule implements Listener {
|
|||
try {
|
||||
config.save(ChestShop.loadFile("discounts.yml"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while loading discounts config", e);
|
||||
}
|
||||
|
||||
groupList = config.getKeys(false);
|
||||
|
@ -62,13 +64,16 @@ public class DiscountModule implements Listener {
|
|||
|
||||
Player client = event.getClient();
|
||||
|
||||
if (!PriceUtil.hasBuyPrice(event.getSign().getLine(PRICE_LINE))) {
|
||||
if (!PriceUtil.hasBuyPrice(ChestShopSign.getPrice(event.getSign()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String group : groupList) {
|
||||
if (Permission.has(client, Permission.DISCOUNT + group)) {
|
||||
event.setExactPrice(event.getExactPrice().multiply(BigDecimal.valueOf(config.getDouble(group) / 100)));
|
||||
double discount = config.getDouble(group);
|
||||
BigDecimal discountedPrice = event.getExactPrice().multiply(BigDecimal.valueOf(discount / 100));
|
||||
event.setExactPrice(discountedPrice);
|
||||
ChestShop.getBukkitLogger().info(String.format(DISCOUNT_MESSAGE, discount, discountedPrice));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static com.Acrobot.Breeze.Utils.StringUtil.getMinecraftStringWidth;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -49,7 +52,7 @@ public class ItemAliasModule implements Listener {
|
|||
configuration.options().copyDefaults(true);
|
||||
configuration.save(ChestShop.loadFile("itemAliases.yml"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while saving item aliases config", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,6 +121,13 @@ public class ItemAliasModule implements Listener {
|
|||
}
|
||||
|
||||
if (newCode != null) {
|
||||
if (event.getMaxWidth() > 0) {
|
||||
int width = getMinecraftStringWidth(newCode);
|
||||
if (width > event.getMaxWidth()) {
|
||||
ChestShop.getBukkitLogger().warning("Can't use configured alias " + newCode + " as it's width (" + width + ") was wider than the allowed max width of " + event.getMaxWidth());
|
||||
return;
|
||||
}
|
||||
}
|
||||
event.setItemString(newCode);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,18 @@
|
|||
package com.Acrobot.ChestShop.Listeners.Modules;
|
||||
|
||||
import com.Acrobot.Breeze.Utils.PriceUtil;
|
||||
import com.Acrobot.Breeze.Utils.QuantityUtil;
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
import com.Acrobot.ChestShop.Configuration.Messages;
|
||||
import com.Acrobot.ChestShop.Events.ChestShopReloadEvent;
|
||||
import com.Acrobot.ChestShop.Events.ItemParseEvent;
|
||||
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
|
||||
import com.Acrobot.ChestShop.Permission;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
@ -20,13 +23,8 @@ import java.math.BigDecimal;
|
|||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.BUY_PRICE_ABOVE_MAX;
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.BUY_PRICE_BELOW_MIN;
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.SELL_PRICE_ABOVE_MAX;
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.SELL_PRICE_BELOW_MIN;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.ITEM_LINE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.PRICE_LINE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.QUANTITY_LINE;
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.*;
|
||||
import static com.Acrobot.ChestShop.Permission.*;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -60,7 +58,7 @@ public class PriceRestrictionModule implements Listener {
|
|||
configuration.options().copyDefaults(true);
|
||||
configuration.save(ChestShop.loadFile("priceLimits.yml"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while loading priceLimits.yml", e);
|
||||
}
|
||||
} else if (!configuration.getBoolean("uses_materials")) {
|
||||
Material testMat = Material.matchMaterial("1");
|
||||
|
@ -75,7 +73,7 @@ public class PriceRestrictionModule implements Listener {
|
|||
configuration.save(file);
|
||||
ChestShop.getBukkitLogger().log(Level.INFO, "Conversion finished!");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while converting priceLimits.yml", e);
|
||||
}
|
||||
} else {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Could not convert numeric IDs in priceLimits.yml to Material names!");
|
||||
|
@ -105,9 +103,10 @@ public class PriceRestrictionModule implements Listener {
|
|||
|
||||
@EventHandler
|
||||
public void onPreShopCreation(PreShopCreationEvent event) {
|
||||
ItemParseEvent parseEvent = new ItemParseEvent(event.getSignLine(ITEM_LINE));
|
||||
ItemParseEvent parseEvent = new ItemParseEvent(ChestShopSign.getItem(event.getSignLines()));
|
||||
Bukkit.getPluginManager().callEvent(parseEvent);
|
||||
ItemStack material = parseEvent.getItem();
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (material == null) {
|
||||
return;
|
||||
|
@ -116,32 +115,45 @@ public class PriceRestrictionModule implements Listener {
|
|||
String itemType = material.getType().toString().toLowerCase(Locale.ROOT);
|
||||
int amount;
|
||||
try {
|
||||
amount = QuantityUtil.parseQuantity(event.getSignLine(QUANTITY_LINE));
|
||||
amount = ChestShopSign.getQuantity(event.getSignLines());
|
||||
} catch (IllegalArgumentException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (PriceUtil.hasBuyPrice(event.getSignLine(PRICE_LINE))) {
|
||||
BigDecimal buyPrice = PriceUtil.getExactBuyPrice(event.getSignLine(PRICE_LINE));
|
||||
String priceLine = ChestShopSign.getPrice(event.getSignLines());
|
||||
if (PriceUtil.hasBuyPrice(priceLine)) {
|
||||
BigDecimal buyPrice = PriceUtil.getExactBuyPrice(priceLine);
|
||||
|
||||
if (isValid("min.buy_price." + itemType) && buyPrice.compareTo(BigDecimal.valueOf(configuration.getDouble("min.buy_price." + itemType) * amount)) < 0) {
|
||||
BigDecimal minBuyPrice = BigDecimal.valueOf(configuration.getDouble("min.buy_price." + itemType) * amount);
|
||||
if (isValid("min.buy_price." + itemType) && buyPrice.compareTo(minBuyPrice) < 0
|
||||
&& !Permission.has(player, NOLIMIT_MIN_BUY) && !Permission.has(player, NOLIMIT_MIN_BUY_ID + itemType)) {
|
||||
event.setOutcome(BUY_PRICE_BELOW_MIN);
|
||||
Messages.BUY_PRICE_BELOW_MIN.sendWithPrefix(player, "price", buyPrice.toPlainString(), "minprice", minBuyPrice.toPlainString());
|
||||
}
|
||||
|
||||
if (isValid("max.buy_price." + itemType) && buyPrice.compareTo(BigDecimal.valueOf(configuration.getDouble("max.buy_price." + itemType) * amount)) > 0) {
|
||||
BigDecimal maxBuyPrice = BigDecimal.valueOf(configuration.getDouble("max.buy_price." + itemType) * amount);
|
||||
if (isValid("max.buy_price." + itemType) && buyPrice.compareTo(maxBuyPrice) > 0
|
||||
&& !Permission.has(player, NOLIMIT_MAX_BUY) && !Permission.has(player, NOLIMIT_MAX_BUY_ID + itemType)) {
|
||||
event.setOutcome(BUY_PRICE_ABOVE_MAX);
|
||||
Messages.BUY_PRICE_ABOVE_MAX.sendWithPrefix(player, "price", buyPrice.toPlainString(), "maxprice", maxBuyPrice.toPlainString());
|
||||
}
|
||||
}
|
||||
|
||||
if (PriceUtil.hasSellPrice(event.getSignLine(PRICE_LINE))) {
|
||||
BigDecimal sellPrice = PriceUtil.getExactSellPrice(event.getSignLine(PRICE_LINE));
|
||||
if (PriceUtil.hasSellPrice(priceLine)) {
|
||||
BigDecimal sellPrice = PriceUtil.getExactSellPrice(priceLine);
|
||||
|
||||
if (isValid("min.sell_price." + itemType) && sellPrice.compareTo(BigDecimal.valueOf(configuration.getDouble("min.sell_price." + itemType) * amount)) < 0) {
|
||||
BigDecimal minSellPrice = BigDecimal.valueOf(configuration.getDouble("min.sell_price." + itemType) * amount);
|
||||
if (isValid("min.sell_price." + itemType) && sellPrice.compareTo(minSellPrice) < 0
|
||||
&& !Permission.has(player, NOLIMIT_MIN_SELL) && !Permission.has(player, NOLIMIT_MIN_SELL_ID + itemType)) {
|
||||
event.setOutcome(SELL_PRICE_BELOW_MIN);
|
||||
Messages.SELL_PRICE_BELOW_MIN.sendWithPrefix(player, "price", sellPrice.toPlainString(), "minprice", minSellPrice.toPlainString());
|
||||
}
|
||||
|
||||
if (isValid("max.sell_price." + itemType) && sellPrice.compareTo(BigDecimal.valueOf(configuration.getDouble("max.sell_price." + itemType) * amount)) > 0) {
|
||||
BigDecimal maxSellPrice = BigDecimal.valueOf(configuration.getDouble("max.sell_price." + itemType) * amount);
|
||||
if (isValid("max.sell_price." + itemType) && sellPrice.compareTo(maxSellPrice) > 0
|
||||
&& !Permission.has(player, NOLIMIT_MAX_SELL) && !Permission.has(player, NOLIMIT_MAX_SELL_ID + itemType)) {
|
||||
event.setOutcome(SELL_PRICE_ABOVE_MAX);
|
||||
Messages.SELL_PRICE_ABOVE_MAX.sendWithPrefix(player, "price", sellPrice.toPlainString(), "maxprice", maxSellPrice.toPlainString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.Acrobot.ChestShop.Listeners.Modules;
|
||||
|
||||
import com.Acrobot.Breeze.Utils.InventoryUtil;
|
||||
import com.Acrobot.Breeze.Utils.MaterialUtil;
|
||||
import com.Acrobot.Breeze.Utils.QuantityUtil;
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
|
@ -10,6 +11,7 @@ import com.Acrobot.ChestShop.Events.TransactionEvent;
|
|||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import com.Acrobot.ChestShop.Utils.uBlock;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.Container;
|
||||
import org.bukkit.block.Sign;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
@ -18,13 +20,12 @@ import org.bukkit.event.Listener;
|
|||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.IllegalFormatException;
|
||||
|
||||
import static com.Acrobot.Breeze.Utils.ImplementationAdapter.getHolder;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.ITEM_LINE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.QUANTITY_LINE;
|
||||
|
||||
|
||||
|
@ -38,17 +39,17 @@ public class StockCounterModule implements Listener {
|
|||
public static void onPreShopCreation(PreShopCreationEvent event) {
|
||||
int quantity;
|
||||
try {
|
||||
quantity = QuantityUtil.parseQuantity(event.getSignLine(QUANTITY_LINE));
|
||||
quantity = ChestShopSign.getQuantity(event.getSignLines());
|
||||
} catch (IllegalArgumentException invalidQuantity) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (QuantityUtil.quantityLineContainsCounter(event.getSignLine(QUANTITY_LINE))) {
|
||||
if (QuantityUtil.quantityLineContainsCounter(ChestShopSign.getQuantityLine(event.getSignLines()))) {
|
||||
event.setSignLine(QUANTITY_LINE, Integer.toString(quantity));
|
||||
}
|
||||
|
||||
if (!Properties.USE_STOCK_COUNTER
|
||||
|| (Properties.FORCE_UNLIMITED_ADMIN_SHOP && ChestShopSign.isAdminShop(event.getSignLine(NAME_LINE)))) {
|
||||
|| (Properties.FORCE_UNLIMITED_ADMIN_SHOP && ChestShopSign.isAdminShop(event.getSignLines()))) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -57,7 +58,7 @@ public class StockCounterModule implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
ItemStack itemTradedByShop = determineItemTradedByShop(event.getSignLine(ITEM_LINE));
|
||||
ItemStack itemTradedByShop = determineItemTradedByShop(ChestShopSign.getItem(event.getSignLines()));
|
||||
if (itemTradedByShop != null) {
|
||||
Container container = uBlock.findConnectedContainer(event.getSign());
|
||||
if (container != null) {
|
||||
|
@ -68,14 +69,19 @@ public class StockCounterModule implements Listener {
|
|||
|
||||
@EventHandler
|
||||
public static void onInventoryClose(InventoryCloseEvent event) {
|
||||
if (event.getInventory().getType() == InventoryType.ENDER_CHEST || event.getInventory().getLocation() == null || !uBlock.couldBeShopContainer(event.getInventory().getLocation().getBlock())) {
|
||||
if (event.getInventory().getType() == InventoryType.ENDER_CHEST || event.getInventory().getLocation() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Sign shopSign : uBlock.findConnectedShopSigns(getHolder(event.getInventory(), false))) {
|
||||
InventoryHolder holder = getHolder(event.getInventory(), false);
|
||||
if (!uBlock.couldBeShopContainer(holder)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (Sign shopSign : uBlock.findConnectedShopSigns(holder)) {
|
||||
if (!Properties.USE_STOCK_COUNTER
|
||||
|| (Properties.FORCE_UNLIMITED_ADMIN_SHOP && ChestShopSign.isAdminShop(shopSign))) {
|
||||
if (QuantityUtil.quantityLineContainsCounter(shopSign.getLine(QUANTITY_LINE))) {
|
||||
if (QuantityUtil.quantityLineContainsCounter(ChestShopSign.getQuantityLine(shopSign))) {
|
||||
removeCounterFromQuantityLine(shopSign);
|
||||
}
|
||||
continue;
|
||||
|
@ -83,7 +89,7 @@ public class StockCounterModule implements Listener {
|
|||
|
||||
if (Properties.MAX_SHOP_AMOUNT > 99999) {
|
||||
ChestShop.getBukkitLogger().warning("Stock counter cannot be used if MAX_SHOP_AMOUNT is over 5 digits");
|
||||
if (QuantityUtil.quantityLineContainsCounter(shopSign.getLine(QUANTITY_LINE))) {
|
||||
if (QuantityUtil.quantityLineContainsCounter(ChestShopSign.getQuantityLine(shopSign))) {
|
||||
removeCounterFromQuantityLine(shopSign);
|
||||
}
|
||||
return;
|
||||
|
@ -95,8 +101,9 @@ public class StockCounterModule implements Listener {
|
|||
|
||||
@EventHandler(priority = EventPriority.HIGH)
|
||||
public static void onTransaction(final TransactionEvent event) {
|
||||
String quantityLine = ChestShopSign.getQuantityLine(event.getSign());
|
||||
if (!Properties.USE_STOCK_COUNTER) {
|
||||
if (QuantityUtil.quantityLineContainsCounter(event.getSign().getLine(QUANTITY_LINE))) {
|
||||
if (QuantityUtil.quantityLineContainsCounter(quantityLine)) {
|
||||
removeCounterFromQuantityLine(event.getSign());
|
||||
}
|
||||
return;
|
||||
|
@ -104,7 +111,7 @@ public class StockCounterModule implements Listener {
|
|||
|
||||
if (Properties.MAX_SHOP_AMOUNT > 99999) {
|
||||
ChestShop.getBukkitLogger().warning("Stock counter cannot be used if MAX_SHOP_AMOUNT is over 5 digits");
|
||||
if (QuantityUtil.quantityLineContainsCounter(event.getSign().getLine(QUANTITY_LINE))) {
|
||||
if (QuantityUtil.quantityLineContainsCounter(quantityLine)) {
|
||||
removeCounterFromQuantityLine(event.getSign());
|
||||
}
|
||||
return;
|
||||
|
@ -119,7 +126,13 @@ public class StockCounterModule implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
public static void updateCounterOnQuantityLine(Sign sign, Inventory chestShopInventory) {
|
||||
/**
|
||||
* Update the stock counter on the sign's quantity line
|
||||
* @param sign The sign to update
|
||||
* @param chestShopInventory The inventory to search in
|
||||
* @param extraItems The extra items to add in the search
|
||||
*/
|
||||
public static void updateCounterOnQuantityLine(Sign sign, Inventory chestShopInventory, ItemStack... extraItems) {
|
||||
ItemStack itemTradedByShop = determineItemTradedByShop(sign);
|
||||
if (itemTradedByShop == null) {
|
||||
return;
|
||||
|
@ -127,21 +140,36 @@ public class StockCounterModule implements Listener {
|
|||
|
||||
int quantity;
|
||||
try {
|
||||
quantity = QuantityUtil.parseQuantity(sign.getLine(QUANTITY_LINE));
|
||||
quantity = ChestShopSign.getQuantity(sign);
|
||||
} catch (IllegalFormatException invalidQuantity) {
|
||||
return;
|
||||
}
|
||||
|
||||
int numTradedItemsInChest = InventoryUtil.getAmount(itemTradedByShop, chestShopInventory);
|
||||
|
||||
for (ItemStack extraStack : extraItems) {
|
||||
if (!MaterialUtil.equals(extraStack, itemTradedByShop)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
numTradedItemsInChest += extraStack.getAmount();
|
||||
}
|
||||
|
||||
sign.setLine(QUANTITY_LINE, String.format(PRICE_LINE_WITH_COUNT, quantity, numTradedItemsInChest));
|
||||
sign.update(true);
|
||||
}
|
||||
|
||||
public static void updateCounterOnItemMoveEvent(ItemStack toAdd, InventoryHolder destinationHolder) {
|
||||
Block shopBlock = ChestShopSign.getShopBlock(destinationHolder);
|
||||
Sign connectedSign = uBlock.getConnectedSign(shopBlock);
|
||||
|
||||
updateCounterOnQuantityLine(connectedSign, destinationHolder.getInventory(), toAdd);
|
||||
}
|
||||
|
||||
public static void removeCounterFromQuantityLine(Sign sign) {
|
||||
int quantity;
|
||||
try {
|
||||
quantity = QuantityUtil.parseQuantity(sign.getLine(QUANTITY_LINE));
|
||||
quantity = ChestShopSign.getQuantity(sign);
|
||||
} catch (IllegalFormatException invalidQuantity) {
|
||||
return;
|
||||
}
|
||||
|
@ -157,7 +185,7 @@ public class StockCounterModule implements Listener {
|
|||
}
|
||||
|
||||
public static ItemStack determineItemTradedByShop(Sign sign) {
|
||||
return determineItemTradedByShop(sign.getLine(ITEM_LINE));
|
||||
return determineItemTradedByShop(ChestShopSign.getItem(sign));
|
||||
}
|
||||
|
||||
public static ItemStack determineItemTradedByShop(String material) {
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package com.Acrobot.ChestShop.Listeners.Player;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
@ -23,7 +22,7 @@ public class PlayerConnect implements Listener {
|
|||
|
||||
final PlayerDTO playerDTO = new PlayerDTO(event.getPlayer());
|
||||
|
||||
Bukkit.getScheduler().runTaskAsynchronously(ChestShop.getPlugin(), () -> {
|
||||
ChestShop.runInAsyncThread(() -> {
|
||||
if (NameManager.getAccount(playerDTO.getUniqueId()) != null) {
|
||||
NameManager.storeUsername(playerDTO);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.bukkit.inventory.ItemStack;
|
|||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
|
||||
|
@ -81,7 +82,7 @@ public class PlayerInteract implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
if (!isSign(block) || player.getInventory().getItemInMainHand().getType().name().contains("SIGN")) // Blocking accidental sign edition
|
||||
if (!isSign(block))
|
||||
return;
|
||||
|
||||
Sign sign = (Sign) getState(block, false);
|
||||
|
@ -89,10 +90,11 @@ public class PlayerInteract implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
if (Properties.ALLOW_AUTO_ITEM_FILL && ChatColor.stripColor(sign.getLine(ITEM_LINE)).equals(AUTOFILL_CODE)) {
|
||||
if (Properties.ALLOW_AUTO_ITEM_FILL && ChatColor.stripColor(ChestShopSign.getItem(sign)).equals(AUTOFILL_CODE)) {
|
||||
if (ChestShopSign.hasPermission(player, OTHER_NAME_CREATE, sign)) {
|
||||
ItemStack item = player.getInventory().getItemInMainHand();
|
||||
if (!MaterialUtil.isEmpty(item)) {
|
||||
event.setCancelled(true);
|
||||
String itemCode;
|
||||
try {
|
||||
itemCode = ItemUtil.getSignName(item);
|
||||
|
@ -108,11 +110,10 @@ public class PlayerInteract implements Listener {
|
|||
com.Acrobot.ChestShop.ChestShop.callEvent(changeEvent);
|
||||
if (!changeEvent.isCancelled()) {
|
||||
for (byte i = 0; i < changeEvent.getLines().length; ++i) {
|
||||
sign.setLine(i, changeEvent.getLine(i));
|
||||
String line = changeEvent.getLine(i);
|
||||
sign.setLine(i, line != null ? line : "");
|
||||
}
|
||||
sign.update();
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
} else {
|
||||
Messages.NO_ITEM_IN_HAND.sendWithPrefix(player);
|
||||
|
@ -125,6 +126,18 @@ public class PlayerInteract implements Listener {
|
|||
|
||||
if (!AccessToggle.isIgnoring(player) && ChestShopSign.canAccess(player, sign) && !ChestShopSign.isAdminShop(sign)) {
|
||||
if (Properties.IGNORE_ACCESS_PERMS || ChestShopSign.isOwner(player, sign)) {
|
||||
if (player.getInventory().getItemInMainHand().getType().name().contains("SIGN") && action == RIGHT_CLICK_BLOCK) {
|
||||
// Allow editing of sign (if supported)
|
||||
return;
|
||||
} else if ((player.getInventory().getItemInMainHand().getType().name().endsWith("DYE")
|
||||
|| player.getInventory().getItemInMainHand().getType().name().endsWith("INK_SAC"))
|
||||
&& action == RIGHT_CLICK_BLOCK) {
|
||||
if (Properties.SIGN_DYING) {
|
||||
return;
|
||||
} else {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
if (Properties.ALLOW_SIGN_CHEST_OPEN && !(Properties.IGNORE_CREATIVE_MODE && player.getGameMode() == GameMode.CREATIVE)) {
|
||||
if (player.isSneaking() || player.isInsideVehicle()
|
||||
|| (Properties.ALLOW_LEFT_CLICK_DESTROYING && action == LEFT_CLICK_BLOCK)) {
|
||||
|
@ -136,6 +149,10 @@ public class PlayerInteract implements Listener {
|
|||
}
|
||||
// don't allow owners or people with access to buy/sell at this shop
|
||||
Messages.TRADE_DENIED_ACCESS_PERMS.sendWithPrefix(player);
|
||||
if (action == RIGHT_CLICK_BLOCK) {
|
||||
// don't allow editing
|
||||
event.setCancelled(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -165,10 +182,9 @@ public class PlayerInteract implements Listener {
|
|||
}
|
||||
|
||||
private static PreTransactionEvent preparePreTransactionEvent(Sign sign, Player player, Action action) {
|
||||
String name = sign.getLine(NAME_LINE);
|
||||
String quantity = sign.getLine(QUANTITY_LINE);
|
||||
String prices = sign.getLine(PRICE_LINE);
|
||||
String material = sign.getLine(ITEM_LINE);
|
||||
String name = ChestShopSign.getOwner(sign);
|
||||
String prices = ChestShopSign.getPrice(sign);
|
||||
String material = ChestShopSign.getItem(sign);
|
||||
|
||||
AccountQueryEvent accountQueryEvent = new AccountQueryEvent(name);
|
||||
Bukkit.getPluginManager().callEvent(accountQueryEvent);
|
||||
|
@ -206,31 +222,32 @@ public class PlayerInteract implements Listener {
|
|||
|
||||
int amount = -1;
|
||||
try {
|
||||
amount = QuantityUtil.parseQuantity(quantity);
|
||||
} catch (NumberFormatException notANumber) {}
|
||||
amount = ChestShopSign.getQuantity(sign);
|
||||
} catch (NumberFormatException ignored) {} // There is no quantity number on the sign
|
||||
|
||||
if (amount < 1 || amount > Properties.MAX_SHOP_AMOUNT) {
|
||||
Messages.INVALID_SHOP_PRICE.sendWithPrefix(player);
|
||||
return null;
|
||||
}
|
||||
|
||||
BigDecimal pricePerItem = price.divide(BigDecimal.valueOf(amount), MathContext.DECIMAL128);
|
||||
if (Properties.SHIFT_SELLS_IN_STACKS && player.isSneaking() && !price.equals(PriceUtil.NO_PRICE) && isAllowedForShift(action == buy)) {
|
||||
int newAmount = adminShop ? InventoryUtil.getMaxStackSize(item) : getStackAmount(item, ownerInventory, player, action);
|
||||
if (newAmount > 0) {
|
||||
price = price.divide(BigDecimal.valueOf(amount), MathContext.DECIMAL128).multiply(BigDecimal.valueOf(newAmount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP);
|
||||
price = pricePerItem.multiply(BigDecimal.valueOf(newAmount)).setScale(Properties.PRICE_PRECISION, RoundingMode.HALF_UP);
|
||||
amount = newAmount;
|
||||
}
|
||||
} else if (Properties.SHIFT_SELLS_EVERYTHING && player.isSneaking() && !price.equals(PriceUtil.NO_PRICE) && isAllowedForShift(action == buy)) {
|
||||
if (action != buy) {
|
||||
int newAmount = InventoryUtil.getAmount(item, player.getInventory());
|
||||
if (newAmount > 0) {
|
||||
price = price.divide(BigDecimal.valueOf(amount), MathContext.DECIMAL128).multiply(BigDecimal.valueOf(newAmount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP);
|
||||
price = pricePerItem.multiply(BigDecimal.valueOf(newAmount)).setScale(Properties.PRICE_PRECISION, RoundingMode.HALF_UP);
|
||||
amount = newAmount;
|
||||
}
|
||||
} else if (!adminShop && ownerInventory != null) {
|
||||
int newAmount = InventoryUtil.getAmount(item, ownerInventory);
|
||||
if (newAmount > 0) {
|
||||
price = price.divide(BigDecimal.valueOf(amount), MathContext.DECIMAL128).multiply(BigDecimal.valueOf(newAmount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP);
|
||||
price = pricePerItem.multiply(BigDecimal.valueOf(newAmount)).setScale(Properties.PRICE_PRECISION, RoundingMode.HALF_UP);
|
||||
amount = newAmount;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,8 +46,14 @@ public class PlayerInventory implements Listener {
|
|||
List<Block> containers = new ArrayList<>();
|
||||
|
||||
if (holder instanceof DoubleChest) {
|
||||
containers.add(((BlockState) ((DoubleChest) holder).getLeftSide()).getBlock());
|
||||
containers.add(((BlockState) ((DoubleChest) holder).getRightSide()).getBlock());
|
||||
InventoryHolder leftSide = ((DoubleChest) holder).getLeftSide();
|
||||
if (leftSide instanceof BlockState) {
|
||||
containers.add(((BlockState) leftSide).getBlock());
|
||||
}
|
||||
InventoryHolder rightSide = ((DoubleChest) holder).getRightSide();
|
||||
if (rightSide instanceof BlockState) {
|
||||
containers.add(((BlockState) rightSide).getBlock());
|
||||
}
|
||||
} else {
|
||||
containers.add(((BlockState) holder).getBlock());
|
||||
}
|
||||
|
|
|
@ -8,8 +8,6 @@ import org.bukkit.event.EventHandler;
|
|||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.*;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
*/
|
||||
|
@ -18,25 +16,23 @@ public class ShopCreationLogger implements Listener {
|
|||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public static void onShopCreation(final ShopCreatedEvent event) {
|
||||
ChestShop.getBukkitServer().getScheduler().runTaskAsynchronously(ChestShop.getPlugin(), new Runnable() {
|
||||
@Override public void run() {
|
||||
String creator = event.getPlayer().getName();
|
||||
String shopOwner = event.getSignLine(NAME_LINE);
|
||||
String typeOfShop = ChestShopSign.isAdminShop(shopOwner) ? "an Admin Shop" : "a shop" + (event.createdByOwner() ? "" : " for " + event.getOwnerAccount().getName());
|
||||
ChestShop.runInAsyncThread(() -> {
|
||||
String creator = event.getPlayer().getName();
|
||||
String shopOwner = ChestShopSign.getOwner(event.getSignLines());
|
||||
String typeOfShop = ChestShopSign.isAdminShop(shopOwner) ? "an Admin Shop" : "a shop" + (event.createdByOwner() ? "" : " for " + event.getOwnerAccount().getName());
|
||||
|
||||
String item = event.getSignLine(QUANTITY_LINE) + ' ' + event.getSignLine(ITEM_LINE);
|
||||
String prices = event.getSignLine(PRICE_LINE);
|
||||
String location = LocationUtil.locationToString(event.getSign().getLocation());
|
||||
String item = ChestShopSign.getQuantity(event.getSignLines()) + ' ' + ChestShopSign.getItem(event.getSignLines());
|
||||
String prices = ChestShopSign.getPrice(event.getSignLines());
|
||||
String location = LocationUtil.locationToString(event.getSign().getLocation());
|
||||
|
||||
String message = String.format(CREATION_MESSAGE,
|
||||
creator,
|
||||
typeOfShop,
|
||||
item,
|
||||
prices,
|
||||
location);
|
||||
String message = String.format(CREATION_MESSAGE,
|
||||
creator,
|
||||
typeOfShop,
|
||||
item,
|
||||
prices,
|
||||
location);
|
||||
|
||||
ChestShop.getBukkitLogger().info(message);
|
||||
}
|
||||
ChestShop.getShopLogger().info(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@ import org.bukkit.block.data.type.WallSign;
|
|||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
*/
|
||||
|
@ -26,7 +24,7 @@ public class SignSticker implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
if (ChestShopSign.isAdminShop(event.getSignLine(NAME_LINE))) {
|
||||
if (ChestShopSign.isAdminShop(event.getSignLines())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,8 @@ public class EconomicModule implements Listener {
|
|||
event.getExactPrice(),
|
||||
event.getClient(),
|
||||
event.getOwnerAccount().getUuid(),
|
||||
event.getTransactionType() == BUY ? CurrencyTransferEvent.Direction.PARTNER : CurrencyTransferEvent.Direction.INITIATOR
|
||||
event.getTransactionType() == BUY ? CurrencyTransferEvent.Direction.PARTNER : CurrencyTransferEvent.Direction.INITIATOR,
|
||||
event
|
||||
);
|
||||
ChestShop.callEvent(currencyTransferEvent);
|
||||
if (!currencyTransferEvent.wasHandled()) {
|
||||
|
|
|
@ -52,7 +52,9 @@ public class EmptyShopDeleter implements Listener {
|
|||
sign.getBlock().setType(Material.AIR);
|
||||
|
||||
if (Properties.REMOVE_EMPTY_CHESTS && !ChestShopSign.isAdminShop(ownerInventory) && InventoryUtil.isEmpty(ownerInventory)) {
|
||||
connectedContainer.getBlock().setType(Material.AIR);
|
||||
if (connectedContainer != null) {
|
||||
connectedContainer.getBlock().setType(Material.AIR);
|
||||
}
|
||||
} else {
|
||||
if (!signType.isItem()) {
|
||||
try {
|
||||
|
|
|
@ -36,6 +36,6 @@ public class TransactionLogger implements Listener {
|
|||
event.getOwnerAccount().getName(),
|
||||
LocationUtil.locationToString(event.getSign().getLocation()));
|
||||
|
||||
ChestShop.getBukkitLogger().info(message);
|
||||
ChestShop.getShopLogger().info(message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.Acrobot.ChestShop.Commands.Toggle;
|
|||
import com.Acrobot.ChestShop.Configuration.Messages;
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Economy.Economy;
|
||||
import com.Acrobot.ChestShop.Events.Economy.CurrencyTransferEvent;
|
||||
import com.Acrobot.ChestShop.Events.TransactionEvent;
|
||||
import com.Acrobot.ChestShop.Utils.ItemUtil;
|
||||
import org.bukkit.Bukkit;
|
||||
|
@ -15,6 +16,7 @@ import org.bukkit.event.EventHandler;
|
|||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -23,65 +25,87 @@ import java.util.Map;
|
|||
*/
|
||||
public class TransactionMessageSender implements Listener {
|
||||
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
|
||||
public static void onTransaction(TransactionEvent event) {
|
||||
if (event.getTransactionType() == TransactionEvent.TransactionType.BUY) {
|
||||
public static void onCurrencyTransfer(CurrencyTransferEvent event) {
|
||||
if (event.getTransactionEvent() == null) {
|
||||
return;
|
||||
}
|
||||
if (event.getTransactionEvent().getTransactionType() == TransactionEvent.TransactionType.BUY) {
|
||||
sendBuyMessage(event);
|
||||
} else {
|
||||
sendSellMessage(event);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void sendBuyMessage(TransactionEvent event) {
|
||||
Player player = event.getClient();
|
||||
protected static void sendBuyMessage(CurrencyTransferEvent event) {
|
||||
TransactionEvent transactionEvent = event.getTransactionEvent();
|
||||
Player player = transactionEvent.getClient();
|
||||
|
||||
if (Properties.SHOW_TRANSACTION_INFORMATION_CLIENT) {
|
||||
sendMessage(player, event.getClient().getName(), Messages.YOU_BOUGHT_FROM_SHOP, event, "owner", event.getOwnerAccount().getName());
|
||||
sendMessage(player, transactionEvent.getClient().getName(), Messages.YOU_BOUGHT_FROM_SHOP, event, MessageTarget.BUYER, "owner", transactionEvent.getOwnerAccount().getName());
|
||||
}
|
||||
|
||||
if (Properties.SHOW_TRANSACTION_INFORMATION_OWNER && !Toggle.isIgnoring(event.getOwnerAccount().getUuid())) {
|
||||
Player owner = Bukkit.getPlayer(event.getOwnerAccount().getUuid());
|
||||
sendMessage(owner, event.getOwnerAccount().getName(), Messages.SOMEBODY_BOUGHT_FROM_YOUR_SHOP, event, "buyer", player.getName());
|
||||
if (Properties.SHOW_TRANSACTION_INFORMATION_OWNER && !Toggle.isIgnoring(transactionEvent.getOwnerAccount().getUuid())) {
|
||||
Player owner = Bukkit.getPlayer(transactionEvent.getOwnerAccount().getUuid());
|
||||
sendMessage(owner, transactionEvent.getOwnerAccount().getName(), Messages.SOMEBODY_BOUGHT_FROM_YOUR_SHOP, event, MessageTarget.SELLER, "buyer", player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
protected static void sendSellMessage(TransactionEvent event) {
|
||||
Player player = event.getClient();
|
||||
|
||||
protected static void sendSellMessage(CurrencyTransferEvent event) {
|
||||
TransactionEvent transactionEvent = event.getTransactionEvent();
|
||||
Player player = transactionEvent.getClient();
|
||||
|
||||
if (Properties.SHOW_TRANSACTION_INFORMATION_CLIENT) {
|
||||
sendMessage(player, event.getClient().getName(), Messages.YOU_SOLD_TO_SHOP, event, "buyer", event.getOwnerAccount().getName());
|
||||
sendMessage(player, transactionEvent.getClient().getName(), Messages.YOU_SOLD_TO_SHOP, event, MessageTarget.SELLER, "buyer", transactionEvent.getOwnerAccount().getName());
|
||||
}
|
||||
|
||||
if (Properties.SHOW_TRANSACTION_INFORMATION_OWNER && !Toggle.isIgnoring(event.getOwnerAccount().getUuid())) {
|
||||
Player owner = Bukkit.getPlayer(event.getOwnerAccount().getUuid());
|
||||
sendMessage(owner, event.getOwnerAccount().getName(), Messages.SOMEBODY_SOLD_TO_YOUR_SHOP, event, "seller", player.getName());
|
||||
if (Properties.SHOW_TRANSACTION_INFORMATION_OWNER && !Toggle.isIgnoring(transactionEvent.getOwnerAccount().getUuid())) {
|
||||
Player owner = Bukkit.getPlayer(transactionEvent.getOwnerAccount().getUuid());
|
||||
sendMessage(owner, transactionEvent.getOwnerAccount().getName(), Messages.SOMEBODY_SOLD_TO_YOUR_SHOP, event, MessageTarget.BUYER, "seller", player.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private static void sendMessage(Player player, String playerName, Messages.Message rawMessage, TransactionEvent event, String... replacements) {
|
||||
Location loc = event.getSign().getLocation();
|
||||
|
||||
private static void sendMessage(Player player, String playerName, Messages.Message rawMessage, CurrencyTransferEvent event, MessageTarget messageTarget, String... replacements) {
|
||||
TransactionEvent transactionEvent = event.getTransactionEvent();
|
||||
|
||||
BigDecimal actualAmount = getTransactionActualAmount(event, messageTarget);
|
||||
|
||||
Location loc = transactionEvent.getSign().getLocation();
|
||||
Map<String, String> replacementMap = new LinkedHashMap<>();
|
||||
replacementMap.put("price", Economy.formatBalance(event.getExactPrice()));
|
||||
replacementMap.put("price", Economy.formatBalance(actualAmount));
|
||||
replacementMap.put("world", loc.getWorld().getName());
|
||||
replacementMap.put("x", String.valueOf(loc.getBlockX()));
|
||||
replacementMap.put("y", String.valueOf(loc.getBlockY()));
|
||||
replacementMap.put("z", String.valueOf(loc.getBlockZ()));
|
||||
replacementMap.put("material", "%item");
|
||||
|
||||
for (int i = 0; i + 1 < replacements.length; i+=2) {
|
||||
|
||||
for (int i = 0; i + 1 < replacements.length; i += 2) {
|
||||
replacementMap.put(replacements[i], replacements[i + 1]);
|
||||
}
|
||||
|
||||
if (Properties.SHOWITEM_MESSAGE && MaterialUtil.Show.sendMessage(player, playerName, rawMessage, event.getStock(), replacementMap)) {
|
||||
if (Properties.SHOWITEM_MESSAGE && MaterialUtil.Show.sendMessage(player, playerName, rawMessage, transactionEvent.getStock(), replacementMap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (player != null) {
|
||||
replacementMap.put("item", ItemUtil.getItemList(event.getStock()));
|
||||
replacementMap.put("item", ItemUtil.getItemList(transactionEvent.getStock()));
|
||||
rawMessage.sendWithPrefix(player, replacementMap);
|
||||
} else if (playerName != null) {
|
||||
replacementMap.put("item", ItemUtil.getItemList(event.getStock()));
|
||||
replacementMap.put("item", ItemUtil.getItemList(transactionEvent.getStock()));
|
||||
ChestShop.sendBungeeMessage(playerName, rawMessage, replacementMap);
|
||||
}
|
||||
}
|
||||
|
||||
private static BigDecimal getTransactionActualAmount(CurrencyTransferEvent event, MessageTarget messageTarget) {
|
||||
if (messageTarget == MessageTarget.SELLER) {
|
||||
return event.getAmountReceived();
|
||||
} else {
|
||||
return event.getAmountSent();
|
||||
}
|
||||
}
|
||||
|
||||
private enum MessageTarget {
|
||||
BUYER,
|
||||
SELLER
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ import org.bukkit.event.Listener;
|
|||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.NO_CHEST;
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.NO_PERMISSION_FOR_CHEST;
|
||||
import static com.Acrobot.ChestShop.Permission.ADMIN;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -23,7 +22,7 @@ public class ChestChecker implements Listener {
|
|||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public static void onPreShopCreation(PreShopCreationEvent event) {
|
||||
String nameLine = event.getSignLine(NAME_LINE);
|
||||
String nameLine = ChestShopSign.getOwner(event.getSignLines());
|
||||
|
||||
Container connectedContainer = uBlock.findConnectedContainer(event.getSign().getBlock());
|
||||
|
||||
|
|
|
@ -18,7 +18,6 @@ import org.bukkit.event.Listener;
|
|||
import java.math.BigDecimal;
|
||||
|
||||
import static com.Acrobot.ChestShop.Permission.NOFEE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -33,7 +32,7 @@ public class CreationFeeGetter implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
if (ChestShopSign.isAdminShop(event.getSignLine(NAME_LINE))) {
|
||||
if (ChestShopSign.isAdminShop(event.getSignLines())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,19 +33,7 @@ public class ErrorMessageSender implements Listener {
|
|||
message = Messages.INVALID_SHOP_QUANTITY;
|
||||
break;
|
||||
case SELL_PRICE_HIGHER_THAN_BUY_PRICE:
|
||||
message = Messages.YOU_CANNOT_CREATE_SHOP;
|
||||
break;
|
||||
case SELL_PRICE_ABOVE_MAX:
|
||||
message = Messages.SELL_PRICE_ABOVE_MAX;
|
||||
break;
|
||||
case SELL_PRICE_BELOW_MIN:
|
||||
message = Messages.SELL_PRICE_BELOW_MIN;
|
||||
break;
|
||||
case BUY_PRICE_ABOVE_MAX:
|
||||
message = Messages.BUY_PRICE_ABOVE_MAX;
|
||||
break;
|
||||
case BUY_PRICE_BELOW_MIN:
|
||||
message = Messages.BUY_PRICE_BELOW_MIN;
|
||||
message = Messages.SELL_PRICE_HIGHER_THAN_BUY_PRICE;
|
||||
break;
|
||||
case NO_CHEST:
|
||||
message = Messages.NO_CHEST_DETECTED;
|
||||
|
|
|
@ -31,7 +31,7 @@ public class ItemChecker implements Listener {
|
|||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public static void onPreShopCreation(PreShopCreationEvent event) {
|
||||
String itemCode = event.getSignLine(ITEM_LINE);
|
||||
String itemCode = ChestShopSign.getItem(event.getSignLines());
|
||||
|
||||
ItemParseEvent parseEvent = new ItemParseEvent(itemCode);
|
||||
Bukkit.getPluginManager().callEvent(parseEvent);
|
||||
|
|
|
@ -14,7 +14,6 @@ import java.math.BigDecimal;
|
|||
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.NOT_ENOUGH_MONEY;
|
||||
import static com.Acrobot.ChestShop.Permission.NOFEE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -29,7 +28,7 @@ public class MoneyChecker implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
if (ChestShopSign.isAdminShop(event.getSignLine(NAME_LINE))) {
|
||||
if (ChestShopSign.isAdminShop(event.getSignLines())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,12 +4,15 @@ import com.Acrobot.ChestShop.ChestShop;
|
|||
import com.Acrobot.ChestShop.Database.Account;
|
||||
import com.Acrobot.ChestShop.Events.AccountQueryEvent;
|
||||
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import com.Acrobot.ChestShop.UUIDs.NameManager;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static com.Acrobot.ChestShop.Permission.OTHER_NAME_CREATE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.UNKNOWN_PLAYER;
|
||||
|
@ -30,7 +33,7 @@ public class NameChecker implements Listener {
|
|||
}
|
||||
|
||||
private static void handleEvent(PreShopCreationEvent event) {
|
||||
String name = event.getSignLine(NAME_LINE);
|
||||
String name = ChestShopSign.getOwner(event.getSignLines());
|
||||
Player player = event.getPlayer();
|
||||
|
||||
Account account = event.getOwnerAccount();
|
||||
|
@ -57,7 +60,7 @@ public class NameChecker implements Listener {
|
|||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while trying to check account for name " + name + " with player " + player.getName(), e);
|
||||
}
|
||||
}
|
||||
event.setOwnerAccount(account);
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.Acrobot.Breeze.Utils.PriceUtil;
|
|||
import com.Acrobot.ChestShop.Events.ItemParseEvent;
|
||||
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
|
||||
import com.Acrobot.ChestShop.Permission;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import com.Acrobot.ChestShop.UUIDs.NameManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -15,9 +16,7 @@ import java.util.Locale;
|
|||
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.NO_PERMISSION;
|
||||
import static com.Acrobot.ChestShop.Permission.*;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.ITEM_LINE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.PRICE_LINE;
|
||||
import static org.bukkit.event.EventPriority.HIGH;
|
||||
|
||||
/**
|
||||
|
@ -36,8 +35,8 @@ public class PermissionChecker implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
String priceLine = event.getSignLine(PRICE_LINE);
|
||||
String itemLine = event.getSignLine(ITEM_LINE);
|
||||
String priceLine = ChestShopSign.getPrice(event.getSignLines());
|
||||
String itemLine = ChestShopSign.getItem(event.getSignLines());
|
||||
|
||||
ItemParseEvent parseEvent = new ItemParseEvent(itemLine);
|
||||
Bukkit.getPluginManager().callEvent(parseEvent);
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.Acrobot.ChestShop.Listeners.PreShopCreation;
|
|||
import com.Acrobot.Breeze.Utils.PriceUtil;
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
@ -20,7 +21,7 @@ public class PriceChecker implements Listener {
|
|||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public static void onPreShopCreation(PreShopCreationEvent event) {
|
||||
String line = event.getSignLine(PRICE_LINE).toUpperCase(Locale.ROOT);
|
||||
String line = ChestShopSign.getPrice(event.getSignLines()).toUpperCase(Locale.ROOT);
|
||||
if (Properties.PRICE_PRECISION <= 0) {
|
||||
line = line.replaceAll("\\.\\d*", ""); //remove too many decimal places
|
||||
} else {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.Acrobot.ChestShop.Listeners.PreShopCreation;
|
|||
|
||||
import com.Acrobot.Breeze.Utils.PriceUtil;
|
||||
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
|
@ -10,7 +11,6 @@ import java.math.BigDecimal;
|
|||
import static com.Acrobot.Breeze.Utils.PriceUtil.hasBuyPrice;
|
||||
import static com.Acrobot.Breeze.Utils.PriceUtil.hasSellPrice;
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.SELL_PRICE_HIGHER_THAN_BUY_PRICE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.PRICE_LINE;
|
||||
import static org.bukkit.event.EventPriority.HIGH;
|
||||
|
||||
/**
|
||||
|
@ -20,7 +20,7 @@ public class PriceRatioChecker implements Listener {
|
|||
|
||||
@EventHandler(priority = HIGH)
|
||||
public static void onPreShopCreation(PreShopCreationEvent event) {
|
||||
String priceLine = event.getSignLine(PRICE_LINE);
|
||||
String priceLine = ChestShopSign.getPrice(event.getSignLines());
|
||||
|
||||
if (hasBuyPrice(priceLine) && hasSellPrice(priceLine)) {
|
||||
BigDecimal buyPrice = PriceUtil.getExactBuyPrice(priceLine);
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
package com.Acrobot.ChestShop.Listeners.PreShopCreation;
|
||||
|
||||
import com.Acrobot.Breeze.Utils.QuantityUtil;
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Events.PreShopCreationEvent;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import static com.Acrobot.ChestShop.Events.PreShopCreationEvent.CreationOutcome.INVALID_QUANTITY;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.QUANTITY_LINE;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -19,8 +18,8 @@ public class QuantityChecker implements Listener {
|
|||
public static void onPreShopCreation(PreShopCreationEvent event) {
|
||||
int amount = -1;
|
||||
try {
|
||||
amount = QuantityUtil.parseQuantity(event.getSignLine(QUANTITY_LINE));
|
||||
} catch (NumberFormatException notANumber) {}
|
||||
amount = ChestShopSign.getQuantity(event.getSignLines());
|
||||
} catch (NumberFormatException ignored) {} // not a quantity on the line
|
||||
|
||||
if (amount < 1 || amount > Properties.MAX_SHOP_AMOUNT) {
|
||||
event.setOutcome(INVALID_QUANTITY);
|
||||
|
|
|
@ -52,10 +52,10 @@ public class ErrorMessageSender implements Listener {
|
|||
|
||||
switch (event.getTransactionOutcome()) {
|
||||
case SHOP_DOES_NOT_BUY_THIS_ITEM:
|
||||
message = Messages.NO_BUYING_HERE;
|
||||
message = Messages.NO_SELLING_HERE;
|
||||
break;
|
||||
case SHOP_DOES_NOT_SELL_THIS_ITEM:
|
||||
message = Messages.NO_SELLING_HERE;
|
||||
message = Messages.NO_BUYING_HERE;
|
||||
break;
|
||||
case CLIENT_DOES_NOT_HAVE_PERMISSION:
|
||||
message = Messages.NO_PERMISSION;
|
||||
|
|
|
@ -59,7 +59,13 @@ public class PartialTransactionModule implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
event.setExactPrice(pricePerItem.multiply(new BigDecimal(amountAffordable)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP));
|
||||
BigDecimal pricePerItemScaled = pricePerItem.multiply(new BigDecimal(amountAffordable)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP);
|
||||
if (pricePerItem.compareTo(BigDecimal.ZERO) > 0 && pricePerItemScaled.compareTo(BigDecimal.ZERO) == 0) {
|
||||
event.setCancelled(CLIENT_DOES_NOT_HAVE_ENOUGH_MONEY);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setExactPrice(pricePerItemScaled);
|
||||
event.setStock(getCountedItemStack(event.getStock(), amountAffordable));
|
||||
}
|
||||
|
||||
|
@ -72,7 +78,13 @@ public class PartialTransactionModule implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
event.setExactPrice(pricePerItem.multiply(BigDecimal.valueOf(possessedItemCount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP));
|
||||
BigDecimal pricePerItemScaled = pricePerItem.multiply(new BigDecimal(possessedItemCount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP);
|
||||
if (pricePerItem.compareTo(BigDecimal.ZERO) > 0 && pricePerItemScaled.compareTo(BigDecimal.ZERO) == 0) {
|
||||
event.setCancelled(NOT_ENOUGH_STOCK_IN_CHEST);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setExactPrice(pricePerItemScaled);
|
||||
event.setStock(itemsHad);
|
||||
}
|
||||
|
||||
|
@ -84,8 +96,14 @@ public class PartialTransactionModule implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
BigDecimal pricePerItemScaled = pricePerItem.multiply(new BigDecimal(possessedItemCount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP);
|
||||
if (pricePerItem.compareTo(BigDecimal.ZERO) > 0 && pricePerItemScaled.compareTo(BigDecimal.ZERO) == 0) {
|
||||
event.setCancelled(NOT_ENOUGH_SPACE_IN_INVENTORY);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setExactPrice(pricePerItemScaled);
|
||||
event.setStock(itemsFit);
|
||||
event.setExactPrice(pricePerItem.multiply(BigDecimal.valueOf(possessedItemCount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP));
|
||||
}
|
||||
|
||||
UUID seller = event.getOwnerAccount().getUuid();
|
||||
|
@ -126,7 +144,13 @@ public class PartialTransactionModule implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
event.setExactPrice(pricePerItem.multiply(BigDecimal.valueOf(amountAffordable)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP));
|
||||
BigDecimal pricePerItemScaled = pricePerItem.multiply(new BigDecimal(amountAffordable)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP);
|
||||
if (pricePerItem.compareTo(BigDecimal.ZERO) > 0 && pricePerItemScaled.compareTo(BigDecimal.ZERO) == 0) {
|
||||
event.setCancelled(SHOP_DOES_NOT_HAVE_ENOUGH_MONEY);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setExactPrice(pricePerItemScaled);
|
||||
event.setStock(getCountedItemStack(event.getStock(), amountAffordable));
|
||||
}
|
||||
}
|
||||
|
@ -140,7 +164,13 @@ public class PartialTransactionModule implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
event.setExactPrice(pricePerItem.multiply(BigDecimal.valueOf(possessedItemCount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP));
|
||||
BigDecimal pricePerItemScaled = pricePerItem.multiply(new BigDecimal(possessedItemCount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP);
|
||||
if (pricePerItem.compareTo(BigDecimal.ZERO) > 0 && pricePerItemScaled.compareTo(BigDecimal.ZERO) == 0) {
|
||||
event.setCancelled(NOT_ENOUGH_STOCK_IN_INVENTORY);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setExactPrice(pricePerItemScaled);
|
||||
event.setStock(itemsHad);
|
||||
}
|
||||
|
||||
|
@ -152,8 +182,14 @@ public class PartialTransactionModule implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
BigDecimal pricePerItemScaled = pricePerItem.multiply(new BigDecimal(possessedItemCount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP);
|
||||
if (pricePerItem.compareTo(BigDecimal.ZERO) > 0 && pricePerItemScaled.compareTo(BigDecimal.ZERO) == 0) {
|
||||
event.setCancelled(NOT_ENOUGH_SPACE_IN_CHEST);
|
||||
return;
|
||||
}
|
||||
|
||||
event.setExactPrice(pricePerItemScaled);
|
||||
event.setStock(itemsFit);
|
||||
event.setExactPrice(pricePerItem.multiply(BigDecimal.valueOf(possessedItemCount)).setScale(Properties.PRICE_PRECISION, BigDecimal.ROUND_HALF_UP));
|
||||
}
|
||||
|
||||
CurrencyHoldEvent currencyHoldEvent = new CurrencyHoldEvent(event.getExactPrice(), client);
|
||||
|
@ -175,10 +211,10 @@ public class PartialTransactionModule implements Listener {
|
|||
int amount = InventoryUtil.getAmount(item, inventory);
|
||||
|
||||
Collections.addAll(toReturn, getCountedItemStack(new ItemStack[]{item},
|
||||
amount > item.getAmount() ? item.getAmount() : amount));
|
||||
Math.min(amount, item.getAmount())));
|
||||
}
|
||||
|
||||
return toReturn.toArray(new ItemStack[toReturn.size()]);
|
||||
return toReturn.toArray(new ItemStack[0]);
|
||||
}
|
||||
|
||||
private static ItemStack[] getCountedItemStack(ItemStack[] stock, int numberOfItems) {
|
||||
|
@ -227,7 +263,7 @@ public class PartialTransactionModule implements Listener {
|
|||
}
|
||||
}
|
||||
|
||||
return stacks.toArray(new ItemStack[stacks.size()]);
|
||||
return stacks.toArray(new ItemStack[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -247,7 +283,9 @@ public class PartialTransactionModule implements Listener {
|
|||
int free = 0;
|
||||
for (ItemStack itemInInventory : inventory.getContents()) {
|
||||
if (MaterialUtil.equals(item, itemInInventory)) {
|
||||
free += (maxStackSize - itemInInventory.getAmount()) % maxStackSize;
|
||||
if (itemInInventory != null) {
|
||||
free += (maxStackSize - itemInInventory.getAmount()) % maxStackSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -271,6 +309,6 @@ public class PartialTransactionModule implements Listener {
|
|||
Collections.addAll(resultStock, InventoryUtil.getItemsStacked(item));
|
||||
}
|
||||
|
||||
return resultStock.toArray(new ItemStack[resultStock.size()]);
|
||||
return resultStock.toArray(new ItemStack[0]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.Acrobot.ChestShop.Listeners.PreTransaction;
|
|||
import com.Acrobot.ChestShop.Events.PreTransactionEvent;
|
||||
import com.Acrobot.ChestShop.Events.TransactionEvent;
|
||||
import com.Acrobot.ChestShop.Permission;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
|
@ -12,7 +13,6 @@ import java.util.Locale;
|
|||
|
||||
import static com.Acrobot.ChestShop.Events.PreTransactionEvent.TransactionOutcome.CLIENT_DOES_NOT_HAVE_PERMISSION;
|
||||
import static com.Acrobot.ChestShop.Events.TransactionEvent.TransactionType.BUY;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.ITEM_LINE;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -27,7 +27,7 @@ public class PermissionChecker implements Listener {
|
|||
Player client = event.getClient();
|
||||
TransactionEvent.TransactionType transactionType = event.getTransactionType();
|
||||
|
||||
String itemLine = event.getSign().getLine(ITEM_LINE);
|
||||
String itemLine = ChestShopSign.getItem(event.getSign());
|
||||
if (itemLine.contains("#") && Permission.hasPermissionSetFalse(client, (transactionType == BUY ? Permission.BUY_ID : Permission.SELL_ID) + itemLine)) {
|
||||
event.setCancelled(CLIENT_DOES_NOT_HAVE_PERMISSION);
|
||||
return;
|
||||
|
|
|
@ -28,9 +28,9 @@ public class PriceValidator implements Listener {
|
|||
|
||||
if (price.equals(NO_PRICE)) {
|
||||
if (transactionType == BUY) {
|
||||
event.setCancelled(SHOP_DOES_NOT_BUY_THIS_ITEM);
|
||||
} else {
|
||||
event.setCancelled(SHOP_DOES_NOT_SELL_THIS_ITEM);
|
||||
} else {
|
||||
event.setCancelled(SHOP_DOES_NOT_BUY_THIS_ITEM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,9 @@ package com.Acrobot.ChestShop.Listeners;
|
|||
import com.Acrobot.Breeze.Utils.InventoryUtil;
|
||||
import com.Acrobot.Breeze.Utils.MaterialUtil;
|
||||
import com.Acrobot.Breeze.Utils.PriceUtil;
|
||||
import com.Acrobot.Breeze.Utils.QuantityUtil;
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
import com.Acrobot.ChestShop.Configuration.Messages;
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Economy.Economy;
|
||||
import com.Acrobot.ChestShop.Events.AccountQueryEvent;
|
||||
import com.Acrobot.ChestShop.Events.Economy.CurrencyFormatEvent;
|
||||
import com.Acrobot.ChestShop.Events.ItemInfoEvent;
|
||||
|
@ -23,7 +21,6 @@ import org.bukkit.event.Listener;
|
|||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
|
@ -34,15 +31,15 @@ public class ShopInfoListener implements Listener {
|
|||
@EventHandler(ignoreCancelled = true)
|
||||
public static void showShopInfo(ShopInfoEvent event) {
|
||||
if (ChestShopSign.isValid(event.getSign())) {
|
||||
String nameLine = event.getSign().getLine(ChestShopSign.NAME_LINE);
|
||||
String nameLine = ChestShopSign.getOwner(event.getSign());
|
||||
int amount;
|
||||
try {
|
||||
amount = QuantityUtil.parseQuantity(event.getSign().getLine(ChestShopSign.QUANTITY_LINE));
|
||||
amount = ChestShopSign.getQuantity(event.getSign());
|
||||
} catch (NumberFormatException notANumber) {
|
||||
Messages.INVALID_SHOP_DETECTED.sendWithPrefix(event.getSender());
|
||||
return;
|
||||
}
|
||||
String pricesLine = event.getSign().getLine(ChestShopSign.PRICE_LINE);
|
||||
String pricesLine = ChestShopSign.getPrice(event.getSign());
|
||||
|
||||
AccountQueryEvent queryEvent = new AccountQueryEvent(nameLine);
|
||||
ChestShop.callEvent(queryEvent);
|
||||
|
@ -54,7 +51,7 @@ public class ShopInfoListener implements Listener {
|
|||
String ownerName = queryEvent.getAccount().getName();
|
||||
ownerName = ownerName != null ? ownerName : nameLine;
|
||||
|
||||
ItemParseEvent parseEvent = new ItemParseEvent(event.getSign().getLine(ChestShopSign.ITEM_LINE));
|
||||
ItemParseEvent parseEvent = new ItemParseEvent(ChestShopSign.getItem(event.getSign()));
|
||||
ItemStack item = ChestShop.callEvent(parseEvent).getItem();
|
||||
if (item == null || amount < 1) {
|
||||
Messages.INVALID_SHOP_DETECTED.sendWithPrefix(event.getSender());
|
||||
|
|
|
@ -10,6 +10,7 @@ import com.Acrobot.ChestShop.Events.Economy.CurrencyAddEvent;
|
|||
import com.Acrobot.ChestShop.Events.Economy.CurrencySubtractEvent;
|
||||
import com.Acrobot.ChestShop.Events.ShopDestroyedEvent;
|
||||
import com.Acrobot.ChestShop.Permission;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import com.Acrobot.ChestShop.UUIDs.NameManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.ChatColor;
|
||||
|
@ -18,12 +19,9 @@ import org.bukkit.event.EventPriority;
|
|||
import org.bukkit.event.Listener;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.Acrobot.ChestShop.Permission.NOFEE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.AUTOFILL_CODE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.ITEM_LINE;
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.NAME_LINE;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -37,11 +35,11 @@ public class ShopRefundListener implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
if (ChatColor.stripColor(event.getSign().getLine(ITEM_LINE)).equals(AUTOFILL_CODE)) {
|
||||
if (ChatColor.stripColor(ChestShopSign.getItem(event.getSign())).equals(AUTOFILL_CODE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AccountQueryEvent accountQueryEvent = new AccountQueryEvent(event.getSign().getLine(NAME_LINE));
|
||||
AccountQueryEvent accountQueryEvent = new AccountQueryEvent(ChestShopSign.getOwner(event.getSign()));
|
||||
Bukkit.getPluginManager().callEvent(accountQueryEvent);
|
||||
Account account = accountQueryEvent.getAccount();
|
||||
if (account == null) {
|
||||
|
|
|
@ -9,8 +9,6 @@ import org.bukkit.event.EventHandler;
|
|||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
import static com.Acrobot.ChestShop.Signs.ChestShopSign.*;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
*/
|
||||
|
@ -19,28 +17,26 @@ public class ShopRemovalLogger implements Listener {
|
|||
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public static void onShopRemoval(final ShopDestroyedEvent event) {
|
||||
if (Properties.LOG_ALL_SHOP_REMOVALS || event.getDestroyer() != null) {
|
||||
if (!Properties.LOG_ALL_SHOP_REMOVALS && event.getDestroyer() != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ChestShop.getBukkitServer().getScheduler().runTaskAsynchronously(ChestShop.getPlugin(), new Runnable() {
|
||||
@Override public void run() {
|
||||
String shopOwner = event.getSign().getLine(NAME_LINE);
|
||||
String typeOfShop = ChestShopSign.isAdminShop(shopOwner) ? "An Admin Shop" : "A shop belonging to " + shopOwner;
|
||||
ChestShop.runInAsyncThread(() -> {
|
||||
String shopOwner = ChestShopSign.getOwner(event.getSign());
|
||||
String typeOfShop = ChestShopSign.isAdminShop(shopOwner) ? "An Admin Shop" : "A shop belonging to " + shopOwner;
|
||||
|
||||
String item = event.getSign().getLine(QUANTITY_LINE) + ' ' + event.getSign().getLine(ITEM_LINE);
|
||||
String prices = event.getSign().getLine(PRICE_LINE);
|
||||
String location = LocationUtil.locationToString(event.getSign().getLocation());
|
||||
String item = ChestShopSign.getQuantity(event.getSign()) + ' ' + ChestShopSign.getItem(event.getSign());
|
||||
String prices = ChestShopSign.getPrice(event.getSign());
|
||||
String location = LocationUtil.locationToString(event.getSign().getLocation());
|
||||
|
||||
String message = String.format(REMOVAL_MESSAGE,
|
||||
typeOfShop,
|
||||
event.getDestroyer() != null ? event.getDestroyer().getName() : "???",
|
||||
item,
|
||||
prices,
|
||||
location);
|
||||
String message = String.format(REMOVAL_MESSAGE,
|
||||
typeOfShop,
|
||||
event.getDestroyer() != null ? event.getDestroyer().getName() : "???",
|
||||
item,
|
||||
prices,
|
||||
location);
|
||||
|
||||
ChestShop.getBukkitLogger().info(message);
|
||||
}
|
||||
ChestShop.getShopLogger().info(message);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ public class ItemDatabase {
|
|||
itemDao = DaoCreator.getDaoAndCreateTable(Item.class);
|
||||
handleMetadataUpdate();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while loading items database", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ public class ItemDatabase {
|
|||
try {
|
||||
versionConfig.save(configFile);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while updating metadata-version from " + previousVersion + " to " + newVersion, e);
|
||||
}
|
||||
} else {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while updating Item Metadata database! While the plugin will still run it will work less efficiently.");
|
||||
|
@ -70,8 +70,10 @@ public class ItemDatabase {
|
|||
private int getCurrentMetadataVersion() {
|
||||
ItemStack item = new ItemStack(Material.STONE);
|
||||
ItemMeta meta = item.getItemMeta();
|
||||
meta.setDisplayName("GetCurrentMetadataVersion");
|
||||
item.setItemMeta(meta);
|
||||
if (meta != null) {
|
||||
meta.setDisplayName("GetCurrentMetadataVersion");
|
||||
item.setItemMeta(meta);
|
||||
}
|
||||
Map<String, Object> serialized = item.serialize();
|
||||
return (int) serialized.getOrDefault("v", -1);
|
||||
}
|
||||
|
@ -101,7 +103,7 @@ public class ItemDatabase {
|
|||
item.setBase64ItemCode(Base64.encodeObject(yaml.dump(itemStack)));
|
||||
itemDao.update(item);
|
||||
updated.getAndIncrement();
|
||||
} catch (YAMLException e) {
|
||||
} catch (YAMLException | ClassCastException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "YAML of the item with ID " + Base62.encode(item.getId()) + " (" + item.getId() + ") is corrupted: \n" + serialized);
|
||||
}
|
||||
}
|
||||
|
@ -117,7 +119,7 @@ public class ItemDatabase {
|
|||
return true;
|
||||
});
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Unable to update metadata version of all items from " + previousVersion + " to " + newVersion, e);
|
||||
return false;
|
||||
} finally {
|
||||
it.closeQuietly();
|
||||
|
@ -153,10 +155,8 @@ public class ItemDatabase {
|
|||
itemDao.create(itemEntity);
|
||||
}
|
||||
return Base62.encode(itemEntity.getId());
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (SQLException | IOException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Unable to get code of item " + item, e);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -196,7 +196,7 @@ public class ItemDatabase {
|
|||
return null;
|
||||
}
|
||||
|
||||
private class YamlBukkitConstructor extends YamlConstructor {
|
||||
private static class YamlBukkitConstructor extends YamlConstructor {
|
||||
public YamlBukkitConstructor() {
|
||||
this.yamlConstructors.put(new Tag(Tag.PREFIX + "org.bukkit.inventory.ItemStack"), yamlConstructors.get(Tag.MAP));
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import org.bukkit.command.CommandSender;
|
|||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
|
@ -43,7 +42,19 @@ public enum Permission {
|
|||
NOTIFY_TOGGLE("ChestShop.toggle"),
|
||||
ACCESS_TOGGLE("ChestShop.accesstoggle"),
|
||||
ITEMINFO("ChestShop.iteminfo"),
|
||||
SHOPINFO("ChestShop.shopinfo");
|
||||
SHOPINFO("ChestShop.shopinfo"),
|
||||
|
||||
NOLIMIT_MIN_BUY("ChestShop.nolimit.buy.min"),
|
||||
NOLIMIT_MIN_BUY_ID("ChestShop.nolimit.buy.min."),
|
||||
|
||||
NOLIMIT_MAX_BUY("ChestShop.nolimit.buy.max"),
|
||||
NOLIMIT_MAX_BUY_ID("ChestShop.nolimit.buy.max."),
|
||||
|
||||
NOLIMIT_MIN_SELL("ChestShop.nolimit.sell.min"),
|
||||
NOLIMIT_MIN_SELL_ID("ChestShop.nolimit.sell.min."),
|
||||
|
||||
NOLIMIT_MAX_SELL("ChestShop.nolimit.sell.max"),
|
||||
NOLIMIT_MAX_SELL_ID("ChestShop.nolimit.sell.max.");
|
||||
|
||||
private final String permission;
|
||||
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
package com.Acrobot.ChestShop.Plugins;
|
||||
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
import com.Acrobot.ChestShop.Events.ItemParseEvent;
|
||||
import com.Acrobot.ChestShop.Events.ItemStringQueryEvent;
|
||||
import com.jojodmo.itembridge.ItemBridgeKey;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import static com.Acrobot.Breeze.Utils.StringUtil.getMinecraftStringWidth;
|
||||
|
||||
/**
|
||||
* Support for the <a href="https://www.spigotmc.org/resources/77080/">ItemBridge plugin</a> to use their strings for
|
||||
* custom items directly on ChestShop signs.
|
||||
*
|
||||
* @author Phoenix616
|
||||
*/
|
||||
public class ItemBridge implements Listener {
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onItemParse(ItemParseEvent event) {
|
||||
if (event.getItem() == null) {
|
||||
ItemStack item = com.jojodmo.itembridge.ItemBridge.getItemStack(event.getItemString());
|
||||
if (item != null) {
|
||||
event.setItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onItemStringQuery(ItemStringQueryEvent event) {
|
||||
ItemBridgeKey key = com.jojodmo.itembridge.ItemBridge.getItemKey(event.getItem());
|
||||
// If namespace is "minecraft" then we ignore it and use our own logic
|
||||
if (key != null && !"minecraft".equalsIgnoreCase(key.getNamespace())) {
|
||||
String code = key.toString();
|
||||
// Make sure the ItemBridge string is not too long as we can't parse shortened ones
|
||||
if (event.getMaxWidth() > 0) {
|
||||
int width = getMinecraftStringWidth(code);
|
||||
if (width > event.getMaxWidth()) {
|
||||
ChestShop.logDebug("Can't use ItemBridge alias " + code + " as it's width (" + width + ") was wider than the allowed max width of " + event.getMaxWidth());
|
||||
return;
|
||||
}
|
||||
}
|
||||
event.setItemString(key.toString());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -162,8 +162,11 @@ public class LightweightChestProtection implements Listener {
|
|||
return;
|
||||
}
|
||||
|
||||
Protection.Type type = Protection.Type.PRIVATE;
|
||||
Protection.Type type;
|
||||
switch (event.getType()) {
|
||||
case PRIVATE:
|
||||
type = Protection.Type.PRIVATE;
|
||||
break;
|
||||
case PUBLIC:
|
||||
type = Protection.Type.PUBLIC;
|
||||
break;
|
||||
|
@ -173,8 +176,14 @@ public class LightweightChestProtection implements Listener {
|
|||
case DISPLAY:
|
||||
try {
|
||||
type = Protection.Type.valueOf("DISPLAY");
|
||||
} catch (IllegalArgumentException ignored) {}
|
||||
} catch (IllegalArgumentException e) {
|
||||
// Not supported
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// Not supported
|
||||
return;
|
||||
}
|
||||
|
||||
Protection protection = null;
|
||||
|
|
|
@ -9,7 +9,9 @@ import org.bukkit.event.Listener;
|
|||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
/**
|
||||
* @author Acrobot
|
||||
* Support RedProtect region checks.
|
||||
*
|
||||
* @author Phoenix616
|
||||
*/
|
||||
public class RedProtectBuilding implements Listener {
|
||||
private RedProtect redProtect;
|
||||
|
|
|
@ -98,7 +98,7 @@ public class Security {
|
|||
continue;
|
||||
}
|
||||
|
||||
AccountQueryEvent accountQueryEvent = new AccountQueryEvent(sign.getLine(ChestShopSign.NAME_LINE));
|
||||
AccountQueryEvent accountQueryEvent = new AccountQueryEvent(ChestShopSign.getOwner(sign));
|
||||
Bukkit.getPluginManager().callEvent(accountQueryEvent);
|
||||
Account account = accountQueryEvent.getAccount();
|
||||
if (account != null && !account.getUuid().equals(player.getUniqueId())) {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.Acrobot.ChestShop.Signs;
|
||||
|
||||
import com.Acrobot.Breeze.Utils.BlockUtil;
|
||||
import com.Acrobot.Breeze.Utils.QuantityUtil;
|
||||
import com.Acrobot.Breeze.Utils.StringUtil;
|
||||
import com.Acrobot.ChestShop.Configuration.Properties;
|
||||
import com.Acrobot.ChestShop.Containers.AdminInventory;
|
||||
|
@ -20,6 +21,7 @@ import org.bukkit.inventory.Inventory;
|
|||
import org.bukkit.inventory.InventoryHolder;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.Optional;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
|
@ -35,7 +37,7 @@ public class ChestShopSign {
|
|||
public static final byte ITEM_LINE = 3;
|
||||
|
||||
public static final Pattern[][] SHOP_SIGN_PATTERN = {
|
||||
{ Pattern.compile("^[1-9][0-9]{0,5}$"), Pattern.compile("^Q [1-9][0-9]{0,4} : C [0-9]{0,5}$") },
|
||||
{ Pattern.compile("^[1-9][0-9]{0,5}$"), QuantityUtil.QUANTITY_LINE_WITH_COUNTER_PATTERN },
|
||||
{
|
||||
Pattern.compile("(?i)^((\\d*([.e]\\d+)?)|free)$"),
|
||||
Pattern.compile("(?i)^([BS] *((\\d*([.e]\\d+)?)|free))( *: *([BS] *((\\d*([.e]\\d+)?)|free)))?$"),
|
||||
|
@ -43,7 +45,7 @@ public class ChestShopSign {
|
|||
Pattern.compile("(?i)^(((\\d*([.e]\\d+)?)|free) *[BS]) *: *(((\\d*([.e]\\d+)?)|free) *[BS])$"),
|
||||
Pattern.compile("(?i)^([BS] *((\\d*([.e]\\d+)?)|free)) *: *(((\\d*([.e]\\d+)?)|free) *[BS])$"),
|
||||
},
|
||||
{ Pattern.compile("^[\\w? #:\\-]+$") }
|
||||
{ Pattern.compile("^[\\p{L}\\d_? #:\\-]+$") }
|
||||
};
|
||||
public static final String AUTOFILL_CODE = "?";
|
||||
|
||||
|
@ -56,16 +58,23 @@ public class ChestShopSign {
|
|||
}
|
||||
|
||||
public static boolean isAdminShop(Sign sign) {
|
||||
return isAdminShop(sign.getLine(NAME_LINE));
|
||||
return isAdminShop(sign.getLines());
|
||||
}
|
||||
|
||||
public static boolean isAdminShop(String[] lines) {
|
||||
return isAdminShop(getOwner(lines));
|
||||
}
|
||||
|
||||
public static boolean isValid(Sign sign) {
|
||||
return isValid(sign.getLines());
|
||||
}
|
||||
|
||||
public static boolean isValid(String[] line) {
|
||||
line = StringUtil.stripColourCodes(line);
|
||||
return isValidPreparedSign(line) && (line[PRICE_LINE].toUpperCase(Locale.ROOT).contains("B") || line[PRICE_LINE].toUpperCase(Locale.ROOT).contains("S")) && !line[NAME_LINE].isEmpty();
|
||||
public static boolean isValid(String[] lines) {
|
||||
lines = StringUtil.stripColourCodes(lines);
|
||||
return isValidPreparedSign(lines)
|
||||
&& (getPrice(lines).toUpperCase(Locale.ROOT).contains("B")
|
||||
|| getPrice(lines).toUpperCase(Locale.ROOT).contains("S"))
|
||||
&& !getOwner(lines).isEmpty();
|
||||
}
|
||||
|
||||
public static boolean isValid(Block sign) {
|
||||
|
@ -120,6 +129,16 @@ public class ChestShopSign {
|
|||
return false;
|
||||
}
|
||||
|
||||
public static Block getShopBlock(InventoryHolder holder) {
|
||||
if (holder instanceof DoubleChest) {
|
||||
return Optional.ofNullable(getShopBlock(((DoubleChest) holder).getLeftSide()))
|
||||
.orElse(getShopBlock(((DoubleChest) holder).getRightSide()));
|
||||
} else if (holder instanceof BlockState) {
|
||||
return ((BlockState) holder).getBlock();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static boolean canAccess(Player player, Sign sign) {
|
||||
return hasPermission(player, Permission.OTHER_NAME_ACCESS, sign);
|
||||
}
|
||||
|
@ -128,7 +147,7 @@ public class ChestShopSign {
|
|||
if (player == null) return false;
|
||||
if (sign == null) return true;
|
||||
|
||||
String name = sign.getLine(NAME_LINE);
|
||||
String name = getOwner(sign);
|
||||
if (name == null || name.isEmpty()) return true;
|
||||
|
||||
return NameManager.canUseName(player, base, name);
|
||||
|
@ -137,7 +156,7 @@ public class ChestShopSign {
|
|||
public static boolean isOwner(Player player, Sign sign) {
|
||||
if (player == null || sign == null) return false;
|
||||
|
||||
String name = sign.getLine(NAME_LINE);
|
||||
String name = getOwner(sign);
|
||||
if (name == null || name.isEmpty()) return false;
|
||||
|
||||
AccountQueryEvent accountQueryEvent = new AccountQueryEvent(name);
|
||||
|
@ -150,8 +169,7 @@ public class ChestShopSign {
|
|||
}
|
||||
|
||||
public static boolean isValidPreparedSign(String[] lines) {
|
||||
// The first line is the name of the shop owner
|
||||
String playername = lines[0];
|
||||
String playername = ChestShopSign.getOwner(lines);
|
||||
|
||||
// If the shop owner is not blank (auto-filled) or the admin shop string, we need to validate it
|
||||
if ((!isAdminShop(playername)) && (playername.length() > 0)) {
|
||||
|
@ -171,11 +189,11 @@ public class ChestShopSign {
|
|||
}
|
||||
}
|
||||
|
||||
// The first line is valid. Now validate the last 3 lines against the predefined regexp patterns.
|
||||
// The playername on the first line is valid. Now validate the last 3 lines against the predefined regexp patterns.
|
||||
for (int i = 0; i < 3; i++) {
|
||||
boolean matches = false;
|
||||
for (Pattern pattern : SHOP_SIGN_PATTERN[i]) {
|
||||
if (pattern.matcher(lines[i+1]).matches()) {
|
||||
if (pattern.matcher(StringUtil.strip(StringUtil.stripColourCodes(lines[i+1]))).matches()) {
|
||||
matches = true;
|
||||
break;
|
||||
}
|
||||
|
@ -186,6 +204,101 @@ public class ChestShopSign {
|
|||
}
|
||||
|
||||
// All lines are looking good. If the price line contains only one ':', then this is a valid prepared sign.
|
||||
return lines[PRICE_LINE].indexOf(':') == lines[PRICE_LINE].lastIndexOf(':');
|
||||
String priceLine = getPrice(lines);
|
||||
return priceLine.indexOf(':') == priceLine.lastIndexOf(':');
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the owner string of a shop sign
|
||||
* @param sign The sign
|
||||
* @return The owner string
|
||||
*/
|
||||
public static String getOwner(Sign sign) {
|
||||
return getOwner(sign.getLines());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the owner string of a shop sign
|
||||
* @param lines The sign lines
|
||||
* @return The owner string
|
||||
*/
|
||||
public static String getOwner(String[] lines) {
|
||||
return StringUtil.stripColourCodes(StringUtil.strip(StringUtil.stripColourCodes(lines[NAME_LINE])));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the quantity and count line of the shop sign
|
||||
* @param sign The sign
|
||||
* @return The quantity line
|
||||
* @throws IllegalArgumentException Thrown when an invalid quantity is present
|
||||
*/
|
||||
public static String getQuantityLine(Sign sign) throws IllegalArgumentException {
|
||||
return getQuantityLine(sign.getLines());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the quantity and count line of sign lines
|
||||
* @param lines The sign lines
|
||||
* @return The quantity line
|
||||
* @throws IllegalArgumentException Thrown when an invalid quantity is present
|
||||
*/
|
||||
public static String getQuantityLine(String[] lines) throws IllegalArgumentException {
|
||||
return lines.length > QUANTITY_LINE ? StringUtil.strip(StringUtil.stripColourCodes(lines[QUANTITY_LINE])) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the quantity of the shop sign
|
||||
* @param sign The sign
|
||||
* @return The quantity line
|
||||
* @throws IllegalArgumentException Thrown when an invalid quantity is present
|
||||
*/
|
||||
public static int getQuantity(Sign sign) throws IllegalArgumentException {
|
||||
return getQuantity(sign.getLines());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the quantity of sign lines
|
||||
* @param lines The sign lines
|
||||
* @return The quantity
|
||||
* @throws IllegalArgumentException Thrown when an invalid quantity is present
|
||||
*/
|
||||
public static int getQuantity(String[] lines) throws IllegalArgumentException {
|
||||
return QuantityUtil.parseQuantity(getQuantityLine(lines));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the price line of the shop sign
|
||||
* @param sign The sign
|
||||
* @return The price line
|
||||
*/
|
||||
public static String getPrice(Sign sign) {
|
||||
return StringUtil.strip(StringUtil.stripColourCodes(sign.getLine(PRICE_LINE)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the price line of sign lines
|
||||
* @param lines The sign lines
|
||||
* @return The price line
|
||||
*/
|
||||
public static String getPrice(String[] lines) {
|
||||
return lines.length > PRICE_LINE ? StringUtil.strip(StringUtil.stripColourCodes(lines[PRICE_LINE])) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the item line of the shop sign
|
||||
* @param sign The sign
|
||||
* @return The item line
|
||||
*/
|
||||
public static String getItem(Sign sign) {
|
||||
return getItem(sign.getLines());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the item line of sign lines
|
||||
* @param lines The sign lines
|
||||
* @return The item line
|
||||
*/
|
||||
public static String getItem(String[] lines) {
|
||||
return lines.length > ITEM_LINE ? StringUtil.strip(StringUtil.stripColourCodes(lines[ITEM_LINE])) : "";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,10 +12,11 @@ import com.Acrobot.ChestShop.Events.AccountAccessEvent;
|
|||
import com.Acrobot.ChestShop.Events.AccountQueryEvent;
|
||||
import com.Acrobot.ChestShop.Permission;
|
||||
import com.Acrobot.ChestShop.Signs.ChestShopSign;
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.j256.ormlite.dao.Dao;
|
||||
|
||||
import com.j256.ormlite.stmt.SelectArg;
|
||||
import org.apache.commons.lang.Validate;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.OfflinePlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
@ -36,6 +37,8 @@ import java.util.logging.Level;
|
|||
*/
|
||||
@SuppressWarnings("UnusedAssignment") // I deliberately set the variables to null while initializing
|
||||
public class NameManager implements Listener {
|
||||
private static final Object accountsLock = new Object();
|
||||
|
||||
private static Dao<Account, String> accounts;
|
||||
|
||||
private static SimpleCache<String, Account> usernameToAccount = new SimpleCache<>(Properties.CACHE_SIZE);
|
||||
|
@ -63,8 +66,8 @@ public class NameManager implements Listener {
|
|||
* @throws IllegalArgumentException when an invalid player object was passed
|
||||
*/
|
||||
public static Account getOrCreateAccount(OfflinePlayer player) {
|
||||
Validate.notNull(player.getName(), "Name of player " + player.getUniqueId() + " is null?");
|
||||
Validate.isTrue(!(player instanceof Player) || !Properties.ENSURE_CORRECT_PLAYERID || uuidVersion < 0 || player.getUniqueId().version() == uuidVersion,
|
||||
Preconditions.checkNotNull(player.getName(), "Name of player " + player.getUniqueId() + " is null?");
|
||||
Preconditions.checkArgument(player instanceof Player || !Properties.ENSURE_CORRECT_PLAYERID || uuidVersion < 0 || player.getUniqueId().version() == uuidVersion,
|
||||
"Invalid OfflinePlayer! " + player.getUniqueId() + " has version " + player.getUniqueId().version() + " and not server version " + uuidVersion + ". " +
|
||||
"If you believe that is an error and your setup allows such UUIDs then set the ENSURE_CORRECT_PLAYERID config option to false.");
|
||||
return getOrCreateAccount(player.getUniqueId(), player.getName());
|
||||
|
@ -79,8 +82,8 @@ public class NameManager implements Listener {
|
|||
* @throws IllegalArgumentException when id or name are null
|
||||
*/
|
||||
public static Account getOrCreateAccount(UUID id, String name) {
|
||||
Validate.notNull(id, "UUID of player is null?");
|
||||
Validate.notNull(name, "Name of player " + id + " is null?");
|
||||
Preconditions.checkNotNull(id, "UUID of player is null?");
|
||||
Preconditions.checkNotNull(name, "Name of player " + id + " is null?");
|
||||
|
||||
Account account = getAccount(id);
|
||||
if (account == null) {
|
||||
|
@ -97,20 +100,22 @@ public class NameManager implements Listener {
|
|||
*/
|
||||
public static Account getAccount(UUID uuid) {
|
||||
try {
|
||||
return uuidToAccount.get(uuid, () -> {
|
||||
try {
|
||||
Account account = accounts.queryBuilder().orderBy("lastSeen", false).where().eq("uuid", new SelectArg(uuid)).queryForFirst();
|
||||
if (account != null) {
|
||||
account.setUuid(uuid); // HOW IS IT EVEN POSSIBLE THAT UUID IS NOT SET EVEN IF WE HAVE FOUND THE PLAYER?!
|
||||
shortToAccount.put(account.getShortName(), account);
|
||||
usernameToAccount.put(account.getName(), account);
|
||||
return account;
|
||||
synchronized (accountsLock) {
|
||||
return uuidToAccount.get(uuid, () -> {
|
||||
try {
|
||||
Account account = accounts.queryBuilder().orderBy("lastSeen", false).where().eq("uuid", new SelectArg(uuid)).queryForFirst();
|
||||
if (account != null) {
|
||||
account.setUuid(uuid); // HOW IS IT EVEN POSSIBLE THAT UUID IS NOT SET EVEN IF WE HAVE FOUND THE PLAYER?!
|
||||
shortToAccount.put(account.getShortName(), account);
|
||||
usernameToAccount.put(account.getName(), account);
|
||||
return account;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while getting account for " + uuid + ":", e);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while getting account for " + uuid + ":", e);
|
||||
}
|
||||
throw new Exception("Could not find account for " + uuid);
|
||||
});
|
||||
throw new Exception("Could not find account for " + uuid);
|
||||
});
|
||||
}
|
||||
} catch (ExecutionException ignored) {
|
||||
return null;
|
||||
}
|
||||
|
@ -124,21 +129,24 @@ public class NameManager implements Listener {
|
|||
* @throws IllegalArgumentException if the username is empty or null
|
||||
*/
|
||||
public static Account getAccount(String fullName) {
|
||||
Validate.notEmpty(fullName, "fullName cannot be null or empty!");
|
||||
Preconditions.checkNotNull(fullName, "fullName cannot be null!");
|
||||
Preconditions.checkArgument(!fullName.isEmpty(), "fullName cannot be empty!");
|
||||
try {
|
||||
return usernameToAccount.get(fullName, () -> {
|
||||
try {
|
||||
Account account = accounts.queryBuilder().orderBy("lastSeen", false).where().eq("name", new SelectArg(fullName)).queryForFirst();
|
||||
if (account != null) {
|
||||
account.setName(fullName); // HOW IS IT EVEN POSSIBLE THAT THE NAME IS NOT SET EVEN IF WE HAVE FOUND THE PLAYER?!
|
||||
shortToAccount.put(account.getShortName(), account);
|
||||
return account;
|
||||
synchronized (accountsLock) {
|
||||
return usernameToAccount.get(fullName, () -> {
|
||||
try {
|
||||
Account account = accounts.queryBuilder().orderBy("lastSeen", false).where().eq("name", new SelectArg(fullName)).queryForFirst();
|
||||
if (account != null) {
|
||||
account.setName(fullName); // HOW IS IT EVEN POSSIBLE THAT THE NAME IS NOT SET EVEN IF WE HAVE FOUND THE PLAYER?!
|
||||
shortToAccount.put(account.getShortName(), account);
|
||||
return account;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while getting account for " + fullName + ":", e);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while getting account for " + fullName + ":", e);
|
||||
}
|
||||
throw new Exception("Could not find account for " + fullName);
|
||||
});
|
||||
throw new Exception("Could not find account for " + fullName);
|
||||
});
|
||||
}
|
||||
} catch (ExecutionException ignored) {
|
||||
return null;
|
||||
}
|
||||
|
@ -161,22 +169,25 @@ public class NameManager implements Listener {
|
|||
*/
|
||||
@Deprecated
|
||||
public static Account getAccountFromShortName(String shortName) {
|
||||
Validate.notEmpty(shortName, "shortName cannot be null or empty!");
|
||||
Preconditions.checkNotNull(shortName, "shortName cannot be null!");
|
||||
Preconditions.checkArgument(!shortName.isEmpty(), "shortName cannot be empty!");
|
||||
Account account = null;
|
||||
|
||||
try {
|
||||
account = shortToAccount.get(shortName, () -> {
|
||||
try {
|
||||
Account a = accounts.queryBuilder().where().eq("shortName", new SelectArg(shortName)).queryForFirst();
|
||||
if (a != null) {
|
||||
a.setShortName(shortName); // HOW IS IT EVEN POSSIBLE THAT THE NAME IS NOT SET EVEN IF WE HAVE FOUND THE PLAYER?!
|
||||
return a;
|
||||
synchronized (accountsLock) {
|
||||
account = shortToAccount.get(shortName, () -> {
|
||||
try {
|
||||
Account a = accounts.queryBuilder().where().eq("shortName", new SelectArg(shortName)).queryForFirst();
|
||||
if (a != null) {
|
||||
a.setShortName(shortName); // HOW IS IT EVEN POSSIBLE THAT THE NAME IS NOT SET EVEN IF WE HAVE FOUND THE PLAYER?!
|
||||
return a;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while getting account for " + shortName + ":", e);
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while getting account for " + shortName + ":", e);
|
||||
}
|
||||
throw new Exception("Could not find account for " + shortName);
|
||||
});
|
||||
throw new Exception("Could not find account for " + shortName);
|
||||
});
|
||||
}
|
||||
} catch (ExecutionException ignored) {}
|
||||
return account;
|
||||
}
|
||||
|
@ -220,27 +231,29 @@ public class NameManager implements Listener {
|
|||
final UUID uuid = player.getUniqueId();
|
||||
|
||||
Account latestAccount = null;
|
||||
try {
|
||||
latestAccount = accounts.queryBuilder().where().eq("uuid", new SelectArg(uuid)).and().eq("name", new SelectArg(player.getName())).queryForFirst();
|
||||
} catch (SQLException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while searching for latest account of " + player.getName() + "/" + uuid + ":", e);
|
||||
}
|
||||
synchronized (accountsLock) {
|
||||
try {
|
||||
latestAccount = accounts.queryBuilder().where().eq("uuid", new SelectArg(uuid)).and().eq("name", new SelectArg(player.getName())).queryForFirst();
|
||||
} catch (SQLException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while searching for latest account of " + player.getName() + "/" + uuid + ":", e);
|
||||
}
|
||||
|
||||
if (latestAccount == null) {
|
||||
latestAccount = new Account(player.getName(), getNewShortenedName(player), player.getUniqueId());
|
||||
}
|
||||
if (latestAccount == null) {
|
||||
latestAccount = new Account(player.getName(), getNewShortenedName(player), player.getUniqueId());
|
||||
}
|
||||
|
||||
latestAccount.setLastSeen(new Date());
|
||||
try {
|
||||
accounts.createOrUpdate(latestAccount);
|
||||
} catch (SQLException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while updating account " + latestAccount + ":", e);
|
||||
return null;
|
||||
}
|
||||
latestAccount.setLastSeen(new Date());
|
||||
try {
|
||||
accounts.createOrUpdate(latestAccount);
|
||||
} catch (SQLException e) {
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Error while updating account " + latestAccount + ":", e);
|
||||
return null;
|
||||
}
|
||||
|
||||
usernameToAccount.put(latestAccount.getName(), latestAccount);
|
||||
uuidToAccount.put(uuid, latestAccount);
|
||||
shortToAccount.put(latestAccount.getShortName(), latestAccount);
|
||||
usernameToAccount.put(latestAccount.getName(), latestAccount);
|
||||
uuidToAccount.put(uuid, latestAccount);
|
||||
shortToAccount.put(latestAccount.getShortName(), latestAccount);
|
||||
}
|
||||
|
||||
return latestAccount;
|
||||
}
|
||||
|
@ -269,7 +282,12 @@ public class NameManager implements Listener {
|
|||
|
||||
public static boolean canUseName(Player player, Permission base, String name) {
|
||||
if (ChestShopSign.isAdminShop(name)) {
|
||||
return Permission.has(player, Permission.ADMIN_SHOP);
|
||||
if (Permission.has(player, Permission.ADMIN_SHOP)) {
|
||||
return true;
|
||||
} else {
|
||||
ChestShop.logDebug(player.getName() + " cannot use the name " + name + " as it's an admin shop and they don't have the permission " + Permission.ADMIN_SHOP);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (Permission.otherName(player, base, name)) {
|
||||
|
@ -277,10 +295,15 @@ public class NameManager implements Listener {
|
|||
}
|
||||
|
||||
AccountQueryEvent queryEvent = new AccountQueryEvent(name);
|
||||
queryEvent.searchOfflinePlayers(false);
|
||||
ChestShop.callEvent(queryEvent);
|
||||
Account account = queryEvent.getAccount();
|
||||
if (account == null) {
|
||||
// There is no account by the provided name, but it matches the player name
|
||||
// Return true as they specified their own name and a new account should get created
|
||||
if (player.getName().equalsIgnoreCase(name)) {
|
||||
return true;
|
||||
}
|
||||
ChestShop.logDebug(player.getName() + " cannot use the name " + name + " for a shop as no account with that name exists");
|
||||
return false;
|
||||
}
|
||||
if (!account.getName().equalsIgnoreCase(name) && Permission.otherName(player, base, account.getName())) {
|
||||
|
@ -295,6 +318,11 @@ public class NameManager implements Listener {
|
|||
public static void onAccountAccessCheck(AccountAccessEvent event) {
|
||||
if (!event.canAccess()) {
|
||||
event.setAccess(event.getPlayer().getUniqueId().equals(event.getAccount().getUuid()));
|
||||
if (!event.canAccess()) {
|
||||
ChestShop.logDebug(event.getPlayer().getName() + "/" + event.getPlayer().getUniqueId()
|
||||
+ " cannot access the account " + event.getAccount().getName() + "/" + event.getAccount().getUuid()
|
||||
+ " as their UUID doesn't match!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -317,7 +345,14 @@ public class NameManager implements Listener {
|
|||
try {
|
||||
accounts = DaoCreator.getDaoAndCreateTable(Account.class);
|
||||
|
||||
adminAccount = new Account(Properties.ADMIN_SHOP_NAME, Bukkit.getOfflinePlayer(Properties.ADMIN_SHOP_NAME).getUniqueId());
|
||||
try {
|
||||
adminAccount = new Account(Properties.ADMIN_SHOP_NAME, Bukkit.getOfflinePlayer(Properties.ADMIN_SHOP_NAME).getUniqueId());
|
||||
} catch (NullPointerException ratelimitedException) {
|
||||
// This happens when the server was ratelimited by Mojang. Unfortunately there is no nice way to check that.
|
||||
// We fall back to the method used by CraftBukkit to generate an OfflinePlayer's UUID
|
||||
adminAccount = new Account(Properties.ADMIN_SHOP_NAME, UUID.nameUUIDFromBytes(("OfflinePlayer:" + Properties.ADMIN_SHOP_NAME).getBytes(Charsets.UTF_8)));
|
||||
ChestShop.getBukkitLogger().log(Level.WARNING, "Your server appears to be ratelimited by Mojang and can't query UUID data from their API. If you run into issues with admin shops please report them!");
|
||||
}
|
||||
accounts.createOrUpdate(adminAccount);
|
||||
|
||||
if (!Properties.SERVER_ECONOMY_ACCOUNT.isEmpty()) {
|
||||
|
@ -338,7 +373,7 @@ public class NameManager implements Listener {
|
|||
}
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
ChestShop.getBukkitLogger().log(Level.SEVERE, "Error while trying to setup accounts", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.Acrobot.ChestShop.Updater;
|
||||
|
||||
import com.Acrobot.ChestShop.ChestShop;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
|
@ -55,7 +56,7 @@ public class JenkinsBuildsNotifier implements Runnable {
|
|||
|
||||
try {
|
||||
apiUrl = new URL(jenkinsJobUrl + "api/json");
|
||||
plugin.getServer().getScheduler().runTaskAsynchronously(plugin, this);
|
||||
ChestShop.runInAsyncThread(this);
|
||||
} catch (MalformedURLException e) {
|
||||
plugin.getLogger().log(Level.WARNING, "Can not check for new dev builds as " + jenkinsJobUrl + "api/json is not a valid url!", e);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
package com.Acrobot.ChestShop.Updater;
|
||||
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.common.io.Files;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.json.simple.JSONArray;
|
||||
|
@ -19,6 +21,8 @@ import java.net.URLConnection;
|
|||
import java.util.Enumeration;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
|
@ -39,12 +43,13 @@ import java.util.zip.ZipFile;
|
|||
* @version 2.1
|
||||
*/
|
||||
|
||||
public class Updater {
|
||||
public final class Updater {
|
||||
|
||||
private Plugin plugin;
|
||||
private UpdateType type;
|
||||
private String versionName;
|
||||
private String versionLink;
|
||||
private String versionHash;
|
||||
private String versionType;
|
||||
private String versionGameVersion;
|
||||
|
||||
|
@ -54,21 +59,21 @@ public class Updater {
|
|||
private File file; // The plugin's file
|
||||
private Thread thread; // Updater thread
|
||||
|
||||
private int id = -1; // Project's Curse ID
|
||||
private String apiKey = null; // BukkitDev ServerMods API key
|
||||
private static final String TITLE_VALUE = "name"; // Gets remote file's title
|
||||
private static final String LINK_VALUE = "downloadUrl"; // Gets remote file's download link
|
||||
private static final String TYPE_VALUE = "releaseType"; // Gets remote file's release type
|
||||
private static final String VERSION_VALUE = "gameVersion"; // Gets remote file's build version
|
||||
private static final String QUERY = "/servermods/files?projectIds="; // Path to GET
|
||||
private static final String HOST = "https://api.curseforge.com"; // Slugs will be appended to this to get to the project's RSS feed
|
||||
private String id; // Project's Curse ID
|
||||
private String apiKey = null; // Modrinth API key
|
||||
private static final String TITLE_VALUE = "version_number"; // Gets remote version
|
||||
private static final String FILES_VALUE = "files"; // Gets all files associated with that version
|
||||
private static final String LINK_VALUE = "url"; // Gets remote file's download link
|
||||
private static final String TYPE_VALUE = "version_type"; // Gets remote file's release type
|
||||
private static final String VERSION_VALUE = "game_versions"; // Gets remote file's build version
|
||||
private static final String QUERY = "/v2/project/%projectid%/version"; // Path to GET
|
||||
private static final String HOST = "https://api.modrinth.com"; // Slugs will be appended to this to get to the project's versions
|
||||
|
||||
private static final String USER_AGENT = "Updater (by Gravity)";
|
||||
private static final String delimiter = "^v|[\\s_-]v"; // Used for locating version numbers in file names
|
||||
private static final String USER_AGENT = "Updater v2.1 (by Gravity) - Modified by Phoenix616 for Modrinth";
|
||||
private static final Pattern VERSION_PATTERN = Pattern.compile("(\\d+\\.\\d+(?>\\.\\d+)?)"); // Used for locating version numbers in file names
|
||||
private static final String[] NO_UPDATE_TAG = { "-DEV", "-PRE", "-SNAPSHOT" }; // If the version number contains one of these, don't update.
|
||||
private static final int BYTE_SIZE = 1024; // Used for downloading files
|
||||
private final YamlConfiguration config = new YamlConfiguration(); // Config file
|
||||
private String updateFolder;// The folder that downloads will be placed in
|
||||
private Updater.UpdateResult result = Updater.UpdateResult.SUCCESS; // Used for determining the outcome of the update process
|
||||
|
||||
/**
|
||||
|
@ -110,7 +115,11 @@ public class Updater {
|
|||
/**
|
||||
* The updater found an update, but because of the UpdateType being set to NO_DOWNLOAD, it wasn't downloaded.
|
||||
*/
|
||||
UPDATE_AVAILABLE
|
||||
UPDATE_AVAILABLE,
|
||||
/**
|
||||
* The downloaded file does not match the SHA1 hash sum provided by the api.
|
||||
*/
|
||||
FAIL_HASH,
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,27 +162,26 @@ public class Updater {
|
|||
* Initialize the updater.
|
||||
*
|
||||
* @param plugin The plugin that is checking for an update.
|
||||
* @param id The dev.bukkit.org id of the project.
|
||||
* @param id The id of the project.
|
||||
* @param file The file that the plugin is running from, get this by doing this.getFile() from within your main class.
|
||||
* @param type Specify the type of update this will be. See {@link UpdateType}
|
||||
* @param announce True if the program should announce the progress of new updates in console.
|
||||
*/
|
||||
public Updater(Plugin plugin, int id, File file, UpdateType type, boolean announce) {
|
||||
public Updater(Plugin plugin, String id, File file, UpdateType type, boolean announce) {
|
||||
this.plugin = plugin;
|
||||
this.type = type;
|
||||
this.announce = announce;
|
||||
this.file = file;
|
||||
this.id = id;
|
||||
this.updateFolder = plugin.getServer().getUpdateFolder();
|
||||
|
||||
final File pluginFile = plugin.getDataFolder().getParentFile();
|
||||
final File updaterFile = new File(pluginFile, "Updater");
|
||||
final File updaterConfigFile = new File(updaterFile, "config.yml");
|
||||
|
||||
this.config.options().header("This configuration file affects all plugins using the Updater system (version 2+ - http://forums.bukkit.org/threads/96681/ )" + '\n'
|
||||
+ "If you wish to use your API key, read http://wiki.bukkit.org/ServerMods_API and place it below." + '\n'
|
||||
this.config.options().header("This configuration file affects all plugins using the Updater system (version 2+ )" + '\n'
|
||||
+ "If you wish to use your API key, then you can get it from https://modrinth.com/settings/pats and place it below." + '\n'
|
||||
+ "Some updating systems will not adhere to the disabled value, but these may be turned off in their plugin's configuration.");
|
||||
this.config.addDefault("api-key", "PUT_API_KEY_HERE");
|
||||
this.config.addDefault("modrinth-key", "PUT_PAT_HERE");
|
||||
this.config.addDefault("disable", false);
|
||||
|
||||
if (!updaterFile.exists()) {
|
||||
|
@ -204,14 +212,14 @@ public class Updater {
|
|||
}
|
||||
|
||||
String key = this.config.getString("api-key");
|
||||
if (key.equalsIgnoreCase("PUT_API_KEY_HERE") || key.equals("")) {
|
||||
if (key != null && (key.equalsIgnoreCase("PUT_API_KEY_HERE") || key.equals(""))) {
|
||||
key = null;
|
||||
}
|
||||
|
||||
this.apiKey = key;
|
||||
|
||||
try {
|
||||
this.url = new URL(Updater.HOST + Updater.QUERY + id);
|
||||
this.url = new URL(Updater.HOST + Updater.QUERY.replace("%projectid%", id));
|
||||
} catch (final MalformedURLException e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "The project ID provided for updating, " + id + " is invalid.", e);
|
||||
this.result = UpdateResult.FAIL_BADID;
|
||||
|
@ -240,6 +248,16 @@ public class Updater {
|
|||
*/
|
||||
public ReleaseType getLatestType() {
|
||||
this.waitForThread();
|
||||
return getLatestTypeInternal();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the latest version's release type without waiting for the thread to finish.
|
||||
*
|
||||
* @return latest version's release type.
|
||||
* @see ReleaseType
|
||||
*/
|
||||
private ReleaseType getLatestTypeInternal() {
|
||||
if (this.versionType != null) {
|
||||
for (ReleaseType type : ReleaseType.values()) {
|
||||
if (this.versionType.equals(type.name().toLowerCase(Locale.ROOT))) {
|
||||
|
@ -305,57 +323,61 @@ public class Updater {
|
|||
if (!folder.exists()) {
|
||||
folder.mkdir();
|
||||
}
|
||||
BufferedInputStream in = null;
|
||||
FileOutputStream fout = null;
|
||||
try {
|
||||
// Download the file
|
||||
final URL url = new URL(link);
|
||||
final int fileLength = url.openConnection().getContentLength();
|
||||
in = new BufferedInputStream(url.openStream());
|
||||
fout = new FileOutputStream(folder.getAbsolutePath() + File.separator + file);
|
||||
final File targetFile = new File(folder, file);
|
||||
try (BufferedInputStream in = new BufferedInputStream(url.openStream());
|
||||
FileOutputStream fout = new FileOutputStream(targetFile)) {
|
||||
|
||||
final byte[] data = new byte[Updater.BYTE_SIZE];
|
||||
int count;
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("About to download a new update: " + this.versionName);
|
||||
}
|
||||
long downloaded = 0;
|
||||
while ((count = in.read(data, 0, Updater.BYTE_SIZE)) != -1) {
|
||||
downloaded += count;
|
||||
fout.write(data, 0, count);
|
||||
final int percent = (int) ((downloaded * 100) / fileLength);
|
||||
if (this.announce && ((percent % 10) == 0)) {
|
||||
this.plugin.getLogger().info("Downloading update: " + percent + "% of " + fileLength + " bytes.");
|
||||
final byte[] data = new byte[Updater.BYTE_SIZE];
|
||||
int count;
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("About to download a new update: " + this.versionName);
|
||||
}
|
||||
}
|
||||
//Just a quick check to make sure we didn't leave any files from last time...
|
||||
for (final File xFile : new File(this.plugin.getDataFolder().getParent(), this.updateFolder).listFiles()) {
|
||||
if (xFile.getName().endsWith(".zip")) {
|
||||
xFile.delete();
|
||||
long downloaded = 0;
|
||||
int lastAnnouncePercent = 0;
|
||||
while ((count = in.read(data, 0, Updater.BYTE_SIZE)) != -1) {
|
||||
downloaded += count;
|
||||
fout.write(data, 0, count);
|
||||
final int percent = (int) ((downloaded * 100) / fileLength);
|
||||
if (this.announce && lastAnnouncePercent != percent && ((percent % 10) == 0)) {
|
||||
lastAnnouncePercent = percent;
|
||||
this.plugin.getLogger().info("Downloading update: " + percent + "% of " + fileLength + " bytes.");
|
||||
}
|
||||
}
|
||||
// Check sha1 sum of the downloaded file
|
||||
if (this.versionHash != null) {
|
||||
final String fileHash = Files.asByteSource(targetFile).hash(Hashing.sha512()).toString();
|
||||
if (!this.versionHash.equalsIgnoreCase(fileHash)) {
|
||||
this.plugin.getLogger().warning("Downloaded file " + file + " does not match the remote file's SHA-1 hash");
|
||||
this.result = UpdateResult.FAIL_HASH;
|
||||
return;
|
||||
}
|
||||
}
|
||||
//Just a quick check to make sure we didn't leave any files from last time...
|
||||
File[] files = this.plugin.getServer().getUpdateFolderFile().listFiles();
|
||||
if (files != null) {
|
||||
for (final File xFile : files) {
|
||||
if (xFile.getName().endsWith(".zip")) {
|
||||
xFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check to see if it's a zip file, if it is, unzip it.
|
||||
final File dFile = new File(folder.getAbsolutePath(), file);
|
||||
if (dFile.getName().endsWith(".zip")) {
|
||||
// Unzip
|
||||
this.unzip(dFile.getCanonicalPath());
|
||||
}
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("Finished updating.");
|
||||
}
|
||||
}
|
||||
// Check to see if it's a zip file, if it is, unzip it.
|
||||
final File dFile = new File(folder.getAbsolutePath() + File.separator + file);
|
||||
if (dFile.getName().endsWith(".zip")) {
|
||||
// Unzip
|
||||
this.unzip(dFile.getCanonicalPath());
|
||||
}
|
||||
if (this.announce) {
|
||||
this.plugin.getLogger().info("Finished updating.");
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
this.plugin.getLogger().warning("The auto-updater tried to download a new update, but was unsuccessful.");
|
||||
this.result = Updater.UpdateResult.FAIL_DOWNLOAD;
|
||||
} finally {
|
||||
try {
|
||||
if (in != null) {
|
||||
in.close();
|
||||
}
|
||||
if (fout != null) {
|
||||
fout.close();
|
||||
}
|
||||
} catch (final Exception ex) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -365,21 +387,18 @@ public class Updater {
|
|||
* @param file the location of the file to extract.
|
||||
*/
|
||||
private void unzip(String file) {
|
||||
try {
|
||||
final File fSourceZip = new File(file);
|
||||
final String zipPath = file.substring(0, file.length() - 4);
|
||||
ZipFile zipFile = new ZipFile(fSourceZip);
|
||||
final File fSourceZip = new File(file);
|
||||
final String zipPath = file.substring(0, file.length() - 4);
|
||||
try (ZipFile zipFile = new ZipFile(fSourceZip)) {
|
||||
Enumeration<? extends ZipEntry> e = zipFile.entries();
|
||||
while (e.hasMoreElements()) {
|
||||
ZipEntry entry = e.nextElement();
|
||||
File destinationFilePath = new File(zipPath, entry.getName());
|
||||
destinationFilePath.getParentFile().mkdirs();
|
||||
if (entry.isDirectory()) {
|
||||
continue;
|
||||
} else {
|
||||
if (!entry.isDirectory()) {
|
||||
final BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
|
||||
int b;
|
||||
final byte buffer[] = new byte[Updater.BYTE_SIZE];
|
||||
final byte[] buffer = new byte[Updater.BYTE_SIZE];
|
||||
final FileOutputStream fos = new FileOutputStream(destinationFilePath);
|
||||
final BufferedOutputStream bos = new BufferedOutputStream(fos, Updater.BYTE_SIZE);
|
||||
while ((b = bis.read(buffer, 0, Updater.BYTE_SIZE)) != -1) {
|
||||
|
@ -390,43 +409,47 @@ public class Updater {
|
|||
bis.close();
|
||||
final String name = destinationFilePath.getName();
|
||||
if (name.endsWith(".jar") && this.pluginFile(name)) {
|
||||
destinationFilePath.renameTo(new File(this.plugin.getDataFolder().getParent(), this.updateFolder + File.separator + name));
|
||||
destinationFilePath.renameTo(new File(this.plugin.getServer().getUpdateFolderFile(),name));
|
||||
}
|
||||
}
|
||||
entry = null;
|
||||
destinationFilePath = null;
|
||||
}
|
||||
e = null;
|
||||
zipFile.close();
|
||||
zipFile = null;
|
||||
|
||||
// Move any plugin data folders that were included to the right place, Bukkit won't do this for us.
|
||||
for (final File dFile : new File(zipPath).listFiles()) {
|
||||
if (dFile.isDirectory()) {
|
||||
if (this.pluginFile(dFile.getName())) {
|
||||
final File oFile = new File(this.plugin.getDataFolder().getParent(), dFile.getName()); // Get current dir
|
||||
final File[] contents = oFile.listFiles(); // List of existing files in the current dir
|
||||
for (final File cFile : dFile.listFiles()) // Loop through all the files in the new dir
|
||||
{
|
||||
boolean found = false;
|
||||
for (final File xFile : contents) // Loop through contents to see if it exists
|
||||
{
|
||||
if (xFile.getName().equals(cFile.getName())) {
|
||||
found = true;
|
||||
break;
|
||||
File[] files = new File(zipPath).listFiles();
|
||||
if (files != null) {
|
||||
for (final File dFile : files) {
|
||||
if (dFile.isDirectory()) {
|
||||
if (this.pluginFile(dFile.getName())) {
|
||||
final File oFile = new File(this.plugin.getDataFolder().getParent(), dFile.getName()); // Get current dir
|
||||
final File[] contents = oFile.listFiles(); // List of existing files in the current dir
|
||||
final File[] newFiles = dFile.listFiles();
|
||||
if (newFiles != null) {
|
||||
for (final File cFile : newFiles) // Loop through all the files in the new dir
|
||||
{
|
||||
boolean found = false;
|
||||
if (contents != null) {
|
||||
for (final File xFile : contents) // Loop through contents to see if it exists
|
||||
{
|
||||
if (xFile.getName().equals(cFile.getName())) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Move the new file into the current dir
|
||||
cFile.renameTo(new File(oFile.getCanonicalFile(), cFile.getName()));
|
||||
} else {
|
||||
// This file already exists, so we don't need it anymore.
|
||||
cFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
// Move the new file into the current dir
|
||||
cFile.renameTo(new File(oFile.getCanonicalFile() + File.separator + cFile.getName()));
|
||||
} else {
|
||||
// This file already exists, so we don't need it anymore.
|
||||
cFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
dFile.delete();
|
||||
}
|
||||
dFile.delete();
|
||||
}
|
||||
new File(zipPath).delete();
|
||||
fSourceZip.delete();
|
||||
|
@ -444,9 +467,12 @@ public class Updater {
|
|||
* @return true if a file inside the plugins folder is named this.
|
||||
*/
|
||||
private boolean pluginFile(String name) {
|
||||
for (final File file : new File("plugins").listFiles()) {
|
||||
if (file.getName().equals(name)) {
|
||||
return true;
|
||||
File[] files = new File("plugins").listFiles();
|
||||
if (files != null) {
|
||||
for (final File file : files) {
|
||||
if (file.getName().equals(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
@ -460,11 +486,14 @@ public class Updater {
|
|||
*/
|
||||
private boolean versionCheck(String title) {
|
||||
if (this.type != UpdateType.NO_VERSION_CHECK) {
|
||||
final String localVersion = this.plugin.getDescription().getVersion();
|
||||
if (title.split(delimiter).length == 2) {
|
||||
final String remoteVersion = title.split(delimiter)[1].split(" ")[0]; // Get the newest file's version number
|
||||
final String rawLocalVersion = this.plugin.getDescription().getVersion();
|
||||
final Matcher localMatcher = Updater.VERSION_PATTERN.matcher(rawLocalVersion);
|
||||
final Matcher titleMatcher = Updater.VERSION_PATTERN.matcher(title);
|
||||
if (titleMatcher.find() && localMatcher.find()) {
|
||||
final String localVersion = localMatcher.group(1); // Get the plugins version number
|
||||
final String remoteVersion = titleMatcher.group(1); // Get the newest file's version number
|
||||
|
||||
if (this.hasTag(localVersion) || !this.shouldUpdate(localVersion, remoteVersion)) {
|
||||
if (this.hasTag(rawLocalVersion) || !this.shouldUpdate(localVersion, remoteVersion)) {
|
||||
// We already have the latest version, or this build is tagged for no-update
|
||||
this.result = Updater.UpdateResult.NO_UPDATE;
|
||||
return false;
|
||||
|
@ -506,11 +535,49 @@ public class Updater {
|
|||
* @return true if Updater should consider the remote version an update, false if not.
|
||||
*/
|
||||
public boolean shouldUpdate(String localVersion, String remoteVersion) {
|
||||
if (localVersion.contains("DEV") || getLatestType() != ReleaseType.RELEASE) {
|
||||
if (this.type != Updater.UpdateType.NO_DOWNLOAD && localVersion.contains("DEV") || getLatestTypeInternal() != ReleaseType.RELEASE) {
|
||||
return false; //Do not download alphas or betas
|
||||
}
|
||||
|
||||
return !localVersion.equalsIgnoreCase(remoteVersion);
|
||||
if (localVersion.equalsIgnoreCase(remoteVersion)) {
|
||||
return true; //Already the same version
|
||||
}
|
||||
|
||||
try {
|
||||
int[] localSemanticVersion = parseVersion(localVersion);
|
||||
int[] remoteSemanticVersion = parseVersion(remoteVersion);
|
||||
|
||||
for (int i = 0; i < localSemanticVersion.length; i++) {
|
||||
if (remoteSemanticVersion.length < i + 1) {
|
||||
return false;
|
||||
}
|
||||
if (localSemanticVersion[i] < remoteSemanticVersion[i]) {
|
||||
return true;
|
||||
} else if (localSemanticVersion[i] > remoteSemanticVersion[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} catch (NumberFormatException e) {
|
||||
this.plugin.getLogger().warning("Invalid version number found: " + localVersion + " or " + remoteVersion);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the version number from a string. This expects the version number to be consisting of numbers separated by dots.
|
||||
*
|
||||
* @param version the version string to parse
|
||||
* @return the parsed version number
|
||||
* @throws NumberFormatException if the version number is not in the expected format
|
||||
*/
|
||||
private int[] parseVersion(String version) {
|
||||
final String[] split = version.split("\\.");
|
||||
final int[] semanticVersion = new int[split.length];
|
||||
for (int i = 0; i < split.length; i++) {
|
||||
semanticVersion[i] = Integer.parseInt(split[i]);
|
||||
}
|
||||
return semanticVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -539,7 +606,7 @@ public class Updater {
|
|||
conn.setConnectTimeout(5000);
|
||||
|
||||
if (this.apiKey != null) {
|
||||
conn.addRequestProperty("X-API-Key", this.apiKey);
|
||||
conn.addRequestProperty("Authorization", this.apiKey);
|
||||
}
|
||||
conn.addRequestProperty("User-Agent", Updater.USER_AGENT);
|
||||
|
||||
|
@ -557,18 +624,26 @@ public class Updater {
|
|||
}
|
||||
|
||||
this.versionName = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.TITLE_VALUE);
|
||||
this.versionLink = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.LINK_VALUE);
|
||||
JSONArray versionFiles = (JSONArray) ((JSONObject) array.get(array.size() - 1)).get(Updater.FILES_VALUE);
|
||||
for (Object versionFile : versionFiles) {
|
||||
JSONObject file = (JSONObject) versionFile;
|
||||
if (file.get("primary").equals(true)) {
|
||||
versionLink = (String) file.get(Updater.LINK_VALUE);
|
||||
versionHash = ((JSONObject) file.get("hashes")).get("sha512").toString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.versionType = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.TYPE_VALUE);
|
||||
this.versionGameVersion = (String) ((JSONObject) array.get(array.size() - 1)).get(Updater.VERSION_VALUE);
|
||||
|
||||
JSONArray gameVersions = (JSONArray) ((JSONObject) array.get(array.size() - 1)).get(Updater.VERSION_VALUE);
|
||||
this.versionGameVersion = gameVersions.get(gameVersions.size() - 1).toString();
|
||||
return true;
|
||||
} catch (final IOException e) {
|
||||
if (e.getMessage().contains("HTTP response code: 403")) {
|
||||
this.plugin.getLogger().severe("dev.bukkit.org rejected the API key provided in plugins/Updater/config.yml");
|
||||
this.plugin.getLogger().severe("The Modrinth API server rejected the API key provided in plugins/Updater/config.yml");
|
||||
this.plugin.getLogger().severe("Please double-check your configuration to ensure it is correct.");
|
||||
this.result = UpdateResult.FAIL_APIKEY;
|
||||
} else {
|
||||
this.plugin.getLogger().severe("The updater could not contact dev.bukkit.org for updating.");
|
||||
this.plugin.getLogger().severe("The updater could not contact the api.modrinth.com server for updating.");
|
||||
this.plugin.getLogger().severe("If you have not recently modified your configuration and this is the first time you are seeing this message, the site may be experiencing temporary downtime.");
|
||||
this.result = UpdateResult.FAIL_DBO;
|
||||
}
|
||||
|
@ -592,7 +667,7 @@ public class Updater {
|
|||
final String[] split = Updater.this.versionLink.split("/");
|
||||
name = split[split.length - 1];
|
||||
}
|
||||
Updater.this.saveFile(new File(Updater.this.plugin.getDataFolder().getParent(), Updater.this.updateFolder), name, Updater.this.versionLink);
|
||||
Updater.this.saveFile(Updater.this.plugin.getServer().getUpdateFolderFile(), name, Updater.this.versionLink);
|
||||
} else {
|
||||
Updater.this.result = UpdateResult.UPDATE_AVAILABLE;
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ public class ItemUtil {
|
|||
* @return ItemStack's name
|
||||
*/
|
||||
public static String getName(ItemStack itemStack, int maxWidth) {
|
||||
String code = ChestShop.callEvent(new ItemStringQueryEvent(itemStack)).getItemString();
|
||||
String code = ChestShop.callEvent(new ItemStringQueryEvent(itemStack, maxWidth)).getItemString();
|
||||
if (code != null) {
|
||||
if (maxWidth > 0) {
|
||||
int codeWidth = getMinecraftStringWidth(code);
|
||||
|
|
|
@ -51,6 +51,9 @@ public class uBlock {
|
|||
*/
|
||||
@Deprecated
|
||||
public static org.bukkit.block.Chest findConnectedChest(Sign sign) {
|
||||
if (!BlockUtil.isLoaded(sign.getBlock())) {
|
||||
return null;
|
||||
}
|
||||
BlockFace signFace = null;
|
||||
BlockData data = sign.getBlockData();
|
||||
if (data instanceof WallSign) {
|
||||
|
@ -79,6 +82,10 @@ public class uBlock {
|
|||
*/
|
||||
@Deprecated
|
||||
private static org.bukkit.block.Chest findConnectedChest(Block block, BlockFace signFace) {
|
||||
if (!BlockUtil.isLoaded(block)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (signFace != null) {
|
||||
Block faceBlock = block.getRelative(signFace);
|
||||
if (BlockUtil.isChest(faceBlock)) {
|
||||
|
@ -98,6 +105,10 @@ public class uBlock {
|
|||
}
|
||||
|
||||
public static Container findConnectedContainer(Sign sign) {
|
||||
if (!BlockUtil.isLoaded(sign.getBlock())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BlockFace signFace = null;
|
||||
BlockData data = sign.getBlockData();
|
||||
if (data instanceof WallSign) {
|
||||
|
@ -107,6 +118,10 @@ public class uBlock {
|
|||
}
|
||||
|
||||
public static Container findConnectedContainer(Block block) {
|
||||
if (!BlockUtil.isLoaded(block)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BlockFace signFace = null;
|
||||
BlockData data = block.getBlockData();
|
||||
if (data instanceof WallSign) {
|
||||
|
@ -134,6 +149,7 @@ public class uBlock {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Sign findValidShopSign(Block block, String originalName) {
|
||||
Sign ownerShopSign = null;
|
||||
|
||||
|
@ -205,7 +221,7 @@ public class uBlock {
|
|||
Sign sign = (Sign) faceBlock.getState();
|
||||
|
||||
Container signContainer = findConnectedContainer(sign);
|
||||
if (!chestBlock.equals(signContainer.getBlock())) {
|
||||
if (signContainer == null || !chestBlock.equals(signContainer.getBlock())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -220,8 +236,17 @@ public class uBlock {
|
|||
public static Sign findAnyNearbyShopSign(Block block) {
|
||||
for (BlockFace bf : SHOP_FACES) {
|
||||
Block faceBlock = block.getRelative(bf);
|
||||
if (!BlockUtil.isLoaded(faceBlock)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!BlockUtil.isSign(faceBlock)) {
|
||||
BlockData data = faceBlock.getBlockData();
|
||||
if (data instanceof WallSign) {
|
||||
if (((WallSign) data).getFacing() != bf
|
||||
&& couldBeShopContainer(faceBlock.getRelative(((WallSign) data).getFacing().getOppositeFace()))) {
|
||||
continue;
|
||||
}
|
||||
} else if (!(data instanceof org.bukkit.block.data.type.Sign)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -240,6 +265,10 @@ public class uBlock {
|
|||
}
|
||||
|
||||
public static Block findNeighbor(Block block) {
|
||||
if (!BlockUtil.isLoaded(block)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
BlockData blockData = block.getBlockData();
|
||||
if (!(blockData instanceof Chest)) {
|
||||
return null;
|
||||
|
@ -268,6 +297,10 @@ public class uBlock {
|
|||
}
|
||||
|
||||
Block neighborBlock = block.getRelative(chestFace);
|
||||
if (!BlockUtil.isLoaded(neighborBlock)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (neighborBlock.getType() == block.getType()) {
|
||||
return neighborBlock;
|
||||
}
|
||||
|
@ -280,10 +313,11 @@ public class uBlock {
|
|||
}
|
||||
|
||||
public static boolean couldBeShopContainer(Block block) {
|
||||
return block != null && Properties.SHOP_CONTAINERS.contains(block.getType());
|
||||
return block != null && BlockUtil.isLoaded(block) && Properties.SHOP_CONTAINERS.contains(block.getType());
|
||||
}
|
||||
|
||||
public static boolean couldBeShopContainer(InventoryHolder holder) {
|
||||
return holder instanceof Container && couldBeShopContainer(((Container) holder).getBlock());
|
||||
return (holder instanceof Container && couldBeShopContainer(((Container) holder).getBlock()))
|
||||
|| (holder instanceof DoubleChest && couldBeShopContainer(((DoubleChest) holder).getLeftSide()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,10 +51,11 @@ INVALID_SHOP_DETECTED: "The shop cannot be used!"
|
|||
INVALID_SHOP_PRICE: "The shop has an invalid price!"
|
||||
INVALID_SHOP_QUANTITY: "The shop has an invalid quantity!"
|
||||
CANNOT_ACCESS_THE_CHEST: "You don't have permissions to access this chest!"
|
||||
SELL_PRICE_ABOVE_MAX: "Sell price is above maximum!"
|
||||
SELL_PRICE_BELOW_MIN: "Sell price is below minimum!"
|
||||
BUY_PRICE_ABOVE_MAX: "Buy price is above maximum!"
|
||||
BUY_PRICE_BELOW_MIN: "Buy price is below minimum!"
|
||||
SELL_PRICE_HIGHER_THAN_BUY_PRICE: "Sell price is above the buy price!"
|
||||
SELL_PRICE_ABOVE_MAX: "Sell price %price is above maximum %maxprice!"
|
||||
SELL_PRICE_BELOW_MIN: "Sell price %price is below minimum %minprice!"
|
||||
BUY_PRICE_ABOVE_MAX: "Buy price %price is above maximum %maxprice!"
|
||||
BUY_PRICE_BELOW_MIN: "Buy price %price is below minimum %minprice!"
|
||||
CLICK_TO_AUTOFILL_ITEM: "Click the sign with the item that this shop is for!"
|
||||
NO_ITEM_IN_HAND: "You don't have an item in your hand to autofill!"
|
||||
PROTECTED_SHOP: "Successfully protected the shop with LWC!"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
prefix: "&a[Shop] &r"
|
||||
prefix: "&a[متجر]&r"
|
||||
shopinfo: |-
|
||||
&aShop Information:
|
||||
&fOwner: &7%owner
|
||||
|
@ -51,10 +51,11 @@ INVALID_SHOP_DETECTED: "The shop cannot be used!"
|
|||
INVALID_SHOP_PRICE: "The shop has an invalid price!"
|
||||
INVALID_SHOP_QUANTITY: "The shop has an invalid quantity!"
|
||||
CANNOT_ACCESS_THE_CHEST: "You don't have permissions to access this chest!"
|
||||
SELL_PRICE_ABOVE_MAX: "Sell price is above maximum!"
|
||||
SELL_PRICE_BELOW_MIN: "Sell price is below minimum!"
|
||||
BUY_PRICE_ABOVE_MAX: "Buy price is above maximum!"
|
||||
BUY_PRICE_BELOW_MIN: "Buy price is below minimum!"
|
||||
SELL_PRICE_HIGHER_THAN_BUY_PRICE: "Sell price is above the buy price!"
|
||||
SELL_PRICE_ABOVE_MAX: "Sell price %price is above maximum %maxprice!"
|
||||
SELL_PRICE_BELOW_MIN: "Sell price %price is below minimum %minprice!"
|
||||
BUY_PRICE_ABOVE_MAX: "Buy price %price is above maximum %maxprice!"
|
||||
BUY_PRICE_BELOW_MIN: "Buy price %price is below minimum %minprice!"
|
||||
CLICK_TO_AUTOFILL_ITEM: "Click the sign with the item that this shop is for!"
|
||||
NO_ITEM_IN_HAND: "You don't have an item in your hand to autofill!"
|
||||
PROTECTED_SHOP: "Successfully protected the shop with LWC!"
|
||||
|
|
|
@ -51,10 +51,11 @@ INVALID_SHOP_DETECTED: "The shop cannot be used!"
|
|||
INVALID_SHOP_PRICE: "The shop has an invalid price!"
|
||||
INVALID_SHOP_QUANTITY: "The shop has an invalid quantity!"
|
||||
CANNOT_ACCESS_THE_CHEST: "You don't have permissions to access this chest!"
|
||||
SELL_PRICE_ABOVE_MAX: "Sell price is above maximum!"
|
||||
SELL_PRICE_BELOW_MIN: "Sell price is below minimum!"
|
||||
BUY_PRICE_ABOVE_MAX: "Buy price is above maximum!"
|
||||
BUY_PRICE_BELOW_MIN: "Buy price is below minimum!"
|
||||
SELL_PRICE_HIGHER_THAN_BUY_PRICE: "Sell price is above the buy price!"
|
||||
SELL_PRICE_ABOVE_MAX: "Sell price %price is above maximum %maxprice!"
|
||||
SELL_PRICE_BELOW_MIN: "Sell price %price is below minimum %minprice!"
|
||||
BUY_PRICE_ABOVE_MAX: "Buy price %price is above maximum %maxprice!"
|
||||
BUY_PRICE_BELOW_MIN: "Buy price %price is below minimum %minprice!"
|
||||
CLICK_TO_AUTOFILL_ITEM: "Click the sign with the item that this shop is for!"
|
||||
NO_ITEM_IN_HAND: "You don't have an item in your hand to autofill!"
|
||||
PROTECTED_SHOP: "Successfully protected the shop with LWC!"
|
||||
|
|
|
@ -51,10 +51,11 @@ INVALID_SHOP_DETECTED: "Obchod není možné použít!"
|
|||
INVALID_SHOP_PRICE: "Obchod má neplatnou cenu!"
|
||||
INVALID_SHOP_QUANTITY: "Obchod má neplatné množství!"
|
||||
CANNOT_ACCESS_THE_CHEST: "Nemáš právo otevírat tuto truhlu!"
|
||||
SELL_PRICE_ABOVE_MAX: "Prodejní cena je vyšší než nastavené maximum!"
|
||||
SELL_PRICE_BELOW_MIN: "Prodejní cena je nižší než nastavené minimum!"
|
||||
BUY_PRICE_ABOVE_MAX: "Nákupní cena je vyšší než nastavené maximum!"
|
||||
BUY_PRICE_BELOW_MIN: "Nákupní cena je nižší než nastavené maximum!"
|
||||
SELL_PRICE_HIGHER_THAN_BUY_PRICE: "Prodejní cena je vyšší než kupní cena!"
|
||||
SELL_PRICE_ABOVE_MAX: "Prodejní cena %price vyšší než maximální %maxprice!"
|
||||
SELL_PRICE_BELOW_MIN: "Prodejní cena %price je nižší než minimální %minprice!"
|
||||
BUY_PRICE_ABOVE_MAX: "Kupní cena %price vyšší než maximální %maxprice!"
|
||||
BUY_PRICE_BELOW_MIN: "Kupní cena %price je nižší než minimální %minprice!"
|
||||
CLICK_TO_AUTOFILL_ITEM: "Klikni na ceduli s předmětem, který chceš prodávat!"
|
||||
NO_ITEM_IN_HAND: "Nemáš v ruce předmět, automatické předvyplnění není možné!"
|
||||
PROTECTED_SHOP: "Obchod úspěšně ochráněn pomocí LWC!"
|
||||
|
|
|
@ -51,10 +51,11 @@ INVALID_SHOP_DETECTED: "The shop cannot be used!"
|
|||
INVALID_SHOP_PRICE: "The shop has an invalid price!"
|
||||
INVALID_SHOP_QUANTITY: "The shop has an invalid quantity!"
|
||||
CANNOT_ACCESS_THE_CHEST: "You don't have permissions to access this chest!"
|
||||
SELL_PRICE_ABOVE_MAX: "Sell price is above maximum!"
|
||||
SELL_PRICE_BELOW_MIN: "Sell price is below minimum!"
|
||||
BUY_PRICE_ABOVE_MAX: "Buy price is above maximum!"
|
||||
BUY_PRICE_BELOW_MIN: "Buy price is below minimum!"
|
||||
SELL_PRICE_HIGHER_THAN_BUY_PRICE: "Sell price is above the buy price!"
|
||||
SELL_PRICE_ABOVE_MAX: "Sell price %price is above maximum %maxprice!"
|
||||
SELL_PRICE_BELOW_MIN: "Sell price %price is below minimum %minprice!"
|
||||
BUY_PRICE_ABOVE_MAX: "Buy price %price is above maximum %maxprice!"
|
||||
BUY_PRICE_BELOW_MIN: "Buy price %price is below minimum %minprice!"
|
||||
CLICK_TO_AUTOFILL_ITEM: "Click the sign with the item that this shop is for!"
|
||||
NO_ITEM_IN_HAND: "You don't have an item in your hand to autofill!"
|
||||
PROTECTED_SHOP: "Successfully protected the shop with LWC!"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue