diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigType.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigType.java index f44d8c24..bb8d1f0e 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigType.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/ConfigType.java @@ -32,7 +32,23 @@ import java.util.function.Supplier; * Configuration types for various mechanics. */ public class ConfigType { - + public static final ConfigType GEAR = of( + "gear", //new + () -> { + HashMap> parsers = new HashMap<>(); + parsers.putAll(BukkitCustomFishingPlugin.getInstance().getConfigManager().getItemFormatFunctions()); + parsers.putAll(BukkitCustomFishingPlugin.getInstance().getConfigManager().getEffectModifierFormatFunctions()); + parsers.putAll(BukkitCustomFishingPlugin.getInstance().getConfigManager().getEventFormatFunctions()); + return parsers; + }, + (id, section, functions) -> { + MechanicType.register(id, MechanicType.GEAR); + GearConfigParser config = new GearConfigParser(id, section, functions); + BukkitCustomFishingPlugin.getInstance().getItemManager().registerItem(config.getItem()); + BukkitCustomFishingPlugin.getInstance().getEffectManager().registerEffectModifier(config.getEffectModifier(), MechanicType.GEAR); + BukkitCustomFishingPlugin.getInstance().getEventManager().registerEventCarrier(config.getEventCarrier()); + } + ); public static final ConfigType ITEM = of( "item", () -> { @@ -218,7 +234,7 @@ public class ConfigType { } ); - private static final ConfigType[] values = new ConfigType[] {ITEM, ENTITY, BLOCK, HOOK, ROD, BAIT, UTIL, TOTEM, ENCHANT, MINI_GAME, COMPETITION}; + private static final ConfigType[] values = new ConfigType[] {ITEM, ENTITY, BLOCK, HOOK, ROD, BAIT, UTIL, TOTEM, ENCHANT, MINI_GAME, COMPETITION, GEAR}; /** * Gets an array of all configuration types. diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/GearConfigParser.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/GearConfigParser.java new file mode 100644 index 00000000..ff5a2da5 --- /dev/null +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/config/GearConfigParser.java @@ -0,0 +1,99 @@ +package net.momirealms.customfishing.api.mechanic.config; + +import dev.dejvokep.boostedyaml.block.implementation.Section; +import net.momirealms.customfishing.api.mechanic.MechanicType; +import net.momirealms.customfishing.api.mechanic.config.function.*; +import net.momirealms.customfishing.api.mechanic.context.Context; +import net.momirealms.customfishing.api.mechanic.effect.EffectModifier; +import net.momirealms.customfishing.api.mechanic.event.EventCarrier; +import net.momirealms.customfishing.api.mechanic.item.CustomFishingItem; +import net.momirealms.customfishing.common.config.node.Node; +import net.momirealms.customfishing.common.item.Item; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.Consumer; + +public class GearConfigParser { + + private final String id; + private final String material; + private final List, Context>>> tagConsumers = new ArrayList<>(); + private final List> eventBuilderConsumers = new ArrayList<>(); + private final List> effectBuilderConsumers = new ArrayList<>(); + + public GearConfigParser(String id, Section section, Map> functionMap) { + this.id = id; + this.material = section.getString("material"); + if (!section.contains("tag")) section.set("tag", true); + analyze(section, functionMap); + } + + private void analyze(Section section, Map> functionMap) { + Map dataMap = section.getStringRouteMappedValues(false); + for (Map.Entry entry : dataMap.entrySet()) { + String key = entry.getKey(); + Node node = functionMap.get(key); + if (node == null) continue; + ConfigParserFunction function = node.nodeValue(); + if (function != null) { + switch (function.type()) { + case ITEM: + ItemParserFunction propertyFunction = (ItemParserFunction) function; + BiConsumer, Context> result = propertyFunction.accept(entry.getValue()); + tagConsumers.add(new PriorityFunction<>(propertyFunction.getPriority(), result)); + break; + case EVENT: + EventParserFunction eventParserFunction = (EventParserFunction) function; + Consumer consumerEvent = eventParserFunction.accept(entry.getValue()); + eventBuilderConsumers.add(consumerEvent); + break; + case EFFECT_MODIFIER: + EffectModifierParserFunction effectModifierParserFunction = (EffectModifierParserFunction) function; + Consumer consumerEffect = effectModifierParserFunction.accept(entry.getValue()); + effectBuilderConsumers.add(consumerEffect); + break; + default: + // Handle other types or log a warning if an unexpected type is encountered + break; + } + continue; + } + if (entry.getValue() instanceof Section innerSection) { + analyze(innerSection, node.getChildTree()); + } + } + } + + public CustomFishingItem getItem() { + return CustomFishingItem.builder() + .material(material) + .id(id) + .tagConsumers(tagConsumers) + .build(); + } + + public EffectModifier getEffectModifier() { + EffectModifier.Builder builder = EffectModifier.builder() + .id(id) + .type(MechanicType.GEAR); + for (Consumer consumer : effectBuilderConsumers) { + consumer.accept(builder); + } + return builder.build(); + } + + public EventCarrier getEventCarrier() { + EventCarrier.Builder builder = EventCarrier.builder() + .id(id) + .type(MechanicType.GEAR); + for (Consumer consumer : eventBuilderConsumers) { + consumer.accept(builder); + } + return builder.build(); + } +} \ No newline at end of file diff --git a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingGears.java b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingGears.java index d65dbf0b..3a410158 100644 --- a/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingGears.java +++ b/api/src/main/java/net/momirealms/customfishing/api/mechanic/fishing/FishingGears.java @@ -239,6 +239,27 @@ public class FishingGears { } } } + ItemStack helmet = playerInventory.getHelmet(); + ItemStack chestplate = playerInventory.getChestplate(); + ItemStack leggings = playerInventory.getLeggings(); + ItemStack boots = playerInventory.getBoots(); + + ItemStack[] armorContents = new ItemStack[]{helmet, chestplate, leggings, boots}; + List> gearItemsList = new ArrayList<>(); + + for (ItemStack armorPiece : armorContents) { + if (armorPiece != null && armorPiece.getType() != Material.AIR) { + String gearID = BukkitCustomFishingPlugin.getInstance().getItemManager().getItemID(armorPiece); + List itemTypes = MechanicType.getTypeByID(gearID); + if (itemTypes != null && itemTypes.contains(MechanicType.GEAR)) { + gearItemsList.add(Pair.of(gearID, armorPiece)); + BukkitCustomFishingPlugin.getInstance().getEffectManager().getEffectModifier(gearID, MechanicType.GEAR).ifPresent(fishingGears.modifiers::add); + } + } + } + if (!gearItemsList.isEmpty()) { + fishingGears.gears.put(GearType.GEAR, gearItemsList); + } // check requirements before checking totems for (EffectModifier modifier : fishingGears.modifiers) { @@ -283,7 +304,17 @@ public class FishingGears { ((context, itemStack) -> {}), ((context, itemStack) -> {}) ); - + public static final GearType GEAR = new GearType(MechanicType.GEAR, + ((context, itemStack) -> {}), // castFunction + ((context, itemStack) -> {}), // reelFunction + ((context, itemStack) -> {}), // biteFunction + ((context, itemStack) -> {}), // successFunction + ((context, itemStack) -> {}), // failureFunction + ((context, itemStack) -> {}), // lureFunction + ((context, itemStack) -> {}), // escapeFunction + ((context, itemStack) -> {}), // landFunction + ((context, itemStack) -> {}) // hookFunction + ); public static final GearType BAIT = new GearType(MechanicType.BAIT, ((context, itemStack) -> { if (context.holder().getGameMode() != GameMode.CREATIVE) diff --git a/core/src/main/resources/contents/gear/default.yml b/core/src/main/resources/contents/gear/default.yml new file mode 100644 index 00000000..a8d06ac8 --- /dev/null +++ b/core/src/main/resources/contents/gear/default.yml @@ -0,0 +1,75 @@ +angler_helmet: + material: IRON_HELMET + display: + name: "<#A0D2DB>Angler's Helmet" + lore: + - '' + - '<#7FFFD4>Description:' + - ' - A sturdy helmet that slightly increases concentration when fishing.' + - '' + - '<#FFD700>Effects:' + - ' - Slightly reduces fishing difficulty.' + custom-model-data: 50010 # Example + events: + success: # -1 durability when player successfully catches fish + durability_action: + type: durability + value: + slot: head + amount: -1 + effects: + effect_1: + type: difficulty + value: -2 + +deep_sea_chestplate: + material: DIAMOND_CHESTPLATE + display: + name: "<#3A6EA5>Deep Sea Chestplate" + lore: + - '' + - '<#7FFFD4>Description:' + - ' - Reinforced chestplate that helps attract larger fish.' + - '' + - '<#FFD700>Effects:' + - ' - Increases the chance of catching silver star fish.' + custom-model-data: 50011 + effects: + effect_1: + type: group-mod + value: + - silver_star:+1 + +swift_leggings: + material: LEATHER_LEGGINGS + display: + name: "<#C0C0C0>Swift Leggings" + lore: + - '' + - '<#7FFFD4>Description:' + - ' - Lightweight leggings that help reduce the waiting time for a fish to bite.' + - '' + - '<#FFD700>Effects:' + - ' - Slightly reduces waiting time.' + custom-model-data: 50012 # Example + effects: + effect_1: + type: wait-time-multiplier + value: 0.98 # Reduces by 2% + +sturdy_boots: + material: GOLDEN_BOOTS + display: + name: "<#FFD700>Sturdy Boots" + lore: + - '' + - '<#7FFFD4>Description:' + - ' - Boots that help you stand firmer, making the game a little easier.' + - '' + - '<#FFD700>Effects:' + - ' - Slightly reduces game time (making it easier).' + custom-model-data: 50013 # Example + effects: + effect_1: + type: game-time + value: -0.5 # Reduces game time by 0.5 seconds diff --git a/core/src/main/resources/translations/vi_vn.yml b/core/src/main/resources/translations/vi_vn.yml new file mode 100644 index 00000000..113ad91b --- /dev/null +++ b/core/src/main/resources/translations/vi_vn.yml @@ -0,0 +1,94 @@ +# Không đổi !!! +# Việt hóa bởi https://github.com/NguyenSonhoa +config-version: "33" + +exception.invalid_syntax: "Cú pháp không hợp lệ. Cú pháp đúng: " +exception.invalid_argument: "Tham số không hợp lệ. Lý do: " +exception.invalid_sender: " không được phép thực thi lệnh đó. Phải là " +exception.unexpected: "Đã xảy ra lỗi nội bộ khi thực thi lệnh này" +exception.no_permission: "Xin lỗi, bạn không có quyền thực thi lệnh này" +exception.no_such_command: "Lệnh vô định." +argument.entity.notfound.player: "" +argument.entity.notfound.entity: "" +argument.parse.failure.time: "'' không phải là định dạng thời gian hợp lệ" +argument.parse.failure.material: "'' không phải là tên vật phẩm hợp lệ" +argument.parse.failure.enchantment: "'' không phải là phù phép hợp lệ" +argument.parse.failure.offlineplayer: "Không tìm thấy người chơi với tên ''" +argument.parse.failure.player: "Không tìm thấy người chơi với tên ''" +argument.parse.failure.world: "'' không phải là một thế giới Minecraft hợp lệ" +argument.parse.failure.location.invalid_format: "'' không phải là vị trí hợp lệ. Định dạng yêu cầu là ' " +argument.parse.failure.location.mixed_local_absolute: "Không thể trộn lẫn tọa độ cục bộ và tọa độ tuyệt đối. (hoặc tất cả tọa độ đều dùng '^' hoặc không tọa độ nào dùng)" +argument.parse.failure.namespacedkey.namespace: "Không gian tên không hợp lệ ''. Phải là [a-z0-9._-]" +argument.parse.failure.namespacedkey.key: "Khóa không hợp lệ ''. Phải là [a-z0-9/._-]" +argument.parse.failure.namespacedkey.need_namespace: "Dữ liệu vào không hợp lệ '', yêu cầu một không gian tên rõ ràng" +argument.parse.failure.boolean: "Không thể phân tích giá trị boolean từ ''" +argument.parse.failure.number: "'' không phải là một số hợp lệ trong khoảng từ đến " +argument.parse.failure.char: "'' không phải là một ký tự hợp lệ" +argument.parse.failure.string: "'' không phải là một chuỗi hợp lệ của loại " +argument.parse.failure.uuid: "'' không phải là một UUID hợp lệ" +argument.parse.failure.enum: "'' không phải là một trong những giá trị sau: " +argument.parse.failure.regex: "'' không khớp với ''" +argument.parse.failure.flag.unknown: "Flag không xác định ''" +argument.parse.failure.flag.duplicate_flag: "Flag bị trùng lặp ''" +argument.parse.failure.flag.no_flag_started: "Không có Flag nào được bắt đầu. Không biết phải làm gì với ''" +argument.parse.failure.flag.missing_argument: "Thiếu tham số cho ''" +argument.parse.failure.flag.no_permission: "Bạn không có quyền sử dụng ''" +argument.parse.failure.color: "'' không phải là màu hợp lệ" +argument.parse.failure.duration: "'' không phải là định dạng thời gian" +argument.parse.failure.aggregate.missing: "Thiếu thành phần ''" +argument.parse.failure.aggregate.failure: "Thành phần không hợp lệ '': " +argument.parse.failure.either: "Không thể phân giải hoặc từ ''" +argument.parse.failure.namedtextcolor: "'' không phải là một màu văn bản được đặt tên" +command.reload.success: "Tải lại hoàn tất. Mất mili giây." +command.item.failure.not_exist: "Vật phẩm [] không tồn tại." +command.item.give.success: "Đã đưa thành công cho x ." +command.item.get.success: "Đã nhận thành công x ." +command.item.import.failure.no_item: "Bạn không thể nhập không khí" +command.item.import.success: "Vật phẩm [] đã được lưu vào /plugins/CustomFishing/imported_items.yml" +command.fish_finder.possible_loots: "Vật phẩm có thể câu được ở đây: " +command.fish_finder.no_loot: "Không tìm thấy vật phẩm nào ở đây" +command.fish_finder.split_char: ", " +command.competition.failure.not_exist: "Cuộc thi không tồn tại." +command.competition.failure.no_competition: "Hiện không có cuộc thi nào đang diễn ra." +command.competition.stop.success: "Đã dừng cuộc thi hiện tại." +command.competition.end.success: "Đã kết thúc cuộc thi hiện tại." +command.competition.start.success: "Đã bắt đầu cuộc thi." +command.bag.edit.failure.unsafe: "Không thể chỉnh sửa túi câu của người chơi nếu họ đang hoạt động trên một máy chủ liên kết khác." +command.bag.edit.failure.never_played: "Người chơi chưa từng tham gia máy chủ này. Không thể sửa đổi túi câu của người chơi không tồn tại." +command.bag.open.success: "Đã mở thành công túi câu cho " +command.bag.open.failure.not_loaded: "Không thể mở túi cho vì dữ liệu chưa được tải" +command.data.failure.not_loaded: "Dữ liệu chưa được tải. Vui lòng vào lại máy chủ. Nếu sự cố vẫn tiếp diễn, hãy liên hệ với quản trị viên máy chủ." +command.market.open.success: "Đã mở thành công giao diện chợ cho " +command.market.open.failure.not_loaded: "Không thể mở chợ cho vì dữ liệu chưa được tải" +command.data.unlock.success: "Đã mở khóa thành công dữ liệu cho " +command.data.import.failure.not_exists: "Tệp đó không tồn tại" +command.data.import.failure.invalid_file: "Tệp đó không hợp lệ" +command.data.import.failure.player_online: "Vui lòng kick tất cả người chơi đang trực tuyến trước khi sử dụng lệnh này" +command.data.import.start: "Đang nhập..." +command.data.import.progress: "Tiến trình: /" +command.data.import.success: "Đã nhập dữ liệu thành công" +command.data.export.failure.player_online: "Vui lòng kick tất cả người chơi đang trực tuyến trước khi sử dụng lệnh này" +command.data.export.start: "Đang xuất..." +command.data.export.progress: "Tiến trình: /" +command.data.export.success: "Đã xuất dữ liệu thành công" +command.statistics.failure.not_loaded: "Dữ liệu chưa được tải cho người chơi đó" +command.statistics.failure.unsupported: "Thao tác không được hỗ trợ" +command.statistics.modify.success: "Đã sửa đổi thành công số liệu thống kê câu cá cho " +command.statistics.reset.success: "Đã đặt lại thành công số liệu thống kê câu cá cho " +command.statistics.query.size: "Kích thước tối đa: " +command.statistics.query.amount: "Số lượng cá đã bắt: " +command.debug.loot.failure.rod: "Vui lòng cầm cần câu trước khi sử dụng lệnh này" +command.debug.loot.failure.no_loot: "Không có vật phẩm nào" +command.debug.loot.success: "Vật phẩm có sẵn: " +competition.no_score: "Không có điểm" +competition.no_player: "Không có người chơi" +competition.no_rank: "Không có thứ hạng" +competition.goal.catch_amount: "Số lượng cá bắt được" +competition.goal.max_size: "Con cá lớn nhất bắt được" +competition.goal.min_size: "Con cá nhỏ nhất bắt được" +competition.goal.total_score: "Tổng điểm của cá bắt được" +competition.goal.total_size: "Tổng chiều dài của cá bắt được" +format.day: "ngày" +format.hour: "giờ" +format.minute: "phút" +format.second: "giây" \ No newline at end of file