Иконка ресурса

Configurable Weight System 0.5.0

Нет прав для скачивания
1,159
38
544
RareScrap добавил(а) новый ресурс:

Configurable Weight System - Задавайте вес предметов через конфиг

Простая реализация WeightAPI, позволяющая вам задавать вес каждого итема (в том числе и из других модов) через конфиг.

Дополнительные фичи:
  • При достижении максимального переносимого веса вы не сможете подбирать итемы
  • При перегрузке игрок...

Узнать больше об этом ресурсе...
 

Eifel

Модератор
1,623
78
608
Хотелось бы иметь возможность скачать еще сурсы
 
7,099
324
1,509
Зачем регать на каждого игрока хандлер, если и так из эвента можно достать игрока? RareScrap/ConfigurableWeight
Также было бы неплохо хранить вес инвентаря не в мапе, а прямо в игроке, в капабилити
 
1,159
38
544
Хотелось бы иметь возможность скачать еще сурсы
Кнопка "дополнительная информация" ведет на гитхаб

Зачем регать на каждого игрока хандлер, если и так из эвента можно достать игрока?
Офигеть... И правда. Что-то я не заметил такого. Щас пофиксим

Также было бы неплохо хранить вес инвентаря не в мапе, а прямо в игроке, в капабилити
Может ты имеешь ввиду вес преметов? Потому как вес инвентаря не хранится, а вычисляется. Или ты про максимальный переносимый вес?
 
1,159
38
544
7,099
324
1,509
1,159
38
544
PlayerWeightTracker можно хранить в капабилити
Капы - это же вроде IEEP для версии 1.8+? Цель этих штук - уметь сохранять инфу при выходе игрока из сети. Зачем там трекер? Ну или я чего не понимаю...
 
2,505
81
397
Сначала подвезу критику сюда. Аргументы типа "можешь написать свой WightProvider" попрошу не использовать.

Utils#calculateAllowingStackSize
Создание копии стака? Зачем? Сохрани изначальный размер стака, а потом установи обратно.

Utils#drawCenteredStringWithoutShadow
Там до сих пор лежит выключение освещения.

EndlessPotionEffect
Насколько я помню, нельзя переопределять PotionEffect. При перезагрузке майн все равно создаст обычный PotionEffect, а не твой.
Провангую, что через это ты накладываешь перевес. Кому как, конечно, но мне кажется лучше просто накладывать модификатор на скорость перемещения, а не использовать поушн.

PlayerWeightTracker
Про этот трэкер тебе уже сказали. Его лучше держать в IEEP/Cap. И нет, эти механизмы в первую очередь предназначены для хранения данных, в данном случае, в игроке. Исходя из этого мапа тебе не потребуется.
А вообще, даже если использовать мапу, то для игроков лучше использовать WeakHashMap. А то мало ли что может произойти.

Что за костыль prevWeightClient? Даже в одиночной игре игре существуют два объекта одного и того же игрока (для клиента и сервера). Поэтому я вообще не понимаю зачем вообще вставлен этот костыль.

Ивент хэндлеры в отдельный класс! И регать один раз, а не для каждого игрока!

Почему getWeight считает вес???? Пересчитать вес это дорого!! А ты это делаешь постоянно. Даже в рендере.
Делай это хотя бы раз в секунду и при подборе айтемов. Но в идеале, конечно, при изменении инвентаря.

Куча повторяющегося кода в ивент хэндлерах. Не красиво.

Не стоит все крашить, если в конфиге описан несуществующий айтем.

weightStorage.containsKey(itemStack.getItem()) ? weightStorage.get(itemStack.getItem()) : defaultWeight;
Типичный случай неумения работать с мапой. get вернет null, если ключ не найдет, поэтому не нужно доставать значение дважды. И вообще должен быть метод getOrDefault.

