Помогите Отсчет времени для каждого элемента из конфига

  • Автор темы Автор темы reZero
  • Дата начала Дата начала

reZero

Активный участник
Пользователь
Баллы
76
Всем привет.
Я пишу плагин-аддон к одному интересному для меня плагину.
Так вот, если вкратце, то для игрока есть команда, при вводе которой открывается gui, где он может купить ту или иную "постройку" (это лишь название, на самом деле, всё виртуально и каждая купленная "постройка" записывается в бд) и получать с неё либо ресурсы, либо деньги, либо эффекты. Все это зависит от ветки развития (каждая "постройка" имеет свою ветку развития).
Это маленькая предыстория, а теперь перейдем к самой проблеме...
Каждая такая "постройка" прописана в конфиге в следующем виде:
PHP:
builds:
  money-1:
    name: 'Банк-1'
    branch: PVEmoney
    cost: 25000
    description:
      - ''
      - '&6❙ &7Цена: &e⛂%cost%'
      - ''
      - '&6❙ &7Улучшение:'
      - '&fПри постройке Банк-1 Вы будете получать '
      - '&f100 игровой валюты в банк города.'
    type: MONEY
    value: 100
    delay: 30
    showItem: BEACON,0,1
    x: 0
    y: 3
  money-2:
    name: 'Рынок'
    required: money-1
    branch: PVEmoney
    cost: 50000
    description:
      - ''
      - '&6❙ &7Цена: &e⛂%cost%'
      - ''
      - '&6❙ &7Улучшение:'
      - '&fПри постройке Рынок Вы будете получать '
      - '&f200 игровой валюты в банк города, каждый час.'
    type: MONEY
    value: 200
    delay: 1400
    showItem: CHEST,0,1
    x: 1
    y: 3
  money-3:
    name: 'Резиденция'
    required: money-2
    branch: PVEmoney
    cost: 75000
    description:
      - ''
      - '&6❙ &7Цена: &e⛂%cost%'
      - ''
      - '&6❙ &7Улучшение:'
      - '&fПри постройке Резиденция Вы будете получать '
      - '&f250 игровой валюты в банк города, каждый час.'
    type: MONEY
    value: 250
    delay: 3600
    showItem: BOOKSHELF,0,1
    x: 2
    y: 3
  money-4:
    name: 'Банк'
    required: money-3
    branch: PVEmoney
    cost: 150000
    description:
      - ''
      - '&6❙ &7Цена: &e⛂%cost%'
      - ''
      - '&6❙ &7Улучшение:'
      - '&fПри постройке Банк Вы будете получать '
      - '&f1000 игровой валюты в банк города, каждый час.'
    type: MONEY
    value: 1000
    delay: 60
    showItem: GOLD_BLOCK,0,1
    x: 3
    y: 3
У каждой такой "постройки" есть значение delay. Оно должно отвечать за то, раз во сколько секунд выдавать игроку ту или иную "награду" (зависит от вертки прокачки).
И проблема заключается в том, что я сильно затупил и вовсе не понимаю, каким образом можно считать время У КАЖДОЙ такой "постройки". То есть, например, у нас в конфиге есть 5 "построек" ветки MONEY, если игрок покупает сразу все 5 "построек", он должен получать деньги с каждой из них, но ведь у каждой их них есть свой delay и отталкиваясь от этого я хотел бы сделать так, чтобы время считалось у каждой купленной постройки и по его достижению того самого значения delay из конфига, происходило то самое действие (в зависимости от ветки пркоачки).
Возможно, стоит создать какой-то дополнительный класс? Честно, туплю и не могу понять, как это можно сделать.

