Система временных эффектов (Замена Potion)

Система временных эффектов (Замена Potion)

Нет прав для скачивания
243
28
202
AustereTony добавил(а) новый ресурс:

Система временных эффектов (Замена Potion) - Те, кого не устраивают стандартные эффекты зелий - добро пожаловать!

Предисловие

Здравствуйте. В данном туториале я опишу процесс создания собственной системы временных эффектов (баффов) для игрока. Работают они так же, как и ванильные эффекты зелий, однако имеют ряд улучшений и оптимизаций. Туториал написан под версию 1.7.10, и для реализации требуются настроенные EEP (заменить на Capability в более поздних версиях) и пакетная система, ну и знание классов стандартного пакета java util.

Данный туториал не содержит...

Узнать больше об этом ресурсе...
 
3,005
192
592
Реализации по замене ванильной на такую не будет?
 
243
28
202
AustereTony обновил(а) ресурс Система временных эффектов (Замена Potion) новой записью:

Обновление #1

Обновлён BuffManager. Заменил обычный массив на ArrayList, добавил метод getBuff() для упрощения доступа к элементам. Теперь создание эффектов стало ещё проще, спасибо Agravaine за совет.

Узнать больше об этом обновлении...
 

CMTV

Основатель
Администратор
1,304
4
601
Вау. Это действительно круто (подача отличная)!

@AustereTony, можете добавить иконку к ресурсу? Тогда будет совсем красота!
 
5,018
47
783
В эвенте не советую) В наследнике Potion можно переопределить все необходимые методы для применения чего угодно. А если по существу, то создание собственной системы позволяет слепить всё что угодно в зависимости от потребностей и не добавлять ничего лишнего.
Почему ж эвенте не советуешь? Там тоже можно установить разные промежутки времени благодаря ticksExisted
 
243
28
202
@Maxik001, несомненно.

Предполагаю, что проверяешь как-то так:
Java:
        if (player.isPotionActive(potion)) {   //Если potion активно.    

            if (player.ticksExisted % 20 == 0) {
                
                player.heal(3.0F);//хил 3 пункта раз в секунду.
            }
        }
Зачем лишний раз каждый тик проверять(делать запрос в HashMap), если главный цикл делает это вызывая isReady() и performEffect() в Potion (мы же создаём наследника и можем переопределить их). Вот как применять эффект не создавая дополнительной нагрузки:
Java:
    public void performEffect(EntityLivingBase entityliving, int tier) {
        
        //Вызывается только если isReady() вернёт true;
        
        if (entityliving.getHealth() < entityliving.getMaxHealth()) {
            
            entityliving.heal(3.0F);
        }
    }
    
    public boolean isReady(int duration, int tier) {
        
        return duration % 20 == 0;//вернёт true каждую секунду.
    }
Если же нужно что то добавить/удалить один раз, то нужно переопределять:
Java:
    public void applyAttributesModifiersToEntity(EntityLivingBase entitiLiving, BaseAttributeMap map, int tier) {
        
        //Вызывается однократно при применении эффекта.
    }
    
    public void removeAttributesModifiersFromEntity(EntityLivingBase entityLiving, BaseAttributeMap map, int tier) {
        
        //Вызывается однократно при удалении эффекта.
    }
Они так же вызываются однократно при добавлении/удалении эффекта. В самом деле, неужели лучше поступать так:
Java:
        if (player.getActivePotionEffect(potion).getDuration() == 1) {   
            
            //Удаление модификаторов.
        }
Поначалу я и сам использовал тик-эвенты, но через десяток другой проверок сервер стал подлагивать.
 
243
28
202
AustereTony обновил(а) ресурс Система временных эффектов (Замена Potion) новой записью:

Обновление #2

Туториал переписан для использования со всеми EntityLivingBase.

Вся работа с эффектами перенесена в BuffManager, класс с EEP можно создать и забыть.

Исправлены некоторые недочёты, добавлены новые методы.

Узнать больше об этом обновлении...
 
  • Like
Реакции: CMTV

CMTV

Основатель
Администратор
1,304
4
601
Похоже, намечается супер-гайд. Что думаете?
 
2,505
81
397
Гайд, конечно, хороший, но слишком жирный для гайда. :unsure: Это можно было бы оформить, как либу (или просто как пачку классов для прямого копипаста), сделать немного по-красивее и больше функционала. У меня есть к чему придраться. Если интересно, могу высказать.
 
