Compare commits
43 Commits
Author | SHA1 | Date | |
---|---|---|---|
0d077ccdbb | |||
1bc03d7670 | |||
f192a5a2b5 | |||
bd00a59d08 | |||
8423eabc57 | |||
488d4c7589 | |||
753c7c6275 | |||
a856aa03e0 | |||
913cc5736e | |||
a5ae3cb295 | |||
7d940ee334 | |||
ea54492ccf | |||
30b8507b9f | |||
c5ffa2b0c4 | |||
a9cfea2d32 | |||
1bab972c13 | |||
d1c549fd20 | |||
c9ff3af6ac | |||
5089a721a0 | |||
a036c39dc3 | |||
a501a3cbb4 | |||
7875e9a705 | |||
ac5f032ce9 | |||
7784ee46a5 | |||
3c805ee284 | |||
3c4394d6fa | |||
d0f4ff11b7 | |||
ee2b503886 | |||
89c1c4a56c | |||
012d1df099 | |||
10bfd29468 | |||
849e9d7a9d | |||
89d1f79f7d | |||
36e254c0df | |||
05440e66a0 | |||
4d740521f3 | |||
b38cfbe710 | |||
cc7d66f270 | |||
39e164c9c8 | |||
9f433cb0f1 | |||
64004e4267 | |||
3c677c18cb | |||
9b1480453b |
33
Jenkinsfile
vendored
Normal file
33
Jenkinsfile
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
pipeline {
|
||||
agent any
|
||||
tools {
|
||||
jdk 'JDK17'
|
||||
}
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
echo 'Building...'
|
||||
sh 'mvn clean & mvn validate & mvn compile'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
echo 'Testing...'
|
||||
sh 'mvn test'
|
||||
}
|
||||
}
|
||||
stage('Verify') {
|
||||
steps {
|
||||
echo 'Verifying...'
|
||||
sh 'mvn verify -Dmaven.test.skip=true'
|
||||
}
|
||||
}
|
||||
stage('Deploy') {
|
||||
steps {
|
||||
echo 'Deploying...'
|
||||
sh 'mvn deploy -Dmaven.install.skip=true -Dmaven.test.skip=true'
|
||||
archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
194
README.md
194
README.md
@ -10,7 +10,7 @@ fee. Costs are highly customizable.
|
||||
- By default, natural cost is used. The original fork made it cheaper the more damaged an item is, but natural cost
|
||||
makes the cost increase the more damaged the item is.
|
||||
- EnchantmentTarget is used instead of a hard-coded list of repairable items
|
||||
- All settings (except default reforge-able-items), both global and for each blacksmith, can be changed using commands,
|
||||
- All settings, both global and for each blacksmith, can be changed using commands,
|
||||
and support tab-completion.
|
||||
- This plugin is not directly compatible with the original. If you are using the old one, you will need to set it up
|
||||
again!
|
||||
@ -19,12 +19,16 @@ fee. Costs are highly customizable.
|
||||
|
||||
- Citizens2
|
||||
- Vault
|
||||
- Any Vault-supported Economy plugin
|
||||
|
||||
## Basic usage
|
||||
|
||||
To create a new blacksmith, simply add the blacksmith trait to an NPC. Right-clicking the NPC will tell you if the
|
||||
currently held item is repairable by the blacksmith. If it is, the blacksmith should give a price quote. Right-clicking
|
||||
again starts the repair. The item should be given back or dropped after a random delay according to the set limits.
|
||||
To create a new blacksmith, simply add the blacksmith trait to an NPC by selecting it with `/npc select`, and then using
|
||||
`/trait add Blacksmith` (See Citizens' documentation for more details).
|
||||
|
||||
Right-clicking the NPC will tell you if the currently held item is repairable by the blacksmith. If it is, the
|
||||
blacksmith should give a price quote. Right-clicking again starts the repair. The item should be given back or dropped
|
||||
after a random delay according to the set limits.
|
||||
|
||||
While costs are always set globally (no blacksmith can do the same job for cheaper), the blacksmith's messages,
|
||||
cool-down between each reforge, whether the item is dropped or given, the chance of failing or adding an enchantment,
|
||||
@ -43,111 +47,149 @@ In addition to just being able to repair items, blacksmiths have some random fea
|
||||
- There is a chance that blacksmiths fail to repair an item, leaving it at about the same durability as before. Use
|
||||
failReforgeChance to control the chance. Set it to 0 to remove the feature.
|
||||
- There is a chance a blacksmith may add an enchantment to a reforged item. You can control the probability using
|
||||
extraEnchantmentChance, and set the maximum number of enchantments using maxEnchantments
|
||||
extraEnchantmentChance, and set the maximum number of enchantments using maxEnchantments. EnchantmentBlocklist can be
|
||||
used to block any enchantments you don't want to randomly grant.
|
||||
|
||||
## Commands
|
||||
|
||||
| Command | Arguments | Description |
|
||||
| --- | --- | --- |
|
||||
| /blacksmith | \<option> \[new-value] | Changes a configuration option for the selected blacksmith (use Citizens' /npc select first) |
|
||||
| /blacksmithconfig | \<reload/option> \[new-value] | Changes a default/global configuration value |
|
||||
| /preset | \<preset>\[:filter] | Displays all materials included in the given preset, after applying the filter if set |
|
||||
| Command | Arguments | Description |
|
||||
|-------------------|-------------------------------|----------------------------------------------------------------------------------------------|
|
||||
| /blacksmith | \<option> \[new-value] | Changes a configuration option for the selected blacksmith (use Citizens' /npc select first) |
|
||||
| /blacksmithconfig | \<reload/option> \[new-value] | Changes a default/global configuration value |
|
||||
| /preset | \<preset>\[:filter] | Displays all materials included in the given preset, after applying the filter if set |
|
||||
|
||||
For /blacksmith and /blacksmithconfig, if a new value isn't specified, the current value is displayed instead.
|
||||
|
||||
For /blacksmith, using "" or null as the value will clear a custom value, making the NPC use the default value set in
|
||||
the config instead. Additionally, every value overridden for an NPC will display a marker (default \[NPC]) when
|
||||
For /blacksmith, using -1 or null as the value will clear a custom value, making the NPC use the default value set in
|
||||
the config instead. Additionally, every value overridden for an NPC will display a marker (default: \[NPC]) when
|
||||
displaying the current value.
|
||||
|
||||
Note: basePrice, pricePerDurabilityPoint and enchantmentCost can be set like: `/blacksmithconfig option 4` or
|
||||
like `/blacksmithconfig option material/enchantment 4` depending on whether you are setting the default or an override
|
||||
for a specific material/enchantment.
|
||||
for a specific material/enchantment. For /blacksmithconfig <basePrice/pricePerDurabilityPoint/enchantmentCost> <
|
||||
material/enchantment>, using -1 or null as the value will clear the cost for the specified material/enchantment, using
|
||||
the default one instead.
|
||||
|
||||
basePrice and pricePerDurabilityPoint support using a wildcard "*" to set the price for multiple groups of materials at
|
||||
once. `/blacksmithconfig basePrice golden* 43` would set the price of any material starting with "GOLDEN" to 43. You can
|
||||
also set `netherite*: 34` directly in the config file to set the price of all netherite materials to 34.
|
||||
|
||||
### Presets and filters:
|
||||
|
||||
Note: All of these can be used when specifying reforge-able items, such as "preset:weapon-smith:bow,preset:armor_smith:
|
||||
gold,PRESET:TOOL_SMITH,shield"
|
||||
**Presets are a nice way to make specialized blacksmiths by specifying categories of materials, instead of manually
|
||||
listing every material manually. They can only be used for the `reforgeAbleItems` option.**
|
||||
|
||||
Note: All of these can be used when specifying reforge-able items, such as
|
||||
"preset:weapon-smith:bow,preset:armor_smith:gold,PRESET:TOOL_SMITH,shield"
|
||||
|
||||
The format of reforge-able items requires each preset/material to be separated by a comma. If specifying a preset
|
||||
instead of a material, start by typing "preset:". Then you can type BLACKSMITH, WEAPON_SMITH, ARMOR_SMITH or TOOL_SMITH.
|
||||
If you want, you can add another colon and one of the filters supported by the preset.
|
||||
For example: "preset:WEAPON_SMITH:BOW" to make the blacksmith only repair bows and crossbows. You can use the same
|
||||
preset several times with different filters. For example: "preset:ARMOR_SMITH:DIAMOND,preset:ARMOR_SMITH:NETHERITE"
|
||||
would allow the blacksmith to repair all diamond and netherite armor.
|
||||
|
||||
Presets and filters can also be negated by applying a "-" character in front of the material name. For example,
|
||||
"-SHIELD" would make shields unrepairable, even if included in a listed preset. "preset:WEAPON_SMITH,-SHIELD"
|
||||
would allow the blacksmith to repair any weapon included in the WEAPON_SMITH preset except shields.
|
||||
"preset:BLACKSMITH,-ELYTRA"would allow the blacksmith to repair any repairable item, except elytra. You can also negate
|
||||
entire presets or filters. For example: "preset:blacksmith,-preset:armor-smith:diamond" would allow a blacksmith to
|
||||
repair all items, except diamond armor.
|
||||
|
||||
All currently supported presets, and available filters for each preset:
|
||||
|
||||
- WEAPON_SMITH:
|
||||
- BOW
|
||||
- SWORD
|
||||
- RANGED
|
||||
- ARMOR_SMITH:
|
||||
- LEATHER
|
||||
- IRON
|
||||
- CHAINMAIL
|
||||
- GOLD
|
||||
- DIAMOND
|
||||
- NETHERITE
|
||||
- HELMET
|
||||
- BOOTS
|
||||
- LEGGINGS
|
||||
- CHESTPLATE
|
||||
- TOOL_SMITH
|
||||
- WOOD
|
||||
- STONE
|
||||
- IRON
|
||||
- GOLD
|
||||
- DIAMOND
|
||||
- NETHERITE
|
||||
- PICKAXE
|
||||
- AXE
|
||||
- HOE
|
||||
- SHOVEL
|
||||
- MISC
|
||||
- BLACKSMITH (WEAPON_SMITH + ARMOR_SMITH + TOOL_SMITH)
|
||||
- WEAPON_SMITH: (RANGED + SWORD + SHIELD)
|
||||
- BOW (bows and crossbows)
|
||||
- SWORD (swords)
|
||||
- RANGED (bows, crossbows and tridents)
|
||||
- ARMOR_SMITH: (HELMET + BOOTS + LEGGINGS + CHESTPLATE + ELYTRA)
|
||||
- LEATHER (all pieces of leather armor)
|
||||
- IRON (all pieces of iron armor)
|
||||
- CHAINMAIL (all pieces of chainmail armor)
|
||||
- GOLD (all pieces of gold armor)
|
||||
- DIAMOND (all pieces of diamond armor)
|
||||
- NETHERITE (all pieces of netherite armor)
|
||||
- HELMET (all helmets)
|
||||
- BOOTS (all boots)
|
||||
- LEGGINGS (all leggings)
|
||||
- CHESTPLATE (all chest-plates)
|
||||
- TOOL_SMITH: (PICKAXE + AXE + HOE + SHOVEL + MISC)
|
||||
- WOOD (all wood tools)
|
||||
- STONE (all stone tools)
|
||||
- IRON (all iron tools)
|
||||
- GOLD (all gold tools)
|
||||
- DIAMOND (all diamond tools)
|
||||
- NETHERITE (all netherite tools)
|
||||
- PICKAXE (all pickaxes)
|
||||
- AXE (all axes)
|
||||
- HOE (all hoes)
|
||||
- SHOVEL (all shovels)
|
||||
- MISC (FISHING_ROD + SHEARS + FLINT_AND_STEEL)
|
||||
|
||||
## Permissions
|
||||
|
||||
| Permission node | Description |
|
||||
| --- | --- |
|
||||
| blacksmith.admin | Allows overall blacksmith configuration |
|
||||
| blacksmith.edit | Allows changing settings for the selected blacksmith NPC |
|
||||
| blacksmith.use | Allows the player to repair items using blacksmiths |
|
||||
| Permission node | Description |
|
||||
|------------------|----------------------------------------------------------|
|
||||
| blacksmith.admin | Allows overall blacksmith configuration |
|
||||
| blacksmith.edit | Allows changing settings for the selected blacksmith NPC |
|
||||
| blacksmith.use | Allows the player to repair items using blacksmiths |
|
||||
|
||||
## Configuration options
|
||||
|
||||
### Plugin Options
|
||||
|
||||
| Key | Value type | Description |
|
||||
|----------|------------|----------------------------------------------------------------------------------------------|
|
||||
| language | string | The language used for this plugin. Only "en" is supported, unless you add a custom language. |
|
||||
|
||||
### Global-only options
|
||||
|
||||
| Key | Value type | Description |
|
||||
| --- | --- | --- |
|
||||
| basePrice | positive decimal number | The base price which has to be paid regardless of the durability remaining for an item. Setting this without specifying a material sets the basePrice for any item the basePrice has not been set for. |
|
||||
| pricePerDurabilityPoint | positive decimal number | The price added for each durability point present/missing (depends on whether natural cost is set to true or false). Setting this without specifying a material sets the pricePerDurabilityPoint for any item the pricePerDurabilityPoint has not been set for. |
|
||||
| enchantmentCost | positive decimal number | The added cost for each level of an enchantment present on the item. The cost can be set for specific enchantments. Not specifying an enchantment sets the value for all enchantments without a set value.
|
||||
| useNaturalCost | true/false | If true, each missing durability will add to the cost (price = basePrice + missingDurability * pricePerDurabilityPoint + enchantmentCost). If false, durability will be used to calculate the cost instead of missingDurability (this was the behavior before natural cost was added). |
|
||||
| Key | Value type | Description |
|
||||
|---------------------------|-------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| basePrice | positive decimal number | The base price which has to be paid regardless of the durability remaining for an item. Setting this without specifying a material sets the basePrice for any item the basePrice has not been set for. You can use for example "netherite*: 10" to set the value for any material beginning with "netherite". |
|
||||
| pricePerDurabilityPoint | positive decimal number | The price added for each durability point present/missing (depends on whether natural cost is set to true or false). Setting this without specifying a material sets the pricePerDurabilityPoint for any item the pricePerDurabilityPoint has not been set for. You can use for example "netherite*: 10" to set the value for any material beginning with "netherite". |
|
||||
| enchantmentCost | positive decimal number | The added cost for each level of an enchantment present on the item. The cost can be set for specific enchantments. Not specifying an enchantment sets the value for all enchantments without a set value. |
|
||||
| useNaturalCost | true/false | If true, each missing durability will add to the cost (price = basePrice + missingDurability * pricePerDurabilityPoint + enchantmentCost). If false, durability will be used to calculate the cost instead of missingDurability (this was the behavior before natural cost was added). |
|
||||
| showExactTime | true/false | If true, blacksmiths will display exact time remaining in minutes and seconds, instead of vague expressions |
|
||||
| chippedAnvilReforgingCost | positive decimal number | The price for reforging a chipped anvil (slightly damaged). No other costs apply! |
|
||||
| damagedAnvilReforgingCost | positive decimal number | The price for reforging a damaged anvil (very damaged). No other costs apply! |
|
||||
|
||||
### Per-npc (with default values set in config.yml)
|
||||
|
||||
#### Configuration values
|
||||
|
||||
| Key | Value type | Description |
|
||||
| --- | --- | --- |
|
||||
| dropItem | true/false | Whether the blacksmith should drop the repaired item on the ground (instead of putting it into the player's inventory). |
|
||||
| disableCoolDown | true/false | Whether to completely disable the cool-down between repairs. |
|
||||
| disableDelay | true/false | Whether to completely disable the delay required to reforge an item. |
|
||||
| failReforgeChance | 0-100 | The chance of the blacksmith failing to repair an item. |
|
||||
| extraEnchantmentChance | 0-100 | The chance of the blacksmith adding an enchantment to an item. |
|
||||
| maxEnchantments | 0-10 | The maximum number of different enchantments a blacksmith can add. |
|
||||
| maxReforgeDelay | 0-3600 | The maximum number of seconds a player needs to wait for an item to be repaired. |
|
||||
| minReforgeDelay | 0-3600 | The minimum number of seconds a player needs to wait for an item to be repaired. |
|
||||
| reforgeCoolDown | 0-3600 | The cool-down, in seconds, a player has to wait between each time they use one specific blacksmith. |
|
||||
| reforgeAbleItems | DIAMOND_LEGGINGS,GOLD-pickaxe,bow, etc. | Specifies which items this blacksmith is able to reforge. If set to "" or null, all normally repairable items can be repaired. If set to a list of items, only the items specified can be repaired. Some presets have been included for ease of use. Use a preset by specifying "preset:sword-smith" instead of a material such as "gold-pickaxe". Available presets: SWORD_SMITH, WEAPON_SMITH, ARMOR_SMITH, TOOL_SMITH, RANGED_SMITH. |
|
||||
| Key | Value type | Description |
|
||||
|------------------------|-----------------------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| dropItem | true/false | Whether the blacksmith should drop the repaired item on the ground (instead of putting it into the player's inventory). |
|
||||
| disableCoolDown | true/false | Whether to completely disable the cool-down between repairs. |
|
||||
| disableDelay | true/false | Whether to completely disable the delay required to reforge an item. |
|
||||
| failReforgeChance | 0-100 | The chance of the blacksmith failing to repair an item. |
|
||||
| extraEnchantmentChance | 0-100 | The chance of the blacksmith adding an enchantment to an item. |
|
||||
| maxEnchantments | 0-10 | The maximum number of different enchantments a blacksmith can add. |
|
||||
| maxReforgeDelay | 0-3600 | The maximum number of seconds a player needs to wait for an item to be repaired. |
|
||||
| minReforgeDelay | 0-3600 | The minimum number of seconds a player needs to wait for an item to be repaired. |
|
||||
| reforgeCoolDown | 0-3600 | The cool-down, in seconds, a player has to wait between each time they use one specific blacksmith. |
|
||||
| reforgeAbleItems | DIAMOND_LEGGINGS,GOLD-pickaxe,bow, etc. | Specifies which items this blacksmith is able to reforge. If set to "" or null, all normally repairable items can be repaired. If set to a list of items, only the items specified can be repaired. Some presets have been included for ease of use. Use a preset by specifying "preset:sword-smith" instead of a material such as "gold-pickaxe". |
|
||||
| blacksmithTitle | text string | The title displayed as part of the message explaining that a blacksmith doesn't recognize a player's held item |
|
||||
| enchantmentBlocklist | string list | A string list of all enchantments a blacksmith should not be allowed to add to items. |
|
||||
| reforgeAnvils | true/false | Whether to allow the blacksmith to reforge anvils. If enabled, chipped and damaged anvils will be replaced with a normal anvil. |
|
||||
|
||||
#### Messages
|
||||
|
||||
| Message Key | Explanation |
|
||||
| --- | --- |
|
||||
| busyPlayerMessage | The message displayed when the blacksmith is serving another player |
|
||||
| busyReforgeMessage | The message displayed when the blacksmith is busy reforging an item |
|
||||
| Message Key | Explanation |
|
||||
|--------------------------|-----------------------------------------------------------------------------------------------------------------|
|
||||
| busyPlayerMessage | The message displayed when the blacksmith is serving another player |
|
||||
| busyReforgeMessage | The message displayed when the blacksmith is busy reforging an item |
|
||||
| coolDownUnexpiredMessage | The message displayed when the player has to wait for the cool-down to expire before using the blacksmith again |
|
||||
| costMessage | The message displayed when telling a player about the cost of repairing an item |
|
||||
| failReforgeMessage | The message displayed when a blacksmith fails to reforge an item |
|
||||
| insufficientFundsMessage | The message displayed when a player is unable to pay for reforging an item |
|
||||
| invalidItemMessage | The message displayed when a blacksmith is presented an item which it cannot repair |
|
||||
| itemChangedMessage | The message displayed when a player changes their item after being shown the repair cost |
|
||||
| startReforgeMessage | The message displayed when a blacksmith starts reforging an item |
|
||||
| successMessage | The message displayed when a blacksmith successfully repairs an item |
|
||||
| costMessage | The message displayed when telling a player about the cost of repairing an item |
|
||||
| failReforgeMessage | The message displayed when a blacksmith fails to reforge an item |
|
||||
| insufficientFundsMessage | The message displayed when a player is unable to pay for reforging an item |
|
||||
| invalidItemMessage | The message displayed when a blacksmith is presented an item which it cannot repair |
|
||||
| itemChangedMessage | The message displayed when a player changes their item after being shown the repair cost |
|
||||
| startReforgeMessage | The message displayed when a blacksmith starts reforging an item |
|
||||
| successMessage | The message displayed when a blacksmith successfully repairs an item |
|
||||
| notDamagedMessage | The message displayed if a player tries to reforge an item with full durability |
|
||||
|
||||
## Language customization
|
||||
|
||||
|
85
pom.xml
85
pom.xml
@ -6,31 +6,46 @@
|
||||
|
||||
<groupId>net.knarcraft</groupId>
|
||||
<artifactId>blacksmith</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<version>1.0.4</version>
|
||||
<name>Blacksmith</name>
|
||||
<description>Blacksmith Character for the CitizensAPI</description>
|
||||
<description>Blacksmith NPC for the Citizens API</description>
|
||||
|
||||
<!-- Properties -->
|
||||
<properties>
|
||||
<java.version>16</java.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<build.number>Unknown</build.number>
|
||||
</properties>
|
||||
|
||||
<!-- Repositories -->
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>knarcraft-repo</id>
|
||||
<url>https://git.knarcraft.net/api/packages/EpicKnarvik97/maven</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>citizens-repo</id>
|
||||
<url>http://repo.citizensnpcs.co/</url>
|
||||
<url>https://repo.citizensnpcs.co/</url>
|
||||
</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>
|
||||
</repositories>
|
||||
<distributionManagement>
|
||||
<repository>
|
||||
<id>knarcraft-repo</id>
|
||||
<url>https://git.knarcraft.net/api/packages/EpicKnarvik97/maven</url>
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<id>knarcraft-repo</id>
|
||||
<url>https://git.knarcraft.net/api/packages/EpicKnarvik97/maven</url>
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
<!-- Dependencies -->
|
||||
<dependencies>
|
||||
@ -50,7 +65,7 @@
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.19.2-R0.1-SNAPSHOT</version>
|
||||
<version>1.19.3-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
@ -62,34 +77,66 @@
|
||||
<dependency>
|
||||
<groupId>org.jetbrains</groupId>
|
||||
<artifactId>annotations</artifactId>
|
||||
<version>23.0.0</version>
|
||||
<version>23.1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.knarcraft</groupId>
|
||||
<artifactId>knarlib</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<!-- Build information -->
|
||||
<build>
|
||||
<defaultGoal>clean package install</defaultGoal>
|
||||
<resources>
|
||||
<resource>
|
||||
<filtering>true</filtering>
|
||||
<directory>${basedir}/src/main/resources</directory>
|
||||
<includes>
|
||||
<include>*.yml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.7.0</version>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<source>16</source>
|
||||
<target>16</target>
|
||||
<source>${java.version}</source>
|
||||
<target>${java.version}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>3.2.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||
<filters>
|
||||
<filter>
|
||||
<artifact>net.knarcraft:knarlib</artifact>
|
||||
<includes>
|
||||
<include>net/knarcraft/knarlib/**</include>
|
||||
</includes>
|
||||
</filter>
|
||||
<filter>
|
||||
<excludes>
|
||||
<exclude>*.MF</exclude>
|
||||
<exclude>*.yml</exclude>
|
||||
</excludes>
|
||||
</filter>
|
||||
</filters>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
@ -8,11 +8,15 @@ import net.knarcraft.blacksmith.command.BlackSmithEditTabCompleter;
|
||||
import net.knarcraft.blacksmith.command.PresetCommand;
|
||||
import net.knarcraft.blacksmith.command.PresetTabCompleter;
|
||||
import net.knarcraft.blacksmith.config.GlobalSettings;
|
||||
import net.knarcraft.blacksmith.formatting.Translator;
|
||||
import net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage;
|
||||
import net.knarcraft.blacksmith.listener.NPCClickListener;
|
||||
import net.knarcraft.blacksmith.listener.PlayerListener;
|
||||
import net.knarcraft.blacksmith.manager.EconomyManager;
|
||||
import net.knarcraft.blacksmith.trait.BlacksmithTrait;
|
||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||
import net.knarcraft.knarlib.formatting.TranslatableTimeUnit;
|
||||
import net.knarcraft.knarlib.formatting.Translator;
|
||||
import net.knarcraft.knarlib.util.UpdateChecker;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.configuration.file.FileConfiguration;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
@ -27,6 +31,8 @@ public class BlacksmithPlugin extends JavaPlugin {
|
||||
|
||||
private static BlacksmithPlugin instance;
|
||||
private GlobalSettings config;
|
||||
private static Translator translator;
|
||||
private static StringFormatter stringFormatter;
|
||||
|
||||
/**
|
||||
* Gets an instance of the Blacksmith plugin
|
||||
@ -50,7 +56,27 @@ public class BlacksmithPlugin extends JavaPlugin {
|
||||
* Reloads the configuration file from disk
|
||||
*/
|
||||
public void reload() {
|
||||
this.reloadConfig();
|
||||
config.load();
|
||||
translator.loadLanguages(this.getDataFolder(), this.getConfig().getString("language", "en"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the translator to use for translation
|
||||
*
|
||||
* @return <p>The translator to use</p>
|
||||
*/
|
||||
public static Translator getTranslator() {
|
||||
return BlacksmithPlugin.translator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string formatter to use for formatting
|
||||
*
|
||||
* @return <p>The string formatter to use</p>
|
||||
*/
|
||||
public static StringFormatter getStringFormatter() {
|
||||
return BlacksmithPlugin.stringFormatter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -73,7 +99,12 @@ public class BlacksmithPlugin extends JavaPlugin {
|
||||
config = new GlobalSettings(this);
|
||||
config.load();
|
||||
|
||||
Translator.loadLanguages("en");
|
||||
//Prepare the translator
|
||||
translator = new Translator();
|
||||
translator.registerMessageCategory(TranslatableTimeUnit.UNIT_SECOND);
|
||||
translator.registerMessageCategory(BlacksmithTranslatableMessage.ITEM_TYPE_ENCHANTMENT);
|
||||
translator.loadLanguages(this.getDataFolder(), fileConfiguration.getString("language", "en"));
|
||||
BlacksmithPlugin.stringFormatter = new StringFormatter(this.getDescription().getPrefix(), translator);
|
||||
|
||||
//Set up Vault integration
|
||||
if (!setUpVault()) {
|
||||
@ -90,6 +121,10 @@ public class BlacksmithPlugin extends JavaPlugin {
|
||||
registerListeners();
|
||||
|
||||
getLogger().log(Level.INFO, " v" + getDescription().getVersion() + " enabled.");
|
||||
|
||||
//Alert about an update in the console
|
||||
UpdateChecker.checkForUpdate(this, "https://api.spigotmc.org/legacy/update.php?resource=105938",
|
||||
() -> this.getDescription().getVersion(), null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,13 +5,13 @@ import net.knarcraft.blacksmith.config.GlobalSetting;
|
||||
import net.knarcraft.blacksmith.config.GlobalSettings;
|
||||
import net.knarcraft.blacksmith.config.NPCSetting;
|
||||
import net.knarcraft.blacksmith.config.SettingValueType;
|
||||
import net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage;
|
||||
import net.knarcraft.blacksmith.formatting.ItemType;
|
||||
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
|
||||
import net.knarcraft.blacksmith.util.InputParsingHelper;
|
||||
import net.knarcraft.blacksmith.util.ItemHelper;
|
||||
import net.knarcraft.blacksmith.util.TypeValidationHelper;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
@ -20,9 +20,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.displayErrorMessage;
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.displaySuccessMessage;
|
||||
import static net.knarcraft.blacksmith.formatting.TranslatableMessage.getValueChangedMessage;
|
||||
import static net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage.getValueChangedMessage;
|
||||
|
||||
/**
|
||||
* The command used for changing global configuration options
|
||||
@ -42,12 +40,6 @@ public class BlackSmithConfigCommand implements CommandExecutor {
|
||||
}
|
||||
GlobalSettings settings = BlacksmithPlugin.getInstance().getSettings();
|
||||
|
||||
//Changing reforge-able items' default isn't recommended
|
||||
if (commandName.equalsIgnoreCase(NPCSetting.REFORGE_ABLE_ITEMS.getCommandName())) {
|
||||
displayErrorMessage(sender, TranslatableMessage.DEFAULT_REFORGE_ABLE_ITEMS_UNCHANGEABLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
//Find which global setting the user has specified, if any
|
||||
GlobalSetting detectedGlobalSetting = null;
|
||||
for (GlobalSetting globalSetting : GlobalSetting.values()) {
|
||||
@ -81,7 +73,14 @@ public class BlackSmithConfigCommand implements CommandExecutor {
|
||||
}
|
||||
|
||||
//Change the value of the specified setting
|
||||
return changeValue(args, detectedGlobalSetting, detectedNPCSetting, settings, sender);
|
||||
if ((detectedGlobalSetting != null &&
|
||||
TypeValidationHelper.isValid(detectedGlobalSetting.getValueType(), args[1], sender)) ||
|
||||
(detectedNPCSetting != null &&
|
||||
TypeValidationHelper.isValid(detectedNPCSetting.getValueType(), args[1], sender))) {
|
||||
return changeValue(args, detectedGlobalSetting, detectedNPCSetting, settings, sender);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,7 +98,8 @@ public class BlackSmithConfigCommand implements CommandExecutor {
|
||||
String newValue = args[1];
|
||||
if (detectedGlobalSetting != null) {
|
||||
settings.changeValue(detectedGlobalSetting, newValue);
|
||||
displaySuccessMessage(sender, getValueChangedMessage(detectedGlobalSetting.getCommandName(), newValue));
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
|
||||
getValueChangedMessage(detectedGlobalSetting.getCommandName(), newValue));
|
||||
return true;
|
||||
} else if (detectedNPCSetting != null) {
|
||||
//This makes sure all arguments are treated as a sentence
|
||||
@ -107,7 +107,8 @@ public class BlackSmithConfigCommand implements CommandExecutor {
|
||||
newValue = String.join(" ", Arrays.asList(args).subList(1, args.length));
|
||||
}
|
||||
settings.changeValue(detectedNPCSetting, newValue);
|
||||
displaySuccessMessage(sender, getValueChangedMessage(detectedNPCSetting.getCommandName(), newValue));
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
|
||||
getValueChangedMessage(detectedNPCSetting.getCommandName(), newValue));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -145,10 +146,11 @@ public class BlackSmithConfigCommand implements CommandExecutor {
|
||||
return false;
|
||||
}
|
||||
//Display the current value of the setting
|
||||
displaySuccessMessage(sender, TranslatableMessage.getCurrentValueMessage(correctCommandName, settingValue));
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
|
||||
BlacksmithTranslatableMessage.getCurrentValueMessage(correctCommandName, settingValue));
|
||||
//Print the value with any colors displayed as &a-f0-9
|
||||
if (printRawValue) {
|
||||
sender.sendMessage(TranslatableMessage.getRawValueMessage(
|
||||
sender.sendMessage(BlacksmithTranslatableMessage.getRawValueMessage(
|
||||
settingValue.replace(ChatColor.COLOR_CHAR, '&')));
|
||||
}
|
||||
return true;
|
||||
@ -166,7 +168,7 @@ public class BlackSmithConfigCommand implements CommandExecutor {
|
||||
private boolean displaySpecialCaseValue(String selector, CommandSender sender, GlobalSetting setting,
|
||||
GlobalSettings settings) {
|
||||
if (setting == GlobalSetting.BASE_PRICE || setting == GlobalSetting.PRICE_PER_DURABILITY_POINT) {
|
||||
Material material = Material.matchMaterial(selector);
|
||||
Material material = InputParsingHelper.matchMaterial(selector);
|
||||
if (material == null) {
|
||||
return false;
|
||||
}
|
||||
@ -176,16 +178,19 @@ public class BlackSmithConfigCommand implements CommandExecutor {
|
||||
} else {
|
||||
currentValue = String.valueOf(settings.getPricePerDurabilityPoint(material));
|
||||
}
|
||||
displaySuccessMessage(sender, TranslatableMessage.getItemCurrentValueMessage(setting.getCommandName(), ItemType.MATERIAL,
|
||||
material.name(), currentValue));
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
|
||||
BlacksmithTranslatableMessage.getItemCurrentValueMessage(setting.getCommandName(),
|
||||
ItemType.MATERIAL, material.name(), currentValue));
|
||||
return true;
|
||||
} else if (setting == GlobalSetting.ENCHANTMENT_COST) {
|
||||
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(selector));
|
||||
Enchantment enchantment = InputParsingHelper.matchEnchantment(selector);
|
||||
if (enchantment == null) {
|
||||
return false;
|
||||
}
|
||||
displaySuccessMessage(sender, TranslatableMessage.getItemCurrentValueMessage(setting.getCommandName(), ItemType.ENCHANTMENT,
|
||||
enchantment.toString(), String.valueOf(settings.getEnchantmentCost(enchantment))));
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
|
||||
BlacksmithTranslatableMessage.getItemCurrentValueMessage(setting.getCommandName(),
|
||||
ItemType.ENCHANTMENT, enchantment.getKey().getKey(),
|
||||
String.valueOf(settings.getEnchantmentCost(enchantment))));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -215,42 +220,94 @@ public class BlackSmithConfigCommand implements CommandExecutor {
|
||||
*/
|
||||
private boolean updateSpecialCase(GlobalSettings settings, GlobalSetting detectedGlobalSetting, String[] args,
|
||||
CommandSender sender) {
|
||||
if (!TypeValidationHelper.isValid(SettingValueType.POSITIVE_DOUBLE, args[2], sender)) {
|
||||
if (InputParsingHelper.isEmpty(args[2])) {
|
||||
args[2] = "-1";
|
||||
} else if (!TypeValidationHelper.isValid(SettingValueType.POSITIVE_DOUBLE, args[2], sender)) {
|
||||
return true;
|
||||
}
|
||||
double newPrice = Double.parseDouble(args[2]);
|
||||
String itemChanged;
|
||||
ItemType itemType;
|
||||
String newValue = String.valueOf(newPrice);
|
||||
|
||||
if (detectedGlobalSetting == GlobalSetting.BASE_PRICE ||
|
||||
detectedGlobalSetting == GlobalSetting.PRICE_PER_DURABILITY_POINT) {
|
||||
Material material = InputParsingHelper.matchMaterial(args[1]);
|
||||
return updatePriceSpecialCase(settings, detectedGlobalSetting, args[1], newPrice, sender);
|
||||
} else if (detectedGlobalSetting == GlobalSetting.ENCHANTMENT_COST) {
|
||||
//Update enchantment cost for an item
|
||||
Enchantment enchantment = InputParsingHelper.matchEnchantment(args[1]);
|
||||
if (enchantment == null) {
|
||||
return false;
|
||||
}
|
||||
ItemType itemType = ItemType.ENCHANTMENT;
|
||||
String itemChanged = enchantment.getKey().getKey();
|
||||
settings.setEnchantmentCost(enchantment, newPrice);
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
|
||||
BlacksmithTranslatableMessage.getItemValueChangedMessage(detectedGlobalSetting.getCommandName(),
|
||||
itemType, itemChanged, newValue));
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a special case price configuration value if a special case is encountered
|
||||
*
|
||||
* @param settings <p>The settings to modify</p>
|
||||
* @param detectedGlobalSetting <p>The global setting specified</p>
|
||||
* @param materialName <p>The material name to update the price for</p>
|
||||
* @param newPrice <p>The new price to update to</p>
|
||||
* @param sender <p>The command sender to respond to</p>
|
||||
* @return <p>True if the input was valid, and the item(s) was/were updated</p>
|
||||
*/
|
||||
private boolean updatePriceSpecialCase(GlobalSettings settings, GlobalSetting detectedGlobalSetting,
|
||||
String materialName, double newPrice, CommandSender sender) {
|
||||
ItemType itemType = ItemType.MATERIAL;
|
||||
String itemChanged;
|
||||
//Update base price or price per durability point for an item
|
||||
if (materialName.contains("*")) {
|
||||
itemChanged = materialName;
|
||||
updateAllMatchedPrices(settings, detectedGlobalSetting, materialName, newPrice);
|
||||
} else {
|
||||
Material material = InputParsingHelper.matchMaterial(materialName);
|
||||
if (material == null) {
|
||||
return false;
|
||||
}
|
||||
itemType = ItemType.MATERIAL;
|
||||
itemChanged = material.name();
|
||||
if (detectedGlobalSetting == GlobalSetting.BASE_PRICE) {
|
||||
settings.setBasePrice(material, newPrice);
|
||||
} else {
|
||||
settings.setPricePerDurabilityPoint(material, newPrice);
|
||||
}
|
||||
} else if (detectedGlobalSetting == GlobalSetting.ENCHANTMENT_COST) {
|
||||
Enchantment enchantment = InputParsingHelper.matchEnchantment(args[1]);
|
||||
if (enchantment == null) {
|
||||
return false;
|
||||
}
|
||||
itemType = ItemType.ENCHANTMENT;
|
||||
itemChanged = enchantment.toString();
|
||||
settings.setEnchantmentCost(enchantment, newPrice);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
displaySuccessMessage(sender, TranslatableMessage.getItemValueChangedMessage(detectedGlobalSetting.getCommandName(),
|
||||
itemType, itemChanged, newValue));
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
|
||||
BlacksmithTranslatableMessage.getItemValueChangedMessage(detectedGlobalSetting.getCommandName(),
|
||||
itemType, itemChanged, String.valueOf(newPrice)));
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates all materials matching the material name wildcard
|
||||
*
|
||||
* @param settings <p>The settings to modify</p>
|
||||
* @param detectedGlobalSetting <p>The global setting specified</p>
|
||||
* @param materialName <p>The wildcard material name to update cost for</p>
|
||||
* @param newPrice <p>The new cost for the matched items</p>
|
||||
*/
|
||||
private void updateAllMatchedPrices(GlobalSettings settings, GlobalSetting detectedGlobalSetting,
|
||||
String materialName, double newPrice) {
|
||||
String search = InputParsingHelper.regExIfy(materialName);
|
||||
for (Material material : ItemHelper.getAllReforgeAbleMaterials()) {
|
||||
if (!material.name().matches(search)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (detectedGlobalSetting == GlobalSetting.BASE_PRICE) {
|
||||
settings.setBasePrice(material, newPrice);
|
||||
} else {
|
||||
settings.setPricePerDurabilityPoint(material, newPrice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package net.knarcraft.blacksmith.command;
|
||||
import net.knarcraft.blacksmith.config.GlobalSetting;
|
||||
import net.knarcraft.blacksmith.config.NPCSetting;
|
||||
import net.knarcraft.blacksmith.config.SettingValueType;
|
||||
import net.knarcraft.blacksmith.util.InputParsingHelper;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
@ -13,7 +14,7 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.knarcraft.blacksmith.util.TabCompleteValuesHelper.getTabCompletions;
|
||||
import static net.knarcraft.blacksmith.util.TabCompletionHelper.filterMatchingContains;
|
||||
import static net.knarcraft.knarlib.util.TabCompletionHelper.filterMatchingContains;
|
||||
|
||||
/**
|
||||
* The tab completer for the command used for changing global configuration options
|
||||
@ -28,6 +29,13 @@ public class BlackSmithConfigTabCompleter implements TabCompleter {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
//Arguments: <setting> [new value/material or enchantment] []
|
||||
|
||||
//Prevent tab-completion when typing messages with spaces
|
||||
if (skipCompletionForSpacedMessage(args) != null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
if (args.length == 1) {
|
||||
List<String> availableCommands = new ArrayList<>();
|
||||
availableCommands.add("reload");
|
||||
@ -40,10 +48,60 @@ public class BlackSmithConfigTabCompleter implements TabCompleter {
|
||||
return filterMatchingContains(availableCommands, args[0]);
|
||||
} else if (args.length == 2) {
|
||||
return tabCompleteCommandValues(args[0], args[1]);
|
||||
} else if (args.length == 3) {
|
||||
//Get per-material tab completions, or return nothing if an invalid setting was specified
|
||||
for (GlobalSetting globalSetting : GlobalSetting.values()) {
|
||||
if (globalSetting.getCommandName().equalsIgnoreCase(args[0])) {
|
||||
return getPerTypeTabCompletions(globalSetting, args);
|
||||
}
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether to tab-complete nothing because a message containing spaces is being written
|
||||
*
|
||||
* @param args <p>The arguments given by the user</p>
|
||||
* @return <p>Null if not writing a spaced message</p>
|
||||
*/
|
||||
private List<String> skipCompletionForSpacedMessage(String[] args) {
|
||||
if (args.length > 2) {
|
||||
NPCSetting npcSetting = null;
|
||||
for (NPCSetting setting : NPCSetting.values()) {
|
||||
if (setting.getCommandName().equalsIgnoreCase(args[0])) {
|
||||
npcSetting = setting;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (npcSetting != null && npcSetting.getPath().startsWith("defaults.messages")) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets tab-completions for a selected material or enchantment
|
||||
*
|
||||
* @param globalSetting <p>The global setting to get tab-completions for</p>
|
||||
* @param args <p>The arguments given by the user</p>
|
||||
* @return <p>The tab-completions to show to the user</p>
|
||||
*/
|
||||
private List<String> getPerTypeTabCompletions(GlobalSetting globalSetting, String[] args) {
|
||||
//Display possible tab-completions only if a valid enchantment or material is provided
|
||||
if (((globalSetting == GlobalSetting.BASE_PRICE ||
|
||||
globalSetting == GlobalSetting.PRICE_PER_DURABILITY_POINT) &&
|
||||
InputParsingHelper.matchMaterial(args[1]) != null) ||
|
||||
(globalSetting == GlobalSetting.ENCHANTMENT_COST &&
|
||||
InputParsingHelper.matchEnchantment(args[1]) != null)) {
|
||||
return filterMatchingContains(getTabCompletions(globalSetting.getValueType()), args[2]);
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tab completes the values available for the given command
|
||||
*
|
||||
|
@ -5,10 +5,9 @@ import net.citizensnpcs.api.npc.NPC;
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.config.NPCSetting;
|
||||
import net.knarcraft.blacksmith.config.SettingValueType;
|
||||
import net.knarcraft.blacksmith.formatting.StringFormatter;
|
||||
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
|
||||
import net.knarcraft.blacksmith.formatting.Translator;
|
||||
import net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage;
|
||||
import net.knarcraft.blacksmith.trait.BlacksmithTrait;
|
||||
import net.knarcraft.blacksmith.util.InputParsingHelper;
|
||||
import net.knarcraft.blacksmith.util.TypeValidationHelper;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.command.Command;
|
||||
@ -18,9 +17,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.displaySuccessMessage;
|
||||
import static net.knarcraft.blacksmith.formatting.TranslatableMessage.getCurrentValueMessage;
|
||||
import static net.knarcraft.blacksmith.formatting.TranslatableMessage.getValueChangedMessage;
|
||||
import static net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage.getCurrentValueMessage;
|
||||
import static net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage.getValueChangedMessage;
|
||||
|
||||
/**
|
||||
* The main command used for blacksmith editing
|
||||
@ -32,7 +30,8 @@ public class BlackSmithEditCommand implements CommandExecutor {
|
||||
@NotNull String[] args) {
|
||||
NPC npc = CitizensAPI.getDefaultNPCSelector().getSelected(sender);
|
||||
if (npc == null || !npc.hasTrait(BlacksmithTrait.class)) {
|
||||
StringFormatter.displayErrorMessage(sender, TranslatableMessage.NO_NPC_SELECTED);
|
||||
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
|
||||
BlacksmithTranslatableMessage.NO_NPC_SELECTED);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -72,7 +71,7 @@ public class BlackSmithEditCommand implements CommandExecutor {
|
||||
displayNPCSetting(blacksmithTrait, npcSetting, sender);
|
||||
} else {
|
||||
//If an empty value or null, clear the value instead of changing it
|
||||
if (newValue.equalsIgnoreCase("null") || newValue.equals("\"\"") || newValue.trim().isEmpty()) {
|
||||
if (InputParsingHelper.isEmpty(newValue)) {
|
||||
newValue = null;
|
||||
} else {
|
||||
//Abort if an invalid value is given
|
||||
@ -85,7 +84,8 @@ public class BlackSmithEditCommand implements CommandExecutor {
|
||||
|
||||
//Change the setting
|
||||
blacksmithTrait.getSettings().changeSetting(npcSetting, newValue);
|
||||
displaySuccessMessage(sender, getValueChangedMessage(npcSetting.getCommandName(), String.valueOf(newValue)));
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
|
||||
getValueChangedMessage(npcSetting.getCommandName(), String.valueOf(newValue)));
|
||||
//Save the changes immediately to prevent data loss on server crash
|
||||
CitizensAPI.getNPCRegistry().saveToStore();
|
||||
}
|
||||
@ -101,17 +101,21 @@ public class BlackSmithEditCommand implements CommandExecutor {
|
||||
*/
|
||||
private void displayNPCSetting(BlacksmithTrait blacksmithTrait, NPCSetting npcSetting, CommandSender sender) {
|
||||
String rawValue = String.valueOf(blacksmithTrait.getSettings().getRawValue(npcSetting));
|
||||
if (rawValue == null || rawValue.trim().isEmpty() || rawValue.equalsIgnoreCase("null")) {
|
||||
if (InputParsingHelper.isEmpty(rawValue)) {
|
||||
//Display the default value, if no custom value has been specified
|
||||
rawValue = String.valueOf(BlacksmithPlugin.getInstance().getSettings().getRawValue(npcSetting));
|
||||
displaySuccessMessage(sender, getCurrentValueMessage(npcSetting.getCommandName(), rawValue));
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
|
||||
getCurrentValueMessage(npcSetting.getCommandName(), rawValue));
|
||||
} else {
|
||||
//Add a marker if the value has been customized
|
||||
String marker = Translator.getTranslatedMessage(TranslatableMessage.SETTING_OVERRIDDEN_MARKER);
|
||||
displaySuccessMessage(sender, getCurrentValueMessage(npcSetting.getCommandName(), rawValue) + marker);
|
||||
String marker = BlacksmithPlugin.getTranslator().getTranslatedMessage(
|
||||
BlacksmithTranslatableMessage.SETTING_OVERRIDDEN_MARKER);
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender,
|
||||
getCurrentValueMessage(npcSetting.getCommandName(), rawValue) + marker);
|
||||
}
|
||||
if (npcSetting.getPath().startsWith("defaults.messages")) {
|
||||
sender.sendMessage(TranslatableMessage.getRawValueMessage(rawValue.replace(ChatColor.COLOR_CHAR, '&')));
|
||||
sender.sendMessage(BlacksmithTranslatableMessage.getRawValueMessage(
|
||||
rawValue.replace(ChatColor.COLOR_CHAR, '&')));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ package net.knarcraft.blacksmith.command;
|
||||
|
||||
import net.knarcraft.blacksmith.config.NPCSetting;
|
||||
import net.knarcraft.blacksmith.util.TabCompleteValuesHelper;
|
||||
import net.knarcraft.blacksmith.util.TabCompletionHelper;
|
||||
import net.knarcraft.knarlib.util.TabCompletionHelper;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
@ -33,7 +33,7 @@ public class BlackSmithEditTabCompleter implements TabCompleter {
|
||||
if (args.length == 1) {
|
||||
return TabCompletionHelper.filterMatchingContains(npcSettings, args[0]);
|
||||
} else {
|
||||
if (npcSettings.contains(args[0]) && args.length <= 2) {
|
||||
if (npcSettings.contains(args[0]) && args.length == 2) {
|
||||
return tabCompleteCommandValues(args[0], args[1]);
|
||||
} else {
|
||||
return new ArrayList<>();
|
||||
|
@ -1,10 +1,10 @@
|
||||
package net.knarcraft.blacksmith.command;
|
||||
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.config.SmithPreset;
|
||||
import net.knarcraft.blacksmith.config.SmithPresetFilter;
|
||||
import net.knarcraft.blacksmith.formatting.StringFormatter;
|
||||
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
|
||||
import net.knarcraft.blacksmith.formatting.Translator;
|
||||
import net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage;
|
||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandExecutor;
|
||||
@ -14,9 +14,6 @@ import org.jetbrains.annotations.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.displayErrorMessage;
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.displaySuccessMessage;
|
||||
|
||||
/**
|
||||
* The command for displaying which materials are contained in a preset
|
||||
*/
|
||||
@ -40,7 +37,8 @@ public class PresetCommand implements CommandExecutor {
|
||||
SmithPresetFilter filter = SmithPresetFilter.valueOf(parts[1]);
|
||||
|
||||
if (!smithPreset.supportsFilter(filter)) {
|
||||
displayErrorMessage(sender, TranslatableMessage.INVALID_FILTER_FOR_PRESET);
|
||||
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
|
||||
BlacksmithTranslatableMessage.INVALID_FILTER_FOR_PRESET);
|
||||
return false;
|
||||
}
|
||||
includedMaterials = smithPreset.getFilteredMaterials(filter);
|
||||
@ -48,7 +46,8 @@ public class PresetCommand implements CommandExecutor {
|
||||
includedMaterials = SmithPreset.valueOf(presetName).getMaterials();
|
||||
}
|
||||
} catch (IllegalArgumentException exception) {
|
||||
displayErrorMessage(sender, TranslatableMessage.INVALID_PRESET_OR_FILTER);
|
||||
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
|
||||
BlacksmithTranslatableMessage.INVALID_PRESET_OR_FILTER);
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -57,8 +56,9 @@ public class PresetCommand implements CommandExecutor {
|
||||
for (Material material : includedMaterials) {
|
||||
materialNames.add(material.name());
|
||||
}
|
||||
displaySuccessMessage(sender, StringFormatter.replacePlaceholder(Translator.getTranslatedMessage(
|
||||
TranslatableMessage.PRESET_MATERIALS), "{materials}", String.join(", ", materialNames)));
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender, StringFormatter.replacePlaceholder(
|
||||
BlacksmithPlugin.getTranslator().getTranslatedMessage(BlacksmithTranslatableMessage.PRESET_MATERIALS),
|
||||
"{materials}", String.join(", ", materialNames)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@ package net.knarcraft.blacksmith.command;
|
||||
|
||||
import net.knarcraft.blacksmith.config.SmithPreset;
|
||||
import net.knarcraft.blacksmith.config.SmithPresetFilter;
|
||||
import net.knarcraft.blacksmith.util.TabCompletionHelper;
|
||||
import net.knarcraft.knarlib.util.TabCompletionHelper;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabCompleter;
|
||||
|
@ -1,7 +1,7 @@
|
||||
package net.knarcraft.blacksmith.command;
|
||||
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
|
||||
import net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.TabExecutor;
|
||||
@ -11,8 +11,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.displaySuccessMessage;
|
||||
|
||||
/**
|
||||
* The command for re-loading the plugin
|
||||
*/
|
||||
@ -22,7 +20,7 @@ public class ReloadCommand implements TabExecutor {
|
||||
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label,
|
||||
@NotNull String[] args) {
|
||||
BlacksmithPlugin.getInstance().reload();
|
||||
displaySuccessMessage(sender, TranslatableMessage.PLUGIN_RELOADED);
|
||||
BlacksmithPlugin.getStringFormatter().displaySuccessMessage(sender, BlacksmithTranslatableMessage.PLUGIN_RELOADED);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,8 @@ public enum GlobalSetting {
|
||||
*
|
||||
* <p>This can be specified for each possible enchantment by setting enchantment-cost.enchantment_name</p>
|
||||
*/
|
||||
ENCHANTMENT_COST("global.enchantmentCost.default", SettingValueType.POSITIVE_DOUBLE, 5.0, "enchantmentCost"),
|
||||
ENCHANTMENT_COST("global.enchantmentCost.default", SettingValueType.POSITIVE_DOUBLE, 5.0,
|
||||
"enchantmentCost"),
|
||||
|
||||
/**
|
||||
* Whether the cost should increase for damage taken, as opposed to increase for durability present
|
||||
@ -36,7 +37,19 @@ public enum GlobalSetting {
|
||||
/**
|
||||
* Whether to show exact time when displaying the wait time for a reforging or the cool-down
|
||||
*/
|
||||
SHOW_EXACT_TIME("global.showExactTime", SettingValueType.BOOLEAN, false, "showExactTime");
|
||||
SHOW_EXACT_TIME("global.showExactTime", SettingValueType.BOOLEAN, false, "showExactTime"),
|
||||
|
||||
/**
|
||||
* The cost for repairing a chipped anvil
|
||||
*/
|
||||
ANVIL_CHIPPED_COST("global.chippedAnvilReforgingCost", SettingValueType.POSITIVE_DOUBLE, 10.0,
|
||||
"chippedAnvilReforgingCost"),
|
||||
|
||||
/**
|
||||
* The cost for repairing a damaged anvil
|
||||
*/
|
||||
ANVIL_DAMAGED_COST("global.damagedAnvilReforgingCost", SettingValueType.POSITIVE_DOUBLE, 20.0,
|
||||
"damagedAnvilReforgingCost");
|
||||
|
||||
private final String path;
|
||||
private final String parent;
|
||||
|
@ -4,12 +4,15 @@ import net.citizensnpcs.api.util.DataKey;
|
||||
import net.citizensnpcs.api.util.YamlStorage;
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.util.ConfigHelper;
|
||||
import net.knarcraft.blacksmith.util.InputParsingHelper;
|
||||
import net.knarcraft.blacksmith.util.ItemHelper;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
@ -21,8 +24,9 @@ public class GlobalSettings {
|
||||
private final Map<Material, Double> materialBasePrices = new HashMap<>();
|
||||
private final Map<Material, Double> materialPricePerDurabilityPoints = new HashMap<>();
|
||||
private final Map<Enchantment, Double> enchantmentCosts = new HashMap<>();
|
||||
|
||||
private final Map<NPCSetting, Object> defaultNPCSettings = new HashMap<>();
|
||||
private final List<Material> defaultReforgeAbleMaterials = new ArrayList<>();
|
||||
private final List<Enchantment> defaultEnchantmentBlocklist = new ArrayList<>();
|
||||
private final Map<GlobalSetting, Object> globalSettings = new HashMap<>();
|
||||
|
||||
private final YamlStorage defaultConfig;
|
||||
@ -81,8 +85,19 @@ public class GlobalSettings {
|
||||
* @param newValue <p>The new value for the setting</p>
|
||||
*/
|
||||
public void changeValue(NPCSetting npcSetting, Object newValue) {
|
||||
defaultNPCSettings.put(npcSetting, newValue);
|
||||
if (npcSetting.getValueType() == SettingValueType.STRING_LIST ||
|
||||
npcSetting.getValueType() == SettingValueType.REFORGE_ABLE_ITEMS) {
|
||||
//Workaround to make sure it's treated as the correct type
|
||||
defaultNPCSettings.put(npcSetting, newValue == null ? null : ConfigHelper.asStringList(newValue));
|
||||
} else {
|
||||
defaultNPCSettings.put(npcSetting, newValue);
|
||||
}
|
||||
save();
|
||||
if (npcSetting == NPCSetting.REFORGE_ABLE_ITEMS) {
|
||||
loadReforgeAbleItems();
|
||||
} else if (npcSetting == NPCSetting.ENCHANTMENT_BLOCKLIST) {
|
||||
loadEnchantmentBlocklist();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -112,13 +127,17 @@ public class GlobalSettings {
|
||||
* @param newEnchantmentCost <p>The new enchantment cost</p>
|
||||
*/
|
||||
public void setEnchantmentCost(Enchantment enchantment, double newEnchantmentCost) {
|
||||
if (newEnchantmentCost < 0) {
|
||||
throw new IllegalArgumentException("Enchantment cost cannot be negative!");
|
||||
}
|
||||
if (enchantment == null) {
|
||||
if (newEnchantmentCost < 0) {
|
||||
throw new IllegalArgumentException("Enchantment cost cannot be negative!");
|
||||
}
|
||||
globalSettings.put(GlobalSetting.ENCHANTMENT_COST, newEnchantmentCost);
|
||||
} else {
|
||||
enchantmentCosts.put(enchantment, newEnchantmentCost);
|
||||
if (newEnchantmentCost < 0) {
|
||||
enchantmentCosts.put(enchantment, null);
|
||||
} else {
|
||||
enchantmentCosts.put(enchantment, newEnchantmentCost);
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
@ -130,13 +149,18 @@ public class GlobalSettings {
|
||||
* @param newPrice <p>The new price per durability point price</p>
|
||||
*/
|
||||
public void setPricePerDurabilityPoint(Material material, double newPrice) {
|
||||
if (newPrice < 0) {
|
||||
throw new IllegalArgumentException("Price per durability point cannot be negative!");
|
||||
}
|
||||
if (material == null) {
|
||||
if (newPrice < 0) {
|
||||
throw new IllegalArgumentException("Price per durability point cannot be negative!");
|
||||
}
|
||||
globalSettings.put(GlobalSetting.PRICE_PER_DURABILITY_POINT, newPrice);
|
||||
} else {
|
||||
materialPricePerDurabilityPoints.put(material, newPrice);
|
||||
//Use a negative price to unset the per-item value
|
||||
if (newPrice < 0) {
|
||||
materialPricePerDurabilityPoints.put(material, null);
|
||||
} else {
|
||||
materialPricePerDurabilityPoints.put(material, newPrice);
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
@ -148,13 +172,18 @@ public class GlobalSettings {
|
||||
* @param newBasePrice <p>The new base price</p>
|
||||
*/
|
||||
public void setBasePrice(Material material, double newBasePrice) {
|
||||
if (newBasePrice < 0) {
|
||||
throw new IllegalArgumentException("Base price cannot be negative!");
|
||||
}
|
||||
if (material == null) {
|
||||
if (newBasePrice < 0) {
|
||||
throw new IllegalArgumentException("Base price cannot be negative!");
|
||||
}
|
||||
globalSettings.put(GlobalSetting.BASE_PRICE, newBasePrice);
|
||||
} else {
|
||||
materialBasePrices.put(material, newBasePrice);
|
||||
//Use a negative price to unset the per-item value
|
||||
if (newBasePrice < 0) {
|
||||
materialBasePrices.put(material, null);
|
||||
} else {
|
||||
materialBasePrices.put(material, newBasePrice);
|
||||
}
|
||||
}
|
||||
save();
|
||||
}
|
||||
@ -232,6 +261,40 @@ public class GlobalSettings {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of reforgeAbleItems
|
||||
*
|
||||
* @return <p>The value of reforgeAbleItems</p>
|
||||
*/
|
||||
public List<Material> getReforgeAbleItems() {
|
||||
return this.defaultReforgeAbleMaterials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of enchantmentBlocklist
|
||||
*
|
||||
* @return <p>The value of enchantmentBlocklist</p>
|
||||
*/
|
||||
public List<Enchantment> getEnchantmentBlocklist() {
|
||||
return this.defaultEnchantmentBlocklist;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cost for repairing the given type of anvil
|
||||
*
|
||||
* @param material <p>The anvil material to repair</p>
|
||||
* @return <p>The cost of repairing the anvil</p>
|
||||
*/
|
||||
public double getAnvilCost(Material material) {
|
||||
if (material == Material.CHIPPED_ANVIL) {
|
||||
return asDouble(GlobalSetting.ANVIL_CHIPPED_COST);
|
||||
} else if (material == Material.DAMAGED_ANVIL) {
|
||||
return asDouble(GlobalSetting.ANVIL_DAMAGED_COST);
|
||||
} else {
|
||||
throw new IllegalArgumentException("An unexpected item was encountered!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the given value as a boolean
|
||||
*
|
||||
@ -288,48 +351,98 @@ public class GlobalSettings {
|
||||
}
|
||||
|
||||
//Load all base prices
|
||||
DataKey basePriceNode = root.getRelative(GlobalSetting.BASE_PRICE.getParent());
|
||||
Map<String, String> relevantKeys = getRelevantKeys(basePriceNode);
|
||||
for (String key : relevantKeys.keySet()) {
|
||||
String materialName = relevantKeys.get(key);
|
||||
Material material = Material.matchMaterial(materialName);
|
||||
if (material != null) {
|
||||
materialBasePrices.put(material, basePriceNode.getDouble(key));
|
||||
} else {
|
||||
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING,
|
||||
"Unable to find a material matching " + materialName);
|
||||
}
|
||||
}
|
||||
loadBasePrices(root);
|
||||
|
||||
//Load all per-durability-point prices
|
||||
DataKey basePerDurabilityPriceNode = root.getRelative(GlobalSetting.PRICE_PER_DURABILITY_POINT.getParent());
|
||||
relevantKeys = getRelevantKeys(basePerDurabilityPriceNode);
|
||||
for (String key : relevantKeys.keySet()) {
|
||||
String materialName = relevantKeys.get(key);
|
||||
Material material = Material.matchMaterial(materialName);
|
||||
if (material != null) {
|
||||
materialPricePerDurabilityPoints.put(material, basePerDurabilityPriceNode.getDouble(key));
|
||||
} else {
|
||||
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING,
|
||||
"Unable to find a material matching " + materialName);
|
||||
}
|
||||
}
|
||||
loadPricesPerDurabilityPoint(root);
|
||||
|
||||
//Load all enchantment prices
|
||||
DataKey enchantmentCostNode = root.getRelative(GlobalSetting.ENCHANTMENT_COST.getParent());
|
||||
relevantKeys = getRelevantKeys(basePerDurabilityPriceNode);
|
||||
Map<String, String> relevantKeys = getRelevantKeys(enchantmentCostNode);
|
||||
for (String key : relevantKeys.keySet()) {
|
||||
String enchantmentName = relevantKeys.get(key);
|
||||
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(enchantmentName));
|
||||
if (enchantment != null) {
|
||||
enchantmentCosts.put(enchantment, enchantmentCostNode.getDouble(key));
|
||||
Enchantment enchantment = InputParsingHelper.matchEnchantment(enchantmentName);
|
||||
setItemPrice(enchantmentCosts, enchantmentName, enchantment, enchantmentCostNode.getDouble(key));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all prices per durability point for all materials
|
||||
*
|
||||
* @param root <p>The configuration root node to search from</p>
|
||||
*/
|
||||
private void loadPricesPerDurabilityPoint(DataKey root) {
|
||||
DataKey basePerDurabilityPriceNode = root.getRelative(GlobalSetting.PRICE_PER_DURABILITY_POINT.getParent());
|
||||
Map<String, String> relevantKeys = getRelevantKeys(basePerDurabilityPriceNode);
|
||||
|
||||
for (String key : relevantKeys.keySet()) {
|
||||
String materialName = relevantKeys.get(key);
|
||||
double price = basePerDurabilityPriceNode.getDouble(key);
|
||||
if (materialName.contains("*")) {
|
||||
//Treat *CHESTPLATE as a regular expression to match all chest-plates
|
||||
setMatchedMaterialPrices(materialPricePerDurabilityPoints, materialName, price);
|
||||
} else {
|
||||
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING,
|
||||
"Unable to find an enchantment matching " + enchantmentName);
|
||||
Material material = InputParsingHelper.matchMaterial(materialName);
|
||||
setItemPrice(materialPricePerDurabilityPoints, materialName, material, price);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads base prices for all materials
|
||||
*
|
||||
* @param root <p>The configuration root node to search from</p>
|
||||
*/
|
||||
private void loadBasePrices(DataKey root) {
|
||||
DataKey basePriceNode = root.getRelative(GlobalSetting.BASE_PRICE.getParent());
|
||||
Map<String, String> relevantKeys = getRelevantKeys(basePriceNode);
|
||||
|
||||
for (String key : relevantKeys.keySet()) {
|
||||
String materialName = relevantKeys.get(key);
|
||||
double price = basePriceNode.getDouble(key);
|
||||
if (materialName.contains("*")) {
|
||||
//Treat *CHESTPLATE as a regular expression to match all chest-plates
|
||||
setMatchedMaterialPrices(materialBasePrices, materialName, price);
|
||||
} else {
|
||||
Material material = InputParsingHelper.matchMaterial(materialName);
|
||||
setItemPrice(materialBasePrices, materialName, material, price);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the price for any materials matching the given wildcard material name
|
||||
*
|
||||
* @param prices <p>The map to store the prices in</p>
|
||||
* @param materialName <p>The material name to match</p>
|
||||
* @param price <p>The price to set for the matched materials</p>
|
||||
*/
|
||||
private void setMatchedMaterialPrices(Map<Material, Double> prices, String materialName, double price) {
|
||||
String search = InputParsingHelper.regExIfy(materialName);
|
||||
for (Material material : ItemHelper.getAllReforgeAbleMaterials()) {
|
||||
if (material.name().matches(search)) {
|
||||
setItemPrice(prices, material.name(), material, price);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the price for the given material
|
||||
*
|
||||
* @param prices <p>The map to store the price in</p>
|
||||
* @param itemName <p>The name of the material to add a price for</p>
|
||||
* @param item <p>The material parsed from the name</p>
|
||||
* @param price <p>The price to set</p>
|
||||
*/
|
||||
private <K> void setItemPrice(Map<K, Double> prices, String itemName, K item, double price) {
|
||||
if (item != null) {
|
||||
prices.put(item, price);
|
||||
} else {
|
||||
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING,
|
||||
"Unable to find a material/enchantment matching " + itemName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a map between relevant keys and their normalized name
|
||||
*
|
||||
@ -375,6 +488,26 @@ public class GlobalSettings {
|
||||
defaultNPCSettings.put(setting, root.getRaw(setting.getPath()));
|
||||
}
|
||||
}
|
||||
loadReforgeAbleItems();
|
||||
loadEnchantmentBlocklist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads reforgeAble items from the current value
|
||||
*/
|
||||
private void loadReforgeAbleItems() {
|
||||
defaultReforgeAbleMaterials.clear();
|
||||
defaultReforgeAbleMaterials.addAll(NPCSettings.getReforgeAbleItems(ConfigHelper.asStringList(
|
||||
defaultNPCSettings.get(NPCSetting.REFORGE_ABLE_ITEMS))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the enchantment blocklist from the current value
|
||||
*/
|
||||
private void loadEnchantmentBlocklist() {
|
||||
defaultEnchantmentBlocklist.clear();
|
||||
defaultEnchantmentBlocklist.addAll(NPCSettings.getEnchantmentBlocklist(ConfigHelper.asStringList(
|
||||
defaultNPCSettings.get(NPCSetting.ENCHANTMENT_BLOCKLIST))));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -407,7 +540,7 @@ public class GlobalSettings {
|
||||
//Load all enchantment prices
|
||||
DataKey enchantmentCostNode = root.getRelative(GlobalSetting.ENCHANTMENT_COST.getParent());
|
||||
for (Enchantment enchantment : enchantmentCosts.keySet()) {
|
||||
enchantmentCostNode.setRaw(unNormalizeName(enchantment.getKey().toString()), enchantmentCosts.get(enchantment));
|
||||
enchantmentCostNode.setRaw(unNormalizeName(enchantment.getKey().getKey()), enchantmentCosts.get(enchantment));
|
||||
}
|
||||
|
||||
//Perform the actual save to disk
|
||||
|
@ -46,7 +46,7 @@ public enum NPCSetting {
|
||||
/**
|
||||
* The setting for which items the blacksmith is able to reforge
|
||||
*/
|
||||
REFORGE_ABLE_ITEMS("reforgeAbleItems", SettingValueType.STRING_LIST, new String[]{}, "reforgeAbleItems"),
|
||||
REFORGE_ABLE_ITEMS("reforgeAbleItems", SettingValueType.REFORGE_ABLE_ITEMS, "", "reforgeAbleItems"),
|
||||
|
||||
/**
|
||||
* The setting for the title used to display which kind of blacksmith the NPC is
|
||||
@ -56,6 +56,17 @@ public enum NPCSetting {
|
||||
*/
|
||||
BLACKSMITH_TITLE("blacksmithTitle", SettingValueType.STRING, "blacksmith", "blacksmithTitle"),
|
||||
|
||||
/**
|
||||
* The setting for the enchantments a blacksmith cannot apply to items
|
||||
*/
|
||||
ENCHANTMENT_BLOCKLIST("enchantmentBlocklist", SettingValueType.STRING_LIST, new String[]{"binding_curse",
|
||||
"mending", "vanishing_curse"}, "enchantmentBlocklist"),
|
||||
|
||||
/**
|
||||
* Whether to allow this blacksmith to repair anvils
|
||||
*/
|
||||
REPAIR_ANVILS("reforgeAnvils", SettingValueType.BOOLEAN, false, "reforgeAnvils"),
|
||||
|
||||
/*-----------
|
||||
| Messages |
|
||||
-----------*/
|
||||
|
@ -4,13 +4,17 @@ import net.citizensnpcs.api.util.DataKey;
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.trait.BlacksmithTrait;
|
||||
import net.knarcraft.blacksmith.util.ConfigHelper;
|
||||
import net.knarcraft.blacksmith.util.InputParsingHelper;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
@ -19,6 +23,7 @@ import java.util.logging.Level;
|
||||
public class NPCSettings {
|
||||
|
||||
private final List<Material> reforgeAbleItems = new ArrayList<>();
|
||||
private final List<Enchantment> enchantmentBlocklist = new ArrayList<>();
|
||||
private final Map<NPCSetting, Object> currentValues = new HashMap<>();
|
||||
private final GlobalSettings globalSettings;
|
||||
|
||||
@ -42,6 +47,7 @@ public class NPCSettings {
|
||||
}
|
||||
//Updates the list of reforge-able items/materials
|
||||
updateReforgeAbleItems();
|
||||
updateEnchantmentBlocklist();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -62,10 +68,19 @@ public class NPCSettings {
|
||||
* @param newValue <p>The new value of the setting</p>
|
||||
*/
|
||||
public void changeSetting(NPCSetting setting, Object newValue) {
|
||||
currentValues.put(setting, newValue);
|
||||
if (setting.getValueType() == SettingValueType.STRING_LIST ||
|
||||
setting.getValueType() == SettingValueType.REFORGE_ABLE_ITEMS) {
|
||||
//Workaround to make sure it's treated as the correct type
|
||||
currentValues.put(setting, newValue == null ? null : ConfigHelper.asStringList(newValue));
|
||||
} else {
|
||||
currentValues.put(setting, newValue);
|
||||
}
|
||||
if (setting == NPCSetting.REFORGE_ABLE_ITEMS) {
|
||||
updateReforgeAbleItems();
|
||||
}
|
||||
if (setting == NPCSetting.ENCHANTMENT_BLOCKLIST) {
|
||||
updateEnchantmentBlocklist();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -185,7 +200,26 @@ public class NPCSettings {
|
||||
* @return <p>All items reforge-able by this NPC</p>
|
||||
*/
|
||||
public List<Material> getReforgeAbleItems() {
|
||||
return new ArrayList<>(reforgeAbleItems);
|
||||
Object currentValue = currentValues.get(NPCSetting.REFORGE_ABLE_ITEMS);
|
||||
if (currentValue == null || String.valueOf(currentValue).isEmpty()) {
|
||||
return globalSettings.getReforgeAbleItems();
|
||||
} else {
|
||||
return new ArrayList<>(this.reforgeAbleItems);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of blocked enchantments
|
||||
*
|
||||
* @return <p>The list of blocked enchantments</p>
|
||||
*/
|
||||
public List<Enchantment> getEnchantmentBlocklist() {
|
||||
Object currentValue = currentValues.get(NPCSetting.ENCHANTMENT_BLOCKLIST);
|
||||
if (currentValue == null || String.valueOf(currentValue).isEmpty()) {
|
||||
return globalSettings.getEnchantmentBlocklist();
|
||||
} else {
|
||||
return new ArrayList<>(this.enchantmentBlocklist);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -278,6 +312,15 @@ public class NPCSettings {
|
||||
return asInt(NPCSetting.MAX_REFORGE_DELAY) <= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this blacksmith is able to repair anvils
|
||||
*
|
||||
* @return <p>True if this blacksmith is able to repair anvils</p>
|
||||
*/
|
||||
public boolean getRepairAnvils() {
|
||||
return ConfigHelper.asBoolean(getValue(NPCSetting.REPAIR_ANVILS));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the given value as an integer
|
||||
*
|
||||
@ -325,26 +368,57 @@ public class NPCSettings {
|
||||
/**
|
||||
* Replaces placeholders in the given reforge-able value
|
||||
*
|
||||
* @param value <p>The value specified by a user</p>
|
||||
* @param stringList <p>The value specified by a user</p>
|
||||
* @return <p>The value with placeholders replaced</p>
|
||||
*/
|
||||
private Object replaceReforgeAblePresets(Object value) {
|
||||
if (value instanceof String string) {
|
||||
String[] list = string.split(",");
|
||||
List<String> replaced = new ArrayList<>(list.length);
|
||||
for (String item : list) {
|
||||
replaced.add(SmithPreset.replacePreset(item));
|
||||
private static List<String> replaceReforgeAblePresets(List<String> stringList) {
|
||||
List<String> newStrings = new ArrayList<>();
|
||||
for (String item : stringList) {
|
||||
if (item == null) {
|
||||
continue;
|
||||
}
|
||||
return String.join(",", replaced);
|
||||
} else if (value instanceof String[] stringList) {
|
||||
List<String> replaced = new ArrayList<>(stringList.length);
|
||||
for (String item : stringList) {
|
||||
replaced.add(SmithPreset.replacePreset(item));
|
||||
String replaced = SmithPreset.replacePreset(item);
|
||||
if (!replaced.equals(item)) {
|
||||
newStrings.addAll(List.of(replaced.split(",")));
|
||||
} else {
|
||||
newStrings.add(item);
|
||||
}
|
||||
return replaced.toArray();
|
||||
} else {
|
||||
throw new IllegalArgumentException("Unexpected object type encountered!");
|
||||
}
|
||||
return newStrings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the list of blocked enchantments
|
||||
*/
|
||||
private void updateEnchantmentBlocklist() {
|
||||
this.enchantmentBlocklist.clear();
|
||||
this.enchantmentBlocklist.addAll(getEnchantmentBlocklist(ConfigHelper.asStringList(getValue(
|
||||
NPCSetting.ENCHANTMENT_BLOCKLIST))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of enchantments listed in the given string list
|
||||
*
|
||||
* @param enchantments <p>The enchantment names to block</p>
|
||||
* @return <p>The enchantments to be blocked</p>
|
||||
*/
|
||||
public static List<Enchantment> getEnchantmentBlocklist(List<String> enchantments) {
|
||||
List<Enchantment> enchantmentBlocklist = new ArrayList<>();
|
||||
|
||||
for (String item : enchantments) {
|
||||
if (InputParsingHelper.isEmpty(item)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Enchantment enchantment = InputParsingHelper.matchEnchantment(item);
|
||||
if (enchantment != null) {
|
||||
enchantmentBlocklist.add(enchantment);
|
||||
} else {
|
||||
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to verify " + item +
|
||||
" as a valid enchantment");
|
||||
}
|
||||
}
|
||||
return enchantmentBlocklist;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -352,26 +426,55 @@ public class NPCSettings {
|
||||
*/
|
||||
private void updateReforgeAbleItems() {
|
||||
this.reforgeAbleItems.clear();
|
||||
String newReforgeAbleItems = (String) currentValues.get(NPCSetting.REFORGE_ABLE_ITEMS);
|
||||
if (newReforgeAbleItems == null) {
|
||||
return;
|
||||
this.reforgeAbleItems.addAll(getReforgeAbleItems(ConfigHelper.asStringList(getValue(
|
||||
NPCSetting.REFORGE_ABLE_ITEMS))));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of the reforgeAbleItems described in the given item list
|
||||
*
|
||||
* @param itemList <p>The list of items defined by the user</p>
|
||||
* @return <p>The materials contained in the item list</p>
|
||||
*/
|
||||
public static List<Material> getReforgeAbleItems(List<String> itemList) {
|
||||
List<Material> reforgeAbleItems = new ArrayList<>();
|
||||
if (itemList == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//Convert any presets with a list of materials
|
||||
newReforgeAbleItems = (String) replaceReforgeAblePresets(newReforgeAbleItems);
|
||||
itemList = replaceReforgeAblePresets(itemList);
|
||||
|
||||
for (String item : newReforgeAbleItems.split(",")) {
|
||||
if (item == null || item.trim().isEmpty() || item.equalsIgnoreCase("null")) {
|
||||
Set<Material> blacklisted = new HashSet<>();
|
||||
//Parse every material, and add to reforgeAble items
|
||||
for (String item : itemList) {
|
||||
//Ignore ,,
|
||||
if (InputParsingHelper.isEmpty(item)) {
|
||||
continue;
|
||||
}
|
||||
Material material = Material.matchMaterial(item.replace('-', '_'));
|
||||
|
||||
boolean blacklist = false;
|
||||
if (item.startsWith("-")) {
|
||||
blacklist = true;
|
||||
item = item.substring(1);
|
||||
}
|
||||
|
||||
Material material = InputParsingHelper.matchMaterial(item);
|
||||
if (material != null && BlacksmithTrait.isRepairable(new ItemStack(material, 1))) {
|
||||
this.reforgeAbleItems.add(material);
|
||||
if (!blacklist) {
|
||||
reforgeAbleItems.add(material);
|
||||
} else {
|
||||
blacklisted.add(material);
|
||||
}
|
||||
} else {
|
||||
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING, "Unable to verify " + item +
|
||||
" as a valid reforge-able item");
|
||||
}
|
||||
}
|
||||
|
||||
//Remove any blacklisted materials at the end to make sure order of arguments won't matter
|
||||
reforgeAbleItems.removeAll(blacklisted);
|
||||
return reforgeAbleItems;
|
||||
}
|
||||
|
||||
}
|
@ -43,6 +43,11 @@ public enum SettingValueType {
|
||||
/**
|
||||
* An enchantment
|
||||
*/
|
||||
ENCHANTMENT
|
||||
ENCHANTMENT,
|
||||
|
||||
/**
|
||||
* A comma-separated list of reforge-able items
|
||||
*/
|
||||
REFORGE_ABLE_ITEMS,
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package net.knarcraft.blacksmith.config;
|
||||
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.util.ItemHelper;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -12,6 +13,11 @@ import java.util.logging.Level;
|
||||
*/
|
||||
public enum SmithPreset {
|
||||
|
||||
/**
|
||||
* A blacksmith capable of re-forging everything
|
||||
*/
|
||||
BLACKSMITH(new SmithPresetFilter[]{}),
|
||||
|
||||
/**
|
||||
* A blacksmith capable of re-forging all weapons (including shields)
|
||||
*/
|
||||
@ -81,11 +87,23 @@ public enum SmithPreset {
|
||||
* @return <p>The string, possibly with the preset replaced</p>
|
||||
*/
|
||||
public static String replacePreset(String possiblePreset) {
|
||||
boolean negated = false;
|
||||
|
||||
String upperCasedPreset = possiblePreset.replace('-', '_').toUpperCase();
|
||||
if (!upperCasedPreset.startsWith("PRESET:")) {
|
||||
if (possiblePreset.startsWith("-")) {
|
||||
negated = true;
|
||||
}
|
||||
|
||||
if ((negated && !upperCasedPreset.startsWith("_PRESET:")) ||
|
||||
(!negated && !upperCasedPreset.startsWith("PRESET:"))) {
|
||||
return possiblePreset;
|
||||
}
|
||||
|
||||
//Strip the "-" here to prevent stripping for material names
|
||||
if (negated) {
|
||||
upperCasedPreset = upperCasedPreset.substring(1);
|
||||
}
|
||||
|
||||
//Parse the input
|
||||
SmithPresetFilter filter = null;
|
||||
SmithPreset preset;
|
||||
@ -105,11 +123,16 @@ public enum SmithPreset {
|
||||
}
|
||||
|
||||
//Return the list of materials included in the preset
|
||||
List<String> materialNames;
|
||||
if (filter != null) {
|
||||
return String.join(",", preset.getMaterialNames(filter));
|
||||
materialNames = preset.getMaterialNames(filter);
|
||||
} else {
|
||||
return String.join(",", preset.getMaterialNames());
|
||||
materialNames = preset.getMaterialNames();
|
||||
}
|
||||
if (negated) {
|
||||
materialNames = negateMaterials(materialNames);
|
||||
}
|
||||
return String.join(",", materialNames);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,6 +154,7 @@ public enum SmithPreset {
|
||||
*/
|
||||
public List<Material> getMaterials() {
|
||||
return switch (this) {
|
||||
case BLACKSMITH -> ItemHelper.getAllReforgeAbleMaterials();
|
||||
case WEAPON_SMITH -> getWeapons();
|
||||
case ARMOR_SMITH -> getArmor();
|
||||
case TOOL_SMITH -> getTools();
|
||||
@ -205,13 +229,13 @@ public enum SmithPreset {
|
||||
* @return <p>The resulting materials</p>
|
||||
*/
|
||||
private List<Material> getMaterialsEndingWith(String end) {
|
||||
List<Material> swords = new ArrayList<>();
|
||||
for (Material material : Material.values()) {
|
||||
List<Material> matchedMaterials = new ArrayList<>();
|
||||
for (Material material : ItemHelper.getAllReforgeAbleMaterials()) {
|
||||
if (!material.name().startsWith("LEGACY") && material.name().endsWith(end)) {
|
||||
swords.add(material);
|
||||
matchedMaterials.add(material);
|
||||
}
|
||||
}
|
||||
return swords;
|
||||
return matchedMaterials;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -247,4 +271,20 @@ public enum SmithPreset {
|
||||
return items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Negates the given material names
|
||||
*
|
||||
* @param materials <p>The material names to negate</p>
|
||||
* @return <p>The negated material names</p>
|
||||
*/
|
||||
private static List<String> negateMaterials(List<String> materials) {
|
||||
List<String> negatedMaterials = new ArrayList<>(materials.size());
|
||||
materials.forEach((material) -> {
|
||||
if (material != null && !material.isBlank()) {
|
||||
negatedMaterials.add("-" + material);
|
||||
}
|
||||
});
|
||||
return negatedMaterials;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,30 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.knarcraft.knarlib.property.ColorConversion;
|
||||
import net.knarcraft.knarlib.util.ColorHelper;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* A formatter for formatting displayed messages
|
||||
*/
|
||||
public final class BlacksmithStringFormatter {
|
||||
|
||||
private BlacksmithStringFormatter() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message from a blacksmith NPC to a player
|
||||
*
|
||||
* @param npc <p>The NPC sending the message</p>
|
||||
* @param player <p>The player to send the message to</p>
|
||||
* @param message <p>The message to send</p>
|
||||
*/
|
||||
public static void sendNPCMessage(NPC npc, Player player, String message) {
|
||||
player.sendMessage(ChatColor.GREEN + "[" + npc.getName() + "] -> You:" + ChatColor.RESET + " " +
|
||||
ColorHelper.translateColorCodes(message, ColorConversion.NORMAL));
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.replacePlaceholders;
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||
import net.knarcraft.knarlib.formatting.TranslatableMessage;
|
||||
|
||||
/**
|
||||
* An enum containing all translatable global messages
|
||||
@ -8,7 +10,7 @@ import static net.knarcraft.blacksmith.formatting.StringFormatter.replacePlaceho
|
||||
* <p>This does not include NPC messages as they are configurable per-npc, and can be translated by changing the
|
||||
* default message values in the main config file.</p>
|
||||
*/
|
||||
public enum TranslatableMessage {
|
||||
public enum BlacksmithTranslatableMessage implements TranslatableMessage {
|
||||
|
||||
/**
|
||||
* The message displayed when a configuration value has been successfully changed
|
||||
@ -50,11 +52,6 @@ public enum TranslatableMessage {
|
||||
*/
|
||||
NO_NPC_SELECTED,
|
||||
|
||||
/**
|
||||
* The message displayed if trying to change the default value of reforge-able item using commands
|
||||
*/
|
||||
DEFAULT_REFORGE_ABLE_ITEMS_UNCHANGEABLE,
|
||||
|
||||
/**
|
||||
* The message displayed if a string list is required, but something else is given
|
||||
*/
|
||||
@ -105,36 +102,6 @@ public enum TranslatableMessage {
|
||||
*/
|
||||
PRESET_MATERIALS,
|
||||
|
||||
/**
|
||||
* The format for displaying the exact duration of a blacksmith's cool-down or delay
|
||||
*/
|
||||
DURATION_FORMAT,
|
||||
|
||||
/**
|
||||
* The text to display for 0 seconds
|
||||
*/
|
||||
UNIT_NOW,
|
||||
|
||||
/**
|
||||
* The text to display for 1 second
|
||||
*/
|
||||
UNIT_SECOND,
|
||||
|
||||
/**
|
||||
* The text to display for a number of seconds
|
||||
*/
|
||||
UNIT_SECONDS,
|
||||
|
||||
/**
|
||||
* The text to display for 1 minute
|
||||
*/
|
||||
UNIT_MINUTE,
|
||||
|
||||
/**
|
||||
* The text to display for a number of minutes
|
||||
*/
|
||||
UNIT_MINUTES,
|
||||
|
||||
/**
|
||||
* The text to display when describing less than 10 seconds remaining
|
||||
*/
|
||||
@ -172,8 +139,8 @@ public enum TranslatableMessage {
|
||||
* @return <p>The message to display</p>
|
||||
*/
|
||||
public static String getRawValueMessage(String rawValue) {
|
||||
return StringFormatter.replacePlaceholder(Translator.getTranslatedMessage(TranslatableMessage.RAW_VALUE),
|
||||
"{rawValue}", rawValue);
|
||||
return StringFormatter.replacePlaceholder(BlacksmithPlugin.getTranslator().getTranslatedMessage(
|
||||
BlacksmithTranslatableMessage.RAW_VALUE), "{rawValue}", rawValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -184,8 +151,9 @@ public enum TranslatableMessage {
|
||||
* @return <p>The string to display to a user</p>
|
||||
*/
|
||||
public static String getValueChangedMessage(String setting, String newValue) {
|
||||
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.VALUE_CHANGED),
|
||||
new String[]{"{setting}", "{newValue}"}, new String[]{setting, newValue});
|
||||
return StringFormatter.replacePlaceholders(BlacksmithPlugin.getTranslator().getTranslatedMessage(
|
||||
BlacksmithTranslatableMessage.VALUE_CHANGED), new String[]{"{setting}", "{newValue}"},
|
||||
new String[]{setting, newValue});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -198,7 +166,8 @@ public enum TranslatableMessage {
|
||||
* @return <p>The string to display to a user</p>
|
||||
*/
|
||||
public static String getItemValueChangedMessage(String setting, ItemType itemType, String item, String newValue) {
|
||||
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.VALUE_FOR_ITEM_CHANGED),
|
||||
return StringFormatter.replacePlaceholders(BlacksmithPlugin.getTranslator().getTranslatedMessage(
|
||||
BlacksmithTranslatableMessage.VALUE_FOR_ITEM_CHANGED),
|
||||
new String[]{"{setting}", "{itemType}", "{item}", "{newValue}"},
|
||||
new String[]{setting, itemType.getItemTypeName(), item, newValue});
|
||||
}
|
||||
@ -211,8 +180,9 @@ public enum TranslatableMessage {
|
||||
* @return <p>The string to display to a user</p>
|
||||
*/
|
||||
public static String getCurrentValueMessage(String setting, String currentValue) {
|
||||
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.CURRENT_VALUE),
|
||||
new String[]{"{setting}", "{currentValue}"}, new String[]{setting, currentValue});
|
||||
return StringFormatter.replacePlaceholders(BlacksmithPlugin.getTranslator().getTranslatedMessage(
|
||||
BlacksmithTranslatableMessage.CURRENT_VALUE), new String[]{"{setting}", "{currentValue}"},
|
||||
new String[]{setting, currentValue});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -225,9 +195,14 @@ public enum TranslatableMessage {
|
||||
* @return <p>The string to display to a user</p>
|
||||
*/
|
||||
public static String getItemCurrentValueMessage(String setting, ItemType itemType, String item, String currentValue) {
|
||||
return replacePlaceholders(Translator.getTranslatedMessage(TranslatableMessage.CURRENT_VALUE_FOR_ITEM),
|
||||
return StringFormatter.replacePlaceholders(BlacksmithPlugin.getTranslator().getTranslatedMessage(
|
||||
BlacksmithTranslatableMessage.CURRENT_VALUE_FOR_ITEM),
|
||||
new String[]{"{setting}", "{itemType}", "{item}", "{currentValue}"},
|
||||
new String[]{setting, itemType.getItemTypeName(), item, currentValue});
|
||||
}
|
||||
|
||||
@Override
|
||||
public TranslatableMessage[] getAllMessages() {
|
||||
return BlacksmithTranslatableMessage.values();
|
||||
}
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
|
||||
/**
|
||||
* An enum representing all item types used in messages
|
||||
*/
|
||||
@ -15,8 +17,10 @@ public enum ItemType {
|
||||
*/
|
||||
public String getItemTypeName() {
|
||||
return switch (this) {
|
||||
case MATERIAL -> Translator.getTranslatedMessage(TranslatableMessage.ITEM_TYPE_MATERIAL);
|
||||
case ENCHANTMENT -> Translator.getTranslatedMessage(TranslatableMessage.ITEM_TYPE_ENCHANTMENT);
|
||||
case MATERIAL -> BlacksmithPlugin.getTranslator().getTranslatedMessage(
|
||||
BlacksmithTranslatableMessage.ITEM_TYPE_MATERIAL);
|
||||
case ENCHANTMENT -> BlacksmithPlugin.getTranslator().getTranslatedMessage(
|
||||
BlacksmithTranslatableMessage.ITEM_TYPE_ENCHANTMENT);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,128 +0,0 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
import net.citizensnpcs.api.npc.NPC;
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.md_5.bungee.api.ChatColor;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* A formatter for formatting displayed messages
|
||||
*/
|
||||
public final class StringFormatter {
|
||||
|
||||
private final static String pluginName = BlacksmithPlugin.getInstance().getDescription().getName();
|
||||
|
||||
private StringFormatter() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message from a blacksmith NPC to a player
|
||||
*
|
||||
* @param npc <p>The NPC sending the message</p>
|
||||
* @param player <p>The player to send the message to</p>
|
||||
* @param message <p>The message to send</p>
|
||||
*/
|
||||
public static void sendNPCMessage(NPC npc, Player player, String message) {
|
||||
player.sendMessage(ChatColor.GREEN + "[" + npc.getName() + "] -> You:" + ChatColor.RESET + " " +
|
||||
translateColors(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a message signifying a successful action
|
||||
*
|
||||
* @param sender <p>The command sender to display the message to</p>
|
||||
* @param message <p>The translatable message to display</p>
|
||||
*/
|
||||
public static void displaySuccessMessage(CommandSender sender, TranslatableMessage message) {
|
||||
sender.sendMessage(ChatColor.GREEN + getFormattedMessage(Translator.getTranslatedMessage(message)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a message signifying a successful action
|
||||
*
|
||||
* @param sender <p>The command sender to display the message to</p>
|
||||
* @param message <p>The raw message to display</p>
|
||||
*/
|
||||
public static void displaySuccessMessage(CommandSender sender, String message) {
|
||||
sender.sendMessage(ChatColor.GREEN + getFormattedMessage(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays a message signifying an unsuccessful action
|
||||
*
|
||||
* @param sender <p>The command sender to display the message to</p>
|
||||
* @param message <p>The translatable message to display</p>
|
||||
*/
|
||||
public static void displayErrorMessage(CommandSender sender, TranslatableMessage message) {
|
||||
sender.sendMessage(ChatColor.DARK_RED + getFormattedMessage(Translator.getTranslatedMessage(message)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the formatted version of any chat message
|
||||
*
|
||||
* @param message <p>The message to format</p>
|
||||
* @return <p>The formatted message</p>
|
||||
*/
|
||||
private static String getFormattedMessage(String message) {
|
||||
return "[" + pluginName + "] " + ChatColor.RESET + translateColors(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates & color codes to proper colors
|
||||
*
|
||||
* @param input <p>The input string to translate colors for</p>
|
||||
* @return <p>The input with color codes translated</p>
|
||||
*/
|
||||
private static String translateColors(String input) {
|
||||
return ChatColor.translateAlternateColorCodes('&', input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces a placeholder in a string
|
||||
*
|
||||
* @param input <p>The input string to replace in</p>
|
||||
* @param placeholder <p>The placeholder to replace</p>
|
||||
* @param replacement <p>The replacement value</p>
|
||||
* @return <p>The input string with the placeholder replaced</p>
|
||||
*/
|
||||
public static String replacePlaceholder(String input, String placeholder, String replacement) {
|
||||
return input.replace(placeholder, replacement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces placeholders in a string
|
||||
*
|
||||
* @param input <p>The input string to replace in</p>
|
||||
* @param placeholders <p>The placeholders to replace</p>
|
||||
* @param replacements <p>The replacement values</p>
|
||||
* @return <p>The input string with placeholders replaced</p>
|
||||
*/
|
||||
public static String replacePlaceholders(String input, String[] placeholders, String[] replacements) {
|
||||
for (int i = 0; i < Math.min(placeholders.length, replacements.length); i++) {
|
||||
input = replacePlaceholder(input, placeholders[i], replacements[i]);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates all found color codes to formatting in a string
|
||||
*
|
||||
* @param message <p>The string to search for color codes</p>
|
||||
* @return <p>The message with color codes translated</p>
|
||||
*/
|
||||
public static String translateAllColorCodes(String message) {
|
||||
message = ChatColor.translateAlternateColorCodes('&', message);
|
||||
Pattern pattern = Pattern.compile("(#[a-fA-F0-9]{6})");
|
||||
Matcher matcher = pattern.matcher(message);
|
||||
while (matcher.find()) {
|
||||
message = message.replace(matcher.group(), "" + ChatColor.of(matcher.group()));
|
||||
}
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +1,16 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.replacePlaceholder;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* A utility for formatting a string specifying an amount of time
|
||||
*/
|
||||
public final class TimeFormatter {
|
||||
|
||||
private static Map<Double, TranslatableMessage[]> timeUnits;
|
||||
private static List<Double> sortedUnits;
|
||||
|
||||
private TimeFormatter() {
|
||||
|
||||
}
|
||||
@ -31,7 +24,7 @@ public final class TimeFormatter {
|
||||
*/
|
||||
public static String formatTime(boolean exact, int seconds) {
|
||||
if (exact) {
|
||||
return getDurationString(seconds);
|
||||
return net.knarcraft.knarlib.formatting.TimeFormatter.getDurationString(BlacksmithPlugin.getTranslator(), seconds);
|
||||
} else {
|
||||
return formatUnclearTime(seconds);
|
||||
}
|
||||
@ -60,7 +53,7 @@ public final class TimeFormatter {
|
||||
* @return <p>Text describing the time interval</p>
|
||||
*/
|
||||
private static String getMessageFromInterval(TimeInterval interval) {
|
||||
String text = Translator.getTranslatedMessage(TranslatableMessage.valueOf(interval.name()));
|
||||
String text = BlacksmithPlugin.getTranslator().getTranslatedMessage(BlacksmithTranslatableMessage.valueOf(interval.name()));
|
||||
|
||||
//Choose a random entry if a comma-separated list is provided
|
||||
if (text != null && text.contains(",")) {
|
||||
@ -79,68 +72,4 @@ public final class TimeFormatter {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string used for displaying this sign's duration
|
||||
*
|
||||
* @return <p>The string used for displaying this sign's duration</p>
|
||||
*/
|
||||
public static String getDurationString(int duration) {
|
||||
if (duration == 0) {
|
||||
return Translator.getTranslatedMessage(TranslatableMessage.UNIT_NOW);
|
||||
} else {
|
||||
if (sortedUnits == null) {
|
||||
initializeUnits();
|
||||
}
|
||||
for (Double unit : sortedUnits) {
|
||||
if (duration / unit >= 1) {
|
||||
double units = round(duration / unit);
|
||||
return formatDurationString(units, timeUnits.get(unit)[units == 1 ? 0 : 1],
|
||||
(units * 10) % 10 == 0);
|
||||
}
|
||||
}
|
||||
return formatDurationString(duration, TranslatableMessage.UNIT_SECONDS, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds a number to its last two digits
|
||||
*
|
||||
* @param number <p>The number to round</p>
|
||||
* @return <p>The rounded number</p>
|
||||
*/
|
||||
private static double round(double number) {
|
||||
return Math.round(number * 100.0) / 100.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats a duration string
|
||||
*
|
||||
* @param duration <p>The duration to display</p>
|
||||
* @param translatableMessage <p>The time unit to display</p>
|
||||
* @param castToInt <p>Whether to cast the duration to an int</p>
|
||||
* @return <p>The formatted duration string</p>
|
||||
*/
|
||||
private static String formatDurationString(double duration, TranslatableMessage translatableMessage, boolean castToInt) {
|
||||
String durationFormat = Translator.getTranslatedMessage(TranslatableMessage.DURATION_FORMAT);
|
||||
durationFormat = replacePlaceholder(durationFormat, "{unit}",
|
||||
Translator.getTranslatedMessage(translatableMessage));
|
||||
return replacePlaceholder(durationFormat, "{duration}", castToInt ? String.valueOf((int) duration) :
|
||||
String.valueOf(duration));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the mapping of available time units for formatting permission sign duration
|
||||
*/
|
||||
private static void initializeUnits() {
|
||||
double minute = 60;
|
||||
|
||||
timeUnits = new HashMap<>();
|
||||
timeUnits.put(minute, new TranslatableMessage[]{TranslatableMessage.UNIT_MINUTE, TranslatableMessage.UNIT_MINUTES});
|
||||
timeUnits.put(1D, new TranslatableMessage[]{TranslatableMessage.UNIT_SECOND, TranslatableMessage.UNIT_SECONDS});
|
||||
|
||||
sortedUnits = new ArrayList<>(timeUnits.keySet());
|
||||
Collections.sort(sortedUnits);
|
||||
Collections.reverse(sortedUnits);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ public enum TimeInterval {
|
||||
/**
|
||||
* Less than 10 seconds left
|
||||
*/
|
||||
INTERVAL_LESS_THAN_10_SECONDS("momentarily", 10),
|
||||
INTERVAL_LESS_THAN_10_SECONDS("in just a moment", 10),
|
||||
|
||||
/**
|
||||
* Less than 30 seconds left
|
||||
|
@ -1,120 +0,0 @@
|
||||
package net.knarcraft.blacksmith.formatting;
|
||||
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.util.FileHelper;
|
||||
import org.bukkit.configuration.file.YamlConfiguration;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/**
|
||||
* A tool to get strings translated to the correct language
|
||||
*/
|
||||
public final class Translator {
|
||||
|
||||
private static Map<TranslatableMessage, String> translatedMessages;
|
||||
private static Map<TranslatableMessage, String> backupTranslatedMessages;
|
||||
|
||||
private Translator() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the languages used by this translator
|
||||
*/
|
||||
public static void loadLanguages(String selectedLanguage) {
|
||||
backupTranslatedMessages = loadTranslatedMessages("en");
|
||||
translatedMessages = loadCustomTranslatedMessages(selectedLanguage);
|
||||
if (translatedMessages == null) {
|
||||
translatedMessages = loadTranslatedMessages(selectedLanguage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a translated version of the given translatable message
|
||||
*
|
||||
* @param translatableMessage <p>The message to translate</p>
|
||||
* @return <p>The translated message</p>
|
||||
*/
|
||||
public static String getTranslatedMessage(TranslatableMessage translatableMessage) {
|
||||
if (translatedMessages == null) {
|
||||
return "Translated strings not loaded";
|
||||
}
|
||||
String translatedMessage;
|
||||
if (translatedMessages.containsKey(translatableMessage)) {
|
||||
translatedMessage = translatedMessages.get(translatableMessage);
|
||||
} else if (backupTranslatedMessages.containsKey(translatableMessage)) {
|
||||
translatedMessage = backupTranslatedMessages.get(translatableMessage);
|
||||
} else {
|
||||
translatedMessage = translatableMessage.toString();
|
||||
}
|
||||
return StringFormatter.translateAllColorCodes(translatedMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads all translated messages for the given language
|
||||
*
|
||||
* @param language <p>The language chosen by the user</p>
|
||||
* @return <p>A mapping of all strings for the given language</p>
|
||||
*/
|
||||
public static Map<TranslatableMessage, String> loadTranslatedMessages(String language) {
|
||||
try {
|
||||
BufferedReader reader = FileHelper.getBufferedReaderForInternalFile("/strings.yml");
|
||||
return loadTranslatableMessages(language, reader);
|
||||
} catch (FileNotFoundException e) {
|
||||
BlacksmithPlugin.getInstance().getLogger().log(Level.SEVERE, "Unable to load translated messages");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to load translated messages from a custom strings.yml file
|
||||
*
|
||||
* @param language <p>The selected language</p>
|
||||
* @return <p>The loaded translated strings, or null if no custom language file exists</p>
|
||||
*/
|
||||
public static Map<TranslatableMessage, String> loadCustomTranslatedMessages(String language) {
|
||||
BlacksmithPlugin instance = BlacksmithPlugin.getInstance();
|
||||
|
||||
File strings = new File(instance.getDataFolder(), "strings.yml");
|
||||
if (!strings.exists()) {
|
||||
instance.getLogger().log(Level.FINEST, "Strings file not found");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
instance.getLogger().log(Level.INFO, "Loading custom strings...");
|
||||
return loadTranslatableMessages(language, new BufferedReader(new InputStreamReader(new FileInputStream(strings))));
|
||||
} catch (FileNotFoundException e) {
|
||||
instance.getLogger().log(Level.WARNING, "Unable to load custom messages");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads translatable messages from the given reader
|
||||
*
|
||||
* @param language <p>The selected language</p>
|
||||
* @param reader <p>The buffered reader to read from</p>
|
||||
* @return <p>The loaded translated strings</p>
|
||||
*/
|
||||
private static Map<TranslatableMessage, String> loadTranslatableMessages(String language, BufferedReader reader) {
|
||||
Map<TranslatableMessage, String> translatedMessages = new HashMap<>();
|
||||
YamlConfiguration configuration = YamlConfiguration.loadConfiguration(reader);
|
||||
|
||||
for (TranslatableMessage message : TranslatableMessage.values()) {
|
||||
String translated = configuration.getString(language + "." + message.toString());
|
||||
if (translated != null) {
|
||||
translatedMessages.put(message, translated);
|
||||
}
|
||||
}
|
||||
return translatedMessages;
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package net.knarcraft.blacksmith.listener;
|
||||
|
||||
import net.knarcraft.blacksmith.formatting.StringFormatter;
|
||||
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage;
|
||||
import net.knarcraft.blacksmith.trait.BlacksmithTrait;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
@ -25,7 +25,8 @@ public class NPCClickListener implements Listener {
|
||||
|
||||
//Permission check
|
||||
if (!player.hasPermission("blacksmith.use")) {
|
||||
StringFormatter.displayErrorMessage(player, TranslatableMessage.PERMISSION_DENIED);
|
||||
BlacksmithPlugin.getStringFormatter().displayErrorMessage(player,
|
||||
BlacksmithTranslatableMessage.PERMISSION_DENIED);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -91,6 +91,7 @@ public class EconomyManager {
|
||||
private static double getCost(ItemStack item) {
|
||||
GlobalSettings globalSettings = BlacksmithPlugin.getInstance().getSettings();
|
||||
Material material = item.getType();
|
||||
|
||||
//Calculate the base price
|
||||
double price = globalSettings.getBasePrice(material);
|
||||
|
||||
@ -106,6 +107,11 @@ public class EconomyManager {
|
||||
|
||||
//Increase price for any enchantments
|
||||
price += getEnchantmentCost(item);
|
||||
|
||||
//Override the cost for anvils
|
||||
if (ItemHelper.isAnvil(material, true)) {
|
||||
price = globalSettings.getAnvilCost(material);
|
||||
}
|
||||
return price;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@ import net.knarcraft.blacksmith.config.NPCSettings;
|
||||
import net.knarcraft.blacksmith.formatting.TimeFormatter;
|
||||
import net.knarcraft.blacksmith.manager.EconomyManager;
|
||||
import net.knarcraft.blacksmith.util.ItemHelper;
|
||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.EnchantmentTarget;
|
||||
@ -23,8 +24,7 @@ import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.replacePlaceholder;
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.sendNPCMessage;
|
||||
import static net.knarcraft.blacksmith.formatting.BlacksmithStringFormatter.sendNPCMessage;
|
||||
|
||||
/**
|
||||
* The class representing the Blacksmith NPC trait
|
||||
@ -114,7 +114,7 @@ public class BlacksmithTrait extends Trait {
|
||||
coolDowns.remove(playerId);
|
||||
}
|
||||
//Deny if permission is missing
|
||||
if (!player.hasPermission("blacksmith.reforge")) {
|
||||
if (!player.hasPermission("blacksmith.use")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -122,9 +122,9 @@ public class BlacksmithTrait extends Trait {
|
||||
if (coolDowns.get(playerId) != null) {
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
if (!calendar.after(coolDowns.get(playerId))) {
|
||||
int secondDifference = (int) ((calendar.getTimeInMillis() - coolDowns.get(playerId).getTimeInMillis()) * 1000);
|
||||
int secondDifference = (int) (coolDowns.get(playerId).getTimeInMillis() - calendar.getTimeInMillis()) / 1000;
|
||||
boolean exactTime = BlacksmithPlugin.getInstance().getSettings().getShowExactTime();
|
||||
sendNPCMessage(this.npc, player, replacePlaceholder(config.getCoolDownUnexpiredMessage(),
|
||||
sendNPCMessage(this.npc, player, StringFormatter.replacePlaceholder(config.getCoolDownUnexpiredMessage(),
|
||||
"{time}", TimeFormatter.formatTime(exactTime, secondDifference)));
|
||||
return false;
|
||||
}
|
||||
@ -133,8 +133,8 @@ public class BlacksmithTrait extends Trait {
|
||||
|
||||
//If already in a session, but the player has failed to interact, and left the blacksmith, allow a new session
|
||||
if (session != null) {
|
||||
if (System.currentTimeMillis() > _sessionStart + 10 * 1000 &&
|
||||
this.npc.getEntity().getLocation().distance(session.getPlayer().getLocation()) > 20) {
|
||||
if (!session.isRunning() && (System.currentTimeMillis() > _sessionStart + 10 * 1000 ||
|
||||
this.npc.getEntity().getLocation().distance(session.getPlayer().getLocation()) > 20)) {
|
||||
session = null;
|
||||
}
|
||||
}
|
||||
@ -157,8 +157,8 @@ public class BlacksmithTrait extends Trait {
|
||||
if (session.isRunning()) {
|
||||
int timeRemaining = (int) ((session.getFinishTime() - System.currentTimeMillis()) / 1000);
|
||||
boolean showExactTime = BlacksmithPlugin.getInstance().getSettings().getShowExactTime();
|
||||
sendNPCMessage(this.npc, player, replacePlaceholder(config.getBusyReforgingMessage(), "{time}",
|
||||
TimeFormatter.formatTime(showExactTime, timeRemaining)));
|
||||
sendNPCMessage(this.npc, player, StringFormatter.replacePlaceholder(config.getBusyReforgingMessage(),
|
||||
"{time}", TimeFormatter.formatTime(showExactTime, timeRemaining)));
|
||||
return;
|
||||
}
|
||||
if (session.endSession()) {
|
||||
@ -179,14 +179,15 @@ public class BlacksmithTrait extends Trait {
|
||||
ItemStack hand = player.getInventory().getItemInMainHand();
|
||||
//Refuse if not repairable, or if reforge-able items is set, but doesn't include the held item
|
||||
List<Material> reforgeAbleItems = config.getReforgeAbleItems();
|
||||
if (!isRepairable(hand) || (!reforgeAbleItems.isEmpty() && !reforgeAbleItems.contains(hand.getType()))) {
|
||||
String invalidMessage = replacePlaceholder(config.getInvalidItemMessage(),
|
||||
if ((!this.config.getRepairAnvils() || !ItemHelper.isAnvil(hand.getType(), false)) &&
|
||||
(!isRepairable(hand) || (!reforgeAbleItems.isEmpty() && !reforgeAbleItems.contains(hand.getType())))) {
|
||||
String invalidMessage = StringFormatter.replacePlaceholder(config.getInvalidItemMessage(),
|
||||
"{title}", config.getBlacksmithTitle());
|
||||
sendNPCMessage(this.npc, player, invalidMessage);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ItemHelper.getDamage(hand) == 0) {
|
||||
if (ItemHelper.getDamage(hand) == 0 && !ItemHelper.isAnvil(hand.getType(), true)) {
|
||||
sendNPCMessage(this.npc, player, config.getNotDamagedMessage());
|
||||
return;
|
||||
}
|
||||
|
@ -4,8 +4,9 @@ import net.citizensnpcs.api.npc.NPC;
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.config.NPCSettings;
|
||||
import net.knarcraft.blacksmith.manager.EconomyManager;
|
||||
import net.knarcraft.blacksmith.util.InputParsingHelper;
|
||||
import net.knarcraft.blacksmith.util.ItemHelper;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
@ -21,7 +22,7 @@ import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.sendNPCMessage;
|
||||
import static net.knarcraft.blacksmith.formatting.BlacksmithStringFormatter.sendNPCMessage;
|
||||
|
||||
/**
|
||||
* A representation of the session between a player and a blacksmith
|
||||
@ -57,7 +58,7 @@ public class ReforgeSession implements Runnable {
|
||||
if (enchantments[0] == null) {
|
||||
int i = 0;
|
||||
for (Enchantment enchantment : Enchantment.values()) {
|
||||
enchantments[i++] = enchantment.getKey().toString();
|
||||
enchantments[i++] = enchantment.getKey().getKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -129,6 +130,11 @@ public class ReforgeSession implements Runnable {
|
||||
// Remove any damage done to the item
|
||||
updateDamage(itemToReforge, 0);
|
||||
|
||||
//Replace damaged anvils with a normal anvil
|
||||
if (ItemHelper.isAnvil(itemToReforge.getType(), true)) {
|
||||
itemToReforge.setType(Material.ANVIL);
|
||||
}
|
||||
|
||||
// Add random enchantments
|
||||
int roll = random.nextInt(100);
|
||||
if (!(roll < config.getExtraEnchantmentChance() &&
|
||||
@ -140,11 +146,18 @@ public class ReforgeSession implements Runnable {
|
||||
//Find usable enchantments first
|
||||
List<Enchantment> usableEnchantments = new ArrayList<>();
|
||||
for (String enchantmentName : enchantments) {
|
||||
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.fromString(enchantmentName));
|
||||
Enchantment enchantment = InputParsingHelper.matchEnchantment(enchantmentName);
|
||||
if (enchantment != null && enchantment.canEnchantItem(itemToReforge)) {
|
||||
usableEnchantments.add(enchantment);
|
||||
}
|
||||
}
|
||||
//Remove any enchantments in the block list
|
||||
usableEnchantments.removeAll(blacksmithTrait.getSettings().getEnchantmentBlocklist());
|
||||
|
||||
//In case all usable enchantments have been blocked, abort
|
||||
if (usableEnchantments.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//Choose a random enchantment
|
||||
Enchantment randomEnchantment = usableEnchantments.get(random.nextInt(usableEnchantments.size()));
|
||||
|
@ -1,5 +1,8 @@
|
||||
package net.knarcraft.blacksmith.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A helper class for getting an object value as the correct type
|
||||
*/
|
||||
@ -9,6 +12,25 @@ public final class ConfigHelper {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the given value as a string list
|
||||
*
|
||||
* @param value <p>The raw string list value</p>
|
||||
* @return <p>The value as a string list</p>
|
||||
*/
|
||||
public static List<String> asStringList(Object value) {
|
||||
if (value instanceof String) {
|
||||
return List.of(((String) value).split(","));
|
||||
} else {
|
||||
List<String> strings = new ArrayList<>();
|
||||
List<?> list = (List<?>) value;
|
||||
for (Object object : list) {
|
||||
strings.add(String.valueOf(object));
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the given value as a double
|
||||
*
|
||||
|
@ -1,32 +0,0 @@
|
||||
package net.knarcraft.blacksmith.util;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
/**
|
||||
* A helper class for dealing with files
|
||||
*/
|
||||
public final class FileHelper {
|
||||
|
||||
private FileHelper() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a buffered reader for
|
||||
*
|
||||
* @return <p>A buffered read for reading the file</p>
|
||||
* @throws FileNotFoundException <p>If unable to get an input stream for the given file</p>
|
||||
*/
|
||||
public static BufferedReader getBufferedReaderForInternalFile(String file) throws FileNotFoundException {
|
||||
InputStream inputStream = FileHelper.class.getResourceAsStream(file);
|
||||
if (inputStream == null) {
|
||||
throw new FileNotFoundException("Unable to read the given file");
|
||||
}
|
||||
return new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
}
|
@ -13,6 +13,17 @@ public final class InputParsingHelper {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether the input is an "empty" value treated as null
|
||||
*
|
||||
* @param input <p>The input to check</p>
|
||||
* @return <p>True if the value is empty</p>
|
||||
*/
|
||||
public static boolean isEmpty(String input) {
|
||||
return input == null || input.equalsIgnoreCase("null") || input.equals("\"\"") ||
|
||||
input.trim().isEmpty() || input.equals("-1");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to find the material matching the given input string
|
||||
*
|
||||
@ -33,4 +44,14 @@ public final class InputParsingHelper {
|
||||
return Enchantment.getByKey(NamespacedKey.minecraft(input.replace("-", "_")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a material name like "*helmet" into a regular expression ".*HELMET"
|
||||
*
|
||||
* @param input <p>The input to RegExIfy</p>
|
||||
* @return <p>The converted input</p>
|
||||
*/
|
||||
public static String regExIfy(String input) {
|
||||
return input.replace("*", ".*").toUpperCase().replace("-", "_");
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,13 @@
|
||||
package net.knarcraft.blacksmith.util;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.EnchantmentTarget;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class ItemHelper {
|
||||
|
||||
private ItemHelper() {
|
||||
@ -40,4 +45,33 @@ public final class ItemHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a complete list of all reforge-able materials
|
||||
*
|
||||
* @return <p>A complete list of reforge-able materials</p>
|
||||
*/
|
||||
public static List<Material> getAllReforgeAbleMaterials() {
|
||||
List<Material> reforgeAbleMaterials = new ArrayList<>();
|
||||
for (Material material : Material.values()) {
|
||||
ItemStack item = new ItemStack(material);
|
||||
if (item.getItemMeta() instanceof Damageable && EnchantmentTarget.BREAKABLE.includes(item)) {
|
||||
reforgeAbleMaterials.add(material);
|
||||
}
|
||||
}
|
||||
return reforgeAbleMaterials;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the given material is an anvil
|
||||
*
|
||||
* @param material <p>The material to check</p>
|
||||
* @param requireDamaged <p>Whether only a damaged anvil should count</p>
|
||||
* @return <p>True if the given material is an anvil</p>
|
||||
*/
|
||||
public static boolean isAnvil(Material material, boolean requireDamaged) {
|
||||
boolean isDamagedAnvil = material == Material.CHIPPED_ANVIL || material == Material.DAMAGED_ANVIL;
|
||||
boolean isAnvil = isDamagedAnvil || material == Material.ANVIL;
|
||||
return (requireDamaged && isDamagedAnvil) || (!requireDamaged && isAnvil);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,11 +1,10 @@
|
||||
package net.knarcraft.blacksmith.util;
|
||||
|
||||
import net.knarcraft.blacksmith.config.SettingValueType;
|
||||
import net.knarcraft.blacksmith.config.SmithPreset;
|
||||
import net.knarcraft.blacksmith.config.SmithPresetFilter;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.enchantments.EnchantmentTarget;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.Damageable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@ -32,25 +31,47 @@ public final class TabCompleteValuesHelper {
|
||||
case POSITIVE_DOUBLE -> getPositiveDoubles();
|
||||
case STRING -> getStrings();
|
||||
case PERCENTAGE -> getPercentages();
|
||||
case STRING_LIST -> getReforgeAbleMaterials();
|
||||
case MATERIAL -> getAllReforgeAbleMaterials();
|
||||
case REFORGE_ABLE_ITEMS -> getReforgeAbleMaterials();
|
||||
case MATERIAL -> getAllReforgeAbleMaterialNames();
|
||||
case ENCHANTMENT -> getAllEnchantments();
|
||||
case STRING_LIST -> getExampleEnchantmentBlockLists();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a complete list of all reforge-able materials
|
||||
* Gets example enchantment block lists
|
||||
*
|
||||
* @return <p>A complete list of reforge-able materials</p>
|
||||
* @return <p>Some example enchantment block lists</p>
|
||||
*/
|
||||
private static List<String> getAllReforgeAbleMaterials() {
|
||||
private static List<String> getExampleEnchantmentBlockLists() {
|
||||
List<String> exampleBlockLists = new ArrayList<>();
|
||||
exampleBlockLists.add(Enchantment.VANISHING_CURSE.getKey().getKey() + "," +
|
||||
Enchantment.BINDING_CURSE.getKey().getKey() + "," + Enchantment.MENDING.getKey().getKey());
|
||||
exampleBlockLists.add(Enchantment.VANISHING_CURSE.getKey().getKey() + "," +
|
||||
Enchantment.BINDING_CURSE.getKey().getKey());
|
||||
return exampleBlockLists;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a complete list of all reforge-able material names
|
||||
*
|
||||
* @return <p>A complete list of reforge-able material names</p>
|
||||
*/
|
||||
private static List<String> getAllReforgeAbleMaterialNames() {
|
||||
List<String> reforgeAbleMaterials = new ArrayList<>();
|
||||
for (Material material : Material.values()) {
|
||||
ItemStack item = new ItemStack(material);
|
||||
if (item.getItemMeta() instanceof Damageable && EnchantmentTarget.BREAKABLE.includes(item)) {
|
||||
reforgeAbleMaterials.add(material.name());
|
||||
}
|
||||
for (Material material : ItemHelper.getAllReforgeAbleMaterials()) {
|
||||
reforgeAbleMaterials.add(material.name());
|
||||
}
|
||||
reforgeAbleMaterials.add("NETHERITE_*");
|
||||
reforgeAbleMaterials.add("DIAMOND_*");
|
||||
reforgeAbleMaterials.add("GOLDEN_*");
|
||||
reforgeAbleMaterials.add("IRON_*");
|
||||
reforgeAbleMaterials.add("CHAINMAIL_*");
|
||||
reforgeAbleMaterials.add("STONE_*");
|
||||
reforgeAbleMaterials.add("*BOW");
|
||||
reforgeAbleMaterials.add("LEATHER_*");
|
||||
reforgeAbleMaterials.add("WOODEN_*");
|
||||
return reforgeAbleMaterials;
|
||||
}
|
||||
|
||||
@ -62,7 +83,7 @@ public final class TabCompleteValuesHelper {
|
||||
private static List<String> getAllEnchantments() {
|
||||
List<String> enchantments = new ArrayList<>();
|
||||
for (Enchantment enchantment : Enchantment.values()) {
|
||||
enchantments.add(enchantment.toString());
|
||||
enchantments.add(enchantment.getKey().getKey());
|
||||
}
|
||||
return enchantments;
|
||||
}
|
||||
@ -74,12 +95,17 @@ public final class TabCompleteValuesHelper {
|
||||
*/
|
||||
private static List<String> getReforgeAbleMaterials() {
|
||||
List<String> stringLists = new ArrayList<>();
|
||||
stringLists.add("preset:sword-smith");
|
||||
stringLists.add("preset:weapon-smith");
|
||||
stringLists.add("preset:armor-smith");
|
||||
stringLists.add("preset:tool-smith");
|
||||
stringLists.add("preset:ranged-smith");
|
||||
stringLists.add("bow,crossbow,elytra");
|
||||
for (SmithPreset preset : SmithPreset.values()) {
|
||||
stringLists.add("preset:" + preset.name());
|
||||
for (SmithPresetFilter filter : preset.getSupportedFilters()) {
|
||||
stringLists.add("preset:" + preset.name() + ":" + filter.name());
|
||||
}
|
||||
}
|
||||
stringLists.add("preset:WEAPON_SMITH:RANGED,SHIELD");
|
||||
stringLists.add("preset:WEAPON_SMITH,preset:ARMOR_SMITH");
|
||||
stringLists.add("preset:WEAPON_SMITH,preset:TOOL_SMITH");
|
||||
stringLists.add("preset:ARMOR_SMITH,preset:TOOL_SMITH");
|
||||
stringLists.add("BOW,CROSSBOW,ELYTRA");
|
||||
return stringLists;
|
||||
}
|
||||
|
||||
|
@ -1,32 +0,0 @@
|
||||
package net.knarcraft.blacksmith.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A helper class for tab-completion
|
||||
*/
|
||||
public final class TabCompletionHelper {
|
||||
|
||||
private TabCompletionHelper() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds tab complete values that contain the typed text
|
||||
*
|
||||
* @param values <p>The values to filter</p>
|
||||
* @param typedText <p>The text the player has started typing</p>
|
||||
* @return <p>The given string values that contain the player's typed text</p>
|
||||
*/
|
||||
public static List<String> filterMatchingContains(List<String> values, String typedText) {
|
||||
List<String> configValues = new ArrayList<>();
|
||||
for (String value : values) {
|
||||
if (value.toLowerCase().contains(typedText.toLowerCase())) {
|
||||
configValues.add(value);
|
||||
}
|
||||
}
|
||||
return configValues;
|
||||
}
|
||||
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
package net.knarcraft.blacksmith.util;
|
||||
|
||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||
import net.knarcraft.blacksmith.config.SettingValueType;
|
||||
import net.knarcraft.blacksmith.formatting.TranslatableMessage;
|
||||
import net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
||||
import static net.knarcraft.blacksmith.formatting.StringFormatter.displayErrorMessage;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A helper class for validating a value's type
|
||||
@ -31,7 +32,7 @@ public final class TypeValidationHelper {
|
||||
case POSITIVE_INTEGER -> isPositiveInteger(value, sender);
|
||||
case PERCENTAGE -> isPercentage(value, sender);
|
||||
case BOOLEAN -> true;
|
||||
case STRING_LIST -> isStringList(value, sender);
|
||||
case STRING_LIST, REFORGE_ABLE_ITEMS -> isStringList(value, sender);
|
||||
case MATERIAL, ENCHANTMENT -> false;
|
||||
};
|
||||
} catch (ClassCastException exception) {
|
||||
@ -48,9 +49,10 @@ public final class TypeValidationHelper {
|
||||
* @return <p>True if the value is a string list</p>
|
||||
*/
|
||||
private static boolean isStringList(Object value, CommandSender sender) {
|
||||
boolean isStringList = value instanceof String[] || value instanceof String;
|
||||
boolean isStringList = value instanceof String[] || value instanceof List<?> || value instanceof String;
|
||||
if (!isStringList && sender != null) {
|
||||
displayErrorMessage(sender, TranslatableMessage.INPUT_STRING_LIST_REQUIRED);
|
||||
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
|
||||
BlacksmithTranslatableMessage.INPUT_STRING_LIST_REQUIRED);
|
||||
}
|
||||
return isStringList;
|
||||
}
|
||||
@ -65,10 +67,11 @@ public final class TypeValidationHelper {
|
||||
private static boolean isPercentage(Object value, CommandSender sender) {
|
||||
try {
|
||||
int intValue = ConfigHelper.asInt(value);
|
||||
return intValue > 0 && intValue <= 100;
|
||||
return intValue >= 0 && intValue <= 100;
|
||||
} catch (NumberFormatException | NullPointerException exception) {
|
||||
if (sender != null) {
|
||||
displayErrorMessage(sender, TranslatableMessage.INPUT_PERCENTAGE_REQUIRED);
|
||||
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
|
||||
BlacksmithTranslatableMessage.INPUT_PERCENTAGE_REQUIRED);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -82,9 +85,10 @@ public final class TypeValidationHelper {
|
||||
* @return <p>True if the value is a non-empty string</p>
|
||||
*/
|
||||
private static boolean isNonEmptyString(Object value, CommandSender sender) {
|
||||
boolean isString = value instanceof String string && !string.strip().isEmpty();
|
||||
boolean isString = value instanceof String string && !string.isBlank();
|
||||
if (!isString && sender != null) {
|
||||
displayErrorMessage(sender, TranslatableMessage.INPUT_STRING_REQUIRED);
|
||||
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
|
||||
BlacksmithTranslatableMessage.INPUT_STRING_REQUIRED);
|
||||
}
|
||||
return isString;
|
||||
}
|
||||
@ -98,10 +102,11 @@ public final class TypeValidationHelper {
|
||||
*/
|
||||
private static boolean isPositiveDouble(Object value, CommandSender sender) {
|
||||
try {
|
||||
return ConfigHelper.asDouble(value) > 0.0;
|
||||
return ConfigHelper.asDouble(value) >= 0.0;
|
||||
} catch (NumberFormatException | NullPointerException exception) {
|
||||
if (sender != null) {
|
||||
displayErrorMessage(sender, TranslatableMessage.INPUT_POSITIVE_DOUBLE_REQUIRED);
|
||||
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
|
||||
BlacksmithTranslatableMessage.INPUT_POSITIVE_DOUBLE_REQUIRED);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -116,10 +121,11 @@ public final class TypeValidationHelper {
|
||||
*/
|
||||
private static boolean isPositiveInteger(Object value, CommandSender sender) {
|
||||
try {
|
||||
return ConfigHelper.asInt(value) > 0;
|
||||
return ConfigHelper.asInt(value) >= 0;
|
||||
} catch (NumberFormatException | NullPointerException exception) {
|
||||
if (sender != null) {
|
||||
displayErrorMessage(sender, TranslatableMessage.INPUT_POSITIVE_INTEGER_REQUIRED);
|
||||
BlacksmithPlugin.getStringFormatter().displayErrorMessage(sender,
|
||||
BlacksmithTranslatableMessage.INPUT_POSITIVE_INTEGER_REQUIRED);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -1,5 +1,8 @@
|
||||
# Blacksmith Configuration
|
||||
|
||||
# The language used for messages. Only "en" is supported
|
||||
language: en
|
||||
|
||||
# The settings which apply to all Blacksmith NPCs. These can also be changed using the /blacksmithconfig command
|
||||
global:
|
||||
# The minimum price of each cost
|
||||
@ -25,6 +28,12 @@ global:
|
||||
# reforging delay messages, instead of just vaguely hinting at the remaining time.
|
||||
showExactTime: false
|
||||
|
||||
# The cost of fully repairing a chipped anvil
|
||||
chippedAnvilReforgingCost: 10.0
|
||||
|
||||
# The cost of fully repairing a damaged anvil
|
||||
damagedAnvilReforgingCost: 20.0
|
||||
|
||||
# The settings which are set to any new NPC. To change any of these settings for an existing NPC, you must change the
|
||||
# Citizens NPC file, or use the /blacksmith command
|
||||
defaults:
|
||||
@ -36,6 +45,9 @@ defaults:
|
||||
# up yet.
|
||||
reforgeAbleItems: [ ]
|
||||
|
||||
# The enchantments a blacksmith is denied from applying to an item. Disable anything you find too op or annoying.
|
||||
enchantmentBlocklist: [ "binding_curse", "mending", "vanishing_curse" ]
|
||||
|
||||
# The chance to fail reforging an item, which only repairs the item a tiny bit or not at all (0-100)
|
||||
failReforgeChance: 10 # Default = 10%
|
||||
|
||||
@ -45,6 +57,9 @@ defaults:
|
||||
# The maximum number of enchantments the blacksmith will try to add
|
||||
maxEnchantments: 3
|
||||
|
||||
# Whether the blacksmith will reforge anvils as a special case
|
||||
reforgeAnvils: false
|
||||
|
||||
# All settable delays
|
||||
delaysInSeconds:
|
||||
# The maximum time for a reforging to finish
|
||||
|
@ -1,7 +1,7 @@
|
||||
name: Blacksmith
|
||||
author: EpicKnarvik97, aPunch, jrbudda, HurricanKai
|
||||
authors: [ EpicKnarvik97, aPunch, jrbudda, HurricanKai ]
|
||||
version: 1.0.0
|
||||
version: '${project.version}'
|
||||
main: net.knarcraft.blacksmith.BlacksmithPlugin
|
||||
depend: [ Citizens, Vault ]
|
||||
|
||||
|
@ -7,7 +7,6 @@ en:
|
||||
ITEM_TYPE_MATERIAL: "material"
|
||||
RAW_VALUE: "Raw value: {rawValue}"
|
||||
NO_NPC_SELECTED: "You must select an NPC before running this command"
|
||||
DEFAULT_REFORGE_ABLE_ITEMS_UNCHANGEABLE: "Changing reforge-able items globally will make every new blacksmith unable to reforge anything not in the list, unless it's changed for the individual NPC. If you really want to change this, change it manually."
|
||||
INPUT_STRING_LIST_REQUIRED: "A string list is required!"
|
||||
INPUT_PERCENTAGE_REQUIRED: "You specified a value which isn't between 0 and 100!"
|
||||
INPUT_STRING_REQUIRED: "A non-empty string is required!"
|
||||
@ -18,13 +17,25 @@ en:
|
||||
INVALID_FILTER_FOR_PRESET: "The specified filter is not valid for that preset"
|
||||
INVALID_PRESET_OR_FILTER: "You specified an invalid preset or an invalid filter"
|
||||
PRESET_MATERIALS: "Materials in preset: {materials}"
|
||||
DURATION_FORMAT: "{time} {unit}"
|
||||
DURATION_FORMAT: "in {time} {unit}"
|
||||
UNIT_NOW: "imminently"
|
||||
UNIT_SECOND: "second"
|
||||
UNIT_SECONDS: "seconds"
|
||||
UNIT_MINUTE: "minute"
|
||||
UNIT_MINUTES: "minutes"
|
||||
INTERVAL_LESS_THAN_10_SECONDS: "momentarily"
|
||||
UNIT_HOUR: "hour"
|
||||
UNIT_HOURS: "hours"
|
||||
UNIT_DAY: "day"
|
||||
UNIT_DAYS: "days"
|
||||
UNIT_WEEK: "week"
|
||||
UNIT_WEEKS: "weeks"
|
||||
UNIT_MONTH: "month"
|
||||
UNIT_MONTHS: "months"
|
||||
UNIT_YEAR: "year"
|
||||
UNIT_YEARS: "years"
|
||||
UNIT_DECADE: "decade"
|
||||
UNIT_DECADES: "decades"
|
||||
INTERVAL_LESS_THAN_10_SECONDS: "in just a moment"
|
||||
INTERVAL_LESS_THAN_30_SECONDS: "in a little while"
|
||||
INTERVAL_LESS_THAN_1_MINUTE: "in a while"
|
||||
INTERVAL_LESS_THAN_5_MINUTES: "after some time"
|
||||
|
Reference in New Issue
Block a user