Надеюсь, что я более-менее понятно все объяснил (если все же Вы чего-то не поняли, можете уточнить какой-либо момент, я всё постараюсь максимально подробно разъяснить). Надеюсь на Вашу помощь, не будьте злыми, помогите говнокодеру =(

Здесь у меня есть цикл, который срабатывает каждую секунду и перебирает все деревни игроков (из другого плагина), чтобы уже выдавать игрокам "награду" за купленные "постройки"
PHP:
 Bukkit.getScheduler().runTaskTimer(this, () -> {
            for(Town town : TownyUniverse.getDataSource().getTowns()) {
                TownBuild townBuild = new TownBuild(this, town);
                townBuild.giveRewards();
            }
        }, 20L, 20L);
Этот метод нужен для выдачи "награды" игроку. Сюда бы, наверное, и нужно засунуть ту самую проверку, подошло ли время выдачи награды.
Мною написанный код ниже, скорее всего, является жутким говном, но тем не менее, попрошу Вас не упрекать меня в моём говнокодерстве, а дать какую-то конструктивную критику по улучшению этого кода

PHP:
public void giveRewards() {
        if(getRewardType() != null) {
            switch (getRewardType()) {
                case MONEY: {
                    for (String rewardValue : configGetter.getValues(getRewardType(), this)) {
                        TownyEconomyHandler.add(town.getEconomyName(), Double.valueOf(rewardValue), Bukkit.getWorlds().get(0));
                    }
                    return;
                }
                case EFFECT: {
                    for(String rewardValue : configGetter.getValues(getRewardType(), this)) {
                        String[] effectParam = rewardValue.split(",");
                        PotionEffectType potionEffectType = PotionEffectType.getByName(effectParam[0]);
                        int potionLevel = Integer.parseInt(effectParam[1]);
                        for (Player player : TownyUniverse.getOnlinePlayers(town)) {
                            if (configGetter.getDisabledWorld().contains(player.getWorld().getName())) return;
                            if (player.hasPotionEffect(potionEffectType)) player.removePotionEffect(potionEffectType);
                            player.addPotionEffect(new PotionEffect(potionEffectType, 40, potionLevel));
                        }
                    }
                    return;
                }
                case RESOURCE: {
                    if(delay(Type.RESOURCE)) {
                        for (String rewardValue : configGetter.getValues(getRewardType(), this)) {
                            String[] itemsParam = rewardValue.split(",");
                            ItemStack itemStack = new ItemStack(Material.matchMaterial(itemsParam[0]), Integer.parseInt(itemsParam[2]), Short.parseShort(itemsParam[1]));
                            addItemsToDatabase(itemsParam);
                            getItems().add(itemStack);
                        }
                    }
                    return;
                }
            }
        }
    }
 
Если я всё правильно понял, ...

Есть несколько вариантов, в зависимости от деталей, которые пока не прояснены:
  1. Можно ли пренебречь фактом перезапуска сервера? Если да, и можно считать каждый таймер с 0 при загрузке, а если сервер ребутнулся, не успев выдать очередную награду, и фиг с ним, то я бы предложил две возможные реализации:
    1. Рассчитывать время до следующей выдачи и сохранять его в Map<Ресурс, СледВремяВыдачи>. В шедулере пробегать по мапе, если где-то время наступило, совершить выдачу и пересчитать следующее время.
    2. Похожий вариант, но можно хранить не следующее время, а номер периода выдачи (как System.currentTimeMillis() % delay). Если текущий период поменялся, то совершить выдачу (можно даже 2 или больше, т.к. в таком случае становится понятно, сколько периодов выдача не случалась). Но тут есть опасность выдать миллионы ресурсов, если delay захочется уменьшить 🙂
  2. Если есть длительные delay, которые сравнимы/больше времени работы сервера до рестарта, то придётся сохранять текущие значения СледВремяВыдачи или НомерПериода в БД или конфиг.
Плюс, если выдачи для разных игроков в разное время, всё вышеперечисленное -- для каждого игрока хранить.
 
дополню коммент выше (upd: или вероятно даже перефразирую его, так как перечитав его я понял что написал примерно то же самое)
можно в момент покупки или выдачи награды вычислять время следующей выдачи награды как текущее + delay (вариант 2 в комменте выше). его можно хранить локально и в базе
в базу можно писать не всегда, а лишь иногда для надежности сбрасывать (мб асинхронно) + сохранять при выключении сервера
а по таймеру проверять, не настало ли время выдачи награды. кстати, если delay кратен 30, 60 или еще сколько то секунд, можно таймер запускать не каждую секунду, а тоже 30 или 60
либо все то же самое, но хранить оставшееся время до выдачи. и в таймере вычитать
в твоем коде это надо впихнуть перед giveRewards, чтобы выдавать награду только когда надо. ну и впихнуть куда-то привязку к игроку
 
Последнее редактирование:
ну и впихнуть куда-то привязку к игроку
Тут по постановке вопроса не очень понятно, нужно ли, может просто каждые N времени выдавать всем, у кого есть нужный "ресурс", награду, одновременно. Плюс если надо быть онлайн, вообще огонь как всё просто становится.
 
Тут по постановке вопроса не очень понятно, нужно ли, может просто каждые N времени выдавать всем, у кого есть нужный "ресурс", награду, одновременно. Плюс если надо быть онлайн, вообще огонь как всё просто становится.
логично. ну тогда вопрос, что значит ветка развития постройки. и можно ли просто каждой паре (игрок,постройка) сказать, есть у этого игрока или нет. или все же каждая постройка уникальна и от игрока к игроку может отличаться (мб постройку можно будет еще как-то грейдить/ускорять), можно ли перебирать только типы построек и выдавать награды всем обладателям, или надо отдельно обрабатывать каждый экземпляр.
короче вопрос к ТС, какой конкретно вариант ему нужен и какие конкретно проблемы с реализацией (с учетом новой инфы, если она полезна)
 
логично. ну тогда вопрос, что значит ветка развития постройки. и можно ли просто каждой паре (игрок,постройка) сказать, есть у этого игрока или нет. или все же каждая постройка уникальна и от игрока к игроку может отличаться (мб постройку можно будет еще как-то грейдить/ускорять), можно ли перебирать только типы построек и выдавать награды всем обладателям, или надо отдельно обрабатывать каждый экземпляр.
короче вопрос к ТС, какой конкретно вариант ему нужен и какие конкретно проблемы с реализацией (с учетом новой инфы, если она полезна)
логично. ну тогда вопрос, что значит ветка развития постройки. и можно ли просто каждой паре (игрок,постройка) сказать, есть у этого игрока или нет. или все же каждая постройка уникальна и от игрока к игроку может отличаться (мб постройку можно будет еще как-то грейдить/ускорять), можно ли перебирать только типы построек и выдавать награды всем обладателям, или надо отдельно обрабатывать каждый экземпляр.
короче вопрос к ТС, какой конкретно вариант ему нужен и какие конкретно проблемы с реализацией (с учетом новой инфы, если она полезна)

Всё квда проще)
Есть плагин towny, который позволяет создать свой город.
У меня, пока что, есть 2 ветки прокачки: одна даёт деньги в банк города (который есть изначалано при создании города и с которым можно взаимодействовать даже если игроки города не онлайн), а другая должна давать ресурсы на склад города. Так как в плагине towny никакого склада ресурсов нет, я написал его сам, в этом плагине по которому прошу хелп)
Суть в том, что у меня при включении сервера запускается ранебл, который перебирает все города плагина towny, создаёт новый экземпляр нужного мне класса и ввдаёт награду. Если ветка прокачки это ресурсы то когда подходит нужное время, берется база данных от моего плагина с названием этого города и добавляется туда предмет. Выглядит всё это дело в виде обычного листа типа string, где через запятую записано количество и дата.
Далее, когда игрок захотел открыть склад города, я через цикл перебираю все эти предметы из бд его города и добавляю в кастомный гуи, который и открываю игроку, чтоб он мог оттуда забрать какие-то ресурсы.