isOverloaded опять считает вес инвентаря. Зачем? Нужно доставать значение веса из трекера. getFreeSpace аналогично. Ивенты в этих методах сомнительны. Не представляю жизнепригодного юзкейса. Только для костылей. Опять же все эти вещи может просчитывать трэкер, а не провайдер при каждом обращении.

Почему пакет регистрирует систему веса? Пахнет костылем. Он должен пересылать данные системы и распаковывать их в существующую, а не создавать новую. И что опять за разделение на serverWeightProvider и clientWeightProvider? Зачем оно?

Почему onMessage @SideOnly(Side.CLIENT)? У тебя класс не загрузится на выделенном сервере, потому что метод удалится.

Провайдеру не нужно поле config. Оно нужно только для инициализации. Зачем хранить постоянно?

Два раза создаешь мапу на клиенте в провайдере.

Если подытожить, то мне не нравится. Если все это исправить, то будет лучше. Но мне не нравится в первую очередь само API.
 
1,159
38
544
Создание копии стака? Зачем? Сохрани изначальный размер стака, а потом установи обратно.
Это можно, хорошая идея

Там до сих пор лежит выключение освещения.
Ты хочешь чтобы я его назад включал? Ну так строка перестает рендерится как мне надо. Если не включать - все норм.

При перезагрузке майн все равно создаст обычный PotionEffect, а не твой.
А вот я и удаляю тот самый обычный PotionEffect и заменяю его на свой в EntityJoinWorldEvent.

Кому как, конечно, но мне кажется лучше просто накладывать модификатор на скорость перемещения, а не использовать поушн.
Меня привлекает, то поушн уже умеет рендериться в привычном для игрока виде. А насчет модификаторов - просвяти, будь добр. Как они работают?

Про этот трэкер тебе уже сказали. Его лучше держать в IEEP/Cap
Ну хз... Хук в PlayerInventory#setInventorySlotContent() и дело с концом. И никакой капы не надо.

Исходя из этого мапа тебе не потребуется.
А вообще, даже если использовать мапу, то для игроков лучше использовать WeakHashMap. А то мало ли что может произойти.
По сути ты предлагаешь веса итемов хранить в капе игрока. Но нафига, если на всех игроков один вес итемов?

Что за костыль prevWeightClient? Даже в одиночной игре игре существуют два объекта одного и того же игрока (для клиента и сервера). Поэтому я вообще не понимаю зачем вообще вставлен этот костыль.
Потому что для трекера это не работает. Если запущен интегрированный сервер, то на клиентский и серверный поток один объект PlayerWeightTracker. Да, это костыль. Хук добавлю и уберу этот класс вообще.

Ивент хэндлеры в отдельный класс! И регать один раз, а не для каждого игрока!
Тут кода-то на 5 классов. Какой резон выносить хандеры в отдельный класс, если мод маленький? Я согласен, все должно быть на своем месте, но в меру. А для каждого игрока я их регал, т.к. привязывал поля prevWeightClient и prevWeight к конкретному игроку. Но опять же я выпилю это класс к чертовой бабушке.

Куча повторяющегося кода в ивент хэндлерах. Не красиво.
Только в трекере. Угадай что я с ним сделаю?

Типичный случай неумения работать с мапой. get вернет null, если ключ не найдет, поэтому не нужно доставать значение дважды.
Я выбрал такой способ потому что мне он кажется более удобочитаемым. Можно и проверкой на null, почему бы и нет.

И вообще должен быть метод getOrDefault
А вот это прикольно. Сделаем.

Не стоит все крашить, если в конфиге описан несуществующий айтем.
Можно и лог выводить, но мне больше нравится идея дать по шапке юзеру, чтобы заполнял конфиг нормально. Не маленький уже.

isOverloaded опять считает вес инвентаря. Зачем? Нужно доставать значение веса из трекера. getFreeSpace аналогично.
Мне ОЧЕНЬ не нравится идея обращаться к трекеру. Я думаю, что WeightProvider должен быть как можно более независим от других классов.

