Gl11 minecraft что это

Обновлено: 13.05.2024

[h]Предисловие[/h]
Здесь я постарался как можно более емко и кратко рассказать о тех возможностях openGL, которые могут пригодиться при создании модов для Minecraft. Несмотря на это, объем текста получился весьма внушительным.
Для того, чтобы по-настоящему владеть openGL, этого туториала вам все равно не хватит. Нужно будет прочитать раз в 10 больше литературы. Кроме того, нужны базовые, но уверенные познания в математике и достаточное количество терпения, чтобы понять суть матриц трансформации.
Туториал носит по большей части теоретический характер, реальных примеров в нем очень мало. Он призван немного сбалансировать огромное количество туториалов, в которых используется openGL-код без толкового объяснения происходящего.
Описываются по большей части возможности openGL 1, на котором построен Minecraft. Да, я в курсе, что он давным-давно устарел, но в процессе модификации Minecraft'а избежать использования openGL 1 всё равно не выйдет. Про новые возможности будет сказано немного и в самом конце.


[h]Небольшое FAQ по определениям[/h]
q: Что такое openGL?
a: OpenGL - это API, предоставляющий программистам доступ к возможностям видеокарты. В случае c Minecraft'ом, этот API реализует библиотека LWJGL.

q: Что делают функции openGL?
a: Функции openGL делятся на два типа: одни меняют его глобальное состояние (openGL state), в то время как другие передают в него данные (позиции вершин, UV-координаты и нормали) для отрисовки.

q: Что такое глобальное состояние openGL?
a: Состояние openGL - это набор глобальных параметров, в зависимости от которого один и тот же набор вершин отрисовывается по-разному. Описание отдельных элементов состояния openGL будет ниже.

q: В чем суть того, что делает openGL?
a: OpenGL строит изображение на экране (или в памяти) на основе поступающих в него вершин (координат) и своего состояния. В зависимости от состояния он может рисовать точки, линии и многоугольники.

q: Что такое UV-координаты?
a: UV-координаты - пары вещественных чисел от 0 до 1, соответствующие некоторым координатам на текстуре. U - горизонтальная координата, V - вертикальная. Если при рендеринге используется текстура, то, передавая вершину на отрисовку, необходимо указать еще и ее UV-координаты.

q: Что такое нормали?
a: Нормали - вектора, перпендикулярные поверхности. Они нужны для рассчета освещения. Нормалью к вершине может быть как перпендикуляр к полигону, к которому она принадлежит, так и средний вектор между перпендикулярами к нескольким полигонам, если вершина принадлежит к нескольким полигонам одновременно. Нормали должны быть нормализованы (то есть иметь единичную длину).

Подсказка: можно прописать в импортах import static org.lwjgl.opengl.GL11.* (и другие нужные версии) и не заморачиваться с постоянным повторением GL11.


[h]Немного практики[/h]
Наша пробная задача - отрендерить tile entity в виде квадрата. Будем считать, что вы уже умеете создавать блок с моделью . Код ниже должен быть в методе renderTileEntityAt(x, y, z, f, partialTickTime) нашего TileEntitySpecialRenderer.

Используя только openGL:

Этой возможностью стоит пользоваться, потому что вызывать каждый раз функции openGL - очень и очень медленно, а здесь применены некоторые оптимизации. Если наложена текстура, то вместо addVertex() нужно использовать addVertexWithUV(), а если включено освещение, то перед добавлением вершин, принадлежащих новому полигону, нужно применять setNormal().

Если с добавлением вершин все должно быть более-менее понятно, то остальное - понятно не всем. В openGL есть такое понятие, как "матрицы трансформации". Я вряд ли опишу лучше, чем здесь, но всё же попробую вкратце пересказать, а также немного дополнить.


[h]Матрицы трансформации[/h]
Матрица трансформации в openGL - это двумерный массив чисел 4х4. По сути матрицы в комьютерной графике используется для того, чтобы перейти от одной системы координат (иногда используется слово "пространство" или "space") к другой. Я не буду здесь подробно описывать арифметику матриц, потому что это займет кучу места и не очень нужно в целом, но для глубокого понимания лучше все-таки прочитать про неё отдельно.
Чаще всего применяется две операции. Их суть вы поймете чуть позже.
1) Умножение вектора на матрицу. Как результат этой операции мы получаем вектор в другой системе координат.
2) Умножение матриц. Как результат мы получаем новую матрицу, которая трансформирует вектора так же, как если бы мы умножили сначала на одну матрицу, а потом на другую.
При умножении матриц (как и при умножении вектора на две матрицы последовательно) важен порядок действий. Это легко понять, если представить две последовательности действий:
1) Пройти десять метров вперед, повернуть на 90 градусов вправо, пройти пять метров вперед.
2) Повернуть на 90 градусов вправо, пройти десять метров вперед, пройти пять метров вперед.
Очевидно, что в результате мы окажемся на разных координатах. Так же и с матрицами.

Основных систем координат (и, соответственно, матриц) три - MODEL (для перехода из пространства текущего объекта в мировое), VIEW или CAMERA (для перехода из мирового пространства в пространство камеры) и PROJECTION (для проекции сцены на 2d изображение).
По поводу MODEL и VIEW матриц стоит сделать два замечания. Во-первых, в openGL эти матрицы объединены в одну, которая называется MODELVIEW. Во-вторых, из-за огромных размеров мира в Minecraft'e пришлось отказаться от использования мирового пространства вообще.
При построении матрицы MODELVIEW для отрисовки блока с моделью выполняется последовательность действий (упрощённо):
1) Если включен вид от третьего лица, сместить на несколько метров вперед или назад
2) Если включен вид спереди, повернуть на 180 градусов вокруг оси Y
3) Повернуть камеру в соответствии со взглядом игрока
4) Сместиться на разность координат между позицией блока и камеры. Именно эта разность передается как x, y и z в метод renderTileEntityAt().
Первые три действия делает Minecraft, четвертое нужно делать самому. При умножении координат какой-либо вершины в пространстве модели на матрицу MODELVIEW эти операции будут применены в обратном порядке и мы перейдем в пространство камеры. Непосредственно перед отрисовкой модели можно применить и другие операции с матрицей MODELVIEW, такие как масштабирование или поворот.

Я почти уверен, что из моего посредственного объяснения вы вынесли очень немногое, и настоятельно рекомендую сейчас перейти по этой ссылке и прочитать ВСЮ статью. Три раза.


[h]Функции openGL, связанные с матрицами[/h]
Систему координат мы можем сдвигать, поворачивать и масштабировать. Для этого используются функции glTranslate*(x, y, z), glRotate*(angle, x, y, z) и glScale*(x, y, z). Вместо * в названии функции используется "f" или "d" в зависимости от того, какой тип данных она принимает в качестве аргументов - float или double. В glRotate аргумент angle - это угол в градусах (положительный угол = поворот против часовой стрелки), а x, y и z - вектор, вокруг которого поворачивать. Например, glRotatef(-90, 0, 1, 0) - повернуть на 90 градусов по часовой стрелке вокруг вертикальной оси.

Часто необходимо сохранить текущую матрицу с возможностью последующего восстановления. Это возможно при помощи функций glPushMatrix() и glPopMatrix(). glPushMatrix() добавляет матрицу в стек (список) сохраненных матриц. glPopMatrix() восстанавливает последнюю матрицу из стека и удаляет ее оттуда. Например:

Функция glLoadIdentity() задает единичную матрицу (которая не делает никаких трансформаций). На практике при создании модов она вряд ли понадобится.


[h]Другие параметры openGL[/h]
Кроме матриц трансформации, есть огромное количество других составляющих состояния openGL. Я попробую рассказать о тех, что наиболее важны при создании модов.
В openGL есть несколько boolean-параметров, которые включаются и отключаются при помощи функций glEnable() и glDisable(), куда в качестве аргумента передается опкод этого параметра. С некоторыми из этих параметров связаны другие функции.

