9
0
mirror of https://github.com/Xiao-MoMi/Custom-Fishing.git synced 2025-12-19 15:09:24 +00:00

Merge pull request #55 from NguyenSonhoa/main

vi_vn language support & added gears armor equipment effect.
This commit is contained in:
XiaoMoMi
2025-06-03 22:29:09 +08:00
committed by GitHub
5 changed files with 318 additions and 3 deletions

View File

@@ -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<String, Node<ConfigParserFunction>> 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.

View File

@@ -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<PriorityFunction<BiConsumer<Item<ItemStack>, Context<Player>>>> tagConsumers = new ArrayList<>();
private final List<Consumer<EventCarrier.Builder>> eventBuilderConsumers = new ArrayList<>();
private final List<Consumer<EffectModifier.Builder>> effectBuilderConsumers = new ArrayList<>();
public GearConfigParser(String id, Section section, Map<String, Node<ConfigParserFunction>> 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<String, Node<ConfigParserFunction>> functionMap) {
Map<String, Object> dataMap = section.getStringRouteMappedValues(false);
for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
String key = entry.getKey();
Node<ConfigParserFunction> 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<Item<ItemStack>, Context<Player>> result = propertyFunction.accept(entry.getValue());
tagConsumers.add(new PriorityFunction<>(propertyFunction.getPriority(), result));
break;
case EVENT:
EventParserFunction eventParserFunction = (EventParserFunction) function;
Consumer<EventCarrier.Builder> consumerEvent = eventParserFunction.accept(entry.getValue());
eventBuilderConsumers.add(consumerEvent);
break;
case EFFECT_MODIFIER:
EffectModifierParserFunction effectModifierParserFunction = (EffectModifierParserFunction) function;
Consumer<EffectModifier.Builder> 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<EffectModifier.Builder> consumer : effectBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
public EventCarrier getEventCarrier() {
EventCarrier.Builder builder = EventCarrier.builder()
.id(id)
.type(MechanicType.GEAR);
for (Consumer<EventCarrier.Builder> consumer : eventBuilderConsumers) {
consumer.accept(builder);
}
return builder.build();
}
}

View File

