mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-23 16:16:17 +02:00
Compare commits
30 commits
v1.x.x
...
v1.10.0-be
| Author | SHA1 | Date | |
|---|---|---|---|
| 0dfe0933ca | |||
| 5c17cefd53 | |||
| 85260fcb50 | |||
| 2c0623cd3e | |||
| 064f446d68 | |||
| 8d0d34ae77 | |||
| ffd3baa886 | |||
| c1b252520e | |||
| 736b41f77d | |||
| 0c0df6b856 | |||
| 6958bd0aff | |||
| 15f82abf79 | |||
| c71dfb490e | |||
| d61ef6c0d6 | |||
| 87dd099fca | |||
| 5d4ec394dd | |||
| 079b7bec57 | |||
| 074313fb7c | |||
| 5f3eed08e2 | |||
| 53173bcd33 | |||
| 44f49d7ae6 | |||
| 050d7cb79f | |||
| 32a4f6caf4 | |||
| bc531175b2 | |||
| 00efd7e4e4 | |||
| ea59081ca8 | |||
| 1b39707500 | |||
| 2a1cade9f1 | |||
| 11cd5d1842 | |||
| a0fe84a9d4 |
29 changed files with 2506 additions and 236 deletions
13
README.md
13
README.md
|
|
@ -38,9 +38,16 @@ ca.bypass.fuse: Allow player to combine every enchantments to every item (no cus
|
||||||
ca.bypass.level: Allow player to bypass every level limit (no custom limit)
|
ca.bypass.level: Allow player to bypass every level limit (no custom limit)
|
||||||
ca.command.reload: Allow administrator to reload the plugin's configs
|
ca.command.reload: Allow administrator to reload the plugin's configs
|
||||||
ca.config.edit: Allow administrator to edit the plugin's config in game
|
ca.config.edit: Allow administrator to edit the plugin's config in game
|
||||||
# Related to use of color (usage of permission for color is toggleable in basic config gui or config.yml)
|
# Bellow permissions also require some config change to allow usage of features
|
||||||
ca.color.code: Allow player to use color code if permission is required (toggleable)
|
# usage of these permission is toggleable in basic config gui or config.yml
|
||||||
ca.color.hex: Allow player to use hexadecimal color if permission is required (toggleable)
|
|
||||||
|
# Permissions related to use of color
|
||||||
|
ca.color.code: Allow player to use color code if enabled (toggleable)
|
||||||
|
ca.color.hex: Allow player to use hexadecimal color if enabled (toggleable)
|
||||||
|
|
||||||
|
# Permissions related to edition of the lore
|
||||||
|
ca.lore_edit.book: Allow player to edit lore via book and quil if enabled (toggleable)
|
||||||
|
ca.lore_edit.paper: Allow player to edit lore via paper if enabled (toggleable)
|
||||||
```
|
```
|
||||||
|
|
||||||
### Commands
|
### Commands
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ plugins {
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "xyz.alexcrea"
|
group = "xyz.alexcrea"
|
||||||
version = "1.9.0"
|
version = "1.10.0-beta.1"
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// EcoEnchants
|
// EcoEnchants
|
||||||
|
|
@ -72,7 +72,7 @@ dependencies {
|
||||||
implementation(kotlin("stdlib"))
|
implementation(kotlin("stdlib"))
|
||||||
|
|
||||||
// Test dependency
|
// Test dependency
|
||||||
testImplementation("org.mockbukkit.mockbukkit:mockbukkit-v1.21:4.21.0")
|
testImplementation("org.mockbukkit.mockbukkit:mockbukkit-v1.21:4.37.0")
|
||||||
testRuntimeOnly("commons-lang:commons-lang:2.6")
|
testRuntimeOnly("commons-lang:commons-lang:2.6")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -270,6 +270,91 @@ disable-merge-over:
|
||||||
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
||||||
#minecraft:unbreaking: 2
|
#minecraft:unbreaking: 2
|
||||||
|
|
||||||
|
# Settings for lore modification
|
||||||
|
lore_edit:
|
||||||
|
book_and_quil:
|
||||||
|
# Permission is ca.lore_edit.book
|
||||||
|
use_permission: true
|
||||||
|
append:
|
||||||
|
# If adding lore using book & quil is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Cost used for every lore line added
|
||||||
|
per_line_cost: 0
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If adding the lore consume the book & quil
|
||||||
|
do_consume: false
|
||||||
|
# Allow using color code and hexadecimal color when editing lore via book & quil
|
||||||
|
#
|
||||||
|
# Color code are prefixed by "&" and hexadecimal color by "#"
|
||||||
|
# Color code will not be applied if it colors nothing. "&&" can be used to write "&"
|
||||||
|
allow_color_code: true
|
||||||
|
allow_hexadecimal_color: true
|
||||||
|
use_cost: 0
|
||||||
|
|
||||||
|
remove:
|
||||||
|
# If removing lore using book & quil is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Cost used for every lore line removed
|
||||||
|
per_line_cost: 0
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If removing the lore consume the book & quil
|
||||||
|
do_consume: false
|
||||||
|
# If the color should get back to color code or hex format
|
||||||
|
remove_color_on_remove: true
|
||||||
|
# Cost of replacing colors
|
||||||
|
remove_color_cost: 0
|
||||||
|
|
||||||
|
paper:
|
||||||
|
# Permission is ca.lore_edit.paper
|
||||||
|
use_permission: true
|
||||||
|
# what order should the lines should get added/removed (start/end, if invalid or not present will be end)
|
||||||
|
order: "end"
|
||||||
|
|
||||||
|
append_line:
|
||||||
|
# If adding lore line using paper is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If adding the lore line consume the paper
|
||||||
|
do_consume: false
|
||||||
|
# Allow using color code and hexadecimal color when editing lore via book & quil
|
||||||
|
#
|
||||||
|
# Color code are prefixed by "&" and hexadecimal color by "#"
|
||||||
|
# Color code will not be applied if it colors nothing. "&&" can be used to write "&"
|
||||||
|
allow_color_code: true
|
||||||
|
allow_hexadecimal_color: true
|
||||||
|
color_use_cost: 0
|
||||||
|
|
||||||
|
remove_line:
|
||||||
|
# If removing lore line using paper is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If removing the lore line consume the paper
|
||||||
|
do_consume: false
|
||||||
|
# If the color should get back to color code or hex format
|
||||||
|
remove_color_on_remove: true
|
||||||
|
# Cost of replacing colors
|
||||||
|
remove_color_cost: 0
|
||||||
|
|
||||||
# Whether to show debug logging
|
# Whether to show debug logging
|
||||||
debug_log: false
|
debug_log: false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -270,6 +270,91 @@ disable-merge-over:
|
||||||
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
||||||
#minecraft:unbreaking: 2
|
#minecraft:unbreaking: 2
|
||||||
|
|
||||||
|
# Settings for lore modification
|
||||||
|
lore_edit:
|
||||||
|
book_and_quil:
|
||||||
|
# Permission is ca.lore_edit.book
|
||||||
|
use_permission: true
|
||||||
|
append:
|
||||||
|
# If adding lore using book & quil is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Cost used for every lore line added
|
||||||
|
per_line_cost: 0
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If adding the lore consume the book & quil
|
||||||
|
do_consume: false
|
||||||
|
# Allow using color code and hexadecimal color when editing lore via book & quil
|
||||||
|
#
|
||||||
|
# Color code are prefixed by "&" and hexadecimal color by "#"
|
||||||
|
# Color code will not be applied if it colors nothing. "&&" can be used to write "&"
|
||||||
|
allow_color_code: true
|
||||||
|
allow_hexadecimal_color: true
|
||||||
|
use_cost: 0
|
||||||
|
|
||||||
|
remove:
|
||||||
|
# If removing lore using book & quil is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Cost used for every lore line removed
|
||||||
|
per_line_cost: 0
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If removing the lore consume the book & quil
|
||||||
|
do_consume: false
|
||||||
|
# If the color should get back to color code or hex format
|
||||||
|
remove_color_on_remove: true
|
||||||
|
# Cost of replacing colors
|
||||||
|
remove_color_cost: 0
|
||||||
|
|
||||||
|
paper:
|
||||||
|
# Permission is ca.lore_edit.paper
|
||||||
|
use_permission: true
|
||||||
|
# what order should the lines should get added/removed (start/end, if invalid or not present will be end)
|
||||||
|
order: "end"
|
||||||
|
|
||||||
|
append_line:
|
||||||
|
# If adding lore line using paper is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If adding the lore line consume the paper
|
||||||
|
do_consume: false
|
||||||
|
# Allow using color code and hexadecimal color when editing lore via book & quil
|
||||||
|
#
|
||||||
|
# Color code are prefixed by "&" and hexadecimal color by "#"
|
||||||
|
# Color code will not be applied if it colors nothing. "&&" can be used to write "&"
|
||||||
|
allow_color_code: true
|
||||||
|
allow_hexadecimal_color: true
|
||||||
|
color_use_cost: 0
|
||||||
|
|
||||||
|
remove_line:
|
||||||
|
# If removing lore line using paper is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If removing the lore line consume the paper
|
||||||
|
do_consume: false
|
||||||
|
# If the color should get back to color code or hex format
|
||||||
|
remove_color_on_remove: true
|
||||||
|
# Cost of replacing colors
|
||||||
|
remove_color_cost: 0
|
||||||
|
|
||||||
# Whether to show debug logging
|
# Whether to show debug logging
|
||||||
debug_log: false
|
debug_log: false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
|
||||||
this.currentType = ConfigOptions.INSTANCE.getWorkPenaltyType();
|
this.currentType = ConfigOptions.INSTANCE.getWorkPenaltyType();
|
||||||
this.items = new EnumMap<>(this.currentType.getPartMap());
|
this.items = new EnumMap<>(this.currentType.getPartMap());
|
||||||
|
|
||||||
for (AnvilUseType type : AnvilUseType.getEntries()) {
|
for (AnvilUseType type : useTypes.keySet()) {
|
||||||
updateGuiForType(type);
|
updateGuiForType(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -80,6 +80,14 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
|
||||||
}, CustomAnvil.instance);
|
}, CustomAnvil.instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Map<AnvilUseType, String> useTypes =
|
||||||
|
Map.of(
|
||||||
|
AnvilUseType.RENAME_ONLY, "a1z9Z",
|
||||||
|
AnvilUseType.MERGE, "b2y8Y",
|
||||||
|
AnvilUseType.UNIT_REPAIR, "c3x7X",
|
||||||
|
AnvilUseType.CUSTOM_CRAFT, "d4w6W"
|
||||||
|
);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Pattern getGuiPattern() {
|
protected Pattern getGuiPattern() {
|
||||||
return new Pattern( // Yeah that a mess
|
return new Pattern( // Yeah that a mess
|
||||||
|
|
@ -92,13 +100,14 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
|
||||||
|
|
||||||
public void updateGuiForType(AnvilUseType type) {
|
public void updateGuiForType(AnvilUseType type) {
|
||||||
PatternPane pane = getPane();
|
PatternPane pane = getPane();
|
||||||
int ordinal = type.ordinal();
|
|
||||||
|
|
||||||
int display = 'z' - ordinal;
|
String typeVals = useTypes.get(type);
|
||||||
int increment = 'a' + ordinal;
|
|
||||||
int additive = '1' + ordinal;
|
char increment = typeVals.charAt(0);
|
||||||
int exclusiveIncrement = 'Z' - ordinal;
|
char additive = typeVals.charAt(1);
|
||||||
int exclusiveAdditive = '9' - ordinal;
|
char display = typeVals.charAt(2);
|
||||||
|
char exclusiveIncrement = typeVals.charAt(3);
|
||||||
|
char exclusiveAdditive = typeVals.charAt(4);
|
||||||
|
|
||||||
WorkPenaltyType.WorkPenaltyPart part = items.get(type);
|
WorkPenaltyType.WorkPenaltyPart part = items.get(type);
|
||||||
String increasingStr = (part.penaltyIncrease() ? "§a" : "§c") + "Increasing";
|
String increasingStr = (part.penaltyIncrease() ? "§a" : "§c") + "Increasing";
|
||||||
|
|
@ -210,12 +219,11 @@ public class WorkPenaltyTypeSettingGui extends AbstractSettingGui {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean saveWorkPenalty(Map<AnvilUseType, WorkPenaltyType.WorkPenaltyPart> partEnum) {
|
public static boolean saveWorkPenalty(Map<AnvilUseType, WorkPenaltyType.WorkPenaltyPart> partEnum) {
|
||||||
String path = ConfigOptions.WORK_PENALTY_ROOT;
|
|
||||||
ConfigHolder configHolder = ConfigHolder.DEFAULT_CONFIG;
|
ConfigHolder configHolder = ConfigHolder.DEFAULT_CONFIG;
|
||||||
FileConfiguration config = configHolder.getConfig();
|
FileConfiguration config = configHolder.getConfig();
|
||||||
|
|
||||||
partEnum.forEach((key, value) -> {
|
partEnum.forEach((key, value) -> {
|
||||||
String partPath = path + "." + key.getTypeName();
|
String partPath = key.getPath();
|
||||||
|
|
||||||
if (key.getDefaultPenalty().equals(value)) {
|
if (key.getDefaultPenalty().equals(value)) {
|
||||||
config.set(partPath, null);
|
config.set(partPath, null);
|
||||||
|
|
|
||||||
|
|
@ -5,51 +5,82 @@ import io.delilaheve.util.ConfigOptions;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil;
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditType;
|
||||||
|
|
||||||
|
import static io.delilaheve.util.ConfigOptions.*;
|
||||||
|
import static xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.*;
|
||||||
|
|
||||||
public class PluginSetDefault {
|
public class PluginSetDefault {
|
||||||
|
|
||||||
public static void reAddMissingDefault(){
|
public static void reAddMissingDefault() {
|
||||||
FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig();
|
FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig();
|
||||||
|
|
||||||
int nbSet = 0;
|
int nbSet = 0;
|
||||||
|
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.CAP_ANVIL_COST, ConfigOptions.DEFAULT_CAP_ANVIL_COST);
|
nbSet += trySetDefault(config, CAP_ANVIL_COST, DEFAULT_CAP_ANVIL_COST);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.MAX_ANVIL_COST, ConfigOptions.DEFAULT_MAX_ANVIL_COST);
|
nbSet += trySetDefault(config, MAX_ANVIL_COST, DEFAULT_MAX_ANVIL_COST);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.REMOVE_ANVIL_COST_LIMIT, ConfigOptions.DEFAULT_REMOVE_ANVIL_COST_LIMIT);
|
nbSet += trySetDefault(config, REMOVE_ANVIL_COST_LIMIT, DEFAULT_REMOVE_ANVIL_COST_LIMIT);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.REPLACE_TOO_EXPENSIVE, ConfigOptions.DEFAULT_REPLACE_TOO_EXPENSIVE);
|
nbSet += trySetDefault(config, REPLACE_TOO_EXPENSIVE, DEFAULT_REPLACE_TOO_EXPENSIVE);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.ITEM_REPAIR_COST, ConfigOptions.DEFAULT_ITEM_REPAIR_COST);
|
nbSet += trySetDefault(config, ITEM_REPAIR_COST, DEFAULT_ITEM_REPAIR_COST);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.UNIT_REPAIR_COST, ConfigOptions.DEFAULT_UNIT_REPAIR_COST);
|
nbSet += trySetDefault(config, UNIT_REPAIR_COST, DEFAULT_UNIT_REPAIR_COST);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.ITEM_RENAME_COST, ConfigOptions.DEFAULT_ITEM_RENAME_COST);
|
nbSet += trySetDefault(config, ITEM_RENAME_COST, DEFAULT_ITEM_RENAME_COST);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.SACRIFICE_ILLEGAL_COST, ConfigOptions.DEFAULT_SACRIFICE_ILLEGAL_COST);
|
nbSet += trySetDefault(config, SACRIFICE_ILLEGAL_COST, DEFAULT_SACRIFICE_ILLEGAL_COST);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.ALLOW_COLOR_CODE, ConfigOptions.DEFAULT_ALLOW_COLOR_CODE);
|
nbSet += trySetDefault(config, ConfigOptions.ALLOW_COLOR_CODE, ConfigOptions.DEFAULT_ALLOW_COLOR_CODE);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.ALLOW_HEXADECIMAL_COLOR, ConfigOptions.DEFAULT_ALLOW_HEXADECIMAL_COLOR);
|
nbSet += trySetDefault(config, ALLOW_HEXADECIMAL_COLOR, DEFAULT_ALLOW_HEXADECIMAL_COLOR);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.PERMISSION_NEEDED_FOR_COLOR, ConfigOptions.DEFAULT_PERMISSION_NEEDED_FOR_COLOR);
|
nbSet += trySetDefault(config, PERMISSION_NEEDED_FOR_COLOR, DEFAULT_PERMISSION_NEEDED_FOR_COLOR);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.USE_OF_COLOR_COST, ConfigOptions.DEFAULT_USE_OF_COLOR_COST);
|
nbSet += trySetDefault(config, USE_OF_COLOR_COST, DEFAULT_USE_OF_COLOR_COST);
|
||||||
nbSet+= trySetDefault(config, ConfigOptions.DEFAULT_LIMIT_PATH, ConfigOptions.DEFAULT_ENCHANT_LIMIT);
|
nbSet += trySetDefault(config, DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT);
|
||||||
|
|
||||||
if(nbSet > 0){
|
// Lore Edit defaults
|
||||||
|
for (@NotNull LoreEditType value : LoreEditType.values()) {
|
||||||
|
String path = value.getRootPath() + ".";
|
||||||
|
|
||||||
|
nbSet += trySetDefault(config, path + IS_ENABLED, DEFAULT_IS_ENABLED);
|
||||||
|
nbSet += trySetDefault(config, path + FIXED_COST, DEFAULT_FIXED_COST);
|
||||||
|
|
||||||
|
nbSet += trySetDefault(config, path + DO_CONSUME, DEFAULT_DO_CONSUME);
|
||||||
|
if (value.isMultiLine()) {
|
||||||
|
nbSet += trySetDefault(config, path + PER_LINE_COST, DEFAULT_PER_LINE_COST);
|
||||||
|
}
|
||||||
|
if (value.isAppend()) {
|
||||||
|
nbSet += trySetDefault(config, path + LoreEditConfigUtil.ALLOW_COLOR_CODE, LoreEditConfigUtil.DEFAULT_ALLOW_COLOR_CODE);
|
||||||
|
nbSet += trySetDefault(config, path + ALLOW_HEX_COLOR, DEFAULT_ALLOW_HEX_COLOR);
|
||||||
|
nbSet += trySetDefault(config, path + USE_COLOR_COST, DEFAULT_USE_COLOR_COST);
|
||||||
|
} else {
|
||||||
|
nbSet += trySetDefault(config, path + REMOVE_COLOR_ON_LORE_REMOVE, DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE);
|
||||||
|
nbSet += trySetDefault(config, path + REMOVE_COLOR_COST, DEFAULT_REMOVE_COLOR_COST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nbSet += trySetDefault(config, BOOK_PERMISSION_NEEDED, DEFAULT_BOOK_PERMISSION_NEEDED);
|
||||||
|
nbSet += trySetDefault(config, PAPER_PERMISSION_NEEDED, DEFAULT_PAPER_PERMISSION_NEEDED);
|
||||||
|
|
||||||
|
nbSet += trySetDefault(config, PAPER_EDIT_ORDER, DEFAULT_PAPER_EDIT_ORDER);
|
||||||
|
|
||||||
|
if (nbSet > 0) {
|
||||||
CustomAnvil.instance.getLogger().info("Adding " + nbSet + " absent default config values.");
|
CustomAnvil.instance.getLogger().info("Adding " + nbSet + " absent default config values.");
|
||||||
ConfigHolder.DEFAULT_CONFIG.saveToDisk(true);
|
ConfigHolder.DEFAULT_CONFIG.saveToDisk(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, @NotNull String value){
|
private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, @NotNull String value) {
|
||||||
if(config.isSet(path)) return 0;
|
if (config.isSet(path)) return 0;
|
||||||
|
|
||||||
config.set(path, value);
|
config.set(path, value);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, int value){
|
private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, int value) {
|
||||||
if(config.isSet(path)) return 0;
|
if (config.isSet(path)) return 0;
|
||||||
|
|
||||||
config.set(path, value);
|
config.set(path, value);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, boolean value){
|
private static int trySetDefault(@NotNull FileConfiguration config, @NotNull String path, boolean value) {
|
||||||
if(config.isSet(path)) return 0;
|
if (config.isSet(path)) return 0;
|
||||||
|
|
||||||
config.set(path, value);
|
config.set(path, value);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import xyz.alexcrea.cuanvil.config.WorkPenaltyType
|
||||||
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
|
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
|
||||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
|
import xyz.alexcrea.cuanvil.enchant.CAEnchantment
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilUseType
|
import xyz.alexcrea.cuanvil.util.AnvilUseType
|
||||||
import java.util.EnumMap
|
import java.util.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config option accessors
|
* Config option accessors
|
||||||
|
|
@ -37,6 +37,7 @@ object ConfigOptions {
|
||||||
const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color"
|
const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color"
|
||||||
const val USE_OF_COLOR_COST = "use_of_color_cost"
|
const val USE_OF_COLOR_COST = "use_of_color_cost"
|
||||||
|
|
||||||
|
// Work penalty config
|
||||||
const val WORK_PENALTY_ROOT = "work_penalty"
|
const val WORK_PENALTY_ROOT = "work_penalty"
|
||||||
const val WORK_PENALTY_INCREASE = "shared_increase"
|
const val WORK_PENALTY_INCREASE = "shared_increase"
|
||||||
const val WORK_PENALTY_ADDITIVE = "shared_additive"
|
const val WORK_PENALTY_ADDITIVE = "shared_additive"
|
||||||
|
|
@ -115,6 +116,9 @@ object ConfigOptions {
|
||||||
@JvmField
|
@JvmField
|
||||||
val ENCHANT_LIMIT_RANGE = 1..255
|
val ENCHANT_LIMIT_RANGE = 1..255
|
||||||
|
|
||||||
|
// --------------
|
||||||
|
// Other defaults
|
||||||
|
// --------------
|
||||||
|
|
||||||
// Default value for an enchantment multiplier
|
// Default value for an enchantment multiplier
|
||||||
private const val DEFAULT_ENCHANT_VALUE = 0
|
private const val DEFAULT_ENCHANT_VALUE = 0
|
||||||
|
|
@ -239,7 +243,10 @@ object ConfigOptions {
|
||||||
/**
|
/**
|
||||||
* If one of the color component is enabled
|
* If one of the color component is enabled
|
||||||
*/
|
*/
|
||||||
val renameColorPossible: Boolean get() { return allowColorCode || allowHexadecimalColor }
|
val renameColorPossible: Boolean
|
||||||
|
get() {
|
||||||
|
return allowColorCode || allowHexadecimalColor
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If players need a permission to use color
|
* If players need a permission to use color
|
||||||
|
|
@ -282,16 +289,17 @@ object ConfigOptions {
|
||||||
*/
|
*/
|
||||||
fun workPenaltyPart(type: AnvilUseType): WorkPenaltyPart {
|
fun workPenaltyPart(type: AnvilUseType): WorkPenaltyPart {
|
||||||
val config = ConfigHolder.DEFAULT_CONFIG.config
|
val config = ConfigHolder.DEFAULT_CONFIG.config
|
||||||
val path = WORK_PENALTY_ROOT + "." + type.typeName
|
|
||||||
|
|
||||||
// Find values
|
// Find values
|
||||||
val defaultPenalty = type.defaultPenalty
|
val defaultPenalty = type.defaultPenalty
|
||||||
val section = config.getConfigurationSection(path) ?: return defaultPenalty
|
val section = config.getConfigurationSection(type.path) ?: return defaultPenalty
|
||||||
|
|
||||||
val penaltyIncrease = section.getBoolean(WORK_PENALTY_INCREASE, defaultPenalty.penaltyIncrease)
|
val penaltyIncrease = section.getBoolean(WORK_PENALTY_INCREASE, defaultPenalty.penaltyIncrease)
|
||||||
val penaltyAdditive = section.getBoolean(WORK_PENALTY_ADDITIVE, defaultPenalty.penaltyAdditive)
|
val penaltyAdditive = section.getBoolean(WORK_PENALTY_ADDITIVE, defaultPenalty.penaltyAdditive)
|
||||||
val exclusivePenaltyIncrease = section.getBoolean(EXCLUSIVE_WORK_PENALTY_INCREASE, defaultPenalty.exclusivePenaltyIncrease)
|
val exclusivePenaltyIncrease =
|
||||||
val exclusivePenaltyAdditive = section.getBoolean(EXCLUSIVE_WORK_PENALTY_ADDITIVE, defaultPenalty.exclusivePenaltyAdditive)
|
section.getBoolean(EXCLUSIVE_WORK_PENALTY_INCREASE, defaultPenalty.exclusivePenaltyIncrease)
|
||||||
|
val exclusivePenaltyAdditive =
|
||||||
|
section.getBoolean(EXCLUSIVE_WORK_PENALTY_ADDITIVE, defaultPenalty.exclusivePenaltyAdditive)
|
||||||
|
|
||||||
return WorkPenaltyPart(penaltyIncrease, penaltyAdditive, exclusivePenaltyIncrease, exclusivePenaltyAdditive)
|
return WorkPenaltyPart(penaltyIncrease, penaltyAdditive, exclusivePenaltyIncrease, exclusivePenaltyAdditive)
|
||||||
}
|
}
|
||||||
|
|
@ -332,11 +340,11 @@ object ConfigOptions {
|
||||||
fun enchantLimit(enchantment: CAEnchantment): Int {
|
fun enchantLimit(enchantment: CAEnchantment): Int {
|
||||||
// Test namespace
|
// Test namespace
|
||||||
var limit = enchantLimit(enchantment.key.toString())
|
var limit = enchantLimit(enchantment.key.toString())
|
||||||
if(limit != null) return limit
|
if (limit != null) return limit
|
||||||
|
|
||||||
// Test legacy (name only)
|
// Test legacy (name only)
|
||||||
limit = enchantLimit(enchantment.enchantmentName)
|
limit = enchantLimit(enchantment.enchantmentName)
|
||||||
if(limit != null) return limit
|
if (limit != null) return limit
|
||||||
|
|
||||||
// get default (and test old legacy if present)
|
// get default (and test old legacy if present)
|
||||||
return getDefaultLevel(enchantment.enchantmentName)
|
return getDefaultLevel(enchantment.enchantmentName)
|
||||||
|
|
@ -350,18 +358,19 @@ object ConfigOptions {
|
||||||
val path = "${ENCHANT_LIMIT_ROOT}.$enchantmentName"
|
val path = "${ENCHANT_LIMIT_ROOT}.$enchantmentName"
|
||||||
return CustomAnvil.instance
|
return CustomAnvil.instance
|
||||||
.config
|
.config
|
||||||
.getInt(path, ENCHANT_LIMIT_RANGE.first-1)
|
.getInt(path, ENCHANT_LIMIT_RANGE.first - 1)
|
||||||
.takeIf { it in ENCHANT_LIMIT_RANGE }
|
.takeIf { it in ENCHANT_LIMIT_RANGE }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get default value if enchantment do not exist on config
|
* Get default value if enchantment do not exist on config
|
||||||
*/
|
*/
|
||||||
private fun getDefaultLevel(enchantmentName: String, // compatibility with 1.20.5. TODO better update system
|
private fun getDefaultLevel(
|
||||||
) : Int {
|
enchantmentName: String, // compatibility with 1.20.5. TODO better update system
|
||||||
if(enchantmentName == "sweeping_edge"){
|
): Int {
|
||||||
val limit = enchantLimit("sweeping")
|
if (enchantmentName == "sweeping_edge") {
|
||||||
if(limit != null) return limit
|
val limit = enchantLimit("sweeping")
|
||||||
|
if (limit != null) return limit
|
||||||
|
|
||||||
}
|
}
|
||||||
return defaultEnchantLimit
|
return defaultEnchantLimit
|
||||||
|
|
@ -377,11 +386,11 @@ object ConfigOptions {
|
||||||
): Int {
|
): Int {
|
||||||
// Test namespace
|
// Test namespace
|
||||||
var limit = enchantmentValue(enchantment.key.toString(), isFromBook)
|
var limit = enchantmentValue(enchantment.key.toString(), isFromBook)
|
||||||
if(limit != null) return limit
|
if (limit != null) return limit
|
||||||
|
|
||||||
// Test legacy (name only)
|
// Test legacy (name only)
|
||||||
limit = enchantmentValue(enchantment.enchantmentName, isFromBook)
|
limit = enchantmentValue(enchantment.enchantmentName, isFromBook)
|
||||||
if(limit != null) return limit
|
if (limit != null) return limit
|
||||||
|
|
||||||
// get default (and test old legacy if present)
|
// get default (and test old legacy if present)
|
||||||
return getDefaultValue(enchantment, isFromBook)
|
return getDefaultValue(enchantment, isFromBook)
|
||||||
|
|
@ -407,21 +416,23 @@ object ConfigOptions {
|
||||||
/**
|
/**
|
||||||
* Get default value if enchantment do not exist on config
|
* Get default value if enchantment do not exist on config
|
||||||
*/
|
*/
|
||||||
private fun getDefaultValue(enchantment: CAEnchantment, // compatibility with 1.20.5. TODO better update system
|
private fun getDefaultValue(
|
||||||
isFromBook: Boolean) : Int {
|
enchantment: CAEnchantment, // compatibility with 1.20.5. TODO better update system
|
||||||
|
isFromBook: Boolean
|
||||||
|
): Int {
|
||||||
|
|
||||||
val enchantmentName = enchantment.key.toString()
|
val enchantmentName = enchantment.key.toString()
|
||||||
if(enchantmentName == "minecraft:sweeping_edge"){
|
if (enchantmentName == "minecraft:sweeping_edge") {
|
||||||
var limit = enchantmentValue("minecraft:sweeping", isFromBook)
|
var limit = enchantmentValue("minecraft:sweeping", isFromBook)
|
||||||
if(limit != null) return limit
|
if (limit != null) return limit
|
||||||
|
|
||||||
// legacy name
|
// legacy name
|
||||||
limit = enchantmentValue("sweeping", isFromBook)
|
limit = enchantmentValue("sweeping", isFromBook)
|
||||||
if(limit != null) return limit
|
if (limit != null) return limit
|
||||||
}
|
}
|
||||||
|
|
||||||
val rarity = enchantment.defaultRarity()
|
val rarity = enchantment.defaultRarity()
|
||||||
return if(isFromBook)
|
return if (isFromBook)
|
||||||
rarity.bookValue
|
rarity.bookValue
|
||||||
else
|
else
|
||||||
rarity.itemValue
|
rarity.itemValue
|
||||||
|
|
@ -434,20 +445,20 @@ object ConfigOptions {
|
||||||
fun maxBeforeMergeDisabled(enchantment: CAEnchantment): Int {
|
fun maxBeforeMergeDisabled(enchantment: CAEnchantment): Int {
|
||||||
val key = enchantment.key.toString()
|
val key = enchantment.key.toString()
|
||||||
var value = maxBeforeMergeDisabled(key)
|
var value = maxBeforeMergeDisabled(key)
|
||||||
if(value != null) return value
|
if (value != null) return value
|
||||||
|
|
||||||
// Legacy name
|
// Legacy name
|
||||||
val legacy = enchantment.enchantmentName
|
val legacy = enchantment.enchantmentName
|
||||||
value = maxBeforeMergeDisabled(legacy)
|
value = maxBeforeMergeDisabled(legacy)
|
||||||
if(value != null) return value
|
if (value != null) return value
|
||||||
|
|
||||||
if(key == "minecraft:sweeping_edge"){
|
if (key == "minecraft:sweeping_edge") {
|
||||||
value = maxBeforeMergeDisabled("minecraft:sweeping")
|
value = maxBeforeMergeDisabled("minecraft:sweeping")
|
||||||
if(value != null) return value
|
if (value != null) return value
|
||||||
|
|
||||||
// legacy name of legacy enchantment name
|
// legacy name of legacy enchantment name
|
||||||
value = maxBeforeMergeDisabled("sweeping")
|
value = maxBeforeMergeDisabled("sweeping")
|
||||||
if(value != null) return value
|
if (value != null) return value
|
||||||
}
|
}
|
||||||
|
|
||||||
return DEFAULT_MAX_BEFORE_MERGE_DISABLED
|
return DEFAULT_MAX_BEFORE_MERGE_DISABLED
|
||||||
|
|
@ -457,7 +468,7 @@ object ConfigOptions {
|
||||||
* Get the given [enchantmentName]'s level before merge is disabled
|
* Get the given [enchantmentName]'s level before merge is disabled
|
||||||
* a negative value would mean never disabled
|
* a negative value would mean never disabled
|
||||||
*/
|
*/
|
||||||
private fun maxBeforeMergeDisabled(enchantmentName: String) : Int? {
|
private fun maxBeforeMergeDisabled(enchantmentName: String): Int? {
|
||||||
// find if set
|
// find if set
|
||||||
val path = "${DISABLE_MERGE_OVER_ROOT}.$enchantmentName"
|
val path = "${DISABLE_MERGE_OVER_ROOT}.$enchantmentName"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import io.delilaheve.util.ItemUtil.canMergeWith
|
||||||
import io.delilaheve.util.ItemUtil.unitRepair
|
import io.delilaheve.util.ItemUtil.unitRepair
|
||||||
import org.bukkit.GameMode
|
import org.bukkit.GameMode
|
||||||
import org.bukkit.Material
|
import org.bukkit.Material
|
||||||
|
import org.bukkit.entity.HumanEntity
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.event.Event
|
import org.bukkit.event.Event
|
||||||
import org.bukkit.event.EventHandler
|
import org.bukkit.event.EventHandler
|
||||||
|
|
@ -15,18 +16,25 @@ import org.bukkit.event.inventory.InventoryClickEvent
|
||||||
import org.bukkit.inventory.AnvilInventory
|
import org.bukkit.inventory.AnvilInventory
|
||||||
import org.bukkit.inventory.InventoryView
|
import org.bukkit.inventory.InventoryView
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.meta.BookMeta
|
||||||
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||||
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT
|
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT
|
||||||
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_RIGHT
|
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_RIGHT
|
||||||
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT
|
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT
|
||||||
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
|
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
|
||||||
|
import xyz.alexcrea.cuanvil.util.AnvilLoreEditUtil
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilUseType
|
import xyz.alexcrea.cuanvil.util.AnvilUseType
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil
|
import xyz.alexcrea.cuanvil.util.AnvilXpUtil
|
||||||
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
|
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
|
||||||
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditType
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class AnvilResultListener: Listener {
|
class AnvilResultListener : Listener {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// static slot container
|
// static slot container
|
||||||
|
|
@ -48,67 +56,80 @@ class AnvilResultListener: Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if the event should bypass custom anvil.
|
// Test if the event should bypass custom anvil.
|
||||||
if(DependencyManager.tryClickAnvilResultBypass(event, inventory)) return
|
if (DependencyManager.tryClickAnvilResultBypass(event, inventory)) return
|
||||||
|
|
||||||
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
|
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
|
||||||
val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||||
val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT)
|
val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT)
|
||||||
|
|
||||||
if(GameMode.CREATIVE != player.gameMode && inventory.repairCost >= inventory.maximumRepairCost) {
|
if (GameMode.CREATIVE != player.gameMode && inventory.repairCost >= inventory.maximumRepairCost) {
|
||||||
event.result = Event.Result.DENY
|
event.result = Event.Result.DENY
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test custom recipe
|
// Test custom recipe
|
||||||
val recipe = CustomRecipeUtil.getCustomRecipe(leftItem, rightItem)
|
val recipe = CustomRecipeUtil.getCustomRecipe(leftItem, rightItem)
|
||||||
if(recipe != null){
|
if (recipe != null) {
|
||||||
event.result = Event.Result.ALLOW
|
event.result = Event.Result.ALLOW
|
||||||
onCustomCraft(
|
onCustomCraft(
|
||||||
event, recipe, player,
|
event, recipe, player,
|
||||||
leftItem, rightItem, output, inventory)
|
leftItem, rightItem, output, inventory
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val canMerge = leftItem.canMergeWith(rightItem)
|
// Do not continue if there was no change
|
||||||
val unitRepairResult = leftItem.getRepair(rightItem)
|
if ((output == inventory.getItem(ANVIL_INPUT_LEFT))) {
|
||||||
val allowed = (rightItem == null)
|
|
||||||
|| (canMerge)
|
|
||||||
|| (unitRepairResult != null)
|
|
||||||
|
|
||||||
// True if there was no change or not allowed
|
|
||||||
if ((output == inventory.getItem(ANVIL_INPUT_LEFT))
|
|
||||||
|| !allowed
|
|
||||||
) {
|
|
||||||
event.result = Event.Result.DENY
|
event.result = Event.Result.DENY
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rename
|
||||||
if (rightItem == null) {
|
if (rightItem == null) {
|
||||||
event.result = Event.Result.ALLOW
|
event.result = Event.Result.ALLOW
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge
|
||||||
|
val canMerge = leftItem.canMergeWith(rightItem)
|
||||||
if (canMerge) {
|
if (canMerge) {
|
||||||
event.result = Event.Result.ALLOW
|
event.result = Event.Result.ALLOW
|
||||||
} else if (unitRepairResult != null) {
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unit repair
|
||||||
|
val unitRepairResult = leftItem.getRepair(rightItem)
|
||||||
|
if (unitRepairResult != null) {
|
||||||
onUnitRepairExtract(
|
onUnitRepairExtract(
|
||||||
leftItem, rightItem, output,
|
leftItem, rightItem, output,
|
||||||
unitRepairResult, event, player, inventory
|
unitRepairResult, event, player, inventory
|
||||||
)
|
)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// For lore edit
|
||||||
|
if (handleBookLoreEdit(event, inventory, player, leftItem, rightItem, output)) {
|
||||||
|
return
|
||||||
|
} else if (handlePaperLoreEdit(event, inventory, player, leftItem, rightItem, output)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else there was no working situation somehow so we deny
|
||||||
|
event.result = Event.Result.DENY
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun onCustomCraft(event: InventoryClickEvent,
|
private fun onCustomCraft(
|
||||||
recipe: AnvilCustomRecipe,
|
event: InventoryClickEvent,
|
||||||
player: Player,
|
recipe: AnvilCustomRecipe,
|
||||||
leftItem: ItemStack,
|
player: Player,
|
||||||
rightItem: ItemStack?,
|
leftItem: ItemStack,
|
||||||
output: ItemStack,
|
rightItem: ItemStack?,
|
||||||
inventory: AnvilInventory
|
output: ItemStack,
|
||||||
|
inventory: AnvilInventory
|
||||||
) {
|
) {
|
||||||
event.result = Event.Result.DENY
|
event.result = Event.Result.DENY
|
||||||
|
|
||||||
if(recipe.leftItem == null) return // in case it changed
|
if (recipe.leftItem == null) return // in case it changed
|
||||||
|
|
||||||
val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, leftItem, rightItem)
|
val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, leftItem, rightItem)
|
||||||
val xpCost = amount * recipe.xpCostPerCraft
|
val xpCost = amount * recipe.xpCostPerCraft
|
||||||
|
|
@ -123,7 +144,8 @@ class AnvilResultListener: Listener {
|
||||||
|
|
||||||
// Handle not creative middle click...
|
// Handle not creative middle click...
|
||||||
if (event.click != ClickType.MIDDLE &&
|
if (event.click != ClickType.MIDDLE &&
|
||||||
!handleCustomCraftClick(event, recipe, inventory, player, leftItem, rightItem, amount, xpCost)) return
|
!handleCustomCraftClick(event, recipe, inventory, player, leftItem, rightItem, amount, xpCost)
|
||||||
|
) return
|
||||||
|
|
||||||
// Finally, we add the item to the player
|
// Finally, we add the item to the player
|
||||||
if (slotDestination.type == SlotType.CURSOR) {
|
if (slotDestination.type == SlotType.CURSOR) {
|
||||||
|
|
@ -133,13 +155,15 @@ class AnvilResultListener: Listener {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleCustomCraftClick(event: InventoryClickEvent, recipe: AnvilCustomRecipe,
|
private fun handleCustomCraftClick(
|
||||||
inventory: AnvilInventory, player: Player,
|
event: InventoryClickEvent, recipe: AnvilCustomRecipe,
|
||||||
leftItem: ItemStack, rightItem: ItemStack?,
|
inventory: AnvilInventory, player: Player,
|
||||||
amount: Int, xpCost: Int): Boolean {
|
leftItem: ItemStack, rightItem: ItemStack?,
|
||||||
|
amount: Int, xpCost: Int
|
||||||
|
): Boolean {
|
||||||
// We remove what should be removed
|
// We remove what should be removed
|
||||||
if(rightItem != null){
|
if (rightItem != null) {
|
||||||
if(recipe.rightItem == null) return false// in case it changed
|
if (recipe.rightItem == null) return false// in case it changed
|
||||||
|
|
||||||
rightItem.amount -= amount * recipe.rightItem!!.amount
|
rightItem.amount -= amount * recipe.rightItem!!.amount
|
||||||
inventory.setItem(ANVIL_INPUT_RIGHT, rightItem)
|
inventory.setItem(ANVIL_INPUT_RIGHT, rightItem)
|
||||||
|
|
@ -148,7 +172,7 @@ class AnvilResultListener: Listener {
|
||||||
leftItem.amount -= amount * recipe.leftItem!!.amount
|
leftItem.amount -= amount * recipe.leftItem!!.amount
|
||||||
inventory.setItem(ANVIL_INPUT_LEFT, leftItem)
|
inventory.setItem(ANVIL_INPUT_LEFT, leftItem)
|
||||||
|
|
||||||
if(player.gameMode != GameMode.CREATIVE){
|
if (player.gameMode != GameMode.CREATIVE) {
|
||||||
player.level -= xpCost
|
player.level -= xpCost
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,9 +180,9 @@ class AnvilResultListener: Listener {
|
||||||
val newAmount = CustomRecipeUtil.getCustomRecipeAmount(recipe, leftItem, rightItem)
|
val newAmount = CustomRecipeUtil.getCustomRecipeAmount(recipe, leftItem, rightItem)
|
||||||
|
|
||||||
CustomAnvil.verboseLog("new amount is $newAmount")
|
CustomAnvil.verboseLog("new amount is $newAmount")
|
||||||
if(newAmount <= 0 || recipe.exactCount){
|
if (newAmount <= 0 || recipe.exactCount) {
|
||||||
inventory.setItem(ANVIL_OUTPUT_SLOT, null)
|
inventory.setItem(ANVIL_OUTPUT_SLOT, null)
|
||||||
}else{
|
} else {
|
||||||
val resultItem: ItemStack = recipe.resultItem!!.clone()
|
val resultItem: ItemStack = recipe.resultItem!!.clone()
|
||||||
resultItem.amount *= newAmount
|
resultItem.amount *= newAmount
|
||||||
|
|
||||||
|
|
@ -174,6 +198,52 @@ class AnvilResultListener: Listener {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun extractAnvilResult(
|
||||||
|
event: InventoryClickEvent,
|
||||||
|
player: Player,
|
||||||
|
inventory: AnvilInventory,
|
||||||
|
leftItem: ItemStack?,
|
||||||
|
leftRemoveCount: Int,
|
||||||
|
rightItem: ItemStack?,
|
||||||
|
rightRemoveCount: Int,
|
||||||
|
output: ItemStack,
|
||||||
|
repairCost: Int,
|
||||||
|
): Boolean {
|
||||||
|
// To avoid vanilla, we cancel the event
|
||||||
|
event.result = Event.Result.DENY
|
||||||
|
event.isCancelled = true
|
||||||
|
|
||||||
|
// Assumed if player do not have enough xp then it returned MIN_VALUE
|
||||||
|
if (repairCost == Int.MIN_VALUE) return false
|
||||||
|
|
||||||
|
// Where should we get the item
|
||||||
|
val slotDestination = getActionSlot(event, player)
|
||||||
|
if (slotDestination.type == SlotType.NO_SLOT) return false
|
||||||
|
|
||||||
|
// If not creative middle click...
|
||||||
|
if (event.click != ClickType.MIDDLE) {
|
||||||
|
// We remove what should be removed
|
||||||
|
if (leftItem != null) leftItem.amount -= leftRemoveCount
|
||||||
|
inventory.setItem(ANVIL_INPUT_LEFT, leftItem)
|
||||||
|
|
||||||
|
if (rightItem != null) rightItem.amount -= rightRemoveCount
|
||||||
|
inventory.setItem(ANVIL_INPUT_RIGHT, rightItem)
|
||||||
|
|
||||||
|
inventory.setItem(ANVIL_OUTPUT_SLOT, null)
|
||||||
|
player.level -= repairCost
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, we add the item to the player
|
||||||
|
if (SlotType.CURSOR == slotDestination.type) {
|
||||||
|
player.setItemOnCursor(output)
|
||||||
|
} else {// We assume SlotType == SlotType.INVENTORY
|
||||||
|
player.inventory.setItem(slotDestination.slot, output)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO probably anvil damage & sound here ??
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
private fun onUnitRepairExtract(
|
private fun onUnitRepairExtract(
|
||||||
leftItem: ItemStack,
|
leftItem: ItemStack,
|
||||||
rightItem: ItemStack,
|
rightItem: ItemStack,
|
||||||
|
|
@ -188,39 +258,23 @@ class AnvilResultListener: Listener {
|
||||||
rightItem.amount, unitRepairResult
|
rightItem.amount, unitRepairResult
|
||||||
)
|
)
|
||||||
|
|
||||||
// To avoid vanilla, we cancel the event for unit repair
|
// Get repair cost
|
||||||
event.result = Event.Result.DENY
|
|
||||||
event.isCancelled = true
|
|
||||||
// And we give the item manually
|
|
||||||
// But first we check if we should give the item
|
|
||||||
val slotDestination = getActionSlot(event, player)
|
|
||||||
if (slotDestination.type == SlotType.NO_SLOT) return
|
|
||||||
|
|
||||||
// Test repair cost
|
|
||||||
val repairCost = getUnitRepairCost(inventory, player, leftItem, output, resultCopy, resultAmount)
|
val repairCost = getUnitRepairCost(inventory, player, leftItem, output, resultCopy, resultAmount)
|
||||||
if(repairCost == Int.MIN_VALUE) return
|
|
||||||
|
|
||||||
// If not creative middle click...
|
// And then we give the item manually
|
||||||
if (event.click != ClickType.MIDDLE) {
|
extractAnvilResult(
|
||||||
// We remove what should be removed
|
event, player, inventory,
|
||||||
inventory.setItem(ANVIL_INPUT_LEFT, null)
|
null, 0,
|
||||||
rightItem.amount -= resultAmount
|
rightItem, resultAmount,
|
||||||
inventory.setItem(ANVIL_INPUT_RIGHT, rightItem)
|
resultCopy, repairCost
|
||||||
inventory.setItem(ANVIL_OUTPUT_SLOT, null)
|
)
|
||||||
player.level -= repairCost
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, we add the item to the player
|
|
||||||
if (slotDestination.type == SlotType.CURSOR) {
|
|
||||||
player.setItemOnCursor(output)
|
|
||||||
} else {// We assume SlotType == SlotType.INVENTORY
|
|
||||||
player.inventory.setItem(slotDestination.slot, output)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getUnitRepairCost(inventory: AnvilInventory, player: Player,
|
private fun getUnitRepairCost(
|
||||||
leftItem: ItemStack, output: ItemStack,
|
inventory: AnvilInventory, player: Player,
|
||||||
resultCopy: ItemStack, resultAmount: Int): Int {
|
leftItem: ItemStack, output: ItemStack,
|
||||||
|
resultCopy: ItemStack, resultAmount: Int
|
||||||
|
): Int {
|
||||||
if (player.gameMode == GameMode.CREATIVE) return 0
|
if (player.gameMode == GameMode.CREATIVE) return 0
|
||||||
|
|
||||||
var repairCost = 0
|
var repairCost = 0
|
||||||
|
|
@ -233,7 +287,7 @@ class AnvilResultListener: Listener {
|
||||||
repairCost += ConfigOptions.itemRenameCost
|
repairCost += ConfigOptions.itemRenameCost
|
||||||
|
|
||||||
// Color cost
|
// Color cost
|
||||||
if(it.displayName.contains('§')){
|
if (it.displayName.contains('§')) {
|
||||||
repairCost += ConfigOptions.useOfColorCost
|
repairCost += ConfigOptions.useOfColorCost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -257,6 +311,185 @@ class AnvilResultListener: Listener {
|
||||||
return repairCost
|
return repairCost
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getFromLoreEditXpCost(
|
||||||
|
xpCost: AtomicInteger,
|
||||||
|
player: Player,
|
||||||
|
inventory: AnvilInventory,
|
||||||
|
): Int {
|
||||||
|
if(GameMode.CREATIVE == player.gameMode) return 0
|
||||||
|
|
||||||
|
val repairCost = xpCost.get()
|
||||||
|
return if ((inventory.maximumRepairCost <= repairCost)
|
||||||
|
|| (player.level < repairCost)) Int.MIN_VALUE
|
||||||
|
|
||||||
|
else repairCost
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleBookLoreEdit(
|
||||||
|
event: InventoryClickEvent,
|
||||||
|
inventory: AnvilInventory,
|
||||||
|
player: Player,
|
||||||
|
leftItem: ItemStack,
|
||||||
|
rightItem: ItemStack,
|
||||||
|
output: ItemStack,
|
||||||
|
): Boolean {
|
||||||
|
if (Material.WRITABLE_BOOK != rightItem.type) return false
|
||||||
|
val bookMeta = rightItem.itemMeta as BookMeta? ?: return false
|
||||||
|
|
||||||
|
val editType = AnvilLoreEditUtil.bookLoreEditIsAppend(leftItem, rightItem) ?: return false
|
||||||
|
|
||||||
|
val xpCost = AtomicInteger()
|
||||||
|
if (editType) {
|
||||||
|
if (output != AnvilLoreEditUtil.handleLoreAppendByBook(player, leftItem, bookMeta, xpCost)) return false
|
||||||
|
|
||||||
|
// Remove pages to book
|
||||||
|
val clearedBook: ItemStack?
|
||||||
|
if (LoreEditType.APPEND_BOOK.doConsume) {
|
||||||
|
clearedBook = null
|
||||||
|
} else {
|
||||||
|
clearedBook = rightItem.clone()
|
||||||
|
bookMeta.pages = Collections.emptyList()
|
||||||
|
clearedBook.itemMeta = bookMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
return extractAnvilResult(
|
||||||
|
event, player, inventory,
|
||||||
|
null, 0,
|
||||||
|
clearedBook, 0,
|
||||||
|
output, getFromLoreEditXpCost(xpCost, player, inventory)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
if (output != AnvilLoreEditUtil.handleLoreRemoveByBook(player, leftItem, xpCost)) return false
|
||||||
|
|
||||||
|
// fill book meta
|
||||||
|
val meta = leftItem.itemMeta
|
||||||
|
if (meta == null || !meta.hasLore()) return false
|
||||||
|
val lore = ArrayList<String>(meta.lore!!)
|
||||||
|
if (lore.isEmpty()) return false
|
||||||
|
|
||||||
|
val rightCopy : ItemStack?
|
||||||
|
if (LoreEditType.REMOVE_BOOK.doConsume) {
|
||||||
|
rightCopy = null
|
||||||
|
} else {
|
||||||
|
// Uncolor the page
|
||||||
|
AnvilLoreEditUtil.uncolorLines(player, lore, LoreEditType.REMOVE_BOOK)
|
||||||
|
|
||||||
|
val bookPage = StringBuilder()
|
||||||
|
lore.forEach {
|
||||||
|
if (bookPage.isNotEmpty()) bookPage.append('\n')
|
||||||
|
bookPage.append(it)
|
||||||
|
}
|
||||||
|
|
||||||
|
val resultPage = bookPage.toString()
|
||||||
|
//TODO maybe check page size ? bc it may be too big ???
|
||||||
|
|
||||||
|
rightCopy = rightItem.clone()
|
||||||
|
bookMeta.setPages(resultPage)
|
||||||
|
rightCopy.itemMeta = bookMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
return extractAnvilResult(
|
||||||
|
event, player, inventory,
|
||||||
|
null, 0,
|
||||||
|
rightCopy, 0,
|
||||||
|
output, getFromLoreEditXpCost(xpCost, player, inventory)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handlePaperLoreEdit(
|
||||||
|
event: InventoryClickEvent,
|
||||||
|
inventory: AnvilInventory,
|
||||||
|
player: Player,
|
||||||
|
leftItem: ItemStack,
|
||||||
|
rightItem: ItemStack,
|
||||||
|
output: ItemStack,
|
||||||
|
): Boolean {
|
||||||
|
if (Material.PAPER != rightItem.type) return false
|
||||||
|
val paperMeta = rightItem.itemMeta ?: return false
|
||||||
|
|
||||||
|
val editType = AnvilLoreEditUtil.paperLoreEditIsAppend(leftItem, rightItem) ?: return false
|
||||||
|
|
||||||
|
val xpCost = AtomicInteger()
|
||||||
|
if (editType) {
|
||||||
|
if (output != AnvilLoreEditUtil.handleLoreAppendByPaper(player, leftItem, rightItem, xpCost)) return false
|
||||||
|
|
||||||
|
val paperCopy: ItemStack?
|
||||||
|
if (LoreEditType.APPEND_PAPER.doConsume) {
|
||||||
|
paperCopy = null
|
||||||
|
} else {
|
||||||
|
// Remove custom name to paper
|
||||||
|
paperCopy = rightItem.clone()
|
||||||
|
paperCopy.amount = 1
|
||||||
|
paperMeta.setDisplayName(null)
|
||||||
|
paperCopy.itemMeta = paperMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (rightItem.amount > 1) {
|
||||||
|
extractAnvilResult(
|
||||||
|
event, player, inventory,
|
||||||
|
paperCopy, 0,
|
||||||
|
rightItem, 1,
|
||||||
|
output, getFromLoreEditXpCost(xpCost, player, inventory)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
extractAnvilResult(
|
||||||
|
event, player, inventory,
|
||||||
|
null, 0,
|
||||||
|
paperCopy, 0,
|
||||||
|
output, getFromLoreEditXpCost(xpCost, player, inventory)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (output != AnvilLoreEditUtil.handleLoreRemoveByPaper(player, leftItem, xpCost)) return false
|
||||||
|
|
||||||
|
val leftMeta = leftItem.itemMeta
|
||||||
|
if (leftMeta == null || !leftMeta.hasLore()) return false
|
||||||
|
val lore = leftMeta.lore!!
|
||||||
|
if (lore.isEmpty()) return false
|
||||||
|
|
||||||
|
// Create result item
|
||||||
|
val rightClone: ItemStack?
|
||||||
|
if(LoreEditType.REMOVE_PAPER.doConsume){
|
||||||
|
rightClone = null
|
||||||
|
}else{
|
||||||
|
val removeEnd = LoreEditConfigUtil.paperLoreOrderIsEnd
|
||||||
|
var line = if (removeEnd) lore[lore.size - 1]
|
||||||
|
else lore[0]
|
||||||
|
|
||||||
|
// Overkill but uncolor the line
|
||||||
|
val tempList = ArrayList<String>(1)
|
||||||
|
tempList.add(line)
|
||||||
|
AnvilLoreEditUtil.uncolorLines(player, tempList, LoreEditType.REMOVE_PAPER)
|
||||||
|
line = tempList[0]
|
||||||
|
|
||||||
|
rightClone = rightItem.clone()
|
||||||
|
rightClone.amount = 1
|
||||||
|
|
||||||
|
val resultMeta = rightClone.itemMeta ?: return false
|
||||||
|
resultMeta.setDisplayName(line)
|
||||||
|
rightClone.itemMeta = resultMeta
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (rightItem.amount > 1) {
|
||||||
|
extractAnvilResult(
|
||||||
|
event, player, inventory,
|
||||||
|
rightClone, 0,
|
||||||
|
rightItem, 1,
|
||||||
|
output, getFromLoreEditXpCost(xpCost, player, inventory)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
extractAnvilResult(
|
||||||
|
event, player, inventory,
|
||||||
|
null, 0,
|
||||||
|
rightClone, 0,
|
||||||
|
output, getFromLoreEditXpCost(xpCost, player, inventory)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the destination slot or "NO_SLOT" slot container if there is no slot available
|
* Get the destination slot or "NO_SLOT" slot container if there is no slot available
|
||||||
*/
|
*/
|
||||||
|
|
@ -283,8 +516,7 @@ class AnvilResultListener: Listener {
|
||||||
return NO_SLOT
|
return NO_SLOT
|
||||||
}
|
}
|
||||||
return SlotContainer(SlotType.INVENTORY, slotIndex)
|
return SlotContainer(SlotType.INVENTORY, slotIndex)
|
||||||
}
|
} else if (player.itemOnCursor.type != Material.AIR) return NO_SLOT
|
||||||
else if (player.itemOnCursor.type != Material.AIR) return NO_SLOT
|
|
||||||
return CURSOR_SLOT
|
return CURSOR_SLOT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import io.delilaheve.util.ItemUtil.repairFrom
|
||||||
import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe
|
import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe
|
||||||
import io.delilaheve.util.ItemUtil.unitRepair
|
import io.delilaheve.util.ItemUtil.unitRepair
|
||||||
import org.bukkit.ChatColor
|
import org.bukkit.ChatColor
|
||||||
|
import org.bukkit.Material
|
||||||
import org.bukkit.entity.HumanEntity
|
import org.bukkit.entity.HumanEntity
|
||||||
import org.bukkit.event.EventHandler
|
import org.bukkit.event.EventHandler
|
||||||
import org.bukkit.event.EventPriority
|
import org.bukkit.event.EventPriority
|
||||||
|
|
@ -19,11 +20,10 @@ import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||||
import org.bukkit.inventory.AnvilInventory
|
import org.bukkit.inventory.AnvilInventory
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilColorUtil
|
import xyz.alexcrea.cuanvil.util.*
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilUseType
|
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil
|
|
||||||
import xyz.alexcrea.cuanvil.util.CustomRecipeUtil
|
|
||||||
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener for anvil events
|
* Listener for anvil events
|
||||||
*/
|
*/
|
||||||
|
|
@ -72,12 +72,15 @@ class PrepareAnvilListener : Listener {
|
||||||
// Test for unit repair
|
// Test for unit repair
|
||||||
if(testUnitRepair(event, inventory, player, first, second)) return
|
if(testUnitRepair(event, inventory, player, first, second)) return
|
||||||
|
|
||||||
|
// Test for lore edit
|
||||||
|
if(testLoreEdit(event, inventory, player, first, second)) return
|
||||||
|
|
||||||
CustomAnvil.log("no anvil fuse type found")
|
CustomAnvil.log("no anvil fuse type found")
|
||||||
event.result = null
|
event.result = null
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if a custom recipe exist with these ingredient
|
// return true if a custom recipe exist with these ingredients
|
||||||
private fun testCustomRecipe(event: PrepareAnvilEvent, inventory: AnvilInventory,
|
private fun testCustomRecipe(event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||||
player: HumanEntity,
|
player: HumanEntity,
|
||||||
first: ItemStack, second: ItemStack?): Boolean {
|
first: ItemStack, second: ItemStack?): Boolean {
|
||||||
|
|
@ -131,7 +134,10 @@ class PrepareAnvilListener : Listener {
|
||||||
if(ConfigOptions.renameColorPossible && inventoryName != null){
|
if(ConfigOptions.renameColorPossible && inventoryName != null){
|
||||||
val resultString = StringBuilder(inventoryName)
|
val resultString = StringBuilder(inventoryName)
|
||||||
|
|
||||||
useColor = AnvilColorUtil.handleRenamingColor(resultString, player)
|
useColor = AnvilColorUtil.handleColor(resultString, player,
|
||||||
|
ConfigOptions.permissionNeededForColor,
|
||||||
|
ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor,
|
||||||
|
AnvilColorUtil.ColorUseType.RENAME)
|
||||||
|
|
||||||
if(useColor) {
|
if(useColor) {
|
||||||
inventoryName = resultString.toString()
|
inventoryName = resultString.toString()
|
||||||
|
|
@ -222,4 +228,27 @@ class PrepareAnvilListener : Listener {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun testLoreEdit(event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
|
||||||
|
first: ItemStack, second: ItemStack): Boolean {
|
||||||
|
val type = second.type
|
||||||
|
var result: ItemStack? = null
|
||||||
|
|
||||||
|
val xpCost = AtomicInteger()
|
||||||
|
if(Material.WRITABLE_BOOK == type) {
|
||||||
|
result = AnvilLoreEditUtil.tryLoreEditByBook(player, first, second, xpCost)
|
||||||
|
}
|
||||||
|
else if(Material.PAPER == type) {
|
||||||
|
result = AnvilLoreEditUtil.tryLoreEditByPaper(player, first, second, xpCost)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(result == null || first == result) {
|
||||||
|
CustomAnvil.log("lore edit, But input is same as output")
|
||||||
|
event.result = null
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
event.result = result
|
||||||
|
AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, xpCost.get())
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,38 +1,99 @@
|
||||||
package xyz.alexcrea.cuanvil.util
|
package xyz.alexcrea.cuanvil.util
|
||||||
|
|
||||||
import io.delilaheve.util.ConfigOptions
|
import org.bukkit.permissions.Permissible
|
||||||
import org.bukkit.entity.HumanEntity
|
|
||||||
import java.util.regex.Matcher
|
import java.util.regex.Matcher
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
object AnvilColorUtil {
|
object AnvilColorUtil {
|
||||||
private val HEX_PATTERN: Pattern = Pattern.compile("#[A-Fa-f0-9]{6}") // pattern to find hexadecimal string
|
private val HEX_PATTERN: Pattern = Pattern.compile("#[A-Fa-f0-9]{6}") // pattern to find hexadecimal string
|
||||||
|
private val TRANSFORMED_HEX_PATTERN = Pattern.compile("§x(§[0-9a-fA-F]){6}") // pattern to find minecraft hex string
|
||||||
|
|
||||||
fun handleRenamingColor(textToColor: StringBuilder, player: HumanEntity): Boolean {
|
/**
|
||||||
val usePermission = ConfigOptions.permissionNeededForColor
|
* Color a stringbuilder object depending on allowed color type and player permissions on color use type
|
||||||
val canUseColorCode = ConfigOptions.allowColorCode && (!usePermission || player.hasPermission("ca.color.code"))
|
* @return if the stringbuilder was changed and color applied
|
||||||
val canUseHexColor = ConfigOptions.allowHexadecimalColor && (!usePermission || player.hasPermission("ca.color.hex"))
|
*/
|
||||||
|
fun handleColor(
|
||||||
|
textToColor: StringBuilder,
|
||||||
|
player: Permissible,
|
||||||
|
usePermission: Boolean,
|
||||||
|
allowColorCode: Boolean,
|
||||||
|
allowHexadecimalColor: Boolean,
|
||||||
|
useType: ColorUseType
|
||||||
|
): Boolean {
|
||||||
|
if (!allowColorCode && !allowHexadecimalColor) return false
|
||||||
|
|
||||||
if((!canUseColorCode) && (!canUseHexColor)) return false
|
val canUseColorCode =
|
||||||
|
allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission(
|
||||||
|
useType.colorCodePerm
|
||||||
|
))
|
||||||
|
val canUseHexColor =
|
||||||
|
allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission(
|
||||||
|
useType.hexColorPerm
|
||||||
|
))
|
||||||
|
|
||||||
|
if ((!canUseColorCode) && (!canUseHexColor)) return false
|
||||||
|
|
||||||
var useColor = false
|
var useColor = false
|
||||||
// Handle color code
|
// Handle color code
|
||||||
if(canUseColorCode){
|
if (canUseColorCode) {
|
||||||
var nbReplacement = replaceAll(textToColor, "&", "§", 2)
|
var nbReplacement = replaceAll(textToColor, "&", "§", 2)
|
||||||
nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2)
|
nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2)
|
||||||
|
|
||||||
if(nbReplacement > 0) useColor = true
|
if (nbReplacement > 0) useColor = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if(canUseHexColor){
|
if (canUseHexColor) {
|
||||||
val nbReplacement = replaceHexToColor(textToColor, 7)
|
val nbReplacement = replaceHexToColor(textToColor, 7)
|
||||||
|
|
||||||
if(nbReplacement > 0) useColor = true
|
if (nbReplacement > 0) useColor = true
|
||||||
}
|
}
|
||||||
|
|
||||||
return useColor
|
return useColor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Revert a stringbuilder to a state where applying handleColor with the same options would give the same result
|
||||||
|
* @return if the stringbuilder was changed and color unapplied
|
||||||
|
*/
|
||||||
|
fun revertColor(
|
||||||
|
colorToText: StringBuilder,
|
||||||
|
player: Permissible,
|
||||||
|
usePermission: Boolean,
|
||||||
|
allowColorCode: Boolean,
|
||||||
|
allowHexadecimalColor: Boolean,
|
||||||
|
useType: ColorUseType
|
||||||
|
): Boolean {
|
||||||
|
if (!allowColorCode && !allowHexadecimalColor) return false
|
||||||
|
|
||||||
|
val canUseColorCode =
|
||||||
|
allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission(
|
||||||
|
useType.colorCodePerm
|
||||||
|
))
|
||||||
|
val canUseHexColor =
|
||||||
|
allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission(
|
||||||
|
useType.hexColorPerm
|
||||||
|
))
|
||||||
|
|
||||||
|
if ((!canUseColorCode) && (!canUseHexColor)) return false
|
||||||
|
var hasReversed = false
|
||||||
|
|
||||||
|
// Reverse hex pattern
|
||||||
|
if (canUseHexColor) {
|
||||||
|
val nbReplacement = replaceColorToHex(colorToText, 14)
|
||||||
|
|
||||||
|
if (nbReplacement > 0) hasReversed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canUseColorCode) {
|
||||||
|
replaceAll(colorToText, "&", "&&", 1)
|
||||||
|
val nbReplacement = replaceAll(colorToText, "§", "&", 2)
|
||||||
|
|
||||||
|
if (nbReplacement > 0) hasReversed = true
|
||||||
|
}
|
||||||
|
|
||||||
|
return hasReversed
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace every instance of "from" to "to".
|
* Replace every instance of "from" to "to".
|
||||||
* @param builder The builder to replace the string from.
|
* @param builder The builder to replace the string from.
|
||||||
|
|
@ -50,7 +111,7 @@ object AnvilColorUtil {
|
||||||
index += to.length
|
index += to.length
|
||||||
index = builder.indexOf(from, index)
|
index = builder.indexOf(from, index)
|
||||||
|
|
||||||
numberOfChanges+=1
|
numberOfChanges += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return numberOfChanges
|
return numberOfChanges
|
||||||
|
|
@ -68,21 +129,58 @@ object AnvilColorUtil {
|
||||||
var numberOfChanges = 0
|
var numberOfChanges = 0
|
||||||
var startIndex = 0
|
var startIndex = 0
|
||||||
|
|
||||||
while(matcher.find(startIndex)){
|
while (matcher.find(startIndex)) {
|
||||||
startIndex = matcher.start()
|
startIndex = matcher.start()
|
||||||
if(startIndex >= builder.length - endOffset) break
|
if (startIndex >= builder.length - endOffset) break //HOW AND WHERE WOULD THIS HAPPEN ?????
|
||||||
|
|
||||||
builder.replace(startIndex, startIndex + 1, "§x")
|
builder.replace(startIndex, startIndex + 1, "§x")
|
||||||
startIndex+=2
|
startIndex += 2
|
||||||
for (i in 0..5) {
|
for (i in 0..5) {
|
||||||
builder.insert(startIndex, '§')
|
builder.insert(startIndex, '§')
|
||||||
startIndex+=2
|
startIndex += 2
|
||||||
}
|
}
|
||||||
|
|
||||||
numberOfChanges+=1
|
numberOfChanges += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
return numberOfChanges
|
return numberOfChanges
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace every hex color from the minecraft format to a format like #000000
|
||||||
|
* @param builder The builder to replace the minecraft hex color from.
|
||||||
|
* @param endOffset Amount of character that should be ignored at the end.
|
||||||
|
* @return The number of replacement was that was done.
|
||||||
|
*/
|
||||||
|
private fun replaceColorToHex(builder: StringBuilder, endOffset: Int): Int {
|
||||||
|
val matcher: Matcher = TRANSFORMED_HEX_PATTERN.matcher(builder)
|
||||||
|
|
||||||
|
var numberOfChanges = 0
|
||||||
|
var startIndex = 0
|
||||||
|
|
||||||
|
while (matcher.find(startIndex)) {
|
||||||
|
startIndex = matcher.start()
|
||||||
|
if (startIndex >= builder.length - endOffset) break //HOW AND WHERE WOULD THIS HAPPEN ?????
|
||||||
|
|
||||||
|
builder.replace(startIndex, startIndex + 2, "#")
|
||||||
|
startIndex += 1
|
||||||
|
for (i in 0..5) {
|
||||||
|
builder.deleteCharAt(startIndex)
|
||||||
|
startIndex += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
numberOfChanges += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return numberOfChanges
|
||||||
|
}
|
||||||
|
|
||||||
|
enum class ColorUseType(
|
||||||
|
val colorCodePerm: String?,
|
||||||
|
val hexColorPerm: String?
|
||||||
|
) {
|
||||||
|
RENAME("ca.color.code", "ca.color.hex"),
|
||||||
|
LORE_EDIT(null, null)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
288
src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt
Normal file
288
src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt
Normal file
|
|
@ -0,0 +1,288 @@
|
||||||
|
package xyz.alexcrea.cuanvil.util
|
||||||
|
|
||||||
|
import org.bukkit.entity.HumanEntity
|
||||||
|
import org.bukkit.inventory.ItemStack
|
||||||
|
import org.bukkit.inventory.meta.BookMeta
|
||||||
|
import org.bukkit.permissions.Permissible
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditType
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
|
object AnvilLoreEditUtil {
|
||||||
|
|
||||||
|
private const val LORE_BY_BOOK: String = "ca.lore_edit.book"
|
||||||
|
private const val LORE_BY_PAPER: String = "ca.lore_edit.paper"
|
||||||
|
|
||||||
|
private fun hasLoreEditByBookPermission(player: Permissible): Boolean {
|
||||||
|
return !LoreEditConfigUtil.bookLoreEditNeedPermission || player.hasPermission(LORE_BY_BOOK)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasLoreEditByPaperPermission(player: Permissible): Boolean {
|
||||||
|
return !LoreEditConfigUtil.paperLoreEditNeedPermission || player.hasPermission(LORE_BY_PAPER)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleLoreAppendByBook(
|
||||||
|
player: Permissible,
|
||||||
|
first: ItemStack,
|
||||||
|
book: BookMeta,
|
||||||
|
xpCost: AtomicInteger
|
||||||
|
): ItemStack? {
|
||||||
|
if (!hasLoreEditByBookPermission(player)) return null
|
||||||
|
|
||||||
|
val result = first.clone()
|
||||||
|
val meta = result.itemMeta ?: return null
|
||||||
|
val lore = if (meta.hasLore()) {
|
||||||
|
ArrayList<String>(meta.lore!!)
|
||||||
|
} else ArrayList()
|
||||||
|
|
||||||
|
val page = book.pages[0]
|
||||||
|
val lines = ArrayList<String>(page.split("\n"))
|
||||||
|
val colorCost = colorLines(player, lines, LoreEditType.APPEND_BOOK)
|
||||||
|
|
||||||
|
lore.addAll(lines)
|
||||||
|
|
||||||
|
meta.lore = lore
|
||||||
|
result.itemMeta = meta
|
||||||
|
|
||||||
|
if (result == first) return null
|
||||||
|
|
||||||
|
// Handle xp
|
||||||
|
xpCost.addAndGet(colorCost) // Cost of using color
|
||||||
|
xpCost.addAndGet(lines.size * LoreEditType.APPEND_BOOK.perLineCost) // per line cost
|
||||||
|
xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.APPEND_BOOK)) // Fixed cost and work penalty
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleLoreRemoveByBook(player: Permissible, first: ItemStack, xpCost: AtomicInteger): ItemStack? {
|
||||||
|
if (!hasLoreEditByBookPermission(player)) return null
|
||||||
|
|
||||||
|
// remove lore
|
||||||
|
val result = first.clone()
|
||||||
|
val leftMeta = result.itemMeta ?: return null
|
||||||
|
val currentLore = ArrayList<String>(leftMeta.lore ?: return null)
|
||||||
|
|
||||||
|
val uncolorCost = uncolorLines(player, currentLore, LoreEditType.REMOVE_BOOK)
|
||||||
|
|
||||||
|
leftMeta.lore = null
|
||||||
|
result.itemMeta = leftMeta
|
||||||
|
|
||||||
|
if (result == first) return null
|
||||||
|
|
||||||
|
// Handle xp
|
||||||
|
xpCost.addAndGet(uncolorCost)
|
||||||
|
xpCost.addAndGet(currentLore.size * LoreEditType.REMOVE_BOOK.perLineCost)
|
||||||
|
xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.REMOVE_BOOK))
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if appended, false if removed, null if neither
|
||||||
|
fun bookLoreEditIsAppend(first: ItemStack, second: ItemStack): Boolean? {
|
||||||
|
// Test if the book & quil contain content
|
||||||
|
val meta = second.itemMeta as BookMeta? ?: return false
|
||||||
|
|
||||||
|
var hasContent = false
|
||||||
|
if (meta.hasPages() && meta.pageCount >= 1) {
|
||||||
|
// Test if the pages is ok
|
||||||
|
for (page in meta.pages) {
|
||||||
|
if (page.isNotBlank()) {
|
||||||
|
hasContent = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't want to "add" the first page is there is content and the first page is empty
|
||||||
|
if (hasContent) {
|
||||||
|
if (meta.pages[0].isEmpty()) return null
|
||||||
|
if (LoreEditType.APPEND_BOOK.enabled)
|
||||||
|
return true
|
||||||
|
} else if (LoreEditType.REMOVE_BOOK.enabled) {
|
||||||
|
if (!first.hasItemMeta()) return null
|
||||||
|
|
||||||
|
val leftMeta = first.itemMeta!!
|
||||||
|
return if (leftMeta.hasLore()) false
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun tryLoreEditByBook(player: HumanEntity, first: ItemStack, second: ItemStack, xpCost: AtomicInteger): ItemStack? {
|
||||||
|
val bookType = bookLoreEditIsAppend(first, second) ?: return null
|
||||||
|
|
||||||
|
val meta = second.itemMeta as BookMeta
|
||||||
|
return if (bookType) handleLoreAppendByBook(player, first, meta, xpCost)
|
||||||
|
else handleLoreRemoveByBook(player, first, xpCost)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true if appended, false if removed, null if neither
|
||||||
|
fun paperLoreEditIsAppend(first: ItemStack, second: ItemStack): Boolean? {
|
||||||
|
// Test if the paper contain a display name
|
||||||
|
val meta = second.itemMeta ?: return false
|
||||||
|
|
||||||
|
val hasContent = meta.hasDisplayName()
|
||||||
|
if (hasContent) {
|
||||||
|
if (LoreEditType.APPEND_PAPER.enabled)
|
||||||
|
return true
|
||||||
|
} else if (LoreEditType.REMOVE_PAPER.enabled) {
|
||||||
|
if (!first.hasItemMeta()) return null
|
||||||
|
|
||||||
|
val leftMeta = first.itemMeta!!
|
||||||
|
return if (leftMeta.hasLore() && leftMeta.lore!!.isNotEmpty()) false
|
||||||
|
else null
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleLoreAppendByPaper(
|
||||||
|
player: Permissible,
|
||||||
|
first: ItemStack,
|
||||||
|
second: ItemStack,
|
||||||
|
xpCost: AtomicInteger
|
||||||
|
): ItemStack? {
|
||||||
|
if (!hasLoreEditByPaperPermission(player)) return null
|
||||||
|
|
||||||
|
val result = first.clone()
|
||||||
|
val meta = result.itemMeta?: return null
|
||||||
|
val lore = if (meta.hasLore()) {
|
||||||
|
ArrayList<String>(meta.lore!!)
|
||||||
|
} else ArrayList()
|
||||||
|
|
||||||
|
val appendEnd = LoreEditConfigUtil.paperLoreOrderIsEnd
|
||||||
|
|
||||||
|
// A bit overdone to color 1 line but hey
|
||||||
|
val tempList = ArrayList<String>(1)
|
||||||
|
tempList.add(second.itemMeta!!.displayName)
|
||||||
|
val colorCost = colorLines(player, tempList, LoreEditType.APPEND_PAPER)
|
||||||
|
|
||||||
|
val line = tempList[0]
|
||||||
|
if (appendEnd)
|
||||||
|
lore.add(line)
|
||||||
|
else
|
||||||
|
lore.add(0, line)
|
||||||
|
|
||||||
|
meta.lore = lore
|
||||||
|
result.itemMeta = meta
|
||||||
|
|
||||||
|
if (result == first) return null
|
||||||
|
|
||||||
|
// Handle xp
|
||||||
|
xpCost.addAndGet(colorCost)
|
||||||
|
xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.APPEND_PAPER))
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun handleLoreRemoveByPaper(player: Permissible, first: ItemStack, xpCost: AtomicInteger): ItemStack? {
|
||||||
|
if (!hasLoreEditByPaperPermission(player)) return null
|
||||||
|
|
||||||
|
// remove lore line
|
||||||
|
val result = first.clone()
|
||||||
|
val meta = result.itemMeta!!
|
||||||
|
|
||||||
|
val removeEnd = LoreEditConfigUtil.paperLoreOrderIsEnd
|
||||||
|
val lore: ArrayList<String> = ArrayList(meta.lore!!)
|
||||||
|
|
||||||
|
val line = if (removeEnd) lore.removeAt(lore.size - 1)
|
||||||
|
else lore.removeAt(0)
|
||||||
|
|
||||||
|
meta.lore = if (lore.isEmpty()) null else lore
|
||||||
|
result.itemMeta = meta
|
||||||
|
|
||||||
|
// Get color cost to uncolor this line
|
||||||
|
val tempList = ArrayList<String>(1)
|
||||||
|
tempList.add(line)
|
||||||
|
val uncolorCost = uncolorLines(player, tempList, LoreEditType.REMOVE_PAPER)
|
||||||
|
|
||||||
|
if (result == first) return null
|
||||||
|
|
||||||
|
// Handle other xp
|
||||||
|
xpCost.addAndGet(uncolorCost)
|
||||||
|
xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.REMOVE_PAPER))
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
fun tryLoreEditByPaper(
|
||||||
|
player: HumanEntity,
|
||||||
|
first: ItemStack,
|
||||||
|
second: ItemStack,
|
||||||
|
xpCost: AtomicInteger
|
||||||
|
): ItemStack? {
|
||||||
|
val bookType = paperLoreEditIsAppend(first, second) ?: return null
|
||||||
|
|
||||||
|
return if (bookType) handleLoreAppendByPaper(player, first, second, xpCost)
|
||||||
|
else handleLoreRemoveByPaper(player, first, xpCost)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun baseEditLoreXpCost(
|
||||||
|
first: ItemStack,
|
||||||
|
result: ItemStack,
|
||||||
|
editType: LoreEditType
|
||||||
|
): Int {
|
||||||
|
var xpCost = editType.fixedCost
|
||||||
|
|
||||||
|
xpCost += AnvilXpUtil.calculatePenalty(first, null, result, editType.useType)
|
||||||
|
return xpCost
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun colorLines(player: Permissible, lines: ArrayList<String>, editType: LoreEditType): Int {
|
||||||
|
val canUseHex = editType.allowHexColor
|
||||||
|
val canUseColorCode = editType.allowColorCode
|
||||||
|
val colorCost = editType.useColorCost
|
||||||
|
|
||||||
|
// Now handle color of each lines
|
||||||
|
var hasUsedColor = false
|
||||||
|
for ((index, line) in lines.withIndex()) {
|
||||||
|
val coloredLine = StringBuilder(line)
|
||||||
|
|
||||||
|
val lineUsedColor = AnvilColorUtil.handleColor(
|
||||||
|
coloredLine,
|
||||||
|
player,
|
||||||
|
false, canUseColorCode, canUseHex,
|
||||||
|
AnvilColorUtil.ColorUseType.LORE_EDIT
|
||||||
|
)
|
||||||
|
|
||||||
|
if (lineUsedColor) {
|
||||||
|
hasUsedColor = true
|
||||||
|
lines[index] = coloredLine.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (hasUsedColor) {
|
||||||
|
colorCost
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun uncolorLines(player: Permissible, lines: ArrayList<String>, editType: LoreEditType): Int {
|
||||||
|
if(!editType.shouldRemoveColorOnLoreRemoval) return 0
|
||||||
|
|
||||||
|
// Now handle color of each lines
|
||||||
|
var hasUndidColor = false
|
||||||
|
for ((index, line) in lines.withIndex()) {
|
||||||
|
val uncoloredLine = StringBuilder(line)
|
||||||
|
|
||||||
|
val lineUndidColor = AnvilColorUtil.revertColor(
|
||||||
|
uncoloredLine,
|
||||||
|
player,
|
||||||
|
false, true, true,
|
||||||
|
AnvilColorUtil.ColorUseType.LORE_EDIT
|
||||||
|
)
|
||||||
|
|
||||||
|
if (lineUndidColor) {
|
||||||
|
hasUndidColor = true
|
||||||
|
lines[index] = uncoloredLine.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (hasUndidColor) {
|
||||||
|
editType.removeColorCost
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -2,28 +2,66 @@ package xyz.alexcrea.cuanvil.util
|
||||||
|
|
||||||
import org.bukkit.Material
|
import org.bukkit.Material
|
||||||
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
|
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditType
|
||||||
|
|
||||||
enum class AnvilUseType(val typeName: String,
|
enum class AnvilUseType(
|
||||||
val defaultPenalty: WorkPenaltyPart,
|
val typeName: String, val path: String,
|
||||||
val displayName: String, val displayMat: Material
|
val defaultPenalty: WorkPenaltyPart,
|
||||||
) {
|
val displayName: String, val displayMat: Material
|
||||||
|
) {
|
||||||
|
|
||||||
RENAME_ONLY("rename_only",
|
RENAME_ONLY(
|
||||||
|
"rename_only",
|
||||||
WorkPenaltyPart(false, true),
|
WorkPenaltyPart(false, true),
|
||||||
"Rename Only", Material.NAME_TAG
|
"Rename Only", Material.NAME_TAG
|
||||||
),
|
),
|
||||||
MERGE("merge",
|
MERGE(
|
||||||
|
"merge",
|
||||||
WorkPenaltyPart(true, true),
|
WorkPenaltyPart(true, true),
|
||||||
"Merge", Material.ANVIL
|
"Merge", Material.ANVIL
|
||||||
),
|
),
|
||||||
UNIT_REPAIR("unit_repair",
|
UNIT_REPAIR(
|
||||||
|
"unit_repair",
|
||||||
WorkPenaltyPart(true, true),
|
WorkPenaltyPart(true, true),
|
||||||
"Unit Repair", Material.DIAMOND
|
"Unit Repair", Material.DIAMOND
|
||||||
),
|
),
|
||||||
CUSTOM_CRAFT("custom_craft",
|
CUSTOM_CRAFT(
|
||||||
|
"custom_craft",
|
||||||
WorkPenaltyPart(false, false),
|
WorkPenaltyPart(false, false),
|
||||||
"Custom Craft", Material.CRAFTING_TABLE
|
"Custom Craft", Material.CRAFTING_TABLE
|
||||||
),
|
),
|
||||||
|
LORE_EDIT_BOOK_APPEND(
|
||||||
|
"lore_edit_book_append", "lore_edit.book_and_quil.append",
|
||||||
|
WorkPenaltyPart(false, false),
|
||||||
|
"Book Add", Material.WRITABLE_BOOK
|
||||||
|
),
|
||||||
|
LORE_EDIT_BOOK_REMOVE(
|
||||||
|
"lore_edit_book_remove", "lore_edit.book_and_quil.remove",
|
||||||
|
WorkPenaltyPart(false, false),
|
||||||
|
"Book Remove", Material.WRITABLE_BOOK
|
||||||
|
),
|
||||||
|
LORE_EDIT_PAPER_APPEND(
|
||||||
|
"lore_edit_paper_append", "lore_edit.paper.append_line",
|
||||||
|
WorkPenaltyPart(false, false),
|
||||||
|
"Paper Add", Material.WRITABLE_BOOK
|
||||||
|
),
|
||||||
|
LORE_EDIT_PAPER_REMOVE(
|
||||||
|
"lore_edit_paper_remove", "lore_edit.paper.remove_line",
|
||||||
|
WorkPenaltyPart(false, false),
|
||||||
|
"Paper Remove", Material.WRITABLE_BOOK
|
||||||
|
),
|
||||||
;
|
;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
typeName: String,
|
||||||
|
defaultPenalty: WorkPenaltyPart,
|
||||||
|
displayName: String, displayMat: Material
|
||||||
|
) :
|
||||||
|
this(
|
||||||
|
typeName,
|
||||||
|
AnvilUseTypeUtil.defaultPath(typeName), // stupid util class
|
||||||
|
defaultPenalty,
|
||||||
|
displayName, displayMat
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package xyz.alexcrea.cuanvil.util
|
||||||
|
|
||||||
|
import io.delilaheve.util.ConfigOptions
|
||||||
|
|
||||||
|
object AnvilUseTypeUtil {
|
||||||
|
|
||||||
|
/*
|
||||||
|
By stupidity of kotlin not allowing static function outside of companion object I need to do another util class only for 1 function:
|
||||||
|
Companion object on enum class seems to get initialized AFTER the enum itself
|
||||||
|
that mean. if you want to call a static function on the enum class itself YOU CAN'T. you need to do this stupid thing
|
||||||
|
or you can make a stupid top level function OR object that even worse because of global scope pollution
|
||||||
|
(btw was gpt ""solution"". fortunately I do not "vibe code" so I do what I know instead of stupid AI solution & code)
|
||||||
|
I mean, this is still global scope pollution bc of a USELESS class that SHOULD not exist but as a class is better than a random *ss function
|
||||||
|
|
||||||
|
sorry for the rent but this made me frustrated
|
||||||
|
|
||||||
|
Note: I still like a lot of part of kotlin compared to java but this part is one that I hate
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Get config path for normal anvil use
|
||||||
|
*/
|
||||||
|
fun defaultPath(typeName: String): String {
|
||||||
|
return "${ConfigOptions.WORK_PENALTY_ROOT}.$typeName"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -11,7 +11,6 @@ import org.bukkit.entity.HumanEntity
|
||||||
import org.bukkit.entity.Player
|
import org.bukkit.entity.Player
|
||||||
import org.bukkit.inventory.AnvilInventory
|
import org.bukkit.inventory.AnvilInventory
|
||||||
import org.bukkit.inventory.InventoryView
|
import org.bukkit.inventory.InventoryView
|
||||||
import org.bukkit.inventory.InventoryView.Property.REPAIR_COST
|
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
import org.bukkit.inventory.meta.Repairable
|
import org.bukkit.inventory.meta.Repairable
|
||||||
import org.bukkit.persistence.PersistentDataType
|
import org.bukkit.persistence.PersistentDataType
|
||||||
|
|
@ -129,13 +128,16 @@ object AnvilXpUtil {
|
||||||
return resultSum
|
return resultSum
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun exclusivePenaltyKey(useType: AnvilUseType): NamespacedKey {
|
||||||
|
return NamespacedKey(CustomAnvil.instance, "${EXCLUSIVE_PENALTY_PREFIX}_${useType.typeName}")
|
||||||
|
}
|
||||||
|
|
||||||
private fun setExclusivePenalty(
|
private fun setExclusivePenalty(
|
||||||
result: ItemStack,
|
result: ItemStack,
|
||||||
resultPenalty: Int,
|
resultPenalty: Int,
|
||||||
useType: AnvilUseType
|
useType: AnvilUseType
|
||||||
) {
|
) {
|
||||||
val tagPath = EXCLUSIVE_PENALTY_PREFIX + "_" + useType.typeName
|
val key = exclusivePenaltyKey(useType)
|
||||||
val key = NamespacedKey(CustomAnvil.instance, tagPath)
|
|
||||||
|
|
||||||
val meta = result.itemMeta!!
|
val meta = result.itemMeta!!
|
||||||
meta.persistentDataContainer.set(key, PersistentDataType.INTEGER, resultPenalty)
|
meta.persistentDataContainer.set(key, PersistentDataType.INTEGER, resultPenalty)
|
||||||
|
|
@ -143,14 +145,13 @@ object AnvilXpUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findExclusivePenalty(
|
private fun findExclusivePenalty(
|
||||||
left: ItemStack?,
|
item: ItemStack?,
|
||||||
useType: AnvilUseType
|
useType: AnvilUseType
|
||||||
): Int {
|
): Int {
|
||||||
if (left == null) return 0
|
if (item == null || !item.hasItemMeta()) return 0
|
||||||
val tagPath = EXCLUSIVE_PENALTY_PREFIX + "_" + useType.typeName
|
val key = exclusivePenaltyKey(useType)
|
||||||
val key = NamespacedKey(CustomAnvil.instance, tagPath)
|
|
||||||
|
|
||||||
val meta = left.itemMeta!!
|
val meta = item.itemMeta!!
|
||||||
return meta.persistentDataContainer.get(key, PersistentDataType.INTEGER) ?: return 0
|
return meta.persistentDataContainer.get(key, PersistentDataType.INTEGER) ?: return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
package xyz.alexcrea.cuanvil.util.config
|
||||||
|
|
||||||
|
import xyz.alexcrea.cuanvil.config.ConfigHolder.DEFAULT_CONFIG as CONFIG
|
||||||
|
|
||||||
|
object LoreEditConfigUtil {
|
||||||
|
|
||||||
|
// Per edit type configs Path
|
||||||
|
const val IS_ENABLED = "enabled"
|
||||||
|
const val FIXED_COST = "fixed_cost"
|
||||||
|
const val PER_LINE_COST = "per_line_cost"
|
||||||
|
const val DO_CONSUME = "do_consume"
|
||||||
|
|
||||||
|
// Permission configs path
|
||||||
|
const val BOOK_PERMISSION_NEEDED = "lore_edit.book_and_quil.use_permission"
|
||||||
|
const val PAPER_PERMISSION_NEEDED = "lore_edit.paper.use_permission"
|
||||||
|
|
||||||
|
// Color configs path
|
||||||
|
const val ALLOW_COLOR_CODE = "allow_color_code"
|
||||||
|
const val ALLOW_HEX_COLOR = "allow_hexadecimal_color"
|
||||||
|
const val USE_COLOR_COST = "use_cost"
|
||||||
|
|
||||||
|
const val REMOVE_COLOR_ON_LORE_REMOVE = "remove_color_on_remove"
|
||||||
|
const val REMOVE_COLOR_COST = "remove_color_cost"
|
||||||
|
|
||||||
|
// Lore order config path
|
||||||
|
const val PAPER_EDIT_ORDER = "lore_edit.paper.order"
|
||||||
|
|
||||||
|
// --------------
|
||||||
|
// Default Values
|
||||||
|
// --------------
|
||||||
|
|
||||||
|
// Per edit type configs defaults
|
||||||
|
const val DEFAULT_IS_ENABLED = false
|
||||||
|
const val DEFAULT_FIXED_COST = 1
|
||||||
|
const val DEFAULT_PER_LINE_COST = 0
|
||||||
|
const val DEFAULT_DO_CONSUME = false
|
||||||
|
|
||||||
|
// Permission configs defaults
|
||||||
|
const val DEFAULT_BOOK_PERMISSION_NEEDED = true
|
||||||
|
const val DEFAULT_PAPER_PERMISSION_NEEDED = true
|
||||||
|
|
||||||
|
// Color configs defaults
|
||||||
|
const val DEFAULT_ALLOW_COLOR_CODE = true
|
||||||
|
const val DEFAULT_ALLOW_HEX_COLOR = true
|
||||||
|
const val DEFAULT_USE_COLOR_COST = 0
|
||||||
|
|
||||||
|
const val DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE = false
|
||||||
|
const val DEFAULT_REMOVE_COLOR_COST = 0
|
||||||
|
|
||||||
|
// Lore order config default
|
||||||
|
const val DEFAULT_PAPER_EDIT_ORDER = "end"
|
||||||
|
|
||||||
|
// -------------
|
||||||
|
// Config Ranges
|
||||||
|
// -------------
|
||||||
|
|
||||||
|
val FIXED_COST_RANGE = 0..1000
|
||||||
|
val PER_LINE_COST_RANGE = 0..1000
|
||||||
|
|
||||||
|
val USE_COLOR_COST_RANGE = 0..1000
|
||||||
|
val REMOVE_COLOR_COST_RANGE = 0..1000
|
||||||
|
|
||||||
|
// -------------------
|
||||||
|
// Generic Get methods
|
||||||
|
// -------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get if we should append/remove at the end or at the start of the lore list
|
||||||
|
* This may change to an "OrderType" enum or equivalent later
|
||||||
|
*/
|
||||||
|
val paperLoreOrderIsEnd: Boolean
|
||||||
|
get() {
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getString(PAPER_EDIT_ORDER, DEFAULT_PAPER_EDIT_ORDER)
|
||||||
|
.equals(DEFAULT_PAPER_EDIT_ORDER, ignoreCase = true)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If lore edit via book need permission
|
||||||
|
*/
|
||||||
|
val bookLoreEditNeedPermission: Boolean
|
||||||
|
get() {
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getBoolean(BOOK_PERMISSION_NEEDED, DEFAULT_BOOK_PERMISSION_NEEDED)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If lore edit via paper need permission
|
||||||
|
*/
|
||||||
|
val paperLoreEditNeedPermission: Boolean
|
||||||
|
get() {
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getBoolean(PAPER_PERMISSION_NEEDED, DEFAULT_PAPER_PERMISSION_NEEDED)
|
||||||
|
}
|
||||||
|
|
||||||
|
// -----------------
|
||||||
|
// Color Get methods
|
||||||
|
// -----------------
|
||||||
|
|
||||||
|
}
|
||||||
142
src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt
Normal file
142
src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
package xyz.alexcrea.cuanvil.util.config
|
||||||
|
|
||||||
|
import xyz.alexcrea.cuanvil.util.AnvilUseType
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.ALLOW_COLOR_CODE
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.ALLOW_HEX_COLOR
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_COLOR_CODE
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_HEX_COLOR
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_REMOVE_COLOR_COST
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_USE_COLOR_COST
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.REMOVE_COLOR_COST
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.REMOVE_COLOR_COST_RANGE
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.REMOVE_COLOR_ON_LORE_REMOVE
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.USE_COLOR_COST
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.USE_COLOR_COST_RANGE
|
||||||
|
import xyz.alexcrea.cuanvil.config.ConfigHolder.DEFAULT_CONFIG as CONFIG
|
||||||
|
|
||||||
|
enum class LoreEditType(
|
||||||
|
val rootPath: String,
|
||||||
|
val useType: AnvilUseType,
|
||||||
|
val isAppend: Boolean,
|
||||||
|
val isMultiLine: Boolean,
|
||||||
|
) {
|
||||||
|
APPEND_BOOK(AnvilUseType.LORE_EDIT_BOOK_APPEND, true, true),
|
||||||
|
REMOVE_BOOK(AnvilUseType.LORE_EDIT_BOOK_REMOVE, false, true),
|
||||||
|
APPEND_PAPER(AnvilUseType.LORE_EDIT_PAPER_APPEND, true, false),
|
||||||
|
REMOVE_PAPER(AnvilUseType.LORE_EDIT_PAPER_REMOVE, false, false),
|
||||||
|
;
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
useType: AnvilUseType,
|
||||||
|
isAppend: Boolean,
|
||||||
|
isMultiLine: Boolean,
|
||||||
|
) : this(useType.path, useType, isAppend, isMultiLine)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If this edit type is enabled
|
||||||
|
*/
|
||||||
|
val enabled: Boolean
|
||||||
|
get() {
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getBoolean("${rootPath}.${LoreEditConfigUtil.IS_ENABLED}", LoreEditConfigUtil.DEFAULT_IS_ENABLED)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed cost added to this edit
|
||||||
|
*/
|
||||||
|
val fixedCost: Int
|
||||||
|
get() {
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getInt("${rootPath}.${LoreEditConfigUtil.FIXED_COST}", LoreEditConfigUtil.DEFAULT_FIXED_COST)
|
||||||
|
.takeIf { it in LoreEditConfigUtil.FIXED_COST_RANGE }
|
||||||
|
?: LoreEditConfigUtil.DEFAULT_FIXED_COST
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cost added per line added
|
||||||
|
*/
|
||||||
|
val perLineCost: Int
|
||||||
|
get() {
|
||||||
|
if (!isMultiLine) throw IllegalStateException("Per line cost get on single line edit type")
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getInt("${rootPath}.${LoreEditConfigUtil.PER_LINE_COST}", LoreEditConfigUtil.DEFAULT_PER_LINE_COST)
|
||||||
|
.takeIf { it in LoreEditConfigUtil.PER_LINE_COST_RANGE }
|
||||||
|
?: LoreEditConfigUtil.DEFAULT_PER_LINE_COST
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the edit should consume the provided material
|
||||||
|
*/
|
||||||
|
val doConsume: Boolean
|
||||||
|
get() {
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getBoolean("${rootPath}.${LoreEditConfigUtil.DO_CONSUME}", LoreEditConfigUtil.DEFAULT_DO_CONSUME)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow usage of color code on lore add
|
||||||
|
*/
|
||||||
|
val allowColorCode: Boolean
|
||||||
|
get() {
|
||||||
|
if (!isAppend) throw IllegalStateException("Can only call with an append edit type")
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getBoolean("$rootPath.$ALLOW_COLOR_CODE", DEFAULT_ALLOW_COLOR_CODE)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow usage of hexadecimal color on lore add
|
||||||
|
*/
|
||||||
|
val allowHexColor: Boolean
|
||||||
|
get() {
|
||||||
|
if (!isAppend) throw IllegalStateException("Can only call with an append edit type")
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getBoolean("${rootPath}.$ALLOW_HEX_COLOR", DEFAULT_ALLOW_HEX_COLOR)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cost when using either color code and hex color on lore add
|
||||||
|
*/
|
||||||
|
val useColorCost: Int
|
||||||
|
get() {
|
||||||
|
if (!isAppend) throw IllegalStateException("Can only call with an append edit type")
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getInt("${rootPath}.$USE_COLOR_COST", DEFAULT_USE_COLOR_COST)
|
||||||
|
.takeIf { it in USE_COLOR_COST_RANGE }
|
||||||
|
?: DEFAULT_USE_COLOR_COST
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should the color code & hex color should get removed on lore remove
|
||||||
|
*/
|
||||||
|
val shouldRemoveColorOnLoreRemoval: Boolean
|
||||||
|
get() {
|
||||||
|
if (isAppend) throw IllegalStateException("Can only call with a remove edit type")
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getBoolean("${rootPath}.$REMOVE_COLOR_ON_LORE_REMOVE", DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cost when using either color code and hex color on lore remove
|
||||||
|
*/
|
||||||
|
val removeColorCost: Int
|
||||||
|
get() {
|
||||||
|
if (isAppend) throw IllegalStateException("Can only call with a remove edit type")
|
||||||
|
return CONFIG
|
||||||
|
.config
|
||||||
|
.getInt("${rootPath}.$REMOVE_COLOR_COST", DEFAULT_REMOVE_COLOR_COST)
|
||||||
|
.takeIf { it in REMOVE_COLOR_COST_RANGE }
|
||||||
|
?: DEFAULT_REMOVE_COLOR_COST
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -270,6 +270,91 @@ disable-merge-over:
|
||||||
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
# If uncommented. 2 unbreaking II book would not give an unbreaking III book. but unbreaking III book can still be applied
|
||||||
#minecraft:unbreaking: 2
|
#minecraft:unbreaking: 2
|
||||||
|
|
||||||
|
# Settings for lore modification
|
||||||
|
lore_edit:
|
||||||
|
book_and_quil:
|
||||||
|
# Permission is ca.lore_edit.book
|
||||||
|
use_permission: true
|
||||||
|
append:
|
||||||
|
# If adding lore using book & quil is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Cost used for every lore line added
|
||||||
|
per_line_cost: 0
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If adding the lore consume the book & quil
|
||||||
|
do_consume: false
|
||||||
|
# Allow using color code and hexadecimal color when editing lore via book & quil
|
||||||
|
#
|
||||||
|
# Color code are prefixed by "&" and hexadecimal color by "#"
|
||||||
|
# Color code will not be applied if it colors nothing. "&&" can be used to write "&"
|
||||||
|
allow_color_code: true
|
||||||
|
allow_hexadecimal_color: true
|
||||||
|
use_cost: 0
|
||||||
|
|
||||||
|
remove:
|
||||||
|
# If removing lore using book & quil is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Cost used for every lore line removed
|
||||||
|
per_line_cost: 0
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If removing the lore consume the book & quil
|
||||||
|
do_consume: false
|
||||||
|
# If the color should get back to color code or hex format
|
||||||
|
remove_color_on_remove: true
|
||||||
|
# Cost of replacing colors
|
||||||
|
remove_color_cost: 0
|
||||||
|
|
||||||
|
paper:
|
||||||
|
# Permission is ca.lore_edit.paper
|
||||||
|
use_permission: true
|
||||||
|
# what order should the lines should get added/removed (start/end, if invalid or not present will be end)
|
||||||
|
order: "end"
|
||||||
|
|
||||||
|
append_line:
|
||||||
|
# If adding lore line using paper is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If adding the lore line consume the paper
|
||||||
|
do_consume: false
|
||||||
|
# Allow using color code and hexadecimal color when editing lore via book & quil
|
||||||
|
#
|
||||||
|
# Color code are prefixed by "&" and hexadecimal color by "#"
|
||||||
|
# Color code will not be applied if it colors nothing. "&&" can be used to write "&"
|
||||||
|
allow_color_code: true
|
||||||
|
allow_hexadecimal_color: true
|
||||||
|
color_use_cost: 0
|
||||||
|
|
||||||
|
remove_line:
|
||||||
|
# If removing lore line using paper is enabled
|
||||||
|
enabled: false
|
||||||
|
# Cost used every time
|
||||||
|
fixed_cost: 1
|
||||||
|
# Use left item vanilla cost penalty if any
|
||||||
|
shared_increase: false
|
||||||
|
# Increase shared left item cost penalty
|
||||||
|
shared_additive: false
|
||||||
|
# If removing the lore line consume the paper
|
||||||
|
do_consume: false
|
||||||
|
# If the color should get back to color code or hex format
|
||||||
|
remove_color_on_remove: true
|
||||||
|
# Cost of replacing colors
|
||||||
|
remove_color_cost: 0
|
||||||
|
|
||||||
# Whether to show debug logging
|
# Whether to show debug logging
|
||||||
debug_log: false
|
debug_log: false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -42,13 +42,19 @@ permissions:
|
||||||
# color permissions
|
# color permissions
|
||||||
ca.color.code:
|
ca.color.code:
|
||||||
default: op
|
default: op
|
||||||
description: Allow player to use color code if permission is required (toggleable)
|
description: Allow player to use color code if enabled (toggleable)
|
||||||
ca.color.hex:
|
ca.color.hex:
|
||||||
default: op
|
default: op
|
||||||
description: Allow player to use hexadecimal color if permission is required (toggleable)
|
description: Allow player to use hexadecimal color if enabled (toggleable)
|
||||||
|
# lore edit permissions
|
||||||
|
ca.lore_edit.book:
|
||||||
|
default: op
|
||||||
|
description: Allow player to edit lore via book and quil if enabled (toggleable)
|
||||||
|
ca.lore_edit.paper:
|
||||||
|
default: op
|
||||||
|
description: Allow player to edit lore via paper if enabled (toggleable)
|
||||||
|
|
||||||
|
# soft depend on old name of this plugin (UnsafeEnchantsPlus), so I can disable it if it is on the same server
|
||||||
# soft depend on old name (UnsafeEnchantsPlus), so I can disable it if it is on the same server (old name for this plugin)
|
|
||||||
# Also depend to other plugin for compatibility
|
# Also depend to other plugin for compatibility
|
||||||
softdepend:
|
softdepend:
|
||||||
- UnsafeEnchantsPlus
|
- UnsafeEnchantsPlus
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ import org.mockbukkit.mockbukkit.entity.PlayerMock;
|
||||||
import org.mockbukkit.mockbukkit.inventory.ItemStackMock;
|
import org.mockbukkit.mockbukkit.inventory.ItemStackMock;
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||||
import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest;
|
import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest;
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilFuseTestData;
|
import xyz.alexcrea.cuanvil.data.AnvilFuseTestData;
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -88,16 +88,16 @@ public class EnchantmentUtilTests extends ConfigResetCustomAnvilTest {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test with no permission
|
// Test with no permission
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData);
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData2);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData2);
|
||||||
|
|
||||||
// Add permission
|
// Add permission
|
||||||
PermissionAttachment attachment = player.addAttachment(plugin);
|
PermissionAttachment attachment = player.addAttachment(plugin);
|
||||||
attachment.setPermission(permission, true);
|
attachment.setPermission(permission, true);
|
||||||
|
|
||||||
// Test with new permission
|
// Test with new permission
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData);
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData2);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -161,24 +161,24 @@ public class EnchantmentUtilTests extends ConfigResetCustomAnvilTest {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Test failing result first
|
// Test failing result first
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData2);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData2);
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData3);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData3);
|
||||||
|
|
||||||
// Test working sharpness 2
|
// Test working sharpness 2
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData);
|
||||||
|
|
||||||
// Set merge limit to 2 & test
|
// Set merge limit to 2 & test
|
||||||
ConfigHolder.DEFAULT_CONFIG.getConfig().set("disable-merge-over.minecraft:sharpness", 1);
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set("disable-merge-over.minecraft:sharpness", 1);
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData);
|
||||||
|
|
||||||
// Add permission
|
// Add permission
|
||||||
PermissionAttachment attachment = player.addAttachment(plugin);
|
PermissionAttachment attachment = player.addAttachment(plugin);
|
||||||
attachment.setPermission(permission, true);
|
attachment.setPermission(permission, true);
|
||||||
|
|
||||||
// Test working sharpness 2
|
// Test working sharpness 2
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData);
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData2);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData2);
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData3);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData3);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import org.bukkit.inventory.Inventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
import org.bukkit.inventory.meta.Repairable;
|
import org.bukkit.inventory.meta.Repairable;
|
||||||
import org.eclipse.aether.util.ConfigUtils;
|
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.BeforeAll;
|
import org.junit.jupiter.api.BeforeAll;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
|
@ -17,7 +16,7 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.mockbukkit.mockbukkit.entity.PlayerMock;
|
import org.mockbukkit.mockbukkit.entity.PlayerMock;
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||||
import xyz.alexcrea.cuanvil.tests.SharedCustomAnvilTest;
|
import xyz.alexcrea.cuanvil.tests.SharedCustomAnvilTest;
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilFuseTestData;
|
import xyz.alexcrea.cuanvil.data.AnvilFuseTestData;
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
||||||
import xyz.alexcrea.cuanvil.util.CommonItemUtil;
|
import xyz.alexcrea.cuanvil.util.CommonItemUtil;
|
||||||
|
|
||||||
|
|
@ -68,7 +67,7 @@ public class AnvilFuseTests extends SharedCustomAnvilTest {
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, data);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -88,7 +87,7 @@ public class AnvilFuseTests extends SharedCustomAnvilTest {
|
||||||
5
|
5
|
||||||
);
|
);
|
||||||
|
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, data);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -102,7 +101,7 @@ public class AnvilFuseTests extends SharedCustomAnvilTest {
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, data);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note: currently anvil can only have null name. maybe handle differently later
|
// Note: currently anvil can only have null name. maybe handle differently later
|
||||||
|
|
@ -121,7 +120,7 @@ public class AnvilFuseTests extends SharedCustomAnvilTest {
|
||||||
1, 1, null
|
1, 1, null
|
||||||
);
|
);
|
||||||
|
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, data);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
623
src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java
Normal file
623
src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java
Normal file
|
|
@ -0,0 +1,623 @@
|
||||||
|
package xyz.alexcrea.cuanvil.anvil;
|
||||||
|
|
||||||
|
import io.delilaheve.util.ConfigOptions;
|
||||||
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.inventory.InventoryType;
|
||||||
|
import org.bukkit.inventory.AnvilInventory;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.bukkit.inventory.meta.BookMeta;
|
||||||
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.junit.jupiter.api.*;
|
||||||
|
import org.junit.jupiter.params.ParameterizedTest;
|
||||||
|
import org.junit.jupiter.params.provider.EnumSource;
|
||||||
|
import org.junit.jupiter.params.provider.MethodSource;
|
||||||
|
import org.junit.jupiter.params.provider.ValueSource;
|
||||||
|
import org.mockbukkit.mockbukkit.entity.PlayerMock;
|
||||||
|
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||||
|
import xyz.alexcrea.cuanvil.data.AnvilClickTestData;
|
||||||
|
import xyz.alexcrea.cuanvil.data.AnvilFuseTestData;
|
||||||
|
import xyz.alexcrea.cuanvil.data.TestDataContainer;
|
||||||
|
import xyz.alexcrea.cuanvil.tests.SharedCustomAnvilTest;
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil;
|
||||||
|
import xyz.alexcrea.cuanvil.util.config.LoreEditType;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class LoreEditTests extends SharedCustomAnvilTest {
|
||||||
|
|
||||||
|
private static AnvilInventory anvil;
|
||||||
|
private static PlayerMock player;
|
||||||
|
|
||||||
|
private static final String COLORED_LORE_LINE = "§x§1§2§3§4§5§6TEST §atest";
|
||||||
|
private static final String UNCOLORED_LORE_LINE = "#123456TEST &atest";
|
||||||
|
|
||||||
|
private static final int COLOR_USE_COST = 1;
|
||||||
|
private static final int COLOR_REMOVE_COST = 2;
|
||||||
|
private static final int NON_ONE_TEST_FIXED_COST = 10;
|
||||||
|
private static final int NON_ZERO_TEST_LINE_COST = 2;
|
||||||
|
|
||||||
|
private static ItemStack emptyItem;
|
||||||
|
private static ItemStack oneColoredLoreItem;
|
||||||
|
private static ItemStack twoColoredLoreItem;
|
||||||
|
private static ItemStack oneUncoloredLoreItem;
|
||||||
|
private static ItemStack twoUncoloredLoreItem;
|
||||||
|
|
||||||
|
private static ItemStack emptyPaperStack;
|
||||||
|
private static ItemStack emptyPaper63Item;
|
||||||
|
private static ItemStack emptyPaperOne;
|
||||||
|
private static ItemStack coloredPaperStack;
|
||||||
|
private static ItemStack coloredPaper63Item;
|
||||||
|
private static ItemStack coloredPaperOne;
|
||||||
|
private static ItemStack uncoloredPaperStack;
|
||||||
|
private static ItemStack uncoloredPaper63Item;
|
||||||
|
private static ItemStack uncoloredPaperOne;
|
||||||
|
|
||||||
|
private static ItemStack emptyBook;
|
||||||
|
private static ItemStack coloredBook1Line;
|
||||||
|
private static ItemStack coloredBook2Line;
|
||||||
|
private static ItemStack uncoloredBook1Line;
|
||||||
|
private static ItemStack uncoloredBook2Line;
|
||||||
|
|
||||||
|
private static TestDataContainer defBookAppend;
|
||||||
|
private static TestDataContainer defBookRemove;
|
||||||
|
|
||||||
|
private static TestDataContainer defPaperAppend;
|
||||||
|
private static TestDataContainer defPaperRemove;
|
||||||
|
|
||||||
|
private static TestDataContainer defMultilineBookAppend;
|
||||||
|
private static TestDataContainer defMultilineBookRemove;
|
||||||
|
|
||||||
|
private static TestDataContainer defMultilinePaperAppend;
|
||||||
|
private static TestDataContainer defMultilinePaperRemove;
|
||||||
|
|
||||||
|
private static Map<LoreEditType, TestDataContainer> singleLineTypeToTest;
|
||||||
|
private static Map<LoreEditType, TestDataContainer> multiLineTypeToTest;
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
public static void setUp() {
|
||||||
|
// Mock used player & open anvil
|
||||||
|
player = server.addPlayer();
|
||||||
|
|
||||||
|
Inventory anvil = server.createInventory(player, InventoryType.ANVIL);
|
||||||
|
|
||||||
|
LoreEditTests.anvil = (AnvilInventory) anvil;
|
||||||
|
player.openInventory(anvil);
|
||||||
|
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(ConfigOptions.DEBUG_LOGGING, true);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(ConfigOptions.VERBOSE_DEBUG_LOGGING, true);
|
||||||
|
|
||||||
|
// Applied item
|
||||||
|
ItemStack item = new ItemStack(Material.STICK, 33);
|
||||||
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
ArrayList<String> lore = new ArrayList<>();
|
||||||
|
|
||||||
|
emptyItem = item.clone();
|
||||||
|
|
||||||
|
lore.add(COLORED_LORE_LINE);
|
||||||
|
meta.setLore(lore);
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
oneColoredLoreItem = item.clone();
|
||||||
|
|
||||||
|
lore.add(COLORED_LORE_LINE);
|
||||||
|
meta.setLore(lore);
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
twoColoredLoreItem = item.clone();
|
||||||
|
|
||||||
|
lore.clear();
|
||||||
|
lore.add(UNCOLORED_LORE_LINE);
|
||||||
|
meta.setLore(lore);
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
oneUncoloredLoreItem = item.clone();
|
||||||
|
|
||||||
|
lore.add(UNCOLORED_LORE_LINE);
|
||||||
|
meta.setLore(lore);
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
twoUncoloredLoreItem = item.clone();
|
||||||
|
lore.clear();
|
||||||
|
|
||||||
|
// Paper items
|
||||||
|
item = new ItemStack(Material.PAPER, 64);
|
||||||
|
meta = item.getItemMeta();
|
||||||
|
emptyPaperStack = item.clone();
|
||||||
|
item.setAmount(63);
|
||||||
|
emptyPaper63Item = item.clone();
|
||||||
|
item.setAmount(1);
|
||||||
|
emptyPaperOne = item.clone();
|
||||||
|
|
||||||
|
item.setAmount(64);
|
||||||
|
meta.setDisplayName(COLORED_LORE_LINE);
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
coloredPaperStack = item.clone();
|
||||||
|
item.setAmount(63);
|
||||||
|
coloredPaper63Item = item.clone();
|
||||||
|
item.setAmount(1);
|
||||||
|
coloredPaperOne = item.clone();
|
||||||
|
|
||||||
|
item.setAmount(64);
|
||||||
|
meta.setDisplayName(UNCOLORED_LORE_LINE);
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
uncoloredPaperStack = item.clone();
|
||||||
|
item.setAmount(63);
|
||||||
|
uncoloredPaper63Item = item.clone();
|
||||||
|
item.setAmount(1);
|
||||||
|
uncoloredPaperOne = item.clone();
|
||||||
|
|
||||||
|
// Book items
|
||||||
|
item = new ItemStack(Material.WRITABLE_BOOK);
|
||||||
|
BookMeta bookmeta = (BookMeta) item.getItemMeta();
|
||||||
|
emptyBook = item.clone();
|
||||||
|
|
||||||
|
bookmeta.setPages(COLORED_LORE_LINE);
|
||||||
|
item.setItemMeta(bookmeta);
|
||||||
|
coloredBook1Line = item.clone();
|
||||||
|
|
||||||
|
bookmeta.setPages(COLORED_LORE_LINE + "\n" + COLORED_LORE_LINE);
|
||||||
|
item.setItemMeta(bookmeta);
|
||||||
|
coloredBook2Line = item.clone();
|
||||||
|
|
||||||
|
bookmeta.setPages(UNCOLORED_LORE_LINE);
|
||||||
|
item.setItemMeta(bookmeta);
|
||||||
|
uncoloredBook1Line = item.clone();
|
||||||
|
|
||||||
|
bookmeta.setPages(UNCOLORED_LORE_LINE + "\n" + UNCOLORED_LORE_LINE);
|
||||||
|
item.setItemMeta(bookmeta);
|
||||||
|
uncoloredBook2Line = item.clone();
|
||||||
|
|
||||||
|
// Default working test data
|
||||||
|
defBookAppend = new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
emptyItem, uncoloredBook1Line,
|
||||||
|
oneColoredLoreItem,
|
||||||
|
1
|
||||||
|
), new AnvilClickTestData(
|
||||||
|
null, emptyBook, null, oneColoredLoreItem,
|
||||||
|
1, Event.Result.DENY,
|
||||||
|
true, Event.Result.DENY
|
||||||
|
));
|
||||||
|
|
||||||
|
defBookRemove = new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
oneColoredLoreItem, emptyBook,
|
||||||
|
emptyItem,
|
||||||
|
1
|
||||||
|
), new AnvilClickTestData(
|
||||||
|
null, coloredBook1Line, null, emptyItem,
|
||||||
|
1, Event.Result.DENY,
|
||||||
|
true, Event.Result.DENY
|
||||||
|
));
|
||||||
|
|
||||||
|
defPaperAppend = new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
emptyItem, uncoloredPaperStack,
|
||||||
|
oneColoredLoreItem,
|
||||||
|
1
|
||||||
|
), new AnvilClickTestData(
|
||||||
|
emptyPaperOne, uncoloredPaper63Item, null, oneColoredLoreItem,
|
||||||
|
1, Event.Result.DENY,
|
||||||
|
true, Event.Result.DENY
|
||||||
|
));
|
||||||
|
|
||||||
|
defPaperRemove = new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
oneColoredLoreItem, emptyPaperStack,
|
||||||
|
emptyItem,
|
||||||
|
1
|
||||||
|
), new AnvilClickTestData(
|
||||||
|
coloredPaperOne, emptyPaper63Item, null, emptyItem,
|
||||||
|
1, Event.Result.DENY,
|
||||||
|
true, Event.Result.DENY
|
||||||
|
));
|
||||||
|
defMultilineBookAppend = new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
emptyItem, uncoloredBook2Line,
|
||||||
|
twoColoredLoreItem,
|
||||||
|
1
|
||||||
|
), new AnvilClickTestData(
|
||||||
|
null, emptyBook, null, twoColoredLoreItem,
|
||||||
|
1, Event.Result.DENY,
|
||||||
|
true, Event.Result.DENY
|
||||||
|
));
|
||||||
|
|
||||||
|
defMultilineBookRemove = new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
twoColoredLoreItem, emptyBook,
|
||||||
|
emptyItem,
|
||||||
|
1
|
||||||
|
), new AnvilClickTestData(
|
||||||
|
null, coloredBook2Line, null, emptyItem,
|
||||||
|
1, Event.Result.DENY,
|
||||||
|
true, Event.Result.DENY
|
||||||
|
));
|
||||||
|
|
||||||
|
defMultilinePaperAppend = new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
oneColoredLoreItem, uncoloredPaperStack,
|
||||||
|
twoColoredLoreItem,
|
||||||
|
1
|
||||||
|
), new AnvilClickTestData(
|
||||||
|
emptyPaperOne, uncoloredPaper63Item, null, twoColoredLoreItem,
|
||||||
|
1, Event.Result.DENY,
|
||||||
|
true, Event.Result.DENY
|
||||||
|
));
|
||||||
|
|
||||||
|
defMultilinePaperRemove = new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
twoColoredLoreItem, emptyPaperStack,
|
||||||
|
oneColoredLoreItem,
|
||||||
|
1
|
||||||
|
), new AnvilClickTestData(
|
||||||
|
coloredPaperOne, emptyPaper63Item, null, oneColoredLoreItem,
|
||||||
|
1, Event.Result.DENY,
|
||||||
|
true, Event.Result.DENY
|
||||||
|
));
|
||||||
|
|
||||||
|
singleLineTypeToTest = Map.of(
|
||||||
|
LoreEditType.APPEND_BOOK, defBookAppend,
|
||||||
|
LoreEditType.REMOVE_BOOK, defBookRemove,
|
||||||
|
LoreEditType.APPEND_PAPER, defPaperAppend,
|
||||||
|
LoreEditType.REMOVE_PAPER, defPaperRemove
|
||||||
|
);
|
||||||
|
|
||||||
|
multiLineTypeToTest = Map.of(
|
||||||
|
LoreEditType.APPEND_BOOK, defMultilineBookAppend,
|
||||||
|
LoreEditType.REMOVE_BOOK, defMultilineBookRemove,
|
||||||
|
LoreEditType.APPEND_PAPER, defMultilinePaperAppend,
|
||||||
|
LoreEditType.REMOVE_PAPER, defMultilinePaperRemove
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void prepareAnvil() {
|
||||||
|
anvil.clear();
|
||||||
|
|
||||||
|
// Make sure we reset value in case it got modified
|
||||||
|
for (@NotNull LoreEditType type : LoreEditType.values()) {
|
||||||
|
// Make sure it is enabled for the tests (unless its is enabled test)
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.IS_ENABLED, true);
|
||||||
|
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.DO_CONSUME, false);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.FIXED_COST, 1);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.PER_LINE_COST, 0);
|
||||||
|
|
||||||
|
// Make sur color is enabled by default
|
||||||
|
if (type.isAppend()) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_HEX_COLOR, true);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_COLOR_CODE, true);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.USE_COLOR_COST, 0);
|
||||||
|
} else {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_ON_LORE_REMOVE, false);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_COST, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disable them by default and test them on specific tests
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.BOOK_PERMISSION_NEEDED, false);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_PERMISSION_NEEDED, false);
|
||||||
|
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_EDIT_ORDER, LoreEditConfigUtil.DEFAULT_PAPER_EDIT_ORDER);
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
public static void tearDown() {
|
||||||
|
player = null;
|
||||||
|
anvil = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ItemStack uncoloredEquivalent(@Nullable ItemStack colored) {
|
||||||
|
// null check
|
||||||
|
if (null == colored) return null;
|
||||||
|
|
||||||
|
if (oneColoredLoreItem == colored) return oneUncoloredLoreItem;
|
||||||
|
if (twoColoredLoreItem == colored) return twoUncoloredLoreItem;
|
||||||
|
|
||||||
|
if (coloredPaperStack == colored) return uncoloredPaperStack;
|
||||||
|
if (coloredPaper63Item == colored) return uncoloredPaper63Item;
|
||||||
|
if (coloredPaperOne == colored) return uncoloredPaperOne;
|
||||||
|
|
||||||
|
if (coloredBook1Line == colored) return uncoloredBook1Line;
|
||||||
|
if (coloredBook2Line == colored) return uncoloredBook2Line;
|
||||||
|
|
||||||
|
// They already are uncolored
|
||||||
|
if (oneUncoloredLoreItem == colored) return oneUncoloredLoreItem;
|
||||||
|
if (twoUncoloredLoreItem == colored) return twoUncoloredLoreItem;
|
||||||
|
|
||||||
|
if (uncoloredPaperStack == colored) return uncoloredPaperStack;
|
||||||
|
if (uncoloredPaper63Item == colored) return uncoloredPaper63Item;
|
||||||
|
if (uncoloredPaperOne == colored) return uncoloredPaperOne;
|
||||||
|
|
||||||
|
if (uncoloredBook1Line == colored) return uncoloredBook1Line;
|
||||||
|
if (uncoloredBook2Line == colored) return uncoloredBook2Line;
|
||||||
|
|
||||||
|
// No lore items return themself
|
||||||
|
if (emptyItem == colored) return emptyItem;
|
||||||
|
if (emptyBook == colored) return emptyBook;
|
||||||
|
if (emptyPaperStack == colored) return emptyPaperStack;
|
||||||
|
if (emptyPaper63Item == colored) return emptyPaper63Item;
|
||||||
|
if (emptyPaperOne == colored) return emptyPaperOne;
|
||||||
|
|
||||||
|
Assertions.fail("Could not find uncolored version of " + colored);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<LoreEditType> onlyAppendTypes() {
|
||||||
|
ArrayList<LoreEditType> typeList = new ArrayList<>();
|
||||||
|
for (@NotNull LoreEditType type : LoreEditType.values()) {
|
||||||
|
if (type.isAppend()) typeList.add(type);
|
||||||
|
}
|
||||||
|
return typeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<LoreEditType> onlyRemoveTypes() {
|
||||||
|
ArrayList<LoreEditType> typeList = new ArrayList<>();
|
||||||
|
for (@NotNull LoreEditType type : LoreEditType.values()) {
|
||||||
|
if (!type.isAppend()) typeList.add(type);
|
||||||
|
}
|
||||||
|
return typeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void simpleTest() {
|
||||||
|
// Test all defaults to make sure they works
|
||||||
|
for (LoreEditType type : LoreEditType.values()) {
|
||||||
|
singleLineTypeToTest.get(type).executeTest(anvil, player);
|
||||||
|
multiLineTypeToTest.get(type).executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(LoreEditType.class)
|
||||||
|
public void testPermissionNeeded_DEOP(LoreEditType type) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.BOOK_PERMISSION_NEEDED, true);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_PERMISSION_NEEDED, true);
|
||||||
|
player.setOp(false);
|
||||||
|
|
||||||
|
singleLineTypeToTest.get(type).nullifyResult().executeTest(anvil, player);
|
||||||
|
multiLineTypeToTest.get(type).nullifyResult().executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(LoreEditType.class)
|
||||||
|
public void testPermissionNeeded_OP(LoreEditType type) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.BOOK_PERMISSION_NEEDED, true);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_PERMISSION_NEEDED, true);
|
||||||
|
player.setOp(true);
|
||||||
|
|
||||||
|
singleLineTypeToTest.get(type).executeTest(anvil, player);
|
||||||
|
multiLineTypeToTest.get(type).executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(LoreEditType.class)
|
||||||
|
public void testLoreTypeDisabled(LoreEditType type) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.IS_ENABLED, false);
|
||||||
|
|
||||||
|
singleLineTypeToTest.get(type).nullifyResult().executeTest(anvil, player);
|
||||||
|
multiLineTypeToTest.get(type).nullifyResult().executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(LoreEditType.class)
|
||||||
|
public void testFixedCost_Default(LoreEditType type) {
|
||||||
|
singleLineTypeToTest.get(type).setCost(1).executeTest(anvil, player);
|
||||||
|
multiLineTypeToTest.get(type).setCost(1).executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(LoreEditType.class)
|
||||||
|
public void testFixedCost_Modified(LoreEditType type) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.FIXED_COST, NON_ONE_TEST_FIXED_COST);
|
||||||
|
|
||||||
|
singleLineTypeToTest.get(type).setCost(NON_ONE_TEST_FIXED_COST).executeTest(anvil, player);
|
||||||
|
multiLineTypeToTest.get(type).setCost(NON_ONE_TEST_FIXED_COST).executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(LoreEditType.class)
|
||||||
|
public void testLineCost_Modified(LoreEditType type) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.PER_LINE_COST, NON_ZERO_TEST_LINE_COST);
|
||||||
|
|
||||||
|
if (type.isMultiLine()) {
|
||||||
|
singleLineTypeToTest.get(type).setCost(NON_ZERO_TEST_LINE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST).executeTest(anvil, player);
|
||||||
|
multiLineTypeToTest.get(type).setCost(2 * NON_ZERO_TEST_LINE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST).executeTest(anvil, player);
|
||||||
|
} else {
|
||||||
|
singleLineTypeToTest.get(type).executeTest(anvil, player);
|
||||||
|
multiLineTypeToTest.get(type).executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@EnumSource(LoreEditType.class)
|
||||||
|
public void testColorCost(LoreEditType type) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.USE_COLOR_COST, COLOR_USE_COST);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_COST, COLOR_REMOVE_COST);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_ON_LORE_REMOVE, true);
|
||||||
|
|
||||||
|
TestDataContainer singleLData = singleLineTypeToTest.get(type);
|
||||||
|
TestDataContainer multiLData = multiLineTypeToTest.get(type);
|
||||||
|
|
||||||
|
if (type.isAppend()) {
|
||||||
|
singleLData.setCost(COLOR_USE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST).executeTest(anvil, player);
|
||||||
|
multiLData.setCost(COLOR_USE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST).executeTest(anvil, player);
|
||||||
|
} else {
|
||||||
|
singleLData
|
||||||
|
.setCost(COLOR_REMOVE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST)
|
||||||
|
.setClickRight(uncoloredEquivalent(singleLData.getRightClick()))
|
||||||
|
.setClickLeft(uncoloredEquivalent(singleLData.getLeftClick()))
|
||||||
|
.executeTest(anvil, player);
|
||||||
|
|
||||||
|
multiLData.setCost(COLOR_REMOVE_COST + LoreEditConfigUtil.DEFAULT_FIXED_COST)
|
||||||
|
.setClickRight(uncoloredEquivalent(multiLData.getRightClick()))
|
||||||
|
.setClickLeft(uncoloredEquivalent(multiLData.getLeftClick()))
|
||||||
|
.executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("onlyAppendTypes")
|
||||||
|
public void testColorDisabled(LoreEditType type) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.USE_COLOR_COST, COLOR_USE_COST);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_HEX_COLOR, false);
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_COLOR_CODE, false);
|
||||||
|
|
||||||
|
TestDataContainer singleLData = singleLineTypeToTest.get(type);
|
||||||
|
TestDataContainer multiLData = multiLineTypeToTest.get(type);
|
||||||
|
|
||||||
|
singleLData
|
||||||
|
.setExpectedResult(uncoloredEquivalent(singleLData.getExpectedFuse()))
|
||||||
|
.executeTest(anvil, player);
|
||||||
|
multiLData
|
||||||
|
.setFuseLeft(uncoloredEquivalent(multiLData.getLeftFuse()))
|
||||||
|
.setExpectedResult(uncoloredEquivalent(multiLData.getExpectedFuse()))
|
||||||
|
.executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("onlyRemoveTypes")
|
||||||
|
public void testColorRemoveEnabled(LoreEditType type) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_ON_LORE_REMOVE, true);
|
||||||
|
|
||||||
|
TestDataContainer singleLData = singleLineTypeToTest.get(type);
|
||||||
|
TestDataContainer multiLData = multiLineTypeToTest.get(type);
|
||||||
|
|
||||||
|
singleLData
|
||||||
|
.setClickRight(uncoloredEquivalent(singleLData.getRightClick()))
|
||||||
|
.setClickLeft(uncoloredEquivalent(singleLData.getLeftClick()))
|
||||||
|
.executeTest(anvil, player);
|
||||||
|
multiLData
|
||||||
|
.setClickRight(uncoloredEquivalent(multiLData.getRightClick()))
|
||||||
|
.setClickLeft(uncoloredEquivalent(multiLData.getLeftClick()))
|
||||||
|
.executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@MethodSource("onlyRemoveTypes")
|
||||||
|
public void testDoConsume(LoreEditType type) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.DO_CONSUME, true);
|
||||||
|
|
||||||
|
TestDataContainer singleLData = singleLineTypeToTest.get(type);
|
||||||
|
TestDataContainer multiLData = multiLineTypeToTest.get(type);
|
||||||
|
|
||||||
|
// NOTE: we set to null right item only on multi line bc the default data has more than one paper and would go to the left instead
|
||||||
|
singleLData = singleLData
|
||||||
|
.setClickRight(type.isMultiLine() ? null : singleLData.getRightClick())
|
||||||
|
.setClickLeft(null);
|
||||||
|
singleLData.executeTest(anvil, player);
|
||||||
|
multiLData = multiLData
|
||||||
|
.setClickRight(type.isMultiLine() ? null : singleLData.getRightClick())
|
||||||
|
.setClickLeft(null);
|
||||||
|
multiLData.executeTest(anvil, player);
|
||||||
|
|
||||||
|
// Single paper consumed
|
||||||
|
if (!type.isMultiLine()) {
|
||||||
|
singleLData.setFuseRight(emptyPaperOne).setClickRight(null).executeTest(anvil, player);
|
||||||
|
multiLData.setFuseRight(emptyPaperOne).setClickRight(null).executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SinglePaperTestPart(LoreEditType type, TestDataContainer data, ItemStack expectedFuse, ItemStack postFuse) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.DO_CONSUME, false);
|
||||||
|
data = data.setFuseRight(expectedFuse).setClickLeft(null).setClickRight(postFuse);
|
||||||
|
data.executeTest(anvil, player);
|
||||||
|
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.DO_CONSUME, true);
|
||||||
|
data.setClickRight(null).executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePaper_Append() {
|
||||||
|
SinglePaperTestPart(LoreEditType.APPEND_PAPER,
|
||||||
|
singleLineTypeToTest.get(LoreEditType.APPEND_PAPER),
|
||||||
|
uncoloredPaperOne, emptyPaperOne);
|
||||||
|
SinglePaperTestPart(LoreEditType.APPEND_PAPER,
|
||||||
|
multiLineTypeToTest.get(LoreEditType.APPEND_PAPER),
|
||||||
|
uncoloredPaperOne, emptyPaperOne);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSinglePaper_Remove() {
|
||||||
|
SinglePaperTestPart(LoreEditType.REMOVE_PAPER,
|
||||||
|
singleLineTypeToTest.get(LoreEditType.REMOVE_PAPER),
|
||||||
|
emptyPaperOne, coloredPaperOne);
|
||||||
|
SinglePaperTestPart(LoreEditType.REMOVE_PAPER,
|
||||||
|
multiLineTypeToTest.get(LoreEditType.REMOVE_PAPER),
|
||||||
|
emptyPaperOne, coloredPaperOne);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static ItemStack insertToLore(@NotNull ItemStack item, int index, @NotNull String toAppend) {
|
||||||
|
item = item.clone();
|
||||||
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
Assertions.assertNotNull(meta);
|
||||||
|
Assertions.assertTrue(meta.hasLore());
|
||||||
|
|
||||||
|
ArrayList<String> lore = new ArrayList<>(meta.getLore());
|
||||||
|
lore.add(index, toAppend);
|
||||||
|
|
||||||
|
meta.setLore(lore);
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static ItemStack setDisplayedName(@NotNull ItemStack item, @NotNull String name) {
|
||||||
|
item = item.clone();
|
||||||
|
ItemMeta meta = item.getItemMeta();
|
||||||
|
Assertions.assertNotNull(meta);
|
||||||
|
|
||||||
|
meta.setDisplayName(name);
|
||||||
|
item.setItemMeta(meta);
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String TESTED_LORE = "tested_lore";
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = {"sTaRt", "eNd"})
|
||||||
|
public void testPaperOrder_Append(String order) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_EDIT_ORDER, order);
|
||||||
|
|
||||||
|
ItemStack result = insertToLore(oneColoredLoreItem, "start".equalsIgnoreCase(order) ? 0 : 1, TESTED_LORE);
|
||||||
|
ItemStack paper = setDisplayedName(emptyPaperOne, TESTED_LORE);
|
||||||
|
|
||||||
|
new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
oneColoredLoreItem, paper, result, 1
|
||||||
|
),
|
||||||
|
new AnvilClickTestData(
|
||||||
|
null, emptyPaperOne, null, result,
|
||||||
|
1,
|
||||||
|
Event.Result.DENY, true, Event.Result.DENY
|
||||||
|
)
|
||||||
|
).executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ParameterizedTest
|
||||||
|
@ValueSource(strings = {"sTaRt", "eNd"})
|
||||||
|
public void testPaperOrder_Remove(String order) {
|
||||||
|
ConfigHolder.DEFAULT_CONFIG.getConfig().set(LoreEditConfigUtil.PAPER_EDIT_ORDER, order);
|
||||||
|
|
||||||
|
ItemStack from = insertToLore(oneColoredLoreItem, "start".equalsIgnoreCase(order) ? 0 : 1, TESTED_LORE);
|
||||||
|
ItemStack paper = setDisplayedName(emptyPaperOne, TESTED_LORE);
|
||||||
|
|
||||||
|
new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
from, emptyPaperOne, oneColoredLoreItem, 1
|
||||||
|
),
|
||||||
|
new AnvilClickTestData(
|
||||||
|
null, paper, null, oneColoredLoreItem,
|
||||||
|
1,
|
||||||
|
Event.Result.DENY, true, Event.Result.DENY
|
||||||
|
)
|
||||||
|
).executeTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO work penalty test
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -16,7 +16,7 @@ import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
||||||
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
|
import xyz.alexcrea.cuanvil.group.EnchantConflictGroup;
|
||||||
import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest;
|
import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest;
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilFuseTestData;
|
import xyz.alexcrea.cuanvil.data.AnvilFuseTestData;
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
||||||
import xyz.alexcrea.cuanvil.util.CommonItemUtil;
|
import xyz.alexcrea.cuanvil.util.CommonItemUtil;
|
||||||
|
|
||||||
|
|
@ -71,7 +71,7 @@ public class ConflictApiTests extends ConfigResetCustomAnvilTest {
|
||||||
Assertions.assertNotNull(sharpness);
|
Assertions.assertNotNull(sharpness);
|
||||||
|
|
||||||
// Testing default conflict (illegal item should not be produced)
|
// Testing default conflict (illegal item should not be produced)
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData);
|
||||||
|
|
||||||
// Try to find & remove conflict
|
// Try to find & remove conflict
|
||||||
EnchantConflictGroup conflict = findGroup("sword_enchant_conflict");
|
EnchantConflictGroup conflict = findGroup("sword_enchant_conflict");
|
||||||
|
|
@ -79,7 +79,7 @@ public class ConflictApiTests extends ConfigResetCustomAnvilTest {
|
||||||
|
|
||||||
// Test what happen when we remove the conflict (illegal item should be allowed)
|
// Test what happen when we remove the conflict (illegal item should be allowed)
|
||||||
ConflictAPI.removeConflict(conflict);
|
ConflictAPI.removeConflict(conflict);
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData);
|
||||||
|
|
||||||
// We create and add a new conflict
|
// We create and add a new conflict
|
||||||
ConflictBuilder builder = new ConflictBuilder("sword_enchant_conflict");
|
ConflictBuilder builder = new ConflictBuilder("sword_enchant_conflict");
|
||||||
|
|
@ -88,11 +88,11 @@ public class ConflictApiTests extends ConfigResetCustomAnvilTest {
|
||||||
|
|
||||||
// Nothing should change as it is not new: it was previously deleted
|
// Nothing should change as it is not new: it was previously deleted
|
||||||
Assertions.assertFalse(builder.registerIfNew());
|
Assertions.assertFalse(builder.registerIfNew());
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData);
|
||||||
|
|
||||||
// Now the conflict should be registered and conflict should exist
|
// Now the conflict should be registered and conflict should exist
|
||||||
Assertions.assertTrue(builder.registerIfAbsent());
|
Assertions.assertTrue(builder.registerIfAbsent());
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import org.mockbukkit.mockbukkit.inventory.ItemStackMock;
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||||
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe;
|
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe;
|
||||||
import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest;
|
import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest;
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilFuseTestData;
|
import xyz.alexcrea.cuanvil.data.AnvilFuseTestData;
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
@ -57,14 +57,14 @@ public class CustomAnvilRecipeApiTests extends ConfigResetCustomAnvilTest {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Testing default conflict (no recipe exist)
|
// Testing default conflict (no recipe exist)
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData);
|
||||||
|
|
||||||
// Add and test recipe
|
// Add and test recipe
|
||||||
AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName);
|
AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName);
|
||||||
builder.setExactCount(true).setLeftItem(stick).setResultItem(stick).setXpCostPerCraft(2);
|
builder.setExactCount(true).setLeftItem(stick).setResultItem(stick).setXpCostPerCraft(2);
|
||||||
|
|
||||||
assertTrue(builder.registerIfAbsent());
|
assertTrue(builder.registerIfAbsent());
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData);
|
||||||
|
|
||||||
AnvilCustomRecipe recipe = getByName(recipeName);
|
AnvilCustomRecipe recipe = getByName(recipeName);
|
||||||
assertNotNull(recipe);
|
assertNotNull(recipe);
|
||||||
|
|
@ -72,21 +72,21 @@ public class CustomAnvilRecipeApiTests extends ConfigResetCustomAnvilTest {
|
||||||
// Remove recipe
|
// Remove recipe
|
||||||
assertTrue(CustomAnvilRecipeApi.removeRecipe(recipe));
|
assertTrue(CustomAnvilRecipeApi.removeRecipe(recipe));
|
||||||
assertFalse(CustomAnvilRecipeApi.removeRecipe(recipe));
|
assertFalse(CustomAnvilRecipeApi.removeRecipe(recipe));
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData);
|
||||||
|
|
||||||
recipe = getByName(recipeName);
|
recipe = getByName(recipeName);
|
||||||
assertNull(recipe);
|
assertNull(recipe);
|
||||||
|
|
||||||
// Try to add deleted recipe with no override (should not add)
|
// Try to add deleted recipe with no override (should not add)
|
||||||
assertFalse(CustomAnvilRecipeApi.addRecipe(builder, false));
|
assertFalse(CustomAnvilRecipeApi.addRecipe(builder, false));
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData);
|
||||||
|
|
||||||
recipe = getByName(recipeName);
|
recipe = getByName(recipeName);
|
||||||
assertNull(recipe);
|
assertNull(recipe);
|
||||||
|
|
||||||
// Try to add deleted recipe with override (should add)
|
// Try to add deleted recipe with override (should add)
|
||||||
assertTrue(CustomAnvilRecipeApi.addRecipe(builder, true));
|
assertTrue(CustomAnvilRecipeApi.addRecipe(builder, true));
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData);
|
||||||
|
|
||||||
recipe = getByName(recipeName);
|
recipe = getByName(recipeName);
|
||||||
assertNotNull(recipe);
|
assertNotNull(recipe);
|
||||||
|
|
@ -119,7 +119,7 @@ public class CustomAnvilRecipeApiTests extends ConfigResetCustomAnvilTest {
|
||||||
null, null
|
null, null
|
||||||
);
|
);
|
||||||
|
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData);
|
||||||
|
|
||||||
AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName);
|
AnvilRecipeBuilder builder = new AnvilRecipeBuilder(recipeName);
|
||||||
builder.setExactCount(false)
|
builder.setExactCount(false)
|
||||||
|
|
@ -130,8 +130,8 @@ public class CustomAnvilRecipeApiTests extends ConfigResetCustomAnvilTest {
|
||||||
assertTrue(builder.registerIfAbsent());
|
assertTrue(builder.registerIfAbsent());
|
||||||
|
|
||||||
// Now working test
|
// Now working test
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData1);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData1);
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData2);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ import org.mockbukkit.mockbukkit.entity.PlayerMock;
|
||||||
import org.mockbukkit.mockbukkit.inventory.ItemStackMock;
|
import org.mockbukkit.mockbukkit.inventory.ItemStackMock;
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
import xyz.alexcrea.cuanvil.config.ConfigHolder;
|
||||||
import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest;
|
import xyz.alexcrea.cuanvil.tests.ConfigResetCustomAnvilTest;
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilFuseTestData;
|
import xyz.alexcrea.cuanvil.data.AnvilFuseTestData;
|
||||||
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
@ -58,7 +58,7 @@ public class UnitRepairApiTests extends ConfigResetCustomAnvilTest {
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
|
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -76,7 +76,7 @@ public class UnitRepairApiTests extends ConfigResetCustomAnvilTest {
|
||||||
// Remove unit repair
|
// Remove unit repair
|
||||||
assertTrue(UnitRepairApi.removeUnitRepair(Material.DIAMOND, Material.DIAMOND_PICKAXE));
|
assertTrue(UnitRepairApi.removeUnitRepair(Material.DIAMOND, Material.DIAMOND_PICKAXE));
|
||||||
|
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData);
|
||||||
|
|
||||||
// see override
|
// see override
|
||||||
assertFalse(UnitRepairApi.addUnitRepair(Material.DIAMOND, Material.DIAMOND_PICKAXE, 0.25));
|
assertFalse(UnitRepairApi.addUnitRepair(Material.DIAMOND, Material.DIAMOND_PICKAXE, 0.25));
|
||||||
|
|
@ -107,12 +107,12 @@ public class UnitRepairApiTests extends ConfigResetCustomAnvilTest {
|
||||||
2
|
2
|
||||||
);
|
);
|
||||||
|
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, nullResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, nullResultData);
|
||||||
|
|
||||||
// Add unit repair
|
// Add unit repair
|
||||||
assertTrue(UnitRepairApi.addUnitRepair(Material.STICK, Material.DIAMOND_PICKAXE));
|
assertTrue(UnitRepairApi.addUnitRepair(Material.STICK, Material.DIAMOND_PICKAXE));
|
||||||
assertFalse(UnitRepairApi.addUnitRepair(Material.STICK, Material.DIAMOND_PICKAXE));
|
assertFalse(UnitRepairApi.addUnitRepair(Material.STICK, Material.DIAMOND_PICKAXE));
|
||||||
AnvilFuseTestUtil.executeAnvilTest(anvil, player, legalResultData);
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, legalResultData);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package xyz.alexcrea.cuanvil.data;
|
||||||
|
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public record AnvilClickTestData(
|
||||||
|
@Nullable ItemStack leftItem,
|
||||||
|
@Nullable ItemStack rightItem,
|
||||||
|
@Nullable ItemStack resultSlotItem,
|
||||||
|
@Nullable ItemStack expectedCursor,
|
||||||
|
int levelCost,
|
||||||
|
@Nullable Event.Result expectedResult,
|
||||||
|
boolean testNoLevelNoChange,
|
||||||
|
@Nullable Event.Result npChangeResult
|
||||||
|
) {
|
||||||
|
|
||||||
|
public AnvilClickTestData(@Nullable ItemStack leftItem,
|
||||||
|
@Nullable ItemStack rightItem,
|
||||||
|
@Nullable ItemStack resultSlotItem,
|
||||||
|
@Nullable ItemStack expectedCursor,
|
||||||
|
int levelCost,
|
||||||
|
@Nullable Event.Result expectedResult) {
|
||||||
|
this(leftItem, rightItem, resultSlotItem,
|
||||||
|
expectedCursor, levelCost, expectedResult,
|
||||||
|
false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnvilClickTestData(@Nullable ItemStack leftItem,
|
||||||
|
@Nullable ItemStack rightItem,
|
||||||
|
@Nullable ItemStack resultSlotItem,
|
||||||
|
@Nullable ItemStack expectedCursor,
|
||||||
|
int levelCost) {
|
||||||
|
this(leftItem, rightItem, resultSlotItem,
|
||||||
|
expectedCursor, levelCost, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnvilClickTestData(@Nullable ItemStack expectedCursor,
|
||||||
|
int levelCost,
|
||||||
|
@Nullable Event.Result expectedResult) {
|
||||||
|
this(null, null, null,
|
||||||
|
expectedCursor, levelCost, expectedResult,
|
||||||
|
false, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AnvilClickTestData(@Nullable ItemStack expectedCursor,
|
||||||
|
int levelCost) {
|
||||||
|
this(expectedCursor, levelCost, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
package xyz.alexcrea.cuanvil.util;
|
package xyz.alexcrea.cuanvil.data;
|
||||||
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
250
src/test/java/xyz/alexcrea/cuanvil/data/TestDataContainer.java
Normal file
250
src/test/java/xyz/alexcrea/cuanvil/data/TestDataContainer.java
Normal file
|
|
@ -0,0 +1,250 @@
|
||||||
|
package xyz.alexcrea.cuanvil.data;
|
||||||
|
|
||||||
|
import org.bukkit.entity.HumanEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.AnvilInventory;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import xyz.alexcrea.cuanvil.util.AnvilFuseTestUtil;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public record TestDataContainer(
|
||||||
|
@NotNull AnvilFuseTestData fuseData,
|
||||||
|
@Nullable AnvilClickTestData clickData
|
||||||
|
) {
|
||||||
|
|
||||||
|
public void executeTest(AnvilInventory anvil, Player player) {
|
||||||
|
executeFuseTest(anvil, player);
|
||||||
|
if (clickData != null) executeClickTest(anvil, player);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeFuseTest(AnvilInventory anvil, HumanEntity player) {
|
||||||
|
AnvilFuseTestUtil.executeAnvilFuseTest(anvil, player, fuseData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeClickTest(AnvilInventory anvil, Player player) {
|
||||||
|
Assertions.assertNotNull(clickData);
|
||||||
|
AnvilFuseTestUtil.executeAnvilClickTest(anvil, player, clickData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer nullifyResult() {
|
||||||
|
return new TestDataContainer(
|
||||||
|
new AnvilFuseTestData(
|
||||||
|
fuseData.leftItem(), fuseData.rightItem(),
|
||||||
|
null
|
||||||
|
), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setCost(
|
||||||
|
@Nullable Integer priceAfterLeft,
|
||||||
|
@Nullable Integer priceAfterRight,
|
||||||
|
int priceAfterBoth
|
||||||
|
) {
|
||||||
|
AnvilFuseTestData data = new AnvilFuseTestData(
|
||||||
|
fuseData.leftItem(), fuseData.rightItem(), fuseData.expectedResult(),
|
||||||
|
fuseData.expectedAfterLeftPlaced(),
|
||||||
|
fuseData.expectedAfterRightPlaced(),
|
||||||
|
priceAfterLeft,
|
||||||
|
priceAfterRight,
|
||||||
|
priceAfterBoth
|
||||||
|
);
|
||||||
|
|
||||||
|
AnvilClickTestData CData;
|
||||||
|
if (clickData == null) {
|
||||||
|
CData = null;
|
||||||
|
} else {
|
||||||
|
CData = new AnvilClickTestData(
|
||||||
|
clickData.leftItem(), clickData.rightItem(), clickData.resultSlotItem(),
|
||||||
|
clickData.expectedCursor(), priceAfterBoth,
|
||||||
|
clickData.expectedResult(),
|
||||||
|
clickData.testNoLevelNoChange(), clickData.npChangeResult()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return new TestDataContainer(data, CData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setCost(
|
||||||
|
int priceAfterBoth
|
||||||
|
) {
|
||||||
|
return setCost(null, null, priceAfterBoth);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set fuse items
|
||||||
|
public @NotNull TestDataContainer setFuseItems(@Nullable ItemStack left, @Nullable ItemStack right, @Nullable ItemStack expected) {
|
||||||
|
AnvilFuseTestData data = new AnvilFuseTestData(
|
||||||
|
left, right, expected,
|
||||||
|
fuseData.expectedAfterLeftPlaced(),
|
||||||
|
fuseData.expectedAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterLeftPlaced(),
|
||||||
|
fuseData.expectedPriceAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterBothPlaced()
|
||||||
|
);
|
||||||
|
return new TestDataContainer(data, clickData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setFuseItems(
|
||||||
|
@Nullable ItemStack left, @Nullable ItemStack right, @Nullable ItemStack expected,
|
||||||
|
@Nullable ItemStack leftExpected, @Nullable ItemStack rightExpected) {
|
||||||
|
AnvilFuseTestData data = new AnvilFuseTestData(
|
||||||
|
left, right, expected,
|
||||||
|
leftExpected,
|
||||||
|
rightExpected,
|
||||||
|
fuseData.expectedPriceAfterLeftPlaced(),
|
||||||
|
fuseData.expectedPriceAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterBothPlaced()
|
||||||
|
);
|
||||||
|
return new TestDataContainer(data, clickData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setFuseLeft(@Nullable ItemStack left) {
|
||||||
|
AnvilFuseTestData data = new AnvilFuseTestData(
|
||||||
|
left, fuseData.rightItem(), fuseData.expectedResult(),
|
||||||
|
fuseData.expectedAfterLeftPlaced(),
|
||||||
|
fuseData.expectedAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterLeftPlaced(),
|
||||||
|
fuseData.expectedPriceAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterBothPlaced()
|
||||||
|
);
|
||||||
|
return new TestDataContainer(data, clickData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setFuseRight(@Nullable ItemStack right) {
|
||||||
|
AnvilFuseTestData data = new AnvilFuseTestData(
|
||||||
|
fuseData.leftItem(), right, fuseData.expectedResult(),
|
||||||
|
fuseData.expectedAfterLeftPlaced(),
|
||||||
|
fuseData.expectedAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterLeftPlaced(),
|
||||||
|
fuseData.expectedPriceAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterBothPlaced()
|
||||||
|
);
|
||||||
|
return new TestDataContainer(data, clickData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setFuseExpected(@Nullable ItemStack expected) {
|
||||||
|
AnvilFuseTestData data = new AnvilFuseTestData(
|
||||||
|
fuseData.leftItem(), fuseData.rightItem(), expected,
|
||||||
|
fuseData.expectedAfterLeftPlaced(),
|
||||||
|
fuseData.expectedAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterLeftPlaced(),
|
||||||
|
fuseData.expectedPriceAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterBothPlaced()
|
||||||
|
);
|
||||||
|
return new TestDataContainer(data, clickData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setFuseExpectedLeft(@Nullable ItemStack expected) {
|
||||||
|
AnvilFuseTestData data = new AnvilFuseTestData(
|
||||||
|
fuseData.leftItem(), fuseData.rightItem(), fuseData.expectedResult(),
|
||||||
|
expected,
|
||||||
|
fuseData.expectedAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterLeftPlaced(),
|
||||||
|
fuseData.expectedPriceAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterBothPlaced()
|
||||||
|
);
|
||||||
|
return new TestDataContainer(data, clickData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setFuseExpectedRight(@Nullable ItemStack expected) {
|
||||||
|
AnvilFuseTestData data = new AnvilFuseTestData(
|
||||||
|
fuseData.leftItem(), fuseData.rightItem(), fuseData.expectedResult(),
|
||||||
|
fuseData.expectedAfterLeftPlaced(),
|
||||||
|
expected,
|
||||||
|
fuseData.expectedPriceAfterLeftPlaced(),
|
||||||
|
fuseData.expectedPriceAfterRightPlaced(),
|
||||||
|
fuseData.expectedPriceAfterBothPlaced()
|
||||||
|
);
|
||||||
|
return new TestDataContainer(data, clickData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set click items
|
||||||
|
public @NotNull TestDataContainer setClickLeft(@Nullable ItemStack left) {
|
||||||
|
if (clickData == null) return this;
|
||||||
|
AnvilClickTestData data = new AnvilClickTestData(
|
||||||
|
left, clickData.rightItem(), clickData.resultSlotItem(), clickData.expectedCursor(),
|
||||||
|
clickData.levelCost(), clickData.expectedResult(),
|
||||||
|
clickData.testNoLevelNoChange(), clickData.npChangeResult()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new TestDataContainer(fuseData, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setClickRight(@Nullable ItemStack right) {
|
||||||
|
if (clickData == null) return this;
|
||||||
|
AnvilClickTestData data = new AnvilClickTestData(
|
||||||
|
clickData.leftItem(), right, clickData.resultSlotItem(), clickData.expectedCursor(),
|
||||||
|
clickData.levelCost(), clickData.expectedResult(),
|
||||||
|
clickData.testNoLevelNoChange(), clickData.npChangeResult()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new TestDataContainer(fuseData, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setClickOutput(@Nullable ItemStack output) {
|
||||||
|
if (clickData == null) return this;
|
||||||
|
AnvilClickTestData data = new AnvilClickTestData(
|
||||||
|
clickData.leftItem(), clickData.rightItem(), output, clickData.expectedCursor(),
|
||||||
|
clickData.levelCost(), clickData.expectedResult(),
|
||||||
|
clickData.testNoLevelNoChange(), clickData.npChangeResult()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new TestDataContainer(fuseData, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
public @NotNull TestDataContainer setClickCursor(@Nullable ItemStack cursor) {
|
||||||
|
if (clickData == null) return this;
|
||||||
|
AnvilClickTestData data = new AnvilClickTestData(
|
||||||
|
clickData.leftItem(), clickData.rightItem(), clickData.resultSlotItem(), cursor,
|
||||||
|
clickData.levelCost(), clickData.expectedResult(),
|
||||||
|
clickData.testNoLevelNoChange(), clickData.npChangeResult()
|
||||||
|
);
|
||||||
|
|
||||||
|
return new TestDataContainer(fuseData, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Both item
|
||||||
|
public @NotNull TestDataContainer setExpectedResult(@Nullable ItemStack result) {
|
||||||
|
return setFuseExpected(result).setClickCursor(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get fuse item
|
||||||
|
public @Nullable ItemStack getLeftFuse() {
|
||||||
|
return fuseData.leftItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ItemStack getRightFuse() {
|
||||||
|
return fuseData.rightItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ItemStack getExpectedFuse() {
|
||||||
|
return fuseData.expectedResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ItemStack getLeftExpectedFuse() {
|
||||||
|
return fuseData.expectedAfterLeftPlaced();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ItemStack getRightExpectedFuse() {
|
||||||
|
return fuseData.expectedAfterRightPlaced();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get click item
|
||||||
|
public @Nullable ItemStack getLeftClick() {
|
||||||
|
return clickData == null ? null : clickData.leftItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ItemStack getRightClick() {
|
||||||
|
return clickData == null ? null : clickData.rightItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ItemStack getOutputClick() {
|
||||||
|
return clickData == null ? null : clickData.resultSlotItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable ItemStack getCursorClick() {
|
||||||
|
return clickData == null ? null : clickData.expectedCursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,9 @@ package xyz.alexcrea.cuanvil.util;
|
||||||
import io.delilaheve.util.ItemUtil;
|
import io.delilaheve.util.ItemUtil;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
import org.bukkit.entity.HumanEntity;
|
import org.bukkit.entity.HumanEntity;
|
||||||
import org.bukkit.event.inventory.PrepareAnvilEvent;
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.inventory.*;
|
||||||
import org.bukkit.inventory.AnvilInventory;
|
import org.bukkit.inventory.AnvilInventory;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
import org.bukkit.inventory.meta.ItemMeta;
|
import org.bukkit.inventory.meta.ItemMeta;
|
||||||
|
|
@ -11,7 +13,10 @@ import org.bukkit.inventory.meta.Repairable;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.junit.jupiter.api.Assertions;
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import xyz.alexcrea.cuanvil.data.AnvilClickTestData;
|
||||||
|
import xyz.alexcrea.cuanvil.data.AnvilFuseTestData;
|
||||||
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
import xyz.alexcrea.cuanvil.enchant.CAEnchantment;
|
||||||
|
import xyz.alexcrea.cuanvil.listener.AnvilResultListener;
|
||||||
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener;
|
import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener;
|
||||||
import xyz.alexcrea.cuanvil.mock.AnvilViewMock;
|
import xyz.alexcrea.cuanvil.mock.AnvilViewMock;
|
||||||
|
|
||||||
|
|
@ -21,16 +26,19 @@ import java.util.List;
|
||||||
|
|
||||||
public class AnvilFuseTestUtil {
|
public class AnvilFuseTestUtil {
|
||||||
|
|
||||||
|
private static PrepareAnvilListener PREPARE_LISTENER = new PrepareAnvilListener();
|
||||||
|
private static AnvilResultListener RESULT_LISTENER = new AnvilResultListener();
|
||||||
|
|
||||||
public static ItemStack prepareItem(@NotNull Material material,
|
public static ItemStack prepareItem(@NotNull Material material,
|
||||||
@NotNull List<CAEnchantment> enchantments,
|
@NotNull List<CAEnchantment> enchantments,
|
||||||
@NotNull List<Integer> level){
|
@NotNull List<Integer> level) {
|
||||||
return prepareItem(material, 0, enchantments, level);
|
return prepareItem(material, 0, enchantments, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack prepareItem(@NotNull Material material,
|
public static ItemStack prepareItem(@NotNull Material material,
|
||||||
int repairCost,
|
int repairCost,
|
||||||
@NotNull List<CAEnchantment> enchantments,
|
@NotNull List<CAEnchantment> enchantments,
|
||||||
@NotNull List<Integer> level){
|
@NotNull List<Integer> level) {
|
||||||
Assertions.assertEquals(enchantments.size(), level.size());
|
Assertions.assertEquals(enchantments.size(), level.size());
|
||||||
|
|
||||||
HashMap<CAEnchantment, Integer> enchantmentMap = new HashMap<>();
|
HashMap<CAEnchantment, Integer> enchantmentMap = new HashMap<>();
|
||||||
|
|
@ -51,13 +59,14 @@ public class AnvilFuseTestUtil {
|
||||||
|
|
||||||
public static ItemStack prepareItem(@NotNull Material material,
|
public static ItemStack prepareItem(@NotNull Material material,
|
||||||
@NotNull List<String> enchantmentNames,
|
@NotNull List<String> enchantmentNames,
|
||||||
Integer... levels){
|
Integer... levels) {
|
||||||
return prepareItem(material, 0, enchantmentNames, levels);
|
return prepareItem(material, 0, enchantmentNames, levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ItemStack prepareItem(@NotNull Material material,
|
public static ItemStack prepareItem(@NotNull Material material,
|
||||||
int repairCost,
|
int repairCost,
|
||||||
@NotNull List<String> enchantmentNames,
|
@NotNull List<String> enchantmentNames,
|
||||||
Integer... levels){
|
Integer... levels) {
|
||||||
List<CAEnchantment> enchantments = new ArrayList<>();
|
List<CAEnchantment> enchantments = new ArrayList<>();
|
||||||
|
|
||||||
for (String enchantmentName : enchantmentNames) {
|
for (String enchantmentName : enchantmentNames) {
|
||||||
|
|
@ -86,18 +95,18 @@ public class AnvilFuseTestUtil {
|
||||||
PrepareAnvilEvent event = new PrepareAnvilEvent(view, anvil.getItem(2));
|
PrepareAnvilEvent event = new PrepareAnvilEvent(view, anvil.getItem(2));
|
||||||
|
|
||||||
// Not ideal but possible and the easiest so why not
|
// Not ideal but possible and the easiest so why not
|
||||||
new PrepareAnvilListener().anvilCombineCheck(event);
|
PREPARE_LISTENER.anvilCombineCheck(event);
|
||||||
anvil.setResult(event.getResult());
|
anvil.setResult(event.getResult());
|
||||||
} catch (Exception e){
|
} catch (Exception e) {
|
||||||
Assertions.fail(e);
|
Assertions.fail(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void executeAnvilTest(
|
public static void executeAnvilFuseTest(
|
||||||
@NotNull AnvilInventory anvil,
|
@NotNull AnvilInventory anvil,
|
||||||
@NotNull HumanEntity player,
|
@NotNull HumanEntity player,
|
||||||
@NotNull AnvilFuseTestData data
|
@NotNull AnvilFuseTestData data
|
||||||
){
|
) {
|
||||||
Assertions.assertEquals(player.getOpenInventory().getTopInventory(), anvil,
|
Assertions.assertEquals(player.getOpenInventory().getTopInventory(), anvil,
|
||||||
"Openned inventory is not anvil");
|
"Openned inventory is not anvil");
|
||||||
|
|
||||||
|
|
@ -117,9 +126,65 @@ public class AnvilFuseTestUtil {
|
||||||
testPlacingItem(anvil, player,
|
testPlacingItem(anvil, player,
|
||||||
0, data.expectedPriceAfterBothPlaced(),
|
0, data.expectedPriceAfterBothPlaced(),
|
||||||
data.leftItem(), data.expectedResult());
|
data.leftItem(), data.expectedResult());
|
||||||
|
}
|
||||||
|
|
||||||
// Sadly, can't currently test player click
|
public static void executeAnvilClickTest(
|
||||||
|
@NotNull AnvilInventory anvil,
|
||||||
|
@NotNull Player player,
|
||||||
|
@NotNull AnvilClickTestData data
|
||||||
|
) {
|
||||||
|
if (data.testNoLevelNoChange()) {
|
||||||
|
ItemStack left = anvil.getFirstItem();
|
||||||
|
ItemStack right = anvil.getSecondItem();
|
||||||
|
ItemStack result = anvil.getResult();
|
||||||
|
|
||||||
|
player.setLevel(0);
|
||||||
|
player.setItemOnCursor(null);
|
||||||
|
|
||||||
|
// Do a test with not enough level
|
||||||
|
simulateClick(anvil, player, data.npChangeResult());
|
||||||
|
|
||||||
|
// Nothing should have changed
|
||||||
|
assertEqual(left, anvil.getFirstItem());
|
||||||
|
assertEqual(right, anvil.getSecondItem());
|
||||||
|
assertEqual(result, anvil.getResult());
|
||||||
|
assertEqual(null, player.getItemOnCursor());
|
||||||
|
}
|
||||||
|
player.setLevel(data.levelCost());
|
||||||
|
player.setItemOnCursor(null);
|
||||||
|
|
||||||
|
simulateClick(anvil, player, data.expectedResult());
|
||||||
|
|
||||||
|
// Should have similated the click
|
||||||
|
assertEqual(data.leftItem(), anvil.getFirstItem());
|
||||||
|
assertEqual(data.rightItem(), anvil.getSecondItem());
|
||||||
|
assertEqual(data.resultSlotItem(), anvil.getResult());
|
||||||
|
assertEqual(data.expectedCursor(), data.expectedCursor());
|
||||||
|
|
||||||
|
// Test if the player has no more xp
|
||||||
|
Assertions.assertEquals(0, player.getLevel(), "Player has more level than expected");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void simulateClick(
|
||||||
|
@NotNull AnvilInventory anvil,
|
||||||
|
@NotNull Player player,
|
||||||
|
@Nullable Event.Result expectedResult
|
||||||
|
) {
|
||||||
|
AnvilViewMock view = new AnvilViewMock(player, anvil);
|
||||||
|
try {
|
||||||
|
InventoryClickEvent event = new InventoryClickEvent(view,
|
||||||
|
InventoryType.SlotType.RESULT,
|
||||||
|
PrepareAnvilListener.ANVIL_OUTPUT_SLOT,
|
||||||
|
ClickType.LEFT,
|
||||||
|
InventoryAction.PICKUP_ALL);
|
||||||
|
|
||||||
|
RESULT_LISTENER.anvilExtractionCheck(event);
|
||||||
|
if (expectedResult != null) {
|
||||||
|
Assertions.assertEquals(expectedResult, event.getResult());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Assertions.fail(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"removal"})
|
@SuppressWarnings({"removal"})
|
||||||
|
|
@ -129,7 +194,7 @@ public class AnvilFuseTestUtil {
|
||||||
int slot,
|
int slot,
|
||||||
Integer expectedPrice,
|
Integer expectedPrice,
|
||||||
@Nullable ItemStack toPlace,
|
@Nullable ItemStack toPlace,
|
||||||
@Nullable ItemStack expectedResult){
|
@Nullable ItemStack expectedResult) {
|
||||||
anvil.setItem(slot, toPlace);
|
anvil.setItem(slot, toPlace);
|
||||||
anvil.setItem(2, null);
|
anvil.setItem(2, null);
|
||||||
AnvilFuseTestUtil.imitateAnvilUpdate(player, anvil);
|
AnvilFuseTestUtil.imitateAnvilUpdate(player, anvil);
|
||||||
|
|
@ -140,25 +205,26 @@ public class AnvilFuseTestUtil {
|
||||||
assertPriceEqual(expectedPrice, anvil.getRepairCost());
|
assertPriceEqual(expectedPrice, anvil.getRepairCost());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertEqual(@Nullable ItemStack item1, @Nullable ItemStack item2) {
|
public static void assertEqual(@Nullable ItemStack expected, @Nullable ItemStack other) {
|
||||||
boolean secondIsAir = isAir(item2);
|
boolean secondIsAir = isAir(other);
|
||||||
if(isAir(item1)) Assertions.assertTrue(secondIsAir,"Item "+item2+" was not AIR but was expected to be air");
|
if (isAir(expected))
|
||||||
|
Assertions.assertTrue(secondIsAir, "Item " + other + " was not air but was expected to be");
|
||||||
else {
|
else {
|
||||||
Assertions.assertFalse(secondIsAir,"Item "+item2+" was expected not to be air");
|
Assertions.assertFalse(secondIsAir, "Item " + other + " is air but was expected to be " + expected);
|
||||||
|
|
||||||
item1.setDurability(item1.getDurability());
|
expected.setDurability(expected.getDurability());
|
||||||
item2.setDurability(item2.getDurability());
|
other.setDurability(other.getDurability());
|
||||||
Assertions.assertEquals(item1, item2);
|
Assertions.assertEquals(expected, other);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isAir(@Nullable ItemStack item){
|
public static boolean isAir(@Nullable ItemStack item) {
|
||||||
return item == null || item.isEmpty();
|
return item == null || item.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void assertPriceEqual(Integer expectedPrice, int price){
|
public static void assertPriceEqual(Integer expectedPrice, int price) {
|
||||||
if(expectedPrice == null) return;
|
if (expectedPrice == null) return;
|
||||||
Assertions.assertEquals(expectedPrice, price);
|
Assertions.assertEquals(expectedPrice, price);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,10 +43,17 @@ permissions:
|
||||||
# color permissions
|
# color permissions
|
||||||
ca.color.code:
|
ca.color.code:
|
||||||
default: op
|
default: op
|
||||||
description: Allow player to use color code if permission is required (toggleable)
|
description: Allow player to use color code if enabled (toggleable)
|
||||||
ca.color.hex:
|
ca.color.hex:
|
||||||
default: op
|
default: op
|
||||||
description: Allow player to use hexadecimal color if permission is required (toggleable)
|
description: Allow player to use hexadecimal color if enabled (toggleable)
|
||||||
|
# lore edit permissions
|
||||||
|
ca.lore_edit.book:
|
||||||
|
default: op
|
||||||
|
description: Allow player to edit lore via book and quil if enabled (toggleable)
|
||||||
|
ca.lore_edit.paper:
|
||||||
|
default: op
|
||||||
|
description: Allow player to edit lore via paper if enabled (toggleable)
|
||||||
|
|
||||||
|
|
||||||
# soft depend on old name (UnsafeEnchantsPlus), so I can disable it if it is on the same server (old name for this plugin)
|
# soft depend on old name (UnsafeEnchantsPlus), so I can disable it if it is on the same server (old name for this plugin)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue