Первый на сервере выполнил квест.

Yarpi

Vassal
Customer
Вообщем дело было вечером, делать было нечего)
Наколдовал при помощи чатгпт скрипт выдачи бонуса при выполнение определенных квестов первым кто выполнил на сервере квест.

Код класса FirstQuestCompletionService

JavaScript:
package services;

import l2.commons.listener.EventListener;
import l2.gameserver.GameServer;
import l2.gameserver.model.Player;
import l2.gameserver.model.quest.Quest;
import l2.gameserver.scripts.Functions;
import l2.gameserver.scripts.ScriptFile;
import l2.gameserver.utils.ItemFunctions;
import l2.gameserver.database.DatabaseFactory;
import l2.gameserver.data.StringHolder;
import l2.gameserver.Config;
import l2.gameserver.Announcements;
import l2.gameserver.network.l2.components.ChatType;

import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class FirstQuestCompletionService extends Functions implements ScriptFile, EventListener {
    private static final String EVENT_FINISH_QUEST = "onQuestFinish";
    private static final String[] LISTENING_EVENTS = new String[]{EVENT_FINISH_QUEST};

    // Карта для хранения отслеживаемых квестов и их наград
    private static final Map<Integer, QuestReward> TRACKED_QUESTS = new HashMap<>();

    // Множество для хранения ID уже завершённых квестов
    private static final Set<Integer> completedQuests = new HashSet<>();

    @Override
    public String[] listeningEventTypes() {
        return LISTENING_EVENTS;
    }

    private void onQuestFinish(Player player, Quest quest, Boolean aborted) {
        if (quest != null && !aborted && TRACKED_QUESTS.containsKey(quest.getQuestIntId())) {
            // Проверяем, был ли этот квест уже завершён кем-то
            if (isFirstCompletion(quest.getQuestIntId())) {
                // Записываем, что квест завершён первым игроком
                recordFirstCompletion(quest.getQuestIntId(), player.getName());

                // Награждаем игрока
                rewardPlayer(player, quest.getQuestIntId());

                // Получаем название квеста
                String questName = TRACKED_QUESTS.get(quest.getQuestIntId()).getName();

                // Сообщаем игроку о первом завершении
                String message = StringHolder.getInstance().getNotNull(player, "first_completion_message");
                player.sendMessage(message.replace("{quest_name}", questName));

                // Уведомляем всех игроков
                announceFirstQuestCompletion(player, questName);
            } else {
                // Получаем название квеста
                String questName = TRACKED_QUESTS.get(quest.getQuestIntId()).getName();
                // Сообщаем игроку, что он не первый
                String notFirstMessage = StringHolder.getInstance().getNotNull(player, "not_first_completion_message");
                player.sendMessage(notFirstMessage.replace("{quest_name}", questName));
            }
        }
    }

    // Метод для уведомления всех игроков о первом завершении квеста
    private void announceFirstQuestCompletion(Player player, String questName) {
        // Получаем сообщение из стринг файла
        String messageTemplate = StringHolder.getInstance().getNotNull(player, "first_quest_completion_announcement");

        // Форматируем сообщение с именем игрока и названием квеста
        String message = messageTemplate.replace("{player_name}", player.getName())
                .replace("{quest_name}", questName);

        // Уведомляем всех игроков
        Announcements.getInstance().announceToAll(message, ChatType.ANNOUNCEMENT);
    }

    @Override
    public void onEvent(String eventType, Object... args) {
        if (eventType.equals(EVENT_FINISH_QUEST)) {
            onQuestFinish((Player) args[0], (Quest) args[1], (Boolean) args[2]);
        }
    }

    @Override
    public void onLoad() {
        // Вывод сообщения в консоль
        System.out.println("Loaded system: First Quest Completion Service");

        // Загружаем информацию о завершённых квестах из базы данных
        loadCompletedQuests();

        // Загружаем информацию о квестах из XML
        loadQuestDataFromXML();

        // Регистрируем слушателя событий
        GameServer.getInstance().getListeners().addEventListener(this);
    }

    @Override
    public void onReload() {
    }

    @Override
    public void onShutdown() {
    }

    // Метод для проверки, был ли квест завершён первым
    private boolean isFirstCompletion(int questId) {
        return !completedQuests.contains(questId);
    }

    // Метод для записи информации о первом завершении квеста
    private void recordFirstCompletion(int questId, String playerName) {
        completedQuests.add(questId);

        try (Connection con = DatabaseFactory.getInstance().getConnection()) {
            PreparedStatement statement = con.prepareStatement("INSERT INTO first_quest_completion (quest_id, player_name) VALUES (?, ?)");
            statement.setInt(1, questId);
            statement.setString(2, playerName);
            statement.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // Метод для загрузки информации о завершённых квестах из базы данных
    private void loadCompletedQuests() {
        try (Connection con = DatabaseFactory.getInstance().getConnection()) {
            PreparedStatement statement = con.prepareStatement("SELECT quest_id FROM first_quest_completion");
            ResultSet rs = statement.executeQuery();

            while (rs.next()) {
                int questId = rs.getInt("quest_id");
                completedQuests.add(questId);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    // Метод для награждения игрока
    private void rewardPlayer(Player player, int questId) {
        QuestReward reward = TRACKED_QUESTS.get(questId);
        if (reward != null) {
            ItemFunctions.addItem(player, reward.getItemId(), reward.getAmount(), true);
        }
    }

    // Метод для загрузки квестов и наград из XML
    private void loadQuestDataFromXML() {
        try {
            File xmlFile = new File(Config.DATAPACK_ROOT, "data/tracked_quests.xml");

            if (!xmlFile.exists()) {
                System.out.println("Файл не найден: " + xmlFile.getAbsolutePath());
                return;
            }

            SAXReader reader = new SAXReader();
            Document document = reader.read(xmlFile);
            Element rootElement = document.getRootElement();

            for (Iterator<?> it = rootElement.elementIterator(); it.hasNext(); ) {
                Element questElement = (Element) it.next();

                if ("quest".equals(questElement.getName())) {
                    int questId = Integer.parseInt(questElement.attributeValue("id"));
                    int rewardItemId = Integer.parseInt(questElement.attributeValue("rewardItemId"));
                    int rewardAmount = Integer.parseInt(questElement.attributeValue("rewardAmount"));
                    String questName = questElement.attributeValue("name"); // Получаем название квеста

                    // Добавляем квест в карту отслеживаемых квестов
                    TRACKED_QUESTS.put(questId, new QuestReward(rewardItemId, rewardAmount, questName));
                }
            }

            System.out.println("Квесты загружены из файла: " + xmlFile.getAbsolutePath());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // Вспомогательный класс для хранения информации о наградах квестов
    private static class QuestReward {
        private final int itemId;
        private final int amount;
        private final String name; // Название квеста

        public QuestReward(int itemId, int amount, String name) {
            this.itemId = itemId;
            this.amount = amount;
            this.name = name;
        }

        public int getItemId() {
            return itemId;
        }

        public int getAmount() {
            return amount;
        }

        public String getName() {
            return name; // Метод для получения названия квеста
        }
    }
}

xml файл в папку data с названием tracked_quests.xml
Code:
<?xml version="1.0" encoding="UTF-8"?>
<quests>
    <quest id="1" name="Letter of Love" rewardItemId="57" rewardAmount="100000" />
    <quest id="60" name="Another Quest" rewardItemId="57" rewardAmount="50000" />
</quests>

sql запрос
Code:
CREATE TABLE IF NOT EXISTS first_quest_completion (
    quest_id INT PRIMARY KEY,
    player_name VARCHAR(255) NOT NULL
);

стринги
Code:
first_quest_completion_announcement=Поздравляем!"{player_name}" завершил первым квест "{quest_name}" и получил специальную награду!
first_completion_message=Поздравляем! Вы первый на сервере, кто завершил квест "{quest_name}" и получили специальную награду!
not_first_completion_message=Вы завершили квест "{quest_name}", но награда за первое завершение уже была получена другим игроком.

прошу тряпками не кидать. писал через чатгпт
 
Last edited:
Back
Top