Ивенты в этих методах сомнительны. Не представляю жизнепригодного юзкейса. Только для костылей.
А вот мне видится один юзкейс: есть какой-то челик, у которого в сборке есть система веса и различные инвентари, поддерживающий этот апи. И все эти вещи с закрытым кодом. А ему нужно изменить малеха правила расчета перегруза (например). Так он запилит простенький модец, подпишится на CalculateOverloadEvent и сделает свое черное дело.

Я считаю, что мы не можем предусмотреть все юзкейсы. Но сделать хоть какую-то расширяемость мы можем. Вот затем тут и евенты.

Почему onMessage @SideOnly(Side.CLIENT)? У тебя класс не загрузится на выделенном сервере, потому что метод удалится.
А ты запусти. У меня все загружается как в IDE, так и в обфусцированном окружении. Да и этот метод вызовется только на клиенте, т.к. целевая сторона пакета SyncMessage - клиент. Такое у него предназначение - высылать таблицу весов, чтобы и на клиенте был аналогичный WeightProvider. Синхронизация эдакая.

Провайдеру не нужно поле config. Оно нужно только для инициализации. Зачем хранить постоянно?
Резонно

Почему пакет регистрирует систему веса? Пахнет костылем. Он должен пересылать данные системы и распаковывать их в существующую, а не создавать новую.
В данном случае WeightProvider инициализируется из конфига, который находится на сервере. А потом пересылает веса итемов на клиент (где кстати вместо системы веса - шиш null). Ну на кой черт сперва создавать WeightProvider на клиенте, а потом ждать пока придет пакет с инфой? Почему бы не создавать провайдер, в момент когда пакет придет? Мой подход кажется мне более логичным.

И что опять за разделение на serverWeightProvider и clientWeightProvider? Зачем оно?
Потому что так меньше кода, чем создавать в SyncMessage поля с мапами весов. И более дешево.

Но мне не нравится в первую очередь само API.
Поделись что именно тебе не нравится. Я попытался свести конфликты к минимуму и сделать его как можно более расширяемым.

И спасибо за кодревью. Есть над чем поразмыслить.
 
Последнее редактирование:
7,099
324
1,509
Хук в PlayerInventory#setInventorySlotContent() и дело с концом
Хуки нужно использовать только если нет другого варианта, т.к. о твоих хуках могут не знать другие разработчики
 
1,159
38
544
Полное цитирование предыдущего сообщения запрещено
Хуки нужно использовать только если нет другого варианта, т.к. о твоих хуках могут не знать другие разработчики
Тоже верно. Но у нас есть выбор: с одной стороны большая куча кода, а с другой - хук в одну строку. В добавок это всего лишь трекер. Его цель - выбрасывать WeightChangedEvent при изменении инвентаря. А сейчас весь этот говнокод нужен трекеру лишь для того чтобы он сам не развалился. Я считаю, что хук тут оправдан.
 
2,505
81
397
Ты хочешь чтобы я его назад включал? Ну так строка перестает рендерится как мне надо. Если не включать - все норм.
Я хочу, чтобы ты сделал, как тебе посоветовали я и Агрованя.

По сути ты предлагаешь веса итемов хранить в капе игрока. Но нафига, если на всех игроков один вес итемов?
Чтобы трэкер был трэкером, а не тем, что у тебя сейчас. И я предлагаю не это. Я предлагаю в трэкере держать значение текущего веса всего игрока. И считать его иногда, а не везде. А провайдер уже доставал бы значения из капы и работал бы в действительности как get, а не как calculate.

Какой резон выносить хандеры в отдельный класс, если мод маленький?
И регать один раз, а не для каждого игрока!

Мне ОЧЕНЬ не нравится идея обращаться к трекеру. Я думаю, что WeightProvider должен быть как можно более независим от других классов.
Обоснуй. Трэкер следит и управляет весом. Вполне нормально, если WeightProvider будет просто делегировать методы трэкера. Ну а вообще, WeightProvider можно вообще выкинуть, но это уже вопрос к API. И про это я напишу там.

