tox1cozZ

aka Agravaine
Модератор
7,401
469
2,293
Бывает, сталкиваешься с проблемами и никак не удается их решить. Либо вообще нет решения в интернете, либо у всех работает, а у тебя почему-то нет.
Расскажу про несколько фич(костылей, ага), которые помогли мне решить проблемы и сделать коддинг чуточку приятнее.

1. Идея не грузит ресурсы(текстуры, модели и т.д)
Да, в инете есть панацея в виде такой строчки в build.gradle:
idea.module.inheritOutputDirs = true
И оно отлично решает проблему. Но, как оказалось, не всегда и не у всех. Помнится, кто-то на форуме даже страдает на постоянной основе из-за этого.
У меня три проекта и во всех ресурсы работают. Но вот понадобилось создать еще один проект, настроил абсолютно идентично, и появилась беда... Вообще ни в какую не пашет. Собирать мод и тестировать на стороннем лаунчере - слишком долго и геморно.
Правильное решение (спасибо @Ivasik):
После обновления от 19 года, идея стала использовать сборку граблей, а именно "раскидывание" ресурсов и классов по разным папкам. Ранее данная "фича" не была введена и всё забрасывалось идеей в одну папку. Чтобы исправить это, надо лишь изменить сборку и запуск с Gradle на IDEA:
1580573042182.png
Ну и всё, далее ресурсы мода будут грузиться как и раньше.

2. Проблемы с HotSwap
Когда запускаешь только клиент - все замечательно, никаких проблем нет. Но как только запускаешь еще и сервер - всё, хотсвап сразу ломается, идея говорит мол "ты удалил/добавил методы, сорян, я не умею так". Как такое может быть, если я просто изменил значение локальной переменной в методе?
Всё дело в фордже и его трансформере, который вырезает всё что помечено SideOnly. Методы/переменные вырезаются и идея думает что это мы ручками что-то убрали в классах.
Да, можно юзать JRebel или DCEVM. Насчёт первого не знаю, но вот второй дико лагучий. Если с одним клиентом еще терпимо, то когда открываешь два во время хотсвапа дико начинает тормозить секунд 15, проц забивается на 100%, а у меня на минуточку не самый хреновый i5.
Решение простое:
Открываем класс SideTransformer и копируем себе в проект в такой же пакет который и был. На 1.7.10 так, на 1.12 вроде немного другой.
1576239743111.png
Открываем его и заменяем код на заглушку.
1576239771764.png
Вот и всё. Идея сама подгружает эти классы и заменяет ими стандартные, поэтому все будет работать и SideOnly ничего вырезать не будет. Только не нужно включать этот класс в собранный мод, хорошо?
Как и ожидалось, хотсвап отлично пашет.

3. Подмена стандартных классов
В предыдущем пункте как раз это и делаем. То есть ты можешь полностью скопировать класс из майна/форджа/другого мода к себе в какой же пакет и идея будет подтаскивать именно его.
Зачем это нужно?
Например, чтобы сделать фикс в стороннем моде, а декомпилить(а в последствии править кучу ошибок во всём моде) или тащить весь мод ради изменения одного класса... Ну такое. А тут взял нужный класс и все, а мод подключил как либу.
Либо же пришла идея, ради которой нужно изменить ванильный класс. Городить сразу же хуки или трансформеры ради сомнительной фичи - слишком долго и муторно. А так взял класс, отредактировал как нужно и потестил. Получилось - сделал это хуками, не получилось - удалил класс и всё.
Кстати, можно с помощью BON'a поменять маппинги скомпилированного класса и запихнуть в minecraft.jar, удалив META-INF и не использовать никакие трансформеры (спасибо @Javanoob).

4. Изменение ассетов без перезагрузки игры
Можно ассеты(текстурки, например) перезагружать\докидывать без перезапуска игры.
Собсна, сначала меняешь\добавляешь ассетики в папку с ресурсами, затем в верхнем списке Run тыкаешь Reload changed classes и в игре жмёшь F3+T (спасибо @Plasticable).

5. Проблемы с Gradle в новых версиях IDEA
По-умолчанию в 1.7.10 версии стоит версия Gradle 2.0, но новая IDEA не работает с такой древней версией граблей.
Идём в папку проект/gradle/wrapper и открываем gradle-wrapper.properties. Меняем строку на distributionUrl=https\://services.gradle.org/distributions/gradle-4.4.1-all.zip, тем самым обновляем версию до 4.4.1 и всё будет работать.

P.S Если ты знаешь похожие фичи - пиши, будем дополнять статью.
 
Последнее редактирование:
514
8
286
Третий пункт заинтриговал, не знал о таком раньше. Идея мне ясна, но можно какой-нибудь практический пример на коленке, пожалуйста? )
 
144
7
31
Просто создаёшь пакет и класс такой же, как в исходниках майна и всё. Кстати, можно с помощью BON'a поменять маппинги скомпилированного класса и запихнуть в minecraft.jar и не использовать никакие трансформеры, но вроде это нарушает eula.
 

tox1cozZ

aka Agravaine
Модератор
7,401
469
2,293
можно какой-нибудь практический пример
Во втором пункте как раз практический пример. Да, это все что нужно сделать ;)

можно с помощью BON'a поменять маппинги скомпилированного заменённого класса и запихнуть в minecraft.jar
Ох, бон умеет менять названия класса и файла? Круть, а то градл не меняет)
 