243
28
202
@Dahaka, выкладывай, буду принимать меры. Насчёт либы подумаю, но на мой взгляд ради трёх классов нет смысла.
 
2,505
81
397
Окей.
1. Manager в названии класса BuffManager ни к месту. Это не Manager. Назови лучше просто Buff. А ActiveBuff переименуй в BuffState.
2. Метод BuffManager#getBuff переименуй в BuffManager#of. BuffManager.of(5) выглядит красивее, чем BuffManager.getBuff(5).
3. В методах onActive, isReady ты пробрасываешь через параметры tier, duration. Пробрасывай лучше весь ActiveBuff.
4. Почему BuffManager#applyBuffEffect и BuffManager#removeBuffEffect статические - мне непонятно.
5. BuffManager#getDurationForDisplay тоже почему-то статический. По идее, если нужен бесконечный баф, то можно было бы переопределить этот метод, чтобы выводить --:--.
6. То что майн и ты завязали текущий стейт на простом ActiveBuff - не очень удобно. А что если понадобится еще один динамический параметр? Решение - создавать ActiveBuff через BuffManager, т.е. немного изменить класс
Java:
public class BuffManager<T extends ActiveBuff> {
    ...

    public T newState(int tier, int duration) {
        return new ActiveBuff(id, tier, duration);
    }

    ...
}
И естественно везде ActiveBuff заменить на T. Таким образом можно будет создавать кастомные стейты. Но тогда придется изменить readBuffFromNBT. Нужно будет сначала читать id, создавать ActiveBuff при помощи BuffManager, а затем вызывать ActiveBuff#readFromNBT.
7. private Map<Integer, ActiveBuff> activeBuffs сделай final.
8. В BuffsLivingBase #haveActiveBuffs нет смысла в проверке на null.
9. BuffsLivingBase#activeBuffsIdSet должен возвращать Set<Integer>.
10. BuffsLivingBase#activeBuffsCollection должен возвращать Set<ActiveBuff>.
11. Замени везде итераторы на foreach циклы.
Java:
for (ActiveBuff buff : activeBuffsCollection()) {
    ...
}
12. new BuffsOverlay(). Создай объект один раз, а потов вызывай какой-нибудь draw.
13. То что ты никогда не синхронишь кулдаун с сервера на клиент немного странно. Что если на сервере лаги? Тогда эффект на клиенте пропадет значительно раньше. Лаги на клиенте - аналогично. По факту эффект пропадет, но игрок будет думать, что баф наложен.
 
243
28
202
А тут есть над чем поработать) Идея в пункте 6 - вот это интересно. Заменять итераторы на foreach такое себе. Конечно удобочитаемость кода повысится, но в производительности выигрыша не будет, да и не все итераторы у меня просто перебирают элементы, а foreach не даст модифицировать мапу в процессе. Но заменить все остальные стоит, это да. На счёт синхронизации - эффекты удаляет только сервер и шлёт игроку пакет об этом, так что проблем не должно возникать (если не лагает сервер). Всё остальное подправлю.

Ну и собираюсь добавить информацию по адаптации на 1.12.2.
 
  • Like
Реакции: CMTV
243
28
202
@Dahaka, поправил.

1. BuffManager на Buff, ActiveBuff оставил как есть.
2. Сделано.
3. Сделано.
4. Совсем забыл, что они не переопределяются. Исправил.
5. Поправил. Добавил новый флаг для создания постоянного эффекта за одно.
6. Над дженерик-стейтами буду работать.
7. Исправлено.
8. Исправлено.
9. Исправлено.
10. Может всё таки Collection?
11. Заменил, где можно.
12. Сделано.
13. Было норм, но не было синхронизации при добавлении с сервера, добавил.
 
  • Like
Реакции: CMTV
243
28
202
AustereTony обновил(а) ресурс Система временных эффектов (Замена Potion) новой записью:

Обновление #3

Туториал дополнен информацией по адаптации на 1.12.2, а так же добавлена ссылка на исходники для обеих версий.

Множественные правки кода, фикс недоработок.

Узнать больше об этом обновлении...
 

CMTV

Основатель
Администратор
1,304
4
601
Сегодня вечером выложу гайд на сайт + досрочно достижение супер-гайд 2018.
 

CMTV

Основатель
Администратор
1,304
4
601
@AustereTony приложи, пожалуйста, рабочие исходники или ссылку на GitHub.
 
Сверху