Ответ от o1-preview:
Я вижу, что вы предоставили ваш текущий код класса Plant_growth. Ваша цель — сделать так, чтобы значения скорости роста растений считывались из файла конфигурации config.yml, и изменения в этом файле влияли на поведение плагина без необходимости переписывать код.
Давайте шаг за шагом модифицируем ваш код, чтобы достичь этого.
1. Считывание значений из конфигурации
В вашем методе onEnable() вам нужно загрузить значения из config.yml и заполнить ими growthTimes.
Шаги:
- Убедитесь, что файл config.yml загружается при старте плагина.
- Пройдитесь по каждому разделу в конфигурации и извлеките необходимые данные.
@Override
public void onEnable() {
getLogger().info("Plugin Enabled");
getServer().getPluginManager().registerEvents(this, this);
// Загружаем конфигурацию
saveDefaultConfig();
reloadConfig();
// Инициализируем время роста из конфигурации
loadGrowthTimesFromConfig();
}
2. Метод для загрузки данных из конфигурации
Создадим метод loadGrowthTimesFromConfig(), который будет считывать данные из конфигурации и заполнять growthTimes.
private void loadGrowthTimesFromConfig() {
for (String key : getConfig().getKeys(false)) {
ConfigurationSection plantSection = getConfig().getConfigurationSection(key);
if (plantSection != null) {
int id = plantSection.getInt("id");
String speedStr = plantSection.getString("speed");
// Парсим значение скорости в тики
long growthTicks = parseDurationToTicks(speedStr);
// Сохраняем в карту
growthTimes.put(id, growthTicks);
}
}
}
3. Парсинг значения скорости в тики
Реализуем метод parseDurationToTicks(String durationString) для преобразования строки вида "7d" в количество тиков.
public long parseDurationToTicks(String durationString) {
durationString = durationString.toLowerCase().trim();
long ticks = 0;
try {
if (durationString.endsWith("d")) {
String numberPart = durationString.substring(0, durationString.length() - 1);
ticks = Long.parseLong(numberPart) * 24 * 60 * 60 * 20; // 1 день = 1728000 тиков
} else if (durationString.endsWith("h")) {
String numberPart = durationString.substring(0, durationString.length() - 1);
ticks = Long.parseLong(numberPart) * 60 * 60 * 20; // 1 час = 72000 тиков
} else if (durationString.endsWith("m")) {
String numberPart = durationString.substring(0, durationString.length() - 1);
ticks = Long.parseLong(numberPart) * 60 * 20; // 1 минута = 1200 тиков
} else if (durationString.endsWith("s")) {
String numberPart = durationString.substring(0, durationString.length() - 1);
ticks = Long.parseLong(numberPart) * 20; // 1 секунда = 20 тиков
} else {
// Если нет суффикса, считаем, что это тики
ticks = Long.parseLong(durationString);
}
} catch (NumberFormatException e) {
getLogger().warning("Неверный формат времени: " + durationString);
ticks = 0;
}
return ticks;
}
4. Обновление обработчика событий роста
Теперь нам нужно обновить метод onPlantGrow, чтобы он корректно работал с новыми данными.
@EventHandler
public void onPlantGrow(BlockGrowEvent event) {
int id = event.getBlock().getType().getId();
if (growthTimes.containsKey(id)) {
event.setCancelled(true); // Отменяем обычный рост
long growthTime = growthTimes.get(id);
getServer().getScheduler().runTaskLater(this, () -> {
// Получаем следующий этап роста растения
Block block = event.getBlock();
Material nextStage = getNextGrowthStage(block.getType());
if (nextStage != null) {
block.setType(nextStage);
}
}, growthTime);
}
}
5. Метод для определения следующей стадии роста
Вам потребуется метод getNextGrowthStage(Material currentStage), чтобы определить, какое растение поставить на следующей стадии роста.
private Material getNextGrowthStage(Material currentStage) {
// Здесь вы можете определить логику перехода между стадиями роста
// Например, для пшеницы можно использовать enum Material по стадиям роста
// Однако в Bukkit API стадии роста растений обычно управляются с помощью данных блока (BlockData)
// Пример для пшеницы:
if (currentStage == Material.WHEAT) {
// Получаем данные о росте
Ageable ageable = (Ageable) currentStage.createBlockData();
if (ageable.getAge() < ageable.getMaximumAge()) {
ageable.setAge(ageable.getAge() + 1);
return ageable.getMaterial();
}
}
// Для других растений аналогично
return null;
}
6. Обработка данных блока (BlockData)
Современный Bukkit API рекомендует использовать BlockData вместо устаревших методов. Мы можем обновить наш код, чтобы использовать BlockData для установки возраста растения.
Обновленный код обработчика события:
@EventHandler
public void onPlantGrow(BlockGrowEvent event) {
Block block = event.getBlock();
Material material = block.getType();
int id = material.getId();
if (growthTimes.containsKey(id)) {
event.setCancelled(true); // Отменяем обычный рост
long growthTime = growthTimes.get(id);
getServer().getScheduler().runTaskLater(this, () -> {
// Увеличиваем стадию роста
BlockData data = block.getBlockData();
if (data instanceof Ageable) {
Ageable ageable = (Ageable) data;
if (ageable.getAge() < ageable.getMaximumAge()) {
ageable.setAge(ageable.getAge() + 1);
block.setBlockData(ageable);
}
}
}, growthTime);
}
}
7. Обновление обработчика события разрушения блока
Если вы хотите управлять выпадением предметов при сборе урожая, вы можете использовать BlockBreakEvent и проверять стадии роста.
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
Block block = event.getBlock();
Material material = block.getType();
int id = material.getId();
if (growthTimes.containsKey(id)) {
BlockData data = block.getBlockData();
if (data instanceof Ageable) {
Ageable ageable = (Ageable) data;
if (ageable.getAge() < ageable.getMaximumAge()) {
// Растение еще не созрело
event.setDropItems(false); // Отменяем выпадение
event.getPlayer().sendMessage("Растение еще не созрело!");
} else {
// Растение созрело, можно настроить выпадение предметов
// Здесь можно использовать данные из конфигурации
}
}
}
}
8. Обработка выпадения предметов при сборе урожая
Чтобы управлять тем, какие предметы выпадают при сборе урожая, используйте данные из раздела droping в конфигурации.
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
Block block = event.getBlock();
Material material = block.getType();
int id = material.getId();
if (growthTimes.containsKey(id)) {
BlockData data = block.getBlockData();
if (data instanceof Ageable) {
Ageable ageable = (Ageable) data;
if (ageable.getAge() < ageable.getMaximumAge()) {
// Растение еще не созрело
event.setDropItems(false);
event.getPlayer().sendMessage("Растение еще не созрело!");
} else {
// Растение созрело
event.setDropItems(false); // Отменяем стандартное выпадение
// Получаем информацию о выпадении из конфигурации
String key = getConfigKeyById(id);
if (key != null) {
ConfigurationSection plantSection = getConfig().getConfigurationSection(key);
if (plantSection != null) {
ConfigurationSection dropSection = plantSection.getConfigurationSection("droping");
if (dropSection != null) {
// Удаляем предметы из списка remove
List<String> removeItems = dropSection.getStringList("remove");
// Добавляем предметы из списка add
List<String> addItems = dropSection.getStringList("add");
// Удаление предметов (если нужно)
// В вашем случае вы отменили стандартное выпадение, поэтому это может быть не нужно
// Добавление новых предметов
for (String itemName : addItems) {
Material dropMaterial = Material.getMaterial(itemName.toUpperCase());
if (dropMaterial != null) {
block.getWorld().dropItemNaturally(block.getLocation(), new ItemStack(dropMaterial));
}
}
}
}
}
}
}
}
}
Метод для получения ключа конфигурации по ID
private String getConfigKeyById(int id) {
for (String key : getConfig().getKeys(false)) {
if (getConfig().getInt(key + ".id") == id) {
return key;
}
}
return null;
}
9. Корректировка файла конфигурации
Убедитесь, что ваш config.yml имеет правильную структуру.
Wheat_Seeds:
id: 59
speed: 7d
droping:
remove:
- wheat_seeds
add:
- wheat
Melon_Seeds:
id: 105
speed: 7d
droping:
remove:
- melon_seeds
add:
- melon_slice
Примечание: Используйте правильные ID блоков и названия материалов. Например, для пшеницы в виде блока используется Material.WHEAT, который имеет ID 59, а для семян — Material.WHEAT_SEEDS.
10. Обновление устаревших методов
Обратите внимание, что метод getId() устарел. Лучше использовать Material напрямую или использовать NamespacedKey для идентификации материалов.
Замена:
private Map<Material, Long> growthTimes = new HashMap<>();
И везде, где вы используете ID, замените на Material.
Пример:
private void loadGrowthTimesFromConfig() {
for (String key : getConfig().getKeys(false)) {
ConfigurationSection plantSection = getConfig().getConfigurationSection(key);
if (plantSection != null) {
String materialName = plantSection.getString("material");
Material material = Material.getMaterial(materialName.toUpperCase());
if (material != null) {
String speedStr = plantSection.getString("speed");
long growthTicks = parseDurationToTicks(speedStr);
growthTimes.put(material, growthTicks);
} else {
getLogger().warning("Неизвестный материал: " + materialName);
}
}
}
}
И в обработчиках событий:
@EventHandler
public void onPlantGrow(BlockGrowEvent event) {
Material material = event.getBlock().getType();
if (growthTimes.containsKey(material)) {
// Остальной код
}
}
11. Полный обновленный код класса
package yt.tanr1.plant_growth;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.data.Ageable;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockGrowEvent;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Plant_growth extends JavaPlugin implements Listener {
// Храним время роста для конкретного материала растения
private Map<Material, Long> growthTimes = new HashMap<>();
@Override
public void onEnable() {
getLogger().info("Plugin Enabled");
getServer().getPluginManager().registerEvents(this, this);
// Загружаем конфигурацию
saveDefaultConfig();
reloadConfig();
// Инициализируем время роста из конфигурации
loadGrowthTimesFromConfig();
}
private void loadGrowthTimesFromConfig() {
for (String key : getConfig().getKeys(false)) {
ConfigurationSection plantSection = getConfig().getConfigurationSection(key);
if (plantSection != null) {
String materialName = plantSection.getString("material");
Material material = Material.getMaterial(materialName.toUpperCase());
if (material != null) {
String speedStr = plantSection.getString("speed");
long growthTicks = parseDurationToTicks(speedStr);
growthTimes.put(material, growthTicks);
} else {
getLogger().warning("Неизвестный материал: " + materialName);
}
}
}
}
public long parseDurationToTicks(String durationString) {
durationString = durationString.toLowerCase().trim();
long ticks = 0;
try {
if (durationString.endsWith("d")) {
String numberPart = durationString.substring(0, durationString.length() - 1);
ticks = Long.parseLong(numberPart) * 24 * 60 * 60 * 20;
} else if (durationString.endsWith("h")) {
String numberPart = durationString.substring(0, durationString.length() - 1);
ticks = Long.parseLong(numberPart) * 60 * 60 * 20;
} else if (durationString.endsWith("m")) {
String numberPart = durationString.substring(0, durationString.length() - 1);
ticks = Long.parseLong(numberPart) * 60 * 20;
} else if (durationString.endsWith("s")) {
String numberPart = durationString.substring(0, durationString.length() - 1);
ticks = Long.parseLong(numberPart) * 20;
} else {
ticks = Long.parseLong(durationString);
}
} catch (NumberFormatException e) {
getLogger().warning("Неверный формат времени: " + durationString);
ticks = 0;
}
return ticks;
}
@EventHandler
public void onPlantGrow(BlockGrowEvent event) {
Block block = event.getBlock();
Material material = block.getType();
if (growthTimes.containsKey(material)) {
event.setCancelled(true); // Отменяем обычный рост
long growthTime = growthTimes.get(material);
new BukkitRunnable() {
@Override
public void run() {
BlockData data = block.getBlockData();
if (data instanceof Ageable) {
Ageable ageable = (Ageable) data;
if (ageable.getAge() < ageable.getMaximumAge()) {
ageable.setAge(ageable.getAge() + 1);
block.setBlockData(ageable);
}
}
}
}.runTaskLater(this, growthTime);
}
}
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
Block block = event.getBlock();
Material material = block.getType();
if (growthTimes.containsKey(material)) {
BlockData data = block.getBlockData();
if (data instanceof Ageable) {
Ageable ageable = (Ageable) data;
if (ageable.getAge() < ageable.getMaximumAge()) {
event.setDropItems(false);
event.getPlayer().sendMessage("Растение еще не созрело!");
} else {
event.setDropItems(false);
String key = getConfigKeyByMaterial(material);
if (key != null) {
ConfigurationSection plantSection = getConfig().getConfigurationSection(key);
if (plantSection != null) {
ConfigurationSection dropSection = plantSection.getConfigurationSection("droping");
if (dropSection != null) {
List<String> addItems = dropSection.getStringList("add");
for (String itemName : addItems) {
Material dropMaterial = Material.getMaterial(itemName.toUpperCase());
if (dropMaterial != null) {
block.getWorld().dropItemNaturally(block.getLocation(), new ItemStack(dropMaterial));
}
}
}
}
}
}
}
}
}
private String getConfigKeyByMaterial(Material material) {
for (String key : getConfig().getKeys(false)) {
String materialName = getConfig().getString(key + ".material");
if (materialName != null && material == Material.getMaterial(materialName.toUpperCase())) {
return key;
}
}
return null;
}
}
12. Обновленный файл конфигурации
Wheat_Seeds:
material: WHEAT
speed: 7d
droping:
remove:
- WHEAT_SEEDS
add:
- WHEAT
Melon_Seeds:
material: MELON_STEM
speed: 7d
droping:
remove:
- MELON_SEEDS
add:
- MELON_SLICE
Примечания:- Используйте Material вместо ID. В современном Bukkit API рекомендуется использовать Material напрямую, так как ID могут меняться и устарели.
- Обратите внимание на регистры. Названия материалов должны быть в верхнем регистре, чтобы метод Material.getMaterial() мог их распознать.
- Проверьте доступность материалов. Убедитесь, что используемые материалы существуют в вашей версии сервера.
- Используйте BlockData и Ageable. Это современные способы управления состояниями блоков в Bukkit API.
- Обработка ошибок. Добавьте проверки и обработку возможных ошибок, чтобы избежать сбоев плагина.
- Перезагрузка конфигурации. Если вы хотите менять конфигурацию без перезагрузки сервера, добавьте команду или механизм для перезагрузки конфигурации во время работы плагина.