alpha version up & cleanup code.

This commit is contained in:
alexcrea 2024-03-31 00:59:50 +01:00
parent 1b83c8db81
commit 00fba2f4b0
40 changed files with 893 additions and 718 deletions

View file

@ -4,7 +4,7 @@ plugins {
}
group = "xyz.alexcrea"
version = "1.3.2-A1"
version = "1.3.2-A2"
repositories {
mavenCentral()

View file

@ -19,27 +19,27 @@ public abstract class ConfigHolder {
public static ConflictConfigHolder CONFLICT_HOLDER;
public static UnitRepairHolder UNIT_REPAIR_HOLDER;
public static boolean loadConfig(){
public static boolean loadConfig() {
DEFAULT_CONFIG = new DefaultConfigHolder();
ITEM_GROUP_HOLDER = new ItemGroupConfigHolder();
CONFLICT_HOLDER = new ConflictConfigHolder();
UNIT_REPAIR_HOLDER = new UnitRepairHolder();
boolean result = reloadAllFromDisk(true);
if(result){
if (result) {
MetricsUtil.INSTANCE.testIfConfigIsDefault();
}
return result;
}
public static boolean reloadAllFromDisk(boolean hardfail){
public static boolean reloadAllFromDisk(boolean hardfail) {
boolean sucess = DEFAULT_CONFIG.reloadFromDisk(hardfail);
if(!sucess) return false;
if (!sucess) return false;
sucess = ITEM_GROUP_HOLDER.reloadFromDisk(hardfail);
if(!sucess) return false;
if (!sucess) return false;
sucess = CONFLICT_HOLDER.reloadFromDisk(hardfail);
if(!sucess) return false;
if (!sucess) return false;
sucess = UNIT_REPAIR_HOLDER.reloadFromDisk(hardfail);
return sucess;
}
@ -49,43 +49,49 @@ public abstract class ConfigHolder {
private static final File BACKUP_FOLDER = new File(CustomAnvil.instance.getDataFolder(), "backup");
protected FileConfiguration configuration;
protected ConfigHolder(){
protected ConfigHolder() {
}
public abstract boolean reloadFromDisk(boolean hardFail);
public abstract void reload();
public FileConfiguration getConfig(){
public FileConfiguration getConfig() {
return configuration;
}
// Config name and files
protected abstract String getConfigFileName();
protected String getConfigFileExtension(){
protected String getConfigFileExtension() {
return ".yml";
}
protected File getConfigFile(){
return new File(CustomAnvil.instance.getDataFolder(), getConfigFileName()+getConfigFileExtension());
protected File getConfigFile() {
return new File(CustomAnvil.instance.getDataFolder(), getConfigFileName() + getConfigFileExtension());
}
protected File getFirstBackup(){
return new File(BACKUP_FOLDER, getConfigFileName()+"-first"+getConfigFileExtension());
protected File getFirstBackup() {
return new File(BACKUP_FOLDER, getConfigFileName() + "-first" + getConfigFileExtension());
}
protected File getLastBackup(){
return new File(BACKUP_FOLDER, getConfigFileName()+"-latest"+getConfigFileExtension());
protected File getLastBackup() {
return new File(BACKUP_FOLDER, getConfigFileName() + "-latest" + getConfigFileExtension());
}
// Save logic
public boolean saveToDisk(boolean doBackup){
if(doBackup){
if(!saveBackup()){
public boolean saveToDisk(boolean doBackup) {
if (doBackup) {
if (!saveBackup()) {
CustomAnvil.instance.getLogger().severe("Could not save backup. see above.");
return false;
}
}
File base = getConfigFile();
// if file exist and can't be deleted the file, then we gave up.
if(base.exists() && !base.delete()) {
if (base.exists() && !base.delete()) {
CustomAnvil.instance.getLogger().severe("Could not save config: can't delete existing file.");
return false;
}
@ -101,15 +107,15 @@ public abstract class ConfigHolder {
return true;
}
protected boolean saveBackup(){
protected boolean saveBackup() {
File base = getConfigFile();
if(!base.exists()) return true; // We did back up everything we had to (nothing in this case)
if (!base.exists()) return true; // We did back up everything we had to (nothing in this case)
boolean sufficientSuccess = false;
BACKUP_FOLDER.mkdirs();
// save first backup if do not exist
File firstBackup = getFirstBackup();
if(!firstBackup.exists()){
if (!firstBackup.exists()) {
try {
Files.copy(base, firstBackup);
sufficientSuccess = true;
@ -120,7 +126,7 @@ public abstract class ConfigHolder {
// save last backup
File lastBackup = getLastBackup();
// if file exist and can't be deleted the file, then we gave up.
if(lastBackup.exists() && !lastBackup.delete()){
if (lastBackup.exists() && !lastBackup.delete()) {
return sufficientSuccess;
}
@ -134,7 +140,7 @@ public abstract class ConfigHolder {
return sufficientSuccess;
}
public static class DefaultConfigHolder extends ConfigHolder{
public static class DefaultConfigHolder extends ConfigHolder {
@Override
protected String getConfigFileName() {
@ -150,15 +156,17 @@ public abstract class ConfigHolder {
}
@Override
public void reload() {}// Nothing to do
public void reload() {
}// Nothing to do
}
// Abstract class for non default config
public abstract static class ResourceConfigHolder extends ConfigHolder{
public abstract static class ResourceConfigHolder extends ConfigHolder {
String resourceName;
private ResourceConfigHolder(String resourceName){
private ResourceConfigHolder(String resourceName) {
this.resourceName = resourceName;
}
@ -170,8 +178,8 @@ public abstract class ConfigHolder {
@Override
public boolean reloadFromDisk(boolean hardFail) {
YamlConfiguration configuration = CustomAnvil.instance.reloadResource(
getConfigFileName()+getConfigFileExtension(), hardFail);
if(configuration == null) return false;
getConfigFileName() + getConfigFileExtension(), hardFail);
if (configuration == null) return false;
this.configuration = configuration;
reload();
return true;
@ -180,10 +188,11 @@ public abstract class ConfigHolder {
}
// Class for itemGroupsManager config
public static class ItemGroupConfigHolder extends ResourceConfigHolder{
public static class ItemGroupConfigHolder extends ResourceConfigHolder {
private final static String FILE_NAME = "item_groups";
ItemGroupManager itemGroupsManager;
private ItemGroupConfigHolder() {
super(FILE_NAME);
}
@ -198,7 +207,7 @@ public abstract class ConfigHolder {
this.itemGroupsManager = new ItemGroupManager();
this.itemGroupsManager.prepareGroups(this.configuration);
if(CONFLICT_HOLDER.getConfig() != null){
if (CONFLICT_HOLDER.getConfig() != null) {
CONFLICT_HOLDER.reload();
}
}
@ -206,10 +215,11 @@ public abstract class ConfigHolder {
}
// Class for enchant conflict config
public static class ConflictConfigHolder extends ResourceConfigHolder{
public static class ConflictConfigHolder extends ResourceConfigHolder {
private final static String FILE_NAME = "enchant_conflict";
EnchantConflictManager conflictManager;
private ConflictConfigHolder() {
super(FILE_NAME);
}
@ -229,14 +239,16 @@ public abstract class ConfigHolder {
}
// Class for unit repair config
public static class UnitRepairHolder extends ResourceConfigHolder{
public static class UnitRepairHolder extends ResourceConfigHolder {
private final static String ITEM_GROUP_FILE_NAME = "unit_repair_item";
private UnitRepairHolder() {
super(ITEM_GROUP_FILE_NAME);
}
@Override
public void reload() {} // Do nothing
public void reload() {
} // Do nothing
}

View file

@ -41,12 +41,11 @@ public enum EnchantmentProperties {
SWEEPING(EnchantmentRarity.RARE),
THORNS(EnchantmentRarity.VERY_RARE),
UNBREAKING(EnchantmentRarity.UNCOMMON),
VANISHING_CURSE(EnchantmentRarity.VERY_RARE)
;
VANISHING_CURSE(EnchantmentRarity.VERY_RARE);
private final EnchantmentRarity rarity;
EnchantmentProperties(EnchantmentRarity rarity){
EnchantmentProperties(EnchantmentRarity rarity) {
this.rarity = rarity;
}

View file

@ -7,19 +7,18 @@ public enum EnchantmentRarity {
COMMON(1),
UNCOMMON(2),
RARE(4),
VERY_RARE(8)
;
VERY_RARE(8);
private final int itemValue;
private final int bookValue;
EnchantmentRarity(int itemValue, int bookValue){
EnchantmentRarity(int itemValue, int bookValue) {
this.itemValue = itemValue;
this.bookValue = bookValue;
}
EnchantmentRarity(int itemValue){
this(itemValue, Math.max(1,itemValue/2));
EnchantmentRarity(int itemValue) {
this(itemValue, Math.max(1, itemValue / 2));
}
public int getBookValue() {

View file

@ -14,15 +14,17 @@ import java.util.List;
/**
* Abstract Global Config gui for enchantment setting configuration.
*
* @param <T> Type of the factory of the type of setting the gui should edit.
*/
public abstract class AbstractEnchantConfigGui<T extends AbstractSettingGui.SettingGuiFactory> extends ValueUpdatableGui {
/**
* Constructor for a gui displaying available enchantment to edit a enchantment setting.
*
* @param title Title of the gui.
*/
protected AbstractEnchantConfigGui(String title){
protected AbstractEnchantConfigGui(String title) {
super(6, title, CustomAnvil.instance);
}
@ -31,7 +33,7 @@ public abstract class AbstractEnchantConfigGui<T extends AbstractSettingGui.Sett
/**
* Initialise value updatable gui pattern
*/
protected void init(){
protected void init() {
// Back item panel
addPane(GuiSharedConstant.BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE);
@ -50,7 +52,7 @@ public abstract class AbstractEnchantConfigGui<T extends AbstractSettingGui.Sett
/**
* Prepare enchantment config gui displayed items factory.
*/
protected void prepareValues(){
protected void prepareValues() {
bookItemFactoryList = new ArrayList<>();
for (Enchantment enchant : GuiSharedConstant.SORTED_ENCHANTMENT_LIST) {

View file

@ -24,6 +24,7 @@ public class ConfirmActionGui extends ChestGui {
private static final ItemStack CANCEL_ITEM;
private static final ItemStack CONFIRM_ITEM;
static {
CANCEL_ITEM = new ItemStack(Material.RED_TERRACOTTA);
ItemMeta meta = CANCEL_ITEM.getItemMeta();
@ -58,21 +59,21 @@ public class ConfirmActionGui extends ChestGui {
event.setCancelled(true);
HumanEntity player = event.getWhoClicked();
if(!player.hasPermission(CustomAnvil.editConfigPermission)) {
if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM);
return;
}
boolean success;
try{
try {
success = onConfirm.get();
}catch (Exception e){
} catch (Exception e) {
CustomAnvil.instance.getLogger().log(Level.WARNING, "Could not process confirmation supplier.", e);
success = false;
}
if(!success){
if (!success) {
event.getWhoClicked().sendMessage("\u00A7cAction could not be completed. ");
}
backOnConfirm.show(player);

View file

@ -33,7 +33,7 @@ public class BasicConfigGui extends ValueUpdatableGui {
/**
* Constructor of this Global gui for basic settings.
*/
private BasicConfigGui(){
private BasicConfigGui() {
super(3, "\u00A78Basic Config", CustomAnvil.instance);
}
@ -42,7 +42,7 @@ public class BasicConfigGui extends ValueUpdatableGui {
/**
* Initialise Basic gui
*/
private void init(){
private void init() {
Pattern pattern = new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
"012345670",
@ -70,15 +70,15 @@ public class BasicConfigGui extends ValueUpdatableGui {
/**
* Prepare basic gui displayed items factory and static items..
*/
protected void prepareValues(){
protected void prepareValues() {
// limit repair item
this.limitRepairFactory = BoolSettingsGui.boolFactory("\u00A78Limit Repair Cost ?",this,
this.limitRepairFactory = BoolSettingsGui.boolFactory("\u00A78Limit Repair Cost ?", this,
ConfigOptions.LIMIT_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG, ConfigOptions.DEFAULT_LIMIT_REPAIR);
// rename cost item
IntRange range = ConfigOptions.REPAIR_LIMIT_RANGE;
this.repairCostFactory = IntSettingsGui.intFactory("\u00A78Repair Cost Limit", this,
ConfigOptions.LIMIT_REPAIR_VALUE, ConfigHolder.DEFAULT_CONFIG, range.getFirst(),range.getLast(),
ConfigOptions.LIMIT_REPAIR_VALUE, ConfigHolder.DEFAULT_CONFIG, range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_LIMIT_REPAIR_VALUE,
1, 5, 10);
@ -92,33 +92,33 @@ public class BasicConfigGui extends ValueUpdatableGui {
this.notNeededLimitValueItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
// remove repair limit item
this.removeRepairLimit = BoolSettingsGui.boolFactory("\u00A78Remove Repair Limit ?",this,
this.removeRepairLimit = BoolSettingsGui.boolFactory("\u00A78Remove Repair Limit ?", this,
ConfigOptions.REMOVE_REPAIR_LIMIT, ConfigHolder.DEFAULT_CONFIG, ConfigOptions.DEFAULT_REMOVE_LIMIT);
// item repair cost
range = ConfigOptions.REPAIR_COST_RANGE;
this.itemRepairCost = IntSettingsGui.intFactory("\u00A78Item Repair Cost", this,
ConfigOptions.ITEM_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG, range.getFirst(),range.getLast(),
ConfigOptions.ITEM_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG, range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_ITEM_REPAIR_COST,
1, 5, 10, 50, 100);
// unit repair cost
this.unitRepairCost = IntSettingsGui.intFactory("\u00A78Unit Repair Cost", this,
ConfigOptions.UNIT_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG, range.getFirst(),range.getLast(),
ConfigOptions.UNIT_REPAIR_COST, ConfigHolder.DEFAULT_CONFIG, range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_UNIT_REPAIR_COST,
1, 5, 10, 50, 100);
// item rename cost
range = ConfigOptions.ITEM_RENAME_COST_RANGE;
this.itemRenameCost = IntSettingsGui.intFactory("\u00A78Rename Cost", this,
ConfigOptions.ITEM_RENAME_COST, ConfigHolder.DEFAULT_CONFIG, range.getFirst(),range.getLast(),
ConfigOptions.ITEM_RENAME_COST, ConfigHolder.DEFAULT_CONFIG, range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_ITEM_RENAME_COST,
1, 5, 10, 50, 100);
// sacrifice illegal enchant cost
range = ConfigOptions.SACRIFICE_ILLEGAL_COST_RANGE;
this.sacrificeIllegalEnchantCost = IntSettingsGui.intFactory("\u00A78Sacrifice Illegal Enchant Cost", this,
ConfigOptions.SACRIFICE_ILLEGAL_COST, ConfigHolder.DEFAULT_CONFIG, range.getFirst(),range.getLast(),
ConfigOptions.SACRIFICE_ILLEGAL_COST, ConfigHolder.DEFAULT_CONFIG, range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_SACRIFICE_ILLEGAL_COST,
1, 5, 10, 50, 100);
@ -132,9 +132,9 @@ public class BasicConfigGui extends ValueUpdatableGui {
// rename cost item
GuiItem limitRepairValueItem;
if(this.limitRepairFactory.getConfiguredValue()){
if (this.limitRepairFactory.getConfiguredValue()) {
limitRepairValueItem = GuiGlobalItems.intSettingGuiItem(this.repairCostFactory, Material.EXPERIENCE_BOTTLE);
}else{
} else {
limitRepairValueItem = this.notNeededLimitValueItem;
}
pane.bindItem('2', limitRepairValueItem);

View file

@ -31,6 +31,7 @@ import java.util.function.Consumer;
public class EnchantConflictGui extends ChestGui {
public final static EnchantConflictGui INSTANCE = new EnchantConflictGui();
static {
INSTANCE.init();
}
@ -47,7 +48,7 @@ public class EnchantConflictGui extends ChestGui {
private HashMap<UUID, Integer> pageMap;
private PatternPane backgroundPane;
private void init(){
private void init() {
// Back item panel
Pattern pattern = new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
@ -80,13 +81,14 @@ public class EnchantConflictGui extends ChestGui {
private GuiItem goLeftItem;
private GuiItem goRightItem;
private void prepareOtherValues() {
// Left item creation for consumer & bind
this.goLeftItem = new GuiItem(new ItemStack(Material.RED_TERRACOTTA), event -> {
HumanEntity viewer = event.getWhoClicked();
UUID playerUUID = viewer.getUniqueId();
int page = this.pageMap.getOrDefault(playerUUID, 0);
this.pageMap.put(playerUUID, page-1);
this.pageMap.put(playerUUID, page - 1);
ItemStack cursor = viewer.getItemOnCursor();
viewer.setItemOnCursor(new ItemStack(Material.AIR));
@ -101,7 +103,7 @@ public class EnchantConflictGui extends ChestGui {
HumanEntity viewer = event.getWhoClicked();
UUID playerUUID = viewer.getUniqueId();
int page = pageMap.getOrDefault(playerUUID, 0);
this.pageMap.put(playerUUID, page+1);
this.pageMap.put(playerUUID, page + 1);
ItemStack cursor = viewer.getItemOnCursor();
viewer.setItemOnCursor(new ItemStack(Material.AIR));
@ -124,12 +126,12 @@ public class EnchantConflictGui extends ChestGui {
createItem.setItemMeta(createMeta);
this.backgroundPane.bindItem('C', new GuiItem(createItem, (clickEvent)->{
this.backgroundPane.bindItem('C', new GuiItem(createItem, (clickEvent) -> {
clickEvent.setCancelled(true);
HumanEntity player = clickEvent.getWhoClicked();
// check permission
if(!player.hasPermission(CustomAnvil.editConfigPermission)) {
if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory();
player.sendMessage(GuiGlobalActions.NO_EDIT_PERM);
return;
@ -147,10 +149,10 @@ public class EnchantConflictGui extends ChestGui {
private Consumer<String> prepareCreateItemConsumer(HumanEntity player) {
AtomicReference<Consumer<String>> selfRef = new AtomicReference<>();
Consumer<String> selfCallback = (message) -> {
if(message == null) return;
if (message == null) return;
message = message.toLowerCase(Locale.ROOT);
if("cancel".equalsIgnoreCase(message)) {
if ("cancel".equalsIgnoreCase(message)) {
player.sendMessage("conflict creation cancelled...");
show(player);
return;
@ -161,7 +163,7 @@ public class EnchantConflictGui extends ChestGui {
// Try to find if it already exists in a for loop
// Not the most efficient on large number of conflict, but it should not run often.
for (EnchantConflictGroup conflict : ConfigHolder.CONFLICT_HOLDER.getConflictManager().getConflictList()) {
if(conflict.getName().equalsIgnoreCase(message)){
if (conflict.getName().equalsIgnoreCase(message)) {
player.sendMessage("\u00A7cPlease enter a conflict name that do not already exist...");
// wait next message.
CustomAnvil.Companion.getChatListener().setListenedCallback(player, selfRef.get());
@ -182,11 +184,11 @@ public class EnchantConflictGui extends ChestGui {
String[] emptyStringArray = new String[0];
FileConfiguration config = ConfigHolder.CONFLICT_HOLDER.getConfig();
config.set(message+".enchantments", emptyStringArray);
config.set(message+".notAffectedGroups", emptyStringArray);
config.set(message+".maxEnchantmentBeforeConflict", 0);
config.set(message + ".enchantments", emptyStringArray);
config.set(message + ".notAffectedGroups", emptyStringArray);
config.set(message + ".maxEnchantmentBeforeConflict", 0);
if(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE){
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}
@ -199,7 +201,7 @@ public class EnchantConflictGui extends ChestGui {
return selfCallback;
}
private OutlinePane createEmptyPage(){
private OutlinePane createEmptyPage() {
OutlinePane page = new OutlinePane(0, 0, 9, 5);
page.align(OutlinePane.Alignment.BEGIN);
page.setOrientation(Orientable.Orientation.HORIZONTAL);
@ -207,7 +209,7 @@ public class EnchantConflictGui extends ChestGui {
return page;
}
public void reloadValues(){
public void reloadValues() {
this.conflictGuiMap.forEach((conflict, gui) -> gui.cleanUnused());
this.conflictGuiMap.clear();
this.firstPage.clear();
@ -221,28 +223,28 @@ public class EnchantConflictGui extends ChestGui {
update();
}
public static ItemStack createItemForConflict(EnchantConflictGroup conflict){
public static ItemStack createItemForConflict(EnchantConflictGroup conflict) {
ItemStack item = new ItemStack(conflict.getRepresentativeMaterial());
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(conflict.getName()) + " \u00A7fConflict");
meta.setLore(Arrays.asList(
"\u00A77Enchantment count: \u00A7e"+conflict.getEnchants().size(),
"\u00A77Group count: \u00A7e"+conflict.getCantConflictGroup().getGroups().size(),
"\u00A77Min enchantments count: \u00A7e"+conflict.getMinBeforeBlock()
"\u00A77Enchantment count: \u00A7e" + conflict.getEnchants().size(),
"\u00A77Group count: \u00A7e" + conflict.getCantConflictGroup().getGroups().size(),
"\u00A77Min enchantments count: \u00A7e" + conflict.getMinBeforeBlock()
));
item.setItemMeta(meta);
return item;
}
public void updateValueForConflict(EnchantConflictGroup conflict, boolean shouldUpdate){
public void updateValueForConflict(EnchantConflictGroup conflict, boolean shouldUpdate) {
EnchantConflictSubSettingGui gui = this.conflictGuiMap.get(conflict);
ItemStack item = createItemForConflict(conflict);
GuiItem guiItem;
if(gui == null){
if (gui == null) {
// Create new sub setting gui
guiItem = new GuiItem(item, CustomAnvil.instance);
gui = new EnchantConflictSubSettingGui(this, conflict, guiItem);
@ -251,22 +253,22 @@ public class EnchantConflictGui extends ChestGui {
this.conflictGuiMap.put(conflict, gui);
addToPage(guiItem);
}else{
} else {
// Replace item with the updated one
guiItem = gui.getParentItemForThisGui();
guiItem.setItem(item);
}
gui.updateLocal();
if(shouldUpdate){
if (shouldUpdate) {
update();
}
}
public void removeConflict(EnchantConflictGroup conflict){
public void removeConflict(EnchantConflictGroup conflict) {
EnchantConflictSubSettingGui gui = this.conflictGuiMap.get(conflict);
if(gui == null) return;
if (gui == null) return;
this.conflictGuiMap.remove(conflict);
removeFromPage(gui.getParentItemForThisGui());
@ -276,8 +278,8 @@ public class EnchantConflictGui extends ChestGui {
private void addToPage(GuiItem guiItem) {
// Get first available page or create one
OutlinePane page = this.pages.get(this.pages.size()-1);
if(page.getItems().size() >= 5*9){
OutlinePane page = this.pages.get(this.pages.size() - 1);
if (page.getItems().size() >= 5 * 9) {
page = createEmptyPage();
this.pages.add(page);
}
@ -289,16 +291,16 @@ public class EnchantConflictGui extends ChestGui {
// get item page
OutlinePane page = null;
int pageID = 0;
while(pageID < this.pages.size()){
while (pageID < this.pages.size()) {
OutlinePane tempPage = this.pages.get(pageID);
if(tempPage.getItems().contains(guiItem)){
if (tempPage.getItems().contains(guiItem)) {
page = tempPage;
break;
}
pageID++;
}
if(page == null){// Why...
if (page == null) {// Why...
return;
}
removeFromPage(page, pageID, guiItem);
@ -308,62 +310,62 @@ public class EnchantConflictGui extends ChestGui {
page.removeItem(guiItem);
// There is now a slot available, let fill it if possible
if(pageID < (this.pages.size() - 1)){
OutlinePane newPage = this.pages.get(pageID+1);
if (pageID < (this.pages.size() - 1)) {
OutlinePane newPage = this.pages.get(pageID + 1);
GuiItem nextPageItem = newPage.getItems().get(0);
removeFromPage(newPage, pageID+1, nextPageItem);
removeFromPage(newPage, pageID + 1, nextPageItem);
OutlinePane thisPage = this.pages.get(pageID);
thisPage.addItem(nextPageItem);
}else if(pageID > 0 && page.getItems().isEmpty()){
} else if (pageID > 0 && page.getItems().isEmpty()) {
this.pages.remove(pageID);
}
}
public int getPlayerPageID(UUID uuid){
public int getPlayerPageID(UUID uuid) {
int pageId = this.pageMap.getOrDefault(uuid, 0);
if(pageId >= this.pages.size()){
pageId = this.pages.size()-1;
if (pageId >= this.pages.size()) {
pageId = this.pages.size() - 1;
}
return pageId;
}
public void placeArrow(int page, boolean customise){
public void placeArrow(int page, boolean customise) {
// Place left arrow
addPane(this.backgroundPane);
if(page > 0){
if(customise){
if (page > 0) {
if (customise) {
ItemStack leftItem = this.goLeftItem.getItem();
ItemMeta leftMeta = leftItem.getItemMeta();
leftMeta.setDisplayName("\u00A7eReturn to page " +(page));
leftMeta.setDisplayName("\u00A7eReturn to page " + (page));
leftItem.setItemMeta(leftMeta);
this.goLeftItem.setItem(leftItem);
}
this.backgroundPane.bindItem('L', this.goLeftItem);
}else{
} else {
this.backgroundPane.bindItem('L', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM);
}
// Place right arrow
if(page < pages.size()-1){
if(customise){
if (page < pages.size() - 1) {
if (customise) {
ItemStack rightItem = this.goRightItem.getItem();
ItemMeta rightMeta = rightItem.getItemMeta();
rightMeta.setDisplayName("\u00A7eGo to page " +(page+2));
rightMeta.setDisplayName("\u00A7eGo to page " + (page + 2));
rightItem.setItemMeta(rightMeta);
this.goRightItem.setItem(rightItem);
}
this.backgroundPane.bindItem('R', this.goRightItem);
}else{
} else {
this.backgroundPane.bindItem('R', GuiSharedConstant.SECONDARY_BACKGROUND_ITEM);
}
}
@ -381,7 +383,7 @@ public class EnchantConflictGui extends ChestGui {
addPane(page);
// set title
setTitle("Conflict Config ("+(pageID+1)+"/"+(pages.size())+")");
setTitle("Conflict Config (" + (pageID + 1) + "/" + (pages.size()) + ")");
super.show(humanEntity);

View file

@ -46,10 +46,11 @@ public class EnchantCostConfigGui extends AbstractEnchantConfigGui<EnchantCostSe
EnchantmentRarity rarity = EnchantmentRarity.NO_RARITY;
try {
rarity = EnchantmentProperties.valueOf(key.toUpperCase(Locale.ENGLISH)).getRarity();
}catch (IllegalArgumentException ignored){}
} catch (IllegalArgumentException ignored) {
}
return EnchantCostSettingsGui.enchantCostFactory(prettyKey+" Level Cost", this,
SECTION_NAME+'.'+key, ConfigHolder.DEFAULT_CONFIG, 0, 255,
return EnchantCostSettingsGui.enchantCostFactory(prettyKey + " Level Cost", this,
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG, 0, 255,
rarity.getItemValue(), rarity.getBookValue(),
1, 10, 50);
}

View file

@ -37,8 +37,8 @@ public class EnchantLimitConfigGui extends AbstractEnchantConfigGui<IntSettingsG
String key = enchant.getKey().getKey().toLowerCase(Locale.ROOT);
String prettyKey = CasedStringUtil.snakeToUpperSpacedCase(key);
return IntSettingsGui.intFactory(prettyKey+" Level Limit", this,
SECTION_NAME+'.'+key, ConfigHolder.DEFAULT_CONFIG, 0, 255,
return IntSettingsGui.intFactory(prettyKey + " Level Limit", this,
SECTION_NAME + '.' + key, ConfigHolder.DEFAULT_CONFIG, 0, 255,
enchant.getMaxLevel(),
1, 5, 10, 50, 100);
}

View file

@ -20,12 +20,13 @@ public class MainConfigGui extends ChestGui {
static {
INSTANCE.init();
}
private MainConfigGui() {
super(3, "\u00A78Anvil Config", CustomAnvil.instance);
}
private void init(){
private void init() {
Pattern pattern = new Pattern(
"I00000000",
"012304560",
@ -101,7 +102,7 @@ public class MainConfigGui extends ChestGui {
GuiItem quitItem = new GuiItem(quitItemstack, event -> {
event.setCancelled(true);
event.getWhoClicked().closeInventory();
},CustomAnvil.instance);
}, CustomAnvil.instance);
pane.bindItem('Q', quitItem);
// create & bind "info" item

View file

@ -26,6 +26,7 @@ public abstract class AbstractSettingGui extends ChestGui {
/**
* Prepare necessary object for a setting gui.
*
* @param rows Number of row for this gui.
* @param title Title of this gui.
* @param parent Parent gui to go back when completed.
@ -37,6 +38,7 @@ public abstract class AbstractSettingGui extends ChestGui {
/**
* Prepare necessary object for a setting gui.
*
* @param rows Number of row for this gui.
* @param title Title of this gui.
* @param parent Parent gui to go back when completed.
@ -50,9 +52,10 @@ public abstract class AbstractSettingGui extends ChestGui {
/**
* Initialise and prepare value for this gui.
*
* @param parent Parent gui to go back when completed.
*/
private void initBase(ValueUpdatableGui parent){
private void initBase(ValueUpdatableGui parent) {
Pattern pattern = getGuiPattern();
pane = new PatternPane(0, 0, pattern.getLength(), pattern.getHeight(), pattern);
addPane(pane);
@ -75,6 +78,7 @@ public abstract class AbstractSettingGui extends ChestGui {
/**
* Get main pane for this setting gui.
*
* @return Main pattern pain of this gui.
*/
protected PatternPane getPane() {
@ -89,12 +93,14 @@ public abstract class AbstractSettingGui extends ChestGui {
* <li><b>B</b>: "back to previous gui" button.</li>
* <li><b>0</b>: default background item.</li>
* </ul>
*
* @return The gui's pattern.
*/
protected abstract Pattern getGuiPattern();
/**
* Called when the associated setting need to be saved.
*
* @return true if the save was successful. false otherwise
*/
public abstract boolean onSave();
@ -102,6 +108,7 @@ public abstract class AbstractSettingGui extends ChestGui {
/**
* If this function return true
* the gui assume the associated setting can be saved.
*
* @return true if there is a change to the setting. false otherwise
*/
public abstract boolean hadChange();
@ -111,16 +118,17 @@ public abstract class AbstractSettingGui extends ChestGui {
* <p>
* It is better to keep a factory that hold setting data than find what parameters to use every time.
*/
public abstract static class SettingGuiFactory{
public abstract static class SettingGuiFactory {
protected String configPath;
protected ConfigHolder config;
/**
* Constructor for settings gui factory
*
* @param configPath Configuration path of this setting.
* @param config Configuration holder of this setting.
*/
protected SettingGuiFactory(String configPath, ConfigHolder config){
protected SettingGuiFactory(String configPath, ConfigHolder config) {
this.configPath = configPath;
this.config = config;
}
@ -141,6 +149,7 @@ public abstract class AbstractSettingGui extends ChestGui {
/**
* Create a gui using setting parameters and current setting value.
*
* @return A new instance of the implemented setting gui.
*/
public abstract AbstractSettingGui create();

View file

@ -21,7 +21,7 @@ import java.util.function.Consumer;
/**
* An instance of a gui used to edit a boolean setting.
*/
public class BoolSettingsGui extends AbstractSettingGui{
public class BoolSettingsGui extends AbstractSettingGui {
private final BoolSettingFactory holder;
private final boolean before;
@ -29,6 +29,7 @@ public class BoolSettingsGui extends AbstractSettingGui{
/**
* Create a boolean setting config gui.
*
* @param holder Configuration factory of this setting.
* @param now The defined value of this setting.
*/
@ -57,12 +58,12 @@ public class BoolSettingsGui extends AbstractSettingGui{
/**
* Prepare "return to default value" gui item.
*/
protected void prepareReturnToDefault(){
protected void prepareReturnToDefault() {
ItemStack item = new ItemStack(Material.COMMAND_BLOCK);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7eReset to default value");
meta.setLore(Collections.singletonList("\u00A77Default value is: "+holder.defaultVal));
meta.setLore(Collections.singletonList("\u00A77Default value is: " + holder.defaultVal));
item.setItemMeta(meta);
returnToDefault = new GuiItem(item, event -> {
event.setCancelled(true);
@ -75,16 +76,16 @@ public class BoolSettingsGui extends AbstractSettingGui{
/**
* Update item using the setting value to match the new value
*/
protected void updateValueDisplay(){
protected void updateValueDisplay() {
PatternPane pane = getPane();
// Get displayed value for this config.
String displayedName;
Material displayedMat;
if(now){
if (now) {
displayedName = "\u00A7aTrue";
displayedMat = Material.GREEN_TERRACOTTA;
}else{
} else {
displayedName = "\u00A7cFalse";
displayedMat = Material.RED_TERRACOTTA;
}
@ -100,9 +101,9 @@ public class BoolSettingsGui extends AbstractSettingGui{
// reset to default
GuiItem returnToDefault;
if(now != holder.defaultVal){
if (now != holder.defaultVal) {
returnToDefault = this.returnToDefault;
}else{
} else {
returnToDefault = GuiGlobalItems.backgroundItem();
}
pane.bindItem('D', returnToDefault);
@ -112,8 +113,8 @@ public class BoolSettingsGui extends AbstractSettingGui{
/**
* @return A consumer to update the current setting's value.
*/
protected Consumer<InventoryClickEvent> inverseNowConsumer(){
return event->{
protected Consumer<InventoryClickEvent> inverseNowConsumer() {
return event -> {
event.setCancelled(true);
now = !now;
updateValueDisplay();
@ -126,7 +127,7 @@ public class BoolSettingsGui extends AbstractSettingGui{
holder.config.getConfig().set(holder.configPath, now);
MetricsUtil.INSTANCE.notifyChange(this.holder.config, this.holder.configPath);
if(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE){
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}
return true;
@ -139,6 +140,7 @@ public class BoolSettingsGui extends AbstractSettingGui{
/**
* Create a bool setting factory from setting's parameters.
*
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param configPath Configuration path of this setting.
@ -148,9 +150,9 @@ public class BoolSettingsGui extends AbstractSettingGui{
*/
public static BoolSettingFactory boolFactory(@NotNull String title, ValueUpdatableGui parent,
String configPath, ConfigHolder config,
boolean defaultVal){
boolean defaultVal) {
return new BoolSettingFactory(
title,parent,
title, parent,
configPath, config,
defaultVal);
}
@ -158,12 +160,15 @@ public class BoolSettingsGui extends AbstractSettingGui{
/**
* A factory for a boolean setting gui that hold setting's information.
*/
public static class BoolSettingFactory extends SettingGuiFactory{
@NotNull String title; ValueUpdatableGui parent;
public static class BoolSettingFactory extends SettingGuiFactory {
@NotNull
String title;
ValueUpdatableGui parent;
boolean defaultVal;
/**
* Constructor for a boolean setting gui factory.
*
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param configPath Configuration path of this setting.
@ -173,7 +178,7 @@ public class BoolSettingsGui extends AbstractSettingGui{
protected BoolSettingFactory(
@NotNull String title, ValueUpdatableGui parent,
String configPath, ConfigHolder config,
boolean defaultVal){
boolean defaultVal) {
super(configPath, config);
this.title = title;
this.parent = parent;
@ -192,7 +197,7 @@ public class BoolSettingsGui extends AbstractSettingGui{
/**
* @return The configured value for the associated setting.
*/
public boolean getConfiguredValue(){
public boolean getConfiguredValue() {
return this.config.getConfig().getBoolean(this.configPath, this.defaultVal);
}

View file

@ -34,6 +34,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
/**
* Create an enchantment cost setting config gui.
*
* @param holder Configuration factory of this setting.
* @param nowItem The defined value of this setting item's value.
*/
@ -54,7 +55,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
protected void initStepsValue() {
super.initStepsValue();
int nowBook = ((EnchantCostSettingFactory)this.holder).getConfiguredBookValue();
int nowBook = ((EnchantCostSettingFactory) this.holder).getConfiguredBookValue();
this.beforeBook = nowBook;
this.nowBook = nowBook;
}
@ -81,7 +82,8 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
bookMeta.setDisplayName("\u00A7aCost of an Enchantment by Book");
bookMeta.setLore(Arrays.asList(
"\u00A77Cost per result item level of an sacrifice enchantment",
"\u00A77Only apply if sacrificed item \u00A7cis \u00A77a book"));bookItemstack.setItemMeta(bookMeta);
"\u00A77Only apply if sacrificed item \u00A7cis \u00A77a book"));
bookItemstack.setItemMeta(bookMeta);
// sword display
ItemStack swordItemstack = new ItemStack(Material.WOODEN_SWORD);
@ -100,7 +102,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
}
@Override
protected void prepareReturnToDefault(){
protected void prepareReturnToDefault() {
ItemStack item = new ItemStack(Material.COMMAND_BLOCK);
ItemMeta meta = item.getItemMeta();
@ -122,7 +124,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
}
@Override
protected void updateValueDisplay(){
protected void updateValueDisplay() {
super.updateValueDisplay();
PatternPane pane = getPane();
@ -133,32 +135,32 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
// minus item
GuiItem minusItem;
if(nowBook > holder.min){
if (nowBook > holder.min) {
int planned = Math.max(holder.min, nowBook - step);
ItemStack item = new ItemStack(Material.RED_TERRACOTTA);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7e"+nowBook+" -> "+planned + " \u00A7r(\u00A7c-"+(nowBook-planned)+"\u00A7r)");
meta.setDisplayName("\u00A7e" + nowBook + " -> " + planned + " \u00A7r(\u00A7c-" + (nowBook - planned) + "\u00A7r)");
meta.setLore(AbstractSettingGui.CLICK_LORE);
item.setItemMeta(meta);
minusItem = new GuiItem(item, updateNowBookConsumer(planned), CustomAnvil.instance);
}else{
} else {
minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
}
pane.bindItem('M', minusItem);
//plus item
GuiItem plusItem;
if(nowBook < holder.max){
if (nowBook < holder.max) {
int planned = Math.min(holder.max, nowBook + step);
ItemStack item = new ItemStack(Material.GREEN_TERRACOTTA);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7e"+nowBook+" -> "+planned + " \u00A7r(\u00A7a+"+(planned-nowBook)+"\u00A7r)");
meta.setDisplayName("\u00A7e" + nowBook + " -> " + planned + " \u00A7r(\u00A7a+" + (planned - nowBook) + "\u00A7r)");
meta.setLore(AbstractSettingGui.CLICK_LORE);
item.setItemMeta(meta);
plusItem = new GuiItem(item, updateNowBookConsumer(planned), CustomAnvil.instance);
}else{
} else {
plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
}
pane.bindItem('P', plusItem);
@ -166,7 +168,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
// "result" display
ItemStack resultPaper = new ItemStack(Material.PAPER);
ItemMeta resultMeta = resultPaper.getItemMeta();
resultMeta.setDisplayName("\u00A7eValue: "+nowBook);
resultMeta.setDisplayName("\u00A7eValue: " + nowBook);
resultPaper.setItemMeta(resultMeta);
GuiItem resultItem = new GuiItem(resultPaper, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
@ -174,9 +176,9 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
// reset to default
GuiItem returnToDefault;
if(now != holder.defaultVal || nowBook != holder.defaultBookVal){
if (now != holder.defaultVal || nowBook != holder.defaultBookVal) {
returnToDefault = this.returnToDefault;
}else{
} else {
returnToDefault = GuiGlobalItems.backgroundItem();
}
pane.bindItem('D', returnToDefault);
@ -188,8 +190,8 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
* @param planned Value to change current book cost setting to.
* @return A consumer to update the current book cost setting's value.
*/
protected Consumer<InventoryClickEvent> updateNowBookConsumer(int planned){
return event->{
protected Consumer<InventoryClickEvent> updateNowBookConsumer(int planned) {
return event -> {
event.setCancelled(true);
nowBook = planned;
updateValueDisplay();
@ -204,11 +206,11 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
@Override
public boolean onSave() {
holder.config.getConfig().set(holder.configPath+ITEM_PATH, now);
holder.config.getConfig().set(holder.configPath+BOOK_PATH, nowBook);
holder.config.getConfig().set(holder.configPath + ITEM_PATH, now);
holder.config.getConfig().set(holder.configPath + BOOK_PATH, nowBook);
MetricsUtil.INSTANCE.notifyChange(this.holder.config, this.holder.configPath);
if(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE){
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}
return true;
@ -221,6 +223,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
/**
* Create an int setting factory from setting's parameters.
*
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param configPath Configuration path of this setting.
@ -239,9 +242,9 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
@NotNull String title, ValueUpdatableGui parent,
String configPath, ConfigHolder config,
int min, int max, int defaultItemVal, int defaultBookVal,
int... steps){
int... steps) {
return new EnchantCostSettingFactory(
title,parent,
title, parent,
configPath, config,
min, max, defaultItemVal, defaultBookVal, steps);
}
@ -255,6 +258,7 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
/**
* Constructor for an enchantment cost setting gui factory.
*
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param configPath Configuration path of this setting.
@ -272,9 +276,9 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
@NotNull String title, ValueUpdatableGui parent,
String configPath, ConfigHolder config,
int min, int max, int defaultItemVal, int defaultBookVal,
int... steps){
int... steps) {
super(title,parent,
super(title, parent,
configPath, config,
min, max, defaultItemVal, steps);
this.defaultBookVal = defaultBookVal;
@ -285,14 +289,14 @@ public class EnchantCostSettingsGui extends IntSettingsGui {
*/
@Override
public int getConfiguredValue() {
return this.config.getConfig().getInt(this.configPath+ITEM_PATH, this.defaultVal);
return this.config.getConfig().getInt(this.configPath + ITEM_PATH, this.defaultVal);
}
/**
* @return The configured value for the enchant setting book value.
*/
public int getConfiguredBookValue(){
return this.config.getConfig().getInt(this.configPath+BOOK_PATH, this.defaultBookVal);
public int getConfiguredBookValue() {
return this.config.getConfig().getInt(this.configPath + BOOK_PATH, this.defaultBookVal);
}
@Override

View file

@ -24,7 +24,7 @@ import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
public class EnchantSelectSettingGui extends AbstractSettingGui{
public class EnchantSelectSettingGui extends AbstractSettingGui {
SelectEnchantmentContainer enchantContainer;
int page;
@ -57,7 +57,7 @@ public class EnchantSelectSettingGui extends AbstractSettingGui{
);
}
protected void initGroups(){
protected void initGroups() {
// Add enchantment gui item
OutlinePane filledEnchant = new OutlinePane(0, 0, 9, 5);
filledEnchant.setPriority(Pane.Priority.HIGH);
@ -66,7 +66,7 @@ public class EnchantSelectSettingGui extends AbstractSettingGui{
Set<Enchantment> illegalEnchant = this.enchantContainer.illegalEnchantments();
for (Enchantment enchant : GuiSharedConstant.SORTED_ENCHANTMENT_LIST) {
if(illegalEnchant.contains(enchant)) {
if (illegalEnchant.contains(enchant)) {
return;
}
filledEnchant.addItem(getGuiItemFromEnchant(enchant));
@ -76,13 +76,13 @@ public class EnchantSelectSettingGui extends AbstractSettingGui{
}
private GuiItem getGuiItemFromEnchant(Enchantment enchantment){
private GuiItem getGuiItemFromEnchant(Enchantment enchantment) {
boolean isIn = this.selectedEnchant.contains(enchantment);
Material usedMaterial;
if(isIn){
if (isIn) {
usedMaterial = Material.ENCHANTED_BOOK;
}else{
} else {
usedMaterial = Material.BOOK;
}
ItemStack item = new ItemStack(usedMaterial);
@ -98,22 +98,22 @@ public class EnchantSelectSettingGui extends AbstractSettingGui{
private static final List<String> TRUE_LORE = Collections.singletonList("\u00A77Value: \u00A7aSelected");
private static final List<String> FALSE_LORE = Collections.singletonList("\u00A77Value: \u00A7cNot Selected");
public void setEnchantItemMeta(ItemStack item, String name, boolean isIn){
public void setEnchantItemMeta(ItemStack item, String name, boolean isIn) {
ItemMeta meta = item.getItemMeta();
if(meta == null){
CustomAnvil.instance.getLogger().warning("Could not create item for enchantment: "+name+":\n" +
"Item do not gave item meta: "+item+". Using placeholder instead");
if (meta == null) {
CustomAnvil.instance.getLogger().warning("Could not create item for enchantment: " + name + ":\n" +
"Item do not gave item meta: " + item + ". Using placeholder instead");
item.setType(Material.PAPER);
meta = item.getItemMeta();
assert meta != null;
}
meta.setDisplayName("\u00A7"+(isIn ? 'a' : 'c')+ CasedStringUtil.snakeToUpperSpacedCase(name));
if(isIn){
meta.setDisplayName("\u00A7" + (isIn ? 'a' : 'c') + CasedStringUtil.snakeToUpperSpacedCase(name));
if (isIn) {
meta.addEnchant(Enchantment.DAMAGE_UNDEAD, 1, true);
meta.setLore(TRUE_LORE);
}else{
} else {
meta.removeEnchant(Enchantment.DAMAGE_UNDEAD);
meta.setLore(FALSE_LORE);
}
@ -122,17 +122,17 @@ public class EnchantSelectSettingGui extends AbstractSettingGui{
item.setItemMeta(meta);
}
private Consumer<InventoryClickEvent> getEnchantItemConsumer(Enchantment enchant, GuiItem guiItem){
private Consumer<InventoryClickEvent> getEnchantItemConsumer(Enchantment enchant, GuiItem guiItem) {
return event -> {
event.setCancelled(true);
ItemStack item = guiItem.getItem();
boolean isIn = this.selectedEnchant.contains(enchant);
if(isIn){
if (isIn) {
this.selectedEnchant.remove(enchant);
item.setType(Material.BOOK);
}else{
} else {
this.selectedEnchant.add(enchant);
item.setType(Material.ENCHANTED_BOOK);
}

View file

@ -20,10 +20,13 @@ import xyz.alexcrea.cuanvil.gui.config.SelectGroupContainer;
import xyz.alexcrea.cuanvil.gui.util.GuiSharedConstant;
import xyz.alexcrea.cuanvil.util.CasedStringUtil;
import java.util.*;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
public class GroupSelectSettingGui extends AbstractSettingGui{
public class GroupSelectSettingGui extends AbstractSettingGui {
SelectGroupContainer groupContainer;
int page;
@ -56,7 +59,7 @@ public class GroupSelectSettingGui extends AbstractSettingGui{
);
}
protected void initGroups(){
protected void initGroups() {
// Add enchantment gui item
OutlinePane filledEnchant = new OutlinePane(0, 0, 9, 5);
filledEnchant.setPriority(Pane.Priority.HIGH);
@ -65,7 +68,7 @@ public class GroupSelectSettingGui extends AbstractSettingGui{
Set<AbstractMaterialGroup> illegalGroup = this.groupContainer.illegalGroups();
for (AbstractMaterialGroup group : ConfigHolder.ITEM_GROUP_HOLDER.getItemGroupsManager().getGroupMap().values()) {
if(illegalGroup.contains(group)) {
if (illegalGroup.contains(group)) {
return;
}
filledEnchant.addItem(getGuiItemFromGroup(group));
@ -75,7 +78,7 @@ public class GroupSelectSettingGui extends AbstractSettingGui{
}
private GuiItem getGuiItemFromGroup(AbstractMaterialGroup group){
private GuiItem getGuiItemFromGroup(AbstractMaterialGroup group) {
boolean isIn = this.selectedGroups.contains(group);
Material usedMaterial = group.getRepresentativeMaterial();
@ -91,22 +94,22 @@ public class GroupSelectSettingGui extends AbstractSettingGui{
private static final List<String> TRUE_LORE = Collections.singletonList("\u00A77Value: \u00A7aSelected");
private static final List<String> FALSE_LORE = Collections.singletonList("\u00A77Value: \u00A7cNot Selected");
public void setGroupItemMeta(ItemStack item, String name, boolean isIn){
public void setGroupItemMeta(ItemStack item, String name, boolean isIn) {
ItemMeta meta = item.getItemMeta();
if(meta == null){
CustomAnvil.instance.getLogger().warning("Could not create item for group: "+name+":\n" +
"Item do not gave item meta: "+item+". Using placeholder instead");
if (meta == null) {
CustomAnvil.instance.getLogger().warning("Could not create item for group: " + name + ":\n" +
"Item do not gave item meta: " + item + ". Using placeholder instead");
item.setType(Material.PAPER);
meta = item.getItemMeta();
assert meta != null;
}
meta.setDisplayName("\u00A7"+(isIn ? 'a' : 'c')+ CasedStringUtil.snakeToUpperSpacedCase(name));
if(isIn){
meta.setDisplayName("\u00A7" + (isIn ? 'a' : 'c') + CasedStringUtil.snakeToUpperSpacedCase(name));
if (isIn) {
meta.addEnchant(Enchantment.DAMAGE_UNDEAD, 1, true);
meta.setLore(TRUE_LORE);
}else{
} else {
meta.removeEnchant(Enchantment.DAMAGE_UNDEAD);
meta.setLore(FALSE_LORE);
}
@ -115,14 +118,14 @@ public class GroupSelectSettingGui extends AbstractSettingGui{
item.setItemMeta(meta);
}
private Consumer<InventoryClickEvent> getGroupItemConsumer(AbstractMaterialGroup group, GuiItem guiItem){
private Consumer<InventoryClickEvent> getGroupItemConsumer(AbstractMaterialGroup group, GuiItem guiItem) {
return event -> {
event.setCancelled(true);
boolean isIn = this.selectedGroups.contains(group);
if(isIn){
if (isIn) {
this.selectedGroups.remove(group);
}else{
} else {
this.selectedGroups.add(group);
}

View file

@ -23,7 +23,7 @@ import java.util.function.Consumer;
/**
* An instance of a gui used to edit an int setting.
*/
public class IntSettingsGui extends AbstractSettingGui{
public class IntSettingsGui extends AbstractSettingGui {
protected final IntSettingFactory holder;
protected final int before;
@ -32,6 +32,7 @@ public class IntSettingsGui extends AbstractSettingGui{
/**
* Create an int setting config gui.
*
* @param holder Configuration factory of this setting.
* @param now The defined value of this setting.
*/
@ -59,15 +60,16 @@ public class IntSettingsGui extends AbstractSettingGui{
}
protected GuiItem returnToDefault;
/**
* Prepare "return to default value" gui item.
*/
protected void prepareReturnToDefault(){
protected void prepareReturnToDefault() {
ItemStack item = new ItemStack(Material.COMMAND_BLOCK);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7eReset to default value");
meta.setLore(Collections.singletonList("\u00A77Default value is: "+holder.defaultVal));
meta.setLore(Collections.singletonList("\u00A77Default value is: " + holder.defaultVal));
item.setItemMeta(meta);
returnToDefault = new GuiItem(item, event -> {
event.setCancelled(true);
@ -80,22 +82,22 @@ public class IntSettingsGui extends AbstractSettingGui{
/**
* Update item using the setting value to match the new value.
*/
protected void updateValueDisplay(){
protected void updateValueDisplay() {
PatternPane pane = getPane();
// minus item
GuiItem minusItem;
if(now > holder.min){
if (now > holder.min) {
int planned = Math.max(holder.min, now - step);
ItemStack item = new ItemStack(Material.RED_TERRACOTTA);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7e"+now+" -> "+planned + " \u00A7r(\u00A7c-"+(now-planned)+"\u00A7r)");
meta.setDisplayName("\u00A7e" + now + " -> " + planned + " \u00A7r(\u00A7c-" + (now - planned) + "\u00A7r)");
meta.setLore(AbstractSettingGui.CLICK_LORE);
item.setItemMeta(meta);
minusItem = new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance);
}else{
} else {
minusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
}
pane.bindItem('-', minusItem);
@ -103,16 +105,16 @@ public class IntSettingsGui extends AbstractSettingGui{
//plus item
// may do a function to generalise ?
GuiItem plusItem;
if(now < holder.max){
if (now < holder.max) {
int planned = Math.min(holder.max, now + step);
ItemStack item = new ItemStack(Material.GREEN_TERRACOTTA);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7e"+now+" -> "+planned + " \u00A7r(\u00A7a+"+(planned-now)+"\u00A7r)");
meta.setDisplayName("\u00A7e" + now + " -> " + planned + " \u00A7r(\u00A7a+" + (planned - now) + "\u00A7r)");
meta.setLore(AbstractSettingGui.CLICK_LORE);
item.setItemMeta(meta);
plusItem = new GuiItem(item, updateNowConsumer(planned), CustomAnvil.instance);
}else{
} else {
plusItem = GuiGlobalItems.backgroundItem(Material.BARRIER);
}
pane.bindItem('+', plusItem);
@ -120,7 +122,7 @@ public class IntSettingsGui extends AbstractSettingGui{
// "result" display
ItemStack resultPaper = new ItemStack(Material.PAPER);
ItemMeta resultMeta = resultPaper.getItemMeta();
resultMeta.setDisplayName("\u00A7eValue: "+now);
resultMeta.setDisplayName("\u00A7eValue: " + now);
resultPaper.setItemMeta(resultMeta);
GuiItem resultItem = new GuiItem(resultPaper, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
@ -128,9 +130,9 @@ public class IntSettingsGui extends AbstractSettingGui{
// reset to default
GuiItem returnToDefault;
if(now != holder.defaultVal){
if (now != holder.defaultVal) {
returnToDefault = this.returnToDefault;
}else{
} else {
returnToDefault = GuiGlobalItems.backgroundItem();
}
pane.bindItem('D', returnToDefault);
@ -142,8 +144,8 @@ public class IntSettingsGui extends AbstractSettingGui{
* @param planned Value to change current setting to.
* @return A consumer to update the current setting's value.
*/
protected Consumer<InventoryClickEvent> updateNowConsumer(int planned){
return event->{
protected Consumer<InventoryClickEvent> updateNowConsumer(int planned) {
return event -> {
event.setCancelled(true);
now = planned;
updateValueDisplay();
@ -154,12 +156,12 @@ public class IntSettingsGui extends AbstractSettingGui{
/**
* Initialise step items.
*/
protected void initStepsValue(){
protected void initStepsValue() {
// Put background glass on the background of 'a' to 'b'
GuiItem background = GuiGlobalItems.backgroundItem();
PatternPane pane = getPane();
for (char i = 'a'; i < (getMidStepChar()-'a')*2+1; i++) {
for (char i = 'a'; i < (getMidStepChar() - 'a') * 2 + 1; i++) {
pane.bindItem(i, background);
}
// Then update legit step values
@ -169,35 +171,37 @@ public class IntSettingsGui extends AbstractSettingGui{
/**
* Update steps items value.
*/
protected void updateStepValue(){
if(holder.steps.length <= 1) return;
protected void updateStepValue() {
if (holder.steps.length <= 1) return;
// We assume steps have a length of 2k+1 cause its more pretty
char val = getMidStepChar();
// Offset to start (not the best way to do it)
val -= (char) ((holder.steps.length-1)/2);
val -= (char) ((holder.steps.length - 1) / 2);
// Then place items
PatternPane pane = getPane();
for (int i = 0; i < holder.steps.length; i++) {
pane.bindItem(val+i, stepGuiItem(i));
pane.bindItem(val + i, stepGuiItem(i));
}
}
/**
* Step use lower case character from 'a' to a certain char.
*
* @return The middle value of the character set for steps.
*/
protected char getMidStepChar(){
protected char getMidStepChar() {
return 'e';
}
/**
* Create a step item from a step value.
*
* @param stepIndex the index of the step item.
* @return A step item corresponding to its index value.
*/
protected GuiItem stepGuiItem(int stepIndex){
protected GuiItem stepGuiItem(int stepIndex) {
int stepValue = holder.steps[stepIndex];
// Get material properties
@ -205,15 +209,15 @@ public class IntSettingsGui extends AbstractSettingGui{
StringBuilder stepName = new StringBuilder("\u00A7");
List<String> stepLore;
Consumer<InventoryClickEvent> clickEvent;
if(stepValue == step){
if (stepValue == step) {
stepMat = Material.GREEN_STAINED_GLASS_PANE;
stepName.append('a');
stepLore = Collections.singletonList("\u00A77Value is changing by "+stepValue);
stepLore = Collections.singletonList("\u00A77Value is changing by " + stepValue);
clickEvent = GuiGlobalActions.stayInPlace;
}else{
} else {
stepMat = Material.RED_STAINED_GLASS_PANE;
stepName.append('c');
stepLore = Collections.singletonList("\u00A77Click here to change the value by "+stepValue);
stepLore = Collections.singletonList("\u00A77Click here to change the value by " + stepValue);
clickEvent = updateStepValue(stepValue);
}
stepName.append("Step of: ").append(stepValue);
@ -233,7 +237,7 @@ public class IntSettingsGui extends AbstractSettingGui{
* @param stepValue Value to change current step to.
* @return A consumer to update the current step of this setting.
*/
protected Consumer<InventoryClickEvent> updateStepValue(int stepValue){
protected Consumer<InventoryClickEvent> updateStepValue(int stepValue) {
return event -> {
event.setCancelled(true);
this.step = stepValue;
@ -248,7 +252,7 @@ public class IntSettingsGui extends AbstractSettingGui{
holder.config.getConfig().set(holder.configPath, now);
MetricsUtil.INSTANCE.notifyChange(this.holder.config, this.holder.configPath);
if(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE){
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
return holder.config.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}
return true;
@ -261,6 +265,7 @@ public class IntSettingsGui extends AbstractSettingGui{
/**
* Create an int setting factory from setting's parameters.
*
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param configPath Configuration path of this setting.
@ -276,9 +281,9 @@ public class IntSettingsGui extends AbstractSettingGui{
*/
public static IntSettingFactory intFactory(@NotNull String title, ValueUpdatableGui parent,
String configPath, ConfigHolder config,
int min, int max, int defaultVal, int... steps){
int min, int max, int defaultVal, int... steps) {
return new IntSettingFactory(
title,parent,
title, parent,
configPath, config,
min, max, defaultVal, steps);
}
@ -286,12 +291,18 @@ public class IntSettingsGui extends AbstractSettingGui{
/**
* A factory for an int setting gui that hold setting's information.
*/
public static class IntSettingFactory extends SettingGuiFactory{
@NotNull String title; ValueUpdatableGui parent;
int min; int max; int defaultVal; int[] steps;
public static class IntSettingFactory extends SettingGuiFactory {
@NotNull
String title;
ValueUpdatableGui parent;
int min;
int max;
int defaultVal;
int[] steps;
/**
* Constructor for an int setting gui factory.
*
* @param title The title of the gui.
* @param parent Parent gui to go back when completed.
* @param configPath Configuration path of this setting.
@ -307,7 +318,7 @@ public class IntSettingsGui extends AbstractSettingGui{
protected IntSettingFactory(
@NotNull String title, ValueUpdatableGui parent,
String configPath, ConfigHolder config,
int min, int max, int defaultVal, int... steps){
int min, int max, int defaultVal, int... steps) {
super(configPath, config);
this.title = title;
this.parent = parent;
@ -328,7 +339,7 @@ public class IntSettingsGui extends AbstractSettingGui{
/**
* @return The configured value for the associated setting.
*/
public int getConfiguredValue(){
public int getConfiguredValue() {
return this.config.getConfig().getInt(this.configPath, this.defaultVal);
}

View file

@ -85,7 +85,7 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
// Displayed item will be updated later
this.enchantSettingItem = new GuiItem(new ItemStack(Material.ENCHANTED_BOOK), (event)->{
this.enchantSettingItem = new GuiItem(new ItemStack(Material.ENCHANTED_BOOK), (event) -> {
event.setCancelled(true);
EnchantSelectSettingGui enchantGui = new EnchantSelectSettingGui(
"\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.getName()) + " \u00A75Enchantments",
@ -93,7 +93,7 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
enchantGui.show(event.getWhoClicked());
}, CustomAnvil.instance);
this.groupSettingItem = new GuiItem(new ItemStack(Material.PAPER), (event)->{
this.groupSettingItem = new GuiItem(new ItemStack(Material.PAPER), (event) -> {
event.setCancelled(true);
GroupSelectSettingGui enchantGui = new GroupSelectSettingGui(
"\u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(this.enchantConflict.getName()) + " \u00A73Groups",
@ -103,7 +103,7 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
this.minBeforeActiveSettingFactory = IntSettingsGui.intFactory(
"\u00A78Minimum enchantment count",
this, this.enchantConflict.getName()+".maxEnchantmentBeforeConflict", ConfigHolder.CONFLICT_HOLDER,
this, this.enchantConflict.getName() + ".maxEnchantmentBeforeConflict", ConfigHolder.CONFLICT_HOLDER,
0, 255, 0, 1
);
@ -116,7 +116,7 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
}
private ConfirmActionGui createDeleteGui() {
Supplier<Boolean> deleteSupplier = () ->{
Supplier<Boolean> deleteSupplier = () -> {
EnchantConflictManager manager = ConfigHolder.CONFLICT_HOLDER.getConflictManager();
// Remove from manager
@ -136,14 +136,14 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
// Save
boolean success = true;
if(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE){
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
success = ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}
return success;
};
return new ConfirmActionGui("\u00A7cDelete \u00A7e"+CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.getName())+"\u00A7c?",
return new ConfirmActionGui("\u00A7cDelete \u00A7e" + CasedStringUtil.snakeToUpperSpacedCase(enchantConflict.getName()) + "\u00A7c?",
"\u00A77Confirm that you want to delete this conflict.",
this, this.parent, deleteSupplier
);
@ -155,16 +155,16 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
// Parent should call updateLocal
}
public void updateLocal(){
if(!this.shouldWorld) return;
public void updateLocal() {
if (!this.shouldWorld) return;
// Prepare enchantment lore
ArrayList<String> enchantLore = new ArrayList<>();
enchantLore.add("\u00A77Allow you to select a list of \u00A75Enchantments \u00A77that this conflict should include");
Set<Enchantment> enchants = getSelectedEnchantments();
if(enchants.isEmpty()){
if (enchants.isEmpty()) {
enchantLore.add("\u00A77There is no included enchantment for this conflict.");
}else{
} else {
enchantLore.add("\u00A77List of included enchantment for this conflict:");
Iterator<Enchantment> enchantIterator = enchants.iterator();
@ -175,8 +175,8 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
String formattedName = CasedStringUtil.snakeToUpperSpacedCase(enchantIterator.next().getKey().getKey());
enchantLore.add("\u00A77- \u00A75" + formattedName);
}
if(greaterThanMax){
enchantLore.add("\u00A77And "+(enchants.size()-4)+" more...");
if (greaterThanMax) {
enchantLore.add("\u00A77And " + (enchants.size() - 4) + " more...");
}
}
@ -185,9 +185,9 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
ArrayList<String> groupLore = new ArrayList<>();
groupLore.add("\u00A77Allow you to select a list of \u00A73Groups \u00A77that this conflict should include");
Set<AbstractMaterialGroup> grouos = getSelectedGroups();
if(grouos.isEmpty()){
if (grouos.isEmpty()) {
groupLore.add("\u00A77There is no excluded groups for this conflict.");
}else{
} else {
groupLore.add("\u00A77List of excluded groups for this conflict:");
Iterator<AbstractMaterialGroup> groupIterator = grouos.iterator();
@ -199,8 +199,8 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
groupLore.add("\u00A77- \u00A73" + formattedName);
}
if(greaterThanMax){
groupLore.add("\u00A77And "+(grouos.size()-4)+" more...");
if (greaterThanMax) {
groupLore.add("\u00A77And " + (grouos.size() - 4) + " more...");
}
}
@ -231,7 +231,7 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
update();
}
public void cleanUnused(){
public void cleanUnused() {
for (HumanEntity viewer : getViewers()) {
this.parent.show(viewer);
}
@ -247,9 +247,9 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
@Override
public void show(@NotNull HumanEntity humanEntity) {
if(this.shouldWorld){
if (this.shouldWorld) {
super.show(humanEntity);
}else{
} else {
this.parent.show(humanEntity);
}
}
@ -267,8 +267,8 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
@Override
public boolean setSelectedEnchantments(Set<Enchantment> enchantments) {
if(!this.shouldWorld) {
CustomAnvil.instance.getLogger().info("Trying to save "+enchantConflict.getName()+" enchants but sub config is destroyed");
if (!this.shouldWorld) {
CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict.getName() + " enchants but sub config is destroyed");
return false;
}
@ -281,17 +281,17 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
for (Enchantment enchantment : enchantments) {
enchantKeys[index++] = enchantment.getKey().getKey();
}
ConfigHolder.CONFLICT_HOLDER.getConfig().set(enchantConflict.getName()+".enchantments", enchantKeys);
ConfigHolder.CONFLICT_HOLDER.getConfig().set(enchantConflict.getName() + ".enchantments", enchantKeys);
try {
updateGuiValues();
}catch (Exception e){
CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for "+this.enchantConflict.getName(), e);
} catch (Exception e) {
CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating enchants for " + this.enchantConflict.getName(), e);
}
// Save file configuration to disk
if(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE){
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
return ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}
@ -312,8 +312,8 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
@Override
public boolean setSelectedGroups(Set<AbstractMaterialGroup> groups) {
if(!this.shouldWorld) {
CustomAnvil.instance.getLogger().info("Trying to save "+enchantConflict.getName()+" groups but sub config is destroyed");
if (!this.shouldWorld) {
CustomAnvil.instance.getLogger().info("Trying to save " + enchantConflict.getName() + " groups but sub config is destroyed");
return false;
}
@ -326,16 +326,16 @@ public class EnchantConflictSubSettingGui extends ValueUpdatableGui implements S
for (AbstractMaterialGroup group : groups) {
groupsNames[index++] = group.getName();
}
ConfigHolder.CONFLICT_HOLDER.getConfig().set(this.enchantConflict.getName()+".notAffectedGroups", groupsNames);
ConfigHolder.CONFLICT_HOLDER.getConfig().set(this.enchantConflict.getName() + ".notAffectedGroups", groupsNames);
try {
updateGuiValues();
}catch (Exception e){
CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for "+this.enchantConflict.getName(), e);
} catch (Exception e) {
CustomAnvil.instance.getLogger().log(Level.WARNING, "An error occurred while updating group for " + this.enchantConflict.getName(), e);
}
// Save file configuration to disk
if(GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE){
if (GuiSharedConstant.TEMPORARY_DO_SAVE_TO_DISK_EVERY_CHANGE) {
return ConfigHolder.CONFLICT_HOLDER.saveToDisk(GuiSharedConstant.TEMPORARY_DO_BACKUP_EVERY_SAVE);
}

View file

@ -27,6 +27,7 @@ public class GuiGlobalActions {
/**
* Create a consumer to create and open a new GUI.
* Used with InventoryClickEvent as the consumer argument as it is planned to be used on click on an GuiItem.
*
* @param clazz The class of the gui to open.
* It is assumed this class contain a constructor requiring arguments of argClass in the same order as argClass array.
* @param argClass Classes of the argument that will be passed to the constructor of the GUI class.
@ -36,12 +37,12 @@ public class GuiGlobalActions {
public static @NotNull Consumer<InventoryClickEvent> openGuiAction(
@NotNull Class<? extends Gui> clazz,
@NotNull Class<?>[] argClass,
@NotNull Object... args){
@NotNull Object... args) {
return event -> {
event.setCancelled(true);
HumanEntity player = event.getWhoClicked();
// Do not allow to open inventory if player do not have edit configuration permission
if(!player.hasPermission(CustomAnvil.editConfigPermission)) {
if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory();
player.sendMessage(NO_EDIT_PERM);
return;
@ -62,22 +63,24 @@ public class GuiGlobalActions {
/**
* Create a consumer to create and open a new GUI.
* Used with InventoryClickEvent as the consumer argument as it is planned to be used on click on an GuiItem.
*
* @param clazz The class of the gui to open.
* It is assumed this class contain a constructor with no argument.
* @return A consumer to create a new gui and open it.
*/
public static @NotNull Consumer<InventoryClickEvent> openGuiAction(
@NotNull Class<? extends Gui> clazz){
@NotNull Class<? extends Gui> clazz) {
return openGuiAction(clazz, new Class<?>[0]);
}
/**
* Create a consumer to open a setting gui from a setting GUI factory.
* Used with InventoryClickEvent as the consumer argument as it is planned to be used on click on an GuiItem.
*
* @param factory The setting gui factory.
* @return A consumer to create and open a new setting GUI.
*/
public static @NotNull Consumer<InventoryClickEvent> openSettingGuiAction(AbstractSettingGui.SettingGuiFactory factory){
public static @NotNull Consumer<InventoryClickEvent> openSettingGuiAction(AbstractSettingGui.SettingGuiFactory factory) {
return event -> {
event.setCancelled(true);
Gui gui = factory.create();
@ -88,6 +91,7 @@ public class GuiGlobalActions {
/**
* Create a consumer to open a global GUI.
* Used with InventoryClickEvent as the consumer argument as it is planned to be used on click on an GuiItem.
*
* @param goal The gui to open when consumer is run.
* @return A consumer to open a global GUI.
*/
@ -95,7 +99,7 @@ public class GuiGlobalActions {
return event -> {
HumanEntity player = event.getWhoClicked();
// Do not allow to open inventory if player do not have edit configuration permission
if(!player.hasPermission(CustomAnvil.editConfigPermission)) {
if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory();
player.sendMessage(NO_EDIT_PERM);
return;
@ -109,6 +113,7 @@ public class GuiGlobalActions {
* Create a consumer to update and open an updatable GUI.
* Used with InventoryClickEvent as the consumer argument as it is planned to be used on click on an GuiItem.
* This consumer check if the player who interacted with the item have the permission to save before saving.
*
* @param setting The gui that contain the modified setting.
* @param goal The gui to update and open when consumer is run.
* @return A consumer to open a global GUI.
@ -120,14 +125,14 @@ public class GuiGlobalActions {
event.setCancelled(true);
HumanEntity player = event.getWhoClicked();
// Do not allow to save configuration if player do not have edit configuration permission
if(!player.hasPermission(CustomAnvil.editConfigPermission)) {
if (!player.hasPermission(CustomAnvil.editConfigPermission)) {
player.closeInventory();
player.sendMessage(NO_EDIT_PERM);
return;
}
// Save setting
if(!setting.onSave()){
if (!setting.onSave()) {
player.sendMessage("\u00A7cSomething went wrong while saving the change of value.");
}
// Update gui for those who have it open.

View file

@ -23,6 +23,7 @@ public class GuiGlobalItems {
// statically create default back itemstack
private static final ItemStack BACK_ITEM;
static {
BACK_ITEM = new ItemStack(Material.BARRIER);
ItemMeta meta = BACK_ITEM.getItemMeta();
@ -32,32 +33,35 @@ public class GuiGlobalItems {
/**
* Create a GuiItem that open the given GUi.
*
* @param item The item to display in the GUI.
* @param goal The GUI to open on click.
* @return An GuiItem that open goal on click.
*/
public static GuiItem goToGuiItem(@NotNull ItemStack item, @NotNull Gui goal){
public static GuiItem goToGuiItem(@NotNull ItemStack item, @NotNull Gui goal) {
return new GuiItem(item, GuiGlobalActions.openGuiAction(goal), CustomAnvil.instance);
}
/**
* Create back button item from default back GuiItem.
* The back item will open the goal inventory when clicked.
*
* @param goal The GUI to go back to.
* @return An GuiItem that go back to goal on click.
*/
public static GuiItem backItem(@NotNull Gui goal){
public static GuiItem backItem(@NotNull Gui goal) {
return goToGuiItem(BACK_ITEM, goal);
}
/**
* Add default back item to a GUI pattern with the reserved character key <strong>B</strong>.
* The back item will open the target inventory when clicked.
*
* @param target The pattern to add the back item.
* @param goal The GUI to go back to.
*/
public static void addBackItem(@NotNull PatternPane target,
@NotNull Gui goal){
@NotNull Gui goal) {
target.bindItem('B', backItem(goal));
}
@ -66,42 +70,47 @@ public class GuiGlobalItems {
/**
* Get a background item with backgroundMat as the displayed material.
* A background item is a GuiItem that do nothing when interacted with and have an empty name.
*
* @param backgroundMat The material to which the background item should be made of.
* @return A background item with backgroundMat as material.
*/
public static GuiItem backgroundItem(Material backgroundMat){
public static GuiItem backgroundItem(Material backgroundMat) {
ItemStack item = new ItemStack(backgroundMat);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A7c");
item.setItemMeta(meta);
return new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
}
/**
* Get default background GuiItem.
* A background item is a GuiItem that do nothing when interacted with and have an empty name.
*
* @return A new instance of the default background item.
*/
public static GuiItem backgroundItem(){
public static GuiItem backgroundItem() {
return backgroundItem(DEFAULT_BACKGROUND_MAT);
}
/**
* Add default background item to a GUI pattern with the reserved character key <strong>0</strong>.
* A background item is a GuiItem that do nothing when interacted with and have an empty name.
*
* @param target The pattern to add the background item.
* @param backgroundMat The material of the background item.
*/
public static void addBackgroundItem(@NotNull PatternPane target,
@NotNull Material backgroundMat){
@NotNull Material backgroundMat) {
target.bindItem('0', backgroundItem(backgroundMat));
}
/**
* Add default background item to a GUI pattern with the reserved character key <strong>0</strong>.
* A background item is a GuiItem that do nothing when interacted with and have an empty name.
*
* @param target The pattern to add the background item.
*/
public static void addBackgroundItem(@NotNull PatternPane target){
public static void addBackgroundItem(@NotNull PatternPane target) {
addBackgroundItem(target, DEFAULT_BACKGROUND_MAT);
}
@ -112,13 +121,14 @@ public class GuiGlobalItems {
* Create a new save setting GuiItem.
* A save setting item is a GuiItem that save a changed setting when clicked.
* This item also check if the player who interacted with the item have the permission to save before saving.
*
* @param setting The setting to change.
* @param goal Parent GUI of this setting GUI. as setting will be change the display of goal GUI will be updated.
* @return A save setting item.
*/
public static GuiItem saveItem(
@NotNull AbstractSettingGui setting,
@NotNull ValueUpdatableGui goal){
@NotNull ValueUpdatableGui goal) {
ItemStack item = new ItemStack(DEFAULT_SAVE_ITEM);
ItemMeta meta = item.getItemMeta();
@ -131,26 +141,29 @@ public class GuiGlobalItems {
// Create static non change item
private static final GuiItem NO_CHANGE_ITEM;
static {
ItemStack item = new ItemStack(DEFAULT_NO_CHANGE_ITEM);
ItemMeta meta = item.getItemMeta();
meta.setDisplayName("\u00A77No change. can't save.");
item.setItemMeta(meta);
NO_CHANGE_ITEM = new GuiItem(item,GuiGlobalActions.stayInPlace, CustomAnvil.instance);
NO_CHANGE_ITEM = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
}
/**
* Get the global "no change" GuiItem.
* The no change item do nothing when interacted, only the title is change to show there is no change.
*
* @return The global "no change" item.
*/
public static GuiItem noChangeItem(){
public static GuiItem noChangeItem() {
return NO_CHANGE_ITEM;
}
/**
* Create a new "create and go to the setting GUI" GuiItem.
* This item will create and open a setting GUI from the factory.
*
* @param item The item that will be displayed.
* @param factory The setting's GUI factory.
* @return A formatted GuiItem that will create and open a GUI for the setting.
@ -158,7 +171,7 @@ public class GuiGlobalItems {
public static GuiItem openSettingGuiItem(
@NotNull ItemStack item,
@NotNull AbstractSettingGui.SettingGuiFactory factory
){
) {
return new GuiItem(item, GuiGlobalActions.openSettingGuiAction(factory), CustomAnvil.instance);
}
@ -169,6 +182,7 @@ public class GuiGlobalItems {
* Create a new Boolean setting GuiItem.
* This item will create and open a boolean setting GUI from the factory.
* The item will have its value written in the lore part of the item.
*
* @param factory The setting's GUI factory.
* @param name Name of the item.
* @return A formatted GuiItem that will create and open a GUI for the boolean setting.
@ -176,16 +190,16 @@ public class GuiGlobalItems {
public static GuiItem boolSettingGuiItem(
@NotNull BoolSettingsGui.BoolSettingFactory factory,
@NotNull String name
){
) {
// Get item properties
boolean value = factory.getConfiguredValue();
Material itemMat;
StringBuilder itemName = new StringBuilder("\u00A7");
if(value){
if (value) {
itemMat = Material.GREEN_TERRACOTTA;
itemName.append("a");
}else{
} else {
itemMat = Material.RED_TERRACOTTA;
itemName.append("c");
}
@ -199,12 +213,13 @@ public class GuiGlobalItems {
* This item will create and open a boolean setting GUI from the factory.
* The item will have its value written in the lore part of the item.
* Item's name will be the factory set title.
*
* @param factory The setting's GUI factory.
* @return A formatted GuiItem that will create and open a GUI for the boolean setting.
*/
public static GuiItem boolSettingGuiItem(
@NotNull BoolSettingsGui.BoolSettingFactory factory
){
) {
String configPath = getConfigNameFromPath(factory.getConfigPath());
return boolSettingGuiItem(factory, CasedStringUtil.snakeToUpperSpacedCase(configPath));
}
@ -213,6 +228,7 @@ public class GuiGlobalItems {
* Create a new int setting GuiItem.
* This item will create and open an int setting GUI from the factory.
* The item will have its value written in the lore part of the item.
*
* @param factory The setting's GUI factory.
* @param itemMat Displayed material of the item.
* @param name Name of the item.
@ -222,7 +238,7 @@ public class GuiGlobalItems {
@NotNull IntSettingsGui.IntSettingFactory factory,
@NotNull Material itemMat,
@NotNull String name
){
) {
// Get item properties
int value = factory.getConfiguredValue();
StringBuilder itemName = new StringBuilder("\u00A7a").append(name);
@ -235,6 +251,7 @@ public class GuiGlobalItems {
* This item will create and open an int setting GUI from the factory.
* The item will have its value written in the lore part of the item.
* Item's name will be the factory set title.
*
* @param factory The setting's GUI factory.
* @param itemMat Displayed material of the item.
* @return A formatted GuiItem that will create and open a GUI for the int setting.
@ -242,13 +259,14 @@ public class GuiGlobalItems {
public static GuiItem intSettingGuiItem(
@NotNull IntSettingsGui.IntSettingFactory factory,
@NotNull Material itemMat
){
) {
String configPath = getConfigNameFromPath(factory.getConfigPath());
return intSettingGuiItem(factory, itemMat, CasedStringUtil.detectToUpperSpacedCase(configPath));
}
/**
* Create an arbitrary GuiItem from a unique setting and item's property.
*
* @param factory The setting's GUI factory.
* @param itemMat Displayed material of the item.
* @param itemName Name of the item.
@ -261,13 +279,13 @@ public class GuiGlobalItems {
@NotNull Material itemMat,
@NotNull StringBuilder itemName,
@NotNull Object value
){
) {
// Create & initialise item
ItemStack item = new ItemStack(itemMat);
ItemMeta itemMeta = item.getItemMeta();
itemMeta.setDisplayName(itemName.toString());
itemMeta.setLore(Collections.singletonList(SETTING_ITEM_LORE_PREFIX+value));
itemMeta.setLore(Collections.singletonList(SETTING_ITEM_LORE_PREFIX + value));
item.setItemMeta(itemMeta);
// Create GuiItem
@ -277,14 +295,15 @@ public class GuiGlobalItems {
/**
* Get the setting name from the setting path.
* For example: "gui.command.name" will return "name".
*
* @param path The setting's path.
* @return The setting's name.
*/
public static String getConfigNameFromPath(String path){
public static String getConfigNameFromPath(String path) {
// Get index of first dot
int indexOfDot = path.indexOf(".");
// when indexOfDot == -1 (not fond), it is implied that indexOfDot+1 = 0. substring will keep the full path as expected
return path.substring(indexOfDot+1);
return path.substring(indexOfDot + 1);
}
}

View file

@ -31,6 +31,7 @@ public class GuiSharedConstant {
public static final boolean TEMPORARY_DO_BACKUP_EVERY_SAVE = true;
public static final PatternPane BACK_TO_MAIN_MENU_BIG_LIST_DISPLAY_BACKGROUND_PANE;
static {
Pattern pattern = new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,

View file

@ -9,17 +9,18 @@ public class CasedStringUtil {
* Transform a snake cased string to an upper-cased spaced string.
* <p>
* for example: if we use "hello_world" as an input this function will return "Hello World".
*
* @param snake_cased_string The input string.
* This argument NEED to be a snake cased string, or it will not work
* @return The input as an upper-cased string with space separator.
*/
public static String snakeToUpperSpacedCase(String snake_cased_string){
if(snake_cased_string.contentEquals("")) return "";
public static String snakeToUpperSpacedCase(String snake_cased_string) {
if (snake_cased_string.contentEquals("")) return "";
StringBuilder result = new StringBuilder();
for (String word : snake_cased_string.split("_")) {
result.append(" ");
if(word.isEmpty()) continue;
if (word.isEmpty()) continue;
char firstChar = word.charAt(0);
result.append(Character.toUpperCase(firstChar));
@ -28,15 +29,15 @@ public class CasedStringUtil {
return result.substring(1);
}
public static String camelCaseToUpperSpaceCase(String camelCasedString){
if(camelCasedString.isEmpty()) return camelCasedString;
public static String camelCaseToUpperSpaceCase(String camelCasedString) {
if (camelCasedString.isEmpty()) return camelCasedString;
StringBuilder stb = new StringBuilder();
char[] chars = camelCasedString.toCharArray();
stb.append(chars[0]);
for (int i = 1; i < chars.length; i++) {
char chr = chars[i];
if(Character.isUpperCase(chr)){
if (Character.isUpperCase(chr)) {
stb.append(" ");
}
stb.append(chr);
@ -45,11 +46,11 @@ public class CasedStringUtil {
return stb.toString();
}
public static String detectToUpperSpacedCase(String toDetect){
public static String detectToUpperSpacedCase(String toDetect) {
//not advanced detection
if(toDetect.contains("_")){
if (toDetect.contains("_")) {
return snakeToUpperSpacedCase(toDetect);
}else{
} else {
return camelCaseToUpperSpaceCase(toDetect);
}
}

View file

@ -39,9 +39,10 @@ class AnvilEventListener : Listener {
private const val ANVIL_INPUT_LEFT = 0
private const val ANVIL_INPUT_RIGHT = 1
private const val ANVIL_OUTPUT_SLOT = 2
// static slot container
private val NO_SLOT = SlotContainer(SlotType.NO_SLOT,0)
private val CURSOR_SLOT = SlotContainer(SlotType.CURSOR,0)
private val NO_SLOT = SlotContainer(SlotType.NO_SLOT, 0)
private val CURSOR_SLOT = SlotContainer(SlotType.CURSOR, 0)
}
/**
@ -55,15 +56,15 @@ class AnvilEventListener : Listener {
// Should find player
val player = event.view.player
if(!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
// Test rename lonely item
if(second == null){
if (second == null) {
val resultItem = first.clone()
var anvilCost = handleRename(resultItem, inventory)
// Test/stop if nothing changed.
if(first == resultItem){
if (first == resultItem) {
CustomAnvil.log("no right item, But input is same as output")
event.result = null
return
@ -71,7 +72,7 @@ class AnvilEventListener : Listener {
// We don't manually set item here as vanilla do it (renaming)
//event.result = null
anvilCost+= calculatePenalty(first,null,resultItem)
anvilCost += calculatePenalty(first, null, resultItem)
handleAnvilXp(inventory, event, anvilCost)
return
@ -91,19 +92,19 @@ class AnvilEventListener : Listener {
if (!first.isEnchantedBook() && !second.isEnchantedBook()) {
// we only need to be concerned with repair when neither item is a book
val repaired = resultItem.repairFrom(first, second)
anvilCost += if(repaired) ConfigOptions.itemRepairCost else 0
anvilCost += if (repaired) ConfigOptions.itemRepairCost else 0
}
// Test/stop if nothing changed.
if(first == resultItem){
if (first == resultItem) {
CustomAnvil.log("Mergable with second, But input is same as output")
event.result = null
return
}
// As calculatePenalty edit result, we need to calculate penalty after checking equality
anvilCost+= calculatePenalty(first, second, resultItem)
anvilCost += calculatePenalty(first, second, resultItem)
// Calculate rename cost
anvilCost+= handleRename(resultItem, inventory)
anvilCost += handleRename(resultItem, inventory)
// Finally, we set result
event.result = resultItem
@ -114,19 +115,19 @@ class AnvilEventListener : Listener {
// Test for unit repair
val unitRepairAmount = first.getRepair(second)
if(unitRepairAmount != null){
if (unitRepairAmount != null) {
val resultItem = first.clone()
var anvilCost = handleRename(resultItem, inventory)
val repairAmount = resultItem.unitRepair(second.amount, unitRepairAmount)
if(repairAmount > 0){
anvilCost += repairAmount*ConfigOptions.unitRepairCost
if (repairAmount > 0) {
anvilCost += repairAmount * ConfigOptions.unitRepairCost
}
// We do not care about right item penalty for unit repair
anvilCost+= calculatePenalty(first,null,resultItem)
anvilCost += calculatePenalty(first, null, resultItem)
// Test/stop if nothing changed.
if(first == resultItem){
if (first == resultItem) {
CustomAnvil.log("unit repair, But input is same as output")
event.result = null
return
@ -134,16 +135,16 @@ class AnvilEventListener : Listener {
event.result = resultItem
handleAnvilXp(inventory, event, anvilCost)
}else{
} else {
CustomAnvil.log("no anvil fuse type found")
event.result = null
}
}
private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory): Int{
private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory): Int {
// Rename item and add renaming cost
resultItem.itemMeta?.let {
if(!it.displayName.contentEquals(inventory.renameText)){
if (!it.displayName.contentEquals(inventory.renameText)) {
it.setDisplayName(inventory.renameText)
resultItem.itemMeta = it
return ConfigOptions.itemRenameCost
@ -158,9 +159,11 @@ class AnvilEventListener : Listener {
@EventHandler(ignoreCancelled = true)
fun anvilExtractionCheck(event: InventoryClickEvent) {
val player = event.whoClicked as? Player ?: return
if(!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
val inventory = event.inventory as? AnvilInventory ?: return
if (event.rawSlot != ANVIL_OUTPUT_SLOT) { return }
if (event.rawSlot != ANVIL_OUTPUT_SLOT) {
return
}
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT)
@ -172,110 +175,117 @@ class AnvilEventListener : Listener {
|| (unitRepairResult != null)
// True if there was no change or not allowed
if((output == inventory.getItem(ANVIL_INPUT_LEFT))
|| !allowed){
if ((output == inventory.getItem(ANVIL_INPUT_LEFT))
|| !allowed
) {
event.result = Event.Result.DENY
return
}
if(rightItem == null){
if (rightItem == null) {
event.result = Event.Result.ALLOW
return
}
if(canMerge){
if (canMerge) {
event.result = Event.Result.ALLOW
}else if(unitRepairResult != null){
onUnitRepairExtract(leftItem, rightItem, output,
unitRepairResult, event, player, inventory)
} else if (unitRepairResult != null) {
onUnitRepairExtract(
leftItem, rightItem, output,
unitRepairResult, event, player, inventory
)
return
}
}
private fun onUnitRepairExtract(leftItem: ItemStack,
private fun onUnitRepairExtract(
leftItem: ItemStack,
rightItem: ItemStack,
output: ItemStack,
unitRepairResult: Double,
event: InventoryClickEvent,
player: Player,
inventory: AnvilInventory){
inventory: AnvilInventory
) {
val resultCopy = leftItem.clone()
val resultAmount = resultCopy.unitRepair(
rightItem.amount, unitRepairResult)
rightItem.amount, unitRepairResult
)
// To avoid vanilla, we cancel the event for unit repair
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
val slotDestination = getActionSlot(event, player)
if (slotDestination.type == SlotType.NO_SLOT) return
// Test repair cost
var repairCost = 0
if(player.gameMode != GameMode.CREATIVE){
if (player.gameMode != GameMode.CREATIVE) {
// Get repairCost
leftItem.itemMeta?.let { leftMeta ->
val leftName = leftMeta.displayName
output.itemMeta?.let {
if(!leftName.contentEquals(it.displayName)){
repairCost+= ConfigOptions.itemRenameCost
if (!leftName.contentEquals(it.displayName)) {
repairCost += ConfigOptions.itemRenameCost
}
}
}
repairCost+= calculatePenalty(leftItem,null,resultCopy)
repairCost+= resultAmount*ConfigOptions.unitRepairCost
repairCost += calculatePenalty(leftItem, null, resultCopy)
repairCost += resultAmount * ConfigOptions.unitRepairCost
if((inventory.maximumRepairCost < repairCost)
|| (player.level < repairCost)) return
if ((inventory.maximumRepairCost < repairCost)
|| (player.level < repairCost)
) return
}
// If not creative middle click...
if(event.click != ClickType.MIDDLE){
if (event.click != ClickType.MIDDLE) {
// We remove what should be removed
inventory.setItem(ANVIL_INPUT_LEFT,null)
rightItem.amount-= resultAmount
inventory.setItem(ANVIL_INPUT_RIGHT,rightItem)
inventory.setItem(ANVIL_INPUT_LEFT, null)
rightItem.amount -= resultAmount
inventory.setItem(ANVIL_INPUT_RIGHT, rightItem)
inventory.setItem(ANVIL_OUTPUT_SLOT, null)
player.level-= repairCost
player.level -= repairCost
}
// Finally, we add the item to the player
if(slotDestination.type == SlotType.CURSOR){
if (slotDestination.type == SlotType.CURSOR) {
player.setItemOnCursor(output)
}else{// We assume SlotType == SlotType.INVENTORY
player.inventory.setItem(slotDestination.slot,output)
} else {// We assume SlotType == SlotType.INVENTORY
player.inventory.setItem(slotDestination.slot, output)
}
}
/**
* Get the destination slot or "NO_SLOT" slot container if there is no slot available
*/
private fun getActionSlot(event: InventoryClickEvent, player: Player): SlotContainer{
if(event.isShiftClick){
private fun getActionSlot(event: InventoryClickEvent, player: Player): SlotContainer {
if (event.isShiftClick) {
val inventory = player.inventory
val firstEmpty = inventory.firstEmpty()
if(firstEmpty == -1){
if (firstEmpty == -1) {
return NO_SLOT
}
//check hotbare full
var slotIndex = 8
while(slotIndex >= 0 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)){
while (slotIndex >= 0 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)) {
slotIndex--
}
if(slotIndex >= 0){
return SlotContainer(SlotType.INVENTORY,slotIndex)
if (slotIndex >= 0) {
return SlotContainer(SlotType.INVENTORY, slotIndex)
}
slotIndex = 35 //4*9 - 1 (max of player inventory)
while(slotIndex >= 9 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)){
while (slotIndex >= 9 && ((inventory.getItem(slotIndex)?.type ?: Material.AIR) != Material.AIR)) {
slotIndex--
}
if(slotIndex < 9){
if (slotIndex < 9) {
return NO_SLOT
}
return SlotContainer(SlotType.INVENTORY,slotIndex)
}else{
if(player.itemOnCursor.type != Material.AIR){
return SlotContainer(SlotType.INVENTORY, slotIndex)
} else {
if (player.itemOnCursor.type != Material.AIR) {
return NO_SLOT
}
return CURSOR_SLOT
@ -286,24 +296,29 @@ class AnvilEventListener : Listener {
* Function to calculate work penalty of anvil work
* Also change result work penalty
*/
private fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack): Int{
private fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack): Int {
// Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation
// Calculate work penalty
val leftPenalty = (left.itemMeta as? Repairable)?.repairCost ?: 0
val rightPenalty =
if(right == null){ 0 }
else{ (right.itemMeta as? Repairable)?.repairCost ?: 0 }
if (right == null) {
0
} else {
(right.itemMeta as? Repairable)?.repairCost ?: 0
}
// Try to set work penalty for the result item
result.itemMeta?.let {
(it as? Repairable)?.repairCost = leftPenalty*2+1
(it as? Repairable)?.repairCost = leftPenalty * 2 + 1
result.itemMeta = it
}
CustomAnvil.log("Calculated penalty: " +
CustomAnvil.log(
"Calculated penalty: " +
"leftPenalty: $leftPenalty, " +
"rightPenalty: $rightPenalty, " +
"result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}")
"result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}"
)
return leftPenalty + rightPenalty
}
@ -312,7 +327,7 @@ class AnvilEventListener : Listener {
* Function to calculate right enchantment values
* it include enchantment placed on final item and conflicting enchantment
*/
private fun getRightValues(right: ItemStack, result:ItemStack) : Int {
private fun getRightValues(right: ItemStack, result: ItemStack): Int {
// Calculate right value and illegal enchant penalty
var illegalPenalty = 0
var rightValue = 0
@ -323,12 +338,16 @@ class AnvilEventListener : Listener {
for (enchantment in right.findEnchantments()) {
// count enchant as illegal enchant if it conflicts with another enchant or not in result
if((enchantment.key !in resultEnchsKeys)){
if ((enchantment.key !in resultEnchsKeys)) {
resultEnchsKeys.add(enchantment.key)
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(resultEnchsKeys,result.type,enchantment.key)
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(
resultEnchsKeys,
result.type,
enchantment.key
)
resultEnchsKeys.remove(enchantment.key)
if(ConflictType.BIG_CONFLICT == conflictType){
if (ConflictType.BIG_CONFLICT == conflictType) {
illegalPenalty += ConfigOptions.sacrificeIllegalCost
}
continue
@ -342,9 +361,11 @@ class AnvilEventListener : Listener {
rightValue += value
}
CustomAnvil.log("Calculated right values: " +
CustomAnvil.log(
"Calculated right values: " +
"rightValue: $rightValue, " +
"illegalPenalty: $illegalPenalty")
"illegalPenalty: $illegalPenalty"
)
return rightValue + illegalPenalty
}
@ -352,15 +373,16 @@ class AnvilEventListener : Listener {
/**
* Display xp needed for the work on the anvil inventory
*/
private fun handleAnvilXp(inventory: AnvilInventory,
private fun handleAnvilXp(
inventory: AnvilInventory,
event: PrepareAnvilEvent,
anvilCost: Int){
anvilCost: Int
) {
// Test repair cost limit
val finalAnvilCost: Int
if (ConfigOptions.limitRepairCost) {
finalAnvilCost = min(anvilCost, ConfigOptions.limitRepairValue)
}else{
finalAnvilCost = anvilCost
val finalAnvilCost = if (ConfigOptions.limitRepairCost) {
min(anvilCost, ConfigOptions.limitRepairValue)
} else {
anvilCost
}
/* Because Minecraft likes to have the final say in the repair cost displayed
@ -383,7 +405,7 @@ class AnvilEventListener : Listener {
private class SlotContainer(val type: SlotType, val slot: Int)
private enum class SlotType{
private enum class SlotType {
CURSOR,
INVENTORY,
NO_SLOT

View file

@ -24,17 +24,22 @@ class CustomAnvil : JavaPlugin() {
// Permission string required to use the plugin's features
const val affectedByPluginPermission = "ca.affected"
// Permission string required to bypass enchantment conflicts test
const val bypassFusePermission = "ca.bypass.fuse"
// Permission string required to bypass enchantment conflicts test
const val bypassLevelPermission = "ca.bypass.level"
// Permission string required to reload the config
const val commandReloadPermission = "ca.command.reload"
// Permission string required to edit the plugin's config
const val editConfigPermission = "ca.config.edit"
// Command Name to reload the config
const val commandReloadName = "anvilconfigreload"
// Test command name
const val commandTestName = "customanvilconfig"
@ -71,7 +76,7 @@ class CustomAnvil : JavaPlugin() {
// Disable old plugin name if exist
val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus")
if(potentialPlugin != null){
if (potentialPlugin != null) {
Bukkit.getPluginManager().disablePlugin(potentialPlugin)
logger.warning("An old version of this plugin was detected")
logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus")
@ -83,7 +88,7 @@ class CustomAnvil : JavaPlugin() {
// Load config
val success = ConfigHolder.loadConfig()
if(!success) return
if (!success) return
// Load metrics
val metric = Metrics(this, bstatsPluginId)
@ -98,26 +103,28 @@ class CustomAnvil : JavaPlugin() {
)
}
fun reloadResource(resourceName: String,
hardFailSafe:Boolean = true): YamlConfiguration?{
fun reloadResource(
resourceName: String,
hardFailSafe: Boolean = true
): YamlConfiguration? {
// Save default resource
val file = File(dataFolder,resourceName)
if(!file.exists()){
saveResource(resourceName,false)
val file = File(dataFolder, resourceName)
if (!file.exists()) {
saveResource(resourceName, false)
}
// Load resource
val yamlConfig = YamlConfiguration()
try {
val configReader = FileReader(file)
yamlConfig.load(configReader)
} catch (test: Exception){
if(hardFailSafe){
} catch (test: Exception) {
if (hardFailSafe) {
// This is important and may impact gameplay if it does not load.
// Failsafe is to stop the plugin
logger.severe("Resource $resourceName Could not be load or reload.")
logger.severe("Disabling plugin.")
Bukkit.getPluginManager().disablePlugin(this)
}else{
} else {
logger.warning("Resource $resourceName Could not be load or reload.")
}
return null

View file

@ -12,67 +12,94 @@ object ConfigOptions {
// Path for default enchantment limits
private const val DEFAULT_LIMIT_PATH = "default_limit"
// Path for limiting repair cost
const val LIMIT_REPAIR_COST = "limit_repair_cost"
// Path for repair value limit
const val LIMIT_REPAIR_VALUE = "limit_repair_value"
// Path for level cost on item repair
const val ITEM_REPAIR_COST = "item_repair_cost"
// Path for level cost on unit repair
const val UNIT_REPAIR_COST = "unit_repair_cost"
// Path for level cost on item renaming
const val ITEM_RENAME_COST = "item_rename_cost"
// Path for level cost on illegal enchantment on sacrifice
const val SACRIFICE_ILLEGAL_COST = "sacrifice_illegal_enchant_cost"
// Path for removing repair cost limits
const val REMOVE_REPAIR_LIMIT = "remove_repair_limit"
// Root path for enchantment limits
const val ENCHANT_LIMIT_ROOT = "enchant_limits"
// Root path for enchantment values
const val ENCHANT_VALUES_ROOT = "enchant_values"
// Keys for specific enchantment values
private const val KEY_BOOK = "book"
private const val KEY_ITEM = "item"
// Debug logging toggle path
private const val DEBUG_LOGGING = "debug_log"
// Debug verbose logging toggle path
private const val VERBOSE_DEBUG_LOGGING = "debug_log_verbose"
// Default value for enchantment limits
private const val DEFAULT_ENCHANT_LIMIT = 5
// Default value for limiting repair cost
const val DEFAULT_LIMIT_REPAIR = false
// Default value for repair cost limit
const val DEFAULT_LIMIT_REPAIR_VALUE = 39
// Default value for level cost on item repair
const val DEFAULT_ITEM_REPAIR_COST = 2
// Default value for level cost per unit repair
const val DEFAULT_UNIT_REPAIR_COST = 1
// Default value for level cost on item renaming
const val DEFAULT_ITEM_RENAME_COST = 1
// Default value for level cost on illegal enchantment on sacrifice
const val DEFAULT_SACRIFICE_ILLEGAL_COST = 1
// Valid range for repair cost limit
@JvmField
val REPAIR_LIMIT_RANGE = 1..39
// Valid range for repair cost
@JvmField
val REPAIR_COST_RANGE = 0..255
// Valid range for rename cost
@JvmField
val ITEM_RENAME_COST_RANGE = 0..255
// Valid range for illegal enchantment conflict cost
@JvmField
val SACRIFICE_ILLEGAL_COST_RANGE = 0..255
// Default for removing repair cost limits
const val DEFAULT_REMOVE_LIMIT = false
// Valid range for an enchantment limit
@JvmField
val ENCHANT_LIMIT_RANGE = 1..255
// Default value for an enchantment multiplier
private const val DEFAULT_ENCHANT_VALUE = 0
// Default value for debug logging
private const val DEFAULT_DEBUG_LOG = false
// Default value for debug logging
private const val DEFAULT_VERBOSE_DEBUG_LOG = false
@ -155,6 +182,7 @@ object ConfigOptions {
.takeIf { it in SACRIFICE_ILLEGAL_COST_RANGE }
?: DEFAULT_SACRIFICE_ILLEGAL_COST
}
/**
* Whether to remove repair cost limit
*/
@ -217,8 +245,9 @@ object ConfigOptions {
/**
* Get an array of key of basic config options
*/
fun getBasicConfigKeys(): Array<String>{
return arrayOf(DEFAULT_LIMIT_PATH,
fun getBasicConfigKeys(): Array<String> {
return arrayOf(
DEFAULT_LIMIT_PATH,
LIMIT_REPAIR_COST,
LIMIT_REPAIR_VALUE,
ITEM_REPAIR_COST,

View file

@ -34,43 +34,51 @@ object EnchantmentUtil {
if (!containsKey(enchantment)) {
// Add the enchantment if it doesn't have conflicts, or if player is allowed to bypass enchantment restrictions
this[enchantment] = level
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys,mat,enchantment);
if(!player.hasPermission(CustomAnvil.bypassFusePermission) &&
(conflictType != ConflictType.NO_CONFLICT)){
val conflictType =
ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys, mat, enchantment)
if (!player.hasPermission(CustomAnvil.bypassFusePermission) &&
(conflictType != ConflictType.NO_CONFLICT)
) {
CustomAnvil.verboseLog("Enchantment not yet in result list, but there is conflict (${enchantment.key}, conflict: $conflictType)")
this.remove(enchantment)
}
}
// Enchantment already in result list
else{
else {
// ... and they are conflicting
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys,mat,enchantment)
if((conflictType != ConflictType.NO_CONFLICT)
&& !player.hasPermission(CustomAnvil.bypassFusePermission)){
val conflictType =
ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys, mat, enchantment)
if ((conflictType != ConflictType.NO_CONFLICT)
&& !player.hasPermission(CustomAnvil.bypassFusePermission)
) {
CustomAnvil.verboseLog("Enchantment already in result list, and they are conflicting (${enchantment.key}, conflict: $conflictType)")
return@forEach
}
// ... and they're not the same level
if(this[enchantment] != other[enchantment]){
if (this[enchantment] != other[enchantment]) {
val newLevel = max(this[enchantment] ?: 0, other[enchantment] ?: 0)
// apply the greater of the two if non-zero
if (newLevel > 0) { this[enchantment] = newLevel }
if (newLevel > 0) {
this[enchantment] = newLevel
}
}
// ... and they're the same level
else {
// try to increase the enchantment level by 1
var newLevel = this[enchantment]!! +1
var newLevel = this[enchantment]!! + 1
// Get max level or 255 if player can bypass
val maxLevel = if(player.hasPermission(CustomAnvil.bypassLevelPermission)){
val maxLevel = if (player.hasPermission(CustomAnvil.bypassLevelPermission)) {
255
}else{
} else {
ConfigOptions.enchantLimit(enchantment)
}
newLevel = min(newLevel, maxLevel)
if (newLevel > 0) { this[enchantment] = newLevel }
if (newLevel > 0) {
this[enchantment] = newLevel
}
}
}
}

View file

@ -75,7 +75,7 @@ object ItemUtil {
(itemMeta as? Damageable)?.let {
val durability = type.maxDurability.toInt()
val firstDamage = (first.itemMeta as? Damageable)?.damage ?: 0
if( firstDamage == 0) return false
if (firstDamage == 0) return false
val firstDurability = durability - firstDamage
val secondDamage = (second.itemMeta as? Damageable)?.damage ?: 0
@ -96,12 +96,12 @@ object ItemUtil {
(itemMeta as? Damageable)?.let {
val durability = type.maxDurability.toInt()
val firstDamage = it.damage
if( firstDamage == 0) return 0
if (firstDamage == 0) return 0
var unitCount = 0
var damage = firstDamage
while((unitCount < unitAmount) && (damage > 0)){
while ((unitCount < unitAmount) && (damage > 0)) {
unitCount++
damage = ceil(firstDamage - durability*percentPerUnit*unitCount).toInt()
damage = ceil(firstDamage - durability * percentPerUnit * unitCount).toInt()
}
it.damage = max(damage, 0)

View file

@ -11,11 +11,11 @@ import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions
class EditConfigExecutor : CommandExecutor {
override fun onCommand(sender: CommandSender, command: Command, label: String, args: Array<out String>): Boolean {
if(!sender.hasPermission(CustomAnvil.editConfigPermission)) {
if (!sender.hasPermission(CustomAnvil.editConfigPermission)) {
sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM)
return false
}
if(sender !is HumanEntity) return false
if (sender !is HumanEntity) return false
MainConfigGui.INSTANCE.show(sender)
return true

View file

@ -13,18 +13,18 @@ import xyz.alexcrea.cuanvil.util.MetricsUtil
class ReloadExecutor : CommandExecutor {
override fun onCommand(sender: CommandSender, cmd: Command, cmdstr: String, args: Array<out String>): Boolean {
if(!sender.hasPermission(CustomAnvil.commandReloadPermission)) {
if (!sender.hasPermission(CustomAnvil.commandReloadPermission)) {
sender.sendMessage("§cYou do not have permission to reload the config")
return false
}
sender.sendMessage("§eReloading config...")
val hardfail = args.isNotEmpty() && ("hard".equals(args[0],true))
val hardfail = args.isNotEmpty() && ("hard".equals(args[0], true))
val commandSuccess = commandBody(hardfail)
if(commandSuccess){
if (commandSuccess) {
sender.sendMessage("§aConfig reloaded !")
}else{
} else {
sender.sendMessage("§cConfig was not able to be reloaded...")
if(hardfail){
if (hardfail) {
sender.sendMessage("§4Hard fail, plugin disabled")
}
}
@ -34,9 +34,9 @@ class ReloadExecutor : CommandExecutor {
/**
* Execute the command, return true if success or false otherwise
*/
private fun commandBody(hardfail: Boolean): Boolean{
private fun commandBody(hardfail: Boolean): Boolean {
try {
if(!ConfigHolder.reloadAllFromDisk(hardfail)) return false
if (!ConfigHolder.reloadAllFromDisk(hardfail)) return false
// Then update all global gui containing value from config
BasicConfigGui.INSTANCE.updateGuiValues()
@ -48,7 +48,7 @@ class ReloadExecutor : CommandExecutor {
MetricsUtil.testIfConfigIsDefault()
return true
}catch (e: Exception){
} catch (e: Exception) {
e.printStackTrace()
return false
}

View file

@ -4,7 +4,7 @@ import org.bukkit.Material
import java.util.*
abstract class AbstractMaterialGroup(private val name: String) {
protected val includedMaterial by lazy {createDefaultSet()}
protected val includedMaterial by lazy { createDefaultSet() }
/**
* Get the group default set
@ -14,24 +14,24 @@ abstract class AbstractMaterialGroup(private val name: String) {
/**
* Get if a material is allowed following the group policy
*/
open fun contain(mat : Material): Boolean {
open fun contain(mat: Material): Boolean {
return mat in getMaterials()
}
/**
* Get if a group is referenced by this:
*/
abstract fun isReferencing(other : AbstractMaterialGroup): Boolean
abstract fun isReferencing(other: AbstractMaterialGroup): Boolean
/**
* Push a material to this group to follow this group policy
*/
abstract fun addToPolicy(mat : Material)
abstract fun addToPolicy(mat: Material)
/**
* Push a group to this group to follow this group policy
*/
abstract fun addToPolicy(other : AbstractMaterialGroup)
abstract fun addToPolicy(other: AbstractMaterialGroup)
/**
* Get the group contained material as a set
@ -44,6 +44,7 @@ abstract class AbstractMaterialGroup(private val name: String) {
open fun getNonGroupInheritedMaterials(): EnumSet<Material> {
return includedMaterial
}
/**
* Get the group non-inherited material as a set
*/
@ -69,19 +70,19 @@ abstract class AbstractMaterialGroup(private val name: String) {
*/
abstract fun getGroups(): MutableSet<AbstractMaterialGroup>
open fun getRepresentativeMaterial() : Material {
open fun getRepresentativeMaterial(): Material {
// Test inner material
val matIterator = includedMaterial.iterator()
while(matIterator.hasNext()){
while (matIterator.hasNext()) {
val material = matIterator.next()
if(material.isAir) continue
if (material.isAir) continue
return material
}
// Test included group representative material
val groupIterator = getGroups().iterator()
while (groupIterator.hasNext()){
while (groupIterator.hasNext()) {
val groupMat = groupIterator.next().getRepresentativeMaterial()
if(groupMat.isAir) continue
if (groupMat.isAir) continue
return groupMat
}
return Material.PAPER

View file

@ -7,29 +7,30 @@ import org.bukkit.enchantments.Enchantment
class EnchantConflictGroup(
val name: String,
private val cantConflict: AbstractMaterialGroup,
val minBeforeBlock: Int){
val minBeforeBlock: Int
) {
private val enchantments = HashSet<Enchantment>()
fun addEnchantment(enchant: Enchantment){
fun addEnchantment(enchant: Enchantment) {
enchantments.add(enchant)
}
fun allowed(enchants: Set<Enchantment>, mat: Material) : Boolean{
if(enchantments.size < minBeforeBlock){
fun allowed(enchants: Set<Enchantment>, mat: Material): Boolean {
if (enchantments.size < minBeforeBlock) {
return true
}
if(cantConflict.contain(mat)){
if (cantConflict.contain(mat)) {
return true
}
// Count the amount of enchantment that are in the list
var enchantAmount = 0
for (enchantment in enchants) {
if(enchantment !in enchantments) continue
if (enchantment !in enchantments) continue
CustomAnvil.verboseLog("Enchant ${enchantment.key} is in: ${enchantAmount + 1}/$minBeforeBlock ")
if(++enchantAmount > minBeforeBlock){
if (++enchantAmount > minBeforeBlock) {
return false
}
@ -37,8 +38,8 @@ class EnchantConflictGroup(
return true
}
fun getCantConflictGroup(): AbstractMaterialGroup{
return this.cantConflict;
fun getCantConflictGroup(): AbstractMaterialGroup {
return this.cantConflict
}
fun getEnchants(): HashSet<Enchantment> {
@ -53,9 +54,9 @@ class EnchantConflictGroup(
fun getRepresentativeMaterial(): Material {
val groups = getCantConflictGroup().getGroups()
val groupIterator = groups.iterator()
while (groupIterator.hasNext()){
while (groupIterator.hasNext()) {
val mat = groupIterator.next().getRepresentativeMaterial()
if(mat != Material.ENCHANTED_BOOK) return mat
if (mat != Material.ENCHANTED_BOOK) return mat
}
return Material.ENCHANTED_BOOK

View file

@ -11,13 +11,17 @@ class EnchantConflictManager {
companion object {
// Path for the enchantments list
const val ENCH_LIST_PATH = "enchantments"
// Path for group list related to the conflict
const val CONFLICT_GROUP_PATH = "notAffectedGroups"
// Path for the maximum number of enchantment before validating the conflict
const val ENCH_MAX_PATH = "maxEnchantmentBeforeConflict"
// Path for a flag: if the enchantment will be used in the last supported version
// TODO maybe replace this system by a list of "future" enchantment.
private const val FUTURE_USE_PATH = "useInFuture"
// Default name for a joining group
private const val DEFAULT_GROUP_NAME = "joinedGroup"
}
@ -26,64 +30,64 @@ class EnchantConflictManager {
lateinit var conflictList: ArrayList<EnchantConflictGroup>
// Read and prepare all conflict
fun prepareConflicts(config: ConfigurationSection, itemManager: ItemGroupManager){
fun prepareConflicts(config: ConfigurationSection, itemManager: ItemGroupManager) {
conflictMap = HashMap()
conflictList = ArrayList()
val keys = config.getKeys(false)
for (key in keys) {
val section = config.getConfigurationSection(key)!!
val conflict = createConflict(section,itemManager,key)
if(conflict != null){
val conflict = createConflict(section, itemManager, key)
addToMap(conflict)
conflictList.add(conflict)
}
}
}
// Add the conflict to the map
private fun addToMap(conflict: EnchantConflictGroup){
conflict.getEnchants().forEach{ enchant ->
addConflictToConflictMap(enchant, conflict);
private fun addToMap(conflict: EnchantConflictGroup) {
conflict.getEnchants().forEach { enchant ->
addConflictToConflictMap(enchant, conflict)
}
}
fun addConflictToConflictMap(enchant: Enchantment, conflict: EnchantConflictGroup){
if(!conflictMap.containsKey(enchant)){
fun addConflictToConflictMap(enchant: Enchantment, conflict: EnchantConflictGroup) {
if (!conflictMap.containsKey(enchant)) {
conflictMap[enchant] = ArrayList()
}
conflictMap[enchant]!!.add(conflict)
}
fun removeConflictFromMap(enchant: Enchantment, conflict: EnchantConflictGroup): Boolean{
fun removeConflictFromMap(enchant: Enchantment, conflict: EnchantConflictGroup): Boolean {
return conflictMap[enchant]!!.remove(conflict)
}
// create and read a conflict from a yaml section
private fun createConflict(section: ConfigurationSection,
private fun createConflict(
section: ConfigurationSection,
itemManager: ItemGroupManager,
conflictName: String): EnchantConflictGroup? {
conflictName: String
): EnchantConflictGroup {
// Is it planed for the future
val futureUse = section.getBoolean(FUTURE_USE_PATH,false)
val futureUse = section.getBoolean(FUTURE_USE_PATH, false)
// Create conflict
val conflict = createConflictObject(section,itemManager,conflictName)
val conflict = createConflictObject(section, itemManager, conflictName)
// Read and add enchantment to conflict
val enchantList = section.getStringList(ENCH_LIST_PATH)
for (enchantName in enchantList) {
val enchantKey = NamespacedKey.minecraft(enchantName)
val enchant = Enchantment.getByKey(enchantKey)
if(enchant == null){
if(!futureUse){
if (enchant == null) {
if (!futureUse) {
CustomAnvil.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName")
}
continue
}
conflict.addEnchantment(enchant)
}
if(conflict.getEnchants().size == 0){
if(!futureUse){
if (conflict.getEnchants().size == 0) {
if (!futureUse) {
CustomAnvil.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not do anything")
}
}
@ -91,12 +95,14 @@ class EnchantConflictManager {
return conflict
}
private fun createConflictObject(section: ConfigurationSection,
private fun createConflictObject(
section: ConfigurationSection,
itemManager: ItemGroupManager,
conflictName: String): EnchantConflictGroup {
conflictName: String
): EnchantConflictGroup {
// Get the maximum number of enchantment before validating the conflict
var minBeforeBlock = section.getInt(ENCH_MAX_PATH,0)
if(minBeforeBlock < 0){
var minBeforeBlock = section.getInt(ENCH_MAX_PATH, 0)
if (minBeforeBlock < 0) {
minBeforeBlock = 0
CustomAnvil.instance.logger.warning("Conflict $conflictName have an invalid value of $ENCH_MAX_PATH")
CustomAnvil.instance.logger.warning("It should be more or equal to 0. default to 0")
@ -112,9 +118,13 @@ class EnchantConflictManager {
return EnchantConflictGroup(conflictName, finalGroup, minBeforeBlock)
}
private fun findGroup(groupName: String, itemManager: ItemGroupManager, conflictName: String): AbstractMaterialGroup {
private fun findGroup(
groupName: String,
itemManager: ItemGroupManager,
conflictName: String
): AbstractMaterialGroup {
val group = itemManager.get(groupName)
if(group == null){
if (group == null) {
CustomAnvil.instance.logger.warning("Group $groupName do not exist but is ask by conflict $conflictName")
return IncludeGroup("error_placeholder")
}
@ -122,7 +132,7 @@ class EnchantConflictManager {
return group
}
fun isConflicting(base: Set<Enchantment>,mat: Material, newEnchant: Enchantment): ConflictType {
fun isConflicting(base: Set<Enchantment>, mat: Material, newEnchant: Enchantment): ConflictType {
CustomAnvil.verboseLog("Testing conflict for ${newEnchant.key} on ${mat.key}")
val conflictList = conflictMap[newEnchant] ?: return ConflictType.NO_CONFLICT
CustomAnvil.verboseLog("Did not get skipped")
@ -130,13 +140,13 @@ class EnchantConflictManager {
var result = ConflictType.NO_CONFLICT
for (conflict in conflictList) {
CustomAnvil.verboseLog("Is against ${conflict.name}")
val conflicting = conflict.allowed(base,mat)
val conflicting = conflict.allowed(base, mat)
CustomAnvil.verboseLog("Was against ${conflict.name} and conflicting: $conflicting ")
if(!conflicting) {
if(conflict.getEnchants().size <= 1){
if (!conflicting) {
if (conflict.getEnchants().size <= 1) {
result = ConflictType.SMALL_CONFLICT
CustomAnvil.verboseLog("Small conflict, continuing")
}else{
} else {
return ConflictType.BIG_CONFLICT
}
}
@ -146,7 +156,7 @@ class EnchantConflictManager {
}
enum class ConflictType{
enum class ConflictType {
NO_CONFLICT,
SMALL_CONFLICT,
BIG_CONFLICT

View file

@ -3,17 +3,17 @@ package xyz.alexcrea.cuanvil.group
import org.bukkit.Material
import java.util.*
class ExcludeGroup(name: String): AbstractMaterialGroup(name) {
class ExcludeGroup(name: String) : AbstractMaterialGroup(name) {
override fun createDefaultSet(): EnumSet<Material> {
return EnumSet.allOf(Material::class.java)
}
private var includedGroup: MutableSet<AbstractMaterialGroup> = HashSet()
private val groupItems by lazy {createDefaultSet()}
private val groupItems by lazy { createDefaultSet() }
override fun isReferencing(other: AbstractMaterialGroup): Boolean {
for (materialGroup in includedGroup.iterator()) {
if((materialGroup == other) || (materialGroup.isReferencing(other))){
if ((materialGroup == other) || (materialGroup.isReferencing(other))) {
return true
}
}
@ -36,7 +36,7 @@ class ExcludeGroup(name: String): AbstractMaterialGroup(name) {
includedGroup.clear()
groups.forEach { group ->
if(!group.isReferencing(this)) {
if (!group.isReferencing(this)) {
includedGroup.add(group)
groupItems.removeAll(group.getMaterials())
}

View file

@ -3,17 +3,17 @@ package xyz.alexcrea.cuanvil.group
import org.bukkit.Material
import java.util.*
class IncludeGroup(name: String): AbstractMaterialGroup(name) {
class IncludeGroup(name: String) : AbstractMaterialGroup(name) {
override fun createDefaultSet(): EnumSet<Material> {
return EnumSet.noneOf(Material::class.java)
}
private var includedGroup: MutableSet<AbstractMaterialGroup> = HashSet()
private val groupItems by lazy {createDefaultSet()}
private val groupItems by lazy { createDefaultSet() }
override fun isReferencing(other: AbstractMaterialGroup): Boolean {
for (materialGroup in includedGroup.iterator()) {
if((materialGroup == other) || (materialGroup.isReferencing(other))){
if ((materialGroup == other) || (materialGroup.isReferencing(other))) {
return true
}
}
@ -36,7 +36,7 @@ class IncludeGroup(name: String): AbstractMaterialGroup(name) {
includedGroup.clear()
groups.forEach { group ->
if(!group.isReferencing(this)){
if (!group.isReferencing(this)) {
includedGroup.add(group)
groupItems.addAll(group.getMaterials())
}

View file

@ -4,49 +4,53 @@ import io.delilaheve.CustomAnvil
import org.bukkit.Material
import org.bukkit.configuration.ConfigurationSection
import java.util.*
import kotlin.collections.LinkedHashMap
class ItemGroupManager {
companion object {
// Path for group type
private const val GROUP_TYPE_PATH = "type"
// Path for included items list
private const val MATERIAL_LIST_PATH = "items"
// Path for included groups list
private const val GROUP_LIST_PATH = "groups"
// Temporary list of elements in default config that are use in future
private val FUTURE_MATERIAL = setOf("PIGLIN_HEAD","BRUSH")
private val FUTURE_MATERIAL = setOf("PIGLIN_HEAD", "BRUSH")
}
lateinit var groupMap : LinkedHashMap<String, AbstractMaterialGroup>
lateinit var groupMap: LinkedHashMap<String, AbstractMaterialGroup>
// Read and create material groups
fun prepareGroups(config: ConfigurationSection){
fun prepareGroups(config: ConfigurationSection) {
groupMap = LinkedHashMap()
val keys = config.getKeys(false)
for (key in keys) {
if(groupMap.containsKey(key))
if (groupMap.containsKey(key))
continue
createGroup(config, keys, key)
}
}
// Create group by key
private fun createGroup(config: ConfigurationSection,
private fun createGroup(
config: ConfigurationSection,
keys: Set<String>,
key: String): AbstractMaterialGroup {
key: String
): AbstractMaterialGroup {
val groupSection = config.getConfigurationSection(key)!!
val groupType = groupSection.getString(GROUP_TYPE_PATH,null)
val groupType = groupSection.getString(GROUP_TYPE_PATH, null)
// Create Material group according to the group type
val group: AbstractMaterialGroup
if(GroupType.EXCLUDE.equal(groupType)){
if (GroupType.EXCLUDE.equal(groupType)) {
group = ExcludeGroup(key)
}else {
} else {
group = IncludeGroup(key)
if(!GroupType.INCLUDE.equal(groupType)){
if (!GroupType.INCLUDE.equal(groupType)) {
CustomAnvil.instance.logger.warning("Group $key have an invalid group type. default to Include.")
}
}
@ -57,20 +61,23 @@ class ItemGroupManager {
}
// Read Group elements
private fun readGroup(group: AbstractMaterialGroup,
private fun readGroup(
group: AbstractMaterialGroup,
groupSection: ConfigurationSection,
config: ConfigurationSection,
keys: Set<String>){
keys: Set<String>
) {
// Read material to include in this group policy
val materialList = groupSection.getStringList(MATERIAL_LIST_PATH)
for (materialTemp in materialList) {
val materialName = materialTemp.uppercase(Locale.getDefault())
val material = Material.getMaterial(materialName)
if(material == null){
if (material == null) {
// Check if we should warn the user
if(materialName !in FUTURE_MATERIAL){
if (materialName !in FUTURE_MATERIAL) {
CustomAnvil.instance.logger.warning(
"Unknown material $materialTemp on group ${group.getName()}")
"Unknown material $materialTemp on group ${group.getName()}"
)
}
continue
@ -82,23 +89,26 @@ class ItemGroupManager {
// please note the group name is case-sensitive.
val groupList = groupSection.getStringList(GROUP_LIST_PATH)
for (groupName in groupList) {
if(groupName !in keys){
if (groupName !in keys) {
CustomAnvil.instance.logger.warning(
"Group $groupName do not exist but is included in group ${group.getName()}")
"Group $groupName do not exist but is included in group ${group.getName()}"
)
continue
}
// Get other group or create it if not yet created
val otherGroup = if(!groupMap.containsKey(groupName)){
createGroup(config,keys,groupName)
}else{
val otherGroup = if (!groupMap.containsKey(groupName)) {
createGroup(config, keys, groupName)
} else {
groupMap[groupName]!!
}
// Avoid self reference or it will create an infinite loop
if(otherGroup.isReferencing(group)){
if (otherGroup.isReferencing(group)) {
CustomAnvil.instance.logger.warning(
"Group $groupName is on a reference loop with group ${group.getName()} !")
"Group $groupName is on a reference loop with group ${group.getName()} !"
)
CustomAnvil.instance.logger.warning(
"Please fix it in your item_groups config or the plugin will probably not work as expected.")
"Please fix it in your item_groups config or the plugin will probably not work as expected."
)
continue
}
@ -121,8 +131,8 @@ enum class GroupType(private val groupID: String) {
;
// Test if string is equal to the groupID of this enum
fun equal(toTest: String?): Boolean{
if(toTest == null)
fun equal(toTest: String?): Boolean {
if (toTest == null)
return false
return groupID.contentEquals(toTest.lowercase(Locale.getDefault()))
}

View file

@ -11,7 +11,7 @@ import java.util.*
import java.util.concurrent.ConcurrentHashMap
import java.util.function.Consumer
class ChatEventListener : Listener{
class ChatEventListener : Listener {
private val playerListenMap: ConcurrentHashMap<UUID, Consumer<String?>> = ConcurrentHashMap()

View file

@ -31,12 +31,11 @@ object MetricsUtil {
*/
private fun getHashFromKey(section: ConfigurationSection, key: String): Int {
// Key is assumend to exist
val resultHash: Int
if(section.isConfigurationSection(key)){
val resultHash = if (section.isConfigurationSection(key)) {
val sectionResult = getConfigurationHash(section.getConfigurationSection(key)!!)
resultHash = key.hashCode() xor sectionResult
}else{
resultHash = key.hashCode() xor section.getString(key).hashCode()
key.hashCode() xor sectionResult
} else {
key.hashCode() xor section.getString(key).hashCode()
}
return resultHash.hashCode()
}
@ -47,7 +46,7 @@ object MetricsUtil {
private fun getConfigurationHash(section: ConfigurationSection): Int {
var resultHash = 0
for (key in section.getKeys(false)) {
resultHash = resultHash xor getHashFromKey(section,key)
resultHash = resultHash xor getHashFromKey(section, key)
}
return resultHash
}
@ -55,10 +54,10 @@ object MetricsUtil {
/**
* Get hash value of the default config
*/
private fun testBaseConfig(defaultConfig: ConfigurationSection): Int{
private fun testBaseConfig(defaultConfig: ConfigurationSection): Int {
var result = 0
for (key in ConfigOptions.getBasicConfigKeys()) {
result = result xor getHashFromKey(defaultConfig,key)
result = result xor getHashFromKey(defaultConfig, key)
}
return result
}
@ -66,7 +65,7 @@ object MetricsUtil {
/**
* Test if the used configuration is the default config
*/
fun testIfConfigIsDefault(){
fun testIfConfigIsDefault() {
// Calculate hash of config
val baseConfig = testBaseConfig(ConfigHolder.DEFAULT_CONFIG.config)
val limitEnchantConfig = getHashFromKey(ConfigHolder.DEFAULT_CONFIG.config, ConfigOptions.ENCHANT_LIMIT_ROOT)
@ -82,32 +81,44 @@ object MetricsUtil {
isDefaultItemGroupsConfig = itemGroupsConfigHash == itemGroupConfig
isDefaultUnitRepairItemConfig = unitRepairItemConfigHash == unitRepairConfig
// If not default and debug flag active, print the hash.
if(ConfigOptions.debugLog){
if(!isDefaultBaseConfig){CustomAnvil.log("baseConfig: $baseConfig")}
if(!isDefaultEnchantLimitsConfig){CustomAnvil.log("limitEnchantConfig: $limitEnchantConfig")}
if(!isDefaultEnchantValuesConfig){CustomAnvil.log("enchantValueConfig: $enchantValueConfig")}
if(!isDefaultEnchantConflictConfig){CustomAnvil.log("enchantConflictConfig: $enchantConflictConfig")}
if(!isDefaultItemGroupsConfig){CustomAnvil.log("itemGroupConfig: $itemGroupConfig")}
if(!isDefaultUnitRepairItemConfig){CustomAnvil.log("unitRepairConfig: $unitRepairConfig")}
if (ConfigOptions.debugLog) {
if (!isDefaultBaseConfig) {
CustomAnvil.log("baseConfig: $baseConfig")
}
if (!isDefaultEnchantLimitsConfig) {
CustomAnvil.log("limitEnchantConfig: $limitEnchantConfig")
}
if (!isDefaultEnchantValuesConfig) {
CustomAnvil.log("enchantValueConfig: $enchantValueConfig")
}
if (!isDefaultEnchantConflictConfig) {
CustomAnvil.log("enchantConflictConfig: $enchantConflictConfig")
}
if (!isDefaultItemGroupsConfig) {
CustomAnvil.log("itemGroupConfig: $itemGroupConfig")
}
if (!isDefaultUnitRepairItemConfig) {
CustomAnvil.log("unitRepairConfig: $unitRepairConfig")
}
}
}
fun notifyChange(holder: ConfigHolder, path: String){
if(ConfigHolder.DEFAULT_CONFIG.equals(holder)){
if(path.startsWith(ConfigOptions.ENCHANT_LIMIT_ROOT+".")){
isDefaultEnchantLimitsConfig = false;
}else if(path.startsWith(ConfigOptions.ENCHANT_VALUES_ROOT+".")){
isDefaultEnchantValuesConfig = false;
}else{
isDefaultBaseConfig = false;
fun notifyChange(holder: ConfigHolder, path: String) {
if (ConfigHolder.DEFAULT_CONFIG.equals(holder)) {
if (path.startsWith(ConfigOptions.ENCHANT_LIMIT_ROOT + ".")) {
isDefaultEnchantLimitsConfig = false
} else if (path.startsWith(ConfigOptions.ENCHANT_VALUES_ROOT + ".")) {
isDefaultEnchantValuesConfig = false
} else {
isDefaultBaseConfig = false
}
}else if(ConfigHolder.CONFLICT_HOLDER.equals(holder)){
isDefaultEnchantConflictConfig = false;
}else if(ConfigHolder.ITEM_GROUP_HOLDER.equals(holder)){
isDefaultItemGroupsConfig = false;
}else if(ConfigHolder.UNIT_REPAIR_HOLDER.equals(holder)){
isDefaultUnitRepairItemConfig = false;
} else if (ConfigHolder.CONFLICT_HOLDER.equals(holder)) {
isDefaultEnchantConflictConfig = false
} else if (ConfigHolder.ITEM_GROUP_HOLDER.equals(holder)) {
isDefaultItemGroupsConfig = false
} else if (ConfigHolder.UNIT_REPAIR_HOLDER.equals(holder)) {
isDefaultUnitRepairItemConfig = false
}
}

View file

@ -8,6 +8,7 @@ object UnitRepairUtil {
// Default value for user set default unit repair %
private const val DEFAULT_DEFAULT_UNIT_REPAIR = 0.25
// Path to user default unit repair value
private const val UNIT_REPAIR_DEFAULT_PATH = "default_repair_amount"
@ -18,23 +19,23 @@ object UnitRepairUtil {
fun ItemStack.getRepair(
other: ItemStack?
): Double? {
if(other == null) return null
if (other == null) return null
val config = ConfigHolder.UNIT_REPAIR_HOLDER.config
// Get configuration section if exist
val otherName = other.type.name.uppercase()
var section = config.getConfigurationSection(otherName)
if(section == null){
if (section == null) {
section = config.getConfigurationSection(otherName.lowercase())
if(section == null) return null
if (section == null) return null
}
// Get repair amount
var userDefault = config.getDouble(UNIT_REPAIR_DEFAULT_PATH, DEFAULT_DEFAULT_UNIT_REPAIR)
if(userDefault <= 0){
if (userDefault <= 0) {
userDefault = DEFAULT_DEFAULT_UNIT_REPAIR
}
return getRepairAmount(this,section,userDefault)
return getRepairAmount(this, section, userDefault)
}
/**
@ -42,16 +43,16 @@ object UnitRepairUtil {
* null if not found.
* If value is set to less than or equal to 0 then it will be set to default
*/
private fun getRepairAmount(item: ItemStack, section: ConfigurationSection, default: Double): Double?{
private fun getRepairAmount(item: ItemStack, section: ConfigurationSection, default: Double): Double? {
val itemName = item.type.name.uppercase()
val repairValue = if(section.isDouble(itemName)){
val repairValue = if (section.isDouble(itemName)) {
section.getDouble(itemName)
}else if(section.isDouble(itemName.lowercase())){
} else if (section.isDouble(itemName.lowercase())) {
section.getDouble(itemName.lowercase())
}else{
} else {
return null
}
if(repairValue <= 0)
if (repairValue <= 0)
return default
return repairValue
}

View file

@ -12,159 +12,159 @@
# ----------------------------------------------------
restriction_aqua_affinity:
enchantments: [aqua_affinity]
notAffectedGroups: [enchanted_book, helmets]
enchantments: [ aqua_affinity ]
notAffectedGroups: [ enchanted_book, helmets ]
restriction_bane_of_arthropods:
enchantments: [bane_of_arthropods]
notAffectedGroups: [enchanted_book, melee_weapons]
enchantments: [ bane_of_arthropods ]
notAffectedGroups: [ enchanted_book, melee_weapons ]
restriction_blast_protection:
enchantments: [blast_protection]
notAffectedGroups: [enchanted_book, armors]
enchantments: [ blast_protection ]
notAffectedGroups: [ enchanted_book, armors ]
restriction_channeling:
enchantments: [channeling]
notAffectedGroups: [enchanted_book, trident]
enchantments: [ channeling ]
notAffectedGroups: [ enchanted_book, trident ]
restriction_binding_curse:
enchantments: [binding_curse]
notAffectedGroups: [enchanted_book, wearable]
enchantments: [ binding_curse ]
notAffectedGroups: [ enchanted_book, wearable ]
restriction_vanishing_curse:
enchantments: [vanishing_curse]
notAffectedGroups: [enchanted_book, can_vanish]
enchantments: [ vanishing_curse ]
notAffectedGroups: [ enchanted_book, can_vanish ]
restriction_depth_strider:
enchantments: [depth_strider]
notAffectedGroups: [enchanted_book, boots]
enchantments: [ depth_strider ]
notAffectedGroups: [ enchanted_book, boots ]
restriction_efficiency:
enchantments: [efficiency]
notAffectedGroups: [enchanted_book, tools, shears]
enchantments: [ efficiency ]
notAffectedGroups: [ enchanted_book, tools, shears ]
restriction_feather_falling:
enchantments: [feather_falling]
notAffectedGroups: [enchanted_book, boots]
enchantments: [ feather_falling ]
notAffectedGroups: [ enchanted_book, boots ]
restriction_fire_aspect:
enchantments: [fire_aspect]
notAffectedGroups: [enchanted_book, swords]
enchantments: [ fire_aspect ]
notAffectedGroups: [ enchanted_book, swords ]
restriction_fire_protection:
enchantments: [fire_protection]
notAffectedGroups: [enchanted_book, armors]
enchantments: [ fire_protection ]
notAffectedGroups: [ enchanted_book, armors ]
restriction_flame:
enchantments: [flame]
notAffectedGroups: [enchanted_book, bow]
enchantments: [ flame ]
notAffectedGroups: [ enchanted_book, bow ]
restriction_fortune:
enchantments: [fortune]
notAffectedGroups: [enchanted_book, tools]
enchantments: [ fortune ]
notAffectedGroups: [ enchanted_book, tools ]
restriction_frost_walker:
enchantments: [frost_walker]
notAffectedGroups: [enchanted_book, boots]
enchantments: [ frost_walker ]
notAffectedGroups: [ enchanted_book, boots ]
restriction_impaling:
enchantments: [impaling]
notAffectedGroups: [enchanted_book, trident]
enchantments: [ impaling ]
notAffectedGroups: [ enchanted_book, trident ]
restriction_infinity:
enchantments: [infinity]
notAffectedGroups: [enchanted_book, bow]
enchantments: [ infinity ]
notAffectedGroups: [ enchanted_book, bow ]
restriction_knockback:
enchantments: [knockback]
notAffectedGroups: [enchanted_book, swords]
enchantments: [ knockback ]
notAffectedGroups: [ enchanted_book, swords ]
restriction_looting:
enchantments: [looting]
notAffectedGroups: [enchanted_book, swords]
enchantments: [ looting ]
notAffectedGroups: [ enchanted_book, swords ]
restriction_loyalty:
enchantments: [loyalty]
notAffectedGroups: [enchanted_book, trident]
enchantments: [ loyalty ]
notAffectedGroups: [ enchanted_book, trident ]
restriction_lure:
enchantments: [lure]
notAffectedGroups: [enchanted_book, fishing_rod]
enchantments: [ lure ]
notAffectedGroups: [ enchanted_book, fishing_rod ]
restriction_mending:
enchantments: [mending]
notAffectedGroups: [enchanted_book, can_unbreak]
enchantments: [ mending ]
notAffectedGroups: [ enchanted_book, can_unbreak ]
restriction_multishot:
enchantments: [multishot]
notAffectedGroups: [enchanted_book, crossbow]
enchantments: [ multishot ]
notAffectedGroups: [ enchanted_book, crossbow ]
restriction_piercing:
enchantments: [piercing]
notAffectedGroups: [enchanted_book, crossbow]
enchantments: [ piercing ]
notAffectedGroups: [ enchanted_book, crossbow ]
restriction_power:
enchantments: [power]
notAffectedGroups: [enchanted_book, bow]
enchantments: [ power ]
notAffectedGroups: [ enchanted_book, bow ]
restriction_projectile_protection:
enchantments: [projectile_protection]
notAffectedGroups: [enchanted_book, armors]
enchantments: [ projectile_protection ]
notAffectedGroups: [ enchanted_book, armors ]
restriction_protection:
enchantments: [protection]
notAffectedGroups: [enchanted_book, armors]
enchantments: [ protection ]
notAffectedGroups: [ enchanted_book, armors ]
restriction_punch:
enchantments: [punch]
notAffectedGroups: [enchanted_book, bow]
enchantments: [ punch ]
notAffectedGroups: [ enchanted_book, bow ]
restriction_quick_charge:
enchantments: [quick_charge]
notAffectedGroups: [enchanted_book, crossbow]
enchantments: [ quick_charge ]
notAffectedGroups: [ enchanted_book, crossbow ]
restriction_respiration:
enchantments: [respiration]
notAffectedGroups: [enchanted_book, helmets]
enchantments: [ respiration ]
notAffectedGroups: [ enchanted_book, helmets ]
restriction_riptide:
enchantments: [riptide]
notAffectedGroups: [enchanted_book, trident]
enchantments: [ riptide ]
notAffectedGroups: [ enchanted_book, trident ]
restriction_sharpness:
enchantments: [sharpness]
notAffectedGroups: [enchanted_book, melee_weapons]
enchantments: [ sharpness ]
notAffectedGroups: [ enchanted_book, melee_weapons ]
restriction_silk_touch:
enchantments: [silk_touch]
notAffectedGroups: [enchanted_book, tools]
enchantments: [ silk_touch ]
notAffectedGroups: [ enchanted_book, tools ]
restriction_smite:
enchantments: [smite]
notAffectedGroups: [enchanted_book, melee_weapons]
enchantments: [ smite ]
notAffectedGroups: [ enchanted_book, melee_weapons ]
restriction_soul_speed:
enchantments: [soul_speed]
notAffectedGroups: [enchanted_book, boots]
enchantments: [ soul_speed ]
notAffectedGroups: [ enchanted_book, boots ]
restriction_sweeping:
enchantments: [sweeping]
notAffectedGroups: [enchanted_book, swords]
enchantments: [ sweeping ]
notAffectedGroups: [ enchanted_book, swords ]
# Do not exist in 1.18, that mean useInFuture will be set to true
# useInFuture set to true also mean it will not warn if there is an issue
restriction_swift_sneak:
useInFuture: true
enchantments: [swift_sneak]
notAffectedGroups: [enchanted_book, boots]
enchantments: [ swift_sneak ]
notAffectedGroups: [ enchanted_book, boots ]
restriction_thorns:
enchantments: [thorns]
notAffectedGroups: [enchanted_book, armors]
enchantments: [ thorns ]
notAffectedGroups: [ enchanted_book, armors ]
restriction_unbreaking:
enchantments: [unbreaking]
notAffectedGroups: [enchanted_book, can_unbreak]
enchantments: [ unbreaking ]
notAffectedGroups: [ enchanted_book, can_unbreak ]
# ----------------------------------------------------
# Now we have conflicts about enchantment Incompatibility
@ -178,7 +178,7 @@ sword_enchant_conflict:
- bane_of_arthropods
- smite
- sharpness
notAffectedGroups: []
notAffectedGroups: [ ]
maxEnchantmentBeforeConflict: 1
protection_enchant_conflict:
@ -187,49 +187,49 @@ protection_enchant_conflict:
- fire_protection
- projectile_protection
- protection
notAffectedGroups: []
notAffectedGroups: [ ]
maxEnchantmentBeforeConflict: 1
trident_conflict1:
enchantments:
- channeling
- riptide
notAffectedGroups: []
notAffectedGroups: [ ]
maxEnchantmentBeforeConflict: 1
trident_conflict2:
enchantments:
- loyalty
- riptide
notAffectedGroups: []
notAffectedGroups: [ ]
maxEnchantmentBeforeConflict: 1
boot_conflict:
enchantments:
- depth_strider
- frost_walker
notAffectedGroups: []
notAffectedGroups: [ ]
maxEnchantmentBeforeConflict: 1
tool_conflict:
enchantments:
- fortune
- silk_touch
notAffectedGroups: []
notAffectedGroups: [ ]
maxEnchantmentBeforeConflict: 1
bow_conflict:
enchantments:
- mending
- infinity
notAffectedGroups: []
notAffectedGroups: [ ]
maxEnchantmentBeforeConflict: 1
crossbow_conflict:
enchantments:
- multishot
- piercing
notAffectedGroups: []
notAffectedGroups: [ ]
maxEnchantmentBeforeConflict: 1
# ----------------------------------------------------

View file

@ -1,11 +1,11 @@
main: io.delilaheve.CustomAnvil
name: CustomAnvil
prefix: "Custom Anvil"
version: 1.3.2-A1
version: 1.3.2-A2
description: Allow to customise anvil mechanics
api-version: 1.18
load: POSTWORLD
authors: [DelilahEve, alexcrea]
authors: [ DelilahEve, alexcrea ]
libraries:
- org.jetbrains.kotlin:kotlin-stdlib:1.6.21
- com.github.stefvanschie.inventoryframework:IF:0.10.13