1. Этот сайт использует файлы cookie. Продолжая пользоваться данным сайтом, Вы соглашаетесь на использование нами Ваших файлов cookie. Узнать больше.
  2. Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.
    Скрыть объявление
Скрыть объявление
В преддверии глобального обновления, мы проводим исследования, которые помогут нам сделать опыт пользования форумом ещё удобнее. Помогите нам, примите участие!

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

Тема в разделе "Разработка плагинов для новичков", создана пользователем reZero, 7 июл 2019.

  1. Автор темы
    reZero

    reZero Активный участник Пользователь

    Баллы:
    76
    Всем привет.
    Я пишу плагин-аддон к одному интересному для меня плагину.
    Так вот, если вкратце, то для игрока есть команда, при вводе которой открывается gui, где он может купить ту или иную "постройку" (это лишь название, на самом деле, всё виртуально и каждая купленная "постройка" записывается в бд) и получать с неё либо ресурсы, либо деньги, либо эффекты. Все это зависит от ветки развития (каждая "постройка" имеет свою ветку развития).
    Это маленькая предыстория, а теперь перейдем к самой проблеме...
    Каждая такая "постройка" прописана в конфиге в следующем виде:
    PHP:
    builds:
      
    money-1:
        
    name'Банк-1'
        
    branchPVEmoney
        cost
    25000
        description
    :
          - 
    ''
          
    '&6❙ &7Цена: &e⛂%cost%'
          
    ''
          
    '&6❙ &7Улучшение:'
          
    '&fПри постройке Банк-1 Вы будете получать '
          
    '&f100 игровой валюты в банк города.'
        
    typeMONEY
        value
    100
        delay
    30
        showItem
    BEACON,0,1
        x
    0
        y
    3
      money
    -2:
        
    name'Рынок'
        
    requiredmoney-1
        branch
    PVEmoney
        cost
    50000
        description
    :
          - 
    ''
          
    '&6❙ &7Цена: &e⛂%cost%'
          
    ''
          
    '&6❙ &7Улучшение:'
          
    '&fПри постройке Рынок Вы будете получать '
          
    '&f200 игровой валюты в банк города, каждый час.'
        
    typeMONEY
        value
    200
        delay
    1400
        showItem
    CHEST,0,1
        x
    1
        y
    3
      money
    -3:
        
    name'Резиденция'
        
    requiredmoney-2
        branch
    PVEmoney
        cost
    75000
        description
    :
          - 
    ''
          
    '&6❙ &7Цена: &e⛂%cost%'
          
    ''
          
    '&6❙ &7Улучшение:'
          
    '&fПри постройке Резиденция Вы будете получать '
          
    '&f250 игровой валюты в банк города, каждый час.'
        
    typeMONEY
        value
    250
        delay
    3600
        showItem
    BOOKSHELF,0,1
        x
    2
        y
    3
      money
    -4:
        
    name'Банк'
        
    requiredmoney-3
        branch
    PVEmoney
        cost
    150000
        description
    :
          - 
    ''
          
    '&6❙ &7Цена: &e⛂%cost%'
          
    ''
          
    '&6❙ &7Улучшение:'
          
    '&fПри постройке Банк Вы будете получать '
          
    '&f1000 игровой валюты в банк города, каждый час.'
        
    typeMONEY
        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(thistown);
                    
    townBuild.giveRewards();
                }
            }, 
    20L20L);
    Этот метод нужен для выдачи "награды" игроку. Сюда бы, наверное, и нужно засунуть ту самую проверку, подошло ли время выдачи награды.
    Мною написанный код ниже, скорее всего, является жутким говном, но тем не менее, попрошу Вас не упрекать меня в моём говнокодерстве, а дать какую-то конструктивную критику по улучшению этого кода

    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(potionEffectType40potionLevel));
                            }
                        }
                        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;
                    }
                }
            }
        }
     
  2. Автор темы
    reZero

    reZero Активный участник Пользователь

    Баллы:
    76
    Ну не игнорьте =(
     
  3. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Если я всё правильно понял, ...

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

    Code Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    _Gizmo
    дополню коммент выше (upd: или вероятно даже перефразирую его, так как перечитав его я понял что написал примерно то же самое)
    можно в момент покупки или выдачи награды вычислять время следующей выдачи награды как текущее + delay (вариант 2 в комменте выше). его можно хранить локально и в базе
    в базу можно писать не всегда, а лишь иногда для надежности сбрасывать (мб асинхронно) + сохранять при выключении сервера
    а по таймеру проверять, не настало ли время выдачи награды. кстати, если delay кратен 30, 60 или еще сколько то секунд, можно таймер запускать не каждую секунду, а тоже 30 или 60
    либо все то же самое, но хранить оставшееся время до выдачи. и в таймере вычитать
    в твоем коде это надо впихнуть перед giveRewards, чтобы выдавать награду только когда надо. ну и впихнуть куда-то привязку к игроку
     
    Последнее редактирование: 8 июл 2019
  5. Reality_SC

    Reality_SC Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    Reality_SC
    Тут по постановке вопроса не очень понятно, нужно ли, может просто каждые N времени выдавать всем, у кого есть нужный "ресурс", награду, одновременно. Плюс если надо быть онлайн, вообще огонь как всё просто становится.
     
  6. Code

    Code Старожил Пользователь

    Баллы:
    123
    Имя в Minecraft:
    _Gizmo
    логично. ну тогда вопрос, что значит ветка развития постройки. и можно ли просто каждой паре (игрок,постройка) сказать, есть у этого игрока или нет. или все же каждая постройка уникальна и от игрока к игроку может отличаться (мб постройку можно будет еще как-то грейдить/ускорять), можно ли перебирать только типы построек и выдавать награды всем обладателям, или надо отдельно обрабатывать каждый экземпляр.
    короче вопрос к ТС, какой конкретно вариант ему нужен и какие конкретно проблемы с реализацией (с учетом новой инфы, если она полезна)
     
  7. Автор темы
    reZero

    reZero Активный участник Пользователь

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

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

    reZero Активный участник Пользователь

    Баллы:
    76
    И всё же, может кто-то может подсказать?
     

Поделиться этой страницей