GL_DEPTH_TEST включает тест глубины. В большинстве случаев он включен и нужен. Его задача - отсекать те полигоны, которые заслонены другими, даже если "дальний" полигон рисуется после "ближнего". При отрисовке кадра кроме того изображения, что позже будет выведено на экран, есть еще один буфер, который называется буфер глубины, depth buffer или z-буфер. При отрисовке пикселя в этот буфер добавляется информация о том, как далеко он расположен от камеры. Подробнее можно прочитать здесь, и я очень советую это сделать.
Сопутствующие функции:
glDepthMask(true/false) - включает/выключает запись в этот буфер. Если тест глубины выключен, то никакого влияния этот параметр не оказывает, в буфер глубины все равно ничего не будет записываться. Единственная функция в этом списке, которая часто нужна в моддинге.
glClearDepth(value) - очищает буфер глубины и заполняет его указанным числом. 1.0 - "пустой" буфер.
glDepthFunc(func) - устанавливает функцию, по которой проверяется, нужно ли отрисовывать пиксель или он чем-то заслонен. GL_LEQUAL используется в майне по умолчанию, это "меньше или равно" (less or equal). Насколько оправдано использовать другие функции - затрудняюсь ответить.
glDepthRange(zNear, zFar) - устанавливает "ближнюю" и "дальнюю" глубину в буфере. 0.0 соответствует ближней глубине, 1.0 - дальней.

GL_BLEND включает полупрозрачность (смешивание цветов). С ней есть две проблемы. Во-первых, эта опция серьезно снижает производительность, и включать ее для всего не стоит. Во-вторых, она плохо сочетается с буфером глубины. При использовании буфера глубины абсолютно безразлично, в каком порядке отрисовывать полигоны, но для корректного смешивания их нужно сортировать от дальнего к ближнему. Обычный путь - это отрисовать сначала всю непрозрачную геометрию со включенными GL_DEPTH_TEST и glDepthMask, потом выключить glDepthMask и отрисовать полупрозрачную геометрию, немножко сортируя ее по ходу дела . В Minecraft'e используется этот подход. Реализуется это через фичу, которая называется render pass. Нулевой pass - это непрозрачная геометрия, первый - полупрозрачная. Например, у сущностей есть метод shouldRenderInPass(). Получить текущий render pass можно через MinecraftForgeClient.getRenderPass().
Сопутствующая функция:
glBlendFunc(sfactor, dfactor) - параметры, по которым считается итоговый цвет пикселя.
finalColor = sfactor * srcColor + dfactor * destColor, где srcColor - цвет рисуемого полигона (например, с текстуры), а destColor - цвет того, что уже нарисовано на месте этого пикселя. Обычные применения:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) - "нормальное" смешивание.
glBlendFunc(GL_ONE, GL_ONE) - аддиктивное смешивание, то есть сложение нового и старого цвета. Полезно для "энергетических" эффектов вроде огня и электричества.
glBlendFunc(GL_SRC_ALPHA, GL_ONE) - то же самое, но с учетом прозрачности с текстуры.

GL_TEXTURE_2D включает использование текстуры. В качестве "сопутствующей" функции можно было бы указать Minecraft.getMinecraft().renderEngine.bindTexture().

GL_LIGHTING включает простое освещение (с двумя источниками света на постоянных позициях). Оно НИКАК не связано с тем, как затеняются блоки ночью и в тени. Про освещение в Minecraft расскажу внизу.
Когда GL_LIGHTING нужно:
1) При рендеринге сущностей
2) При рендеринге tile entity
3) При рендеринге блоков в GUI
4) При рендеринге предмета в руках
Когда оно не нужно:
1) При рендеринге обычных блоков в мире. Там всё работает на костылях.
2) При рендеринге частиц
3) При рендеринге GUI
Сопутствующих фунций и параметров много, а рассказывать о них в контексте Minecraft'a толку мало. Включается дефолтное освещение через RenderHelper.enableStandardItemLighting(), выключается через RenderHelper.disableStandardItemLighting(), вспомогательные функции там и смотрите.

GL_ALPHA_TEST включает запрет на отрисовку пикселей в зависимости от значения alpha (непрозрачности). Обычное использование - запрет на отрисовку полностью прозрачных пикселей, потому что иначе при выключенном смешивании они будут рисоваться. Например, нарисовав квадрат с текстурой круга (на текстуре всё за пределами круга полностью прозрачно), вы всё равно получите квадрат. С этим же параметром связана ситуация, когда при включенном смешивании почти прозрачные пиксели вообще не видны. Тогда нужно отключить альфа-тест.
Сопутствующая функция:
glAlphaFunc(func, ref) - задает параметры альфа-теста. Первое значение - функция сравнения, второе - число, с которым сравнивать. Обычное использование - что-нибудь вроде glAlphaFunc(GL_GREATER, 0.1F).