5,937
211
1,146
Если ты знаешь похожие фичи - пиши, будем дополнять статью
Идея не грузит ресурсы
Помимо ресурспака есть еще один действенный метод: самому закинуть ресурсы в ./classes/production/<module>. Ресурсы обновляются редко(у меня), поэтому это довольно удобно. Еще можно сделать символическую ссылку вместо копирования

весь мод ради изменения одного класса
Стоит отметить, что если не все классы в одном jar были скомпилены одной версией компилятора, то могут возникать NoClassDefFoundError(а может не из-за версии компиля, я не исследовал этот вопрос глубоко), так что частичная перекомпиляция это скорее антипаттерн
 
Последнее редактирование:

tox1cozZ

aka Agravaine
Модератор
7,401
469
2,293
./classes/production/<module>
Хз, они и так там лежат, но все равно не видит.

Стоит отметить, что если не все классы в одном jar были скомпилены одной версией компилятора, то могут возникать NoClassDefFoundError
Сколько уже занимаюсь подобным и ниразу таких проблем не наблюдал..
 
5,937
211
1,146
Не наблюдал потому что, вероятно, делаешь правки в один только майн и пару модов, вероятность нарваться низкая и тебе повезло. А вот мне приходилось вносить правки во множество модов в сборках всяких хайтеков и магиков, где jar-ок разных авторов больше, следовательно, вероятность больше
 

tox1cozZ

aka Agravaine
Модератор
7,401
469
2,293
Опять же, я обычно "щупаю" таким образом код, а фикшу уже трансформерами. По ситуации, в общем.
 
5,937
211
1,146
Упс, забыл что это профичи idea. В среде как раз удобнее черновик делать именно так
 
514
8
286
У меня idea время от времени индексирует заново все файлы. Зачем и почему она это делает, знает кто? Немного бесит, т.к. она стоит на hdd и индексирование всех файлов, особенно если очень много легковесных, иногда сопровождается микрофризами :с
 

Icosider

iMixin
Администратор
3,348
85
532
Не наблюдал потому что, вероятно, делаешь правки в один только майн и пару модов, вероятность нарваться низкая и тебе повезло. А вот мне приходилось вносить правки во множество модов в сборках всяких хайтеков и магиков, где jar-ок разных авторов больше, следовательно, вероятность больше
105 модулей с модами в одном проекте, которые также имею подмодули client/server, всё собирается без проблем.

@Agravaine :j, с текстурпаками идея конечно хорошая, сам пользовался до этой статьи, но это не всегда удобно. Кстати, интеллидж создаёт доп модули api, main, test, не знаешь как такое решить? Это началось после обновления 2019.1, ранее не наблюдал:unsure:
 

tox1cozZ

aka Agravaine
Модератор
7,401
469
2,293
Я как только пробовал - только этот варик сработал.
Создаёт, да. Я папки удалил руками и все, оно мне не мешает)
 

Icosider

iMixin
Администратор
3,348
85
532
Прикол в том, что удалением папки так просто не отделаться, а всяких .iml, .imr файлов создаётся тонна
 
5,937
211
1,146
105 модулей с модами в одном проекте, которые также имею подмодули client/server, всё собирается без проблем
Допустим. А что тогда было источником моих проблем с NoClassDefFound?
 

Icosider

iMixin
Администратор
3,348
85
532
Не знаю. У меня так:
Gradle (Groovy):
duplicatesStrategy = DuplicatesStrategy.EXCLUDE

if (project.mergeWithDep)
   from(zipTree("$libModDir/${project.name}-${project.version}.jar"))
А сами зависимости подхватываются автоматически, как и преобразуются из *.jar в dev.jar и dev-sources.jar. Для подобных манипуляций использовал: свою модификацию BON + fernflower + cfr и соответственно всё в плагин для gradle запаковал, проблем не наблюдаю
 
280
14
145
Если ты знаешь похожие фичи - пиши, будем дополнять статью.
Ну я знаю одну полезную. Можно ассеты(текстурки, например) перезагружать\докидывать без перезапуска игры.
Собсна, сначала меняешь\добавляешь ассетики в папку с ресурсами, затем в верхнем списке Run тыкаешь Reload changed classes и в игре жмёшь F3+T

во время хотсвапа дико начинает тормозить секунд 15, проц забивается на 100%
Я думал, это из-за моего фигового компа, а это у всех так...
 
514
8
286
Но, как оказалось, не всегда и не у всех.
Да оно живое, походу. То работает, то нет, хз вообще от чего зависит. Условия и воркспейс идентичные, а результат разный.
Короче всё же не долго я смог просидеть на эклипсе, чувствую себя инвалидом на нём, перешёл обратно на идею, вписал в build.gradle такую строчку: sourceSets { main { output.resourcesDir = output.classesDir }} и всё заработало, все текстуры и ассеты грузятся без проблем, не придётся танцевать с бубном и ресурспаком )
Так что мне кажется, что панацея это sourceSets { main { output.resourcesDir = output.classesDir }}, а не idea.module.inheritOutputDirs = true.

Но есть один неприятный прекол - я не могу в ide создавать директории для ассетов, тупая идея всё равно склеивает папки, а потом майн опять не видит ассеты, даже если я пропишу и первую, и вторую строчки. Так что приходится ручками через проводник создавать, печально. Idea 2019.3.1 если что :с
 
Сверху