Можно и лог выводить, но мне больше нравится идея дать по шапке юзеру, чтобы заполнял конфиг нормально. Не маленький уже.
А я вот подумал, что один конфиг мог бы использоваться в мультисборках. И было бы неприятно редактировать кучу разных конфигов.

А ты запусти. У меня все загружается как в IDE, так и в обфусцированном окружении. Да и этот метод вызовется только на клиенте, т.к. целевай сторона этого пакета - клиент. Такое у него предназначение - высылать таблицу весов, чтобы и на клиенте был аналогичный WeightProvider. Синхронизация эдакая.
А, точно. Упадет только при создании объекта. А при загрузки класса, наверное, нет.

В данном случае WeightProvider инициализируется из конфига, который находится на сервере. А потом пересылает веса итемов на клиент (где кстати вместо системы веса - шиш null). Ну на кой черт сперва создавать WeightProvider на клиенте, а потом ждать пока придет пакет с инфой? Почему бы не создавать провайдер, в момент когда пакет придет? Мой подход кажется мне более логичным.
Т.е. по сути выбирает систему веса сервер.. Это мне не очень нравится, конечно, но почему бы и нет.

Потому что так меньше кода, чем создавать в SyncMessage поля с мапами весов. И более дешево.
Я там про то, что можно обойтись одним полем, а не двумя костылями

Поделись что именно тебе не нравится. Я попытался свести конфликты к минимуму и сделать его как можно более расширяемым.
Я также распишу все в той теме, как будет время.
 
7,099
324
1,509
@RareScrap хм, возможно ты прав. В forge ведь нет SlotChangeEvent или InventoryChangeEvent и без хука никак, вроде. Но хранить трэкер лучше все же в капе, а не в своей мапе

Я там про то, что можно обойтись одним полем, а не двумя костылями
boolean-поле и чекать if? Костыли
 
7,099
324
1,509
Что за поле?
 
7,099
324
1,509
И как различать клиентскую логику от серверной? При помощи if?
 
2,505
81
397
А ее не нужно различать. Хэндлер вызывается только на клиенте.
 
1,159
38
544
Я хочу, чтобы ты сделал, как тебе посоветовали я и Агрованя.
Да без проблем. Но поторюсь, если включать свет после отрисовки строки - строка не рендерится так как нужно. Затемнится она маленько тогда.

Я предлагаю в трэкере держать значение текущего веса всего игрока. И считать его иногда, а не везде. А провайдер уже доставал бы значения из капы и работал бы в действительности как get, а не как calculate.
Вот теперь я тебя понимаю. Согласен, так лучше чем пересчитывать все заново. Я оставил пересчет, т.к. не хотел
заниматься преждевременной оптимизации. Т.е. пока не допилю апи.

Обоснуй. Трэкер следит и управляет весом.
Я задумывал трекер немного иначе. Главная его задача - слать WeightChangedEvent когда надо. Я не хотел, чтобы он следил и управлял весом. Только выбрасывал евент и все. Текущая реализация трекера неудачная т.к. на момент написания не думал, что треер настолько разрастется.

А я вот подумал, что один конфиг мог бы использоваться в мультисборках. И было бы неприятно редактировать кучу разных конфигов.
Я не знаю что такое "мультисборка", извини. Расскажи что за зверь.

А, точно. Упадет только при создании объекта. А при загрузки класса, наверное, нет.
Ну наверное только если этот объект создавать на сервере. Но зачем хандлер клиентского пакета на севере?

Т.е. по сути выбирает систему веса сервер..
Именно для этого провайдера. Мне показалось это логичным.

Это мне не очень нравится, конечно, но почему бы и нет.
Почему не нравится? Что тебя смущает?

Я там про то, что можно обойтись одним полем, а не двумя костылями
Дай пример кодом, будь добр. Пока я тебя не понимаю.

Я также распишу все в той теме, как будет время.
Спасибо
 
Сверху