GL_CULL_FACE включает запрет на отрисовку полигонов с обратной стороны. По умолчанию включен, имеет смысл выключать в случаях, когда иначе придется дублировать полигоны с обеих сторон. Сопутствующие функции указывают, что считать передней и обратной сторонами полигона и какие стороны обрезать при включенном GL_CULL_FACE. Никакого смысла трогать эти функции нет, по умолчанию передней стороной считается та, которая рисуется против часовой стрелки.

GL_NORMALIZE включает автоматическую нормализацию нормалей. Довольно затратно, на практике использовать не стоит.

GL_RESCALE_NORMAL - упрощенный и ускоренный вариант GL_NORMALIZE. Он подразумевает, что переданные в openGL нормали уже были нормализованы, но вы масшабировали матрицу трансформации (использовали glScale()). Работает верно только в тех случаях, когда матрица была масштабирована без искажений, то есть x, y и z, которые вы передали в glScale(), были равны.

GL_POLYGON_OFFSET_FILL включает смещение данных из буфера глубины при отрисовке. Звучит немного непонятно, зато решает гораздо более понятную проблему. Если попробовать отрендерить что-то поверх уже отрисованной поверхности (пример из ванильного майна - текстура разрушения блока поверх самого блока), то начнутся проблемы, связанные с точностью буфера глубины. Подробнее про них можно почитать по ссылке про этот буфер, которую я уже давал.
Сопутствующая функция:
glPolygonOffset(factor, units) - задает смещение. Обычное использование в майне - glPolygonOffset(-3.0F, -3.0F). Кроме того, перед рендерингом с использованием этой возможности обычно отключают glDepthMask().

GL_SCISSOR_TEST запрещает отрисовку за пределами указанной квадратной зоны на экране. Естественно, основное применение этой фичи - GUI (например, довольно сложно реализовать скроллящуюся панель без этой возможности).
Сопутствующая функция:
glScissor(x, y, width, height). Координаты и размеры указываются в пикселях в окне, а не в том, что называется "пикселями" в ГУИ и на практике обычно оказывается больше реальных пикселей. Кроме того, ось Y идет снизу, а не сверху. Пример использования (запретить отрисовку за пределами квадрата 100х100 в верхнем левом углу экрана):
glScissor(0, mc.diplayHeight - 100, 100, 100);

glColor4f() и tessellator.setColorRGBA_F() - задает RGBA цвет. Аргументы должны быть от 0 до 1. Со включенной текстурой тоже работает, в таком случае цвет текстуры домножается на указанный здесь цвет.

glShadeModel(GL_FLAT/GL_SMOOTH) задает простое или сглаженное освещение. GL_FLAT стоит использовать, если в качестве нормалей вы используете перпендикуляр к полигону, GL_SMOOTH - если средний вектор между перпенндикулярами к нескольким полигонам.

Я рассказал только о тех функциях и параметрах, которые кажутся мне наиболее важными для моддинга. Это где-то треть от всех возможностей даже openGL 1, не говоря о современных версиях. Если этого вам недостаточно, то ваш лучший друг - это официальная документация по openGL.

Далее о некоторых вещах, которым не место в гайде по openGL 1, но о которых стоило бы рассказать.


[h]Освещение в Minecraft[/h]
В Minecraft есть два типа освещения: от блоков и от неба. У каждого блока в игре есть два параметра от 0 до 15: освещенность от неба и от блоков-источников света. С каждым пройденным от источника света блоком освещенность падает на 1. Освещенность от неба под открытым небом равна 15 даже глубокой ночью.
Теперь о том, как же всё это отрисовывается.
Есть динамическая текстура 16х16 (mc.renderEngine.lightmapTexture) и соответствующий ей массив размером 256 int'ов (mc.renderEngine.lightmapColors). В ней хранится информация о том, какой цвет соответствует каждой комбинации освещения от неба и освещения от блоков. Каждый кадр эта динамическая текстура обновляется исходя из текущего времени суток, рандомной "мигалки" (освещение от блоков немного колеблется), настроек игры (гаммы) и наложенного ночного зрения. Некоторые объекты (например, сущности и tile entity) рендерятся в режиме мультитекстурирования: в первой текстуре забиндена обычная текстура этого объекта, а во второй - лайтмапа. UV-координаты на лайтмапе задаются через OpenGLHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, u, v). Для сущностей и тайлов эта операция производится перед рендерингом.
Отключить использование лайтмапы можно через mc.renderEngine.disableLightmap(), включить - через mc.renderEngine.enableLightmap().