@@ -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<Pair<String, ItemStack>> gearItemsList = new ArrayList<>();
for (ItemStack armorPiece : armorContents) {
if (armorPiece != null && armorPiece.getType() != Material.AIR) {
String gearID = BukkitCustomFishingPlugin.getInstance().getItemManager().getItemID(armorPiece);
List<MechanicType> 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)

View File

@@ -0,0 +1,75 @@
angler_helmet:
material: IRON_HELMET
display:
name: "<b><#A0D2DB>Angler's Helmet</b>"
lore:
- ''
- '<#7FFFD4>Description:'
- '<gray> - A sturdy helmet that slightly increases concentration when fishing.'
- ''
- '<#FFD700>Effects:'
- '<gray> - 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: "<b><#3A6EA5>Deep Sea Chestplate</b>"
lore:
- ''
- '<#7FFFD4>Description:'
- '<gray> - Reinforced chestplate that helps attract larger fish.'
- ''
- '<#FFD700>Effects:'
- '<gray> - 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: "<b><#C0C0C0>Swift Leggings</b>"
lore:
- ''
- '<#7FFFD4>Description:'
- '<gray> - Lightweight leggings that help reduce the waiting time for a fish to bite.'
- ''
- '<#FFD700>Effects:'
- '<gray> - 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: "<b><#FFD700>Sturdy Boots</b>"
lore:
- ''
- '<#7FFFD4>Description:'
- '<gray> - Boots that help you stand firmer, making the game a little easier.'
- ''
- '<#FFD700>Effects:'
- '<gray> - 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

View File

@@ -0,0 +1,94 @@
# Không đổi !!!
# Việt hóa bởi https://github.com/NguyenSonhoa
config-version: "33"
exception.invalid_syntax: "<red>Cú pháp không hợp lệ. Cú pháp đúng: <white><arg:0></white></red>"
exception.invalid_argument: "<red>Tham số không hợp lệ. Lý do: <white><arg:0></white></red>"
exception.invalid_sender: "<red><arg:0> không được phép thực thi lệnh đó. Phải là <arg:1></red>"
exception.unexpected: "<red>Đã xảy ra lỗi nội bộ khi thực thi lệnh này</red>"
exception.no_permission: "<red>Xin lỗi, bạn không có quyền thực thi lệnh này</red>"
exception.no_such_command: "Lệnh vô định."
argument.entity.notfound.player: "<red><lang:argument.entity.notfound.player></red>"
argument.entity.notfound.entity: "<red><lang:argument.entity.notfound.entity></red>"
argument.parse.failure.time: "<red>'<arg:0>' không phải là định dạng thời gian hợp lệ</red>"
argument.parse.failure.material: "<red>'<arg:0>' không phải là tên vật phẩm hợp lệ</red>"
argument.parse.failure.enchantment: "<red>'<arg:0>' không phải là phù phép hợp lệ</red>"
argument.parse.failure.offlineplayer: "<red>Không tìm thấy người chơi với tên '<arg:0>'</red>"
argument.parse.failure.player: "<red>Không tìm thấy người chơi với tên '<arg:0>'</red>"
argument.parse.failure.world: "<red>'<arg:0>' không phải là một thế giới Minecraft hợp lệ</red>"
argument.parse.failure.location.invalid_format: "<red>'<arg:0>' không phải là vị trí hợp lệ. Định dạng yêu cầu là '<arg:1> <arg:2> <arg:3></red>"
argument.parse.failure.location.mixed_local_absolute: "<red>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)</red>"
argument.parse.failure.namespacedkey.namespace: "<red>Không gian tên không hợp lệ '<arg:0>'. Phải là [a-z0-9._-]</red>"
argument.parse.failure.namespacedkey.key: "<red>Khóa không hợp lệ '<arg:0>'. Phải là [a-z0-9/._-]</red>"
argument.parse.failure.namespacedkey.need_namespace: "<red>Dữ liệu vào không hợp lệ '<arg:0>', yêu cầu một không gian tên rõ ràng</red>"
argument.parse.failure.boolean: "<red>Không thể phân tích giá trị boolean từ '<arg:0>'</red>"
argument.parse.failure.number: "<red>'<arg:0>' không phải là một số hợp lệ trong khoảng từ <arg:1> đến <arg:2></red>"
argument.parse.failure.char: "<red>'<arg:0>' không phải là một ký tự hợp lệ</red>"
argument.parse.failure.string: "<red>'<arg:0>' không phải là một chuỗi hợp lệ của loại <arg:1></red>"
argument.parse.failure.uuid: "<red>'<arg:0>' không phải là một UUID hợp lệ</red>"
argument.parse.failure.enum: "<red>'<arg:0>' không phải là một trong những giá trị sau: <arg:1></red>"
argument.parse.failure.regex: "<red>'<arg:0>' không khớp với '<arg:1>'</red>"
argument.parse.failure.flag.unknown: "<red>Flag không xác định '<arg:0>'</red>"
argument.parse.failure.flag.duplicate_flag: "<red>Flag bị trùng lặp '<arg:0>'</red>"
argument.parse.failure.flag.no_flag_started: "<red>Không có Flag nào được bắt đầu. Không biết phải làm gì với '<arg:0>'</red>"
argument.parse.failure.flag.missing_argument: "<red>Thiếu tham số cho '<arg:0>'</red>"
argument.parse.failure.flag.no_permission: "<red>Bạn không có quyền sử dụng '<arg:0>'</red>"
argument.parse.failure.color: "<red>'<arg:0>' không phải là màu hợp lệ</red>"
argument.parse.failure.duration: "<red>'<arg:0>' không phải là định dạng thời gian</red>"
argument.parse.failure.aggregate.missing: "<red>Thiếu thành phần '<arg:0>'</red>"
argument.parse.failure.aggregate.failure: "<red>Thành phần không hợp lệ '<arg:0>': <arg:1></red>"
argument.parse.failure.either: "<red>Không thể phân giải <arg:1> hoặc <arg:2> từ '<arg:0>'</red>"
argument.parse.failure.namedtextcolor: "<red>'<arg:0>' không phải là một màu văn bản được đặt tên</red>"
command.reload.success: "<white>Tải lại hoàn tất. Mất <green><arg:0></green> mili giây.</white>"
command.item.failure.not_exist: "<red>Vật phẩm [<arg:0>] không tồn tại.</red>"
command.item.give.success: "<white>Đã đưa thành công cho <arg:0> <arg:1>x <arg:2>.</white>"
command.item.get.success: "<white>Đã nhận thành công <arg:0>x <arg:1>.</white>"
command.item.import.failure.no_item: "<red>Bạn không thể nhập không khí</red>"
command.item.import.success: "<white>Vật phẩm [<arg:0>] đã được lưu vào /plugins/CustomFishing/imported_items.yml</white>"
command.fish_finder.possible_loots: "<white>Vật phẩm có thể câu được ở đây: <arg:0></white>"
command.fish_finder.no_loot: "<white>Không tìm thấy vật phẩm nào ở đây</white>"
command.fish_finder.split_char: ", "
command.competition.failure.not_exist: "<red>Cuộc thi <arg:0> không tồn tại.</red>"
command.competition.failure.no_competition: "<red>Hiện không có cuộc thi nào đang diễn ra.</red>"
command.competition.stop.success: "<white>Đã dừng cuộc thi hiện tại.</white>"
command.competition.end.success: "<white>Đã kết thúc cuộc thi hiện tại.</white>"
command.competition.start.success: "<white>Đã bắt đầu cuộc thi.</white>"
command.bag.edit.failure.unsafe: "<red>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.</red>"
command.bag.edit.failure.never_played: "<red>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.</red>"
command.bag.open.success: "<white>Đã mở thành công túi câu cho <arg:0></white>"
command.bag.open.failure.not_loaded: "<red>Không thể mở túi cho <arg:0> vì dữ liệu chưa được tải</red>"
command.data.failure.not_loaded: "<red>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ủ.</red>"
command.market.open.success: "<white>Đã mở thành công giao diện chợ cho <arg:0></white>"
command.market.open.failure.not_loaded: "<red>Không thể mở chợ cho <arg:0> vì dữ liệu chưa được tải</red>"
command.data.unlock.success: "<white>Đã mở khóa thành công dữ liệu cho <arg:0></white>"
command.data.import.failure.not_exists: "<red>Tệp đó không tồn tại</red>"
command.data.import.failure.invalid_file: "<red>Tệp đó không hợp lệ</red>"
command.data.import.failure.player_online: "<red>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</red>"
command.data.import.start: "<white>Đang nhập...</white>"
command.data.import.progress: "<white>Tiến trình: <arg:0>/<arg:1></white>"
command.data.import.success: "<white>Đã nhập dữ liệu thành công</white>"
command.data.export.failure.player_online: "<red>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</red>"
command.data.export.start: "<white>Đang xuất...</white>"
command.data.export.progress: "<white>Tiến trình: <arg:0>/<arg:1></white>"
command.data.export.success: "<white>Đã xuất dữ liệu thành công</white>"
command.statistics.failure.not_loaded: "<red>Dữ liệu chưa được tải cho người chơi đó</red>"
command.statistics.failure.unsupported: "<red>Thao tác không được hỗ trợ</red>"
command.statistics.modify.success: "<white>Đã sửa đổi thành công số liệu thống kê câu cá cho <arg:0></white>"
command.statistics.reset.success: "<white>Đã đặt lại thành công số liệu thống kê câu cá cho <arg:0></white>"
command.statistics.query.size: "<white>Kích thước tối đa: <arg:0></white>"
command.statistics.query.amount: "<white>Số lượng cá đã bắt: <arg:0></white>"
command.debug.loot.failure.rod: "<red>Vui lòng cầm cần câu trước khi sử dụng lệnh này</red>"
command.debug.loot.failure.no_loot: "<red>Không có vật phẩm nào</red>"
command.debug.loot.success: "<yellow><b>Vật phẩm có sẵn:</b></yellow> <arg:0>"
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"