Если я всё правильно понял, ...

Есть несколько вариантов, в зависимости от деталей, которые пока не прояснены:
  1. Можно ли пренебречь фактом перезапуска сервера? Если да, и можно считать каждый таймер с 0 при загрузке, а если сервер ребутнулся, не успев выдать очередную награду, и фиг с ним, то я бы предложил две возможные реализации:
    1. Рассчитывать время до следующей выдачи и сохранять его в Map<Ресурс, СледВремяВыдачи>. В шедулере пробегать по мапе, если где-то время наступило, совершить выдачу и пересчитать следующее время.
    2. Похожий вариант, но можно хранить не следующее время, а номер периода выдачи (как System.currentTimeMillis() % delay). Если текущий период поменялся, то совершить выдачу (можно даже 2 или больше, т.к. в таком случае становится понятно, сколько периодов выдача не случалась). Но тут есть опасность выдать миллионы ресурсов, если delay захочется уменьшить 🙂
  2. Если есть длительные delay, которые сравнимы/больше времени работы сервера до рестарта, то придётся сохранять текущие значения СледВремяВыдачи или НомерПериода в БД или конфиг.
Плюс, если выдачи для разных игроков в разное время, всё вышеперечисленное -- для каждого игрока хранить.
Да, этим фактом можно пренебречь. Я вот только не понимаю, как сделать этот сам расчёт и таймер. Просто у меня уже есть ранебл в main классе (вроде в шапке темы есть) и не хотелось бы создавать новый, а пользовать этим
 
Всё квда проще)
Есть плагин towny, который позволяет создать свой город.
У меня, пока что, есть 2 ветки прокачки: одна даёт деньги в банк города (который есть изначалано при создании города и с которым можно взаимодействовать даже если игроки города не онлайн), а другая должна давать ресурсы на склад города. Так как в плагине towny никакого склада ресурсов нет, я написал его сам, в этом плагине по которому прошу хелп)
Суть в том, что у меня при включении сервера запускается ранебл, который перебирает все города плагина towny, создаёт новый экземпляр нужного мне класса и ввдаёт награду. Если ветка прокачки это ресурсы то когда подходит нужное время, берется база данных от моего плагина с названием этого города и добавляется туда предмет. Выглядит всё это дело в виде обычного листа типа string, где через запятую записано количество и дата.
Далее, когда игрок захотел открыть склад города, я через цикл перебираю все эти предметы из бд его города и добавляю в кастомный гуи, который и открываю игроку, чтоб он мог оттуда забрать какие-то ресурсы.


Да, этим фактом можно пренебречь. Я вот только не понимаю, как сделать этот сам расчёт и таймер. Просто у меня уже есть ранебл в main классе (вроде в шапке темы есть) и не хотелось бы создавать новый, а пользовать этим
И всё же, может кто-то может подсказать?
 
Назад
Верх