[h]Введение в шейдеры[/h] (а не рассказ о том, как их использовать)
В openGL 1 вы не можете написать ни строчки кода, которая исполнялась бы на видеокарте. Всё, что вам доступно - это стандартные возможности openGL. В openGL 2.0 такая возможность появилась. Хотя официально Minecraft поддерживает все версии openGL, начиная с 1.2, использовать возможности openGL 2.0 можно относительно безбоязненно, потому что видеокарты без его поддержки уже настолько устарели, что Minecraft на них вряд ли запустится.
Шейдеры - это короткие программы на простом си-подобном языке, позво В openGL 2.0 доступно два типа шейдеров: вершинные и фрагментные (пиксельные). Вершинные шейдеры позволяют модифицировать координаты вершин и передавать данные во фрагментные шейдеры. Фрагментные шейдеры позволяют модифицировать цвет вершины на основе данных, полученных из вершинного шейдера и текстур.
С помощью шейдеров можно эффективнее использовать видеокарту для различных вычислений. Примеры использования шейдеров: симуляция воды, реалистичное освещение (с тенями), использование различных карт (normal map для рельефа, specular map для бликов, gloss map для "шероховатости" и другое), создание различных графических эффектов, пост-обработка кадра и другое. Про использование шейдеров можно написать намного больше, чем всё то, что я написал в этом гайде.

GL11 и прозрачность


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


С GL'ем работаю первый день, так что не сердчайте. glDisable не выполняю потому что не знаю когда это нужно делать. Подскажите как быть? Как сделать прозрачность?

Мой проект: SawageWorldRP - ролки в Minecraft'е
Всех фатанов настольных рпг приглашаю присоединиться!
Человек - он как меч. Либо делает свое дело читает книги по java, либо тупой.

Где скачать и как установить Java 16:

Вам не нужно удалять старую версию Java (она нужна для игры на старых версиях), нужно скачать и установить 16 версию, и использовать именно ее для запуска снапшотов и версии 1.17.

Полезно :
Как верно указали в комментариях, есть несколько "официальных" источников Java 16, реализации от разных компаний, все они одинаково хорошо справятся со своей задачей, так что не пугайтесь.

Теперь, когда вы установили 16 версию, необходимо заставить ваш лаунчер использовать именно ее для запуска игры, и при этом пока лаунчеры не научатся сами знать и выбирать нужную версию, вам придется самим указывать нужную версию Java перед запуском конкретной версии игры, ну либо покупайте лицензию.

Адреса расположения версий Java:
При установке 32bit: C:\Program Files\AdoptOpenJDK\jdk-16.0.1.9-hotspot\bin\java.exe
При установке 64bit: C:\Program Files\Java\jdk-16.0.2\bin\java.exe

Предупреждение :
Повторю еще раз, для особенно слепых, кратко и поделу.
До Minecraft 1.17, а именно до снапшота 21w19a все версии игры отлично работали на Java 1.8.0_281, с модами и без модов, НО теперь все новые версии игры требуют версии Java 16, лиц лаунчер сам скачивает и использует нужную версию, а вот пиратам не повезло.

Многие пиратские лаунчеры этого пока не умеют, возможно не все научатся, потому что бы сейчас, а может быть и потом запускать на пиратском лаунчере Minecraft 1.17 нужно установить Java 16 и использовать именно ее для запуска игры. Прочие ванильные версии Minecraft работают на Java 16, а вот версии с модами НЕ РАБОТАЮТ на Java 16, для их запуска вам нужно указывать старую добрую Java 1.8.0.

Большинство лаунчеров позволяют указать адрес до исполняемого файла java.exe, обычно это делается в настройках лаунчера, именно там вы должны указать путь до 16 java, а уже потом запускать Minecraft 1.17, ну а для запуска версий с модами указывать java 1.8.0. В будущем пиратские лаунчеры поумнеют и вам не придется этого делать. ну а пока

Gl11 minecraft что это

---- Minecraft Crash Report ----

WARNING: coremods are present:
Contact their authors BEFORE contacting forge

Time: 25.05.19 11:47
Description: Exception ticking world

RuntimeException: No OpenGL context found in the current thread.
Profiler Position: N/A (disabled)
Player Count: 1 / 8; [EntityPlayerMP['EchoRR'/123, l='osnova', x=229,98, y=4,00, z=324,19]]
Type: Integrated Server (map_client.txt)
Is Modded: Definitely; Client brand changed to 'fml,forge'

Areplaer3

Areplaer3

крашит, а я в этом не шарю. буду благодарен кто поможет
я понимаю какие моды, но в чём проблема нет(

WARNING: coremods are present:
ClientFixer (clientfixer-1.12.2-1.9.jar)
IELoadingPlugin (ImmersiveEngineering-core-0.12-89.jar)
Inventory Tweaks Coremod (inventorytweaks-1.64dev.146.jar)
EnderCorePlugin (EnderCore-1.12.2-0.5.65-core.jar)
Contact their authors BEFORE contacting forge

Time: 17.08.19 1:21
Description: Exception in server tick loop

Missing Mods:
unknown : need [3.2.0,): have missing

Missing Mods:
unknown : need [3.2.3,): have missing

Missing Mods:
unknown : need [5.8.0.242,): have 5.7.0.232

Missing Mods:
unknown : need [2.0.4.7,): have missing

Missing Mods:
unknown : need [14.23.5.2816,): have 14.23.5.2768

Missing Mods:
unknown : need [1.12.2-9.8.1.383,1.12.2-9.8.1.383]: have missing

Missing Mods:
unknown : need [1.12.2-9.8.1.383,1.12.2-9.8.1.383]: have missing

Missing Mods:
unknown : need [5.8,): have 5.7.0.232
unknown : need [1.7,): have missing

Missing Mods:
unknown : need [1.12-1.3.3.49,): have missing

Missing Mods:
unknown : need [1.5.2,): have missing

Missing Mods:
unknown : need [3.1.7,): have missing

Missing Mods:
unknown : need [1.2.0,2.0.0): have missing

Missing Mods:
unknown : need [1.12.2-1.5,): have missing

Caman86

Caman86

ТруЪ Олдфаги-с

Звание: V.I.P на хуторе

obscurus

Звание: V.I.P на хуторе

GriefRu

RuntimeException: No OpenGL context found in the current thread.

LastNight

Areplaer3,
ClientFixer (clientfixer-1.12.2-1.9.jar)
IELoadingPlugin (ImmersiveEngineering-core-0.12-89.jar)
Inventory Tweaks Coremod (inventorytweaks-1.64dev.146.jar)
EnderCorePlugin (EnderCore-1.12.2-0.5.65-core.jar)

Удаляй их, либо заменяй

Caman86

Caman86

ТруЪ Олдфаги-с

Звание: V.I.P на хуторе

LastNight,
чел, не разбираешься - не лезь. Это просто кор-моды, которые написал фордж, он даже сам об этом говорит в логах. Разберись, почитай гайды и прочее на эту тему, пожалуйста, а потом уже отвечай, лады?
FLAYDE

Помогите пожалуйста я не знаю что делать!
---- Minecraft Crash Report ----
// You're mean.

Давайте немного разберемся, что это и как:

Начиная с предварительной версии 21w19a и с релиза 1.17 игра работает на более новой версии JAVA, лицензионный лаунчер это знает, он автоматически скачивает и устанавливает все необходимое, а вот многие пиратские лаунчеры этого пока не умеют, потому пиратам придется делать это руками.

К сожалению, не достаточно просто указать в лаунчере новую версию JAVA, новые версии игры работать будут, другие, более старые версии игры работать тоже будут, а вот многие моды на старых версиях всего скорее работать не будут, так как они устарели.

Предупреждение :
Большинство актуальных пиратских лаунчеров (в том числе наш rulauncher) научилось скачивать и правильно подставлять нужную версию Java, потому данная статья уже потеряла актуальность.

Java 16 - что это и где его взять? Не запускается Minecraft 1.17+ [Гайд]

Java 16 - что это и где его взять? Не запускается Minecraft 1.17+ [Гайд]

Читайте также: