Initial Commit

This commit is contained in:
richard committed 2026-11-13 22:25:04 +01:00
1 parent 377b32db6e
commit 2d9a5eecba
14134 files changed
+1160982

No files matched your search

Binary file not shown.
@@ -0,0 +1,26 @@
package mcp.client;
import java.util.Arrays;
import net.minecraft.client.main.Main;
public class Start
{
public static void main(String[] args)
{
/*
* start minecraft game application
* --version is just used as 'launched version' in snoop data and is required
* Working directory is used as gameDir if not provided
*/
String assets = System.getenv().containsKey("assetDirectory") ? System.getenv("assetDirectory") : "assets";
Main.main(concat(new String[]{"--version", "mcp", "--accessToken", "0", "--assetsDir", assets, "--assetIndex", "5", "--userProperties", "{}"}, args));
}
public static <T> T[] concat(T[] first, T[] second)
{
T[] result = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, result, first.length, second.length);
return result;
}
}
@@ -0,0 +1,2 @@
Manifest-Version: 1.0
@@ -0,0 +1,28 @@
package com.mojang.blaze3d;
import com.mojang.blaze3d.pipeline.RenderCall;
import com.mojang.blaze3d.pipeline.RenderPipeline;
import java.util.concurrent.ConcurrentLinkedQueue;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.system.MemoryUtil;
@OnlyIn(Dist.CLIENT)
public class Blaze3D {
public static void process(RenderPipeline pPipeline, float pUnknown) {
ConcurrentLinkedQueue<RenderCall> concurrentlinkedqueue = pPipeline.getRecordingQueue();
}
public static void render(RenderPipeline pPipeline, float pUnknown) {
ConcurrentLinkedQueue<RenderCall> concurrentlinkedqueue = pPipeline.getProcessedQueue();
}
public static void youJustLostTheGame() {
MemoryUtil.memSet(0L, 0, 1L);
}
public static double getTime() {
return GLFW.glfwGetTime();
}
}
@@ -0,0 +1,14 @@
package com.mojang.blaze3d;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.meta.TypeQualifierDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@TypeQualifierDefault({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.CLASS)
@OnlyIn(Dist.CLIENT)
public @interface DontObfuscate {
}
@@ -0,0 +1,16 @@
package com.mojang.blaze3d;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@Nonnull
@TypeQualifierDefault({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@OnlyIn(Dist.CLIENT)
public @interface FieldsAreNonnullByDefault {
}
@@ -0,0 +1,16 @@
package com.mojang.blaze3d;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@Nonnull
@TypeQualifierDefault({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@OnlyIn(Dist.CLIENT)
public @interface MethodsReturnNonnullByDefault {
}
@@ -0,0 +1,183 @@
package com.mojang.blaze3d.audio;
import com.mojang.logging.LogUtils;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nullable;
import javax.sound.sampled.AudioFormat;
import net.minecraft.client.sounds.AudioStream;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.openal.AL10;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class Channel {
private static final Logger LOGGER = LogUtils.getLogger();
private static final int QUEUED_BUFFER_COUNT = 4;
public static final int BUFFER_DURATION_SECONDS = 1;
private final int source;
private final AtomicBoolean initialized = new AtomicBoolean(true);
private int streamingBufferSize = 16384;
@Nullable
private AudioStream stream;
@Nullable
static Channel create() {
int[] aint = new int[1];
AL10.alGenSources(aint);
return OpenAlUtil.checkALError("Allocate new source") ? null : new Channel(aint[0]);
}
private Channel(int pSource) {
this.source = pSource;
}
public void destroy() {
if (this.initialized.compareAndSet(true, false)) {
AL10.alSourceStop(this.source);
OpenAlUtil.checkALError("Stop");
if (this.stream != null) {
try {
this.stream.close();
} catch (IOException ioexception) {
LOGGER.error("Failed to close audio stream", (Throwable)ioexception);
}
this.removeProcessedBuffers();
this.stream = null;
}
AL10.alDeleteSources(new int[]{this.source});
OpenAlUtil.checkALError("Cleanup");
}
}
public void play() {
AL10.alSourcePlay(this.source);
}
private int getState() {
return !this.initialized.get() ? 4116 : AL10.alGetSourcei(this.source, 4112);
}
public void pause() {
if (this.getState() == 4114) {
AL10.alSourcePause(this.source);
}
}
public void unpause() {
if (this.getState() == 4115) {
AL10.alSourcePlay(this.source);
}
}
public void stop() {
if (this.initialized.get()) {
AL10.alSourceStop(this.source);
OpenAlUtil.checkALError("Stop");
}
}
public boolean playing() {
return this.getState() == 4114;
}
public boolean stopped() {
return this.getState() == 4116;
}
public void setSelfPosition(Vec3 pSource) {
AL10.alSourcefv(this.source, 4100, new float[]{(float)pSource.x, (float)pSource.y, (float)pSource.z});
}
public void setPitch(float pPitch) {
AL10.alSourcef(this.source, 4099, pPitch);
}
public void setLooping(boolean pLooping) {
AL10.alSourcei(this.source, 4103, pLooping ? 1 : 0);
}
public void setVolume(float pVolume) {
AL10.alSourcef(this.source, 4106, pVolume);
}
public void disableAttenuation() {
AL10.alSourcei(this.source, 53248, 0);
}
public void linearAttenuation(float pLinearAttenuation) {
AL10.alSourcei(this.source, 53248, 53251);
AL10.alSourcef(this.source, 4131, pLinearAttenuation);
AL10.alSourcef(this.source, 4129, 1.0F);
AL10.alSourcef(this.source, 4128, 0.0F);
}
public void setRelative(boolean pRelative) {
AL10.alSourcei(this.source, 514, pRelative ? 1 : 0);
}
public void attachStaticBuffer(SoundBuffer pBuffer) {
pBuffer.getAlBuffer().ifPresent((p_83676_) -> {
AL10.alSourcei(this.source, 4105, p_83676_);
});
}
public void attachBufferStream(AudioStream pStream) {
this.stream = pStream;
AudioFormat audioformat = pStream.getFormat();
this.streamingBufferSize = calculateBufferSize(audioformat, 1);
this.pumpBuffers(4);
}
private static int calculateBufferSize(AudioFormat pFormat, int pSampleAmount) {
return (int)((float)(pSampleAmount * pFormat.getSampleSizeInBits()) / 8.0F * (float)pFormat.getChannels() * pFormat.getSampleRate());
}
private void pumpBuffers(int pReadCount) {
if (this.stream != null) {
try {
for(int i = 0; i < pReadCount; ++i) {
ByteBuffer bytebuffer = this.stream.read(this.streamingBufferSize);
if (bytebuffer != null) {
(new SoundBuffer(bytebuffer, this.stream.getFormat())).releaseAlBuffer().ifPresent((p_83669_) -> {
AL10.alSourceQueueBuffers(this.source, new int[]{p_83669_});
});
}
}
} catch (IOException ioexception) {
LOGGER.error("Failed to read from audio stream", (Throwable)ioexception);
}
}
}
public void updateStream() {
if (this.stream != null) {
int i = this.removeProcessedBuffers();
this.pumpBuffers(i);
}
}
private int removeProcessedBuffers() {
int i = AL10.alGetSourcei(this.source, 4118);
if (i > 0) {
int[] aint = new int[i];
AL10.alSourceUnqueueBuffers(this.source, aint);
OpenAlUtil.checkALError("Unqueue buffers");
AL10.alDeleteBuffers(aint);
OpenAlUtil.checkALError("Remove processed buffers");
}
return i;
}
}
@@ -0,0 +1,314 @@
package com.mojang.blaze3d.audio;
import com.google.common.collect.Sets;
import com.mojang.logging.LogUtils;
import java.nio.IntBuffer;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.OptionalLong;
import java.util.Set;
import javax.annotation.Nullable;
import net.minecraft.SharedConstants;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.AL10;
import org.lwjgl.openal.ALC;
import org.lwjgl.openal.ALC10;
import org.lwjgl.openal.ALC11;
import org.lwjgl.openal.ALCCapabilities;
import org.lwjgl.openal.ALCapabilities;
import org.lwjgl.openal.ALUtil;
import org.lwjgl.openal.SOFTHRTF;
import org.lwjgl.system.MemoryStack;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class Library {
static final Logger LOGGER = LogUtils.getLogger();
private static final int NO_DEVICE = 0;
private static final int DEFAULT_CHANNEL_COUNT = 30;
private long currentDevice;
private long context;
private boolean supportsDisconnections;
@Nullable
private String defaultDeviceName;
private static final Library.ChannelPool EMPTY = new Library.ChannelPool() {
@Nullable
public Channel acquire() {
return null;
}
public boolean release(Channel p_83708_) {
return false;
}
public void cleanup() {
}
public int getMaxCount() {
return 0;
}
public int getUsedCount() {
return 0;
}
};
private Library.ChannelPool staticChannels = EMPTY;
private Library.ChannelPool streamingChannels = EMPTY;
private final Listener listener = new Listener();
public Library() {
this.defaultDeviceName = getDefaultDeviceName();
}
public void init(@Nullable String pDeviceSpecifier, boolean p_231086_) {
this.currentDevice = openDeviceOrFallback(pDeviceSpecifier);
this.supportsDisconnections = ALC10.alcIsExtensionPresent(this.currentDevice, "ALC_EXT_disconnect");
ALCCapabilities alccapabilities = ALC.createCapabilities(this.currentDevice);
if (OpenAlUtil.checkALCError(this.currentDevice, "Get capabilities")) {
throw new IllegalStateException("Failed to get OpenAL capabilities");
} else if (!alccapabilities.OpenALC11) {
throw new IllegalStateException("OpenAL 1.1 not supported");
} else {
this.setHrtf(alccapabilities.ALC_SOFT_HRTF && p_231086_);
this.context = ALC10.alcCreateContext(this.currentDevice, (IntBuffer)null);
ALC10.alcMakeContextCurrent(this.context);
int i = this.getChannelCount();
int j = Mth.clamp((int)Mth.sqrt((float)i), 2, 8);
int k = Mth.clamp(i - j, 8, 255);
this.staticChannels = new Library.CountingChannelPool(k);
this.streamingChannels = new Library.CountingChannelPool(j);
ALCapabilities alcapabilities = AL.createCapabilities(alccapabilities);
OpenAlUtil.checkALError("Initialization");
if (!alcapabilities.AL_EXT_source_distance_model) {
throw new IllegalStateException("AL_EXT_source_distance_model is not supported");
} else {
AL10.alEnable(512);
if (!alcapabilities.AL_EXT_LINEAR_DISTANCE) {
throw new IllegalStateException("AL_EXT_LINEAR_DISTANCE is not supported");
} else {
OpenAlUtil.checkALError("Enable per-source distance models");
LOGGER.info("OpenAL initialized on device {}", (Object)this.getCurrentDeviceName());
}
}
}
}
private void setHrtf(boolean p_242278_) {
int i = ALC10.alcGetInteger(this.currentDevice, 6548);
if (i > 0) {
try (MemoryStack memorystack = MemoryStack.stackPush()) {
IntBuffer intbuffer = memorystack.callocInt(10).put(6546).put(p_242278_ ? 1 : 0).put(6550).put(0).put(0).flip();
if (!SOFTHRTF.alcResetDeviceSOFT(this.currentDevice, intbuffer)) {
LOGGER.warn("Failed to reset device: {}", (Object)ALC10.alcGetString(this.currentDevice, ALC10.alcGetError(this.currentDevice)));
}
}
}
}
private int getChannelCount() {
try (MemoryStack memorystack = MemoryStack.stackPush()) {
int i = ALC10.alcGetInteger(this.currentDevice, 4098);
if (OpenAlUtil.checkALCError(this.currentDevice, "Get attributes size")) {
throw new IllegalStateException("Failed to get OpenAL attributes");
}
IntBuffer intbuffer = memorystack.mallocInt(i);
ALC10.alcGetIntegerv(this.currentDevice, 4099, intbuffer);
if (OpenAlUtil.checkALCError(this.currentDevice, "Get attributes")) {
throw new IllegalStateException("Failed to get OpenAL attributes");
}
int j = 0;
while(j < i) {
int k = intbuffer.get(j++);
if (k == 0) {
break;
}
int l = intbuffer.get(j++);
if (k == 4112) {
return l;
}
}
}
return 30;
}
@Nullable
public static String getDefaultDeviceName() {
if (!ALC10.alcIsExtensionPresent(0L, "ALC_ENUMERATE_ALL_EXT")) {
return null;
} else {
ALUtil.getStringList(0L, 4115);
return ALC10.alcGetString(0L, 4114);
}
}
public String getCurrentDeviceName() {
String s = ALC10.alcGetString(this.currentDevice, 4115);
if (s == null) {
s = ALC10.alcGetString(this.currentDevice, 4101);
}
if (s == null) {
s = "Unknown";
}
return s;
}
public synchronized boolean hasDefaultDeviceChanged() {
String s = getDefaultDeviceName();
if (Objects.equals(this.defaultDeviceName, s)) {
return false;
} else {
this.defaultDeviceName = s;
return true;
}
}
private static long openDeviceOrFallback(@Nullable String pDeviceSpecifier) {
OptionalLong optionallong = OptionalLong.empty();
if (pDeviceSpecifier != null) {
optionallong = tryOpenDevice(pDeviceSpecifier);
}
if (optionallong.isEmpty()) {
optionallong = tryOpenDevice(getDefaultDeviceName());
}
if (optionallong.isEmpty()) {
optionallong = tryOpenDevice((String)null);
}
if (optionallong.isEmpty()) {
throw new IllegalStateException("Failed to open OpenAL device");
} else {
return optionallong.getAsLong();
}
}
private static OptionalLong tryOpenDevice(@Nullable String pDeviceSpecifier) {
long i = ALC10.alcOpenDevice(pDeviceSpecifier);
return i != 0L && !OpenAlUtil.checkALCError(i, "Open device") ? OptionalLong.of(i) : OptionalLong.empty();
}
public void cleanup() {
this.staticChannels.cleanup();
this.streamingChannels.cleanup();
ALC10.alcDestroyContext(this.context);
if (this.currentDevice != 0L) {
ALC10.alcCloseDevice(this.currentDevice);
}
}
public Listener getListener() {
return this.listener;
}
/**
* Acquires a sound channel based on the given mode.
*/
@Nullable
public Channel acquireChannel(Library.Pool pPool) {
return (pPool == Library.Pool.STREAMING ? this.streamingChannels : this.staticChannels).acquire();
}
public void releaseChannel(Channel pChannel) {
if (!this.staticChannels.release(pChannel) && !this.streamingChannels.release(pChannel)) {
throw new IllegalStateException("Tried to release unknown channel");
}
}
public String getDebugString() {
return String.format(Locale.ROOT, "Sounds: %d/%d + %d/%d", this.staticChannels.getUsedCount(), this.staticChannels.getMaxCount(), this.streamingChannels.getUsedCount(), this.streamingChannels.getMaxCount());
}
public List<String> getAvailableSoundDevices() {
List<String> list = ALUtil.getStringList(0L, 4115);
return list == null ? Collections.emptyList() : list;
}
public boolean isCurrentDeviceDisconnected() {
return this.supportsDisconnections && ALC11.alcGetInteger(this.currentDevice, 787) == 0;
}
@OnlyIn(Dist.CLIENT)
interface ChannelPool {
@Nullable
Channel acquire();
boolean release(Channel pChannel);
void cleanup();
int getMaxCount();
int getUsedCount();
}
@OnlyIn(Dist.CLIENT)
static class CountingChannelPool implements Library.ChannelPool {
private final int limit;
private final Set<Channel> activeChannels = Sets.newIdentityHashSet();
public CountingChannelPool(int pLimit) {
this.limit = pLimit;
}
@Nullable
public Channel acquire() {
if (this.activeChannels.size() >= this.limit) {
if (SharedConstants.IS_RUNNING_IN_IDE) {
Library.LOGGER.warn("Maximum sound pool size {} reached", (int)this.limit);
}
return null;
} else {
Channel channel = Channel.create();
if (channel != null) {
this.activeChannels.add(channel);
}
return channel;
}
}
public boolean release(Channel pChannel) {
if (!this.activeChannels.remove(pChannel)) {
return false;
} else {
pChannel.destroy();
return true;
}
}
public void cleanup() {
this.activeChannels.forEach(Channel::destroy);
this.activeChannels.clear();
}
public int getMaxCount() {
return this.limit;
}
public int getUsedCount() {
return this.activeChannels.size();
}
}
@OnlyIn(Dist.CLIENT)
public static enum Pool {
STATIC,
STREAMING;
}
}
@@ -0,0 +1,40 @@
package com.mojang.blaze3d.audio;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Vector3f;
import org.lwjgl.openal.AL10;
@OnlyIn(Dist.CLIENT)
public class Listener {
private float gain = 1.0F;
private Vec3 position = Vec3.ZERO;
public void setListenerPosition(Vec3 pPosition) {
this.position = pPosition;
AL10.alListener3f(4100, (float)pPosition.x, (float)pPosition.y, (float)pPosition.z);
}
public Vec3 getListenerPosition() {
return this.position;
}
public void setListenerOrientation(Vector3f pClientViewVector, Vector3f pViewVectorRaised) {
AL10.alListenerfv(4111, new float[]{pClientViewVector.x(), pClientViewVector.y(), pClientViewVector.z(), pViewVectorRaised.x(), pViewVectorRaised.y(), pViewVectorRaised.z()});
}
public void setGain(float pGain) {
AL10.alListenerf(4106, pGain);
this.gain = pGain;
}
public float getGain() {
return this.gain;
}
public void reset() {
this.setListenerPosition(Vec3.ZERO);
this.setListenerOrientation(new Vector3f(0.0F, 0.0F, -1.0F), new Vector3f(0.0F, 1.0F, 0.0F));
}
}
@@ -0,0 +1,232 @@
package com.mojang.blaze3d.audio;
import com.google.common.collect.Lists;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.List;
import javax.sound.sampled.AudioFormat;
import net.minecraft.client.sounds.AudioStream;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.BufferUtils;
import org.lwjgl.PointerBuffer;
import org.lwjgl.stb.STBVorbis;
import org.lwjgl.stb.STBVorbisAlloc;
import org.lwjgl.stb.STBVorbisInfo;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
@OnlyIn(Dist.CLIENT)
public class OggAudioStream implements AudioStream {
private static final int EXPECTED_MAX_FRAME_SIZE = 8192;
private long handle;
private final AudioFormat audioFormat;
private final InputStream input;
private ByteBuffer buffer = MemoryUtil.memAlloc(8192);
public OggAudioStream(InputStream pInput) throws IOException {
this.input = pInput;
this.buffer.limit(0);
try (MemoryStack memorystack = MemoryStack.stackPush()) {
IntBuffer intbuffer = memorystack.mallocInt(1);
IntBuffer intbuffer1 = memorystack.mallocInt(1);
while(this.handle == 0L) {
if (!this.refillFromStream()) {
throw new IOException("Failed to find Ogg header");
}
int i = this.buffer.position();
this.buffer.position(0);
this.handle = STBVorbis.stb_vorbis_open_pushdata(this.buffer, intbuffer, intbuffer1, (STBVorbisAlloc)null);
this.buffer.position(i);
int j = intbuffer1.get(0);
if (j == 1) {
this.forwardBuffer();
} else if (j != 0) {
throw new IOException("Failed to read Ogg file " + j);
}
}
this.buffer.position(this.buffer.position() + intbuffer.get(0));
STBVorbisInfo stbvorbisinfo = STBVorbisInfo.mallocStack(memorystack);
STBVorbis.stb_vorbis_get_info(this.handle, stbvorbisinfo);
this.audioFormat = new AudioFormat((float)stbvorbisinfo.sample_rate(), 16, stbvorbisinfo.channels(), true, false);
}
}
private boolean refillFromStream() throws IOException {
int i = this.buffer.limit();
int j = this.buffer.capacity() - i;
if (j == 0) {
return true;
} else {
byte[] abyte = new byte[j];
int k = this.input.read(abyte);
if (k == -1) {
return false;
} else {
int l = this.buffer.position();
this.buffer.limit(i + k);
this.buffer.position(i);
this.buffer.put(abyte, 0, k);
this.buffer.position(l);
return true;
}
}
}
private void forwardBuffer() {
boolean flag = this.buffer.position() == 0;
boolean flag1 = this.buffer.position() == this.buffer.limit();
if (flag1 && !flag) {
this.buffer.position(0);
this.buffer.limit(0);
} else {
ByteBuffer bytebuffer = MemoryUtil.memAlloc(flag ? 2 * this.buffer.capacity() : this.buffer.capacity());
bytebuffer.put(this.buffer);
MemoryUtil.memFree(this.buffer);
bytebuffer.flip();
this.buffer = bytebuffer;
}
}
private boolean readFrame(OggAudioStream.OutputConcat pOutput) throws IOException {
if (this.handle == 0L) {
return false;
} else {
try (MemoryStack memorystack = MemoryStack.stackPush()) {
PointerBuffer pointerbuffer = memorystack.mallocPointer(1);
IntBuffer intbuffer = memorystack.mallocInt(1);
IntBuffer intbuffer1 = memorystack.mallocInt(1);
while(true) {
int i = STBVorbis.stb_vorbis_decode_frame_pushdata(this.handle, this.buffer, intbuffer, pointerbuffer, intbuffer1);
this.buffer.position(this.buffer.position() + i);
int j = STBVorbis.stb_vorbis_get_error(this.handle);
if (j == 1) {
this.forwardBuffer();
if (!this.refillFromStream()) {
return false;
}
} else {
if (j != 0) {
throw new IOException("Failed to read Ogg file " + j);
}
int k = intbuffer1.get(0);
if (k != 0) {
int l = intbuffer.get(0);
PointerBuffer pointerbuffer1 = pointerbuffer.getPointerBuffer(l);
if (l == 1) {
this.convertMono(pointerbuffer1.getFloatBuffer(0, k), pOutput);
return true;
} else if (l != 2) {
throw new IllegalStateException("Invalid number of channels: " + l);
} else {
this.convertStereo(pointerbuffer1.getFloatBuffer(0, k), pointerbuffer1.getFloatBuffer(1, k), pOutput);
return true;
}
}
}
}
}
}
}
private void convertMono(FloatBuffer pChannel, OggAudioStream.OutputConcat pOutput) {
while(pChannel.hasRemaining()) {
pOutput.put(pChannel.get());
}
}
private void convertStereo(FloatBuffer pLeftChannel, FloatBuffer pRightChannel, OggAudioStream.OutputConcat pOutput) {
while(pLeftChannel.hasRemaining() && pRightChannel.hasRemaining()) {
pOutput.put(pLeftChannel.get());
pOutput.put(pRightChannel.get());
}
}
public void close() throws IOException {
if (this.handle != 0L) {
STBVorbis.stb_vorbis_close(this.handle);
this.handle = 0L;
}
MemoryUtil.memFree(this.buffer);
this.input.close();
}
public AudioFormat getFormat() {
return this.audioFormat;
}
public ByteBuffer read(int pSize) throws IOException {
OggAudioStream.OutputConcat oggaudiostream$outputconcat = new OggAudioStream.OutputConcat(pSize + 8192);
while(this.readFrame(oggaudiostream$outputconcat) && oggaudiostream$outputconcat.byteCount < pSize) {
}
return oggaudiostream$outputconcat.get();
}
public ByteBuffer readAll() throws IOException {
OggAudioStream.OutputConcat oggaudiostream$outputconcat = new OggAudioStream.OutputConcat(16384);
while(this.readFrame(oggaudiostream$outputconcat)) {
}
return oggaudiostream$outputconcat.get();
}
@OnlyIn(Dist.CLIENT)
static class OutputConcat {
private final List<ByteBuffer> buffers = Lists.newArrayList();
private final int bufferSize;
int byteCount;
private ByteBuffer currentBuffer;
public OutputConcat(int pSize) {
this.bufferSize = pSize + 1 & -2;
this.createNewBuffer();
}
private void createNewBuffer() {
this.currentBuffer = BufferUtils.createByteBuffer(this.bufferSize);
}
public void put(float pSample) {
if (this.currentBuffer.remaining() == 0) {
this.currentBuffer.flip();
this.buffers.add(this.currentBuffer);
this.createNewBuffer();
}
int i = Mth.clamp((int)(pSample * 32767.5F - 0.5F), -32768, 32767);
this.currentBuffer.putShort((short)i);
this.byteCount += 2;
}
public ByteBuffer get() {
this.currentBuffer.flip();
if (this.buffers.isEmpty()) {
return this.currentBuffer;
} else {
ByteBuffer bytebuffer = BufferUtils.createByteBuffer(this.byteCount);
this.buffers.forEach(bytebuffer::put);
bytebuffer.put(this.currentBuffer);
bytebuffer.flip();
return bytebuffer;
}
}
}
}
@@ -0,0 +1,96 @@
package com.mojang.blaze3d.audio;
import com.mojang.logging.LogUtils;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioFormat.Encoding;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.openal.AL10;
import org.lwjgl.openal.ALC10;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class OpenAlUtil {
private static final Logger LOGGER = LogUtils.getLogger();
private static String alErrorToString(int pErrorCode) {
switch (pErrorCode) {
case 40961:
return "Invalid name parameter.";
case 40962:
return "Invalid enumerated parameter value.";
case 40963:
return "Invalid parameter parameter value.";
case 40964:
return "Invalid operation.";
case 40965:
return "Unable to allocate memory.";
default:
return "An unrecognized error occurred.";
}
}
static boolean checkALError(String pOperationState) {
int i = AL10.alGetError();
if (i != 0) {
LOGGER.error("{}: {}", pOperationState, alErrorToString(i));
return true;
} else {
return false;
}
}
private static String alcErrorToString(int pErrorCode) {
switch (pErrorCode) {
case 40961:
return "Invalid device.";
case 40962:
return "Invalid context.";
case 40963:
return "Illegal enum.";
case 40964:
return "Invalid value.";
case 40965:
return "Unable to allocate memory.";
default:
return "An unrecognized error occurred.";
}
}
static boolean checkALCError(long pDeviceHandle, String pOperationState) {
int i = ALC10.alcGetError(pDeviceHandle);
if (i != 0) {
LOGGER.error("{}{}: {}", pOperationState, pDeviceHandle, alcErrorToString(i));
return true;
} else {
return false;
}
}
static int audioFormatToOpenAl(AudioFormat pFormat) {
AudioFormat.Encoding encoding = pFormat.getEncoding();
int i = pFormat.getChannels();
int j = pFormat.getSampleSizeInBits();
if (encoding.equals(Encoding.PCM_UNSIGNED) || encoding.equals(Encoding.PCM_SIGNED)) {
if (i == 1) {
if (j == 8) {
return 4352;
}
if (j == 16) {
return 4353;
}
} else if (i == 2) {
if (j == 8) {
return 4354;
}
if (j == 16) {
return 4355;
}
}
}
throw new IllegalArgumentException("Invalid audio format: " + pFormat);
}
}
@@ -0,0 +1,66 @@
package com.mojang.blaze3d.audio;
import java.nio.ByteBuffer;
import java.util.OptionalInt;
import javax.annotation.Nullable;
import javax.sound.sampled.AudioFormat;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.openal.AL10;
@OnlyIn(Dist.CLIENT)
public class SoundBuffer {
@Nullable
private ByteBuffer data;
private final AudioFormat format;
private boolean hasAlBuffer;
private int alBuffer;
public SoundBuffer(ByteBuffer pData, AudioFormat pFormat) {
this.data = pData;
this.format = pFormat;
}
OptionalInt getAlBuffer() {
if (!this.hasAlBuffer) {
if (this.data == null) {
return OptionalInt.empty();
}
int i = OpenAlUtil.audioFormatToOpenAl(this.format);
int[] aint = new int[1];
AL10.alGenBuffers(aint);
if (OpenAlUtil.checkALError("Creating buffer")) {
return OptionalInt.empty();
}
AL10.alBufferData(aint[0], i, this.data, (int)this.format.getSampleRate());
if (OpenAlUtil.checkALError("Assigning buffer data")) {
return OptionalInt.empty();
}
this.alBuffer = aint[0];
this.hasAlBuffer = true;
this.data = null;
}
return OptionalInt.of(this.alBuffer);
}
public void discardAlBuffer() {
if (this.hasAlBuffer) {
AL10.alDeleteBuffers(new int[]{this.alBuffer});
if (OpenAlUtil.checkALError("Deleting stream buffers")) {
return;
}
}
this.hasAlBuffer = false;
}
public OptionalInt releaseAlBuffer() {
OptionalInt optionalint = this.getAlBuffer();
this.hasAlBuffer = false;
return optionalint;
}
}
@@ -0,0 +1,11 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
@OnlyIn(Dist.CLIENT)
package com.mojang.blaze3d.audio;
import com.mojang.blaze3d.FieldsAreNonnullByDefault;
import com.mojang.blaze3d.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -0,0 +1,33 @@
package com.mojang.blaze3d.font;
import java.util.function.Function;
import net.minecraft.client.gui.font.glyphs.BakedGlyph;
import net.minecraft.client.gui.font.glyphs.EmptyGlyph;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public interface GlyphInfo {
float getAdvance();
default float getAdvance(boolean pBold) {
return this.getAdvance() + (pBold ? this.getBoldOffset() : 0.0F);
}
default float getBoldOffset() {
return 1.0F;
}
default float getShadowOffset() {
return 1.0F;
}
BakedGlyph bake(Function<SheetGlyphInfo, BakedGlyph> p_231088_);
@OnlyIn(Dist.CLIENT)
public interface SpaceGlyphInfo extends GlyphInfo {
default BakedGlyph bake(Function<SheetGlyphInfo, BakedGlyph> p_231090_) {
return EmptyGlyph.INSTANCE;
}
}
}
@@ -0,0 +1,19 @@
package com.mojang.blaze3d.font;
import it.unimi.dsi.fastutil.ints.IntSet;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public interface GlyphProvider extends AutoCloseable {
default void close() {
}
@Nullable
default GlyphInfo getGlyph(int pCharacter) {
return null;
}
IntSet getSupportedGlyphs();
}
@@ -0,0 +1,41 @@
package com.mojang.blaze3d.font;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public interface SheetGlyphInfo {
int getPixelWidth();
int getPixelHeight();
void upload(int pXOffset, int pYOffset);
boolean isColored();
float getOversample();
default float getLeft() {
return this.getBearingX();
}
default float getRight() {
return this.getLeft() + (float)this.getPixelWidth() / this.getOversample();
}
default float getUp() {
return this.getBearingY();
}
default float getDown() {
return this.getUp() + (float)this.getPixelHeight() / this.getOversample();
}
default float getBearingX() {
return 0.0F;
}
default float getBearingY() {
return 3.0F;
}
}
@@ -0,0 +1,58 @@
package com.mojang.blaze3d.font;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.ints.IntSets;
import java.util.Map;
import javax.annotation.Nullable;
import net.minecraft.client.gui.font.providers.GlyphProviderDefinition;
import net.minecraft.client.gui.font.providers.GlyphProviderType;
import net.minecraft.util.ExtraCodecs;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class SpaceProvider implements GlyphProvider {
private final Int2ObjectMap<GlyphInfo.SpaceGlyphInfo> glyphs;
public SpaceProvider(Map<Integer, Float> p_286456_) {
this.glyphs = new Int2ObjectOpenHashMap<>(p_286456_.size());
p_286456_.forEach((p_286113_, p_286114_) -> {
this.glyphs.put(p_286113_.intValue(), () -> {
return p_286114_;
});
});
}
@Nullable
public GlyphInfo getGlyph(int p_231105_) {
return this.glyphs.get(p_231105_);
}
public IntSet getSupportedGlyphs() {
return IntSets.unmodifiable(this.glyphs.keySet());
}
@OnlyIn(Dist.CLIENT)
public static record Definition(Map<Integer, Float> advances) implements GlyphProviderDefinition {
public static final MapCodec<SpaceProvider.Definition> CODEC = RecordCodecBuilder.mapCodec((p_286766_) -> {
return p_286766_.group(Codec.unboundedMap(ExtraCodecs.CODEPOINT, Codec.FLOAT).fieldOf("advances").forGetter(SpaceProvider.Definition::advances)).apply(p_286766_, SpaceProvider.Definition::new);
});
public GlyphProviderType type() {
return GlyphProviderType.SPACE;
}
public Either<GlyphProviderDefinition.Loader, GlyphProviderDefinition.Reference> unpack() {
GlyphProviderDefinition.Loader glyphproviderdefinition$loader = (p_286243_) -> {
return new SpaceProvider(this.advances);
};
return Either.left(glyphproviderdefinition$loader);
}
}
}
@@ -0,0 +1,164 @@
package com.mojang.blaze3d.font;
import com.mojang.blaze3d.platform.NativeImage;
import it.unimi.dsi.fastutil.ints.IntArraySet;
import it.unimi.dsi.fastutil.ints.IntCollection;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.util.function.Function;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
import net.minecraft.client.gui.font.glyphs.BakedGlyph;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.stb.STBTTFontinfo;
import org.lwjgl.stb.STBTruetype;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
@OnlyIn(Dist.CLIENT)
public class TrueTypeGlyphProvider implements GlyphProvider {
@Nullable
private ByteBuffer fontMemory;
@Nullable
private STBTTFontinfo font;
final float oversample;
private final IntSet skip = new IntArraySet();
final float shiftX;
final float shiftY;
final float pointScale;
final float ascent;
public TrueTypeGlyphProvider(ByteBuffer pFontMemory, STBTTFontinfo pFont, float pHeight, float pOversample, float pShiftX, float pShiftY, String pSkip) {
this.fontMemory = pFontMemory;
this.font = pFont;
this.oversample = pOversample;
pSkip.codePoints().forEach(this.skip::add);
this.shiftX = pShiftX * pOversample;
this.shiftY = pShiftY * pOversample;
this.pointScale = STBTruetype.stbtt_ScaleForPixelHeight(pFont, pHeight * pOversample);
try (MemoryStack memorystack = MemoryStack.stackPush()) {
IntBuffer intbuffer = memorystack.mallocInt(1);
IntBuffer intbuffer1 = memorystack.mallocInt(1);
IntBuffer intbuffer2 = memorystack.mallocInt(1);
STBTruetype.stbtt_GetFontVMetrics(pFont, intbuffer, intbuffer1, intbuffer2);
this.ascent = (float)intbuffer.get(0) * this.pointScale;
}
}
@Nullable
public GlyphInfo getGlyph(int pCharacter) {
STBTTFontinfo stbttfontinfo = this.validateFontOpen();
if (this.skip.contains(pCharacter)) {
return null;
} else {
try (MemoryStack memorystack = MemoryStack.stackPush()) {
int i = STBTruetype.stbtt_FindGlyphIndex(stbttfontinfo, pCharacter);
if (i == 0) {
return null;
} else {
IntBuffer intbuffer = memorystack.mallocInt(1);
IntBuffer intbuffer1 = memorystack.mallocInt(1);
IntBuffer intbuffer2 = memorystack.mallocInt(1);
IntBuffer intbuffer3 = memorystack.mallocInt(1);
IntBuffer intbuffer4 = memorystack.mallocInt(1);
IntBuffer intbuffer5 = memorystack.mallocInt(1);
STBTruetype.stbtt_GetGlyphHMetrics(stbttfontinfo, i, intbuffer4, intbuffer5);
STBTruetype.stbtt_GetGlyphBitmapBoxSubpixel(stbttfontinfo, i, this.pointScale, this.pointScale, this.shiftX, this.shiftY, intbuffer, intbuffer1, intbuffer2, intbuffer3);
float f = (float)intbuffer4.get(0) * this.pointScale;
int j = intbuffer2.get(0) - intbuffer.get(0);
int k = intbuffer3.get(0) - intbuffer1.get(0);
return (GlyphInfo)(j > 0 && k > 0 ? new TrueTypeGlyphProvider.Glyph(intbuffer.get(0), intbuffer2.get(0), -intbuffer1.get(0), -intbuffer3.get(0), f, (float)intbuffer5.get(0) * this.pointScale, i) : (GlyphInfo.SpaceGlyphInfo)() -> {
return f / this.oversample;
});
}
}
}
}
STBTTFontinfo validateFontOpen() {
if (this.fontMemory != null && this.font != null) {
return this.font;
} else {
throw new IllegalArgumentException("Provider already closed");
}
}
public void close() {
if (this.font != null) {
this.font.free();
this.font = null;
}
MemoryUtil.memFree(this.fontMemory);
this.fontMemory = null;
}
public IntSet getSupportedGlyphs() {
return IntStream.range(0, 65535).filter((p_231118_) -> {
return !this.skip.contains(p_231118_);
}).collect(IntOpenHashSet::new, IntCollection::add, IntCollection::addAll);
}
@OnlyIn(Dist.CLIENT)
class Glyph implements GlyphInfo {
final int width;
final int height;
final float bearingX;
final float bearingY;
private final float advance;
final int index;
Glyph(int pMinWidth, int pMaxWidth, int pMinHeight, int pMaxHeight, float pAdvance, float pBearingX, int pIndex) {
this.width = pMaxWidth - pMinWidth;
this.height = pMinHeight - pMaxHeight;
this.advance = pAdvance / TrueTypeGlyphProvider.this.oversample;
this.bearingX = (pBearingX + (float)pMinWidth + TrueTypeGlyphProvider.this.shiftX) / TrueTypeGlyphProvider.this.oversample;
this.bearingY = (TrueTypeGlyphProvider.this.ascent - (float)pMinHeight + TrueTypeGlyphProvider.this.shiftY) / TrueTypeGlyphProvider.this.oversample;
this.index = pIndex;
}
public float getAdvance() {
return this.advance;
}
public BakedGlyph bake(Function<SheetGlyphInfo, BakedGlyph> p_231120_) {
return p_231120_.apply(new SheetGlyphInfo() {
public int getPixelWidth() {
return Glyph.this.width;
}
public int getPixelHeight() {
return Glyph.this.height;
}
public float getOversample() {
return TrueTypeGlyphProvider.this.oversample;
}
public float getBearingX() {
return Glyph.this.bearingX;
}
public float getBearingY() {
return Glyph.this.bearingY;
}
public void upload(int p_231126_, int p_231127_) {
STBTTFontinfo stbttfontinfo = TrueTypeGlyphProvider.this.validateFontOpen();
NativeImage nativeimage = new NativeImage(NativeImage.Format.LUMINANCE, Glyph.this.width, Glyph.this.height, false);
nativeimage.copyFromFont(stbttfontinfo, Glyph.this.index, Glyph.this.width, Glyph.this.height, TrueTypeGlyphProvider.this.pointScale, TrueTypeGlyphProvider.this.pointScale, TrueTypeGlyphProvider.this.shiftX, TrueTypeGlyphProvider.this.shiftY, 0, 0);
nativeimage.upload(0, p_231126_, p_231127_, 0, 0, Glyph.this.width, Glyph.this.height, false, true);
}
public boolean isColored() {
return false;
}
});
}
}
}
@@ -0,0 +1,11 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
@OnlyIn(Dist.CLIENT)
package com.mojang.blaze3d.font;
import com.mojang.blaze3d.FieldsAreNonnullByDefault;
import com.mojang.blaze3d.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -0,0 +1,9 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
@OnlyIn(Dist.CLIENT)
package com.mojang.blaze3d;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -0,0 +1,148 @@
package com.mojang.blaze3d.pipeline;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.platform.TextureUtil;
import com.mojang.blaze3d.systems.RenderSystem;
import java.nio.IntBuffer;
import java.util.List;
import java.util.Objects;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class MainTarget extends RenderTarget {
public static final int DEFAULT_WIDTH = 854;
public static final int DEFAULT_HEIGHT = 480;
static final MainTarget.Dimension DEFAULT_DIMENSIONS = new MainTarget.Dimension(854, 480);
public MainTarget(int pWidth, int pHeight) {
super(true);
RenderSystem.assertOnRenderThreadOrInit();
if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(() -> {
this.createFrameBuffer(pWidth, pHeight);
});
} else {
this.createFrameBuffer(pWidth, pHeight);
}
}
private void createFrameBuffer(int pWidth, int pHeight) {
RenderSystem.assertOnRenderThreadOrInit();
MainTarget.Dimension maintarget$dimension = this.allocateAttachments(pWidth, pHeight);
this.frameBufferId = GlStateManager.glGenFramebuffers();
GlStateManager._glBindFramebuffer(36160, this.frameBufferId);
GlStateManager._bindTexture(this.colorTextureId);
GlStateManager._texParameter(3553, 10241, 9728);
GlStateManager._texParameter(3553, 10240, 9728);
GlStateManager._texParameter(3553, 10242, 33071);
GlStateManager._texParameter(3553, 10243, 33071);
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, this.colorTextureId, 0);
GlStateManager._bindTexture(this.depthBufferId);
GlStateManager._texParameter(3553, 34892, 0);
GlStateManager._texParameter(3553, 10241, 9728);
GlStateManager._texParameter(3553, 10240, 9728);
GlStateManager._texParameter(3553, 10242, 33071);
GlStateManager._texParameter(3553, 10243, 33071);
GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, this.depthBufferId, 0);
GlStateManager._bindTexture(0);
this.viewWidth = maintarget$dimension.width;
this.viewHeight = maintarget$dimension.height;
this.width = maintarget$dimension.width;
this.height = maintarget$dimension.height;
this.checkStatus();
GlStateManager._glBindFramebuffer(36160, 0);
}
private MainTarget.Dimension allocateAttachments(int pWidth, int pHeight) {
RenderSystem.assertOnRenderThreadOrInit();
this.colorTextureId = TextureUtil.generateTextureId();
this.depthBufferId = TextureUtil.generateTextureId();
MainTarget.AttachmentState maintarget$attachmentstate = MainTarget.AttachmentState.NONE;
for(MainTarget.Dimension maintarget$dimension : MainTarget.Dimension.listWithFallback(pWidth, pHeight)) {
maintarget$attachmentstate = MainTarget.AttachmentState.NONE;
if (this.allocateColorAttachment(maintarget$dimension)) {
maintarget$attachmentstate = maintarget$attachmentstate.with(MainTarget.AttachmentState.COLOR);
}
if (this.allocateDepthAttachment(maintarget$dimension)) {
maintarget$attachmentstate = maintarget$attachmentstate.with(MainTarget.AttachmentState.DEPTH);
}
if (maintarget$attachmentstate == MainTarget.AttachmentState.COLOR_DEPTH) {
return maintarget$dimension;
}
}
throw new RuntimeException("Unrecoverable GL_OUT_OF_MEMORY (allocated attachments = " + maintarget$attachmentstate.name() + ")");
}
private boolean allocateColorAttachment(MainTarget.Dimension pDimension) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._getError();
GlStateManager._bindTexture(this.colorTextureId);
GlStateManager._texImage2D(3553, 0, 32856, pDimension.width, pDimension.height, 0, 6408, 5121, (IntBuffer)null);
return GlStateManager._getError() != 1285;
}
private boolean allocateDepthAttachment(MainTarget.Dimension pDimension) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._getError();
GlStateManager._bindTexture(this.depthBufferId);
GlStateManager._texImage2D(3553, 0, 6402, pDimension.width, pDimension.height, 0, 6402, 5126, (IntBuffer)null);
return GlStateManager._getError() != 1285;
}
@OnlyIn(Dist.CLIENT)
static enum AttachmentState {
NONE,
COLOR,
DEPTH,
COLOR_DEPTH;
private static final MainTarget.AttachmentState[] VALUES = values();
MainTarget.AttachmentState with(MainTarget.AttachmentState pOtherState) {
return VALUES[this.ordinal() | pOtherState.ordinal()];
}
}
@OnlyIn(Dist.CLIENT)
static class Dimension {
public final int width;
public final int height;
Dimension(int pWidth, int pHeight) {
this.width = pWidth;
this.height = pHeight;
}
static List<MainTarget.Dimension> listWithFallback(int pWidth, int pHeight) {
RenderSystem.assertOnRenderThreadOrInit();
int i = RenderSystem.maxSupportedTextureSize();
return pWidth > 0 && pWidth <= i && pHeight > 0 && pHeight <= i ? ImmutableList.of(new MainTarget.Dimension(pWidth, pHeight), MainTarget.DEFAULT_DIMENSIONS) : ImmutableList.of(MainTarget.DEFAULT_DIMENSIONS);
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else if (pOther != null && this.getClass() == pOther.getClass()) {
MainTarget.Dimension maintarget$dimension = (MainTarget.Dimension)pOther;
return this.width == maintarget$dimension.width && this.height == maintarget$dimension.height;
} else {
return false;
}
}
public int hashCode() {
return Objects.hash(this.width, this.height);
}
public String toString() {
return this.width + "x" + this.height;
}
}
}
@@ -0,0 +1,9 @@
package com.mojang.blaze3d.pipeline;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public interface RenderCall {
void execute();
}
@@ -0,0 +1,97 @@
package com.mojang.blaze3d.pipeline;
import com.google.common.collect.ImmutableList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class RenderPipeline {
private final List<ConcurrentLinkedQueue<RenderCall>> renderCalls = ImmutableList.of(new ConcurrentLinkedQueue<>(), new ConcurrentLinkedQueue<>(), new ConcurrentLinkedQueue<>(), new ConcurrentLinkedQueue<>());
private volatile boolean isRecording;
private volatile int recordingBuffer;
private volatile boolean isProcessing;
private volatile int processedBuffer;
private volatile int renderingBuffer;
public RenderPipeline() {
this.recordingBuffer = this.processedBuffer = this.renderingBuffer + 1;
}
public boolean canBeginRecording() {
return !this.isRecording && this.recordingBuffer == this.processedBuffer;
}
public boolean beginRecording() {
if (this.isRecording) {
throw new RuntimeException("ALREADY RECORDING !!!");
} else if (this.canBeginRecording()) {
this.recordingBuffer = (this.processedBuffer + 1) % this.renderCalls.size();
this.isRecording = true;
return true;
} else {
return false;
}
}
public void recordRenderCall(RenderCall pRenderCall) {
if (!this.isRecording) {
throw new RuntimeException("NOT RECORDING !!!");
} else {
ConcurrentLinkedQueue<RenderCall> concurrentlinkedqueue = this.getRecordingQueue();
concurrentlinkedqueue.add(pRenderCall);
}
}
public void endRecording() {
if (this.isRecording) {
this.isRecording = false;
} else {
throw new RuntimeException("NOT RECORDING !!!");
}
}
public boolean canBeginProcessing() {
return !this.isProcessing && this.recordingBuffer != this.processedBuffer;
}
public boolean beginProcessing() {
if (this.isProcessing) {
throw new RuntimeException("ALREADY PROCESSING !!!");
} else if (this.canBeginProcessing()) {
this.isProcessing = true;
return true;
} else {
return false;
}
}
public void processRecordedQueue() {
if (!this.isProcessing) {
throw new RuntimeException("NOT PROCESSING !!!");
}
}
public void endProcessing() {
if (this.isProcessing) {
this.isProcessing = false;
this.renderingBuffer = this.processedBuffer;
this.processedBuffer = this.recordingBuffer;
} else {
throw new RuntimeException("NOT PROCESSING !!!");
}
}
public ConcurrentLinkedQueue<RenderCall> startRendering() {
return this.renderCalls.get(this.renderingBuffer);
}
public ConcurrentLinkedQueue<RenderCall> getRecordingQueue() {
return this.renderCalls.get(this.recordingBuffer);
}
public ConcurrentLinkedQueue<RenderCall> getProcessedQueue() {
return this.renderCalls.get(this.processedBuffer);
}
}
@@ -0,0 +1,328 @@
package com.mojang.blaze3d.pipeline;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.platform.TextureUtil;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.BufferUploader;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.blaze3d.vertex.VertexSorting;
import java.nio.IntBuffer;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
@OnlyIn(Dist.CLIENT)
public abstract class RenderTarget {
private static final int RED_CHANNEL = 0;
private static final int GREEN_CHANNEL = 1;
private static final int BLUE_CHANNEL = 2;
private static final int ALPHA_CHANNEL = 3;
public int width;
public int height;
public int viewWidth;
public int viewHeight;
public final boolean useDepth;
public int frameBufferId;
protected int colorTextureId;
protected int depthBufferId;
private final float[] clearChannels = Util.make(() -> {
return new float[]{1.0F, 1.0F, 1.0F, 0.0F};
});
public int filterMode;
public RenderTarget(boolean pUseDepth) {
this.useDepth = pUseDepth;
this.frameBufferId = -1;
this.colorTextureId = -1;
this.depthBufferId = -1;
}
public void resize(int pWidth, int pHeight, boolean pClearError) {
if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(() -> {
this._resize(pWidth, pHeight, pClearError);
});
} else {
this._resize(pWidth, pHeight, pClearError);
}
}
private void _resize(int pWidth, int pHeight, boolean pClearError) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._enableDepthTest();
if (this.frameBufferId >= 0) {
this.destroyBuffers();
}
this.createBuffers(pWidth, pHeight, pClearError);
GlStateManager._glBindFramebuffer(36160, 0);
}
public void destroyBuffers() {
RenderSystem.assertOnRenderThreadOrInit();
this.unbindRead();
this.unbindWrite();
if (this.depthBufferId > -1) {
TextureUtil.releaseTextureId(this.depthBufferId);
this.depthBufferId = -1;
}
if (this.colorTextureId > -1) {
TextureUtil.releaseTextureId(this.colorTextureId);
this.colorTextureId = -1;
}
if (this.frameBufferId > -1) {
GlStateManager._glBindFramebuffer(36160, 0);
GlStateManager._glDeleteFramebuffers(this.frameBufferId);
this.frameBufferId = -1;
}
}
public void copyDepthFrom(RenderTarget pOtherTarget) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._glBindFramebuffer(36008, pOtherTarget.frameBufferId);
GlStateManager._glBindFramebuffer(36009, this.frameBufferId);
GlStateManager._glBlitFrameBuffer(0, 0, pOtherTarget.width, pOtherTarget.height, 0, 0, this.width, this.height, 256, 9728);
GlStateManager._glBindFramebuffer(36160, 0);
}
public void createBuffers(int pWidth, int pHeight, boolean pClearError) {
RenderSystem.assertOnRenderThreadOrInit();
int i = RenderSystem.maxSupportedTextureSize();
if (pWidth > 0 && pWidth <= i && pHeight > 0 && pHeight <= i) {
this.viewWidth = pWidth;
this.viewHeight = pHeight;
this.width = pWidth;
this.height = pHeight;
this.frameBufferId = GlStateManager.glGenFramebuffers();
this.colorTextureId = TextureUtil.generateTextureId();
if (this.useDepth) {
this.depthBufferId = TextureUtil.generateTextureId();
GlStateManager._bindTexture(this.depthBufferId);
GlStateManager._texParameter(3553, 10241, 9728);
GlStateManager._texParameter(3553, 10240, 9728);
GlStateManager._texParameter(3553, 34892, 0);
GlStateManager._texParameter(3553, 10242, 33071);
GlStateManager._texParameter(3553, 10243, 33071);
if (!stencilEnabled)
GlStateManager._texImage2D(3553, 0, 6402, this.width, this.height, 0, 6402, 5126, (IntBuffer)null);
else
GlStateManager._texImage2D(3553, 0, org.lwjgl.opengl.GL30.GL_DEPTH32F_STENCIL8, this.width, this.height, 0, org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL, org.lwjgl.opengl.GL30.GL_FLOAT_32_UNSIGNED_INT_24_8_REV, null);
}
this.setFilterMode(9728);
GlStateManager._bindTexture(this.colorTextureId);
GlStateManager._texParameter(3553, 10242, 33071);
GlStateManager._texParameter(3553, 10243, 33071);
GlStateManager._texImage2D(3553, 0, 32856, this.width, this.height, 0, 6408, 5121, (IntBuffer)null);
GlStateManager._glBindFramebuffer(36160, this.frameBufferId);
GlStateManager._glFramebufferTexture2D(36160, 36064, 3553, this.colorTextureId, 0);
if (this.useDepth) {
if(!stencilEnabled)
GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, this.depthBufferId, 0);
else if(net.minecraftforge.common.ForgeConfig.CLIENT.useCombinedDepthStencilAttachment.get()) {
GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_DEPTH_STENCIL_ATTACHMENT, 3553, this.depthBufferId, 0);
} else {
GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_DEPTH_ATTACHMENT, 3553, this.depthBufferId, 0);
GlStateManager._glFramebufferTexture2D(org.lwjgl.opengl.GL30.GL_FRAMEBUFFER, org.lwjgl.opengl.GL30.GL_STENCIL_ATTACHMENT, 3553, this.depthBufferId, 0);
}
}
this.checkStatus();
this.clear(pClearError);
this.unbindRead();
} else {
throw new IllegalArgumentException("Window " + pWidth + "x" + pHeight + " size out of bounds (max. size: " + i + ")");
}
}
public void setFilterMode(int pFilterMode) {
RenderSystem.assertOnRenderThreadOrInit();
this.filterMode = pFilterMode;
GlStateManager._bindTexture(this.colorTextureId);
GlStateManager._texParameter(3553, 10241, pFilterMode);
GlStateManager._texParameter(3553, 10240, pFilterMode);
GlStateManager._bindTexture(0);
}
public void checkStatus() {
RenderSystem.assertOnRenderThreadOrInit();
int i = GlStateManager.glCheckFramebufferStatus(36160);
if (i != 36053) {
if (i == 36054) {
throw new RuntimeException("GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT");
} else if (i == 36055) {
throw new RuntimeException("GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
} else if (i == 36059) {
throw new RuntimeException("GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER");
} else if (i == 36060) {
throw new RuntimeException("GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER");
} else if (i == 36061) {
throw new RuntimeException("GL_FRAMEBUFFER_UNSUPPORTED");
} else if (i == 1285) {
throw new RuntimeException("GL_OUT_OF_MEMORY");
} else {
throw new RuntimeException("glCheckFramebufferStatus returned unknown status:" + i);
}
}
}
public void bindRead() {
RenderSystem.assertOnRenderThread();
GlStateManager._bindTexture(this.colorTextureId);
}
public void unbindRead() {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._bindTexture(0);
}
public void bindWrite(boolean pSetViewport) {
if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(() -> {
this._bindWrite(pSetViewport);
});
} else {
this._bindWrite(pSetViewport);
}
}
private void _bindWrite(boolean pSetViewport) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._glBindFramebuffer(36160, this.frameBufferId);
if (pSetViewport) {
GlStateManager._viewport(0, 0, this.viewWidth, this.viewHeight);
}
}
public void unbindWrite() {
if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(() -> {
GlStateManager._glBindFramebuffer(36160, 0);
});
} else {
GlStateManager._glBindFramebuffer(36160, 0);
}
}
public void setClearColor(float pRed, float pGreen, float pBlue, float pAlpha) {
this.clearChannels[0] = pRed;
this.clearChannels[1] = pGreen;
this.clearChannels[2] = pBlue;
this.clearChannels[3] = pAlpha;
}
public void blitToScreen(int pWidth, int pHeight) {
this.blitToScreen(pWidth, pHeight, true);
}
public void blitToScreen(int pWidth, int pHeight, boolean pDisableBlend) {
RenderSystem.assertOnGameThreadOrInit();
if (!RenderSystem.isInInitPhase()) {
RenderSystem.recordRenderCall(() -> {
this._blitToScreen(pWidth, pHeight, pDisableBlend);
});
} else {
this._blitToScreen(pWidth, pHeight, pDisableBlend);
}
}
private void _blitToScreen(int pWidth, int pHeight, boolean pDisableBlend) {
RenderSystem.assertOnRenderThread();
GlStateManager._colorMask(true, true, true, false);
GlStateManager._disableDepthTest();
GlStateManager._depthMask(false);
GlStateManager._viewport(0, 0, pWidth, pHeight);
if (pDisableBlend) {
GlStateManager._disableBlend();
}
Minecraft minecraft = Minecraft.getInstance();
ShaderInstance shaderinstance = minecraft.gameRenderer.blitShader;
shaderinstance.setSampler("DiffuseSampler", this.colorTextureId);
Matrix4f matrix4f = (new Matrix4f()).setOrtho(0.0F, (float)pWidth, (float)pHeight, 0.0F, 1000.0F, 3000.0F);
RenderSystem.setProjectionMatrix(matrix4f, VertexSorting.ORTHOGRAPHIC_Z);
if (shaderinstance.MODEL_VIEW_MATRIX != null) {
shaderinstance.MODEL_VIEW_MATRIX.set((new Matrix4f()).translation(0.0F, 0.0F, -2000.0F));
}
if (shaderinstance.PROJECTION_MATRIX != null) {
shaderinstance.PROJECTION_MATRIX.set(matrix4f);
}
shaderinstance.apply();
float f = (float)pWidth;
float f1 = (float)pHeight;
float f2 = (float)this.viewWidth / (float)this.width;
float f3 = (float)this.viewHeight / (float)this.height;
Tesselator tesselator = RenderSystem.renderThreadTesselator();
BufferBuilder bufferbuilder = tesselator.getBuilder();
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.vertex(0.0D, (double)f1, 0.0D).uv(0.0F, 0.0F).color(255, 255, 255, 255).endVertex();
bufferbuilder.vertex((double)f, (double)f1, 0.0D).uv(f2, 0.0F).color(255, 255, 255, 255).endVertex();
bufferbuilder.vertex((double)f, 0.0D, 0.0D).uv(f2, f3).color(255, 255, 255, 255).endVertex();
bufferbuilder.vertex(0.0D, 0.0D, 0.0D).uv(0.0F, f3).color(255, 255, 255, 255).endVertex();
BufferUploader.draw(bufferbuilder.end());
shaderinstance.clear();
GlStateManager._depthMask(true);
GlStateManager._colorMask(true, true, true, true);
}
public void clear(boolean pClearError) {
RenderSystem.assertOnRenderThreadOrInit();
this.bindWrite(true);
GlStateManager._clearColor(this.clearChannels[0], this.clearChannels[1], this.clearChannels[2], this.clearChannels[3]);
int i = 16384;
if (this.useDepth) {
GlStateManager._clearDepth(1.0D);
i |= 256;
}
GlStateManager._clear(i, pClearError);
this.unbindWrite();
}
public int getColorTextureId() {
return this.colorTextureId;
}
public int getDepthTextureId() {
return this.depthBufferId;
}
/*================================ FORGE START ================================================*/
private boolean stencilEnabled = false;
/**
* Attempts to enable 8 bits of stencil buffer on this FrameBuffer.
* Modders must call this directly to set things up.
* This is to prevent the default cause where graphics cards do not support stencil bits.
* <b>Make sure to call this on the main render thread!</b>
*/
public void enableStencil() {
if(stencilEnabled) return;
stencilEnabled = true;
this.resize(viewWidth, viewHeight, net.minecraft.client.Minecraft.ON_OSX);
}
/**
* Returns wither or not this FBO has been successfully initialized with stencil bits.
* If not, and a modder wishes it to be, they must call enableStencil.
*/
public boolean isStencilEnabled() {
return this.stencilEnabled;
}
/*================================ FORGE END ================================================*/
}
@@ -0,0 +1,14 @@
package com.mojang.blaze3d.pipeline;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class TextureTarget extends RenderTarget {
public TextureTarget(int pWidth, int pHeight, boolean pUseDepth, boolean pClearError) {
super(pUseDepth);
RenderSystem.assertOnRenderThreadOrInit();
this.resize(pWidth, pHeight, pClearError);
}
}
@@ -0,0 +1,11 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
@OnlyIn(Dist.CLIENT)
package com.mojang.blaze3d.pipeline;
import com.mojang.blaze3d.FieldsAreNonnullByDefault;
import com.mojang.blaze3d.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -0,0 +1,55 @@
package com.mojang.blaze3d.platform;
import com.google.common.base.Charsets;
import java.nio.ByteBuffer;
import net.minecraft.util.StringDecomposer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWErrorCallbackI;
import org.lwjgl.system.MemoryUtil;
@OnlyIn(Dist.CLIENT)
public class ClipboardManager {
public static final int FORMAT_UNAVAILABLE = 65545;
private final ByteBuffer clipboardScratchBuffer = BufferUtils.createByteBuffer(8192);
public String getClipboard(long pWindow, GLFWErrorCallbackI pErrorCallback) {
GLFWErrorCallback glfwerrorcallback = GLFW.glfwSetErrorCallback(pErrorCallback);
String s = GLFW.glfwGetClipboardString(pWindow);
s = s != null ? StringDecomposer.filterBrokenSurrogates(s) : "";
GLFWErrorCallback glfwerrorcallback1 = GLFW.glfwSetErrorCallback(glfwerrorcallback);
if (glfwerrorcallback1 != null) {
glfwerrorcallback1.free();
}
return s;
}
private static void pushClipboard(long pWindow, ByteBuffer pBuffer, byte[] pClipboardContent) {
pBuffer.clear();
pBuffer.put(pClipboardContent);
pBuffer.put((byte)0);
pBuffer.flip();
GLFW.glfwSetClipboardString(pWindow, pBuffer);
}
public void setClipboard(long pWindow, String pClipboardContent) {
byte[] abyte = pClipboardContent.getBytes(Charsets.UTF_8);
int i = abyte.length + 1;
if (i < this.clipboardScratchBuffer.capacity()) {
pushClipboard(pWindow, this.clipboardScratchBuffer, abyte);
} else {
ByteBuffer bytebuffer = MemoryUtil.memAlloc(i);
try {
pushClipboard(pWindow, bytebuffer, abyte);
} finally {
MemoryUtil.memFree(bytebuffer);
}
}
}
}
@@ -0,0 +1,43 @@
package com.mojang.blaze3d.platform;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.system.Pointer;
@OnlyIn(Dist.CLIENT)
public class DebugMemoryUntracker {
@Nullable
private static final MethodHandle UNTRACK = GLX.make(() -> {
try {
MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> oclass = Class.forName("org.lwjgl.system.MemoryManage$DebugAllocator");
Method method = oclass.getDeclaredMethod("untrack", Long.TYPE);
method.setAccessible(true);
Field field = Class.forName("org.lwjgl.system.MemoryUtil$LazyInit").getDeclaredField("ALLOCATOR");
field.setAccessible(true);
Object object = field.get((Object)null);
return oclass.isInstance(object) ? lookup.unreflect(method) : null;
} catch (NoSuchMethodException | NoSuchFieldException | IllegalAccessException | ClassNotFoundException classnotfoundexception) {
throw new RuntimeException(classnotfoundexception);
}
});
public static void untrack(long pMemAddr) {
if (UNTRACK != null) {
try {
UNTRACK.invoke(pMemAddr);
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
}
public static void untrack(Pointer pPointer) {
untrack(pPointer.address());
}
}
@@ -0,0 +1,22 @@
package com.mojang.blaze3d.platform;
import java.util.OptionalInt;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class DisplayData {
public final int width;
public final int height;
public final OptionalInt fullscreenWidth;
public final OptionalInt fullscreenHeight;
public final boolean isFullscreen;
public DisplayData(int pWidth, int pHeight, OptionalInt pFullscreenWidth, OptionalInt pFullscreenHeight, boolean pIsFullscreen) {
this.width = pWidth;
this.height = pHeight;
this.fullscreenWidth = pFullscreenWidth;
this.fullscreenHeight = pFullscreenHeight;
this.isFullscreen = pIsFullscreen;
}
}
@@ -0,0 +1,166 @@
package com.mojang.blaze3d.platform;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.DontObfuscate;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import com.mojang.logging.LogUtils;
import java.util.List;
import java.util.Locale;
import java.util.function.Consumer;
import java.util.function.LongSupplier;
import java.util.function.Supplier;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.Version;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWErrorCallbackI;
import org.lwjgl.glfw.GLFWVidMode;
import org.slf4j.Logger;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
@OnlyIn(Dist.CLIENT)
@DontObfuscate
public class GLX {
private static final Logger LOGGER = LogUtils.getLogger();
private static String cpuInfo;
public static String getOpenGLVersionString() {
RenderSystem.assertOnRenderThread();
return GLFW.glfwGetCurrentContext() == 0L ? "NO CONTEXT" : GlStateManager._getString(7937) + " GL version " + GlStateManager._getString(7938) + ", " + GlStateManager._getString(7936);
}
public static int _getRefreshRate(Window pWindow) {
RenderSystem.assertOnRenderThread();
long i = GLFW.glfwGetWindowMonitor(pWindow.getWindow());
if (i == 0L) {
i = GLFW.glfwGetPrimaryMonitor();
}
GLFWVidMode glfwvidmode = i == 0L ? null : GLFW.glfwGetVideoMode(i);
return glfwvidmode == null ? 0 : glfwvidmode.refreshRate();
}
public static String _getLWJGLVersion() {
RenderSystem.assertInInitPhase();
return Version.getVersion();
}
public static LongSupplier _initGlfw() {
RenderSystem.assertInInitPhase();
Window.checkGlfwError((p_242032_, p_242033_) -> {
throw new IllegalStateException(String.format(Locale.ROOT, "GLFW error before init: [0x%X]%s", p_242032_, p_242033_));
});
List<String> list = Lists.newArrayList();
GLFWErrorCallback glfwerrorcallback = GLFW.glfwSetErrorCallback((p_69365_, p_69366_) -> {
list.add(String.format(Locale.ROOT, "GLFW error during init: [0x%X]%s", p_69365_, p_69366_));
});
if (!GLFW.glfwInit()) {
throw new IllegalStateException("Failed to initialize GLFW, errors: " + Joiner.on(",").join(list));
} else {
LongSupplier longsupplier = () -> {
return (long)(GLFW.glfwGetTime() * 1.0E9D);
};
for(String s : list) {
LOGGER.error("GLFW error collected during initialization: {}", (Object)s);
}
RenderSystem.setErrorCallback(glfwerrorcallback);
return longsupplier;
}
}
public static void _setGlfwErrorCallback(GLFWErrorCallbackI pErrorCallback) {
RenderSystem.assertInInitPhase();
GLFWErrorCallback glfwerrorcallback = GLFW.glfwSetErrorCallback(pErrorCallback);
if (glfwerrorcallback != null) {
glfwerrorcallback.free();
}
}
public static boolean _shouldClose(Window pWindow) {
return GLFW.glfwWindowShouldClose(pWindow.getWindow());
}
public static void _init(int pDebugVerbosity, boolean pSynchronous) {
RenderSystem.assertInInitPhase();
try {
CentralProcessor centralprocessor = (new SystemInfo()).getHardware().getProcessor();
cpuInfo = String.format(Locale.ROOT, "%dx %s", centralprocessor.getLogicalProcessorCount(), centralprocessor.getProcessorIdentifier().getName()).replaceAll("\\s+", " ");
} catch (Throwable throwable) {
}
GlDebug.enableDebugCallback(pDebugVerbosity, pSynchronous);
}
public static String _getCpuInfo() {
return cpuInfo == null ? "<unknown>" : cpuInfo;
}
public static void _renderCrosshair(int pLineLength, boolean pRenderX, boolean pRenderY, boolean pRenderZ) {
RenderSystem.assertOnRenderThread();
GlStateManager._depthMask(false);
GlStateManager._disableCull();
RenderSystem.setShader(GameRenderer::getRendertypeLinesShader);
Tesselator tesselator = RenderSystem.renderThreadTesselator();
BufferBuilder bufferbuilder = tesselator.getBuilder();
RenderSystem.lineWidth(4.0F);
bufferbuilder.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL);
if (pRenderX) {
bufferbuilder.vertex(0.0D, 0.0D, 0.0D).color(0, 0, 0, 255).normal(1.0F, 0.0F, 0.0F).endVertex();
bufferbuilder.vertex((double)pLineLength, 0.0D, 0.0D).color(0, 0, 0, 255).normal(1.0F, 0.0F, 0.0F).endVertex();
}
if (pRenderY) {
bufferbuilder.vertex(0.0D, 0.0D, 0.0D).color(0, 0, 0, 255).normal(0.0F, 1.0F, 0.0F).endVertex();
bufferbuilder.vertex(0.0D, (double)pLineLength, 0.0D).color(0, 0, 0, 255).normal(0.0F, 1.0F, 0.0F).endVertex();
}
if (pRenderZ) {
bufferbuilder.vertex(0.0D, 0.0D, 0.0D).color(0, 0, 0, 255).normal(0.0F, 0.0F, 1.0F).endVertex();
bufferbuilder.vertex(0.0D, 0.0D, (double)pLineLength).color(0, 0, 0, 255).normal(0.0F, 0.0F, 1.0F).endVertex();
}
tesselator.end();
RenderSystem.lineWidth(2.0F);
bufferbuilder.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL);
if (pRenderX) {
bufferbuilder.vertex(0.0D, 0.0D, 0.0D).color(255, 0, 0, 255).normal(1.0F, 0.0F, 0.0F).endVertex();
bufferbuilder.vertex((double)pLineLength, 0.0D, 0.0D).color(255, 0, 0, 255).normal(1.0F, 0.0F, 0.0F).endVertex();
}
if (pRenderY) {
bufferbuilder.vertex(0.0D, 0.0D, 0.0D).color(0, 255, 0, 255).normal(0.0F, 1.0F, 0.0F).endVertex();
bufferbuilder.vertex(0.0D, (double)pLineLength, 0.0D).color(0, 255, 0, 255).normal(0.0F, 1.0F, 0.0F).endVertex();
}
if (pRenderZ) {
bufferbuilder.vertex(0.0D, 0.0D, 0.0D).color(127, 127, 255, 255).normal(0.0F, 0.0F, 1.0F).endVertex();
bufferbuilder.vertex(0.0D, 0.0D, (double)pLineLength).color(127, 127, 255, 255).normal(0.0F, 0.0F, 1.0F).endVertex();
}
tesselator.end();
RenderSystem.lineWidth(1.0F);
GlStateManager._enableCull();
GlStateManager._depthMask(true);
}
public static <T> T make(Supplier<T> pSupplier) {
return pSupplier.get();
}
public static <T> T make(T pValue, Consumer<T> pConsumer) {
pConsumer.accept(pValue);
return pValue;
}
}
@@ -0,0 +1,109 @@
package com.mojang.blaze3d.platform;
import com.mojang.blaze3d.DontObfuscate;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
@DontObfuscate
public class GlConst {
public static final int GL_READ_FRAMEBUFFER = 36008;
public static final int GL_DRAW_FRAMEBUFFER = 36009;
public static final int GL_TRUE = 1;
public static final int GL_FALSE = 0;
public static final int GL_NONE = 0;
public static final int GL_LINES = 1;
public static final int GL_LINE_STRIP = 3;
public static final int GL_TRIANGLE_STRIP = 5;
public static final int GL_TRIANGLE_FAN = 6;
public static final int GL_TRIANGLES = 4;
public static final int GL_WRITE_ONLY = 35001;
public static final int GL_EQUAL = 514;
public static final int GL_LEQUAL = 515;
public static final int GL_GREATER = 516;
public static final int GL_GEQUAL = 518;
public static final int GL_ALWAYS = 519;
public static final int GL_TEXTURE_MAG_FILTER = 10240;
public static final int GL_TEXTURE_MIN_FILTER = 10241;
public static final int GL_TEXTURE_WRAP_S = 10242;
public static final int GL_TEXTURE_WRAP_T = 10243;
public static final int GL_NEAREST = 9728;
public static final int GL_LINEAR = 9729;
public static final int GL_NEAREST_MIPMAP_LINEAR = 9986;
public static final int GL_LINEAR_MIPMAP_LINEAR = 9987;
public static final int GL_CLAMP_TO_EDGE = 33071;
public static final int GL_FRONT = 1028;
public static final int GL_FRONT_AND_BACK = 1032;
public static final int GL_LINE = 6913;
public static final int GL_FILL = 6914;
public static final int GL_BYTE = 5120;
public static final int GL_UNSIGNED_BYTE = 5121;
public static final int GL_SHORT = 5122;
public static final int GL_UNSIGNED_SHORT = 5123;
public static final int GL_INT = 5124;
public static final int GL_UNSIGNED_INT = 5125;
public static final int GL_FLOAT = 5126;
public static final int GL_ZERO = 0;
public static final int GL_ONE = 1;
public static final int GL_SRC_COLOR = 768;
public static final int GL_ONE_MINUS_SRC_COLOR = 769;
public static final int GL_SRC_ALPHA = 770;
public static final int GL_ONE_MINUS_SRC_ALPHA = 771;
public static final int GL_DST_ALPHA = 772;
public static final int GL_ONE_MINUS_DST_ALPHA = 773;
public static final int GL_DST_COLOR = 774;
public static final int GL_ONE_MINUS_DST_COLOR = 775;
public static final int GL_REPLACE = 7681;
public static final int GL_DEPTH_BUFFER_BIT = 256;
public static final int GL_COLOR_BUFFER_BIT = 16384;
public static final int GL_RGBA8 = 32856;
public static final int GL_PROXY_TEXTURE_2D = 32868;
public static final int GL_RGBA = 6408;
public static final int GL_TEXTURE_WIDTH = 4096;
public static final int GL_BGR = 32992;
public static final int GL_FUNC_ADD = 32774;
public static final int GL_MIN = 32775;
public static final int GL_MAX = 32776;
public static final int GL_FUNC_SUBTRACT = 32778;
public static final int GL_FUNC_REVERSE_SUBTRACT = 32779;
public static final int GL_DEPTH_COMPONENT24 = 33190;
public static final int GL_STATIC_DRAW = 35044;
public static final int GL_DYNAMIC_DRAW = 35048;
public static final int GL_UNPACK_SWAP_BYTES = 3312;
public static final int GL_UNPACK_LSB_FIRST = 3313;
public static final int GL_UNPACK_ROW_LENGTH = 3314;
public static final int GL_UNPACK_SKIP_ROWS = 3315;
public static final int GL_UNPACK_SKIP_PIXELS = 3316;
public static final int GL_UNPACK_ALIGNMENT = 3317;
public static final int GL_PACK_ALIGNMENT = 3333;
public static final int GL_MAX_TEXTURE_SIZE = 3379;
public static final int GL_TEXTURE_2D = 3553;
public static final int GL_DEPTH_COMPONENT = 6402;
public static final int GL_DEPTH_COMPONENT32 = 33191;
public static final int GL_FRAMEBUFFER = 36160;
public static final int GL_RENDERBUFFER = 36161;
public static final int GL_COLOR_ATTACHMENT0 = 36064;
public static final int GL_DEPTH_ATTACHMENT = 36096;
public static final int GL_FRAMEBUFFER_COMPLETE = 36053;
public static final int GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 36054;
public static final int GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 36055;
public static final int GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER = 36059;
public static final int GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER = 36060;
public static final int GL_FRAMEBUFFER_UNSUPPORTED = 36061;
public static final int GL_LINK_STATUS = 35714;
public static final int GL_COMPILE_STATUS = 35713;
public static final int GL_VERTEX_SHADER = 35633;
public static final int GL_FRAGMENT_SHADER = 35632;
public static final int GL_TEXTURE0 = 33984;
public static final int GL_TEXTURE1 = 33985;
public static final int GL_TEXTURE2 = 33986;
public static final int GL_DEPTH_TEXTURE_MODE = 34891;
public static final int GL_TEXTURE_COMPARE_MODE = 34892;
public static final int GL_ARRAY_BUFFER = 34962;
public static final int GL_ELEMENT_ARRAY_BUFFER = 34963;
public static final int GL_ALPHA_BIAS = 3357;
public static final int GL_RGB = 6407;
public static final int GL_RG = 33319;
public static final int GL_RED = 6403;
public static final int GL_OUT_OF_MEMORY = 1285;
}
@@ -0,0 +1,194 @@
package com.mojang.blaze3d.platform;
import com.google.common.collect.EvictingQueue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.logging.LogUtils;
import java.util.List;
import java.util.Queue;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.opengl.ARBDebugOutput;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GLCapabilities;
import org.lwjgl.opengl.GLDebugMessageARBCallback;
import org.lwjgl.opengl.GLDebugMessageCallback;
import org.lwjgl.opengl.KHRDebug;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class GlDebug {
private static final Logger LOGGER = LogUtils.getLogger();
private static final int CIRCULAR_LOG_SIZE = 10;
private static final Queue<GlDebug.LogEntry> MESSAGE_BUFFER = EvictingQueue.create(10);
@Nullable
private static volatile GlDebug.LogEntry lastEntry;
private static final List<Integer> DEBUG_LEVELS = ImmutableList.of(37190, 37191, 37192, 33387);
private static final List<Integer> DEBUG_LEVELS_ARB = ImmutableList.of(37190, 37191, 37192);
private static boolean debugEnabled;
private static String printUnknownToken(int pToken) {
return "Unknown (0x" + Integer.toHexString(pToken).toUpperCase() + ")";
}
public static String sourceToString(int pSource) {
switch (pSource) {
case 33350:
return "API";
case 33351:
return "WINDOW SYSTEM";
case 33352:
return "SHADER COMPILER";
case 33353:
return "THIRD PARTY";
case 33354:
return "APPLICATION";
case 33355:
return "OTHER";
default:
return printUnknownToken(pSource);
}
}
public static String typeToString(int pType) {
switch (pType) {
case 33356:
return "ERROR";
case 33357:
return "DEPRECATED BEHAVIOR";
case 33358:
return "UNDEFINED BEHAVIOR";
case 33359:
return "PORTABILITY";
case 33360:
return "PERFORMANCE";
case 33361:
return "OTHER";
case 33384:
return "MARKER";
default:
return printUnknownToken(pType);
}
}
public static String severityToString(int pSeverity) {
switch (pSeverity) {
case 33387:
return "NOTIFICATION";
case 37190:
return "HIGH";
case 37191:
return "MEDIUM";
case 37192:
return "LOW";
default:
return printUnknownToken(pSeverity);
}
}
/**
*
* @param p_84039_ The GLenum source represented as an ordinal integer.
* @param p_84040_ The GLenum type represented as an ordinal integer.
* @param p_84041_ The unbounded integer id of the message callback.
* @param p_84042_ The GLenum severity represented as an ordinal integer.
* @param p_84043_ The {@link org.lwjgl.opengl.GLDebugMessageCallback} length argument.
* @param p_84044_ The {@link org.lwjgl.opengl.GLDebugMessageCallback} message argument
* @param p_84045_ A user supplied pointer that will be passed on each invocation of callback.
*/
private static void printDebugLog(int p_84039_, int p_84040_, int p_84041_, int p_84042_, int p_84043_, long p_84044_, long p_84045_) {
String s = GLDebugMessageCallback.getMessage(p_84043_, p_84044_);
GlDebug.LogEntry gldebug$logentry;
synchronized(MESSAGE_BUFFER) {
gldebug$logentry = lastEntry;
if (gldebug$logentry != null && gldebug$logentry.isSame(p_84039_, p_84040_, p_84041_, p_84042_, s)) {
++gldebug$logentry.count;
} else {
gldebug$logentry = new GlDebug.LogEntry(p_84039_, p_84040_, p_84041_, p_84042_, s);
MESSAGE_BUFFER.add(gldebug$logentry);
lastEntry = gldebug$logentry;
}
}
LOGGER.info("OpenGL debug message: {}", (Object)gldebug$logentry);
}
public static List<String> getLastOpenGlDebugMessages() {
synchronized(MESSAGE_BUFFER) {
List<String> list = Lists.newArrayListWithCapacity(MESSAGE_BUFFER.size());
for(GlDebug.LogEntry gldebug$logentry : MESSAGE_BUFFER) {
list.add(gldebug$logentry + " x " + gldebug$logentry.count);
}
return list;
}
}
public static boolean isDebugEnabled() {
return debugEnabled;
}
public static void enableDebugCallback(int pDebugVerbosity, boolean pSynchronous) {
RenderSystem.assertInInitPhase();
if (pDebugVerbosity > 0) {
GLCapabilities glcapabilities = GL.getCapabilities();
if (glcapabilities.GL_KHR_debug) {
debugEnabled = true;
GL11.glEnable(37600);
if (pSynchronous) {
GL11.glEnable(33346);
}
for(int i = 0; i < DEBUG_LEVELS.size(); ++i) {
boolean flag = i < pDebugVerbosity;
KHRDebug.glDebugMessageControl(4352, 4352, DEBUG_LEVELS.get(i), (int[])null, flag);
}
KHRDebug.glDebugMessageCallback(GLX.make(GLDebugMessageCallback.create(GlDebug::printDebugLog), DebugMemoryUntracker::untrack), 0L);
} else if (glcapabilities.GL_ARB_debug_output) {
debugEnabled = true;
if (pSynchronous) {
GL11.glEnable(33346);
}
for(int j = 0; j < DEBUG_LEVELS_ARB.size(); ++j) {
boolean flag1 = j < pDebugVerbosity;
ARBDebugOutput.glDebugMessageControlARB(4352, 4352, DEBUG_LEVELS_ARB.get(j), (int[])null, flag1);
}
ARBDebugOutput.glDebugMessageCallbackARB(GLX.make(GLDebugMessageARBCallback.create(GlDebug::printDebugLog), DebugMemoryUntracker::untrack), 0L);
}
}
}
@OnlyIn(Dist.CLIENT)
static class LogEntry {
private final int id;
private final int source;
private final int type;
private final int severity;
private final String message;
int count = 1;
LogEntry(int pSource, int pType, int pId, int pSeverity, String pMessage) {
this.id = pId;
this.source = pSource;
this.type = pType;
this.severity = pSeverity;
this.message = pMessage;
}
boolean isSame(int pSource, int pType, int pId, int pSeverity, String pMessage) {
return pType == this.type && pSource == this.source && pId == this.id && pSeverity == this.severity && pMessage.equals(this.message);
}
public String toString() {
return "id=" + this.id + ", source=" + GlDebug.sourceToString(this.source) + ", type=" + GlDebug.typeToString(this.type) + ", severity=" + GlDebug.severityToString(this.severity) + ", message='" + this.message + "'";
}
}
}
@@ -0,0 +1,954 @@
package com.mojang.blaze3d.platform;
import com.google.common.base.Charsets;
import com.mojang.blaze3d.DontObfuscate;
import com.mojang.blaze3d.systems.RenderSystem;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.List;
import java.util.function.Consumer;
import java.util.stream.IntStream;
import javax.annotation.Nullable;
import net.minecraft.Util;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import org.lwjgl.PointerBuffer;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.opengl.GL14;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.opengl.GL20C;
import org.lwjgl.opengl.GL30;
import org.lwjgl.opengl.GL32C;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
@OnlyIn(Dist.CLIENT)
@DontObfuscate
public class GlStateManager {
private static final boolean ON_LINUX = Util.getPlatform() == Util.OS.LINUX;
public static final int TEXTURE_COUNT = 12;
private static final GlStateManager.BlendState BLEND = new GlStateManager.BlendState();
private static final GlStateManager.DepthState DEPTH = new GlStateManager.DepthState();
private static final GlStateManager.CullState CULL = new GlStateManager.CullState();
private static final GlStateManager.PolygonOffsetState POLY_OFFSET = new GlStateManager.PolygonOffsetState();
private static final GlStateManager.ColorLogicState COLOR_LOGIC = new GlStateManager.ColorLogicState();
private static final GlStateManager.StencilState STENCIL = new GlStateManager.StencilState();
private static final GlStateManager.ScissorState SCISSOR = new GlStateManager.ScissorState();
private static int activeTexture;
private static final GlStateManager.TextureState[] TEXTURES = IntStream.range(0, 12).mapToObj((p_157120_) -> {
return new GlStateManager.TextureState();
}).toArray((p_157122_) -> {
return new GlStateManager.TextureState[p_157122_];
});
private static final GlStateManager.ColorMask COLOR_MASK = new GlStateManager.ColorMask();
public static void _disableScissorTest() {
RenderSystem.assertOnRenderThreadOrInit();
SCISSOR.mode.disable();
}
public static void _enableScissorTest() {
RenderSystem.assertOnRenderThreadOrInit();
SCISSOR.mode.enable();
}
public static void _scissorBox(int pX, int pY, int pWidth, int pHeight) {
RenderSystem.assertOnRenderThreadOrInit();
GL20.glScissor(pX, pY, pWidth, pHeight);
}
public static void _disableDepthTest() {
RenderSystem.assertOnRenderThreadOrInit();
DEPTH.mode.disable();
}
public static void _enableDepthTest() {
RenderSystem.assertOnRenderThreadOrInit();
DEPTH.mode.enable();
}
public static void _depthFunc(int pDepthFunc) {
RenderSystem.assertOnRenderThreadOrInit();
if (pDepthFunc != DEPTH.func) {
DEPTH.func = pDepthFunc;
GL11.glDepthFunc(pDepthFunc);
}
}
public static void _depthMask(boolean pFlag) {
RenderSystem.assertOnRenderThread();
if (pFlag != DEPTH.mask) {
DEPTH.mask = pFlag;
GL11.glDepthMask(pFlag);
}
}
public static void _disableBlend() {
RenderSystem.assertOnRenderThread();
BLEND.mode.disable();
}
public static void _enableBlend() {
RenderSystem.assertOnRenderThread();
BLEND.mode.enable();
}
public static void _blendFunc(int pSourceFactor, int pDestFactor) {
RenderSystem.assertOnRenderThread();
if (pSourceFactor != BLEND.srcRgb || pDestFactor != BLEND.dstRgb) {
BLEND.srcRgb = pSourceFactor;
BLEND.dstRgb = pDestFactor;
GL11.glBlendFunc(pSourceFactor, pDestFactor);
}
}
public static void _blendFuncSeparate(int pSrcFactor, int pDstFactor, int pSrcFactorAlpha, int pDstFactorAlpha) {
RenderSystem.assertOnRenderThread();
if (pSrcFactor != BLEND.srcRgb || pDstFactor != BLEND.dstRgb || pSrcFactorAlpha != BLEND.srcAlpha || pDstFactorAlpha != BLEND.dstAlpha) {
BLEND.srcRgb = pSrcFactor;
BLEND.dstRgb = pDstFactor;
BLEND.srcAlpha = pSrcFactorAlpha;
BLEND.dstAlpha = pDstFactorAlpha;
glBlendFuncSeparate(pSrcFactor, pDstFactor, pSrcFactorAlpha, pDstFactorAlpha);
}
}
public static void _blendEquation(int pMode) {
RenderSystem.assertOnRenderThread();
GL14.glBlendEquation(pMode);
}
public static int glGetProgrami(int pProgram, int pPname) {
RenderSystem.assertOnRenderThread();
return GL20.glGetProgrami(pProgram, pPname);
}
public static void glAttachShader(int pProgram, int pShader) {
RenderSystem.assertOnRenderThread();
GL20.glAttachShader(pProgram, pShader);
}
public static void glDeleteShader(int pShader) {
RenderSystem.assertOnRenderThread();
GL20.glDeleteShader(pShader);
}
public static int glCreateShader(int pType) {
RenderSystem.assertOnRenderThread();
return GL20.glCreateShader(pType);
}
public static void glShaderSource(int pShader, List<String> pShaderData) {
RenderSystem.assertOnRenderThread();
StringBuilder stringbuilder = new StringBuilder();
for(String s : pShaderData) {
stringbuilder.append(s);
}
byte[] abyte = stringbuilder.toString().getBytes(Charsets.UTF_8);
ByteBuffer bytebuffer = MemoryUtil.memAlloc(abyte.length + 1);
bytebuffer.put(abyte);
bytebuffer.put((byte)0);
bytebuffer.flip();
try (MemoryStack memorystack = MemoryStack.stackPush()) {
PointerBuffer pointerbuffer = memorystack.mallocPointer(1);
pointerbuffer.put(bytebuffer);
GL20C.nglShaderSource(pShader, 1, pointerbuffer.address0(), 0L);
} finally {
MemoryUtil.memFree(bytebuffer);
}
}
public static void glCompileShader(int pShader) {
RenderSystem.assertOnRenderThread();
GL20.glCompileShader(pShader);
}
public static int glGetShaderi(int pShader, int pPname) {
RenderSystem.assertOnRenderThread();
return GL20.glGetShaderi(pShader, pPname);
}
public static void _glUseProgram(int pProgram) {
RenderSystem.assertOnRenderThread();
GL20.glUseProgram(pProgram);
}
public static int glCreateProgram() {
RenderSystem.assertOnRenderThread();
return GL20.glCreateProgram();
}
public static void glDeleteProgram(int pProgram) {
RenderSystem.assertOnRenderThread();
GL20.glDeleteProgram(pProgram);
}
public static void glLinkProgram(int pProgram) {
RenderSystem.assertOnRenderThread();
GL20.glLinkProgram(pProgram);
}
public static int _glGetUniformLocation(int pProgram, CharSequence pName) {
RenderSystem.assertOnRenderThread();
return GL20.glGetUniformLocation(pProgram, pName);
}
public static void _glUniform1(int pLocation, IntBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniform1iv(pLocation, pValue);
}
public static void _glUniform1i(int pLocation, int pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniform1i(pLocation, pValue);
}
public static void _glUniform1(int pLocation, FloatBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniform1fv(pLocation, pValue);
}
public static void _glUniform2(int pLocation, IntBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniform2iv(pLocation, pValue);
}
public static void _glUniform2(int pLocation, FloatBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniform2fv(pLocation, pValue);
}
public static void _glUniform3(int pLocation, IntBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniform3iv(pLocation, pValue);
}
public static void _glUniform3(int pLocation, FloatBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniform3fv(pLocation, pValue);
}
public static void _glUniform4(int pLocation, IntBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniform4iv(pLocation, pValue);
}
public static void _glUniform4(int pLocation, FloatBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniform4fv(pLocation, pValue);
}
public static void _glUniformMatrix2(int pLocation, boolean pTranspose, FloatBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniformMatrix2fv(pLocation, pTranspose, pValue);
}
public static void _glUniformMatrix3(int pLocation, boolean pTranspose, FloatBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniformMatrix3fv(pLocation, pTranspose, pValue);
}
public static void _glUniformMatrix4(int pLocation, boolean pTranspose, FloatBuffer pValue) {
RenderSystem.assertOnRenderThread();
GL20.glUniformMatrix4fv(pLocation, pTranspose, pValue);
}
public static int _glGetAttribLocation(int pProgram, CharSequence pName) {
RenderSystem.assertOnRenderThread();
return GL20.glGetAttribLocation(pProgram, pName);
}
public static void _glBindAttribLocation(int pProgram, int pIndex, CharSequence pName) {
RenderSystem.assertOnRenderThread();
GL20.glBindAttribLocation(pProgram, pIndex, pName);
}
public static int _glGenBuffers() {
RenderSystem.assertOnRenderThreadOrInit();
return GL15.glGenBuffers();
}
public static int _glGenVertexArrays() {
RenderSystem.assertOnRenderThreadOrInit();
return GL30.glGenVertexArrays();
}
public static void _glBindBuffer(int pTarget, int pBuffer) {
RenderSystem.assertOnRenderThreadOrInit();
GL15.glBindBuffer(pTarget, pBuffer);
}
public static void _glBindVertexArray(int pArray) {
RenderSystem.assertOnRenderThreadOrInit();
GL30.glBindVertexArray(pArray);
}
public static void _glBufferData(int pTarget, ByteBuffer pData, int pUsage) {
RenderSystem.assertOnRenderThreadOrInit();
GL15.glBufferData(pTarget, pData, pUsage);
}
public static void _glBufferData(int pTarget, long pSize, int pUsage) {
RenderSystem.assertOnRenderThreadOrInit();
GL15.glBufferData(pTarget, pSize, pUsage);
}
@Nullable
public static ByteBuffer _glMapBuffer(int pTarget, int pAccess) {
RenderSystem.assertOnRenderThreadOrInit();
return GL15.glMapBuffer(pTarget, pAccess);
}
public static void _glUnmapBuffer(int pTarget) {
RenderSystem.assertOnRenderThreadOrInit();
GL15.glUnmapBuffer(pTarget);
}
public static void _glDeleteBuffers(int pBuffer) {
RenderSystem.assertOnRenderThread();
if (ON_LINUX) {
GL32C.glBindBuffer(34962, pBuffer);
GL32C.glBufferData(34962, 0L, 35048);
GL32C.glBindBuffer(34962, 0);
}
GL15.glDeleteBuffers(pBuffer);
}
public static void _glCopyTexSubImage2D(int pTarget, int pLevel, int pXOffset, int pYOffset, int pX, int pY, int pWidth, int pHeight) {
RenderSystem.assertOnRenderThreadOrInit();
GL20.glCopyTexSubImage2D(pTarget, pLevel, pXOffset, pYOffset, pX, pY, pWidth, pHeight);
}
public static void _glDeleteVertexArrays(int pArray) {
RenderSystem.assertOnRenderThread();
GL30.glDeleteVertexArrays(pArray);
}
public static void _glBindFramebuffer(int pTarget, int pFramebuffer) {
RenderSystem.assertOnRenderThreadOrInit();
GL30.glBindFramebuffer(pTarget, pFramebuffer);
}
public static void _glBlitFrameBuffer(int pSrcX0, int pSrcY0, int pSrcX1, int pSrcY1, int pDstX0, int pDstY0, int pDstX1, int pDstY1, int pMask, int pFilter) {
RenderSystem.assertOnRenderThreadOrInit();
GL30.glBlitFramebuffer(pSrcX0, pSrcY0, pSrcX1, pSrcY1, pDstX0, pDstY0, pDstX1, pDstY1, pMask, pFilter);
}
public static void _glBindRenderbuffer(int pTarget, int pRenderBuffer) {
RenderSystem.assertOnRenderThreadOrInit();
GL30.glBindRenderbuffer(pTarget, pRenderBuffer);
}
public static void _glDeleteRenderbuffers(int pRenderBuffer) {
RenderSystem.assertOnRenderThreadOrInit();
GL30.glDeleteRenderbuffers(pRenderBuffer);
}
public static void _glDeleteFramebuffers(int pFrameBuffer) {
RenderSystem.assertOnRenderThreadOrInit();
GL30.glDeleteFramebuffers(pFrameBuffer);
}
public static int glGenFramebuffers() {
RenderSystem.assertOnRenderThreadOrInit();
return GL30.glGenFramebuffers();
}
public static int glGenRenderbuffers() {
RenderSystem.assertOnRenderThreadOrInit();
return GL30.glGenRenderbuffers();
}
public static void _glRenderbufferStorage(int pTarget, int pInternalFormat, int pWidth, int pHeight) {
RenderSystem.assertOnRenderThreadOrInit();
GL30.glRenderbufferStorage(pTarget, pInternalFormat, pWidth, pHeight);
}
public static void _glFramebufferRenderbuffer(int pTarget, int pAttachment, int pRenderBufferTarget, int pRenderBuffer) {
RenderSystem.assertOnRenderThreadOrInit();
GL30.glFramebufferRenderbuffer(pTarget, pAttachment, pRenderBufferTarget, pRenderBuffer);
}
public static int glCheckFramebufferStatus(int pTarget) {
RenderSystem.assertOnRenderThreadOrInit();
return GL30.glCheckFramebufferStatus(pTarget);
}
public static void _glFramebufferTexture2D(int pTarget, int pAttachment, int pTexTarget, int pTexture, int pLevel) {
RenderSystem.assertOnRenderThreadOrInit();
GL30.glFramebufferTexture2D(pTarget, pAttachment, pTexTarget, pTexture, pLevel);
}
public static int getBoundFramebuffer() {
RenderSystem.assertOnRenderThread();
return _getInteger(36006);
}
public static void glActiveTexture(int pTexture) {
RenderSystem.assertOnRenderThread();
GL13.glActiveTexture(pTexture);
}
public static void glBlendFuncSeparate(int pSFactorRGB, int pDFactorRGB, int pSFactorAlpha, int pDFactorAlpha) {
RenderSystem.assertOnRenderThread();
GL14.glBlendFuncSeparate(pSFactorRGB, pDFactorRGB, pSFactorAlpha, pDFactorAlpha);
}
public static String glGetShaderInfoLog(int pShader, int pMaxLength) {
RenderSystem.assertOnRenderThread();
return GL20.glGetShaderInfoLog(pShader, pMaxLength);
}
public static String glGetProgramInfoLog(int pProgram, int pMaxLength) {
RenderSystem.assertOnRenderThread();
return GL20.glGetProgramInfoLog(pProgram, pMaxLength);
}
public static void setupLevelDiffuseLighting(Vector3f pLightingVector1, Vector3f pLightingVector2, Matrix4f pMatrix) {
RenderSystem.assertOnRenderThread();
Vector4f vector4f = pMatrix.transform(new Vector4f(pLightingVector1, 1.0F));
Vector4f vector4f1 = pMatrix.transform(new Vector4f(pLightingVector2, 1.0F));
RenderSystem.setShaderLights(new Vector3f(vector4f.x(), vector4f.y(), vector4f.z()), new Vector3f(vector4f1.x(), vector4f1.y(), vector4f1.z()));
}
public static void setupGuiFlatDiffuseLighting(Vector3f pLightingVector1, Vector3f pLightingVector2) {
RenderSystem.assertOnRenderThread();
Matrix4f matrix4f = (new Matrix4f()).scaling(1.0F, -1.0F, 1.0F).rotateY((-(float)Math.PI / 8F)).rotateX(2.3561945F);
setupLevelDiffuseLighting(pLightingVector1, pLightingVector2, matrix4f);
}
public static void setupGui3DDiffuseLighting(Vector3f pLightingVector1, Vector3f pLightingVector2) {
RenderSystem.assertOnRenderThread();
Matrix4f matrix4f = (new Matrix4f()).rotationYXZ(1.0821041F, 3.2375858F, 0.0F).rotateYXZ((-(float)Math.PI / 8F), 2.3561945F, 0.0F);
setupLevelDiffuseLighting(pLightingVector1, pLightingVector2, matrix4f);
}
public static void _enableCull() {
RenderSystem.assertOnRenderThread();
CULL.enable.enable();
}
public static void _disableCull() {
RenderSystem.assertOnRenderThread();
CULL.enable.disable();
}
public static void _polygonMode(int pFace, int pMode) {
RenderSystem.assertOnRenderThread();
GL11.glPolygonMode(pFace, pMode);
}
public static void _enablePolygonOffset() {
RenderSystem.assertOnRenderThread();
POLY_OFFSET.fill.enable();
}
public static void _disablePolygonOffset() {
RenderSystem.assertOnRenderThread();
POLY_OFFSET.fill.disable();
}
public static void _polygonOffset(float pFactor, float pUnits) {
RenderSystem.assertOnRenderThread();
if (pFactor != POLY_OFFSET.factor || pUnits != POLY_OFFSET.units) {
POLY_OFFSET.factor = pFactor;
POLY_OFFSET.units = pUnits;
GL11.glPolygonOffset(pFactor, pUnits);
}
}
public static void _enableColorLogicOp() {
RenderSystem.assertOnRenderThread();
COLOR_LOGIC.enable.enable();
}
public static void _disableColorLogicOp() {
RenderSystem.assertOnRenderThread();
COLOR_LOGIC.enable.disable();
}
public static void _logicOp(int pLogicOperation) {
RenderSystem.assertOnRenderThread();
if (pLogicOperation != COLOR_LOGIC.op) {
COLOR_LOGIC.op = pLogicOperation;
GL11.glLogicOp(pLogicOperation);
}
}
public static void _activeTexture(int pTexture) {
RenderSystem.assertOnRenderThread();
if (activeTexture != pTexture - '\u84c0') {
activeTexture = pTexture - '\u84c0';
glActiveTexture(pTexture);
}
}
/* Stores the last values sent into glMultiTexCoord2f */
public static float lastBrightnessX = 0.0f;
public static float lastBrightnessY = 0.0f;
public static void _texParameter(int pTarget, int pParameterName, float pParameter) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glTexParameterf(pTarget, pParameterName, pParameter);
if (pTarget == GL13.GL_TEXTURE1) {
lastBrightnessX = pParameterName;
lastBrightnessY = pParameter;
}
}
public static void _texParameter(int pTarget, int pParameterName, int pParameter) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glTexParameteri(pTarget, pParameterName, pParameter);
}
public static int _getTexLevelParameter(int pTarget, int pLevel, int pParameterName) {
RenderSystem.assertInInitPhase();
return GL11.glGetTexLevelParameteri(pTarget, pLevel, pParameterName);
}
public static int _genTexture() {
RenderSystem.assertOnRenderThreadOrInit();
return GL11.glGenTextures();
}
public static void _genTextures(int[] pTextures) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glGenTextures(pTextures);
}
public static void _deleteTexture(int pTexture) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glDeleteTextures(pTexture);
for(GlStateManager.TextureState glstatemanager$texturestate : TEXTURES) {
if (glstatemanager$texturestate.binding == pTexture) {
glstatemanager$texturestate.binding = -1;
}
}
}
public static void _deleteTextures(int[] pTextures) {
RenderSystem.assertOnRenderThreadOrInit();
for(GlStateManager.TextureState glstatemanager$texturestate : TEXTURES) {
for(int i : pTextures) {
if (glstatemanager$texturestate.binding == i) {
glstatemanager$texturestate.binding = -1;
}
}
}
GL11.glDeleteTextures(pTextures);
}
public static void _bindTexture(int pTexture) {
RenderSystem.assertOnRenderThreadOrInit();
if (pTexture != TEXTURES[activeTexture].binding) {
TEXTURES[activeTexture].binding = pTexture;
GL11.glBindTexture(3553, pTexture);
}
}
public static int _getActiveTexture() {
return activeTexture + '\u84c0';
}
public static void _texImage2D(int pTarget, int pLevel, int pInternalFormat, int pWidth, int pHeight, int pBorder, int pFormat, int pType, @Nullable IntBuffer pPixels) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glTexImage2D(pTarget, pLevel, pInternalFormat, pWidth, pHeight, pBorder, pFormat, pType, pPixels);
}
public static void _texSubImage2D(int pTarget, int pLevel, int pXOffset, int pYOffset, int pWidth, int pHeight, int pFormat, int pType, long pPixels) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glTexSubImage2D(pTarget, pLevel, pXOffset, pYOffset, pWidth, pHeight, pFormat, pType, pPixels);
}
public static void upload(int pLevel, int pXOffset, int pYOffset, int pWidth, int pHeight, NativeImage.Format pFormat, IntBuffer pPixels, Consumer<IntBuffer> pOutput) {
if (!RenderSystem.isOnRenderThreadOrInit()) {
RenderSystem.recordRenderCall(() -> {
_upload(pLevel, pXOffset, pYOffset, pWidth, pHeight, pFormat, pPixels, pOutput);
});
} else {
_upload(pLevel, pXOffset, pYOffset, pWidth, pHeight, pFormat, pPixels, pOutput);
}
}
private static void _upload(int pLevel, int pXOffset, int pYOffset, int pWidth, int pHeight, NativeImage.Format pFormat, IntBuffer pPixels, Consumer<IntBuffer> pOutput) {
try {
RenderSystem.assertOnRenderThreadOrInit();
_pixelStore(3314, pWidth);
_pixelStore(3316, 0);
_pixelStore(3315, 0);
pFormat.setUnpackPixelStoreState();
GL11.glTexSubImage2D(3553, pLevel, pXOffset, pYOffset, pWidth, pHeight, pFormat.glFormat(), 5121, pPixels);
} finally {
pOutput.accept(pPixels);
}
}
public static void _getTexImage(int pTex, int pLevel, int pFormat, int pType, long pPixels) {
RenderSystem.assertOnRenderThread();
GL11.glGetTexImage(pTex, pLevel, pFormat, pType, pPixels);
}
public static void _viewport(int pX, int pY, int pWidth, int pHeight) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager.Viewport.INSTANCE.x = pX;
GlStateManager.Viewport.INSTANCE.y = pY;
GlStateManager.Viewport.INSTANCE.width = pWidth;
GlStateManager.Viewport.INSTANCE.height = pHeight;
GL11.glViewport(pX, pY, pWidth, pHeight);
}
public static void _colorMask(boolean pRed, boolean pGreen, boolean pBlue, boolean pAlpha) {
RenderSystem.assertOnRenderThread();
if (pRed != COLOR_MASK.red || pGreen != COLOR_MASK.green || pBlue != COLOR_MASK.blue || pAlpha != COLOR_MASK.alpha) {
COLOR_MASK.red = pRed;
COLOR_MASK.green = pGreen;
COLOR_MASK.blue = pBlue;
COLOR_MASK.alpha = pAlpha;
GL11.glColorMask(pRed, pGreen, pBlue, pAlpha);
}
}
public static void _stencilFunc(int pFunc, int pRef, int pMask) {
RenderSystem.assertOnRenderThread();
if (pFunc != STENCIL.func.func || pFunc != STENCIL.func.ref || pFunc != STENCIL.func.mask) {
STENCIL.func.func = pFunc;
STENCIL.func.ref = pRef;
STENCIL.func.mask = pMask;
GL11.glStencilFunc(pFunc, pRef, pMask);
}
}
public static void _stencilMask(int pMask) {
RenderSystem.assertOnRenderThread();
if (pMask != STENCIL.mask) {
STENCIL.mask = pMask;
GL11.glStencilMask(pMask);
}
}
public static void _stencilOp(int pSfail, int pDpfail, int pDppass) {
RenderSystem.assertOnRenderThread();
if (pSfail != STENCIL.fail || pDpfail != STENCIL.zfail || pDppass != STENCIL.zpass) {
STENCIL.fail = pSfail;
STENCIL.zfail = pDpfail;
STENCIL.zpass = pDppass;
GL11.glStencilOp(pSfail, pDpfail, pDppass);
}
}
public static void _clearDepth(double pDepth) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glClearDepth(pDepth);
}
public static void _clearColor(float pRed, float pGreen, float pBlue, float pAlpha) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glClearColor(pRed, pGreen, pBlue, pAlpha);
}
public static void _clearStencil(int pIndex) {
RenderSystem.assertOnRenderThread();
GL11.glClearStencil(pIndex);
}
public static void _clear(int pMask, boolean pCheckError) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glClear(pMask);
if (pCheckError) {
_getError();
}
}
public static void _glDrawPixels(int pWidth, int pHeight, int pFormat, int pType, long pPixels) {
RenderSystem.assertOnRenderThread();
GL11.glDrawPixels(pWidth, pHeight, pFormat, pType, pPixels);
}
public static void _vertexAttribPointer(int pIndex, int pSize, int pType, boolean pNormalized, int pStride, long pPointer) {
RenderSystem.assertOnRenderThread();
GL20.glVertexAttribPointer(pIndex, pSize, pType, pNormalized, pStride, pPointer);
}
public static void _vertexAttribIPointer(int pIndex, int pSize, int pType, int pStride, long pPointer) {
RenderSystem.assertOnRenderThread();
GL30.glVertexAttribIPointer(pIndex, pSize, pType, pStride, pPointer);
}
public static void _enableVertexAttribArray(int pIndex) {
RenderSystem.assertOnRenderThread();
GL20.glEnableVertexAttribArray(pIndex);
}
public static void _disableVertexAttribArray(int pIndex) {
RenderSystem.assertOnRenderThread();
GL20.glDisableVertexAttribArray(pIndex);
}
public static void _drawElements(int pMode, int pCount, int pType, long pIndices) {
RenderSystem.assertOnRenderThread();
GL11.glDrawElements(pMode, pCount, pType, pIndices);
}
public static void _pixelStore(int pParameterName, int pParam) {
RenderSystem.assertOnRenderThreadOrInit();
GL11.glPixelStorei(pParameterName, pParam);
}
public static void _readPixels(int pX, int pY, int pWidth, int pHeight, int pFormat, int pType, ByteBuffer pPixels) {
RenderSystem.assertOnRenderThread();
GL11.glReadPixels(pX, pY, pWidth, pHeight, pFormat, pType, pPixels);
}
public static void _readPixels(int pX, int pY, int pWidth, int pHeight, int pFormat, int pType, long pPixels) {
RenderSystem.assertOnRenderThread();
GL11.glReadPixels(pX, pY, pWidth, pHeight, pFormat, pType, pPixels);
}
public static int _getError() {
RenderSystem.assertOnRenderThread();
return GL11.glGetError();
}
public static String _getString(int pName) {
RenderSystem.assertOnRenderThread();
return GL11.glGetString(pName);
}
public static int _getInteger(int pPname) {
RenderSystem.assertOnRenderThreadOrInit();
return GL11.glGetInteger(pPname);
}
@OnlyIn(Dist.CLIENT)
static class BlendState {
public final GlStateManager.BooleanState mode = new GlStateManager.BooleanState(3042);
public int srcRgb = 1;
public int dstRgb = 0;
public int srcAlpha = 1;
public int dstAlpha = 0;
}
@OnlyIn(Dist.CLIENT)
static class BooleanState {
private final int state;
private boolean enabled;
public BooleanState(int pState) {
this.state = pState;
}
public void disable() {
this.setEnabled(false);
}
public void enable() {
this.setEnabled(true);
}
public void setEnabled(boolean pEnabled) {
RenderSystem.assertOnRenderThreadOrInit();
if (pEnabled != this.enabled) {
this.enabled = pEnabled;
if (pEnabled) {
GL11.glEnable(this.state);
} else {
GL11.glDisable(this.state);
}
}
}
}
@OnlyIn(Dist.CLIENT)
static class ColorLogicState {
public final GlStateManager.BooleanState enable = new GlStateManager.BooleanState(3058);
public int op = 5379;
}
@OnlyIn(Dist.CLIENT)
static class ColorMask {
public boolean red = true;
public boolean green = true;
public boolean blue = true;
public boolean alpha = true;
}
@OnlyIn(Dist.CLIENT)
static class CullState {
public final GlStateManager.BooleanState enable = new GlStateManager.BooleanState(2884);
public int mode = 1029;
}
@OnlyIn(Dist.CLIENT)
static class DepthState {
public final GlStateManager.BooleanState mode = new GlStateManager.BooleanState(2929);
public boolean mask = true;
public int func = 513;
}
@OnlyIn(Dist.CLIENT)
@DontObfuscate
public static enum DestFactor {
CONSTANT_ALPHA(32771),
CONSTANT_COLOR(32769),
DST_ALPHA(772),
DST_COLOR(774),
ONE(1),
ONE_MINUS_CONSTANT_ALPHA(32772),
ONE_MINUS_CONSTANT_COLOR(32770),
ONE_MINUS_DST_ALPHA(773),
ONE_MINUS_DST_COLOR(775),
ONE_MINUS_SRC_ALPHA(771),
ONE_MINUS_SRC_COLOR(769),
SRC_ALPHA(770),
SRC_COLOR(768),
ZERO(0);
public final int value;
private DestFactor(int pValue) {
this.value = pValue;
}
}
@OnlyIn(Dist.CLIENT)
public static enum LogicOp {
AND(5377),
AND_INVERTED(5380),
AND_REVERSE(5378),
CLEAR(5376),
COPY(5379),
COPY_INVERTED(5388),
EQUIV(5385),
INVERT(5386),
NAND(5390),
NOOP(5381),
NOR(5384),
OR(5383),
OR_INVERTED(5389),
OR_REVERSE(5387),
SET(5391),
XOR(5382);
public final int value;
private LogicOp(int pValue) {
this.value = pValue;
}
}
@OnlyIn(Dist.CLIENT)
static class PolygonOffsetState {
public final GlStateManager.BooleanState fill = new GlStateManager.BooleanState(32823);
public final GlStateManager.BooleanState line = new GlStateManager.BooleanState(10754);
public float factor;
public float units;
}
@OnlyIn(Dist.CLIENT)
static class ScissorState {
public final GlStateManager.BooleanState mode = new GlStateManager.BooleanState(3089);
}
@OnlyIn(Dist.CLIENT)
@DontObfuscate
public static enum SourceFactor {
CONSTANT_ALPHA(32771),
CONSTANT_COLOR(32769),
DST_ALPHA(772),
DST_COLOR(774),
ONE(1),
ONE_MINUS_CONSTANT_ALPHA(32772),
ONE_MINUS_CONSTANT_COLOR(32770),
ONE_MINUS_DST_ALPHA(773),
ONE_MINUS_DST_COLOR(775),
ONE_MINUS_SRC_ALPHA(771),
ONE_MINUS_SRC_COLOR(769),
SRC_ALPHA(770),
SRC_ALPHA_SATURATE(776),
SRC_COLOR(768),
ZERO(0);
public final int value;
private SourceFactor(int pValue) {
this.value = pValue;
}
}
@OnlyIn(Dist.CLIENT)
static class StencilFunc {
public int func = 519;
public int ref;
public int mask = -1;
}
@OnlyIn(Dist.CLIENT)
static class StencilState {
public final GlStateManager.StencilFunc func = new GlStateManager.StencilFunc();
public int mask = -1;
public int fail = 7680;
public int zfail = 7680;
public int zpass = 7680;
}
@OnlyIn(Dist.CLIENT)
static class TextureState {
public int binding;
}
@OnlyIn(Dist.CLIENT)
public static enum Viewport {
INSTANCE;
protected int x;
protected int y;
protected int width;
protected int height;
public static int x() {
return INSTANCE.x;
}
public static int y() {
return INSTANCE.y;
}
public static int width() {
return INSTANCE.width;
}
public static int height() {
return INSTANCE.height;
}
}
}
@@ -0,0 +1,34 @@
package com.mojang.blaze3d.platform;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.system.MemoryUtil;
@OnlyIn(Dist.CLIENT)
public class GlUtil {
public static ByteBuffer allocateMemory(int pSize) {
return MemoryUtil.memAlloc(pSize);
}
public static void freeMemory(Buffer pBuffer) {
MemoryUtil.memFree(pBuffer);
}
public static String getVendor() {
return GlStateManager._getString(7936);
}
public static String getCpuInfo() {
return GLX._getCpuInfo();
}
public static String getRenderer() {
return GlStateManager._getString(7937);
}
public static String getOpenGLVersion() {
return GlStateManager._getString(7938);
}
}
@@ -0,0 +1,41 @@
package com.mojang.blaze3d.platform;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.resources.IoSupplier;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.commons.lang3.ArrayUtils;
@OnlyIn(Dist.CLIENT)
public enum IconSet {
RELEASE("icons"),
SNAPSHOT("icons", "snapshot");
private final String[] path;
private IconSet(String... pPath) {
this.path = pPath;
}
public List<IoSupplier<InputStream>> getStandardIcons(PackResources pResources) throws IOException {
return List.of(this.getFile(pResources, "icon_16x16.png"), this.getFile(pResources, "icon_32x32.png"), this.getFile(pResources, "icon_48x48.png"), this.getFile(pResources, "icon_128x128.png"), this.getFile(pResources, "icon_256x256.png"));
}
public IoSupplier<InputStream> getMacIcon(PackResources pResources) throws IOException {
return this.getFile(pResources, "minecraft.icns");
}
private IoSupplier<InputStream> getFile(PackResources pResources, String pFilename) throws IOException {
String[] astring = ArrayUtils.add(this.path, pFilename);
IoSupplier<InputStream> iosupplier = pResources.getRootResource(astring);
if (iosupplier == null) {
throw new FileNotFoundException(String.join("/", astring));
} else {
return iosupplier;
}
}
}
@@ -0,0 +1,479 @@
package com.mojang.blaze3d.platform;
import com.google.common.collect.Maps;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.OptionalInt;
import java.util.function.BiFunction;
import javax.annotation.Nullable;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.Component;
import net.minecraft.util.LazyLoadedValue;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWCharModsCallbackI;
import org.lwjgl.glfw.GLFWCursorPosCallbackI;
import org.lwjgl.glfw.GLFWDropCallbackI;
import org.lwjgl.glfw.GLFWKeyCallbackI;
import org.lwjgl.glfw.GLFWMouseButtonCallbackI;
import org.lwjgl.glfw.GLFWScrollCallbackI;
@OnlyIn(Dist.CLIENT)
public class InputConstants {
@Nullable
private static final MethodHandle GLFW_RAW_MOUSE_MOTION_SUPPORTED;
private static final int GLFW_RAW_MOUSE_MOTION;
public static final int KEY_0 = 48;
public static final int KEY_1 = 49;
public static final int KEY_2 = 50;
public static final int KEY_3 = 51;
public static final int KEY_4 = 52;
public static final int KEY_5 = 53;
public static final int KEY_6 = 54;
public static final int KEY_7 = 55;
public static final int KEY_8 = 56;
public static final int KEY_9 = 57;
public static final int KEY_A = 65;
public static final int KEY_B = 66;
public static final int KEY_C = 67;
public static final int KEY_D = 68;
public static final int KEY_E = 69;
public static final int KEY_F = 70;
public static final int KEY_G = 71;
public static final int KEY_H = 72;
public static final int KEY_I = 73;
public static final int KEY_J = 74;
public static final int KEY_K = 75;
public static final int KEY_L = 76;
public static final int KEY_M = 77;
public static final int KEY_N = 78;
public static final int KEY_O = 79;
public static final int KEY_P = 80;
public static final int KEY_Q = 81;
public static final int KEY_R = 82;
public static final int KEY_S = 83;
public static final int KEY_T = 84;
public static final int KEY_U = 85;
public static final int KEY_V = 86;
public static final int KEY_W = 87;
public static final int KEY_X = 88;
public static final int KEY_Y = 89;
public static final int KEY_Z = 90;
public static final int KEY_F1 = 290;
public static final int KEY_F2 = 291;
public static final int KEY_F3 = 292;
public static final int KEY_F4 = 293;
public static final int KEY_F5 = 294;
public static final int KEY_F6 = 295;
public static final int KEY_F7 = 296;
public static final int KEY_F8 = 297;
public static final int KEY_F9 = 298;
public static final int KEY_F10 = 299;
public static final int KEY_F11 = 300;
public static final int KEY_F12 = 301;
public static final int KEY_F13 = 302;
public static final int KEY_F14 = 303;
public static final int KEY_F15 = 304;
public static final int KEY_F16 = 305;
public static final int KEY_F17 = 306;
public static final int KEY_F18 = 307;
public static final int KEY_F19 = 308;
public static final int KEY_F20 = 309;
public static final int KEY_F21 = 310;
public static final int KEY_F22 = 311;
public static final int KEY_F23 = 312;
public static final int KEY_F24 = 313;
public static final int KEY_F25 = 314;
public static final int KEY_NUMLOCK = 282;
public static final int KEY_NUMPAD0 = 320;
public static final int KEY_NUMPAD1 = 321;
public static final int KEY_NUMPAD2 = 322;
public static final int KEY_NUMPAD3 = 323;
public static final int KEY_NUMPAD4 = 324;
public static final int KEY_NUMPAD5 = 325;
public static final int KEY_NUMPAD6 = 326;
public static final int KEY_NUMPAD7 = 327;
public static final int KEY_NUMPAD8 = 328;
public static final int KEY_NUMPAD9 = 329;
public static final int KEY_NUMPADCOMMA = 330;
public static final int KEY_NUMPADENTER = 335;
public static final int KEY_NUMPADEQUALS = 336;
public static final int KEY_DOWN = 264;
public static final int KEY_LEFT = 263;
public static final int KEY_RIGHT = 262;
public static final int KEY_UP = 265;
public static final int KEY_ADD = 334;
public static final int KEY_APOSTROPHE = 39;
public static final int KEY_BACKSLASH = 92;
public static final int KEY_COMMA = 44;
public static final int KEY_EQUALS = 61;
public static final int KEY_GRAVE = 96;
public static final int KEY_LBRACKET = 91;
public static final int KEY_MINUS = 45;
public static final int KEY_MULTIPLY = 332;
public static final int KEY_PERIOD = 46;
public static final int KEY_RBRACKET = 93;
public static final int KEY_SEMICOLON = 59;
public static final int KEY_SLASH = 47;
public static final int KEY_SPACE = 32;
public static final int KEY_TAB = 258;
public static final int KEY_LALT = 342;
public static final int KEY_LCONTROL = 341;
public static final int KEY_LSHIFT = 340;
public static final int KEY_LWIN = 343;
public static final int KEY_RALT = 346;
public static final int KEY_RCONTROL = 345;
public static final int KEY_RSHIFT = 344;
public static final int KEY_RWIN = 347;
public static final int KEY_RETURN = 257;
public static final int KEY_ESCAPE = 256;
public static final int KEY_BACKSPACE = 259;
public static final int KEY_DELETE = 261;
public static final int KEY_END = 269;
public static final int KEY_HOME = 268;
public static final int KEY_INSERT = 260;
public static final int KEY_PAGEDOWN = 267;
public static final int KEY_PAGEUP = 266;
public static final int KEY_CAPSLOCK = 280;
public static final int KEY_PAUSE = 284;
public static final int KEY_SCROLLLOCK = 281;
public static final int KEY_PRINTSCREEN = 283;
public static final int PRESS = 1;
public static final int RELEASE = 0;
public static final int REPEAT = 2;
public static final int MOUSE_BUTTON_LEFT = 0;
public static final int MOUSE_BUTTON_MIDDLE = 2;
public static final int MOUSE_BUTTON_RIGHT = 1;
public static final int MOD_CONTROL = 2;
public static final int CURSOR = 208897;
public static final int CURSOR_DISABLED = 212995;
public static final int CURSOR_NORMAL = 212993;
public static final InputConstants.Key UNKNOWN;
public static InputConstants.Key getKey(int pKeyCode, int pScanCode) {
return pKeyCode == -1 ? InputConstants.Type.SCANCODE.getOrCreate(pScanCode) : InputConstants.Type.KEYSYM.getOrCreate(pKeyCode);
}
public static InputConstants.Key getKey(String pName) {
if (InputConstants.Key.NAME_MAP.containsKey(pName)) {
return InputConstants.Key.NAME_MAP.get(pName);
} else {
for(InputConstants.Type inputconstants$type : InputConstants.Type.values()) {
if (pName.startsWith(inputconstants$type.defaultPrefix)) {
String s = pName.substring(inputconstants$type.defaultPrefix.length() + 1);
int i = Integer.parseInt(s);
if (inputconstants$type == InputConstants.Type.MOUSE) {
--i;
}
return inputconstants$type.getOrCreate(i);
}
}
throw new IllegalArgumentException("Unknown key name: " + pName);
}
}
public static boolean isKeyDown(long pWindow, int pKey) {
return GLFW.glfwGetKey(pWindow, pKey) == 1;
}
public static void setupKeyboardCallbacks(long pWindow, GLFWKeyCallbackI pKeyCallback, GLFWCharModsCallbackI pCharModifierCallback) {
GLFW.glfwSetKeyCallback(pWindow, pKeyCallback);
GLFW.glfwSetCharModsCallback(pWindow, pCharModifierCallback);
}
public static void setupMouseCallbacks(long pWindow, GLFWCursorPosCallbackI pCursorPositionCallback, GLFWMouseButtonCallbackI pMouseButtonCallback, GLFWScrollCallbackI pScrollCallback, GLFWDropCallbackI pDragAndDropCallback) {
GLFW.glfwSetCursorPosCallback(pWindow, pCursorPositionCallback);
GLFW.glfwSetMouseButtonCallback(pWindow, pMouseButtonCallback);
GLFW.glfwSetScrollCallback(pWindow, pScrollCallback);
GLFW.glfwSetDropCallback(pWindow, pDragAndDropCallback);
}
public static void grabOrReleaseMouse(long pWindow, int pCursorValue, double pXPos, double pYPos) {
GLFW.glfwSetCursorPos(pWindow, pXPos, pYPos);
GLFW.glfwSetInputMode(pWindow, 208897, pCursorValue);
}
public static boolean isRawMouseInputSupported() {
try {
return GLFW_RAW_MOUSE_MOTION_SUPPORTED != null && (boolean)GLFW_RAW_MOUSE_MOTION_SUPPORTED.invokeExact();
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
}
public static void updateRawMouseInput(long pWindow, boolean pEnableRawMouseMotion) {
if (isRawMouseInputSupported()) {
GLFW.glfwSetInputMode(pWindow, GLFW_RAW_MOUSE_MOTION, pEnableRawMouseMotion ? 1 : 0);
}
}
static {
MethodHandles.Lookup lookup = MethodHandles.lookup();
MethodType methodtype = MethodType.methodType(Boolean.TYPE);
MethodHandle methodhandle = null;
int i = 0;
try {
methodhandle = lookup.findStatic(GLFW.class, "glfwRawMouseMotionSupported", methodtype);
MethodHandle methodhandle1 = lookup.findStaticGetter(GLFW.class, "GLFW_RAW_MOUSE_MOTION", Integer.TYPE);
i = (int)methodhandle1.invokeExact();
} catch (NoSuchFieldException | NoSuchMethodException nosuchmethodexception) {
} catch (Throwable throwable) {
throw new RuntimeException(throwable);
}
GLFW_RAW_MOUSE_MOTION_SUPPORTED = methodhandle;
GLFW_RAW_MOUSE_MOTION = i;
UNKNOWN = InputConstants.Type.KEYSYM.getOrCreate(-1);
}
@OnlyIn(Dist.CLIENT)
public static final class Key {
private final String name;
private final InputConstants.Type type;
private final int value;
private final LazyLoadedValue<Component> displayName;
static final Map<String, InputConstants.Key> NAME_MAP = Maps.newHashMap();
Key(String pName, InputConstants.Type pType, int pValue) {
this.name = pName;
this.type = pType;
this.value = pValue;
this.displayName = new LazyLoadedValue<>(() -> {
return pType.displayTextSupplier.apply(pValue, pName);
});
NAME_MAP.put(pName, this);
}
public InputConstants.Type getType() {
return this.type;
}
public int getValue() {
return this.value;
}
public String getName() {
return this.name;
}
public Component getDisplayName() {
return this.displayName.get();
}
public OptionalInt getNumericKeyValue() {
if (this.value >= 48 && this.value <= 57) {
return OptionalInt.of(this.value - 48);
} else {
return this.value >= 320 && this.value <= 329 ? OptionalInt.of(this.value - 320) : OptionalInt.empty();
}
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else if (pOther != null && this.getClass() == pOther.getClass()) {
InputConstants.Key inputconstants$key = (InputConstants.Key)pOther;
return this.value == inputconstants$key.value && this.type == inputconstants$key.type;
} else {
return false;
}
}
public int hashCode() {
return Objects.hash(this.type, this.value);
}
public String toString() {
return this.name;
}
}
@OnlyIn(Dist.CLIENT)
public static enum Type {
KEYSYM("key.keyboard", (p_288232_, p_288233_) -> {
if ("key.keyboard.unknown".equals(p_288233_)) {
return Component.translatable(p_288233_);
} else {
String s = GLFW.glfwGetKeyName(p_288232_, -1);
return s != null ? Component.literal(s.toUpperCase(Locale.ROOT)) : Component.translatable(p_288233_);
}
}),
SCANCODE("scancode", (p_84911_, p_84912_) -> {
String s = GLFW.glfwGetKeyName(-1, p_84911_);
return s != null ? Component.literal(s) : Component.translatable(p_84912_);
}),
MOUSE("key.mouse", (p_84904_, p_84905_) -> {
return Language.getInstance().has(p_84905_) ? Component.translatable(p_84905_) : Component.translatable("key.mouse", p_84904_ + 1);
});
private static final String KEY_KEYBOARD_UNKNOWN = "key.keyboard.unknown";
private final Int2ObjectMap<InputConstants.Key> map = new Int2ObjectOpenHashMap<>();
final String defaultPrefix;
final BiFunction<Integer, String, Component> displayTextSupplier;
private static void addKey(InputConstants.Type pType, String pName, int pKeyCode) {
InputConstants.Key inputconstants$key = new InputConstants.Key(pName, pType, pKeyCode);
pType.map.put(pKeyCode, inputconstants$key);
}
private Type(String pDefaultPrefix, BiFunction<Integer, String, Component> pDisplayTextSupplier) {
this.defaultPrefix = pDefaultPrefix;
this.displayTextSupplier = pDisplayTextSupplier;
}
public InputConstants.Key getOrCreate(int pKeyCode) {
return this.map.computeIfAbsent(pKeyCode, (p_84907_) -> {
int i = p_84907_;
if (this == MOUSE) {
i = p_84907_ + 1;
}
String s = this.defaultPrefix + "." + i;
return new InputConstants.Key(s, this, p_84907_);
});
}
static {
addKey(KEYSYM, "key.keyboard.unknown", -1);
addKey(MOUSE, "key.mouse.left", 0);
addKey(MOUSE, "key.mouse.right", 1);
addKey(MOUSE, "key.mouse.middle", 2);
addKey(MOUSE, "key.mouse.4", 3);
addKey(MOUSE, "key.mouse.5", 4);
addKey(MOUSE, "key.mouse.6", 5);
addKey(MOUSE, "key.mouse.7", 6);
addKey(MOUSE, "key.mouse.8", 7);
addKey(KEYSYM, "key.keyboard.0", 48);
addKey(KEYSYM, "key.keyboard.1", 49);
addKey(KEYSYM, "key.keyboard.2", 50);
addKey(KEYSYM, "key.keyboard.3", 51);
addKey(KEYSYM, "key.keyboard.4", 52);
addKey(KEYSYM, "key.keyboard.5", 53);
addKey(KEYSYM, "key.keyboard.6", 54);
addKey(KEYSYM, "key.keyboard.7", 55);
addKey(KEYSYM, "key.keyboard.8", 56);
addKey(KEYSYM, "key.keyboard.9", 57);
addKey(KEYSYM, "key.keyboard.a", 65);
addKey(KEYSYM, "key.keyboard.b", 66);
addKey(KEYSYM, "key.keyboard.c", 67);
addKey(KEYSYM, "key.keyboard.d", 68);
addKey(KEYSYM, "key.keyboard.e", 69);
addKey(KEYSYM, "key.keyboard.f", 70);
addKey(KEYSYM, "key.keyboard.g", 71);
addKey(KEYSYM, "key.keyboard.h", 72);
addKey(KEYSYM, "key.keyboard.i", 73);
addKey(KEYSYM, "key.keyboard.j", 74);
addKey(KEYSYM, "key.keyboard.k", 75);
addKey(KEYSYM, "key.keyboard.l", 76);
addKey(KEYSYM, "key.keyboard.m", 77);
addKey(KEYSYM, "key.keyboard.n", 78);
addKey(KEYSYM, "key.keyboard.o", 79);
addKey(KEYSYM, "key.keyboard.p", 80);
addKey(KEYSYM, "key.keyboard.q", 81);
addKey(KEYSYM, "key.keyboard.r", 82);
addKey(KEYSYM, "key.keyboard.s", 83);
addKey(KEYSYM, "key.keyboard.t", 84);
addKey(KEYSYM, "key.keyboard.u", 85);
addKey(KEYSYM, "key.keyboard.v", 86);
addKey(KEYSYM, "key.keyboard.w", 87);
addKey(KEYSYM, "key.keyboard.x", 88);
addKey(KEYSYM, "key.keyboard.y", 89);
addKey(KEYSYM, "key.keyboard.z", 90);
addKey(KEYSYM, "key.keyboard.f1", 290);
addKey(KEYSYM, "key.keyboard.f2", 291);
addKey(KEYSYM, "key.keyboard.f3", 292);
addKey(KEYSYM, "key.keyboard.f4", 293);
addKey(KEYSYM, "key.keyboard.f5", 294);
addKey(KEYSYM, "key.keyboard.f6", 295);
addKey(KEYSYM, "key.keyboard.f7", 296);
addKey(KEYSYM, "key.keyboard.f8", 297);
addKey(KEYSYM, "key.keyboard.f9", 298);
addKey(KEYSYM, "key.keyboard.f10", 299);
addKey(KEYSYM, "key.keyboard.f11", 300);
addKey(KEYSYM, "key.keyboard.f12", 301);
addKey(KEYSYM, "key.keyboard.f13", 302);
addKey(KEYSYM, "key.keyboard.f14", 303);
addKey(KEYSYM, "key.keyboard.f15", 304);
addKey(KEYSYM, "key.keyboard.f16", 305);
addKey(KEYSYM, "key.keyboard.f17", 306);
addKey(KEYSYM, "key.keyboard.f18", 307);
addKey(KEYSYM, "key.keyboard.f19", 308);
addKey(KEYSYM, "key.keyboard.f20", 309);
addKey(KEYSYM, "key.keyboard.f21", 310);
addKey(KEYSYM, "key.keyboard.f22", 311);
addKey(KEYSYM, "key.keyboard.f23", 312);
addKey(KEYSYM, "key.keyboard.f24", 313);
addKey(KEYSYM, "key.keyboard.f25", 314);
addKey(KEYSYM, "key.keyboard.num.lock", 282);
addKey(KEYSYM, "key.keyboard.keypad.0", 320);
addKey(KEYSYM, "key.keyboard.keypad.1", 321);
addKey(KEYSYM, "key.keyboard.keypad.2", 322);
addKey(KEYSYM, "key.keyboard.keypad.3", 323);
addKey(KEYSYM, "key.keyboard.keypad.4", 324);
addKey(KEYSYM, "key.keyboard.keypad.5", 325);
addKey(KEYSYM, "key.keyboard.keypad.6", 326);
addKey(KEYSYM, "key.keyboard.keypad.7", 327);
addKey(KEYSYM, "key.keyboard.keypad.8", 328);
addKey(KEYSYM, "key.keyboard.keypad.9", 329);
addKey(KEYSYM, "key.keyboard.keypad.add", 334);
addKey(KEYSYM, "key.keyboard.keypad.decimal", 330);
addKey(KEYSYM, "key.keyboard.keypad.enter", 335);
addKey(KEYSYM, "key.keyboard.keypad.equal", 336);
addKey(KEYSYM, "key.keyboard.keypad.multiply", 332);
addKey(KEYSYM, "key.keyboard.keypad.divide", 331);
addKey(KEYSYM, "key.keyboard.keypad.subtract", 333);
addKey(KEYSYM, "key.keyboard.down", 264);
addKey(KEYSYM, "key.keyboard.left", 263);
addKey(KEYSYM, "key.keyboard.right", 262);
addKey(KEYSYM, "key.keyboard.up", 265);
addKey(KEYSYM, "key.keyboard.apostrophe", 39);
addKey(KEYSYM, "key.keyboard.backslash", 92);
addKey(KEYSYM, "key.keyboard.comma", 44);
addKey(KEYSYM, "key.keyboard.equal", 61);
addKey(KEYSYM, "key.keyboard.grave.accent", 96);
addKey(KEYSYM, "key.keyboard.left.bracket", 91);
addKey(KEYSYM, "key.keyboard.minus", 45);
addKey(KEYSYM, "key.keyboard.period", 46);
addKey(KEYSYM, "key.keyboard.right.bracket", 93);
addKey(KEYSYM, "key.keyboard.semicolon", 59);
addKey(KEYSYM, "key.keyboard.slash", 47);
addKey(KEYSYM, "key.keyboard.space", 32);
addKey(KEYSYM, "key.keyboard.tab", 258);
addKey(KEYSYM, "key.keyboard.left.alt", 342);
addKey(KEYSYM, "key.keyboard.left.control", 341);
addKey(KEYSYM, "key.keyboard.left.shift", 340);
addKey(KEYSYM, "key.keyboard.left.win", 343);
addKey(KEYSYM, "key.keyboard.right.alt", 346);
addKey(KEYSYM, "key.keyboard.right.control", 345);
addKey(KEYSYM, "key.keyboard.right.shift", 344);
addKey(KEYSYM, "key.keyboard.right.win", 347);
addKey(KEYSYM, "key.keyboard.enter", 257);
addKey(KEYSYM, "key.keyboard.escape", 256);
addKey(KEYSYM, "key.keyboard.backspace", 259);
addKey(KEYSYM, "key.keyboard.delete", 261);
addKey(KEYSYM, "key.keyboard.end", 269);
addKey(KEYSYM, "key.keyboard.home", 268);
addKey(KEYSYM, "key.keyboard.insert", 260);
addKey(KEYSYM, "key.keyboard.page.down", 267);
addKey(KEYSYM, "key.keyboard.page.up", 266);
addKey(KEYSYM, "key.keyboard.caps.lock", 280);
addKey(KEYSYM, "key.keyboard.pause", 284);
addKey(KEYSYM, "key.keyboard.scroll.lock", 281);
addKey(KEYSYM, "key.keyboard.menu", 348);
addKey(KEYSYM, "key.keyboard.print.screen", 283);
addKey(KEYSYM, "key.keyboard.world.1", 161);
addKey(KEYSYM, "key.keyboard.world.2", 162);
}
}
}
@@ -0,0 +1,37 @@
package com.mojang.blaze3d.platform;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
import org.joml.Vector3f;
@OnlyIn(Dist.CLIENT)
public class Lighting {
private static final Vector3f DIFFUSE_LIGHT_0 = (new Vector3f(0.2F, 1.0F, -0.7F)).normalize();
private static final Vector3f DIFFUSE_LIGHT_1 = (new Vector3f(-0.2F, 1.0F, 0.7F)).normalize();
private static final Vector3f NETHER_DIFFUSE_LIGHT_0 = (new Vector3f(0.2F, 1.0F, -0.7F)).normalize();
private static final Vector3f NETHER_DIFFUSE_LIGHT_1 = (new Vector3f(-0.2F, -1.0F, 0.7F)).normalize();
private static final Vector3f INVENTORY_DIFFUSE_LIGHT_0 = (new Vector3f(0.2F, -1.0F, -1.0F)).normalize();
private static final Vector3f INVENTORY_DIFFUSE_LIGHT_1 = (new Vector3f(-0.2F, -1.0F, 0.0F)).normalize();
public static void setupNetherLevel(Matrix4f pMatrix) {
RenderSystem.setupLevelDiffuseLighting(NETHER_DIFFUSE_LIGHT_0, NETHER_DIFFUSE_LIGHT_1, pMatrix);
}
public static void setupLevel(Matrix4f pMatrix) {
RenderSystem.setupLevelDiffuseLighting(DIFFUSE_LIGHT_0, DIFFUSE_LIGHT_1, pMatrix);
}
public static void setupForFlatItems() {
RenderSystem.setupGuiFlatDiffuseLighting(DIFFUSE_LIGHT_0, DIFFUSE_LIGHT_1);
}
public static void setupFor3DItems() {
RenderSystem.setupGui3DDiffuseLighting(DIFFUSE_LIGHT_0, DIFFUSE_LIGHT_1);
}
public static void setupForEntityInInventory() {
RenderSystem.setShaderLights(INVENTORY_DIFFUSE_LIGHT_0, INVENTORY_DIFFUSE_LIGHT_1);
}
}
@@ -0,0 +1,46 @@
package com.mojang.blaze3d.platform;
import ca.weblite.objc.Client;
import ca.weblite.objc.NSObject;
import com.sun.jna.Pointer;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;
import java.util.Optional;
import net.minecraft.server.packs.resources.IoSupplier;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.glfw.GLFWNativeCocoa;
@OnlyIn(Dist.CLIENT)
public class MacosUtil {
private static final int NS_FULL_SCREEN_WINDOW_MASK = 16384;
public static void toggleFullscreen(long pWindowId) {
getNsWindow(pWindowId).filter(MacosUtil::isInKioskMode).ifPresent(MacosUtil::toggleFullscreen);
}
private static Optional<NSObject> getNsWindow(long pWindowId) {
long i = GLFWNativeCocoa.glfwGetCocoaWindow(pWindowId);
return i != 0L ? Optional.of(new NSObject(new Pointer(i))) : Optional.empty();
}
private static boolean isInKioskMode(NSObject p_182520_) {
return (((Number)p_182520_.sendRaw("styleMask", new Object[0])).longValue() & 16384L) == 16384L;
}
private static void toggleFullscreen(NSObject p_182524_) {
p_182524_.send("toggleFullScreen:", new Object[]{Pointer.NULL});
}
public static void loadIcon(IoSupplier<InputStream> p_250929_) throws IOException {
try (InputStream inputstream = p_250929_.get()) {
String s = Base64.getEncoder().encodeToString(inputstream.readAllBytes());
Client client = Client.getInstance();
Object object = client.sendProxy("NSData", "alloc").send("initWithBase64Encoding:", s);
Object object1 = client.sendProxy("NSImage", "alloc").send("initWithData:", object);
client.sendProxy("NSApplication", "sharedApplication").send("setApplicationIconImage:", object1);
}
}
}
@@ -0,0 +1,29 @@
package com.mojang.blaze3d.platform;
import java.nio.ByteBuffer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.system.MemoryUtil;
@OnlyIn(Dist.CLIENT)
public class MemoryTracker {
private static final MemoryUtil.MemoryAllocator ALLOCATOR = MemoryUtil.getAllocator(false);
public static ByteBuffer create(int pSize) {
long i = ALLOCATOR.malloc((long)pSize);
if (i == 0L) {
throw new OutOfMemoryError("Failed to allocate " + pSize + " bytes");
} else {
return MemoryUtil.memByteBuffer(i, pSize);
}
}
public static ByteBuffer resize(ByteBuffer pBuffer, int pByteSize) {
long i = ALLOCATOR.realloc(MemoryUtil.memAddress0(pBuffer), (long)pByteSize);
if (i == 0L) {
throw new OutOfMemoryError("Failed to resize buffer from " + pBuffer.capacity() + " bytes to " + pByteSize + " bytes");
} else {
return MemoryUtil.memByteBuffer(i, pByteSize);
}
}
}
@@ -0,0 +1,96 @@
package com.mojang.blaze3d.platform;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.systems.RenderSystem;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWVidMode;
@OnlyIn(Dist.CLIENT)
public final class Monitor {
private final long monitor;
private final List<VideoMode> videoModes;
private VideoMode currentMode;
private int x;
private int y;
public Monitor(long pMonitor) {
this.monitor = pMonitor;
this.videoModes = Lists.newArrayList();
this.refreshVideoModes();
}
public void refreshVideoModes() {
RenderSystem.assertInInitPhase();
this.videoModes.clear();
GLFWVidMode.Buffer buffer = GLFW.glfwGetVideoModes(this.monitor);
for(int i = buffer.limit() - 1; i >= 0; --i) {
buffer.position(i);
VideoMode videomode = new VideoMode(buffer);
if (videomode.getRedBits() >= 8 && videomode.getGreenBits() >= 8 && videomode.getBlueBits() >= 8) {
this.videoModes.add(videomode);
}
}
int[] aint = new int[1];
int[] aint1 = new int[1];
GLFW.glfwGetMonitorPos(this.monitor, aint, aint1);
this.x = aint[0];
this.y = aint1[0];
GLFWVidMode glfwvidmode = GLFW.glfwGetVideoMode(this.monitor);
this.currentMode = new VideoMode(glfwvidmode);
}
public VideoMode getPreferredVidMode(Optional<VideoMode> pVideoMode) {
RenderSystem.assertInInitPhase();
if (pVideoMode.isPresent()) {
VideoMode videomode = pVideoMode.get();
for(VideoMode videomode1 : this.videoModes) {
if (videomode1.equals(videomode)) {
return videomode1;
}
}
}
return this.getCurrentMode();
}
public int getVideoModeIndex(VideoMode pVideoMode) {
RenderSystem.assertInInitPhase();
return this.videoModes.indexOf(pVideoMode);
}
public VideoMode getCurrentMode() {
return this.currentMode;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public VideoMode getMode(int pIndex) {
return this.videoModes.get(pIndex);
}
public int getModeCount() {
return this.videoModes.size();
}
public long getMonitor() {
return this.monitor;
}
public String toString() {
return String.format(Locale.ROOT, "Monitor[%s %sx%s %s]", this.monitor, this.x, this.y, this.currentMode);
}
}
@@ -0,0 +1,9 @@
package com.mojang.blaze3d.platform;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public interface MonitorCreator {
Monitor createMonitor(long pMonitor);
}
@@ -0,0 +1,795 @@
package com.mojang.blaze3d.platform;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.logging.LogUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;
import java.util.Locale;
import java.util.Set;
import java.util.function.IntUnaryOperator;
import javax.annotation.Nullable;
import net.minecraft.util.FastColor;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.commons.io.IOUtils;
import org.lwjgl.stb.STBIWriteCallback;
import org.lwjgl.stb.STBImage;
import org.lwjgl.stb.STBImageResize;
import org.lwjgl.stb.STBImageWrite;
import org.lwjgl.stb.STBTTFontinfo;
import org.lwjgl.stb.STBTruetype;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public final class NativeImage implements AutoCloseable {
private static final Logger LOGGER = LogUtils.getLogger();
private static final Set<StandardOpenOption> OPEN_OPTIONS = EnumSet.of(StandardOpenOption.WRITE, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING);
private final NativeImage.Format format;
private final int width;
private final int height;
private final boolean useStbFree;
private long pixels;
private final long size;
public NativeImage(int pWidth, int pHeight, boolean pUseCalloc) {
this(NativeImage.Format.RGBA, pWidth, pHeight, pUseCalloc);
}
public NativeImage(NativeImage.Format pFormat, int pWidth, int pHeight, boolean pUseCalloc) {
if (pWidth > 0 && pHeight > 0) {
this.format = pFormat;
this.width = pWidth;
this.height = pHeight;
this.size = (long)pWidth * (long)pHeight * (long)pFormat.components();
this.useStbFree = false;
if (pUseCalloc) {
this.pixels = MemoryUtil.nmemCalloc(1L, this.size);
} else {
this.pixels = MemoryUtil.nmemAlloc(this.size);
}
} else {
throw new IllegalArgumentException("Invalid texture size: " + pWidth + "x" + pHeight);
}
}
private NativeImage(NativeImage.Format pFormat, int pWidth, int pHeight, boolean pUseStbFree, long pPixels) {
if (pWidth > 0 && pHeight > 0) {
this.format = pFormat;
this.width = pWidth;
this.height = pHeight;
this.useStbFree = pUseStbFree;
this.pixels = pPixels;
this.size = (long)pWidth * (long)pHeight * (long)pFormat.components();
} else {
throw new IllegalArgumentException("Invalid texture size: " + pWidth + "x" + pHeight);
}
}
public String toString() {
return "NativeImage[" + this.format + " " + this.width + "x" + this.height + "@" + this.pixels + (this.useStbFree ? "S" : "N") + "]";
}
private boolean isOutsideBounds(int pX, int pY) {
return pX < 0 || pX >= this.width || pY < 0 || pY >= this.height;
}
public static NativeImage read(InputStream pTextureStream) throws IOException {
return read(NativeImage.Format.RGBA, pTextureStream);
}
public static NativeImage read(@Nullable NativeImage.Format pFormat, InputStream pTextureStream) throws IOException {
ByteBuffer bytebuffer = null;
NativeImage nativeimage;
try {
bytebuffer = TextureUtil.readResource(pTextureStream);
bytebuffer.rewind();
nativeimage = read(pFormat, bytebuffer);
} finally {
MemoryUtil.memFree(bytebuffer);
IOUtils.closeQuietly(pTextureStream);
}
return nativeimage;
}
public static NativeImage read(ByteBuffer pTextureData) throws IOException {
return read(NativeImage.Format.RGBA, pTextureData);
}
public static NativeImage read(byte[] pBytes) throws IOException {
try (MemoryStack memorystack = MemoryStack.stackPush()) {
ByteBuffer bytebuffer = memorystack.malloc(pBytes.length);
bytebuffer.put(pBytes);
bytebuffer.rewind();
return read(bytebuffer);
}
}
public static NativeImage read(@Nullable NativeImage.Format pFormat, ByteBuffer pTextureData) throws IOException {
if (pFormat != null && !pFormat.supportedByStb()) {
throw new UnsupportedOperationException("Don't know how to read format " + pFormat);
} else if (MemoryUtil.memAddress(pTextureData) == 0L) {
throw new IllegalArgumentException("Invalid buffer");
} else {
try (MemoryStack memorystack = MemoryStack.stackPush()) {
IntBuffer intbuffer = memorystack.mallocInt(1);
IntBuffer intbuffer1 = memorystack.mallocInt(1);
IntBuffer intbuffer2 = memorystack.mallocInt(1);
ByteBuffer bytebuffer = STBImage.stbi_load_from_memory(pTextureData, intbuffer, intbuffer1, intbuffer2, pFormat == null ? 0 : pFormat.components);
if (bytebuffer == null) {
throw new IOException("Could not load image: " + STBImage.stbi_failure_reason());
} else {
return new NativeImage(pFormat == null ? NativeImage.Format.getStbFormat(intbuffer2.get(0)) : pFormat, intbuffer.get(0), intbuffer1.get(0), true, MemoryUtil.memAddress(bytebuffer));
}
}
}
}
private static void setFilter(boolean pLinear, boolean pMipmap) {
RenderSystem.assertOnRenderThreadOrInit();
if (pLinear) {
GlStateManager._texParameter(3553, 10241, pMipmap ? 9987 : 9729);
GlStateManager._texParameter(3553, 10240, 9729);
} else {
GlStateManager._texParameter(3553, 10241, pMipmap ? 9986 : 9728);
GlStateManager._texParameter(3553, 10240, 9728);
}
}
private void checkAllocated() {
if (this.pixels == 0L) {
throw new IllegalStateException("Image is not allocated.");
}
}
public void close() {
if (this.pixels != 0L) {
if (this.useStbFree) {
STBImage.nstbi_image_free(this.pixels);
} else {
MemoryUtil.nmemFree(this.pixels);
}
}
this.pixels = 0L;
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
public NativeImage.Format format() {
return this.format;
}
public int getPixelRGBA(int pX, int pY) {
if (this.format != NativeImage.Format.RGBA) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "getPixelRGBA only works on RGBA images; have %s", this.format));
} else if (this.isOutsideBounds(pX, pY)) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "(%s, %s) outside of image bounds (%s, %s)", pX, pY, this.width, this.height));
} else {
this.checkAllocated();
long i = ((long)pX + (long)pY * (long)this.width) * 4L;
return MemoryUtil.memGetInt(this.pixels + i);
}
}
public void setPixelRGBA(int pX, int pY, int pAbgrColor) {
if (this.format != NativeImage.Format.RGBA) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "setPixelRGBA only works on RGBA images; have %s", this.format));
} else if (this.isOutsideBounds(pX, pY)) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "(%s, %s) outside of image bounds (%s, %s)", pX, pY, this.width, this.height));
} else {
this.checkAllocated();
long i = ((long)pX + (long)pY * (long)this.width) * 4L;
MemoryUtil.memPutInt(this.pixels + i, pAbgrColor);
}
}
public NativeImage mappedCopy(IntUnaryOperator pFunction) {
if (this.format != NativeImage.Format.RGBA) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "function application only works on RGBA images; have %s", this.format));
} else {
this.checkAllocated();
NativeImage nativeimage = new NativeImage(this.width, this.height, false);
int i = this.width * this.height;
IntBuffer intbuffer = MemoryUtil.memIntBuffer(this.pixels, i);
IntBuffer intbuffer1 = MemoryUtil.memIntBuffer(nativeimage.pixels, i);
for(int j = 0; j < i; ++j) {
intbuffer1.put(j, pFunction.applyAsInt(intbuffer.get(j)));
}
return nativeimage;
}
}
public void applyToAllPixels(IntUnaryOperator pFunction) {
if (this.format != NativeImage.Format.RGBA) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "function application only works on RGBA images; have %s", this.format));
} else {
this.checkAllocated();
int i = this.width * this.height;
IntBuffer intbuffer = MemoryUtil.memIntBuffer(this.pixels, i);
for(int j = 0; j < i; ++j) {
intbuffer.put(j, pFunction.applyAsInt(intbuffer.get(j)));
}
}
}
public int[] getPixelsRGBA() {
if (this.format != NativeImage.Format.RGBA) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "getPixelsRGBA only works on RGBA images; have %s", this.format));
} else {
this.checkAllocated();
int[] aint = new int[this.width * this.height];
MemoryUtil.memIntBuffer(this.pixels, this.width * this.height).get(aint);
return aint;
}
}
public void setPixelLuminance(int pX, int pY, byte pLuminance) {
RenderSystem.assertOnRenderThread();
if (!this.format.hasLuminance()) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "setPixelLuminance only works on image with luminance; have %s", this.format));
} else if (this.isOutsideBounds(pX, pY)) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "(%s, %s) outside of image bounds (%s, %s)", pX, pY, this.width, this.height));
} else {
this.checkAllocated();
long i = ((long)pX + (long)pY * (long)this.width) * (long)this.format.components() + (long)(this.format.luminanceOffset() / 8);
MemoryUtil.memPutByte(this.pixels + i, pLuminance);
}
}
public byte getRedOrLuminance(int pX, int pY) {
RenderSystem.assertOnRenderThread();
if (!this.format.hasLuminanceOrRed()) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "no red or luminance in %s", this.format));
} else if (this.isOutsideBounds(pX, pY)) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "(%s, %s) outside of image bounds (%s, %s)", pX, pY, this.width, this.height));
} else {
int i = (pX + pY * this.width) * this.format.components() + this.format.luminanceOrRedOffset() / 8;
return MemoryUtil.memGetByte(this.pixels + (long)i);
}
}
public byte getGreenOrLuminance(int pX, int pY) {
RenderSystem.assertOnRenderThread();
if (!this.format.hasLuminanceOrGreen()) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "no green or luminance in %s", this.format));
} else if (this.isOutsideBounds(pX, pY)) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "(%s, %s) outside of image bounds (%s, %s)", pX, pY, this.width, this.height));
} else {
int i = (pX + pY * this.width) * this.format.components() + this.format.luminanceOrGreenOffset() / 8;
return MemoryUtil.memGetByte(this.pixels + (long)i);
}
}
public byte getBlueOrLuminance(int pX, int pY) {
RenderSystem.assertOnRenderThread();
if (!this.format.hasLuminanceOrBlue()) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "no blue or luminance in %s", this.format));
} else if (this.isOutsideBounds(pX, pY)) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "(%s, %s) outside of image bounds (%s, %s)", pX, pY, this.width, this.height));
} else {
int i = (pX + pY * this.width) * this.format.components() + this.format.luminanceOrBlueOffset() / 8;
return MemoryUtil.memGetByte(this.pixels + (long)i);
}
}
public byte getLuminanceOrAlpha(int pX, int pY) {
if (!this.format.hasLuminanceOrAlpha()) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "no luminance or alpha in %s", this.format));
} else if (this.isOutsideBounds(pX, pY)) {
throw new IllegalArgumentException(String.format(Locale.ROOT, "(%s, %s) outside of image bounds (%s, %s)", pX, pY, this.width, this.height));
} else {
int i = (pX + pY * this.width) * this.format.components() + this.format.luminanceOrAlphaOffset() / 8;
return MemoryUtil.memGetByte(this.pixels + (long)i);
}
}
public void blendPixel(int pX, int pY, int pAbgrColor) {
if (this.format != NativeImage.Format.RGBA) {
throw new UnsupportedOperationException("Can only call blendPixel with RGBA format");
} else {
int i = this.getPixelRGBA(pX, pY);
float f = (float)FastColor.ABGR32.alpha(pAbgrColor) / 255.0F;
float f1 = (float)FastColor.ABGR32.blue(pAbgrColor) / 255.0F;
float f2 = (float)FastColor.ABGR32.green(pAbgrColor) / 255.0F;
float f3 = (float)FastColor.ABGR32.red(pAbgrColor) / 255.0F;
float f4 = (float)FastColor.ABGR32.alpha(i) / 255.0F;
float f5 = (float)FastColor.ABGR32.blue(i) / 255.0F;
float f6 = (float)FastColor.ABGR32.green(i) / 255.0F;
float f7 = (float)FastColor.ABGR32.red(i) / 255.0F;
float f8 = 1.0F - f;
float f9 = f * f + f4 * f8;
float f10 = f1 * f + f5 * f8;
float f11 = f2 * f + f6 * f8;
float f12 = f3 * f + f7 * f8;
if (f9 > 1.0F) {
f9 = 1.0F;
}
if (f10 > 1.0F) {
f10 = 1.0F;
}
if (f11 > 1.0F) {
f11 = 1.0F;
}
if (f12 > 1.0F) {
f12 = 1.0F;
}
int j = (int)(f9 * 255.0F);
int k = (int)(f10 * 255.0F);
int l = (int)(f11 * 255.0F);
int i1 = (int)(f12 * 255.0F);
this.setPixelRGBA(pX, pY, FastColor.ABGR32.color(j, k, l, i1));
}
}
/** @deprecated */
@Deprecated
public int[] makePixelArray() {
if (this.format != NativeImage.Format.RGBA) {
throw new UnsupportedOperationException("can only call makePixelArray for RGBA images.");
} else {
this.checkAllocated();
int[] aint = new int[this.getWidth() * this.getHeight()];
for(int i = 0; i < this.getHeight(); ++i) {
for(int j = 0; j < this.getWidth(); ++j) {
int k = this.getPixelRGBA(j, i);
aint[j + i * this.getWidth()] = FastColor.ARGB32.color(FastColor.ABGR32.alpha(k), FastColor.ABGR32.red(k), FastColor.ABGR32.green(k), FastColor.ABGR32.blue(k));
}
}
return aint;
}
}
public void upload(int pLevel, int pXOffset, int pYOffset, boolean pMipmap) {
this.upload(pLevel, pXOffset, pYOffset, 0, 0, this.width, this.height, false, pMipmap);
}
public void upload(int pLevel, int pXOffset, int pYOffset, int pUnpackSkipPixels, int pUnpackSkipRows, int pWidth, int pHeight, boolean pMipmap, boolean pAutoClose) {
this.upload(pLevel, pXOffset, pYOffset, pUnpackSkipPixels, pUnpackSkipRows, pWidth, pHeight, false, false, pMipmap, pAutoClose);
}
public void upload(int pLevel, int pXOffset, int pYOffset, int pUnpackSkipPixels, int pUnpackSkipRows, int pWidth, int pHeight, boolean pBlur, boolean pClamp, boolean pMipmap, boolean pAutoClose) {
if (!RenderSystem.isOnRenderThreadOrInit()) {
RenderSystem.recordRenderCall(() -> {
this._upload(pLevel, pXOffset, pYOffset, pUnpackSkipPixels, pUnpackSkipRows, pWidth, pHeight, pBlur, pClamp, pMipmap, pAutoClose);
});
} else {
this._upload(pLevel, pXOffset, pYOffset, pUnpackSkipPixels, pUnpackSkipRows, pWidth, pHeight, pBlur, pClamp, pMipmap, pAutoClose);
}
}
private void _upload(int pLevel, int pXOffset, int pYOffset, int pUnpackSkipPixels, int pUnpackSkipRows, int pWidth, int pHeight, boolean pBlur, boolean pClamp, boolean pMipmap, boolean pAutoClose) {
try {
RenderSystem.assertOnRenderThreadOrInit();
this.checkAllocated();
setFilter(pBlur, pMipmap);
if (pWidth == this.getWidth()) {
GlStateManager._pixelStore(3314, 0);
} else {
GlStateManager._pixelStore(3314, this.getWidth());
}
GlStateManager._pixelStore(3316, pUnpackSkipPixels);
GlStateManager._pixelStore(3315, pUnpackSkipRows);
this.format.setUnpackPixelStoreState();
GlStateManager._texSubImage2D(3553, pLevel, pXOffset, pYOffset, pWidth, pHeight, this.format.glFormat(), 5121, this.pixels);
if (pClamp) {
GlStateManager._texParameter(3553, 10242, 33071);
GlStateManager._texParameter(3553, 10243, 33071);
}
} finally {
if (pAutoClose) {
this.close();
}
}
}
public void downloadTexture(int pLevel, boolean pOpaque) {
RenderSystem.assertOnRenderThread();
this.checkAllocated();
this.format.setPackPixelStoreState();
GlStateManager._getTexImage(3553, pLevel, this.format.glFormat(), 5121, this.pixels);
if (pOpaque && this.format.hasAlpha()) {
for(int i = 0; i < this.getHeight(); ++i) {
for(int j = 0; j < this.getWidth(); ++j) {
this.setPixelRGBA(j, i, this.getPixelRGBA(j, i) | 255 << this.format.alphaOffset());
}
}
}
}
public void downloadDepthBuffer(float pUnused) {
RenderSystem.assertOnRenderThread();
if (this.format.components() != 1) {
throw new IllegalStateException("Depth buffer must be stored in NativeImage with 1 component.");
} else {
this.checkAllocated();
this.format.setPackPixelStoreState();
GlStateManager._readPixels(0, 0, this.width, this.height, 6402, 5121, this.pixels);
}
}
public void drawPixels() {
RenderSystem.assertOnRenderThread();
this.format.setUnpackPixelStoreState();
GlStateManager._glDrawPixels(this.width, this.height, this.format.glFormat(), 5121, this.pixels);
}
public void writeToFile(File pFile) throws IOException {
this.writeToFile(pFile.toPath());
}
/**
* Renders given glyph into this image
*/
public void copyFromFont(STBTTFontinfo pInfo, int pGlyphIndex, int pWidth, int pHeight, float pScaleX, float pScaleY, float pShiftX, float pShiftY, int pX, int pY) {
if (pX >= 0 && pX + pWidth <= this.getWidth() && pY >= 0 && pY + pHeight <= this.getHeight()) {
if (this.format.components() != 1) {
throw new IllegalArgumentException("Can only write fonts into 1-component images.");
} else {
STBTruetype.nstbtt_MakeGlyphBitmapSubpixel(pInfo.address(), this.pixels + (long)pX + (long)(pY * this.getWidth()), pWidth, pHeight, this.getWidth(), pScaleX, pScaleY, pShiftX, pShiftY, pGlyphIndex);
}
} else {
throw new IllegalArgumentException(String.format(Locale.ROOT, "Out of bounds: start: (%s, %s) (size: %sx%s); size: %sx%s", pX, pY, pWidth, pHeight, this.getWidth(), this.getHeight()));
}
}
public void writeToFile(Path pPath) throws IOException {
if (!this.format.supportedByStb()) {
throw new UnsupportedOperationException("Don't know how to write format " + this.format);
} else {
this.checkAllocated();
try (WritableByteChannel writablebytechannel = Files.newByteChannel(pPath, OPEN_OPTIONS)) {
if (!this.writeToChannel(writablebytechannel)) {
throw new IOException("Could not write image to the PNG file \"" + pPath.toAbsolutePath() + "\": " + STBImage.stbi_failure_reason());
}
}
}
}
public byte[] asByteArray() throws IOException {
try (
ByteArrayOutputStream bytearrayoutputstream = new ByteArrayOutputStream();
WritableByteChannel writablebytechannel = Channels.newChannel(bytearrayoutputstream);
) {
if (!this.writeToChannel(writablebytechannel)) {
throw new IOException("Could not write image to byte array: " + STBImage.stbi_failure_reason());
} else {
return bytearrayoutputstream.toByteArray();
}
}
}
private boolean writeToChannel(WritableByteChannel pChannel) throws IOException {
NativeImage.WriteCallback nativeimage$writecallback = new NativeImage.WriteCallback(pChannel);
boolean flag;
try {
int i = Math.min(this.getHeight(), Integer.MAX_VALUE / this.getWidth() / this.format.components());
if (i < this.getHeight()) {
LOGGER.warn("Dropping image height from {} to {} to fit the size into 32-bit signed int", this.getHeight(), i);
}
if (STBImageWrite.nstbi_write_png_to_func(nativeimage$writecallback.address(), 0L, this.getWidth(), i, this.format.components(), this.pixels, 0) != 0) {
nativeimage$writecallback.throwIfException();
return true;
}
flag = false;
} finally {
nativeimage$writecallback.free();
}
return flag;
}
public void copyFrom(NativeImage pOther) {
if (pOther.format() != this.format) {
throw new UnsupportedOperationException("Image formats don't match.");
} else {
int i = this.format.components();
this.checkAllocated();
pOther.checkAllocated();
if (this.width == pOther.width) {
MemoryUtil.memCopy(pOther.pixels, this.pixels, Math.min(this.size, pOther.size));
} else {
int j = Math.min(this.getWidth(), pOther.getWidth());
int k = Math.min(this.getHeight(), pOther.getHeight());
for(int l = 0; l < k; ++l) {
int i1 = l * pOther.getWidth() * i;
int j1 = l * this.getWidth() * i;
MemoryUtil.memCopy(pOther.pixels + (long)i1, this.pixels + (long)j1, (long)j);
}
}
}
}
public void fillRect(int pX, int pY, int pWidth, int pHeight, int pValue) {
for(int i = pY; i < pY + pHeight; ++i) {
for(int j = pX; j < pX + pWidth; ++j) {
this.setPixelRGBA(j, i, pValue);
}
}
}
public void copyRect(int pXFrom, int pYFrom, int pXToDelta, int pYToDelta, int pWidth, int pHeight, boolean pMirrorX, boolean pMirrorY) {
this.copyRect(this, pXFrom, pYFrom, pXFrom + pXToDelta, pYFrom + pYToDelta, pWidth, pHeight, pMirrorX, pMirrorY);
}
public void copyRect(NativeImage pSource, int pXFrom, int pYFrom, int pXTo, int pYTo, int pWidth, int pHeight, boolean pMirrorX, boolean pMirrorY) {
for(int i = 0; i < pHeight; ++i) {
for(int j = 0; j < pWidth; ++j) {
int k = pMirrorX ? pWidth - 1 - j : j;
int l = pMirrorY ? pHeight - 1 - i : i;
int i1 = this.getPixelRGBA(pXFrom + j, pYFrom + i);
pSource.setPixelRGBA(pXTo + k, pYTo + l, i1);
}
}
}
public void flipY() {
this.checkAllocated();
try (MemoryStack memorystack = MemoryStack.stackPush()) {
int i = this.format.components();
int j = this.getWidth() * i;
long k = memorystack.nmalloc(j);
for(int l = 0; l < this.getHeight() / 2; ++l) {
int i1 = l * this.getWidth() * i;
int j1 = (this.getHeight() - 1 - l) * this.getWidth() * i;
MemoryUtil.memCopy(this.pixels + (long)i1, k, (long)j);
MemoryUtil.memCopy(this.pixels + (long)j1, this.pixels + (long)i1, (long)j);
MemoryUtil.memCopy(k, this.pixels + (long)j1, (long)j);
}
}
}
public void resizeSubRectTo(int pX, int pY, int pWidth, int pHeight, NativeImage pImage) {
this.checkAllocated();
if (pImage.format() != this.format) {
throw new UnsupportedOperationException("resizeSubRectTo only works for images of the same format.");
} else {
int i = this.format.components();
STBImageResize.nstbir_resize_uint8(this.pixels + (long)((pX + pY * this.getWidth()) * i), pWidth, pHeight, this.getWidth() * i, pImage.pixels, pImage.getWidth(), pImage.getHeight(), 0, i);
}
}
public void untrack() {
DebugMemoryUntracker.untrack(this.pixels);
}
@OnlyIn(Dist.CLIENT)
public static enum Format {
RGBA(4, 6408, true, true, true, false, true, 0, 8, 16, 255, 24, true),
RGB(3, 6407, true, true, true, false, false, 0, 8, 16, 255, 255, true),
LUMINANCE_ALPHA(2, 33319, false, false, false, true, true, 255, 255, 255, 0, 8, true),
LUMINANCE(1, 6403, false, false, false, true, false, 0, 0, 0, 0, 255, true);
final int components;
private final int glFormat;
private final boolean hasRed;
private final boolean hasGreen;
private final boolean hasBlue;
private final boolean hasLuminance;
private final boolean hasAlpha;
private final int redOffset;
private final int greenOffset;
private final int blueOffset;
private final int luminanceOffset;
private final int alphaOffset;
private final boolean supportedByStb;
private Format(int pComponents, int pGlFormat, boolean pHasRed, boolean pHasGreen, boolean pHasBlue, boolean pHasLuminance, boolean pHasAlpha, int pRedOffset, int pGreenOffset, int pBlueOffset, int pLuminanceOffset, int pAlphaOffset, boolean pSupportedByStb) {
this.components = pComponents;
this.glFormat = pGlFormat;
this.hasRed = pHasRed;
this.hasGreen = pHasGreen;
this.hasBlue = pHasBlue;
this.hasLuminance = pHasLuminance;
this.hasAlpha = pHasAlpha;
this.redOffset = pRedOffset;
this.greenOffset = pGreenOffset;
this.blueOffset = pBlueOffset;
this.luminanceOffset = pLuminanceOffset;
this.alphaOffset = pAlphaOffset;
this.supportedByStb = pSupportedByStb;
}
public int components() {
return this.components;
}
public void setPackPixelStoreState() {
RenderSystem.assertOnRenderThread();
GlStateManager._pixelStore(3333, this.components());
}
public void setUnpackPixelStoreState() {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._pixelStore(3317, this.components());
}
public int glFormat() {
return this.glFormat;
}
public boolean hasRed() {
return this.hasRed;
}
public boolean hasGreen() {
return this.hasGreen;
}
public boolean hasBlue() {
return this.hasBlue;
}
public boolean hasLuminance() {
return this.hasLuminance;
}
public boolean hasAlpha() {
return this.hasAlpha;
}
public int redOffset() {
return this.redOffset;
}
public int greenOffset() {
return this.greenOffset;
}
public int blueOffset() {
return this.blueOffset;
}
public int luminanceOffset() {
return this.luminanceOffset;
}
public int alphaOffset() {
return this.alphaOffset;
}
public boolean hasLuminanceOrRed() {
return this.hasLuminance || this.hasRed;
}
public boolean hasLuminanceOrGreen() {
return this.hasLuminance || this.hasGreen;
}
public boolean hasLuminanceOrBlue() {
return this.hasLuminance || this.hasBlue;
}
public boolean hasLuminanceOrAlpha() {
return this.hasLuminance || this.hasAlpha;
}
public int luminanceOrRedOffset() {
return this.hasLuminance ? this.luminanceOffset : this.redOffset;
}
public int luminanceOrGreenOffset() {
return this.hasLuminance ? this.luminanceOffset : this.greenOffset;
}
public int luminanceOrBlueOffset() {
return this.hasLuminance ? this.luminanceOffset : this.blueOffset;
}
public int luminanceOrAlphaOffset() {
return this.hasLuminance ? this.luminanceOffset : this.alphaOffset;
}
public boolean supportedByStb() {
return this.supportedByStb;
}
static NativeImage.Format getStbFormat(int pChannels) {
switch (pChannels) {
case 1:
return LUMINANCE;
case 2:
return LUMINANCE_ALPHA;
case 3:
return RGB;
case 4:
default:
return RGBA;
}
}
}
@OnlyIn(Dist.CLIENT)
public static enum InternalGlFormat {
RGBA(6408),
RGB(6407),
RG(33319),
RED(6403);
private final int glFormat;
private InternalGlFormat(int pGlFormat) {
this.glFormat = pGlFormat;
}
public int glFormat() {
return this.glFormat;
}
}
@OnlyIn(Dist.CLIENT)
static class WriteCallback extends STBIWriteCallback {
private final WritableByteChannel output;
@Nullable
private IOException exception;
WriteCallback(WritableByteChannel pOutput) {
this.output = pOutput;
}
public void invoke(long pContext, long pData, int pSize) {
ByteBuffer bytebuffer = getData(pData, pSize);
try {
this.output.write(bytebuffer);
} catch (IOException ioexception) {
this.exception = ioexception;
}
}
public void throwIfException() throws IOException {
if (this.exception != null) {
throw this.exception;
}
}
}
}
@@ -0,0 +1,111 @@
package com.mojang.blaze3d.platform;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWMonitorCallback;
import org.lwjgl.glfw.GLFWMonitorCallbackI;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class ScreenManager {
private static final Logger LOGGER = LogUtils.getLogger();
private final Long2ObjectMap<Monitor> monitors = new Long2ObjectOpenHashMap<>();
private final MonitorCreator monitorCreator;
public ScreenManager(MonitorCreator pMonitorCreator) {
RenderSystem.assertInInitPhase();
this.monitorCreator = pMonitorCreator;
GLFW.glfwSetMonitorCallback(this::onMonitorChange);
PointerBuffer pointerbuffer = GLFW.glfwGetMonitors();
if (pointerbuffer != null) {
for(int i = 0; i < pointerbuffer.limit(); ++i) {
long j = pointerbuffer.get(i);
this.monitors.put(j, pMonitorCreator.createMonitor(j));
}
}
}
private void onMonitorChange(long p_85274_, int p_85275_) {
RenderSystem.assertOnRenderThread();
if (p_85275_ == 262145) {
this.monitors.put(p_85274_, this.monitorCreator.createMonitor(p_85274_));
LOGGER.debug("Monitor {} connected. Current monitors: {}", p_85274_, this.monitors);
} else if (p_85275_ == 262146) {
this.monitors.remove(p_85274_);
LOGGER.debug("Monitor {} disconnected. Current monitors: {}", p_85274_, this.monitors);
}
}
@Nullable
public Monitor getMonitor(long pMonitorID) {
RenderSystem.assertInInitPhase();
return this.monitors.get(pMonitorID);
}
@Nullable
public Monitor findBestMonitor(Window pWindow) {
long i = GLFW.glfwGetWindowMonitor(pWindow.getWindow());
if (i != 0L) {
return this.getMonitor(i);
} else {
int j = pWindow.getX();
int k = j + pWindow.getScreenWidth();
int l = pWindow.getY();
int i1 = l + pWindow.getScreenHeight();
int j1 = -1;
Monitor monitor = null;
long k1 = GLFW.glfwGetPrimaryMonitor();
LOGGER.debug("Selecting monitor - primary: {}, current monitors: {}", k1, this.monitors);
for(Monitor monitor1 : this.monitors.values()) {
int l1 = monitor1.getX();
int i2 = l1 + monitor1.getCurrentMode().getWidth();
int j2 = monitor1.getY();
int k2 = j2 + monitor1.getCurrentMode().getHeight();
int l2 = clamp(j, l1, i2);
int i3 = clamp(k, l1, i2);
int j3 = clamp(l, j2, k2);
int k3 = clamp(i1, j2, k2);
int l3 = Math.max(0, i3 - l2);
int i4 = Math.max(0, k3 - j3);
int j4 = l3 * i4;
if (j4 > j1) {
monitor = monitor1;
j1 = j4;
} else if (j4 == j1 && k1 == monitor1.getMonitor()) {
LOGGER.debug("Primary monitor {} is preferred to monitor {}", monitor1, monitor);
monitor = monitor1;
}
}
LOGGER.debug("Selected monitor: {}", (Object)monitor);
return monitor;
}
}
public static int clamp(int pValue, int pMin, int pMax) {
if (pValue < pMin) {
return pMin;
} else {
return pValue > pMax ? pMax : pValue;
}
}
public void shutdown() {
RenderSystem.assertOnRenderThread();
GLFWMonitorCallback glfwmonitorcallback = GLFW.glfwSetMonitorCallback((GLFWMonitorCallbackI)null);
if (glfwmonitorcallback != null) {
glfwmonitorcallback.free();
}
}
}
@@ -0,0 +1,142 @@
package com.mojang.blaze3d.platform;
import com.mojang.blaze3d.DontObfuscate;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.logging.LogUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.Path;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.IntUnaryOperator;
import javax.annotation.Nullable;
import net.minecraft.SharedConstants;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.system.MemoryUtil;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
@DontObfuscate
public class TextureUtil {
private static final Logger LOGGER = LogUtils.getLogger();
public static final int MIN_MIPMAP_LEVEL = 0;
private static final int DEFAULT_IMAGE_BUFFER_SIZE = 8192;
public static int generateTextureId() {
RenderSystem.assertOnRenderThreadOrInit();
if (SharedConstants.IS_RUNNING_IN_IDE) {
int[] aint = new int[ThreadLocalRandom.current().nextInt(15) + 1];
GlStateManager._genTextures(aint);
int i = GlStateManager._genTexture();
GlStateManager._deleteTextures(aint);
return i;
} else {
return GlStateManager._genTexture();
}
}
public static void releaseTextureId(int pTextureId) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._deleteTexture(pTextureId);
}
public static void prepareImage(int pTextureId, int pWidth, int pHeight) {
prepareImage(NativeImage.InternalGlFormat.RGBA, pTextureId, 0, pWidth, pHeight);
}
public static void prepareImage(NativeImage.InternalGlFormat pPixelFormat, int pTextureId, int pWidth, int pHeight) {
prepareImage(pPixelFormat, pTextureId, 0, pWidth, pHeight);
}
public static void prepareImage(int pTextureId, int pMipmapLevel, int pWidth, int pHeight) {
prepareImage(NativeImage.InternalGlFormat.RGBA, pTextureId, pMipmapLevel, pWidth, pHeight);
}
public static void prepareImage(NativeImage.InternalGlFormat pPixelFormat, int pTextureId, int pMipmapLevel, int pWidth, int pHeight) {
RenderSystem.assertOnRenderThreadOrInit();
bind(pTextureId);
if (pMipmapLevel >= 0) {
GlStateManager._texParameter(3553, 33085, pMipmapLevel);
GlStateManager._texParameter(3553, 33082, 0);
GlStateManager._texParameter(3553, 33083, pMipmapLevel);
GlStateManager._texParameter(3553, 34049, 0.0F);
}
for(int i = 0; i <= pMipmapLevel; ++i) {
GlStateManager._texImage2D(3553, i, pPixelFormat.glFormat(), pWidth >> i, pHeight >> i, 0, 6408, 5121, (IntBuffer)null);
}
}
private static void bind(int pTextureId) {
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._bindTexture(pTextureId);
}
public static ByteBuffer readResource(InputStream pInputStream) throws IOException {
ReadableByteChannel readablebytechannel = Channels.newChannel(pInputStream);
if (readablebytechannel instanceof SeekableByteChannel seekablebytechannel) {
return readResource(readablebytechannel, (int)seekablebytechannel.size() + 1);
} else {
return readResource(readablebytechannel, 8192);
}
}
private static ByteBuffer readResource(ReadableByteChannel pChannel, int pSize) throws IOException {
ByteBuffer bytebuffer = MemoryUtil.memAlloc(pSize);
try {
while(pChannel.read(bytebuffer) != -1) {
if (!bytebuffer.hasRemaining()) {
bytebuffer = MemoryUtil.memRealloc(bytebuffer, bytebuffer.capacity() * 2);
}
}
return bytebuffer;
} catch (IOException ioexception) {
MemoryUtil.memFree(bytebuffer);
throw ioexception;
}
}
public static void writeAsPNG(Path pOutputDir, String pTextureName, int pTextureId, int pAmount, int pWidth, int pHeight) {
writeAsPNG(pOutputDir, pTextureName, pTextureId, pAmount, pWidth, pHeight, (IntUnaryOperator)null);
}
public static void writeAsPNG(Path pOutputDir, String pTextureName, int pTextureId, int pAmount, int pWidth, int pHeight, @Nullable IntUnaryOperator pFunction) {
RenderSystem.assertOnRenderThread();
bind(pTextureId);
for(int i = 0; i <= pAmount; ++i) {
int j = pWidth >> i;
int k = pHeight >> i;
try (NativeImage nativeimage = new NativeImage(j, k, false)) {
nativeimage.downloadTexture(i, false);
if (pFunction != null) {
nativeimage.applyToAllPixels(pFunction);
}
Path path = pOutputDir.resolve(pTextureName + "_" + i + ".png");
nativeimage.writeToFile(path);
LOGGER.debug("Exported png to: {}", (Object)path.toAbsolutePath());
} catch (IOException ioexception) {
LOGGER.debug("Unable to write: ", (Throwable)ioexception);
}
}
}
public static Path getDebugTexturePath(Path pBasePath) {
return pBasePath.resolve("screenshots").resolve("debug");
}
public static Path getDebugTexturePath() {
return getDebugTexturePath(Path.of("."));
}
}
@@ -0,0 +1,131 @@
package com.mojang.blaze3d.platform;
import java.util.Locale;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.glfw.GLFWVidMode;
@OnlyIn(Dist.CLIENT)
public final class VideoMode {
private final int width;
private final int height;
private final int redBits;
private final int greenBits;
private final int blueBits;
private final int refreshRate;
private static final Pattern PATTERN = Pattern.compile("(\\d+)x(\\d+)(?:@(\\d+)(?::(\\d+))?)?");
public VideoMode(int pWidth, int pHeight, int pRedBits, int pGreenBits, int pBlueBits, int pRefreshRate) {
this.width = pWidth;
this.height = pHeight;
this.redBits = pRedBits;
this.greenBits = pGreenBits;
this.blueBits = pBlueBits;
this.refreshRate = pRefreshRate;
}
public VideoMode(GLFWVidMode.Buffer pBufferVideoMode) {
this.width = pBufferVideoMode.width();
this.height = pBufferVideoMode.height();
this.redBits = pBufferVideoMode.redBits();
this.greenBits = pBufferVideoMode.greenBits();
this.blueBits = pBufferVideoMode.blueBits();
this.refreshRate = pBufferVideoMode.refreshRate();
}
public VideoMode(GLFWVidMode pGlfwVideoMode) {
this.width = pGlfwVideoMode.width();
this.height = pGlfwVideoMode.height();
this.redBits = pGlfwVideoMode.redBits();
this.greenBits = pGlfwVideoMode.greenBits();
this.blueBits = pGlfwVideoMode.blueBits();
this.refreshRate = pGlfwVideoMode.refreshRate();
}
public int getWidth() {
return this.width;
}
public int getHeight() {
return this.height;
}
public int getRedBits() {
return this.redBits;
}
public int getGreenBits() {
return this.greenBits;
}
public int getBlueBits() {
return this.blueBits;
}
public int getRefreshRate() {
return this.refreshRate;
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else if (pOther != null && this.getClass() == pOther.getClass()) {
VideoMode videomode = (VideoMode)pOther;
return this.width == videomode.width && this.height == videomode.height && this.redBits == videomode.redBits && this.greenBits == videomode.greenBits && this.blueBits == videomode.blueBits && this.refreshRate == videomode.refreshRate;
} else {
return false;
}
}
public int hashCode() {
return Objects.hash(this.width, this.height, this.redBits, this.greenBits, this.blueBits, this.refreshRate);
}
public String toString() {
return String.format(Locale.ROOT, "%sx%s@%s (%sbit)", this.width, this.height, this.refreshRate, this.redBits + this.greenBits + this.blueBits);
}
public static Optional<VideoMode> read(@Nullable String pVideoMode) {
if (pVideoMode == null) {
return Optional.empty();
} else {
try {
Matcher matcher = PATTERN.matcher(pVideoMode);
if (matcher.matches()) {
int i = Integer.parseInt(matcher.group(1));
int j = Integer.parseInt(matcher.group(2));
String s = matcher.group(3);
int k;
if (s == null) {
k = 60;
} else {
k = Integer.parseInt(s);
}
String s1 = matcher.group(4);
int l;
if (s1 == null) {
l = 24;
} else {
l = Integer.parseInt(s1);
}
int i1 = l / 3;
return Optional.of(new VideoMode(i, j, i1, i1, i1, k));
}
} catch (Exception exception) {
}
return Optional.empty();
}
}
public String write() {
return String.format(Locale.ROOT, "%sx%s@%s:%s", this.width, this.height, this.refreshRate, this.redBits + this.greenBits + this.blueBits);
}
}
@@ -0,0 +1,464 @@
package com.mojang.blaze3d.platform;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.logging.LogUtils;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.Locale.Category;
import java.util.function.BiConsumer;
import javax.annotation.Nullable;
import net.minecraft.client.Minecraft;
import net.minecraft.client.main.SilentInitException;
import net.minecraft.server.packs.PackResources;
import net.minecraft.server.packs.resources.IoSupplier;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.PointerBuffer;
import org.lwjgl.glfw.Callbacks;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWImage;
import org.lwjgl.opengl.GL;
import org.lwjgl.system.MemoryStack;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.tinyfd.TinyFileDialogs;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public final class Window implements AutoCloseable {
private static final Logger LOGGER = LogUtils.getLogger();
private final GLFWErrorCallback defaultErrorCallback = GLFWErrorCallback.create(this::defaultErrorCallback);
private final WindowEventHandler eventHandler;
private final ScreenManager screenManager;
private final long window;
private int windowedX;
private int windowedY;
private int windowedWidth;
private int windowedHeight;
private Optional<VideoMode> preferredFullscreenVideoMode;
private boolean fullscreen;
private boolean actuallyFullscreen;
private int x;
private int y;
private int width;
private int height;
private int framebufferWidth;
private int framebufferHeight;
private int guiScaledWidth;
private int guiScaledHeight;
private double guiScale;
private String errorSection = "";
private boolean dirty;
private int framerateLimit;
private boolean vsync;
public Window(WindowEventHandler pEventHandler, ScreenManager pScreenManager, DisplayData pDisplayData, @Nullable String pPreferredFullscreenVideoMode, String pTitle) {
RenderSystem.assertInInitPhase();
this.screenManager = pScreenManager;
this.setBootErrorCallback();
this.setErrorSection("Pre startup");
this.eventHandler = pEventHandler;
Optional<VideoMode> optional = VideoMode.read(pPreferredFullscreenVideoMode);
if (optional.isPresent()) {
this.preferredFullscreenVideoMode = optional;
} else if (pDisplayData.fullscreenWidth.isPresent() && pDisplayData.fullscreenHeight.isPresent()) {
this.preferredFullscreenVideoMode = Optional.of(new VideoMode(pDisplayData.fullscreenWidth.getAsInt(), pDisplayData.fullscreenHeight.getAsInt(), 8, 8, 8, 60));
} else {
this.preferredFullscreenVideoMode = Optional.empty();
}
this.actuallyFullscreen = this.fullscreen = pDisplayData.isFullscreen;
Monitor monitor = pScreenManager.getMonitor(GLFW.glfwGetPrimaryMonitor());
this.windowedWidth = this.width = pDisplayData.width > 0 ? pDisplayData.width : 1;
this.windowedHeight = this.height = pDisplayData.height > 0 ? pDisplayData.height : 1;
GLFW.glfwDefaultWindowHints();
GLFW.glfwWindowHint(139265, 196609);
GLFW.glfwWindowHint(139275, 221185);
GLFW.glfwWindowHint(139266, 3);
GLFW.glfwWindowHint(139267, 2);
GLFW.glfwWindowHint(139272, 204801);
GLFW.glfwWindowHint(139270, 1);
this.window = net.minecraftforge.fml.loading.ImmediateWindowHandler.setupMinecraftWindow(()->this.width, ()->this.height, ()->pTitle, ()->this.fullscreen && monitor != null ? monitor.getMonitor() : 0L);
if (!net.minecraftforge.fml.loading.ImmediateWindowHandler.positionWindow(Optional.ofNullable(monitor), w->this.width = this.windowedWidth = w, h->this.height = this.windowedHeight = h, x->this.x = this.windowedX = x, y->this.y = this.windowedY = y)) {
if (monitor != null) {
VideoMode videomode = monitor.getPreferredVidMode(this.fullscreen ? this.preferredFullscreenVideoMode : Optional.empty());
this.windowedX = this.x = monitor.getX() + videomode.getWidth() / 2 - this.width / 2;
this.windowedY = this.y = monitor.getY() + videomode.getHeight() / 2 - this.height / 2;
} else {
int[] aint1 = new int[1];
int[] aint = new int[1];
GLFW.glfwGetWindowPos(this.window, aint1, aint);
this.windowedX = this.x = aint1[0];
this.windowedY = this.y = aint[0];
}
}
GLFW.glfwMakeContextCurrent(this.window);
Locale locale = Locale.getDefault(Category.FORMAT);
Locale.setDefault(Category.FORMAT, Locale.ROOT);
GL.createCapabilities();
Locale.setDefault(Category.FORMAT, locale);
this.setMode();
this.refreshFramebufferSize();
GLFW.glfwSetFramebufferSizeCallback(this.window, this::onFramebufferResize);
GLFW.glfwSetWindowPosCallback(this.window, this::onMove);
GLFW.glfwSetWindowSizeCallback(this.window, this::onResize);
GLFW.glfwSetWindowFocusCallback(this.window, this::onFocus);
GLFW.glfwSetCursorEnterCallback(this.window, this::onEnter);
}
public int getRefreshRate() {
RenderSystem.assertOnRenderThread();
return GLX._getRefreshRate(this);
}
public boolean shouldClose() {
return GLX._shouldClose(this);
}
public static void checkGlfwError(BiConsumer<Integer, String> pErrorConsumer) {
RenderSystem.assertInInitPhase();
try (MemoryStack memorystack = MemoryStack.stackPush()) {
PointerBuffer pointerbuffer = memorystack.mallocPointer(1);
int i = GLFW.glfwGetError(pointerbuffer);
if (i != 0) {
long j = pointerbuffer.get();
String s = j == 0L ? "" : MemoryUtil.memUTF8(j);
pErrorConsumer.accept(i, s);
}
}
}
public void setIcon(PackResources pPackResources, IconSet pIconSet) throws IOException {
RenderSystem.assertInInitPhase();
if (Minecraft.ON_OSX) {
MacosUtil.loadIcon(pIconSet.getMacIcon(pPackResources));
} else {
List<IoSupplier<InputStream>> list = pIconSet.getStandardIcons(pPackResources);
List<ByteBuffer> list1 = new ArrayList<>(list.size());
try (MemoryStack memorystack = MemoryStack.stackPush()) {
GLFWImage.Buffer buffer = GLFWImage.malloc(list.size(), memorystack);
for(int i = 0; i < list.size(); ++i) {
try (NativeImage nativeimage = NativeImage.read(list.get(i).get())) {
ByteBuffer bytebuffer = MemoryUtil.memAlloc(nativeimage.getWidth() * nativeimage.getHeight() * 4);
list1.add(bytebuffer);
bytebuffer.asIntBuffer().put(nativeimage.getPixelsRGBA());
buffer.position(i);
buffer.width(nativeimage.getWidth());
buffer.height(nativeimage.getHeight());
buffer.pixels(bytebuffer);
}
}
GLFW.glfwSetWindowIcon(this.window, buffer.position(0));
} finally {
list1.forEach(MemoryUtil::memFree);
}
}
}
public void setErrorSection(String pErrorSection) {
this.errorSection = pErrorSection;
}
private void setBootErrorCallback() {
RenderSystem.assertInInitPhase();
GLFW.glfwSetErrorCallback(Window::bootCrash);
}
private static void bootCrash(int p_85413_, long p_85414_) {
RenderSystem.assertInInitPhase();
String s = "GLFW error " + p_85413_ + ": " + MemoryUtil.memUTF8(p_85414_);
TinyFileDialogs.tinyfd_messageBox("Minecraft", s + ".\n\nPlease make sure you have up-to-date drivers (see aka.ms/mcdriver for instructions).", "ok", "error", false);
throw new Window.WindowInitFailed(s);
}
public void defaultErrorCallback(int p_85383_, long p_85384_) {
RenderSystem.assertOnRenderThread();
String s = MemoryUtil.memUTF8(p_85384_);
LOGGER.error("########## GL ERROR ##########");
LOGGER.error("@ {}", (Object)this.errorSection);
LOGGER.error("{}: {}", p_85383_, s);
}
public void setDefaultErrorCallback() {
GLFWErrorCallback glfwerrorcallback = GLFW.glfwSetErrorCallback(this.defaultErrorCallback);
if (glfwerrorcallback != null) {
glfwerrorcallback.free();
}
}
public void updateVsync(boolean pVsync) {
RenderSystem.assertOnRenderThreadOrInit();
this.vsync = pVsync;
GLFW.glfwSwapInterval(pVsync ? 1 : 0);
}
public void close() {
RenderSystem.assertOnRenderThread();
Callbacks.glfwFreeCallbacks(this.window);
this.defaultErrorCallback.close();
GLFW.glfwDestroyWindow(this.window);
GLFW.glfwTerminate();
}
private void onMove(long p_85389_, int p_85390_, int p_85391_) {
this.x = p_85390_;
this.y = p_85391_;
}
private void onFramebufferResize(long p_85416_, int p_85417_, int p_85418_) {
if (p_85416_ == this.window) {
int i = this.getWidth();
int j = this.getHeight();
if (p_85417_ != 0 && p_85418_ != 0) {
this.framebufferWidth = p_85417_;
this.framebufferHeight = p_85418_;
if (this.getWidth() != i || this.getHeight() != j) {
this.eventHandler.resizeDisplay();
}
}
}
}
private void refreshFramebufferSize() {
RenderSystem.assertInInitPhase();
int[] aint = new int[1];
int[] aint1 = new int[1];
GLFW.glfwGetFramebufferSize(this.window, aint, aint1);
this.framebufferWidth = aint[0] > 0 ? aint[0] : 1;
this.framebufferHeight = aint1[0] > 0 ? aint1[0] : 1;
if (this.framebufferHeight == 0 || this.framebufferWidth==0) net.minecraftforge.fml.loading.ImmediateWindowHandler.updateFBSize(w->this.framebufferWidth=w, h->this.framebufferHeight=h);
}
private void onResize(long p_85428_, int p_85429_, int p_85430_) {
this.width = p_85429_;
this.height = p_85430_;
}
private void onFocus(long p_85393_, boolean p_85394_) {
if (p_85393_ == this.window) {
this.eventHandler.setWindowActive(p_85394_);
}
}
/**
*
* @param p_85421_ {@code true} if the cursor entered the window, {@code false} if the cursor left
*/
private void onEnter(long p_85420_, boolean p_85421_) {
if (p_85421_) {
this.eventHandler.cursorEntered();
}
}
public void setFramerateLimit(int pLimit) {
this.framerateLimit = pLimit;
}
public int getFramerateLimit() {
return this.framerateLimit;
}
public void updateDisplay() {
RenderSystem.flipFrame(this.window);
if (this.fullscreen != this.actuallyFullscreen) {
this.actuallyFullscreen = this.fullscreen;
this.updateFullscreen(this.vsync);
}
}
public Optional<VideoMode> getPreferredFullscreenVideoMode() {
return this.preferredFullscreenVideoMode;
}
public void setPreferredFullscreenVideoMode(Optional<VideoMode> pPreferredFullscreenVideoMode) {
boolean flag = !pPreferredFullscreenVideoMode.equals(this.preferredFullscreenVideoMode);
this.preferredFullscreenVideoMode = pPreferredFullscreenVideoMode;
if (flag) {
this.dirty = true;
}
}
public void changeFullscreenVideoMode() {
if (this.fullscreen && this.dirty) {
this.dirty = false;
this.setMode();
this.eventHandler.resizeDisplay();
}
}
private void setMode() {
RenderSystem.assertInInitPhase();
boolean flag = GLFW.glfwGetWindowMonitor(this.window) != 0L;
if (this.fullscreen) {
Monitor monitor = this.screenManager.findBestMonitor(this);
if (monitor == null) {
LOGGER.warn("Failed to find suitable monitor for fullscreen mode");
this.fullscreen = false;
} else {
if (Minecraft.ON_OSX) {
MacosUtil.toggleFullscreen(this.window);
}
VideoMode videomode = monitor.getPreferredVidMode(this.preferredFullscreenVideoMode);
if (!flag) {
this.windowedX = this.x;
this.windowedY = this.y;
this.windowedWidth = this.width;
this.windowedHeight = this.height;
}
this.x = 0;
this.y = 0;
this.width = videomode.getWidth();
this.height = videomode.getHeight();
GLFW.glfwSetWindowMonitor(this.window, monitor.getMonitor(), this.x, this.y, this.width, this.height, videomode.getRefreshRate());
}
} else {
this.x = this.windowedX;
this.y = this.windowedY;
this.width = this.windowedWidth;
this.height = this.windowedHeight;
GLFW.glfwSetWindowMonitor(this.window, 0L, this.x, this.y, this.width, this.height, -1);
}
}
public void toggleFullScreen() {
this.fullscreen = !this.fullscreen;
}
public void setWindowed(int pWindowedWidth, int pWindowedHeight) {
this.windowedWidth = pWindowedWidth;
this.windowedHeight = pWindowedHeight;
this.fullscreen = false;
this.setMode();
}
private void updateFullscreen(boolean pVsyncEnabled) {
RenderSystem.assertOnRenderThread();
try {
this.setMode();
this.eventHandler.resizeDisplay();
this.updateVsync(pVsyncEnabled);
this.updateDisplay();
} catch (Exception exception) {
LOGGER.error("Couldn't toggle fullscreen", (Throwable)exception);
}
}
public int calculateScale(int pGuiScale, boolean pForceUnicode) {
int i;
for(i = 1; i != pGuiScale && i < this.framebufferWidth && i < this.framebufferHeight && this.framebufferWidth / (i + 1) >= 320 && this.framebufferHeight / (i + 1) >= 240; ++i) {
}
if (pForceUnicode && i % 2 != 0) {
++i;
}
return i;
}
public void setGuiScale(double pScaleFactor) {
this.guiScale = pScaleFactor;
int i = (int)((double)this.framebufferWidth / pScaleFactor);
this.guiScaledWidth = (double)this.framebufferWidth / pScaleFactor > (double)i ? i + 1 : i;
int j = (int)((double)this.framebufferHeight / pScaleFactor);
this.guiScaledHeight = (double)this.framebufferHeight / pScaleFactor > (double)j ? j + 1 : j;
}
public void setTitle(String pTitle) {
GLFW.glfwSetWindowTitle(this.window, pTitle);
}
/**
* Gets a pointer to the native window object that is passed to GLFW.
*/
public long getWindow() {
return this.window;
}
public boolean isFullscreen() {
return this.fullscreen;
}
public int getWidth() {
return this.framebufferWidth;
}
public int getHeight() {
return this.framebufferHeight;
}
public void setWidth(int pFramebufferWidth) {
this.framebufferWidth = pFramebufferWidth;
}
public void setHeight(int pFramebufferHeight) {
this.framebufferHeight = pFramebufferHeight;
}
public int getScreenWidth() {
return this.width;
}
public int getScreenHeight() {
return this.height;
}
public int getGuiScaledWidth() {
return this.guiScaledWidth;
}
public int getGuiScaledHeight() {
return this.guiScaledHeight;
}
public int getX() {
return this.x;
}
public int getY() {
return this.y;
}
public double getGuiScale() {
return this.guiScale;
}
@Nullable
public Monitor findBestMonitor() {
return this.screenManager.findBestMonitor(this);
}
public void updateRawMouseInput(boolean pEnableRawMouseMotion) {
InputConstants.updateRawMouseInput(this.window, pEnableRawMouseMotion);
}
@OnlyIn(Dist.CLIENT)
public static class WindowInitFailed extends SilentInitException {
WindowInitFailed(String p_85455_) {
super(p_85455_);
}
}
}
@@ -0,0 +1,13 @@
package com.mojang.blaze3d.platform;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public interface WindowEventHandler {
void setWindowActive(boolean pWindowActive);
void resizeDisplay();
void cursorEntered();
}
@@ -0,0 +1,11 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
@OnlyIn(Dist.CLIENT)
package com.mojang.blaze3d.platform;
import com.mojang.blaze3d.FieldsAreNonnullByDefault;
import com.mojang.blaze3d.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -0,0 +1,126 @@
package com.mojang.blaze3d.preprocessor;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import java.util.List;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import net.minecraft.FileUtil;
import net.minecraft.Util;
import net.minecraft.util.StringUtil;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public abstract class GlslPreprocessor {
private static final String C_COMMENT = "/\\*(?:[^*]|\\*+[^*/])*\\*+/";
private static final String LINE_COMMENT = "//[^\\v]*";
private static final Pattern REGEX_MOJ_IMPORT = Pattern.compile("(#(?:/\\*(?:[^*]|\\*+[^*/])*\\*+/|\\h)*moj_import(?:/\\*(?:[^*]|\\*+[^*/])*\\*+/|\\h)*(?:\"(.*)\"|<(.*)>))");
private static final Pattern REGEX_VERSION = Pattern.compile("(#(?:/\\*(?:[^*]|\\*+[^*/])*\\*+/|\\h)*version(?:/\\*(?:[^*]|\\*+[^*/])*\\*+/|\\h)*(\\d+))\\b");
private static final Pattern REGEX_ENDS_WITH_WHITESPACE = Pattern.compile("(?:^|\\v)(?:\\s|/\\*(?:[^*]|\\*+[^*/])*\\*+/|(//[^\\v]*))*\\z");
public List<String> process(String pShaderData) {
GlslPreprocessor.Context glslpreprocessor$context = new GlslPreprocessor.Context();
List<String> list = this.processImports(pShaderData, glslpreprocessor$context, "");
list.set(0, this.setVersion(list.get(0), glslpreprocessor$context.glslVersion));
return list;
}
private List<String> processImports(String pShaderData, GlslPreprocessor.Context pContext, String pIncludeDirectory) {
int i = pContext.sourceId;
int j = 0;
String s = "";
List<String> list = Lists.newArrayList();
Matcher matcher = REGEX_MOJ_IMPORT.matcher(pShaderData);
while(matcher.find()) {
if (!isDirectiveDisabled(pShaderData, matcher, j)) {
String s1 = matcher.group(2);
boolean flag = s1 != null;
if (!flag) {
s1 = matcher.group(3);
}
if (s1 != null) {
String s2 = pShaderData.substring(j, matcher.start(1));
String s3 = pIncludeDirectory + s1;
String s4 = this.applyImport(flag, s3);
if (!Strings.isNullOrEmpty(s4)) {
if (!StringUtil.endsWithNewLine(s4)) {
s4 = s4 + System.lineSeparator();
}
++pContext.sourceId;
int k = pContext.sourceId;
List<String> list1 = this.processImports(s4, pContext, flag ? FileUtil.getFullResourcePath(s3) : "");
list1.set(0, String.format(Locale.ROOT, "#line %d %d\n%s", 0, k, this.processVersions(list1.get(0), pContext)));
if (!Util.isBlank(s2)) {
list.add(s2);
}
list.addAll(list1);
} else {
String s6 = flag ? String.format(Locale.ROOT, "/*#moj_import \"%s\"*/", s1) : String.format(Locale.ROOT, "/*#moj_import <%s>*/", s1);
list.add(s + s2 + s6);
}
int l = StringUtil.lineCount(pShaderData.substring(0, matcher.end(1)));
s = String.format(Locale.ROOT, "#line %d %d", l, i);
j = matcher.end(1);
}
}
}
String s5 = pShaderData.substring(j);
if (!Util.isBlank(s5)) {
list.add(s + s5);
}
return list;
}
private String processVersions(String pVersionData, GlslPreprocessor.Context pContext) {
Matcher matcher = REGEX_VERSION.matcher(pVersionData);
if (matcher.find() && isDirectiveEnabled(pVersionData, matcher)) {
pContext.glslVersion = Math.max(pContext.glslVersion, Integer.parseInt(matcher.group(2)));
return pVersionData.substring(0, matcher.start(1)) + "/*" + pVersionData.substring(matcher.start(1), matcher.end(1)) + "*/" + pVersionData.substring(matcher.end(1));
} else {
return pVersionData;
}
}
private String setVersion(String pVersionData, int pGlslVersion) {
Matcher matcher = REGEX_VERSION.matcher(pVersionData);
return matcher.find() && isDirectiveEnabled(pVersionData, matcher) ? pVersionData.substring(0, matcher.start(2)) + Math.max(pGlslVersion, Integer.parseInt(matcher.group(2))) + pVersionData.substring(matcher.end(2)) : pVersionData;
}
private static boolean isDirectiveEnabled(String pShaderData, Matcher pMatcher) {
return !isDirectiveDisabled(pShaderData, pMatcher, 0);
}
private static boolean isDirectiveDisabled(String pShaderData, Matcher pMatcher, int pOffset) {
int i = pMatcher.start() - pOffset;
if (i == 0) {
return false;
} else {
Matcher matcher = REGEX_ENDS_WITH_WHITESPACE.matcher(pShaderData.substring(pOffset, pMatcher.start()));
if (!matcher.find()) {
return true;
} else {
int j = matcher.end(1);
return j == pMatcher.start();
}
}
}
@Nullable
public abstract String applyImport(boolean pUseFullPath, String pDirectory);
@OnlyIn(Dist.CLIENT)
static final class Context {
int glslVersion;
int sourceId;
}
}
@@ -0,0 +1,11 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
@OnlyIn(Dist.CLIENT)
package com.mojang.blaze3d.preprocessor;
import com.mojang.blaze3d.FieldsAreNonnullByDefault;
import com.mojang.blaze3d.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -0,0 +1,83 @@
package com.mojang.blaze3d.shaders;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
@OnlyIn(Dist.CLIENT)
public class AbstractUniform {
public void set(float pX) {
}
public void set(float pX, float pY) {
}
public void set(float pX, float pY, float pZ) {
}
public void set(float pX, float pY, float pZ, float pW) {
}
public void setSafe(float pX, float pY, float pZ, float pW) {
}
public void setSafe(int pX, int pY, int pZ, int pW) {
}
public void set(int pX) {
}
public void set(int pX, int pY) {
}
public void set(int pX, int pY, int pZ) {
}
public void set(int pX, int pY, int pZ, int pW) {
}
public void set(float[] pValueArray) {
}
public void set(Vector3f pVector) {
}
public void set(Vector4f pVector) {
}
public void setMat2x2(float pM00, float pM01, float pM10, float pM11) {
}
public void setMat2x3(float pM00, float pM01, float pM02, float pM10, float pM11, float pM12) {
}
public void setMat2x4(float pM00, float pM01, float pM02, float pM03, float pM10, float pM11, float pM12, float pM13) {
}
public void setMat3x2(float pM00, float pM01, float pM10, float pM11, float pM20, float pM21) {
}
public void setMat3x3(float pM00, float pM01, float pM02, float pM10, float pM11, float pM12, float pM20, float pM21, float pM22) {
}
public void setMat3x4(float pM00, float pM01, float pM02, float pM03, float pM10, float pM11, float pM12, float pM13, float pM20, float pM21, float pM22, float pM23) {
}
public void setMat4x2(float pM00, float pM01, float pM02, float pM03, float pM10, float pM11, float pM12, float pM13) {
}
public void setMat4x3(float pM00, float pM01, float pM02, float pM03, float pM10, float pM11, float pM12, float pM13, float pM20, float pM21, float pM22, float pM23) {
}
public void setMat4x4(float pM00, float pM01, float pM02, float pM03, float pM10, float pM11, float pM12, float pM13, float pM20, float pM21, float pM22, float pM23, float pM30, float pM31, float pM32, float pM33) {
}
public void set(Matrix4f pMatrix) {
}
public void set(Matrix3f pMatrix) {
}
}
@@ -0,0 +1,152 @@
package com.mojang.blaze3d.shaders;
import com.mojang.blaze3d.systems.RenderSystem;
import java.util.Locale;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class BlendMode {
@Nullable
private static BlendMode lastApplied;
private final int srcColorFactor;
private final int srcAlphaFactor;
private final int dstColorFactor;
private final int dstAlphaFactor;
private final int blendFunc;
private final boolean separateBlend;
private final boolean opaque;
private BlendMode(boolean pSeparateBlend, boolean pOpaque, int pSrcColorFactor, int pDstColorFactor, int pSrcAlphaFactor, int pDstAlphaFactor, int pBlendFunc) {
this.separateBlend = pSeparateBlend;
this.srcColorFactor = pSrcColorFactor;
this.dstColorFactor = pDstColorFactor;
this.srcAlphaFactor = pSrcAlphaFactor;
this.dstAlphaFactor = pDstAlphaFactor;
this.opaque = pOpaque;
this.blendFunc = pBlendFunc;
}
public BlendMode() {
this(false, true, 1, 0, 1, 0, 32774);
}
public BlendMode(int pSrcFactor, int pDstFactor, int pBlendFunc) {
this(false, false, pSrcFactor, pDstFactor, pSrcFactor, pDstFactor, pBlendFunc);
}
public BlendMode(int pSrcColorFactor, int pDstColorFactor, int pSrcAlphaFactor, int pDstAlphaFactor, int pBlendFunc) {
this(true, false, pSrcColorFactor, pDstColorFactor, pSrcAlphaFactor, pDstAlphaFactor, pBlendFunc);
}
public void apply() {
if (!this.equals(lastApplied)) {
if (lastApplied == null || this.opaque != lastApplied.isOpaque()) {
lastApplied = this;
if (this.opaque) {
RenderSystem.disableBlend();
return;
}
RenderSystem.enableBlend();
}
RenderSystem.blendEquation(this.blendFunc);
if (this.separateBlend) {
RenderSystem.blendFuncSeparate(this.srcColorFactor, this.dstColorFactor, this.srcAlphaFactor, this.dstAlphaFactor);
} else {
RenderSystem.blendFunc(this.srcColorFactor, this.dstColorFactor);
}
}
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else if (!(pOther instanceof BlendMode)) {
return false;
} else {
BlendMode blendmode = (BlendMode)pOther;
if (this.blendFunc != blendmode.blendFunc) {
return false;
} else if (this.dstAlphaFactor != blendmode.dstAlphaFactor) {
return false;
} else if (this.dstColorFactor != blendmode.dstColorFactor) {
return false;
} else if (this.opaque != blendmode.opaque) {
return false;
} else if (this.separateBlend != blendmode.separateBlend) {
return false;
} else if (this.srcAlphaFactor != blendmode.srcAlphaFactor) {
return false;
} else {
return this.srcColorFactor == blendmode.srcColorFactor;
}
}
}
public int hashCode() {
int i = this.srcColorFactor;
i = 31 * i + this.srcAlphaFactor;
i = 31 * i + this.dstColorFactor;
i = 31 * i + this.dstAlphaFactor;
i = 31 * i + this.blendFunc;
i = 31 * i + (this.separateBlend ? 1 : 0);
return 31 * i + (this.opaque ? 1 : 0);
}
public boolean isOpaque() {
return this.opaque;
}
/**
* Converts a blend function name to an id, returning add (32774) if not recognized.
*/
public static int stringToBlendFunc(String pFuncName) {
String s = pFuncName.trim().toLowerCase(Locale.ROOT);
if ("add".equals(s)) {
return 32774;
} else if ("subtract".equals(s)) {
return 32778;
} else if ("reversesubtract".equals(s)) {
return 32779;
} else if ("reverse_subtract".equals(s)) {
return 32779;
} else if ("min".equals(s)) {
return 32775;
} else {
return "max".equals(s) ? '\u8008' : '\u8006';
}
}
public static int stringToBlendFactor(String pFactorName) {
String s = pFactorName.trim().toLowerCase(Locale.ROOT);
s = s.replaceAll("_", "");
s = s.replaceAll("one", "1");
s = s.replaceAll("zero", "0");
s = s.replaceAll("minus", "-");
if ("0".equals(s)) {
return 0;
} else if ("1".equals(s)) {
return 1;
} else if ("srccolor".equals(s)) {
return 768;
} else if ("1-srccolor".equals(s)) {
return 769;
} else if ("dstcolor".equals(s)) {
return 774;
} else if ("1-dstcolor".equals(s)) {
return 775;
} else if ("srcalpha".equals(s)) {
return 770;
} else if ("1-srcalpha".equals(s)) {
return 771;
} else if ("dstalpha".equals(s)) {
return 772;
} else {
return "1-dstalpha".equals(s) ? 773 : -1;
}
}
}
@@ -0,0 +1,8 @@
package com.mojang.blaze3d.shaders;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public interface Effect extends Shader {
}
@@ -0,0 +1,45 @@
package com.mojang.blaze3d.shaders;
import com.mojang.blaze3d.preprocessor.GlslPreprocessor;
import com.mojang.blaze3d.systems.RenderSystem;
import java.io.IOException;
import java.io.InputStream;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class EffectProgram extends Program {
private static final GlslPreprocessor PREPROCESSOR = new GlslPreprocessor() {
public String applyImport(boolean p_166595_, String p_166596_) {
return "#error Import statement not supported";
}
};
private int references;
private EffectProgram(Program.Type pType, int pId, String pName) {
super(pType, pId, pName);
}
public void attachToEffect(Effect pEffect) {
RenderSystem.assertOnRenderThread();
++this.references;
this.attachToShader(pEffect);
}
public void close() {
RenderSystem.assertOnRenderThread();
--this.references;
if (this.references <= 0) {
super.close();
}
}
public static EffectProgram compileShader(Program.Type pType, String pName, InputStream pShaderData, String pSourceName) throws IOException {
RenderSystem.assertOnRenderThread();
int i = compileShaderInternal(pType, pName, pShaderData, pSourceName, PREPROCESSOR);
EffectProgram effectprogram = new EffectProgram(pType, i, pName);
pType.getPrograms().put(pName, effectprogram);
return effectprogram;
}
}
@@ -0,0 +1,20 @@
package com.mojang.blaze3d.shaders;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public enum FogShape {
SPHERE(0),
CYLINDER(1);
private final int index;
private FogShape(int p_202323_) {
this.index = p_202323_;
}
public int getIndex() {
return this.index;
}
}
@@ -0,0 +1,108 @@
package com.mojang.blaze3d.shaders;
import com.google.common.collect.Maps;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.preprocessor.GlslPreprocessor;
import com.mojang.blaze3d.systems.RenderSystem;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
@OnlyIn(Dist.CLIENT)
public class Program {
private static final int MAX_LOG_LENGTH = 32768;
private final Program.Type type;
private final String name;
private int id;
protected Program(Program.Type pType, int pId, String pName) {
this.type = pType;
this.id = pId;
this.name = pName;
}
public void attachToShader(Shader pShader) {
RenderSystem.assertOnRenderThread();
GlStateManager.glAttachShader(pShader.getId(), this.getId());
}
public void close() {
if (this.id != -1) {
RenderSystem.assertOnRenderThread();
GlStateManager.glDeleteShader(this.id);
this.id = -1;
this.type.getPrograms().remove(this.name);
}
}
public String getName() {
return this.name;
}
public static Program compileShader(Program.Type pType, String pName, InputStream pShaderData, String pSourceName, GlslPreprocessor pPreprocessor) throws IOException {
RenderSystem.assertOnRenderThread();
int i = compileShaderInternal(pType, pName, pShaderData, pSourceName, pPreprocessor);
Program program = new Program(pType, i, pName);
pType.getPrograms().put(pName, program);
return program;
}
protected static int compileShaderInternal(Program.Type pType, String pName, InputStream pShaderData, String pSourceName, GlslPreprocessor pPreprocessor) throws IOException {
String s = IOUtils.toString(pShaderData, StandardCharsets.UTF_8);
if (s == null) {
throw new IOException("Could not load program " + pType.getName());
} else {
int i = GlStateManager.glCreateShader(pType.getGlType());
GlStateManager.glShaderSource(i, pPreprocessor.process(s));
GlStateManager.glCompileShader(i);
if (GlStateManager.glGetShaderi(i, 35713) == 0) {
String s1 = StringUtils.trim(GlStateManager.glGetShaderInfoLog(i, 32768));
throw new IOException("Couldn't compile " + pType.getName() + " program (" + pSourceName + ", " + pName + ") : " + s1);
} else {
return i;
}
}
}
protected int getId() {
return this.id;
}
@OnlyIn(Dist.CLIENT)
public static enum Type {
VERTEX("vertex", ".vsh", 35633),
FRAGMENT("fragment", ".fsh", 35632);
private final String name;
private final String extension;
private final int glType;
private final Map<String, Program> programs = Maps.newHashMap();
private Type(String pName, String pExtension, int pGlType) {
this.name = pName;
this.extension = pExtension;
this.glType = pGlType;
}
public String getName() {
return this.name;
}
public String getExtension() {
return this.extension;
}
int getGlType() {
return this.glType;
}
public Map<String, Program> getPrograms() {
return this.programs;
}
}
}
@@ -0,0 +1,48 @@
package com.mojang.blaze3d.shaders;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.logging.LogUtils;
import java.io.IOException;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class ProgramManager {
private static final Logger LOGGER = LogUtils.getLogger();
public static void glUseProgram(int pProgram) {
RenderSystem.assertOnRenderThread();
GlStateManager._glUseProgram(pProgram);
}
public static void releaseProgram(Shader pShader) {
RenderSystem.assertOnRenderThread();
pShader.getFragmentProgram().close();
pShader.getVertexProgram().close();
GlStateManager.glDeleteProgram(pShader.getId());
}
public static int createProgram() throws IOException {
RenderSystem.assertOnRenderThread();
int i = GlStateManager.glCreateProgram();
if (i <= 0) {
throw new IOException("Could not create shader program (returned program ID " + i + ")");
} else {
return i;
}
}
public static void linkShader(Shader pShader) {
RenderSystem.assertOnRenderThread();
pShader.attachToProgram();
GlStateManager.glLinkProgram(pShader.getId());
int i = GlStateManager.glGetProgrami(pShader.getId(), 35714);
if (i == 0) {
LOGGER.warn("Error encountered when linking program containing VS {} and FS {}. Log output:", pShader.getVertexProgram().getName(), pShader.getFragmentProgram().getName());
LOGGER.warn(GlStateManager.glGetProgramInfoLog(pShader.getId(), 32768));
}
}
}
@@ -0,0 +1,17 @@
package com.mojang.blaze3d.shaders;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public interface Shader {
int getId();
void markDirty();
Program getVertexProgram();
Program getFragmentProgram();
void attachToProgram();
}
@@ -0,0 +1,486 @@
package com.mojang.blaze3d.shaders;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.logging.LogUtils;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import org.lwjgl.system.MemoryUtil;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class Uniform extends AbstractUniform implements AutoCloseable {
private static final Logger LOGGER = LogUtils.getLogger();
public static final int UT_INT1 = 0;
public static final int UT_INT2 = 1;
public static final int UT_INT3 = 2;
public static final int UT_INT4 = 3;
public static final int UT_FLOAT1 = 4;
public static final int UT_FLOAT2 = 5;
public static final int UT_FLOAT3 = 6;
public static final int UT_FLOAT4 = 7;
public static final int UT_MAT2 = 8;
public static final int UT_MAT3 = 9;
public static final int UT_MAT4 = 10;
private static final boolean TRANSPOSE_MATRICIES = false;
private int location;
private final int count;
private final int type;
private final IntBuffer intValues;
private final FloatBuffer floatValues;
private final String name;
private boolean dirty;
private final Shader parent;
public Uniform(String pName, int pType, int pCount, Shader pParent) {
this.name = pName;
this.count = pCount;
this.type = pType;
this.parent = pParent;
if (pType <= 3) {
this.intValues = MemoryUtil.memAllocInt(pCount);
this.floatValues = null;
} else {
this.intValues = null;
this.floatValues = MemoryUtil.memAllocFloat(pCount);
}
this.location = -1;
this.markDirty();
}
public static int glGetUniformLocation(int pProgram, CharSequence pName) {
return GlStateManager._glGetUniformLocation(pProgram, pName);
}
public static void uploadInteger(int pLocation, int pValue) {
RenderSystem.glUniform1i(pLocation, pValue);
}
public static int glGetAttribLocation(int pProgram, CharSequence pName) {
return GlStateManager._glGetAttribLocation(pProgram, pName);
}
public static void glBindAttribLocation(int pProgram, int pIndex, CharSequence pName) {
GlStateManager._glBindAttribLocation(pProgram, pIndex, pName);
}
public void close() {
if (this.intValues != null) {
MemoryUtil.memFree(this.intValues);
}
if (this.floatValues != null) {
MemoryUtil.memFree(this.floatValues);
}
}
private void markDirty() {
this.dirty = true;
if (this.parent != null) {
this.parent.markDirty();
}
}
public static int getTypeFromString(String pTypeName) {
int i = -1;
if ("int".equals(pTypeName)) {
i = 0;
} else if ("float".equals(pTypeName)) {
i = 4;
} else if (pTypeName.startsWith("matrix")) {
if (pTypeName.endsWith("2x2")) {
i = 8;
} else if (pTypeName.endsWith("3x3")) {
i = 9;
} else if (pTypeName.endsWith("4x4")) {
i = 10;
}
}
return i;
}
public void setLocation(int pLocation) {
this.location = pLocation;
}
public String getName() {
return this.name;
}
public final void set(float pX) {
this.floatValues.position(0);
this.floatValues.put(0, pX);
this.markDirty();
}
public final void set(float pX, float pY) {
this.floatValues.position(0);
this.floatValues.put(0, pX);
this.floatValues.put(1, pY);
this.markDirty();
}
public final void set(int pIndex, float pValue) {
this.floatValues.position(0);
this.floatValues.put(pIndex, pValue);
this.markDirty();
}
public final void set(float pX, float pY, float pZ) {
this.floatValues.position(0);
this.floatValues.put(0, pX);
this.floatValues.put(1, pY);
this.floatValues.put(2, pZ);
this.markDirty();
}
public final void set(Vector3f pVector) {
this.floatValues.position(0);
pVector.get(this.floatValues);
this.markDirty();
}
public final void set(float pX, float pY, float pZ, float pW) {
this.floatValues.position(0);
this.floatValues.put(pX);
this.floatValues.put(pY);
this.floatValues.put(pZ);
this.floatValues.put(pW);
this.floatValues.flip();
this.markDirty();
}
public final void set(Vector4f pVector) {
this.floatValues.position(0);
pVector.get(this.floatValues);
this.markDirty();
}
public final void setSafe(float pX, float pY, float pZ, float pW) {
this.floatValues.position(0);
if (this.type >= 4) {
this.floatValues.put(0, pX);
}
if (this.type >= 5) {
this.floatValues.put(1, pY);
}
if (this.type >= 6) {
this.floatValues.put(2, pZ);
}
if (this.type >= 7) {
this.floatValues.put(3, pW);
}
this.markDirty();
}
public final void setSafe(int pX, int pY, int pZ, int pW) {
this.intValues.position(0);
if (this.type >= 0) {
this.intValues.put(0, pX);
}
if (this.type >= 1) {
this.intValues.put(1, pY);
}
if (this.type >= 2) {
this.intValues.put(2, pZ);
}
if (this.type >= 3) {
this.intValues.put(3, pW);
}
this.markDirty();
}
public final void set(int pX) {
this.intValues.position(0);
this.intValues.put(0, pX);
this.markDirty();
}
public final void set(int pX, int pY) {
this.intValues.position(0);
this.intValues.put(0, pX);
this.intValues.put(1, pY);
this.markDirty();
}
public final void set(int pX, int pY, int pZ) {
this.intValues.position(0);
this.intValues.put(0, pX);
this.intValues.put(1, pY);
this.intValues.put(2, pZ);
this.markDirty();
}
public final void set(int pX, int pY, int pZ, int pW) {
this.intValues.position(0);
this.intValues.put(0, pX);
this.intValues.put(1, pY);
this.intValues.put(2, pZ);
this.intValues.put(3, pW);
this.markDirty();
}
public final void set(float[] pValueArray) {
if (pValueArray.length < this.count) {
LOGGER.warn("Uniform.set called with a too-small value array (expected {}, got {}). Ignoring.", this.count, pValueArray.length);
} else {
this.floatValues.position(0);
this.floatValues.put(pValueArray);
this.floatValues.position(0);
this.markDirty();
}
}
public final void setMat2x2(float pM00, float pM01, float pM10, float pM11) {
this.floatValues.position(0);
this.floatValues.put(0, pM00);
this.floatValues.put(1, pM01);
this.floatValues.put(2, pM10);
this.floatValues.put(3, pM11);
this.markDirty();
}
public final void setMat2x3(float pM00, float pM01, float pM02, float pM10, float pM11, float pM12) {
this.floatValues.position(0);
this.floatValues.put(0, pM00);
this.floatValues.put(1, pM01);
this.floatValues.put(2, pM02);
this.floatValues.put(3, pM10);
this.floatValues.put(4, pM11);
this.floatValues.put(5, pM12);
this.markDirty();
}
public final void setMat2x4(float pM00, float pM01, float pM02, float pM03, float pM10, float pM11, float pM12, float pM13) {
this.floatValues.position(0);
this.floatValues.put(0, pM00);
this.floatValues.put(1, pM01);
this.floatValues.put(2, pM02);
this.floatValues.put(3, pM03);
this.floatValues.put(4, pM10);
this.floatValues.put(5, pM11);
this.floatValues.put(6, pM12);
this.floatValues.put(7, pM13);
this.markDirty();
}
public final void setMat3x2(float pM00, float pM01, float pM10, float pM11, float pM20, float pM21) {
this.floatValues.position(0);
this.floatValues.put(0, pM00);
this.floatValues.put(1, pM01);
this.floatValues.put(2, pM10);
this.floatValues.put(3, pM11);
this.floatValues.put(4, pM20);
this.floatValues.put(5, pM21);
this.markDirty();
}
public final void setMat3x3(float pM00, float pM01, float pM02, float pM10, float pM11, float pM12, float pM20, float pM21, float pM22) {
this.floatValues.position(0);
this.floatValues.put(0, pM00);
this.floatValues.put(1, pM01);
this.floatValues.put(2, pM02);
this.floatValues.put(3, pM10);
this.floatValues.put(4, pM11);
this.floatValues.put(5, pM12);
this.floatValues.put(6, pM20);
this.floatValues.put(7, pM21);
this.floatValues.put(8, pM22);
this.markDirty();
}
public final void setMat3x4(float pM00, float pM01, float pM02, float pM03, float pM10, float pM11, float pM12, float pM13, float pM20, float pM21, float pM22, float pM23) {
this.floatValues.position(0);
this.floatValues.put(0, pM00);
this.floatValues.put(1, pM01);
this.floatValues.put(2, pM02);
this.floatValues.put(3, pM03);
this.floatValues.put(4, pM10);
this.floatValues.put(5, pM11);
this.floatValues.put(6, pM12);
this.floatValues.put(7, pM13);
this.floatValues.put(8, pM20);
this.floatValues.put(9, pM21);
this.floatValues.put(10, pM22);
this.floatValues.put(11, pM23);
this.markDirty();
}
public final void setMat4x2(float pM00, float pM01, float pM02, float pM03, float pM10, float pM11, float pM12, float pM13) {
this.floatValues.position(0);
this.floatValues.put(0, pM00);
this.floatValues.put(1, pM01);
this.floatValues.put(2, pM02);
this.floatValues.put(3, pM03);
this.floatValues.put(4, pM10);
this.floatValues.put(5, pM11);
this.floatValues.put(6, pM12);
this.floatValues.put(7, pM13);
this.markDirty();
}
public final void setMat4x3(float pM00, float pM01, float pM02, float pM03, float pM10, float pM11, float pM12, float pM13, float pM20, float pM21, float pM22, float pM23) {
this.floatValues.position(0);
this.floatValues.put(0, pM00);
this.floatValues.put(1, pM01);
this.floatValues.put(2, pM02);
this.floatValues.put(3, pM03);
this.floatValues.put(4, pM10);
this.floatValues.put(5, pM11);
this.floatValues.put(6, pM12);
this.floatValues.put(7, pM13);
this.floatValues.put(8, pM20);
this.floatValues.put(9, pM21);
this.floatValues.put(10, pM22);
this.floatValues.put(11, pM23);
this.markDirty();
}
public final void setMat4x4(float pM00, float pM01, float pM02, float pM03, float pM10, float pM11, float pM12, float pM13, float pM20, float pM21, float pM22, float pM23, float pM30, float pM31, float pM32, float pM33) {
this.floatValues.position(0);
this.floatValues.put(0, pM00);
this.floatValues.put(1, pM01);
this.floatValues.put(2, pM02);
this.floatValues.put(3, pM03);
this.floatValues.put(4, pM10);
this.floatValues.put(5, pM11);
this.floatValues.put(6, pM12);
this.floatValues.put(7, pM13);
this.floatValues.put(8, pM20);
this.floatValues.put(9, pM21);
this.floatValues.put(10, pM22);
this.floatValues.put(11, pM23);
this.floatValues.put(12, pM30);
this.floatValues.put(13, pM31);
this.floatValues.put(14, pM32);
this.floatValues.put(15, pM33);
this.markDirty();
}
public final void set(Matrix4f pMatrix) {
this.floatValues.position(0);
pMatrix.get(this.floatValues);
this.markDirty();
}
public final void set(Matrix3f pMatrix) {
this.floatValues.position(0);
pMatrix.get(this.floatValues);
this.markDirty();
}
public void upload() {
if (!this.dirty) {
}
this.dirty = false;
if (this.type <= 3) {
this.uploadAsInteger();
} else if (this.type <= 7) {
this.uploadAsFloat();
} else {
if (this.type > 10) {
LOGGER.warn("Uniform.upload called, but type value ({}) is not a valid type. Ignoring.", (int)this.type);
return;
}
this.uploadAsMatrix();
}
}
private void uploadAsInteger() {
this.intValues.rewind();
switch (this.type) {
case 0:
RenderSystem.glUniform1(this.location, this.intValues);
break;
case 1:
RenderSystem.glUniform2(this.location, this.intValues);
break;
case 2:
RenderSystem.glUniform3(this.location, this.intValues);
break;
case 3:
RenderSystem.glUniform4(this.location, this.intValues);
break;
default:
LOGGER.warn("Uniform.upload called, but count value ({}) is not in the range of 1 to 4. Ignoring.", (int)this.count);
}
}
private void uploadAsFloat() {
this.floatValues.rewind();
switch (this.type) {
case 4:
RenderSystem.glUniform1(this.location, this.floatValues);
break;
case 5:
RenderSystem.glUniform2(this.location, this.floatValues);
break;
case 6:
RenderSystem.glUniform3(this.location, this.floatValues);
break;
case 7:
RenderSystem.glUniform4(this.location, this.floatValues);
break;
default:
LOGGER.warn("Uniform.upload called, but count value ({}) is not in the range of 1 to 4. Ignoring.", (int)this.count);
}
}
private void uploadAsMatrix() {
this.floatValues.clear();
switch (this.type) {
case 8:
RenderSystem.glUniformMatrix2(this.location, false, this.floatValues);
break;
case 9:
RenderSystem.glUniformMatrix3(this.location, false, this.floatValues);
break;
case 10:
RenderSystem.glUniformMatrix4(this.location, false, this.floatValues);
}
}
public int getLocation() {
return this.location;
}
public int getCount() {
return this.count;
}
public int getType() {
return this.type;
}
public IntBuffer getIntBuffer() {
return this.intValues;
}
public FloatBuffer getFloatBuffer() {
return this.floatValues;
}
}
@@ -0,0 +1,11 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
@OnlyIn(Dist.CLIENT)
package com.mojang.blaze3d.shaders;
import com.mojang.blaze3d.FieldsAreNonnullByDefault;
import com.mojang.blaze3d.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -0,0 +1,96 @@
package com.mojang.blaze3d.systems;
import java.util.Optional;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.opengl.ARBTimerQuery;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL32C;
@OnlyIn(Dist.CLIENT)
public class TimerQuery {
private int nextQueryName;
public static Optional<TimerQuery> getInstance() {
return TimerQuery.TimerQueryLazyLoader.INSTANCE;
}
public void beginProfile() {
RenderSystem.assertOnRenderThread();
if (this.nextQueryName != 0) {
throw new IllegalStateException("Current profile not ended");
} else {
this.nextQueryName = GL32C.glGenQueries();
GL32C.glBeginQuery(35007, this.nextQueryName);
}
}
public TimerQuery.FrameProfile endProfile() {
RenderSystem.assertOnRenderThread();
if (this.nextQueryName == 0) {
throw new IllegalStateException("endProfile called before beginProfile");
} else {
GL32C.glEndQuery(35007);
TimerQuery.FrameProfile timerquery$frameprofile = new TimerQuery.FrameProfile(this.nextQueryName);
this.nextQueryName = 0;
return timerquery$frameprofile;
}
}
@OnlyIn(Dist.CLIENT)
public static class FrameProfile {
private static final long NO_RESULT = 0L;
private static final long CANCELLED_RESULT = -1L;
private final int queryName;
private long result;
FrameProfile(int pQueryName) {
this.queryName = pQueryName;
}
public void cancel() {
RenderSystem.assertOnRenderThread();
if (this.result == 0L) {
this.result = -1L;
GL32C.glDeleteQueries(this.queryName);
}
}
public boolean isDone() {
RenderSystem.assertOnRenderThread();
if (this.result != 0L) {
return true;
} else if (1 == GL32C.glGetQueryObjecti(this.queryName, 34919)) {
this.result = ARBTimerQuery.glGetQueryObjecti64(this.queryName, 34918);
GL32C.glDeleteQueries(this.queryName);
return true;
} else {
return false;
}
}
public long get() {
RenderSystem.assertOnRenderThread();
if (this.result == 0L) {
this.result = ARBTimerQuery.glGetQueryObjecti64(this.queryName, 34918);
GL32C.glDeleteQueries(this.queryName);
}
return this.result;
}
}
@OnlyIn(Dist.CLIENT)
static class TimerQueryLazyLoader {
static final Optional<TimerQuery> INSTANCE = Optional.ofNullable(instantiate());
private TimerQueryLazyLoader() {
}
@Nullable
private static TimerQuery instantiate() {
return !GL.getCapabilities().GL_ARB_timer_query ? null : new TimerQuery();
}
}
}
@@ -0,0 +1,11 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
@OnlyIn(Dist.CLIENT)
package com.mojang.blaze3d.systems;
import com.mojang.blaze3d.FieldsAreNonnullByDefault;
import com.mojang.blaze3d.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -0,0 +1,472 @@
package com.mojang.blaze3d.vertex;
import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.platform.MemoryTracker;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.ints.IntConsumer;
import java.nio.ByteBuffer;
import java.nio.FloatBuffer;
import javax.annotation.Nullable;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.commons.lang3.mutable.MutableInt;
import org.joml.Vector3f;
import org.lwjgl.system.MemoryUtil;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class BufferBuilder extends DefaultedVertexConsumer implements BufferVertexConsumer {
private static final int GROWTH_SIZE = 2097152;
private static final Logger LOGGER = LogUtils.getLogger();
private ByteBuffer buffer;
private int renderedBufferCount;
private int renderedBufferPointer;
private int nextElementByte;
private int vertices;
@Nullable
private VertexFormatElement currentElement;
private int elementIndex;
private VertexFormat format;
private VertexFormat.Mode mode;
private boolean fastFormat;
private boolean fullFormat;
private boolean building;
@Nullable
private Vector3f[] sortingPoints;
@Nullable
private VertexSorting sorting;
private boolean indexOnly;
public BufferBuilder(int pCapacity) {
this.buffer = MemoryTracker.create(pCapacity * 6);
}
private void ensureVertexCapacity() {
this.ensureCapacity(this.format.getVertexSize());
}
private void ensureCapacity(int pIncreaseAmount) {
if (this.nextElementByte + pIncreaseAmount > this.buffer.capacity()) {
int i = this.buffer.capacity();
int j = i + roundUp(pIncreaseAmount);
LOGGER.debug("Needed to grow BufferBuilder buffer: Old size {} bytes, new size {} bytes.", i, j);
ByteBuffer bytebuffer = MemoryTracker.resize(this.buffer, j);
bytebuffer.rewind();
this.buffer = bytebuffer;
}
}
private static int roundUp(int pX) {
int i = 2097152;
if (pX == 0) {
return i;
} else {
if (pX < 0) {
i *= -1;
}
int j = pX % i;
return j == 0 ? pX : pX + i - j;
}
}
public void setQuadSorting(VertexSorting pQuadSorting) {
if (this.mode == VertexFormat.Mode.QUADS) {
this.sorting = pQuadSorting;
if (this.sortingPoints == null) {
this.sortingPoints = this.makeQuadSortingPoints();
}
}
}
public BufferBuilder.SortState getSortState() {
return new BufferBuilder.SortState(this.mode, this.vertices, this.sortingPoints, this.sorting);
}
public void restoreSortState(BufferBuilder.SortState pSortState) {
this.buffer.rewind();
this.mode = pSortState.mode;
this.vertices = pSortState.vertices;
this.nextElementByte = this.renderedBufferPointer;
this.sortingPoints = pSortState.sortingPoints;
this.sorting = pSortState.sorting;
this.indexOnly = true;
}
public void begin(VertexFormat.Mode pMode, VertexFormat pFormat) {
if (this.building) {
throw new IllegalStateException("Already building!");
} else {
this.building = true;
this.mode = pMode;
this.switchFormat(pFormat);
this.currentElement = pFormat.getElements().get(0);
this.elementIndex = 0;
this.buffer.rewind();
}
}
private void switchFormat(VertexFormat pFormat) {
if (this.format != pFormat) {
this.format = pFormat;
boolean flag = pFormat == DefaultVertexFormat.NEW_ENTITY;
boolean flag1 = pFormat == DefaultVertexFormat.BLOCK;
this.fastFormat = flag || flag1;
this.fullFormat = flag;
}
}
private IntConsumer intConsumer(int p_231159_, VertexFormat.IndexType pIndexType) {
MutableInt mutableint = new MutableInt(p_231159_);
IntConsumer intconsumer;
switch (pIndexType) {
case SHORT:
intconsumer = (p_231167_) -> {
this.buffer.putShort(mutableint.getAndAdd(2), (short)p_231167_);
};
break;
case INT:
intconsumer = (p_231163_) -> {
this.buffer.putInt(mutableint.getAndAdd(4), p_231163_);
};
break;
default:
throw new IncompatibleClassChangeError();
}
return intconsumer;
}
private Vector3f[] makeQuadSortingPoints() {
FloatBuffer floatbuffer = this.buffer.asFloatBuffer();
int i = this.renderedBufferPointer / 4;
int j = this.format.getIntegerSize();
int k = j * this.mode.primitiveStride;
int l = this.vertices / this.mode.primitiveStride;
Vector3f[] avector3f = new Vector3f[l];
for(int i1 = 0; i1 < l; ++i1) {
float f = floatbuffer.get(i + i1 * k + 0);
float f1 = floatbuffer.get(i + i1 * k + 1);
float f2 = floatbuffer.get(i + i1 * k + 2);
float f3 = floatbuffer.get(i + i1 * k + j * 2 + 0);
float f4 = floatbuffer.get(i + i1 * k + j * 2 + 1);
float f5 = floatbuffer.get(i + i1 * k + j * 2 + 2);
float f6 = (f + f3) / 2.0F;
float f7 = (f1 + f4) / 2.0F;
float f8 = (f2 + f5) / 2.0F;
avector3f[i1] = new Vector3f(f6, f7, f8);
}
return avector3f;
}
private void putSortedQuadIndices(VertexFormat.IndexType pIndexType) {
if (this.sortingPoints != null && this.sorting != null) {
int[] aint = this.sorting.sort(this.sortingPoints);
IntConsumer intconsumer = this.intConsumer(this.nextElementByte, pIndexType);
for(int i : aint) {
intconsumer.accept(i * this.mode.primitiveStride + 0);
intconsumer.accept(i * this.mode.primitiveStride + 1);
intconsumer.accept(i * this.mode.primitiveStride + 2);
intconsumer.accept(i * this.mode.primitiveStride + 2);
intconsumer.accept(i * this.mode.primitiveStride + 3);
intconsumer.accept(i * this.mode.primitiveStride + 0);
}
} else {
throw new IllegalStateException("Sorting state uninitialized");
}
}
public boolean isCurrentBatchEmpty() {
return this.vertices == 0;
}
@Nullable
public BufferBuilder.RenderedBuffer endOrDiscardIfEmpty() {
this.ensureDrawing();
if (this.isCurrentBatchEmpty()) {
this.reset();
return null;
} else {
BufferBuilder.RenderedBuffer bufferbuilder$renderedbuffer = this.storeRenderedBuffer();
this.reset();
return bufferbuilder$renderedbuffer;
}
}
public BufferBuilder.RenderedBuffer end() {
this.ensureDrawing();
BufferBuilder.RenderedBuffer bufferbuilder$renderedbuffer = this.storeRenderedBuffer();
this.reset();
return bufferbuilder$renderedbuffer;
}
private void ensureDrawing() {
if (!this.building) {
throw new IllegalStateException("Not building!");
}
}
private BufferBuilder.RenderedBuffer storeRenderedBuffer() {
int i = this.mode.indexCount(this.vertices);
int j = !this.indexOnly ? this.vertices * this.format.getVertexSize() : 0;
VertexFormat.IndexType vertexformat$indextype = VertexFormat.IndexType.least(i);
boolean flag;
int k;
if (this.sortingPoints != null) {
int l = Mth.roundToward(i * vertexformat$indextype.bytes, 4);
this.ensureCapacity(l);
this.putSortedQuadIndices(vertexformat$indextype);
flag = false;
this.nextElementByte += l;
k = j + l;
} else {
flag = true;
k = j;
}
int i1 = this.renderedBufferPointer;
this.renderedBufferPointer += k;
++this.renderedBufferCount;
BufferBuilder.DrawState bufferbuilder$drawstate = new BufferBuilder.DrawState(this.format, this.vertices, i, this.mode, vertexformat$indextype, this.indexOnly, flag);
return new BufferBuilder.RenderedBuffer(i1, bufferbuilder$drawstate);
}
private void reset() {
this.building = false;
this.vertices = 0;
this.currentElement = null;
this.elementIndex = 0;
this.sortingPoints = null;
this.sorting = null;
this.indexOnly = false;
}
public void putByte(int pIndex, byte pByteValue) {
this.buffer.put(this.nextElementByte + pIndex, pByteValue);
}
public void putShort(int pIndex, short pShortValue) {
this.buffer.putShort(this.nextElementByte + pIndex, pShortValue);
}
public void putFloat(int pIndex, float pFloatValue) {
this.buffer.putFloat(this.nextElementByte + pIndex, pFloatValue);
}
public void endVertex() {
if (this.elementIndex != 0) {
throw new IllegalStateException("Not filled all elements of the vertex");
} else {
++this.vertices;
this.ensureVertexCapacity();
if (this.mode == VertexFormat.Mode.LINES || this.mode == VertexFormat.Mode.LINE_STRIP) {
int i = this.format.getVertexSize();
this.buffer.put(this.nextElementByte, this.buffer, this.nextElementByte - i, i);
this.nextElementByte += i;
++this.vertices;
this.ensureVertexCapacity();
}
}
}
public void nextElement() {
ImmutableList<VertexFormatElement> immutablelist = this.format.getElements();
this.elementIndex = (this.elementIndex + 1) % immutablelist.size();
this.nextElementByte += this.currentElement.getByteSize();
VertexFormatElement vertexformatelement = immutablelist.get(this.elementIndex);
this.currentElement = vertexformatelement;
if (vertexformatelement.getUsage() == VertexFormatElement.Usage.PADDING) {
this.nextElement();
}
if (this.defaultColorSet && this.currentElement.getUsage() == VertexFormatElement.Usage.COLOR) {
BufferVertexConsumer.super.color(this.defaultR, this.defaultG, this.defaultB, this.defaultA);
}
}
public VertexConsumer color(int pRed, int pGreen, int pBlue, int pAlpha) {
if (this.defaultColorSet) {
throw new IllegalStateException();
} else {
return BufferVertexConsumer.super.color(pRed, pGreen, pBlue, pAlpha);
}
}
public void vertex(float pX, float pY, float pZ, float pRed, float pGreen, float pBlue, float pAlpha, float pTexU, float pTexV, int pOverlayUV, int pLightmapUV, float pNormalX, float pNormalY, float pNormalZ) {
if (this.defaultColorSet) {
throw new IllegalStateException();
} else if (this.fastFormat) {
this.putFloat(0, pX);
this.putFloat(4, pY);
this.putFloat(8, pZ);
this.putByte(12, (byte)((int)(pRed * 255.0F)));
this.putByte(13, (byte)((int)(pGreen * 255.0F)));
this.putByte(14, (byte)((int)(pBlue * 255.0F)));
this.putByte(15, (byte)((int)(pAlpha * 255.0F)));
this.putFloat(16, pTexU);
this.putFloat(20, pTexV);
int i;
if (this.fullFormat) {
this.putShort(24, (short)(pOverlayUV & '\uffff'));
this.putShort(26, (short)(pOverlayUV >> 16 & '\uffff'));
i = 28;
} else {
i = 24;
}
this.putShort(i + 0, (short)(pLightmapUV & '\uffff'));
this.putShort(i + 2, (short)(pLightmapUV >> 16 & '\uffff'));
this.putByte(i + 4, BufferVertexConsumer.normalIntValue(pNormalX));
this.putByte(i + 5, BufferVertexConsumer.normalIntValue(pNormalY));
this.putByte(i + 6, BufferVertexConsumer.normalIntValue(pNormalZ));
this.nextElementByte += i + 8;
this.endVertex();
} else {
super.vertex(pX, pY, pZ, pRed, pGreen, pBlue, pAlpha, pTexU, pTexV, pOverlayUV, pLightmapUV, pNormalX, pNormalY, pNormalZ);
}
}
void releaseRenderedBuffer() {
if (this.renderedBufferCount > 0 && --this.renderedBufferCount == 0) {
this.clear();
}
}
public void clear() {
if (this.renderedBufferCount > 0) {
LOGGER.warn("Clearing BufferBuilder with unused batches");
}
this.discard();
}
public void discard() {
this.renderedBufferCount = 0;
this.renderedBufferPointer = 0;
this.nextElementByte = 0;
}
public VertexFormatElement currentElement() {
if (this.currentElement == null) {
throw new IllegalStateException("BufferBuilder not started");
} else {
return this.currentElement;
}
}
public boolean building() {
return this.building;
}
ByteBuffer bufferSlice(int p_231170_, int p_231171_) {
return MemoryUtil.memSlice(this.buffer, p_231170_, p_231171_ - p_231170_);
}
@OnlyIn(Dist.CLIENT)
public static record DrawState(VertexFormat format, int vertexCount, int indexCount, VertexFormat.Mode mode, VertexFormat.IndexType indexType, boolean indexOnly, boolean sequentialIndex) {
public int vertexBufferSize() {
return this.vertexCount * this.format.getVertexSize();
}
public int vertexBufferStart() {
return 0;
}
public int vertexBufferEnd() {
return this.vertexBufferSize();
}
public int indexBufferStart() {
return this.indexOnly ? 0 : this.vertexBufferEnd();
}
public int indexBufferEnd() {
return this.indexBufferStart() + this.indexBufferSize();
}
private int indexBufferSize() {
return this.sequentialIndex ? 0 : this.indexCount * this.indexType.bytes;
}
public int bufferSize() {
return this.indexBufferEnd();
}
}
@OnlyIn(Dist.CLIENT)
public class RenderedBuffer {
private final int pointer;
private final BufferBuilder.DrawState drawState;
private boolean released;
RenderedBuffer(int pPointer, BufferBuilder.DrawState pDrawState) {
this.pointer = pPointer;
this.drawState = pDrawState;
}
public ByteBuffer vertexBuffer() {
int i = this.pointer + this.drawState.vertexBufferStart();
int j = this.pointer + this.drawState.vertexBufferEnd();
return BufferBuilder.this.bufferSlice(i, j);
}
public ByteBuffer indexBuffer() {
int i = this.pointer + this.drawState.indexBufferStart();
int j = this.pointer + this.drawState.indexBufferEnd();
return BufferBuilder.this.bufferSlice(i, j);
}
public BufferBuilder.DrawState drawState() {
return this.drawState;
}
public boolean isEmpty() {
return this.drawState.vertexCount == 0;
}
public void release() {
if (this.released) {
throw new IllegalStateException("Buffer has already been released!");
} else {
BufferBuilder.this.releaseRenderedBuffer();
this.released = true;
}
}
}
@OnlyIn(Dist.CLIENT)
public static class SortState {
final VertexFormat.Mode mode;
final int vertices;
@Nullable
final Vector3f[] sortingPoints;
@Nullable
final VertexSorting sorting;
SortState(VertexFormat.Mode pMode, int pVertices, @Nullable Vector3f[] pSortingPoints, @Nullable VertexSorting pSorting) {
this.mode = pMode;
this.vertices = pVertices;
this.sortingPoints = pSortingPoints;
this.sorting = pSorting;
}
}
// Forge start
public void putBulkData(ByteBuffer buffer) {
ensureCapacity(buffer.limit() + this.format.getVertexSize());
this.buffer.position(this.nextElementByte);
this.buffer.put(buffer);
this.buffer.position(0);
this.vertices += buffer.limit() / this.format.getVertexSize();
this.nextElementByte += buffer.limit();
}
}
@@ -0,0 +1,78 @@
package com.mojang.blaze3d.vertex;
import com.mojang.blaze3d.systems.RenderSystem;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class BufferUploader {
@Nullable
private static VertexBuffer lastImmediateBuffer;
public static void reset() {
if (lastImmediateBuffer != null) {
invalidate();
VertexBuffer.unbind();
}
}
public static void invalidate() {
lastImmediateBuffer = null;
}
public static void drawWithShader(BufferBuilder.RenderedBuffer pBuffer) {
if (!RenderSystem.isOnRenderThreadOrInit()) {
RenderSystem.recordRenderCall(() -> {
_drawWithShader(pBuffer);
});
} else {
_drawWithShader(pBuffer);
}
}
private static void _drawWithShader(BufferBuilder.RenderedBuffer pBuffer) {
VertexBuffer vertexbuffer = upload(pBuffer);
if (vertexbuffer != null) {
vertexbuffer.drawWithShader(RenderSystem.getModelViewMatrix(), RenderSystem.getProjectionMatrix(), RenderSystem.getShader());
}
}
public static void draw(BufferBuilder.RenderedBuffer pBuffer) {
VertexBuffer vertexbuffer = upload(pBuffer);
if (vertexbuffer != null) {
vertexbuffer.draw();
}
}
@Nullable
private static VertexBuffer upload(BufferBuilder.RenderedBuffer pBuffer) {
RenderSystem.assertOnRenderThread();
if (pBuffer.isEmpty()) {
pBuffer.release();
return null;
} else {
VertexBuffer vertexbuffer = bindImmediateBuffer(pBuffer.drawState().format());
vertexbuffer.upload(pBuffer);
return vertexbuffer;
}
}
private static VertexBuffer bindImmediateBuffer(VertexFormat pFormat) {
VertexBuffer vertexbuffer = pFormat.getImmediateDrawVertexBuffer();
bindImmediateBuffer(vertexbuffer);
return vertexbuffer;
}
private static void bindImmediateBuffer(VertexBuffer pBuffer) {
if (pBuffer != lastImmediateBuffer) {
pBuffer.bind();
lastImmediateBuffer = pBuffer;
}
}
}
@@ -0,0 +1,107 @@
package com.mojang.blaze3d.vertex;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public interface BufferVertexConsumer extends VertexConsumer {
VertexFormatElement currentElement();
void nextElement();
void putByte(int pIndex, byte pByteValue);
void putShort(int pIndex, short pShortValue);
void putFloat(int pIndex, float pFloatValue);
default VertexConsumer vertex(double pX, double pY, double pZ) {
if (this.currentElement().getUsage() != VertexFormatElement.Usage.POSITION) {
return this;
} else if (this.currentElement().getType() == VertexFormatElement.Type.FLOAT && this.currentElement().getCount() == 3) {
this.putFloat(0, (float)pX);
this.putFloat(4, (float)pY);
this.putFloat(8, (float)pZ);
this.nextElement();
return this;
} else {
throw new IllegalStateException();
}
}
default VertexConsumer color(int pRed, int pGreen, int pBlue, int pAlpha) {
VertexFormatElement vertexformatelement = this.currentElement();
if (vertexformatelement.getUsage() != VertexFormatElement.Usage.COLOR) {
return this;
} else if (vertexformatelement.getType() == VertexFormatElement.Type.UBYTE && vertexformatelement.getCount() == 4) {
this.putByte(0, (byte)pRed);
this.putByte(1, (byte)pGreen);
this.putByte(2, (byte)pBlue);
this.putByte(3, (byte)pAlpha);
this.nextElement();
return this;
} else {
throw new IllegalStateException();
}
}
default VertexConsumer uv(float pU, float pV) {
VertexFormatElement vertexformatelement = this.currentElement();
if (vertexformatelement.getUsage() == VertexFormatElement.Usage.UV && vertexformatelement.getIndex() == 0) {
if (vertexformatelement.getType() == VertexFormatElement.Type.FLOAT && vertexformatelement.getCount() == 2) {
this.putFloat(0, pU);
this.putFloat(4, pV);
this.nextElement();
return this;
} else {
throw new IllegalStateException();
}
} else {
return this;
}
}
default VertexConsumer overlayCoords(int pU, int pV) {
return this.uvShort((short)pU, (short)pV, 1);
}
default VertexConsumer uv2(int pU, int pV) {
return this.uvShort((short)pU, (short)pV, 2);
}
default VertexConsumer uvShort(short pU, short pV, int pIndex) {
VertexFormatElement vertexformatelement = this.currentElement();
if (vertexformatelement.getUsage() == VertexFormatElement.Usage.UV && vertexformatelement.getIndex() == pIndex) {
if (vertexformatelement.getType() == VertexFormatElement.Type.SHORT && vertexformatelement.getCount() == 2) {
this.putShort(0, pU);
this.putShort(2, pV);
this.nextElement();
return this;
} else {
throw new IllegalStateException();
}
} else {
return this;
}
}
default VertexConsumer normal(float pX, float pY, float pZ) {
VertexFormatElement vertexformatelement = this.currentElement();
if (vertexformatelement.getUsage() != VertexFormatElement.Usage.NORMAL) {
return this;
} else if (vertexformatelement.getType() == VertexFormatElement.Type.BYTE && vertexformatelement.getCount() == 3) {
this.putByte(0, normalIntValue(pX));
this.putByte(1, normalIntValue(pY));
this.putByte(2, normalIntValue(pZ));
this.nextElement();
return this;
} else {
throw new IllegalStateException();
}
}
static byte normalIntValue(float pNum) {
return (byte)((int)(Mth.clamp(pNum, -1.0F, 1.0F) * 127.0F) & 255);
}
}
@@ -0,0 +1,31 @@
package com.mojang.blaze3d.vertex;
import com.google.common.collect.ImmutableMap;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class DefaultVertexFormat {
public static final VertexFormatElement ELEMENT_POSITION = new VertexFormatElement(0, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.POSITION, 3);
public static final VertexFormatElement ELEMENT_COLOR = new VertexFormatElement(0, VertexFormatElement.Type.UBYTE, VertexFormatElement.Usage.COLOR, 4);
public static final VertexFormatElement ELEMENT_UV0 = new VertexFormatElement(0, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.UV, 2);
public static final VertexFormatElement ELEMENT_UV1 = new VertexFormatElement(1, VertexFormatElement.Type.SHORT, VertexFormatElement.Usage.UV, 2);
public static final VertexFormatElement ELEMENT_UV2 = new VertexFormatElement(2, VertexFormatElement.Type.SHORT, VertexFormatElement.Usage.UV, 2);
public static final VertexFormatElement ELEMENT_NORMAL = new VertexFormatElement(0, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.NORMAL, 3);
public static final VertexFormatElement ELEMENT_PADDING = new VertexFormatElement(0, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.PADDING, 1);
public static final VertexFormatElement ELEMENT_UV = ELEMENT_UV0;
public static final VertexFormat BLIT_SCREEN = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("UV", ELEMENT_UV).put("Color", ELEMENT_COLOR).build());
public static final VertexFormat BLOCK = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("Color", ELEMENT_COLOR).put("UV0", ELEMENT_UV0).put("UV2", ELEMENT_UV2).put("Normal", ELEMENT_NORMAL).put("Padding", ELEMENT_PADDING).build());
public static final VertexFormat NEW_ENTITY = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("Color", ELEMENT_COLOR).put("UV0", ELEMENT_UV0).put("UV1", ELEMENT_UV1).put("UV2", ELEMENT_UV2).put("Normal", ELEMENT_NORMAL).put("Padding", ELEMENT_PADDING).build());
public static final VertexFormat PARTICLE = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("UV0", ELEMENT_UV0).put("Color", ELEMENT_COLOR).put("UV2", ELEMENT_UV2).build());
public static final VertexFormat POSITION = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).build());
public static final VertexFormat POSITION_COLOR = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("Color", ELEMENT_COLOR).build());
public static final VertexFormat POSITION_COLOR_NORMAL = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("Color", ELEMENT_COLOR).put("Normal", ELEMENT_NORMAL).put("Padding", ELEMENT_PADDING).build());
public static final VertexFormat POSITION_COLOR_LIGHTMAP = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("Color", ELEMENT_COLOR).put("UV2", ELEMENT_UV2).build());
public static final VertexFormat POSITION_TEX = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("UV0", ELEMENT_UV0).build());
public static final VertexFormat POSITION_COLOR_TEX = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("Color", ELEMENT_COLOR).put("UV0", ELEMENT_UV0).build());
public static final VertexFormat POSITION_TEX_COLOR = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("UV0", ELEMENT_UV0).put("Color", ELEMENT_COLOR).build());
public static final VertexFormat POSITION_COLOR_TEX_LIGHTMAP = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("Color", ELEMENT_COLOR).put("UV0", ELEMENT_UV0).put("UV2", ELEMENT_UV2).build());
public static final VertexFormat POSITION_TEX_LIGHTMAP_COLOR = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("UV0", ELEMENT_UV0).put("UV2", ELEMENT_UV2).put("Color", ELEMENT_COLOR).build());
public static final VertexFormat POSITION_TEX_COLOR_NORMAL = new VertexFormat(ImmutableMap.<String, VertexFormatElement>builder().put("Position", ELEMENT_POSITION).put("UV0", ELEMENT_UV0).put("Color", ELEMENT_COLOR).put("Normal", ELEMENT_NORMAL).put("Padding", ELEMENT_PADDING).build());
}
@@ -0,0 +1,25 @@
package com.mojang.blaze3d.vertex;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public abstract class DefaultedVertexConsumer implements VertexConsumer {
protected boolean defaultColorSet;
protected int defaultR = 255;
protected int defaultG = 255;
protected int defaultB = 255;
protected int defaultA = 255;
public void defaultColor(int p_85830_, int p_85831_, int p_85832_, int p_85833_) {
this.defaultR = p_85830_;
this.defaultG = p_85831_;
this.defaultB = p_85832_;
this.defaultA = p_85833_;
this.defaultColorSet = true;
}
public void unsetDefaultColor() {
this.defaultColorSet = false;
}
}
@@ -0,0 +1,105 @@
package com.mojang.blaze3d.vertex;
import com.google.common.collect.Queues;
import java.util.Deque;
import net.minecraft.Util;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
@OnlyIn(Dist.CLIENT)
public class PoseStack implements net.minecraftforge.client.extensions.IForgePoseStack {
private final Deque<PoseStack.Pose> poseStack = Util.make(Queues.newArrayDeque(), (p_85848_) -> {
Matrix4f matrix4f = new Matrix4f();
Matrix3f matrix3f = new Matrix3f();
p_85848_.add(new PoseStack.Pose(matrix4f, matrix3f));
});
public void translate(double pX, double pY, double pZ) {
this.translate((float)pX, (float)pY, (float)pZ);
}
public void translate(float pX, float pY, float pZ) {
PoseStack.Pose posestack$pose = this.poseStack.getLast();
posestack$pose.pose.translate(pX, pY, pZ);
}
public void scale(float pX, float pY, float pZ) {
PoseStack.Pose posestack$pose = this.poseStack.getLast();
posestack$pose.pose.scale(pX, pY, pZ);
if (pX == pY && pY == pZ) {
if (pX > 0.0F) {
return;
}
posestack$pose.normal.scale(-1.0F);
}
float f = 1.0F / pX;
float f1 = 1.0F / pY;
float f2 = 1.0F / pZ;
float f3 = Mth.fastInvCubeRoot(f * f1 * f2);
posestack$pose.normal.scale(f3 * f, f3 * f1, f3 * f2);
}
public void mulPose(Quaternionf pQuaternion) {
PoseStack.Pose posestack$pose = this.poseStack.getLast();
posestack$pose.pose.rotate(pQuaternion);
posestack$pose.normal.rotate(pQuaternion);
}
public void rotateAround(Quaternionf pQuaternion, float pX, float pY, float pZ) {
PoseStack.Pose posestack$pose = this.poseStack.getLast();
posestack$pose.pose.rotateAround(pQuaternion, pX, pY, pZ);
posestack$pose.normal.rotate(pQuaternion);
}
public void pushPose() {
PoseStack.Pose posestack$pose = this.poseStack.getLast();
this.poseStack.addLast(new PoseStack.Pose(new Matrix4f(posestack$pose.pose), new Matrix3f(posestack$pose.normal)));
}
public void popPose() {
this.poseStack.removeLast();
}
public PoseStack.Pose last() {
return this.poseStack.getLast();
}
public boolean clear() {
return this.poseStack.size() == 1;
}
public void setIdentity() {
PoseStack.Pose posestack$pose = this.poseStack.getLast();
posestack$pose.pose.identity();
posestack$pose.normal.identity();
}
public void mulPoseMatrix(Matrix4f pMatrix) {
(this.poseStack.getLast()).pose.mul(pMatrix);
}
@OnlyIn(Dist.CLIENT)
public static final class Pose {
final Matrix4f pose;
final Matrix3f normal;
Pose(Matrix4f pPose, Matrix3f pNormal) {
this.pose = pPose;
this.normal = pNormal;
}
public Matrix4f pose() {
return this.pose;
}
public Matrix3f normal() {
return this.normal;
}
}
}
@@ -0,0 +1,92 @@
package com.mojang.blaze3d.vertex;
import net.minecraft.core.Direction;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
@OnlyIn(Dist.CLIENT)
public class SheetedDecalTextureGenerator extends DefaultedVertexConsumer {
private final VertexConsumer delegate;
private final Matrix4f cameraInversePose;
private final Matrix3f normalInversePose;
private final float textureScale;
private float x;
private float y;
private float z;
private int overlayU;
private int overlayV;
private int lightCoords;
private float nx;
private float ny;
private float nz;
public SheetedDecalTextureGenerator(VertexConsumer pDelegate, Matrix4f pCameraPose, Matrix3f pNormalPose, float pTextureScale) {
this.delegate = pDelegate;
this.cameraInversePose = (new Matrix4f(pCameraPose)).invert();
this.normalInversePose = (new Matrix3f(pNormalPose)).invert();
this.textureScale = pTextureScale;
this.resetState();
}
private void resetState() {
this.x = 0.0F;
this.y = 0.0F;
this.z = 0.0F;
this.overlayU = 0;
this.overlayV = 10;
this.lightCoords = 15728880;
this.nx = 0.0F;
this.ny = 1.0F;
this.nz = 0.0F;
}
public void endVertex() {
Vector3f vector3f = this.normalInversePose.transform(new Vector3f(this.nx, this.ny, this.nz));
Direction direction = net.minecraftforge.client.ForgeHooksClient.getNearestStable(vector3f.x(), vector3f.y(), vector3f.z());
Vector4f vector4f = this.cameraInversePose.transform(new Vector4f(this.x, this.y, this.z, 1.0F));
vector4f.rotateY((float)Math.PI);
vector4f.rotateX((-(float)Math.PI / 2F));
vector4f.rotate(direction.getRotation());
float f = -vector4f.x() * this.textureScale;
float f1 = -vector4f.y() * this.textureScale;
this.delegate.vertex((double)this.x, (double)this.y, (double)this.z).color(1.0F, 1.0F, 1.0F, 1.0F).uv(f, f1).overlayCoords(this.overlayU, this.overlayV).uv2(this.lightCoords).normal(this.nx, this.ny, this.nz).endVertex();
this.resetState();
}
public VertexConsumer vertex(double pX, double pY, double pZ) {
this.x = (float)pX;
this.y = (float)pY;
this.z = (float)pZ;
return this;
}
public VertexConsumer color(int pRed, int pGreen, int pBlue, int pAlpha) {
return this;
}
public VertexConsumer uv(float pU, float pV) {
return this;
}
public VertexConsumer overlayCoords(int pU, int pV) {
this.overlayU = pU;
this.overlayV = pV;
return this;
}
public VertexConsumer uv2(int pU, int pV) {
this.lightCoords = pU | pV << 16;
return this;
}
public VertexConsumer normal(float pX, float pY, float pZ) {
this.nx = pX;
this.ny = pY;
this.nz = pZ;
return this;
}
}
@@ -0,0 +1,37 @@
package com.mojang.blaze3d.vertex;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class Tesselator {
private static final int MAX_MEMORY_USE = 8388608;
private static final int MAX_FLOATS = 2097152;
private final BufferBuilder builder;
private static final Tesselator INSTANCE = new Tesselator();
public static Tesselator getInstance() {
RenderSystem.assertOnGameThreadOrInit();
return INSTANCE;
}
public Tesselator(int pCapacity) {
this.builder = new BufferBuilder(pCapacity);
}
public Tesselator() {
this(2097152);
}
/**
* Draws the data set up in this tesselator and resets the state to prepare for new drawing.
*/
public void end() {
BufferUploader.drawWithShader(this.builder.end());
}
public BufferBuilder getBuilder() {
return this.builder;
}
}
@@ -0,0 +1,225 @@
package com.mojang.blaze3d.vertex;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.platform.Window;
import com.mojang.blaze3d.systems.RenderSystem;
import java.nio.ByteBuffer;
import javax.annotation.Nullable;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ShaderInstance;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
@OnlyIn(Dist.CLIENT)
public class VertexBuffer implements AutoCloseable {
private final VertexBuffer.Usage usage;
private int vertexBufferId;
private int indexBufferId;
private int arrayObjectId;
@Nullable
private VertexFormat format;
@Nullable
private RenderSystem.AutoStorageIndexBuffer sequentialIndices;
private VertexFormat.IndexType indexType;
private int indexCount;
private VertexFormat.Mode mode;
public VertexBuffer(VertexBuffer.Usage pUsage) {
this.usage = pUsage;
RenderSystem.assertOnRenderThread();
this.vertexBufferId = GlStateManager._glGenBuffers();
this.indexBufferId = GlStateManager._glGenBuffers();
this.arrayObjectId = GlStateManager._glGenVertexArrays();
}
public void upload(BufferBuilder.RenderedBuffer pBuffer) {
if (!this.isInvalid()) {
RenderSystem.assertOnRenderThread();
try {
BufferBuilder.DrawState bufferbuilder$drawstate = pBuffer.drawState();
this.format = this.uploadVertexBuffer(bufferbuilder$drawstate, pBuffer.vertexBuffer());
this.sequentialIndices = this.uploadIndexBuffer(bufferbuilder$drawstate, pBuffer.indexBuffer());
this.indexCount = bufferbuilder$drawstate.indexCount();
this.indexType = bufferbuilder$drawstate.indexType();
this.mode = bufferbuilder$drawstate.mode();
} finally {
pBuffer.release();
}
}
}
private VertexFormat uploadVertexBuffer(BufferBuilder.DrawState pDrawState, ByteBuffer pBuffer) {
boolean flag = false;
if (!pDrawState.format().equals(this.format)) {
if (this.format != null) {
this.format.clearBufferState();
}
GlStateManager._glBindBuffer(34962, this.vertexBufferId);
pDrawState.format().setupBufferState();
flag = true;
}
if (!pDrawState.indexOnly()) {
if (!flag) {
GlStateManager._glBindBuffer(34962, this.vertexBufferId);
}
RenderSystem.glBufferData(34962, pBuffer, this.usage.id);
}
return pDrawState.format();
}
@Nullable
private RenderSystem.AutoStorageIndexBuffer uploadIndexBuffer(BufferBuilder.DrawState pDrawState, ByteBuffer pBuffer) {
if (!pDrawState.sequentialIndex()) {
GlStateManager._glBindBuffer(34963, this.indexBufferId);
RenderSystem.glBufferData(34963, pBuffer, this.usage.id);
return null;
} else {
RenderSystem.AutoStorageIndexBuffer rendersystem$autostorageindexbuffer = RenderSystem.getSequentialBuffer(pDrawState.mode());
if (rendersystem$autostorageindexbuffer != this.sequentialIndices || !rendersystem$autostorageindexbuffer.hasStorage(pDrawState.indexCount())) {
rendersystem$autostorageindexbuffer.bind(pDrawState.indexCount());
}
return rendersystem$autostorageindexbuffer;
}
}
public void bind() {
BufferUploader.invalidate();
GlStateManager._glBindVertexArray(this.arrayObjectId);
}
public static void unbind() {
BufferUploader.invalidate();
GlStateManager._glBindVertexArray(0);
}
public void draw() {
RenderSystem.drawElements(this.mode.asGLMode, this.indexCount, this.getIndexType().asGLType);
}
private VertexFormat.IndexType getIndexType() {
RenderSystem.AutoStorageIndexBuffer rendersystem$autostorageindexbuffer = this.sequentialIndices;
return rendersystem$autostorageindexbuffer != null ? rendersystem$autostorageindexbuffer.type() : this.indexType;
}
public void drawWithShader(Matrix4f pModelViewMatrix, Matrix4f pProjectionMatrix, ShaderInstance pShader) {
if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(() -> {
this._drawWithShader(new Matrix4f(pModelViewMatrix), new Matrix4f(pProjectionMatrix), pShader);
});
} else {
this._drawWithShader(pModelViewMatrix, pProjectionMatrix, pShader);
}
}
private void _drawWithShader(Matrix4f pModelViewMatrix, Matrix4f pProjectionMatrix, ShaderInstance pShader) {
for(int i = 0; i < 12; ++i) {
int j = RenderSystem.getShaderTexture(i);
pShader.setSampler("Sampler" + i, j);
}
if (pShader.MODEL_VIEW_MATRIX != null) {
pShader.MODEL_VIEW_MATRIX.set(pModelViewMatrix);
}
if (pShader.PROJECTION_MATRIX != null) {
pShader.PROJECTION_MATRIX.set(pProjectionMatrix);
}
if (pShader.INVERSE_VIEW_ROTATION_MATRIX != null) {
pShader.INVERSE_VIEW_ROTATION_MATRIX.set(RenderSystem.getInverseViewRotationMatrix());
}
if (pShader.COLOR_MODULATOR != null) {
pShader.COLOR_MODULATOR.set(RenderSystem.getShaderColor());
}
if (pShader.GLINT_ALPHA != null) {
pShader.GLINT_ALPHA.set(RenderSystem.getShaderGlintAlpha());
}
if (pShader.FOG_START != null) {
pShader.FOG_START.set(RenderSystem.getShaderFogStart());
}
if (pShader.FOG_END != null) {
pShader.FOG_END.set(RenderSystem.getShaderFogEnd());
}
if (pShader.FOG_COLOR != null) {
pShader.FOG_COLOR.set(RenderSystem.getShaderFogColor());
}
if (pShader.FOG_SHAPE != null) {
pShader.FOG_SHAPE.set(RenderSystem.getShaderFogShape().getIndex());
}
if (pShader.TEXTURE_MATRIX != null) {
pShader.TEXTURE_MATRIX.set(RenderSystem.getTextureMatrix());
}
if (pShader.GAME_TIME != null) {
pShader.GAME_TIME.set(RenderSystem.getShaderGameTime());
}
if (pShader.SCREEN_SIZE != null) {
Window window = Minecraft.getInstance().getWindow();
pShader.SCREEN_SIZE.set((float)window.getWidth(), (float)window.getHeight());
}
if (pShader.LINE_WIDTH != null && (this.mode == VertexFormat.Mode.LINES || this.mode == VertexFormat.Mode.LINE_STRIP)) {
pShader.LINE_WIDTH.set(RenderSystem.getShaderLineWidth());
}
RenderSystem.setupShaderLights(pShader);
pShader.apply();
this.draw();
pShader.clear();
}
public void close() {
if (this.vertexBufferId >= 0) {
RenderSystem.glDeleteBuffers(this.vertexBufferId);
this.vertexBufferId = -1;
}
if (this.indexBufferId >= 0) {
RenderSystem.glDeleteBuffers(this.indexBufferId);
this.indexBufferId = -1;
}
if (this.arrayObjectId >= 0) {
RenderSystem.glDeleteVertexArrays(this.arrayObjectId);
this.arrayObjectId = -1;
}
}
public VertexFormat getFormat() {
return this.format;
}
public boolean isInvalid() {
return this.arrayObjectId == -1;
}
@OnlyIn(Dist.CLIENT)
public static enum Usage {
STATIC(35044),
DYNAMIC(35048);
final int id;
private Usage(int pId) {
this.id = pId;
}
}
}
@@ -0,0 +1,127 @@
package com.mojang.blaze3d.vertex;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.core.Vec3i;
import net.minecraft.util.FastColor;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import org.lwjgl.system.MemoryStack;
@OnlyIn(Dist.CLIENT)
public interface VertexConsumer extends net.minecraftforge.client.extensions.IForgeVertexConsumer {
VertexConsumer vertex(double pX, double pY, double pZ);
VertexConsumer color(int pRed, int pGreen, int pBlue, int pAlpha);
VertexConsumer uv(float pU, float pV);
VertexConsumer overlayCoords(int pU, int pV);
VertexConsumer uv2(int pU, int pV);
VertexConsumer normal(float pX, float pY, float pZ);
void endVertex();
default void vertex(float pX, float pY, float pZ, float pRed, float pGreen, float pBlue, float pAlpha, float pTexU, float pTexV, int pOverlayUV, int pLightmapUV, float pNormalX, float pNormalY, float pNormalZ) {
this.vertex((double)pX, (double)pY, (double)pZ);
this.color(pRed, pGreen, pBlue, pAlpha);
this.uv(pTexU, pTexV);
this.overlayCoords(pOverlayUV);
this.uv2(pLightmapUV);
this.normal(pNormalX, pNormalY, pNormalZ);
this.endVertex();
}
void defaultColor(int pDefaultR, int pDefaultG, int pDefaultB, int pDefaultA);
void unsetDefaultColor();
default VertexConsumer color(float pRed, float pGreen, float pBlue, float pAlpha) {
return this.color((int)(pRed * 255.0F), (int)(pGreen * 255.0F), (int)(pBlue * 255.0F), (int)(pAlpha * 255.0F));
}
default VertexConsumer color(int pColorARGB) {
return this.color(FastColor.ARGB32.red(pColorARGB), FastColor.ARGB32.green(pColorARGB), FastColor.ARGB32.blue(pColorARGB), FastColor.ARGB32.alpha(pColorARGB));
}
default VertexConsumer uv2(int pLightmapUV) {
return this.uv2(pLightmapUV & '\uffff', pLightmapUV >> 16 & '\uffff');
}
default VertexConsumer overlayCoords(int pOverlayUV) {
return this.overlayCoords(pOverlayUV & '\uffff', pOverlayUV >> 16 & '\uffff');
}
default void putBulkData(PoseStack.Pose pPoseEntry, BakedQuad pQuad, float pRed, float pGreen, float pBlue, int pCombinedLight, int pCombinedOverlay) {
this.putBulkData(pPoseEntry, pQuad, new float[]{1.0F, 1.0F, 1.0F, 1.0F}, pRed, pGreen, pBlue, new int[]{pCombinedLight, pCombinedLight, pCombinedLight, pCombinedLight}, pCombinedOverlay, false);
}
default void putBulkData(PoseStack.Pose pPoseEntry, BakedQuad pQuad, float[] pColorMuls, float pRed, float pGreen, float pBlue, int[] pCombinedLights, int pCombinedOverlay, boolean pMulColor) {
putBulkData(pPoseEntry, pQuad, pColorMuls, pRed, pGreen, pBlue, 1, pCombinedLights, pCombinedOverlay, pMulColor);
}
default void putBulkData(PoseStack.Pose pPoseEntry, BakedQuad pQuad, float[] pColorMuls, float pRed, float pGreen, float pBlue, float alpha, int[] pCombinedLights, int pCombinedOverlay, boolean pMulColor) {
float[] afloat = new float[]{pColorMuls[0], pColorMuls[1], pColorMuls[2], pColorMuls[3]};
int[] aint = new int[]{pCombinedLights[0], pCombinedLights[1], pCombinedLights[2], pCombinedLights[3]};
int[] aint1 = pQuad.getVertices();
Vec3i vec3i = pQuad.getDirection().getNormal();
Matrix4f matrix4f = pPoseEntry.pose();
Vector3f vector3f = pPoseEntry.normal().transform(new Vector3f((float)vec3i.getX(), (float)vec3i.getY(), (float)vec3i.getZ()));
int i = 8;
int j = aint1.length / 8;
try (MemoryStack memorystack = MemoryStack.stackPush()) {
ByteBuffer bytebuffer = memorystack.malloc(DefaultVertexFormat.BLOCK.getVertexSize());
IntBuffer intbuffer = bytebuffer.asIntBuffer();
for(int k = 0; k < j; ++k) {
intbuffer.clear();
intbuffer.put(aint1, k * 8, 8);
float f = bytebuffer.getFloat(0);
float f1 = bytebuffer.getFloat(4);
float f2 = bytebuffer.getFloat(8);
float f3;
float f4;
float f5;
if (pMulColor) {
float f6 = (float)(bytebuffer.get(12) & 255) / 255.0F;
float f7 = (float)(bytebuffer.get(13) & 255) / 255.0F;
float f8 = (float)(bytebuffer.get(14) & 255) / 255.0F;
f3 = f6 * afloat[k] * pRed;
f4 = f7 * afloat[k] * pGreen;
f5 = f8 * afloat[k] * pBlue;
} else {
f3 = afloat[k] * pRed;
f4 = afloat[k] * pGreen;
f5 = afloat[k] * pBlue;
}
int l = applyBakedLighting(pCombinedLights[k], bytebuffer);
float f9 = bytebuffer.getFloat(16);
float f10 = bytebuffer.getFloat(20);
Vector4f vector4f = matrix4f.transform(new Vector4f(f, f1, f2, 1.0F));
applyBakedNormals(vector3f, bytebuffer, pPoseEntry.normal());
float vertexAlpha = pMulColor ? alpha * (float) (bytebuffer.get(15) & 255) / 255.0F : alpha;
this.vertex(vector4f.x(), vector4f.y(), vector4f.z(), f3, f4, f5, vertexAlpha, f9, f10, pCombinedOverlay, l, vector3f.x(), vector3f.y(), vector3f.z());
}
}
}
default VertexConsumer vertex(Matrix4f pMatrix, float pX, float pY, float pZ) {
Vector4f vector4f = pMatrix.transform(new Vector4f(pX, pY, pZ, 1.0F));
return this.vertex((double)vector4f.x(), (double)vector4f.y(), (double)vector4f.z());
}
default VertexConsumer normal(Matrix3f pMatrix, float pX, float pY, float pZ) {
Vector3f vector3f = pMatrix.transform(new Vector3f(pX, pY, pZ));
return this.normal(vector3f.x(), vector3f.y(), vector3f.z());
}
}
@@ -0,0 +1,186 @@
package com.mojang.blaze3d.vertex;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.mojang.blaze3d.systems.RenderSystem;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.List;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class VertexFormat {
private final ImmutableList<VertexFormatElement> elements;
private final ImmutableMap<String, VertexFormatElement> elementMapping;
private final IntList offsets = new IntArrayList();
private final int vertexSize;
@Nullable
private VertexBuffer immediateDrawVertexBuffer;
public VertexFormat(ImmutableMap<String, VertexFormatElement> pElementMapping) {
this.elementMapping = pElementMapping;
this.elements = pElementMapping.values().asList();
int i = 0;
for(VertexFormatElement vertexformatelement : pElementMapping.values()) {
this.offsets.add(i);
i += vertexformatelement.getByteSize();
}
this.vertexSize = i;
}
public String toString() {
return "format: " + this.elementMapping.size() + " elements: " + (String)this.elementMapping.entrySet().stream().map(Object::toString).collect(Collectors.joining(" "));
}
public int getIntegerSize() {
return this.getVertexSize() / 4;
}
public int getVertexSize() {
return this.vertexSize;
}
public ImmutableList<VertexFormatElement> getElements() {
return this.elements;
}
public ImmutableList<String> getElementAttributeNames() {
return this.elementMapping.keySet().asList();
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else if (pOther != null && this.getClass() == pOther.getClass()) {
VertexFormat vertexformat = (VertexFormat)pOther;
return this.vertexSize != vertexformat.vertexSize ? false : this.elementMapping.equals(vertexformat.elementMapping);
} else {
return false;
}
}
public int hashCode() {
return this.elementMapping.hashCode();
}
public void setupBufferState() {
if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(this::_setupBufferState);
} else {
this._setupBufferState();
}
}
private void _setupBufferState() {
int i = this.getVertexSize();
List<VertexFormatElement> list = this.getElements();
for(int j = 0; j < list.size(); ++j) {
list.get(j).setupBufferState(j, (long)this.offsets.getInt(j), i);
}
}
public void clearBufferState() {
if (!RenderSystem.isOnRenderThread()) {
RenderSystem.recordRenderCall(this::_clearBufferState);
} else {
this._clearBufferState();
}
}
private void _clearBufferState() {
ImmutableList<VertexFormatElement> immutablelist = this.getElements();
for(int i = 0; i < immutablelist.size(); ++i) {
VertexFormatElement vertexformatelement = immutablelist.get(i);
vertexformatelement.clearBufferState(i);
}
}
public VertexBuffer getImmediateDrawVertexBuffer() {
VertexBuffer vertexbuffer = this.immediateDrawVertexBuffer;
if (vertexbuffer == null) {
this.immediateDrawVertexBuffer = vertexbuffer = new VertexBuffer(VertexBuffer.Usage.DYNAMIC);
}
return vertexbuffer;
}
@OnlyIn(Dist.CLIENT)
public static enum IndexType {
SHORT(5123, 2),
INT(5125, 4);
public final int asGLType;
public final int bytes;
private IndexType(int pAsGLType, int pBytes) {
this.asGLType = pAsGLType;
this.bytes = pBytes;
}
public static VertexFormat.IndexType least(int pIndexCount) {
return (pIndexCount & -65536) != 0 ? INT : SHORT;
}
}
@OnlyIn(Dist.CLIENT)
public static enum Mode {
LINES(4, 2, 2, false),
LINE_STRIP(5, 2, 1, true),
DEBUG_LINES(1, 2, 2, false),
DEBUG_LINE_STRIP(3, 2, 1, true),
TRIANGLES(4, 3, 3, false),
TRIANGLE_STRIP(5, 3, 1, true),
TRIANGLE_FAN(6, 3, 1, true),
QUADS(4, 4, 4, false);
public final int asGLMode;
public final int primitiveLength;
public final int primitiveStride;
public final boolean connectedPrimitives;
private Mode(int pAsGLMode, int pPrimitiveLength, int pPrimitiveStride, boolean pConnectedPrimitives) {
this.asGLMode = pAsGLMode;
this.primitiveLength = pPrimitiveLength;
this.primitiveStride = pPrimitiveStride;
this.connectedPrimitives = pConnectedPrimitives;
}
public int indexCount(int pVertices) {
int i;
switch (this) {
case LINE_STRIP:
case DEBUG_LINES:
case DEBUG_LINE_STRIP:
case TRIANGLES:
case TRIANGLE_STRIP:
case TRIANGLE_FAN:
i = pVertices;
break;
case LINES:
case QUADS:
i = pVertices / 4 * 6;
break;
default:
i = 0;
}
return i;
}
}
public ImmutableMap<String, VertexFormatElement> getElementMapping() { return elementMapping; }
public int getOffset(int index) { return offsets.getInt(index); }
public boolean hasPosition() { return elements.stream().anyMatch(e -> e.getUsage() == VertexFormatElement.Usage.POSITION); }
public boolean hasNormal() { return elements.stream().anyMatch(e -> e.getUsage() == VertexFormatElement.Usage.NORMAL); }
public boolean hasColor() { return elements.stream().anyMatch(e -> e.getUsage() == VertexFormatElement.Usage.COLOR); }
public boolean hasUV(int which) { return elements.stream().anyMatch(e -> e.getUsage() == VertexFormatElement.Usage.UV && e.getIndex() == which); }
}
@@ -0,0 +1,205 @@
package com.mojang.blaze3d.vertex;
import com.mojang.blaze3d.platform.GlStateManager;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class VertexFormatElement {
private final VertexFormatElement.Type type;
private final VertexFormatElement.Usage usage;
private final int index;
private final int count;
private final int byteSize;
public VertexFormatElement(int pIndex, VertexFormatElement.Type pType, VertexFormatElement.Usage pUsage, int pCount) {
if (this.supportsUsage(pIndex, pUsage)) {
this.usage = pUsage;
this.type = pType;
this.index = pIndex;
this.count = pCount;
this.byteSize = pType.getSize() * this.count;
} else {
throw new IllegalStateException("Multiple vertex elements of the same type other than UVs are not supported");
}
}
private boolean supportsUsage(int pIndex, VertexFormatElement.Usage pUsage) {
return pIndex == 0 || pUsage == VertexFormatElement.Usage.UV;
}
public final VertexFormatElement.Type getType() {
return this.type;
}
public final VertexFormatElement.Usage getUsage() {
return this.usage;
}
public final int getCount() {
return this.count;
}
public final int getIndex() {
return this.index;
}
public String toString() {
return this.count + "," + this.usage.getName() + "," + this.type.getName();
}
public final int getByteSize() {
return this.byteSize;
}
public final boolean isPosition() {
return this.usage == VertexFormatElement.Usage.POSITION;
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else if (pOther != null && this.getClass() == pOther.getClass()) {
VertexFormatElement vertexformatelement = (VertexFormatElement)pOther;
if (this.count != vertexformatelement.count) {
return false;
} else if (this.index != vertexformatelement.index) {
return false;
} else if (this.type != vertexformatelement.type) {
return false;
} else {
return this.usage == vertexformatelement.usage;
}
} else {
return false;
}
}
public int hashCode() {
int i = this.type.hashCode();
i = 31 * i + this.usage.hashCode();
i = 31 * i + this.index;
return 31 * i + this.count;
}
public void setupBufferState(int pStateIndex, long pOffset, int pStride) {
this.usage.setupBufferState(this.count, this.type.getGlType(), pStride, pOffset, this.index, pStateIndex);
}
public void clearBufferState(int pElementIndex) {
this.usage.clearBufferState(this.index, pElementIndex);
}
public int getElementCount() {
return count;
}
@OnlyIn(Dist.CLIENT)
public static enum Type {
FLOAT(4, "Float", 5126),
UBYTE(1, "Unsigned Byte", 5121),
BYTE(1, "Byte", 5120),
USHORT(2, "Unsigned Short", 5123),
SHORT(2, "Short", 5122),
UINT(4, "Unsigned Int", 5125),
INT(4, "Int", 5124);
private final int size;
private final String name;
private final int glType;
private Type(int pSize, String pName, int pGlType) {
this.size = pSize;
this.name = pName;
this.glType = pGlType;
}
public int getSize() {
return this.size;
}
public String getName() {
return this.name;
}
public int getGlType() {
return this.glType;
}
}
@OnlyIn(Dist.CLIENT)
public static enum Usage {
POSITION("Position", (p_167043_, p_167044_, p_167045_, p_167046_, p_167047_, p_167048_) -> {
GlStateManager._enableVertexAttribArray(p_167048_);
GlStateManager._vertexAttribPointer(p_167048_, p_167043_, p_167044_, false, p_167045_, p_167046_);
}, (p_167040_, p_167041_) -> {
GlStateManager._disableVertexAttribArray(p_167041_);
}),
NORMAL("Normal", (p_167033_, p_167034_, p_167035_, p_167036_, p_167037_, p_167038_) -> {
GlStateManager._enableVertexAttribArray(p_167038_);
GlStateManager._vertexAttribPointer(p_167038_, p_167033_, p_167034_, true, p_167035_, p_167036_);
}, (p_167030_, p_167031_) -> {
GlStateManager._disableVertexAttribArray(p_167031_);
}),
COLOR("Vertex Color", (p_167023_, p_167024_, p_167025_, p_167026_, p_167027_, p_167028_) -> {
GlStateManager._enableVertexAttribArray(p_167028_);
GlStateManager._vertexAttribPointer(p_167028_, p_167023_, p_167024_, true, p_167025_, p_167026_);
}, (p_167020_, p_167021_) -> {
GlStateManager._disableVertexAttribArray(p_167021_);
}),
UV("UV", (p_167013_, p_167014_, p_167015_, p_167016_, p_167017_, p_167018_) -> {
GlStateManager._enableVertexAttribArray(p_167018_);
if (p_167014_ == 5126) {
GlStateManager._vertexAttribPointer(p_167018_, p_167013_, p_167014_, false, p_167015_, p_167016_);
} else {
GlStateManager._vertexAttribIPointer(p_167018_, p_167013_, p_167014_, p_167015_, p_167016_);
}
}, (p_167010_, p_167011_) -> {
GlStateManager._disableVertexAttribArray(p_167011_);
}),
PADDING("Padding", (p_167003_, p_167004_, p_167005_, p_167006_, p_167007_, p_167008_) -> {
}, (p_167000_, p_167001_) -> {
}),
GENERIC("Generic", (p_166993_, p_166994_, p_166995_, p_166996_, p_166997_, p_166998_) -> {
GlStateManager._enableVertexAttribArray(p_166998_);
GlStateManager._vertexAttribPointer(p_166998_, p_166993_, p_166994_, false, p_166995_, p_166996_);
}, (p_166990_, p_166991_) -> {
GlStateManager._disableVertexAttribArray(p_166991_);
});
private final String name;
private final VertexFormatElement.Usage.SetupState setupState;
private final VertexFormatElement.Usage.ClearState clearState;
private Usage(String pName, VertexFormatElement.Usage.SetupState pSetupState, VertexFormatElement.Usage.ClearState pClearState) {
this.name = pName;
this.setupState = pSetupState;
this.clearState = pClearState;
}
void setupBufferState(int pCount, int pGlType, int pStride, long pOffset, int pIndex, int pStateIndex) {
this.setupState.setupBufferState(pCount, pGlType, pStride, pOffset, pIndex, pStateIndex);
}
public void clearBufferState(int pIndex, int pElementIndex) {
this.clearState.clearBufferState(pIndex, pElementIndex);
}
public String getName() {
return this.name;
}
@FunctionalInterface
@OnlyIn(Dist.CLIENT)
interface ClearState {
void clearBufferState(int pIndex, int pElementIndex);
}
@FunctionalInterface
@OnlyIn(Dist.CLIENT)
interface SetupState {
void setupBufferState(int pCount, int pGlType, int pStride, long pOffset, int pIndex, int pStateIndex);
}
}
}
@@ -0,0 +1,181 @@
package com.mojang.blaze3d.vertex;
import java.util.function.Consumer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class VertexMultiConsumer {
public static VertexConsumer create() {
throw new IllegalArgumentException();
}
public static VertexConsumer create(VertexConsumer pConsumer) {
return pConsumer;
}
public static VertexConsumer create(VertexConsumer pFirst, VertexConsumer pSecond) {
return new VertexMultiConsumer.Double(pFirst, pSecond);
}
public static VertexConsumer create(VertexConsumer... pDelegates) {
return new VertexMultiConsumer.Multiple(pDelegates);
}
@OnlyIn(Dist.CLIENT)
static class Double implements VertexConsumer {
private final VertexConsumer first;
private final VertexConsumer second;
public Double(VertexConsumer pFirst, VertexConsumer pSecond) {
if (pFirst == pSecond) {
throw new IllegalArgumentException("Duplicate delegates");
} else {
this.first = pFirst;
this.second = pSecond;
}
}
public VertexConsumer vertex(double pX, double pY, double pZ) {
this.first.vertex(pX, pY, pZ);
this.second.vertex(pX, pY, pZ);
return this;
}
public VertexConsumer color(int pRed, int pGreen, int pBlue, int pAlpha) {
this.first.color(pRed, pGreen, pBlue, pAlpha);
this.second.color(pRed, pGreen, pBlue, pAlpha);
return this;
}
public VertexConsumer uv(float pU, float pV) {
this.first.uv(pU, pV);
this.second.uv(pU, pV);
return this;
}
public VertexConsumer overlayCoords(int pU, int pV) {
this.first.overlayCoords(pU, pV);
this.second.overlayCoords(pU, pV);
return this;
}
public VertexConsumer uv2(int pU, int pV) {
this.first.uv2(pU, pV);
this.second.uv2(pU, pV);
return this;
}
public VertexConsumer normal(float pX, float pY, float pZ) {
this.first.normal(pX, pY, pZ);
this.second.normal(pX, pY, pZ);
return this;
}
public void vertex(float pX, float pY, float pZ, float pRed, float pGreen, float pBlue, float pAlpha, float pTexU, float pTexV, int pOverlayUV, int pLightmapUV, float pNormalX, float pNormalY, float pNormalZ) {
this.first.vertex(pX, pY, pZ, pRed, pGreen, pBlue, pAlpha, pTexU, pTexV, pOverlayUV, pLightmapUV, pNormalX, pNormalY, pNormalZ);
this.second.vertex(pX, pY, pZ, pRed, pGreen, pBlue, pAlpha, pTexU, pTexV, pOverlayUV, pLightmapUV, pNormalX, pNormalY, pNormalZ);
}
public void endVertex() {
this.first.endVertex();
this.second.endVertex();
}
public void defaultColor(int pDefaultR, int pDefaultG, int pDefaultB, int pDefaultA) {
this.first.defaultColor(pDefaultR, pDefaultG, pDefaultB, pDefaultA);
this.second.defaultColor(pDefaultR, pDefaultG, pDefaultB, pDefaultA);
}
public void unsetDefaultColor() {
this.first.unsetDefaultColor();
this.second.unsetDefaultColor();
}
}
@OnlyIn(Dist.CLIENT)
static class Multiple implements VertexConsumer {
private final VertexConsumer[] delegates;
public Multiple(VertexConsumer[] pDelegates) {
for(int i = 0; i < pDelegates.length; ++i) {
for(int j = i + 1; j < pDelegates.length; ++j) {
if (pDelegates[i] == pDelegates[j]) {
throw new IllegalArgumentException("Duplicate delegates");
}
}
}
this.delegates = pDelegates;
}
private void forEach(Consumer<VertexConsumer> pConsumer) {
for(VertexConsumer vertexconsumer : this.delegates) {
pConsumer.accept(vertexconsumer);
}
}
public VertexConsumer vertex(double pX, double pY, double pZ) {
this.forEach((p_167082_) -> {
p_167082_.vertex(pX, pY, pZ);
});
return this;
}
public VertexConsumer color(int pRed, int pGreen, int pBlue, int pAlpha) {
this.forEach((p_167163_) -> {
p_167163_.color(pRed, pGreen, pBlue, pAlpha);
});
return this;
}
public VertexConsumer uv(float pU, float pV) {
this.forEach((p_167125_) -> {
p_167125_.uv(pU, pV);
});
return this;
}
public VertexConsumer overlayCoords(int pU, int pV) {
this.forEach((p_167167_) -> {
p_167167_.overlayCoords(pU, pV);
});
return this;
}
public VertexConsumer uv2(int pU, int pV) {
this.forEach((p_167143_) -> {
p_167143_.uv2(pU, pV);
});
return this;
}
public VertexConsumer normal(float pX, float pY, float pZ) {
this.forEach((p_167121_) -> {
p_167121_.normal(pX, pY, pZ);
});
return this;
}
public void vertex(float pX, float pY, float pZ, float pRed, float pGreen, float pBlue, float pAlpha, float pTexU, float pTexV, int pOverlayUV, int pLightmapUV, float pNormalX, float pNormalY, float pNormalZ) {
this.forEach((p_167116_) -> {
p_167116_.vertex(pX, pY, pZ, pRed, pGreen, pBlue, pAlpha, pTexU, pTexV, pOverlayUV, pLightmapUV, pNormalX, pNormalY, pNormalZ);
});
}
public void endVertex() {
this.forEach(VertexConsumer::endVertex);
}
public void defaultColor(int pDefaultR, int pDefaultG, int pDefaultB, int pDefaultA) {
this.forEach((p_167139_) -> {
p_167139_.defaultColor(pDefaultR, pDefaultG, pDefaultB, pDefaultA);
});
}
public void unsetDefaultColor() {
this.forEach(VertexConsumer::unsetDefaultColor);
}
}
}
@@ -0,0 +1,46 @@
package com.mojang.blaze3d.vertex;
import com.google.common.primitives.Floats;
import it.unimi.dsi.fastutil.ints.IntArrays;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Vector3f;
@OnlyIn(Dist.CLIENT)
public interface VertexSorting {
VertexSorting DISTANCE_TO_ORIGIN = byDistance(0.0F, 0.0F, 0.0F);
VertexSorting ORTHOGRAPHIC_Z = byDistance((p_277433_) -> {
return -p_277433_.z();
});
static VertexSorting byDistance(float pX, float pY, float pZ) {
return byDistance(new Vector3f(pX, pY, pZ));
}
static VertexSorting byDistance(Vector3f pVector) {
return byDistance(pVector::distanceSquared);
}
static VertexSorting byDistance(VertexSorting.DistanceFunction pDistanceFunction) {
return (p_278083_) -> {
float[] afloat = new float[p_278083_.length];
int[] aint = new int[p_278083_.length];
for(int i = 0; i < p_278083_.length; aint[i] = i++) {
afloat[i] = pDistanceFunction.apply(p_278083_[i]);
}
IntArrays.mergeSort(aint, (p_277443_, p_277864_) -> {
return Floats.compare(afloat[p_277864_], afloat[p_277443_]);
});
return aint;
};
}
int[] sort(Vector3f[] pVectors);
@OnlyIn(Dist.CLIENT)
public interface DistanceFunction {
float apply(Vector3f pVector);
}
}
@@ -0,0 +1,11 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
@OnlyIn(Dist.CLIENT)
package com.mojang.blaze3d.vertex;
import com.mojang.blaze3d.FieldsAreNonnullByDefault;
import com.mojang.blaze3d.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -0,0 +1,38 @@
package com.mojang.math;
import org.joml.Quaternionf;
import org.joml.Vector3f;
@FunctionalInterface
public interface Axis {
Axis XN = (p_254437_) -> {
return (new Quaternionf()).rotationX(-p_254437_);
};
Axis XP = (p_254466_) -> {
return (new Quaternionf()).rotationX(p_254466_);
};
Axis YN = (p_254442_) -> {
return (new Quaternionf()).rotationY(-p_254442_);
};
Axis YP = (p_254103_) -> {
return (new Quaternionf()).rotationY(p_254103_);
};
Axis ZN = (p_254110_) -> {
return (new Quaternionf()).rotationZ(-p_254110_);
};
Axis ZP = (p_253997_) -> {
return (new Quaternionf()).rotationZ(p_253997_);
};
static Axis of(Vector3f p_254398_) {
return (p_254401_) -> {
return (new Quaternionf()).rotationAxis(p_254401_, p_254398_);
};
}
Quaternionf rotation(float p_254545_);
default Quaternionf rotationDegrees(float p_253800_) {
return this.rotation(p_253800_ * ((float)Math.PI / 180F));
}
}
@@ -0,0 +1,8 @@
package com.mojang.math;
public class Constants {
public static final float PI = (float)Math.PI;
public static final float RAD_TO_DEG = (180F / (float)Math.PI);
public static final float DEG_TO_RAD = ((float)Math.PI / 180F);
public static final float EPSILON = 1.0E-6F;
}
@@ -0,0 +1,52 @@
package com.mojang.math;
import com.google.common.annotations.VisibleForTesting;
import it.unimi.dsi.fastutil.ints.IntIterator;
import java.util.NoSuchElementException;
public class Divisor implements IntIterator {
private final int denominator;
private final int quotient;
private final int mod;
private int returnedParts;
private int remainder;
public Divisor(int pNumerator, int pDenominator) {
this.denominator = pDenominator;
if (pDenominator > 0) {
this.quotient = pNumerator / pDenominator;
this.mod = pNumerator % pDenominator;
} else {
this.quotient = 0;
this.mod = 0;
}
}
public boolean hasNext() {
return this.returnedParts < this.denominator;
}
public int nextInt() {
if (!this.hasNext()) {
throw new NoSuchElementException();
} else {
int i = this.quotient;
this.remainder += this.mod;
if (this.remainder >= this.denominator) {
this.remainder -= this.denominator;
++i;
}
++this.returnedParts;
return i;
}
}
@VisibleForTesting
public static Iterable<Integer> asIterable(int pNumerator, int pDenominator) {
return () -> {
return new Divisor(pNumerator, pDenominator);
};
}
}
@@ -0,0 +1,13 @@
package com.mojang.math;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Nonnull
@TypeQualifierDefault({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface FieldsAreNonnullByDefault {
}
@@ -0,0 +1,87 @@
package com.mojang.math;
import org.joml.Math;
import org.joml.Matrix3f;
import org.joml.Quaternionf;
public record GivensParameters(float sinHalf, float cosHalf) {
public static GivensParameters fromUnnormalized(float pSinHalf, float pCosHalf) {
float f = Math.invsqrt(pSinHalf * pSinHalf + pCosHalf * pCosHalf);
return new GivensParameters(f * pSinHalf, f * pCosHalf);
}
public static GivensParameters fromPositiveAngle(float pAngle) {
float f = Math.sin(pAngle / 2.0F);
float f1 = Math.cosFromSin(f, pAngle / 2.0F);
return new GivensParameters(f, f1);
}
public GivensParameters inverse() {
return new GivensParameters(-this.sinHalf, this.cosHalf);
}
public Quaternionf aroundX(Quaternionf pQuaternion) {
return pQuaternion.set(this.sinHalf, 0.0F, 0.0F, this.cosHalf);
}
public Quaternionf aroundY(Quaternionf pQuaternion) {
return pQuaternion.set(0.0F, this.sinHalf, 0.0F, this.cosHalf);
}
public Quaternionf aroundZ(Quaternionf pQuaternion) {
return pQuaternion.set(0.0F, 0.0F, this.sinHalf, this.cosHalf);
}
public float cos() {
return this.cosHalf * this.cosHalf - this.sinHalf * this.sinHalf;
}
public float sin() {
return 2.0F * this.sinHalf * this.cosHalf;
}
public Matrix3f aroundX(Matrix3f pMatrix) {
pMatrix.m01 = 0.0F;
pMatrix.m02 = 0.0F;
pMatrix.m10 = 0.0F;
pMatrix.m20 = 0.0F;
float f = this.cos();
float f1 = this.sin();
pMatrix.m11 = f;
pMatrix.m22 = f;
pMatrix.m12 = f1;
pMatrix.m21 = -f1;
pMatrix.m00 = 1.0F;
return pMatrix;
}
public Matrix3f aroundY(Matrix3f pMatrix) {
pMatrix.m01 = 0.0F;
pMatrix.m10 = 0.0F;
pMatrix.m12 = 0.0F;
pMatrix.m21 = 0.0F;
float f = this.cos();
float f1 = this.sin();
pMatrix.m00 = f;
pMatrix.m22 = f;
pMatrix.m02 = -f1;
pMatrix.m20 = f1;
pMatrix.m11 = 1.0F;
return pMatrix;
}
public Matrix3f aroundZ(Matrix3f pMatrix) {
pMatrix.m02 = 0.0F;
pMatrix.m12 = 0.0F;
pMatrix.m20 = 0.0F;
pMatrix.m21 = 0.0F;
float f = this.cos();
float f1 = this.sin();
pMatrix.m00 = f;
pMatrix.m11 = f;
pMatrix.m01 = f1;
pMatrix.m10 = -f1;
pMatrix.m22 = 1.0F;
return pMatrix;
}
}
@@ -0,0 +1,134 @@
package com.mojang.math;
import org.apache.commons.lang3.tuple.Triple;
import org.joml.Math;
import org.joml.Matrix3f;
import org.joml.Matrix3fc;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
public class MatrixUtil {
private static final float G = 3.0F + 2.0F * Math.sqrt(2.0F);
private static final GivensParameters PI_4 = GivensParameters.fromPositiveAngle(((float)java.lang.Math.PI / 4F));
private MatrixUtil() {
}
public static Matrix4f mulComponentWise(Matrix4f pMatrix, float pScalar) {
return pMatrix.set(pMatrix.m00() * pScalar, pMatrix.m01() * pScalar, pMatrix.m02() * pScalar, pMatrix.m03() * pScalar, pMatrix.m10() * pScalar, pMatrix.m11() * pScalar, pMatrix.m12() * pScalar, pMatrix.m13() * pScalar, pMatrix.m20() * pScalar, pMatrix.m21() * pScalar, pMatrix.m22() * pScalar, pMatrix.m23() * pScalar, pMatrix.m30() * pScalar, pMatrix.m31() * pScalar, pMatrix.m32() * pScalar, pMatrix.m33() * pScalar);
}
private static GivensParameters approxGivensQuat(float p_276275_, float p_276276_, float p_276282_) {
float f = 2.0F * (p_276275_ - p_276282_);
return G * p_276276_ * p_276276_ < f * f ? GivensParameters.fromUnnormalized(p_276276_, f) : PI_4;
}
private static GivensParameters qrGivensQuat(float p_253897_, float p_254413_) {
float f = (float)java.lang.Math.hypot((double)p_253897_, (double)p_254413_);
float f1 = f > 1.0E-6F ? p_254413_ : 0.0F;
float f2 = Math.abs(p_253897_) + Math.max(f, 1.0E-6F);
if (p_253897_ < 0.0F) {
float f3 = f1;
f1 = f2;
f2 = f3;
}
return GivensParameters.fromUnnormalized(f1, f2);
}
private static void similarityTransform(Matrix3f p_276319_, Matrix3f p_276263_) {
p_276319_.mul(p_276263_);
p_276263_.transpose();
p_276263_.mul(p_276319_);
p_276319_.set((Matrix3fc)p_276263_);
}
private static void stepJacobi(Matrix3f p_276262_, Matrix3f p_276279_, Quaternionf p_276314_, Quaternionf p_276299_) {
if (p_276262_.m01 * p_276262_.m01 + p_276262_.m10 * p_276262_.m10 > 1.0E-6F) {
GivensParameters givensparameters = approxGivensQuat(p_276262_.m00, 0.5F * (p_276262_.m01 + p_276262_.m10), p_276262_.m11);
Quaternionf quaternionf = givensparameters.aroundZ(p_276314_);
p_276299_.mul(quaternionf);
givensparameters.aroundZ(p_276279_);
similarityTransform(p_276262_, p_276279_);
}
if (p_276262_.m02 * p_276262_.m02 + p_276262_.m20 * p_276262_.m20 > 1.0E-6F) {
GivensParameters givensparameters1 = approxGivensQuat(p_276262_.m00, 0.5F * (p_276262_.m02 + p_276262_.m20), p_276262_.m22).inverse();
Quaternionf quaternionf1 = givensparameters1.aroundY(p_276314_);
p_276299_.mul(quaternionf1);
givensparameters1.aroundY(p_276279_);
similarityTransform(p_276262_, p_276279_);
}
if (p_276262_.m12 * p_276262_.m12 + p_276262_.m21 * p_276262_.m21 > 1.0E-6F) {
GivensParameters givensparameters2 = approxGivensQuat(p_276262_.m11, 0.5F * (p_276262_.m12 + p_276262_.m21), p_276262_.m22);
Quaternionf quaternionf2 = givensparameters2.aroundX(p_276314_);
p_276299_.mul(quaternionf2);
givensparameters2.aroundX(p_276279_);
similarityTransform(p_276262_, p_276279_);
}
}
public static Quaternionf eigenvalueJacobi(Matrix3f p_276278_, int p_276269_) {
Quaternionf quaternionf = new Quaternionf();
Matrix3f matrix3f = new Matrix3f();
Quaternionf quaternionf1 = new Quaternionf();
for(int i = 0; i < p_276269_; ++i) {
stepJacobi(p_276278_, matrix3f, quaternionf1, quaternionf);
}
quaternionf.normalize();
return quaternionf;
}
public static Triple<Quaternionf, Vector3f, Quaternionf> svdDecompose(Matrix3f pMatrix) {
Matrix3f matrix3f = new Matrix3f(pMatrix);
matrix3f.transpose();
matrix3f.mul(pMatrix);
Quaternionf quaternionf = eigenvalueJacobi(matrix3f, 5);
float f = matrix3f.m00;
float f1 = matrix3f.m11;
boolean flag = (double)f < 1.0E-6D;
boolean flag1 = (double)f1 < 1.0E-6D;
Matrix3f matrix3f1 = pMatrix.rotate(quaternionf);
Quaternionf quaternionf1 = new Quaternionf();
Quaternionf quaternionf2 = new Quaternionf();
GivensParameters givensparameters;
if (flag) {
givensparameters = qrGivensQuat(matrix3f1.m11, -matrix3f1.m10);
} else {
givensparameters = qrGivensQuat(matrix3f1.m00, matrix3f1.m01);
}
Quaternionf quaternionf3 = givensparameters.aroundZ(quaternionf2);
Matrix3f matrix3f2 = givensparameters.aroundZ(matrix3f);
quaternionf1.mul(quaternionf3);
matrix3f2.transpose().mul(matrix3f1);
if (flag) {
givensparameters = qrGivensQuat(matrix3f2.m22, -matrix3f2.m20);
} else {
givensparameters = qrGivensQuat(matrix3f2.m00, matrix3f2.m02);
}
givensparameters = givensparameters.inverse();
Quaternionf quaternionf4 = givensparameters.aroundY(quaternionf2);
Matrix3f matrix3f3 = givensparameters.aroundY(matrix3f1);
quaternionf1.mul(quaternionf4);
matrix3f3.transpose().mul(matrix3f2);
if (flag1) {
givensparameters = qrGivensQuat(matrix3f3.m22, -matrix3f3.m21);
} else {
givensparameters = qrGivensQuat(matrix3f3.m11, matrix3f3.m12);
}
Quaternionf quaternionf5 = givensparameters.aroundX(quaternionf2);
Matrix3f matrix3f4 = givensparameters.aroundX(matrix3f2);
quaternionf1.mul(quaternionf5);
matrix3f4.transpose().mul(matrix3f3);
Vector3f vector3f = new Vector3f(matrix3f4.m00, matrix3f4.m11, matrix3f4.m22);
return Triple.of(quaternionf1, vector3f, quaternionf.conjugate());
}
}
@@ -0,0 +1,13 @@
package com.mojang.math;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import javax.annotation.Nonnull;
import javax.annotation.meta.TypeQualifierDefault;
@Nonnull
@TypeQualifierDefault({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface MethodsReturnNonnullByDefault {
}
@@ -0,0 +1,173 @@
package com.mojang.math;
import com.google.common.collect.Maps;
import com.mojang.datafixers.util.Pair;
import it.unimi.dsi.fastutil.booleans.BooleanArrayList;
import it.unimi.dsi.fastutil.booleans.BooleanList;
import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
import net.minecraft.Util;
import net.minecraft.core.Direction;
import net.minecraft.core.FrontAndTop;
import net.minecraft.util.StringRepresentable;
import org.joml.Matrix3f;
public enum OctahedralGroup implements StringRepresentable {
IDENTITY("identity", SymmetricGroup3.P123, false, false, false),
ROT_180_FACE_XY("rot_180_face_xy", SymmetricGroup3.P123, true, true, false),
ROT_180_FACE_XZ("rot_180_face_xz", SymmetricGroup3.P123, true, false, true),
ROT_180_FACE_YZ("rot_180_face_yz", SymmetricGroup3.P123, false, true, true),
ROT_120_NNN("rot_120_nnn", SymmetricGroup3.P231, false, false, false),
ROT_120_NNP("rot_120_nnp", SymmetricGroup3.P312, true, false, true),
ROT_120_NPN("rot_120_npn", SymmetricGroup3.P312, false, true, true),
ROT_120_NPP("rot_120_npp", SymmetricGroup3.P231, true, false, true),
ROT_120_PNN("rot_120_pnn", SymmetricGroup3.P312, true, true, false),
ROT_120_PNP("rot_120_pnp", SymmetricGroup3.P231, true, true, false),
ROT_120_PPN("rot_120_ppn", SymmetricGroup3.P231, false, true, true),
ROT_120_PPP("rot_120_ppp", SymmetricGroup3.P312, false, false, false),
ROT_180_EDGE_XY_NEG("rot_180_edge_xy_neg", SymmetricGroup3.P213, true, true, true),
ROT_180_EDGE_XY_POS("rot_180_edge_xy_pos", SymmetricGroup3.P213, false, false, true),
ROT_180_EDGE_XZ_NEG("rot_180_edge_xz_neg", SymmetricGroup3.P321, true, true, true),
ROT_180_EDGE_XZ_POS("rot_180_edge_xz_pos", SymmetricGroup3.P321, false, true, false),
ROT_180_EDGE_YZ_NEG("rot_180_edge_yz_neg", SymmetricGroup3.P132, true, true, true),
ROT_180_EDGE_YZ_POS("rot_180_edge_yz_pos", SymmetricGroup3.P132, true, false, false),
ROT_90_X_NEG("rot_90_x_neg", SymmetricGroup3.P132, false, false, true),
ROT_90_X_POS("rot_90_x_pos", SymmetricGroup3.P132, false, true, false),
ROT_90_Y_NEG("rot_90_y_neg", SymmetricGroup3.P321, true, false, false),
ROT_90_Y_POS("rot_90_y_pos", SymmetricGroup3.P321, false, false, true),
ROT_90_Z_NEG("rot_90_z_neg", SymmetricGroup3.P213, false, true, false),
ROT_90_Z_POS("rot_90_z_pos", SymmetricGroup3.P213, true, false, false),
INVERSION("inversion", SymmetricGroup3.P123, true, true, true),
INVERT_X("invert_x", SymmetricGroup3.P123, true, false, false),
INVERT_Y("invert_y", SymmetricGroup3.P123, false, true, false),
INVERT_Z("invert_z", SymmetricGroup3.P123, false, false, true),
ROT_60_REF_NNN("rot_60_ref_nnn", SymmetricGroup3.P312, true, true, true),
ROT_60_REF_NNP("rot_60_ref_nnp", SymmetricGroup3.P231, true, false, false),
ROT_60_REF_NPN("rot_60_ref_npn", SymmetricGroup3.P231, false, false, true),
ROT_60_REF_NPP("rot_60_ref_npp", SymmetricGroup3.P312, false, false, true),
ROT_60_REF_PNN("rot_60_ref_pnn", SymmetricGroup3.P231, false, true, false),
ROT_60_REF_PNP("rot_60_ref_pnp", SymmetricGroup3.P312, true, false, false),
ROT_60_REF_PPN("rot_60_ref_ppn", SymmetricGroup3.P312, false, true, false),
ROT_60_REF_PPP("rot_60_ref_ppp", SymmetricGroup3.P231, true, true, true),
SWAP_XY("swap_xy", SymmetricGroup3.P213, false, false, false),
SWAP_YZ("swap_yz", SymmetricGroup3.P132, false, false, false),
SWAP_XZ("swap_xz", SymmetricGroup3.P321, false, false, false),
SWAP_NEG_XY("swap_neg_xy", SymmetricGroup3.P213, true, true, false),
SWAP_NEG_YZ("swap_neg_yz", SymmetricGroup3.P132, false, true, true),
SWAP_NEG_XZ("swap_neg_xz", SymmetricGroup3.P321, true, false, true),
ROT_90_REF_X_NEG("rot_90_ref_x_neg", SymmetricGroup3.P132, true, false, true),
ROT_90_REF_X_POS("rot_90_ref_x_pos", SymmetricGroup3.P132, true, true, false),
ROT_90_REF_Y_NEG("rot_90_ref_y_neg", SymmetricGroup3.P321, true, true, false),
ROT_90_REF_Y_POS("rot_90_ref_y_pos", SymmetricGroup3.P321, false, true, true),
ROT_90_REF_Z_NEG("rot_90_ref_z_neg", SymmetricGroup3.P213, false, true, true),
ROT_90_REF_Z_POS("rot_90_ref_z_pos", SymmetricGroup3.P213, true, false, true);
private final Matrix3f transformation;
private final String name;
@Nullable
private Map<Direction, Direction> rotatedDirections;
private final boolean invertX;
private final boolean invertY;
private final boolean invertZ;
private final SymmetricGroup3 permutation;
private static final OctahedralGroup[][] cayleyTable = Util.make(new OctahedralGroup[values().length][values().length], (p_56533_) -> {
Map<Pair<SymmetricGroup3, BooleanList>, OctahedralGroup> map = Arrays.stream(values()).collect(Collectors.toMap((p_174952_) -> {
return Pair.of(p_174952_.permutation, p_174952_.packInversions());
}, (p_174950_) -> {
return p_174950_;
}));
for(OctahedralGroup octahedralgroup : values()) {
for(OctahedralGroup octahedralgroup1 : values()) {
BooleanList booleanlist = octahedralgroup.packInversions();
BooleanList booleanlist1 = octahedralgroup1.packInversions();
SymmetricGroup3 symmetricgroup3 = octahedralgroup1.permutation.compose(octahedralgroup.permutation);
BooleanArrayList booleanarraylist = new BooleanArrayList(3);
for(int i = 0; i < 3; ++i) {
booleanarraylist.add(booleanlist.getBoolean(i) ^ booleanlist1.getBoolean(octahedralgroup.permutation.permutation(i)));
}
p_56533_[octahedralgroup.ordinal()][octahedralgroup1.ordinal()] = map.get(Pair.of(symmetricgroup3, booleanarraylist));
}
}
});
private static final OctahedralGroup[] inverseTable = Arrays.stream(values()).map((p_56536_) -> {
return Arrays.stream(values()).filter((p_174947_) -> {
return p_56536_.compose(p_174947_) == IDENTITY;
}).findAny().get();
}).toArray((p_56520_) -> {
return new OctahedralGroup[p_56520_];
});
private OctahedralGroup(String pName, SymmetricGroup3 pPermutation, boolean pInvertX, boolean pInvertY, boolean pInvertZ) {
this.name = pName;
this.invertX = pInvertX;
this.invertY = pInvertY;
this.invertZ = pInvertZ;
this.permutation = pPermutation;
this.transformation = (new Matrix3f()).scaling(pInvertX ? -1.0F : 1.0F, pInvertY ? -1.0F : 1.0F, pInvertZ ? -1.0F : 1.0F);
this.transformation.mul(pPermutation.transformation());
}
private BooleanList packInversions() {
return new BooleanArrayList(new boolean[]{this.invertX, this.invertY, this.invertZ});
}
public OctahedralGroup compose(OctahedralGroup pOther) {
return cayleyTable[this.ordinal()][pOther.ordinal()];
}
public OctahedralGroup inverse() {
return inverseTable[this.ordinal()];
}
public Matrix3f transformation() {
return new Matrix3f(this.transformation);
}
public String toString() {
return this.name;
}
public String getSerializedName() {
return this.name;
}
public Direction rotate(Direction pDirection) {
if (this.rotatedDirections == null) {
this.rotatedDirections = Maps.newEnumMap(Direction.class);
Direction.Axis[] adirection$axis = Direction.Axis.values();
for(Direction direction : Direction.values()) {
Direction.Axis direction$axis = direction.getAxis();
Direction.AxisDirection direction$axisdirection = direction.getAxisDirection();
Direction.Axis direction$axis1 = adirection$axis[this.permutation.permutation(direction$axis.ordinal())];
Direction.AxisDirection direction$axisdirection1 = this.inverts(direction$axis1) ? direction$axisdirection.opposite() : direction$axisdirection;
Direction direction1 = Direction.fromAxisAndDirection(direction$axis1, direction$axisdirection1);
this.rotatedDirections.put(direction, direction1);
}
}
return this.rotatedDirections.get(pDirection);
}
public boolean inverts(Direction.Axis pAxis) {
switch (pAxis) {
case X:
return this.invertX;
case Y:
return this.invertY;
case Z:
default:
return this.invertZ;
}
}
public FrontAndTop rotate(FrontAndTop pFrontAndTop) {
return FrontAndTop.fromFrontAndTop(this.rotate(pFrontAndTop.front()), this.rotate(pFrontAndTop.top()));
}
}
@@ -0,0 +1,58 @@
package com.mojang.math;
import java.util.Arrays;
import net.minecraft.Util;
import org.joml.Matrix3f;
/**
* The symmetric group S3, also known as all the permutation orders of three elements.
*/
public enum SymmetricGroup3 {
P123(0, 1, 2),
P213(1, 0, 2),
P132(0, 2, 1),
P231(1, 2, 0),
P312(2, 0, 1),
P321(2, 1, 0);
private final int[] permutation;
private final Matrix3f transformation;
private static final int ORDER = 3;
private static final SymmetricGroup3[][] cayleyTable = Util.make(new SymmetricGroup3[values().length][values().length], (p_109188_) -> {
for(SymmetricGroup3 symmetricgroup3 : values()) {
for(SymmetricGroup3 symmetricgroup31 : values()) {
int[] aint = new int[3];
for(int i = 0; i < 3; ++i) {
aint[i] = symmetricgroup3.permutation[symmetricgroup31.permutation[i]];
}
SymmetricGroup3 symmetricgroup32 = Arrays.stream(values()).filter((p_175577_) -> {
return Arrays.equals(p_175577_.permutation, aint);
}).findFirst().get();
p_109188_[symmetricgroup3.ordinal()][symmetricgroup31.ordinal()] = symmetricgroup32;
}
}
});
private SymmetricGroup3(int pFirst, int pSecond, int pThird) {
this.permutation = new int[]{pFirst, pSecond, pThird};
this.transformation = new Matrix3f();
this.transformation.set(this.permutation(0), 0, 1.0F);
this.transformation.set(this.permutation(1), 1, 1.0F);
this.transformation.set(this.permutation(2), 2, 1.0F);
}
public SymmetricGroup3 compose(SymmetricGroup3 pOther) {
return cayleyTable[this.ordinal()][pOther.ordinal()];
}
public int permutation(int pElement) {
return this.permutation[pElement];
}
public Matrix3f transformation() {
return this.transformation;
}
}
@@ -0,0 +1,191 @@
package com.mojang.math;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.util.Objects;
import javax.annotation.Nullable;
import net.minecraft.Util;
import net.minecraft.util.ExtraCodecs;
import org.apache.commons.lang3.tuple.Triple;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Quaternionf;
import org.joml.Vector3f;
import org.joml.Vector3fc;
public final class Transformation implements net.minecraftforge.common.extensions.IForgeTransformation {
private final Matrix4f matrix;
public static final Codec<Transformation> CODEC = RecordCodecBuilder.create((p_269604_) -> {
return p_269604_.group(ExtraCodecs.VECTOR3F.fieldOf("translation").forGetter((p_269599_) -> {
return p_269599_.translation;
}), ExtraCodecs.QUATERNIONF.fieldOf("left_rotation").forGetter((p_269600_) -> {
return p_269600_.leftRotation;
}), ExtraCodecs.VECTOR3F.fieldOf("scale").forGetter((p_269603_) -> {
return p_269603_.scale;
}), ExtraCodecs.QUATERNIONF.fieldOf("right_rotation").forGetter((p_269598_) -> {
return p_269598_.rightRotation;
})).apply(p_269604_, Transformation::new);
});
public static final Codec<Transformation> EXTENDED_CODEC = Codec.either(CODEC, ExtraCodecs.MATRIX4F.xmap(Transformation::new, Transformation::getMatrix)).xmap((p_269605_) -> {
return p_269605_.map((p_269601_) -> {
return p_269601_;
}, (p_269602_) -> {
return p_269602_;
});
}, Either::left);
private boolean decomposed;
@Nullable
private Vector3f translation;
@Nullable
private Quaternionf leftRotation;
@Nullable
private Vector3f scale;
@Nullable
private Quaternionf rightRotation;
private static final Transformation IDENTITY = Util.make(() -> {
Transformation transformation = new Transformation(new Matrix4f());
transformation.translation = new Vector3f();
transformation.leftRotation = new Quaternionf();
transformation.scale = new Vector3f(1.0F, 1.0F, 1.0F);
transformation.rightRotation = new Quaternionf();
transformation.decomposed = true;
return transformation;
});
public Transformation(@Nullable Matrix4f p_253689_) {
if (p_253689_ == null) {
this.matrix = new Matrix4f();
} else {
this.matrix = p_253689_;
}
}
public Transformation(@Nullable Vector3f p_253831_, @Nullable Quaternionf p_253846_, @Nullable Vector3f p_254502_, @Nullable Quaternionf p_253912_) {
this.matrix = compose(p_253831_, p_253846_, p_254502_, p_253912_);
this.translation = p_253831_ != null ? p_253831_ : new Vector3f();
this.leftRotation = p_253846_ != null ? p_253846_ : new Quaternionf();
this.scale = p_254502_ != null ? p_254502_ : new Vector3f(1.0F, 1.0F, 1.0F);
this.rightRotation = p_253912_ != null ? p_253912_ : new Quaternionf();
this.decomposed = true;
}
public static Transformation identity() {
return IDENTITY;
}
public Transformation compose(Transformation pOther) {
Matrix4f matrix4f = this.getMatrix();
matrix4f.mul(pOther.getMatrix());
return new Transformation(matrix4f);
}
@Nullable
public Transformation inverse() {
if (this == IDENTITY) {
return this;
} else {
Matrix4f matrix4f = this.getMatrix().invert();
return matrix4f.isFinite() ? new Transformation(matrix4f) : null;
}
}
private void ensureDecomposed() {
if (!this.decomposed) {
float f = 1.0F / this.matrix.m33();
Triple<Quaternionf, Vector3f, Quaternionf> triple = MatrixUtil.svdDecompose((new Matrix3f(this.matrix)).scale(f));
this.translation = this.matrix.getTranslation(new Vector3f()).mul(f);
this.leftRotation = new Quaternionf(triple.getLeft());
this.scale = new Vector3f(triple.getMiddle());
this.rightRotation = new Quaternionf(triple.getRight());
this.decomposed = true;
}
}
private static Matrix4f compose(@Nullable Vector3f pTranslation, @Nullable Quaternionf pLeftRotation, @Nullable Vector3f pScale, @Nullable Quaternionf pRightRotation) {
Matrix4f matrix4f = new Matrix4f();
if (pTranslation != null) {
matrix4f.translation(pTranslation);
}
if (pLeftRotation != null) {
matrix4f.rotate(pLeftRotation);
}
if (pScale != null) {
matrix4f.scale(pScale);
}
if (pRightRotation != null) {
matrix4f.rotate(pRightRotation);
}
return matrix4f;
}
public Matrix4f getMatrix() {
return new Matrix4f(this.matrix);
}
public Vector3f getTranslation() {
this.ensureDecomposed();
return new Vector3f((Vector3fc)this.translation);
}
public Quaternionf getLeftRotation() {
this.ensureDecomposed();
return new Quaternionf(this.leftRotation);
}
public Vector3f getScale() {
this.ensureDecomposed();
return new Vector3f((Vector3fc)this.scale);
}
public Quaternionf getRightRotation() {
this.ensureDecomposed();
return new Quaternionf(this.rightRotation);
}
public boolean equals(Object pOther) {
if (this == pOther) {
return true;
} else if (pOther != null && this.getClass() == pOther.getClass()) {
Transformation transformation = (Transformation)pOther;
return Objects.equals(this.matrix, transformation.matrix);
} else {
return false;
}
}
public int hashCode() {
return Objects.hash(this.matrix);
}
private Matrix3f normalTransform = null;
public Matrix3f getNormalMatrix() {
checkNormalTransform();
return normalTransform;
}
private void checkNormalTransform() {
if (normalTransform == null) {
normalTransform = new Matrix3f(matrix);
normalTransform.invert();
normalTransform.transpose();
}
}
public Transformation slerp(Transformation pTransformation, float pDelta) {
Vector3f vector3f = this.getTranslation();
Quaternionf quaternionf = this.getLeftRotation();
Vector3f vector3f1 = this.getScale();
Quaternionf quaternionf1 = this.getRightRotation();
vector3f.lerp(pTransformation.getTranslation(), pDelta);
quaternionf.slerp(pTransformation.getLeftRotation(), pDelta);
vector3f1.lerp(pTransformation.getScale(), pDelta);
quaternionf1.slerp(pTransformation.getRightRotation(), pDelta);
return new Transformation(vector3f, quaternionf, vector3f1, quaternionf1);
}
}
@@ -0,0 +1,6 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@FieldsAreNonnullByDefault
package com.mojang.math;
import javax.annotation.ParametersAreNonnullByDefault;
@@ -0,0 +1,48 @@
package com.mojang.realmsclient;
import java.util.Arrays;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class KeyCombo {
private final char[] chars;
private int matchIndex;
private final Runnable onCompletion;
public KeyCombo(char[] pChars, Runnable pOnCompletion) {
this.onCompletion = pOnCompletion;
if (pChars.length < 1) {
throw new IllegalArgumentException("Must have at least one char");
} else {
this.chars = pChars;
}
}
public KeyCombo(char[] pChars) {
this(pChars, () -> {
});
}
public boolean keyPressed(char pKey) {
if (pKey == this.chars[this.matchIndex++]) {
if (this.matchIndex == this.chars.length) {
this.reset();
this.onCompletion.run();
return true;
}
} else {
this.reset();
}
return false;
}
public void reset() {
this.matchIndex = 0;
}
public String toString() {
return "KeyCombo{chars=" + Arrays.toString(this.chars) + ", matchIndex=" + this.matchIndex + "}";
}
}
@@ -0,0 +1,48 @@
package com.mojang.realmsclient;
import java.util.Locale;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public enum Unit {
B,
KB,
MB,
GB;
private static final int BASE_UNIT = 1024;
public static Unit getLargest(long pBytes) {
if (pBytes < 1024L) {
return B;
} else {
try {
int i = (int)(Math.log((double)pBytes) / Math.log(1024.0D));
String s = String.valueOf("KMGTPE".charAt(i - 1));
return valueOf(s + "B");
} catch (Exception exception) {
return GB;
}
}
}
public static double convertTo(long pBytes, Unit pUnit) {
return pUnit == B ? (double)pBytes : (double)pBytes / Math.pow(1024.0D, (double)pUnit.ordinal());
}
public static String humanReadable(long pBytes) {
int i = 1024;
if (pBytes < 1024L) {
return pBytes + " B";
} else {
int j = (int)(Math.log((double)pBytes) / Math.log(1024.0D));
String s = "" + "KMGTPE".charAt(j - 1);
return String.format(Locale.ROOT, "%.1f %sB", (double)pBytes / Math.pow(1024.0D, (double)j), s);
}
}
public static String humanReadable(long pBytes, Unit pUnit) {
return String.format(Locale.ROOT, "%." + (pUnit == GB ? "1" : "0") + "f %s", convertTo(pBytes, pUnit), pUnit.name());
}
}
@@ -0,0 +1,413 @@
package com.mojang.realmsclient.client;
import com.google.common.hash.Hashing;
import com.google.common.io.Files;
import com.mojang.logging.LogUtils;
import com.mojang.realmsclient.dto.WorldDownload;
import com.mojang.realmsclient.exception.RealmsDefaultUncaughtExceptionHandler;
import com.mojang.realmsclient.gui.screens.RealmsDownloadLatestWorldScreen;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Path;
import java.util.Locale;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import net.minecraft.SharedConstants;
import net.minecraft.client.Minecraft;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import net.minecraft.world.level.storage.LevelResource;
import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.validation.ContentValidationException;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.output.CountingOutputStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class FileDownload {
static final Logger LOGGER = LogUtils.getLogger();
volatile boolean cancelled;
volatile boolean finished;
volatile boolean error;
volatile boolean extracting;
@Nullable
private volatile File tempFile;
volatile File resourcePackPath;
@Nullable
private volatile HttpGet request;
@Nullable
private Thread currentThread;
private final RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(120000).setConnectTimeout(120000).build();
private static final String[] INVALID_FILE_NAMES = new String[]{"CON", "COM", "PRN", "AUX", "CLOCK$", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"};
public long contentLength(String pUri) {
CloseableHttpClient closeablehttpclient = null;
HttpGet httpget = null;
long i;
try {
httpget = new HttpGet(pUri);
closeablehttpclient = HttpClientBuilder.create().setDefaultRequestConfig(this.requestConfig).build();
CloseableHttpResponse closeablehttpresponse = closeablehttpclient.execute(httpget);
return Long.parseLong(closeablehttpresponse.getFirstHeader("Content-Length").getValue());
} catch (Throwable throwable) {
LOGGER.error("Unable to get content length for download");
i = 0L;
} finally {
if (httpget != null) {
httpget.releaseConnection();
}
if (closeablehttpclient != null) {
try {
closeablehttpclient.close();
} catch (IOException ioexception) {
LOGGER.error("Could not close http client", (Throwable)ioexception);
}
}
}
return i;
}
public void download(WorldDownload pDownload, String pWorldName, RealmsDownloadLatestWorldScreen.DownloadStatus pStatus, LevelStorageSource pSource) {
if (this.currentThread == null) {
this.currentThread = new Thread(() -> {
CloseableHttpClient closeablehttpclient = null;
try {
this.tempFile = File.createTempFile("backup", ".tar.gz");
this.request = new HttpGet(pDownload.downloadLink);
closeablehttpclient = HttpClientBuilder.create().setDefaultRequestConfig(this.requestConfig).build();
HttpResponse httpresponse = closeablehttpclient.execute(this.request);
pStatus.totalBytes = Long.parseLong(httpresponse.getFirstHeader("Content-Length").getValue());
if (httpresponse.getStatusLine().getStatusCode() == 200) {
OutputStream outputstream = new FileOutputStream(this.tempFile);
FileDownload.ProgressListener filedownload$progresslistener = new FileDownload.ProgressListener(pWorldName.trim(), this.tempFile, pSource, pStatus);
FileDownload.DownloadCountingOutputStream filedownload$downloadcountingoutputstream = new FileDownload.DownloadCountingOutputStream(outputstream);
filedownload$downloadcountingoutputstream.setListener(filedownload$progresslistener);
IOUtils.copy(httpresponse.getEntity().getContent(), filedownload$downloadcountingoutputstream);
return;
}
this.error = true;
this.request.abort();
} catch (Exception exception1) {
LOGGER.error("Caught exception while downloading: {}", (Object)exception1.getMessage());
this.error = true;
return;
} finally {
this.request.releaseConnection();
if (this.tempFile != null) {
this.tempFile.delete();
}
if (!this.error) {
if (!pDownload.resourcePackUrl.isEmpty() && !pDownload.resourcePackHash.isEmpty()) {
try {
this.tempFile = File.createTempFile("resources", ".tar.gz");
this.request = new HttpGet(pDownload.resourcePackUrl);
HttpResponse httpresponse1 = closeablehttpclient.execute(this.request);
pStatus.totalBytes = Long.parseLong(httpresponse1.getFirstHeader("Content-Length").getValue());
if (httpresponse1.getStatusLine().getStatusCode() != 200) {
this.error = true;
this.request.abort();
return;
}
OutputStream outputstream1 = new FileOutputStream(this.tempFile);
FileDownload.ResourcePackProgressListener filedownload$resourcepackprogresslistener = new FileDownload.ResourcePackProgressListener(this.tempFile, pStatus, pDownload);
FileDownload.DownloadCountingOutputStream filedownload$downloadcountingoutputstream1 = new FileDownload.DownloadCountingOutputStream(outputstream1);
filedownload$downloadcountingoutputstream1.setListener(filedownload$resourcepackprogresslistener);
IOUtils.copy(httpresponse1.getEntity().getContent(), filedownload$downloadcountingoutputstream1);
} catch (Exception exception) {
LOGGER.error("Caught exception while downloading: {}", (Object)exception.getMessage());
this.error = true;
} finally {
this.request.releaseConnection();
if (this.tempFile != null) {
this.tempFile.delete();
}
}
} else {
this.finished = true;
}
}
if (closeablehttpclient != null) {
try {
closeablehttpclient.close();
} catch (IOException ioexception) {
LOGGER.error("Failed to close Realms download client");
}
}
}
});
this.currentThread.setUncaughtExceptionHandler(new RealmsDefaultUncaughtExceptionHandler(LOGGER));
this.currentThread.start();
}
}
public void cancel() {
if (this.request != null) {
this.request.abort();
}
if (this.tempFile != null) {
this.tempFile.delete();
}
this.cancelled = true;
}
public boolean isFinished() {
return this.finished;
}
public boolean isError() {
return this.error;
}
public boolean isExtracting() {
return this.extracting;
}
/**
* Modifies a folder name to make sure it is valid to store on disk.
* @return the modified folder name
* @param pFolderName The folder name to modify
*/
public static String findAvailableFolderName(String pFolderName) {
pFolderName = pFolderName.replaceAll("[\\./\"]", "_");
for(String s : INVALID_FILE_NAMES) {
if (pFolderName.equalsIgnoreCase(s)) {
pFolderName = "_" + pFolderName + "_";
}
}
return pFolderName;
}
void untarGzipArchive(String p_86992_, @Nullable File p_86993_, LevelStorageSource p_86994_) throws IOException {
Pattern pattern = Pattern.compile(".*-([0-9]+)$");
int i = 1;
for(char c0 : SharedConstants.ILLEGAL_FILE_CHARACTERS) {
p_86992_ = p_86992_.replace(c0, '_');
}
if (StringUtils.isEmpty(p_86992_)) {
p_86992_ = "Realm";
}
p_86992_ = findAvailableFolderName(p_86992_);
try {
for(LevelStorageSource.LevelDirectory levelstoragesource$leveldirectory : p_86994_.findLevelCandidates()) {
String s1 = levelstoragesource$leveldirectory.directoryName();
if (s1.toLowerCase(Locale.ROOT).startsWith(p_86992_.toLowerCase(Locale.ROOT))) {
Matcher matcher = pattern.matcher(s1);
if (matcher.matches()) {
int j = Integer.parseInt(matcher.group(1));
if (j > i) {
i = j;
}
} else {
++i;
}
}
}
} catch (Exception exception1) {
LOGGER.error("Error getting level list", (Throwable)exception1);
this.error = true;
return;
}
String s;
if (p_86994_.isNewLevelIdAcceptable(p_86992_) && i <= 1) {
s = p_86992_;
} else {
s = p_86992_ + (i == 1 ? "" : "-" + i);
if (!p_86994_.isNewLevelIdAcceptable(s)) {
boolean flag = false;
while(!flag) {
++i;
s = p_86992_ + (i == 1 ? "" : "-" + i);
if (p_86994_.isNewLevelIdAcceptable(s)) {
flag = true;
}
}
}
}
TarArchiveInputStream tararchiveinputstream = null;
File file1 = new File(Minecraft.getInstance().gameDirectory.getAbsolutePath(), "saves");
try {
file1.mkdir();
tararchiveinputstream = new TarArchiveInputStream(new GzipCompressorInputStream(new BufferedInputStream(new FileInputStream(p_86993_))));
for(TarArchiveEntry tararchiveentry = tararchiveinputstream.getNextTarEntry(); tararchiveentry != null; tararchiveentry = tararchiveinputstream.getNextTarEntry()) {
File file2 = new File(file1, tararchiveentry.getName().replace("world", s));
if (tararchiveentry.isDirectory()) {
file2.mkdirs();
} else {
file2.createNewFile();
try (FileOutputStream fileoutputstream = new FileOutputStream(file2)) {
IOUtils.copy(tararchiveinputstream, fileoutputstream);
}
}
}
} catch (Exception exception) {
LOGGER.error("Error extracting world", (Throwable)exception);
this.error = true;
} finally {
if (tararchiveinputstream != null) {
tararchiveinputstream.close();
}
if (p_86993_ != null) {
p_86993_.delete();
}
try (LevelStorageSource.LevelStorageAccess levelstoragesource$levelstorageaccess = p_86994_.validateAndCreateAccess(s)) {
levelstoragesource$levelstorageaccess.renameLevel(s.trim());
Path path = levelstoragesource$levelstorageaccess.getLevelPath(LevelResource.LEVEL_DATA_FILE);
deletePlayerTag(path.toFile());
} catch (IOException ioexception) {
LOGGER.error("Failed to rename unpacked realms level {}", s, ioexception);
} catch (ContentValidationException contentvalidationexception) {
LOGGER.warn("{}", (Object)contentvalidationexception.getMessage());
}
this.resourcePackPath = new File(file1, s + File.separator + "resources.zip");
}
}
private static void deletePlayerTag(File p_86988_) {
if (p_86988_.exists()) {
try {
CompoundTag compoundtag = NbtIo.readCompressed(p_86988_);
CompoundTag compoundtag1 = compoundtag.getCompound("Data");
compoundtag1.remove("Player");
NbtIo.writeCompressed(compoundtag, p_86988_);
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
@OnlyIn(Dist.CLIENT)
static class DownloadCountingOutputStream extends CountingOutputStream {
@Nullable
private ActionListener listener;
public DownloadCountingOutputStream(OutputStream pOut) {
super(pOut);
}
public void setListener(ActionListener pListener) {
this.listener = pListener;
}
protected void afterWrite(int pBytesWritten) throws IOException {
super.afterWrite(pBytesWritten);
if (this.listener != null) {
this.listener.actionPerformed(new ActionEvent(this, 0, (String)null));
}
}
}
@OnlyIn(Dist.CLIENT)
class ProgressListener implements ActionListener {
private final String worldName;
private final File tempFile;
private final LevelStorageSource levelStorageSource;
private final RealmsDownloadLatestWorldScreen.DownloadStatus downloadStatus;
ProgressListener(String pWorldName, File pTempFile, LevelStorageSource pLevelStorageSource, RealmsDownloadLatestWorldScreen.DownloadStatus pDownloadStatus) {
this.worldName = pWorldName;
this.tempFile = pTempFile;
this.levelStorageSource = pLevelStorageSource;
this.downloadStatus = pDownloadStatus;
}
public void actionPerformed(ActionEvent pAction) {
this.downloadStatus.bytesWritten = ((FileDownload.DownloadCountingOutputStream)pAction.getSource()).getByteCount();
if (this.downloadStatus.bytesWritten >= this.downloadStatus.totalBytes && !FileDownload.this.cancelled && !FileDownload.this.error) {
try {
FileDownload.this.extracting = true;
FileDownload.this.untarGzipArchive(this.worldName, this.tempFile, this.levelStorageSource);
} catch (IOException ioexception) {
FileDownload.LOGGER.error("Error extracting archive", (Throwable)ioexception);
FileDownload.this.error = true;
}
}
}
}
@OnlyIn(Dist.CLIENT)
class ResourcePackProgressListener implements ActionListener {
private final File tempFile;
private final RealmsDownloadLatestWorldScreen.DownloadStatus downloadStatus;
private final WorldDownload worldDownload;
ResourcePackProgressListener(File pTempFile, RealmsDownloadLatestWorldScreen.DownloadStatus pDownloadStatus, WorldDownload pWorldDownload) {
this.tempFile = pTempFile;
this.downloadStatus = pDownloadStatus;
this.worldDownload = pWorldDownload;
}
public void actionPerformed(ActionEvent pAction) {
this.downloadStatus.bytesWritten = ((FileDownload.DownloadCountingOutputStream)pAction.getSource()).getByteCount();
if (this.downloadStatus.bytesWritten >= this.downloadStatus.totalBytes && !FileDownload.this.cancelled) {
try {
String s = Hashing.sha1().hashBytes(Files.toByteArray(this.tempFile)).toString();
if (s.equals(this.worldDownload.resourcePackHash)) {
FileUtils.copyFile(this.tempFile, FileDownload.this.resourcePackPath);
FileDownload.this.finished = true;
} else {
FileDownload.LOGGER.error("Resourcepack had wrong hash (expected {}, found {}). Deleting it.", this.worldDownload.resourcePackHash, s);
FileUtils.deleteQuietly(this.tempFile);
FileDownload.this.error = true;
}
} catch (IOException ioexception) {
FileDownload.LOGGER.error("Error copying resourcepack file: {}", (Object)ioexception.getMessage());
FileDownload.this.error = true;
}
}
}
}
}
@@ -0,0 +1,224 @@
package com.mojang.realmsclient.client;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.mojang.logging.LogUtils;
import com.mojang.realmsclient.dto.UploadInfo;
import com.mojang.realmsclient.gui.screens.UploadResult;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Duration;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import net.minecraft.client.User;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.InputStreamEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.Args;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class FileUpload {
private static final Logger LOGGER = LogUtils.getLogger();
private static final int MAX_RETRIES = 5;
private static final String UPLOAD_PATH = "/upload";
private final File file;
private final long worldId;
private final int slotId;
private final UploadInfo uploadInfo;
private final String sessionId;
private final String username;
private final String clientVersion;
private final UploadStatus uploadStatus;
private final AtomicBoolean cancelled = new AtomicBoolean(false);
@Nullable
private CompletableFuture<UploadResult> uploadTask;
private final RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout((int)TimeUnit.MINUTES.toMillis(10L)).setConnectTimeout((int)TimeUnit.SECONDS.toMillis(15L)).build();
public FileUpload(File pFile, long pWorldId, int pSlotId, UploadInfo pUploadInfo, User pUser, String pClientVersion, UploadStatus pUploadStatus) {
this.file = pFile;
this.worldId = pWorldId;
this.slotId = pSlotId;
this.uploadInfo = pUploadInfo;
this.sessionId = pUser.getSessionId();
this.username = pUser.getName();
this.clientVersion = pClientVersion;
this.uploadStatus = pUploadStatus;
}
public void upload(Consumer<UploadResult> p_87085_) {
if (this.uploadTask == null) {
this.uploadTask = CompletableFuture.supplyAsync(() -> {
return this.requestUpload(0);
});
this.uploadTask.thenAccept(p_87085_);
}
}
public void cancel() {
this.cancelled.set(true);
if (this.uploadTask != null) {
this.uploadTask.cancel(false);
this.uploadTask = null;
}
}
/**
*
* @param pRetries The number of times this upload has already been attempted
*/
private UploadResult requestUpload(int pRetries) {
UploadResult.Builder uploadresult$builder = new UploadResult.Builder();
if (this.cancelled.get()) {
return uploadresult$builder.build();
} else {
this.uploadStatus.totalBytes = this.file.length();
HttpPost httppost = new HttpPost(this.uploadInfo.getUploadEndpoint().resolve("/upload/" + this.worldId + "/" + this.slotId));
CloseableHttpClient closeablehttpclient = HttpClientBuilder.create().setDefaultRequestConfig(this.requestConfig).build();
UploadResult uploadresult;
try {
this.setupRequest(httppost);
HttpResponse httpresponse = closeablehttpclient.execute(httppost);
long i = this.getRetryDelaySeconds(httpresponse);
if (!this.shouldRetry(i, pRetries)) {
this.handleResponse(httpresponse, uploadresult$builder);
return uploadresult$builder.build();
}
uploadresult = this.retryUploadAfter(i, pRetries);
} catch (Exception exception) {
if (!this.cancelled.get()) {
LOGGER.error("Caught exception while uploading: ", (Throwable)exception);
}
return uploadresult$builder.build();
} finally {
this.cleanup(httppost, closeablehttpclient);
}
return uploadresult;
}
}
private void cleanup(HttpPost p_87094_, @Nullable CloseableHttpClient p_87095_) {
p_87094_.releaseConnection();
if (p_87095_ != null) {
try {
p_87095_.close();
} catch (IOException ioexception) {
LOGGER.error("Failed to close Realms upload client");
}
}
}
private void setupRequest(HttpPost p_87092_) throws FileNotFoundException {
p_87092_.setHeader("Cookie", "sid=" + this.sessionId + ";token=" + this.uploadInfo.getToken() + ";user=" + this.username + ";version=" + this.clientVersion);
FileUpload.CustomInputStreamEntity fileupload$custominputstreamentity = new FileUpload.CustomInputStreamEntity(new FileInputStream(this.file), this.file.length(), this.uploadStatus);
fileupload$custominputstreamentity.setContentType("application/octet-stream");
p_87092_.setEntity(fileupload$custominputstreamentity);
}
private void handleResponse(HttpResponse pResponse, UploadResult.Builder pUploadResult) throws IOException {
int i = pResponse.getStatusLine().getStatusCode();
if (i == 401) {
LOGGER.debug("Realms server returned 401: {}", (Object)pResponse.getFirstHeader("WWW-Authenticate"));
}
pUploadResult.withStatusCode(i);
if (pResponse.getEntity() != null) {
String s = EntityUtils.toString(pResponse.getEntity(), "UTF-8");
if (s != null) {
try {
JsonParser jsonparser = new JsonParser();
JsonElement jsonelement = jsonparser.parse(s).getAsJsonObject().get("errorMsg");
Optional<String> optional = Optional.ofNullable(jsonelement).map(JsonElement::getAsString);
pUploadResult.withErrorMessage(optional.orElse((String)null));
} catch (Exception exception) {
}
}
}
}
private boolean shouldRetry(long p_87082_, int pRetries) {
return p_87082_ > 0L && pRetries + 1 < 5;
}
private UploadResult retryUploadAfter(long pSeconds, int pRetries) throws InterruptedException {
Thread.sleep(Duration.ofSeconds(pSeconds).toMillis());
return this.requestUpload(pRetries + 1);
}
private long getRetryDelaySeconds(HttpResponse pHttpResponse) {
return Optional.ofNullable(pHttpResponse.getFirstHeader("Retry-After")).map(NameValuePair::getValue).map(Long::valueOf).orElse(0L);
}
public boolean isFinished() {
return this.uploadTask.isDone() || this.uploadTask.isCancelled();
}
@OnlyIn(Dist.CLIENT)
static class CustomInputStreamEntity extends InputStreamEntity {
private final long length;
private final InputStream content;
private final UploadStatus uploadStatus;
public CustomInputStreamEntity(InputStream pContent, long pLength, UploadStatus pUploadStatus) {
super(pContent);
this.content = pContent;
this.length = pLength;
this.uploadStatus = pUploadStatus;
}
public void writeTo(OutputStream p_87109_) throws IOException {
Args.notNull(p_87109_, "Output stream");
InputStream inputstream = this.content;
try {
byte[] abyte = new byte[4096];
int j;
if (this.length < 0L) {
while((j = inputstream.read(abyte)) != -1) {
p_87109_.write(abyte, 0, j);
this.uploadStatus.bytesWritten += (long)j;
}
} else {
long i = this.length;
while(i > 0L) {
j = inputstream.read(abyte, 0, (int)Math.min(4096L, i));
if (j == -1) {
break;
}
p_87109_.write(abyte, 0, j);
this.uploadStatus.bytesWritten += (long)j;
i -= (long)j;
p_87109_.flush();
}
}
} finally {
inputstream.close();
}
}
}
}
@@ -0,0 +1,81 @@
package com.mojang.realmsclient.client;
import com.google.common.collect.Lists;
import com.mojang.realmsclient.dto.RegionPingResult;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.Comparator;
import java.util.List;
import net.minecraft.Util;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.commons.io.IOUtils;
@OnlyIn(Dist.CLIENT)
public class Ping {
public static List<RegionPingResult> ping(Ping.Region... pRegions) {
for(Ping.Region ping$region : pRegions) {
ping(ping$region.endpoint);
}
List<RegionPingResult> list = Lists.newArrayList();
for(Ping.Region ping$region1 : pRegions) {
list.add(new RegionPingResult(ping$region1.name, ping(ping$region1.endpoint)));
}
list.sort(Comparator.comparingInt(RegionPingResult::ping));
return list;
}
private static int ping(String pHostname) {
int i = 700;
long j = 0L;
Socket socket = null;
for(int k = 0; k < 5; ++k) {
try {
SocketAddress socketaddress = new InetSocketAddress(pHostname, 80);
socket = new Socket();
long l = now();
socket.connect(socketaddress, 700);
j += now() - l;
} catch (Exception exception) {
j += 700L;
} finally {
IOUtils.closeQuietly(socket);
}
}
return (int)((double)j / 5.0D);
}
private static long now() {
return Util.getMillis();
}
public static List<RegionPingResult> pingAllRegions() {
return ping(Ping.Region.values());
}
@OnlyIn(Dist.CLIENT)
static enum Region {
US_EAST_1("us-east-1", "ec2.us-east-1.amazonaws.com"),
US_WEST_2("us-west-2", "ec2.us-west-2.amazonaws.com"),
US_WEST_1("us-west-1", "ec2.us-west-1.amazonaws.com"),
EU_WEST_1("eu-west-1", "ec2.eu-west-1.amazonaws.com"),
AP_SOUTHEAST_1("ap-southeast-1", "ec2.ap-southeast-1.amazonaws.com"),
AP_SOUTHEAST_2("ap-southeast-2", "ec2.ap-southeast-2.amazonaws.com"),
AP_NORTHEAST_1("ap-northeast-1", "ec2.ap-northeast-1.amazonaws.com"),
SA_EAST_1("sa-east-1", "ec2.sa-east-1.amazonaws.com");
final String name;
final String endpoint;
private Region(String pName, String pEndpoint) {
this.name = pName;
this.endpoint = pEndpoint;
}
}
}
@@ -0,0 +1,497 @@
package com.mojang.realmsclient.client;
import com.google.gson.JsonArray;
import com.mojang.logging.LogUtils;
import com.mojang.realmsclient.dto.BackupList;
import com.mojang.realmsclient.dto.GuardedSerializer;
import com.mojang.realmsclient.dto.Ops;
import com.mojang.realmsclient.dto.PendingInvite;
import com.mojang.realmsclient.dto.PendingInvitesList;
import com.mojang.realmsclient.dto.PingResult;
import com.mojang.realmsclient.dto.PlayerInfo;
import com.mojang.realmsclient.dto.RealmsDescriptionDto;
import com.mojang.realmsclient.dto.RealmsNews;
import com.mojang.realmsclient.dto.RealmsNotification;
import com.mojang.realmsclient.dto.RealmsServer;
import com.mojang.realmsclient.dto.RealmsServerAddress;
import com.mojang.realmsclient.dto.RealmsServerList;
import com.mojang.realmsclient.dto.RealmsServerPlayerLists;
import com.mojang.realmsclient.dto.RealmsWorldOptions;
import com.mojang.realmsclient.dto.RealmsWorldResetDto;
import com.mojang.realmsclient.dto.ServerActivityList;
import com.mojang.realmsclient.dto.Subscription;
import com.mojang.realmsclient.dto.UploadInfo;
import com.mojang.realmsclient.dto.WorldDownload;
import com.mojang.realmsclient.dto.WorldTemplatePaginatedList;
import com.mojang.realmsclient.exception.RealmsHttpException;
import com.mojang.realmsclient.exception.RealmsServiceException;
import com.mojang.realmsclient.exception.RetryCallException;
import com.mojang.realmsclient.util.WorldGenerationInfo;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Locale;
import java.util.Optional;
import java.util.UUID;
import javax.annotation.Nullable;
import net.minecraft.SharedConstants;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.language.I18n;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class RealmsClient {
public static RealmsClient.Environment currentEnvironment = RealmsClient.Environment.PRODUCTION;
private static boolean initialized;
private static final Logger LOGGER = LogUtils.getLogger();
private final String sessionId;
private final String username;
private final Minecraft minecraft;
private static final String WORLDS_RESOURCE_PATH = "worlds";
private static final String INVITES_RESOURCE_PATH = "invites";
private static final String MCO_RESOURCE_PATH = "mco";
private static final String SUBSCRIPTION_RESOURCE = "subscriptions";
private static final String ACTIVITIES_RESOURCE = "activities";
private static final String OPS_RESOURCE = "ops";
private static final String REGIONS_RESOURCE = "regions/ping/stat";
private static final String TRIALS_RESOURCE = "trial";
private static final String NOTIFICATIONS_RESOURCE = "notifications";
private static final String PATH_INITIALIZE = "/$WORLD_ID/initialize";
private static final String PATH_GET_ACTIVTIES = "/$WORLD_ID";
private static final String PATH_GET_LIVESTATS = "/liveplayerlist";
private static final String PATH_GET_SUBSCRIPTION = "/$WORLD_ID";
private static final String PATH_OP = "/$WORLD_ID/$PROFILE_UUID";
private static final String PATH_PUT_INTO_MINIGAMES_MODE = "/minigames/$MINIGAME_ID/$WORLD_ID";
private static final String PATH_AVAILABLE = "/available";
private static final String PATH_TEMPLATES = "/templates/$WORLD_TYPE";
private static final String PATH_WORLD_JOIN = "/v1/$ID/join/pc";
private static final String PATH_WORLD_GET = "/$ID";
private static final String PATH_WORLD_INVITES = "/$WORLD_ID";
private static final String PATH_WORLD_UNINVITE = "/$WORLD_ID/invite/$UUID";
private static final String PATH_PENDING_INVITES_COUNT = "/count/pending";
private static final String PATH_PENDING_INVITES = "/pending";
private static final String PATH_ACCEPT_INVITE = "/accept/$INVITATION_ID";
private static final String PATH_REJECT_INVITE = "/reject/$INVITATION_ID";
private static final String PATH_UNINVITE_MYSELF = "/$WORLD_ID";
private static final String PATH_WORLD_UPDATE = "/$WORLD_ID";
private static final String PATH_SLOT = "/$WORLD_ID/slot/$SLOT_ID";
private static final String PATH_WORLD_OPEN = "/$WORLD_ID/open";
private static final String PATH_WORLD_CLOSE = "/$WORLD_ID/close";
private static final String PATH_WORLD_RESET = "/$WORLD_ID/reset";
private static final String PATH_DELETE_WORLD = "/$WORLD_ID";
private static final String PATH_WORLD_BACKUPS = "/$WORLD_ID/backups";
private static final String PATH_WORLD_DOWNLOAD = "/$WORLD_ID/slot/$SLOT_ID/download";
private static final String PATH_WORLD_UPLOAD = "/$WORLD_ID/backups/upload";
private static final String PATH_CLIENT_COMPATIBLE = "/client/compatible";
private static final String PATH_TOS_AGREED = "/tos/agreed";
private static final String PATH_NEWS = "/v1/news";
private static final String PATH_MARK_NOTIFICATIONS_SEEN = "/seen";
private static final String PATH_DISMISS_NOTIFICATIONS = "/dismiss";
private static final String PATH_STAGE_AVAILABLE = "/stageAvailable";
private static final GuardedSerializer GSON = new GuardedSerializer();
public static RealmsClient create() {
Minecraft minecraft = Minecraft.getInstance();
return create(minecraft);
}
public static RealmsClient create(Minecraft pMinecraft) {
String s = pMinecraft.getUser().getName();
String s1 = pMinecraft.getUser().getSessionId();
if (!initialized) {
initialized = true;
Optional<String> optional = Optional.ofNullable(System.getenv("realms.environment")).or(() -> {
return Optional.ofNullable(System.getProperty("realms.environment"));
});
optional.flatMap(RealmsClient.Environment::byName).ifPresent((p_289648_) -> {
currentEnvironment = p_289648_;
});
}
return new RealmsClient(s1, s, pMinecraft);
}
public static void switchToStage() {
currentEnvironment = RealmsClient.Environment.STAGE;
}
public static void switchToProd() {
currentEnvironment = RealmsClient.Environment.PRODUCTION;
}
public static void switchToLocal() {
currentEnvironment = RealmsClient.Environment.LOCAL;
}
public RealmsClient(String pSessionId, String pUsername, Minecraft pMinecraft) {
this.sessionId = pSessionId;
this.username = pUsername;
this.minecraft = pMinecraft;
RealmsClientConfig.setProxy(pMinecraft.getProxy());
}
public RealmsServerList listWorlds() throws RealmsServiceException {
String s = this.url("worlds");
String s1 = this.execute(Request.get(s));
return RealmsServerList.parse(s1);
}
public List<RealmsNotification> getNotifications() throws RealmsServiceException {
String s = this.url("notifications");
String s1 = this.execute(Request.get(s));
List<RealmsNotification> list = RealmsNotification.parseList(s1);
return list.size() > 1 ? List.of(list.get(0)) : list;
}
private static JsonArray uuidListToJsonArray(List<UUID> pUuidList) {
JsonArray jsonarray = new JsonArray();
for(UUID uuid : pUuidList) {
if (uuid != null) {
jsonarray.add(uuid.toString());
}
}
return jsonarray;
}
public void notificationsSeen(List<UUID> pUuidList) throws RealmsServiceException {
String s = this.url("notifications/seen");
this.execute(Request.post(s, GSON.toJson(uuidListToJsonArray(pUuidList))));
}
public void notificationsDismiss(List<UUID> pUuidList) throws RealmsServiceException {
String s = this.url("notifications/dismiss");
this.execute(Request.post(s, GSON.toJson(uuidListToJsonArray(pUuidList))));
}
public RealmsServer getOwnWorld(long pServerId) throws RealmsServiceException {
String s = this.url("worlds" + "/$ID".replace("$ID", String.valueOf(pServerId)));
String s1 = this.execute(Request.get(s));
return RealmsServer.parse(s1);
}
public ServerActivityList getActivity(long pWorldId) throws RealmsServiceException {
String s = this.url("activities" + "/$WORLD_ID".replace("$WORLD_ID", String.valueOf(pWorldId)));
String s1 = this.execute(Request.get(s));
return ServerActivityList.parse(s1);
}
public RealmsServerPlayerLists getLiveStats() throws RealmsServiceException {
String s = this.url("activities/liveplayerlist");
String s1 = this.execute(Request.get(s));
return RealmsServerPlayerLists.parse(s1);
}
public RealmsServerAddress join(long pServerId) throws RealmsServiceException {
String s = this.url("worlds" + "/v1/$ID/join/pc".replace("$ID", "" + pServerId));
String s1 = this.execute(Request.get(s, 5000, 30000));
return RealmsServerAddress.parse(s1);
}
public void initializeWorld(long pWorldId, String pName, String pDescription) throws RealmsServiceException {
RealmsDescriptionDto realmsdescriptiondto = new RealmsDescriptionDto(pName, pDescription);
String s = this.url("worlds" + "/$WORLD_ID/initialize".replace("$WORLD_ID", String.valueOf(pWorldId)));
String s1 = GSON.toJson(realmsdescriptiondto);
this.execute(Request.post(s, s1, 5000, 10000));
}
public Boolean mcoEnabled() throws RealmsServiceException {
String s = this.url("mco/available");
String s1 = this.execute(Request.get(s));
return Boolean.valueOf(s1);
}
public Boolean stageAvailable() throws RealmsServiceException {
String s = this.url("mco/stageAvailable");
String s1 = this.execute(Request.get(s));
return Boolean.valueOf(s1);
}
public RealmsClient.CompatibleVersionResponse clientCompatible() throws RealmsServiceException {
String s = this.url("mco/client/compatible");
String s1 = this.execute(Request.get(s));
try {
return RealmsClient.CompatibleVersionResponse.valueOf(s1);
} catch (IllegalArgumentException illegalargumentexception) {
throw new RealmsServiceException(500, "Could not check compatible version, got response: " + s1);
}
}
public void uninvite(long pWorldId, String pUuid) throws RealmsServiceException {
String s = this.url("invites" + "/$WORLD_ID/invite/$UUID".replace("$WORLD_ID", String.valueOf(pWorldId)).replace("$UUID", pUuid));
this.execute(Request.delete(s));
}
public void uninviteMyselfFrom(long pWorldId) throws RealmsServiceException {
String s = this.url("invites" + "/$WORLD_ID".replace("$WORLD_ID", String.valueOf(pWorldId)));
this.execute(Request.delete(s));
}
public RealmsServer invite(long pWorldId, String pPlayerName) throws RealmsServiceException {
PlayerInfo playerinfo = new PlayerInfo();
playerinfo.setName(pPlayerName);
String s = this.url("invites" + "/$WORLD_ID".replace("$WORLD_ID", String.valueOf(pWorldId)));
String s1 = this.execute(Request.post(s, GSON.toJson(playerinfo)));
return RealmsServer.parse(s1);
}
public BackupList backupsFor(long pWorldId) throws RealmsServiceException {
String s = this.url("worlds" + "/$WORLD_ID/backups".replace("$WORLD_ID", String.valueOf(pWorldId)));
String s1 = this.execute(Request.get(s));
return BackupList.parse(s1);
}
public void update(long pWorldId, String pName, String pDescription) throws RealmsServiceException {
RealmsDescriptionDto realmsdescriptiondto = new RealmsDescriptionDto(pName, pDescription);
String s = this.url("worlds" + "/$WORLD_ID".replace("$WORLD_ID", String.valueOf(pWorldId)));
this.execute(Request.post(s, GSON.toJson(realmsdescriptiondto)));
}
public void updateSlot(long pWorldId, int pSlotId, RealmsWorldOptions pWorldOptions) throws RealmsServiceException {
String s = this.url("worlds" + "/$WORLD_ID/slot/$SLOT_ID".replace("$WORLD_ID", String.valueOf(pWorldId)).replace("$SLOT_ID", String.valueOf(pSlotId)));
String s1 = pWorldOptions.toJson();
this.execute(Request.post(s, s1));
}
public boolean switchSlot(long pWorldId, int pSlotId) throws RealmsServiceException {
String s = this.url("worlds" + "/$WORLD_ID/slot/$SLOT_ID".replace("$WORLD_ID", String.valueOf(pWorldId)).replace("$SLOT_ID", String.valueOf(pSlotId)));
String s1 = this.execute(Request.put(s, ""));
return Boolean.valueOf(s1);
}
public void restoreWorld(long pWorldId, String pBackupId) throws RealmsServiceException {
String s = this.url("worlds" + "/$WORLD_ID/backups".replace("$WORLD_ID", String.valueOf(pWorldId)), "backupId=" + pBackupId);
this.execute(Request.put(s, "", 40000, 600000));
}
public WorldTemplatePaginatedList fetchWorldTemplates(int pPage, int pPageSize, RealmsServer.WorldType pWorldType) throws RealmsServiceException {
String s = this.url("worlds" + "/templates/$WORLD_TYPE".replace("$WORLD_TYPE", pWorldType.toString()), String.format(Locale.ROOT, "page=%d&pageSize=%d", pPage, pPageSize));
String s1 = this.execute(Request.get(s));
return WorldTemplatePaginatedList.parse(s1);
}
public Boolean putIntoMinigameMode(long pWorldId, String pMinigameId) throws RealmsServiceException {
String s = "/minigames/$MINIGAME_ID/$WORLD_ID".replace("$MINIGAME_ID", pMinigameId).replace("$WORLD_ID", String.valueOf(pWorldId));
String s1 = this.url("worlds" + s);
return Boolean.valueOf(this.execute(Request.put(s1, "")));
}
public Ops op(long pWorldId, String pProfileUuid) throws RealmsServiceException {
String s = "/$WORLD_ID/$PROFILE_UUID".replace("$WORLD_ID", String.valueOf(pWorldId)).replace("$PROFILE_UUID", pProfileUuid);
String s1 = this.url("ops" + s);
return Ops.parse(this.execute(Request.post(s1, "")));
}
public Ops deop(long pWorldId, String pProfileUuid) throws RealmsServiceException {
String s = "/$WORLD_ID/$PROFILE_UUID".replace("$WORLD_ID", String.valueOf(pWorldId)).replace("$PROFILE_UUID", pProfileUuid);
String s1 = this.url("ops" + s);
return Ops.parse(this.execute(Request.delete(s1)));
}
public Boolean open(long pWorldId) throws RealmsServiceException {
String s = this.url("worlds" + "/$WORLD_ID/open".replace("$WORLD_ID", String.valueOf(pWorldId)));
String s1 = this.execute(Request.put(s, ""));
return Boolean.valueOf(s1);
}
public Boolean close(long pWorldId) throws RealmsServiceException {
String s = this.url("worlds" + "/$WORLD_ID/close".replace("$WORLD_ID", String.valueOf(pWorldId)));
String s1 = this.execute(Request.put(s, ""));
return Boolean.valueOf(s1);
}
public Boolean resetWorldWithSeed(long pWorldId, WorldGenerationInfo pGenerationInfo) throws RealmsServiceException {
RealmsWorldResetDto realmsworldresetdto = new RealmsWorldResetDto(pGenerationInfo.getSeed(), -1L, pGenerationInfo.getLevelType().getDtoIndex(), pGenerationInfo.shouldGenerateStructures());
String s = this.url("worlds" + "/$WORLD_ID/reset".replace("$WORLD_ID", String.valueOf(pWorldId)));
String s1 = this.execute(Request.post(s, GSON.toJson(realmsworldresetdto), 30000, 80000));
return Boolean.valueOf(s1);
}
public Boolean resetWorldWithTemplate(long pWorldId, String pWorldTemplateId) throws RealmsServiceException {
RealmsWorldResetDto realmsworldresetdto = new RealmsWorldResetDto((String)null, Long.valueOf(pWorldTemplateId), -1, false);
String s = this.url("worlds" + "/$WORLD_ID/reset".replace("$WORLD_ID", String.valueOf(pWorldId)));
String s1 = this.execute(Request.post(s, GSON.toJson(realmsworldresetdto), 30000, 80000));
return Boolean.valueOf(s1);
}
public Subscription subscriptionFor(long pWorldId) throws RealmsServiceException {
String s = this.url("subscriptions" + "/$WORLD_ID".replace("$WORLD_ID", String.valueOf(pWorldId)));
String s1 = this.execute(Request.get(s));
return Subscription.parse(s1);
}
public int pendingInvitesCount() throws RealmsServiceException {
return this.pendingInvites().pendingInvites.size();
}
public PendingInvitesList pendingInvites() throws RealmsServiceException {
String s = this.url("invites/pending");
String s1 = this.execute(Request.get(s));
PendingInvitesList pendinginviteslist = PendingInvitesList.parse(s1);
pendinginviteslist.pendingInvites.removeIf(this::isBlocked);
return pendinginviteslist;
}
private boolean isBlocked(PendingInvite p_87198_) {
try {
UUID uuid = UUID.fromString(p_87198_.worldOwnerUuid);
return this.minecraft.getPlayerSocialManager().isBlocked(uuid);
} catch (IllegalArgumentException illegalargumentexception) {
return false;
}
}
public void acceptInvitation(String pInviteId) throws RealmsServiceException {
String s = this.url("invites" + "/accept/$INVITATION_ID".replace("$INVITATION_ID", pInviteId));
this.execute(Request.put(s, ""));
}
public WorldDownload requestDownloadInfo(long pWorldId, int pSlotId) throws RealmsServiceException {
String s = this.url("worlds" + "/$WORLD_ID/slot/$SLOT_ID/download".replace("$WORLD_ID", String.valueOf(pWorldId)).replace("$SLOT_ID", String.valueOf(pSlotId)));
String s1 = this.execute(Request.get(s));
return WorldDownload.parse(s1);
}
@Nullable
public UploadInfo requestUploadInfo(long pWorldId, @Nullable String pToken) throws RealmsServiceException {
String s = this.url("worlds" + "/$WORLD_ID/backups/upload".replace("$WORLD_ID", String.valueOf(pWorldId)));
return UploadInfo.parse(this.execute(Request.put(s, UploadInfo.createRequest(pToken))));
}
public void rejectInvitation(String pInviteId) throws RealmsServiceException {
String s = this.url("invites" + "/reject/$INVITATION_ID".replace("$INVITATION_ID", pInviteId));
this.execute(Request.put(s, ""));
}
public void agreeToTos() throws RealmsServiceException {
String s = this.url("mco/tos/agreed");
this.execute(Request.post(s, ""));
}
public RealmsNews getNews() throws RealmsServiceException {
String s = this.url("mco/v1/news");
String s1 = this.execute(Request.get(s, 5000, 10000));
return RealmsNews.parse(s1);
}
public void sendPingResults(PingResult pPingResult) throws RealmsServiceException {
String s = this.url("regions/ping/stat");
this.execute(Request.post(s, GSON.toJson(pPingResult)));
}
public Boolean trialAvailable() throws RealmsServiceException {
String s = this.url("trial");
String s1 = this.execute(Request.get(s));
return Boolean.valueOf(s1);
}
public void deleteWorld(long pWorldId) throws RealmsServiceException {
String s = this.url("worlds" + "/$WORLD_ID".replace("$WORLD_ID", String.valueOf(pWorldId)));
this.execute(Request.delete(s));
}
private String url(String pPath) {
return this.url(pPath, (String)null);
}
private String url(String pPath, @Nullable String pQuery) {
try {
return (new URI(currentEnvironment.protocol, currentEnvironment.baseUrl, "/" + pPath, pQuery, (String)null)).toASCIIString();
} catch (URISyntaxException urisyntaxexception) {
throw new IllegalArgumentException(pPath, urisyntaxexception);
}
}
private String execute(Request<?> pRequest) throws RealmsServiceException {
pRequest.cookie("sid", this.sessionId);
pRequest.cookie("user", this.username);
pRequest.cookie("version", SharedConstants.getCurrentVersion().getName());
try {
int i = pRequest.responseCode();
if (i != 503 && i != 277) {
String s1 = pRequest.text();
if (i >= 200 && i < 300) {
return s1;
} else if (i == 401) {
String s2 = pRequest.getHeader("WWW-Authenticate");
LOGGER.info("Could not authorize you against Realms server: {}", (Object)s2);
throw new RealmsServiceException(i, s2);
} else {
RealmsError realmserror = RealmsError.parse(s1);
if (realmserror != null) {
LOGGER.error("Realms http code: {} - error code: {} - message: {} - raw body: {}", i, realmserror.getErrorCode(), realmserror.getErrorMessage(), s1);
throw new RealmsServiceException(i, s1, realmserror);
} else {
LOGGER.error("Realms http code: {} - raw body (message failed to parse): {}", i, s1);
String s = getHttpCodeDescription(i);
throw new RealmsServiceException(i, s);
}
}
} else {
int j = pRequest.getRetryAfterHeader();
throw new RetryCallException(j, i);
}
} catch (RealmsHttpException realmshttpexception) {
throw new RealmsServiceException(500, "Could not connect to Realms: " + realmshttpexception.getMessage());
}
}
private static String getHttpCodeDescription(int pHttpCode) {
String s;
switch (pHttpCode) {
case 429:
s = I18n.get("mco.errorMessage.serviceBusy");
break;
default:
s = "Unknown error";
}
return s;
}
@OnlyIn(Dist.CLIENT)
public static enum CompatibleVersionResponse {
COMPATIBLE,
OUTDATED,
OTHER;
}
@OnlyIn(Dist.CLIENT)
public static enum Environment {
PRODUCTION("pc.realms.minecraft.net", "https"),
STAGE("pc-stage.realms.minecraft.net", "https"),
LOCAL("localhost:8080", "http");
public String baseUrl;
public String protocol;
private Environment(String pBaseUrl, String pProtocol) {
this.baseUrl = pBaseUrl;
this.protocol = pProtocol;
}
public static Optional<RealmsClient.Environment> byName(String pName) {
Optional optional;
switch (pName.toLowerCase(Locale.ROOT)) {
case "production":
optional = Optional.of(PRODUCTION);
break;
case "local":
optional = Optional.of(LOCAL);
break;
case "stage":
optional = Optional.of(STAGE);
break;
default:
optional = Optional.empty();
}
return optional;
}
}
}
@@ -0,0 +1,24 @@
package com.mojang.realmsclient.client;
import java.net.Proxy;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class RealmsClientConfig {
@Nullable
private static Proxy proxy;
@Nullable
public static Proxy getProxy() {
return proxy;
}
public static void setProxy(Proxy pProxy) {
if (proxy == null) {
proxy = pProxy;
}
}
}
@@ -0,0 +1,49 @@
package com.mojang.realmsclient.client;
import com.google.common.base.Strings;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.mojang.logging.LogUtils;
import com.mojang.realmsclient.util.JsonUtils;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.slf4j.Logger;
@OnlyIn(Dist.CLIENT)
public class RealmsError {
private static final Logger LOGGER = LogUtils.getLogger();
private final String errorMessage;
private final int errorCode;
private RealmsError(String pErrorMessage, int pErrorCode) {
this.errorMessage = pErrorMessage;
this.errorCode = pErrorCode;
}
@Nullable
public static RealmsError parse(String pError) {
if (Strings.isNullOrEmpty(pError)) {
return null;
} else {
try {
JsonObject jsonobject = JsonParser.parseString(pError).getAsJsonObject();
String s = JsonUtils.getStringOr("errorMsg", jsonobject, "");
int i = JsonUtils.getIntOr("errorCode", jsonobject, -1);
return new RealmsError(s, i);
} catch (Exception exception) {
LOGGER.error("Could not parse RealmsError: {}", (Object)exception.getMessage());
LOGGER.error("The error was: {}", (Object)pError);
return null;
}
}
}
public String getErrorMessage() {
return this.errorMessage;
}
public int getErrorCode() {
return this.errorCode;
}
}
@@ -0,0 +1,301 @@
package com.mojang.realmsclient.client;
import com.mojang.realmsclient.exception.RealmsHttpException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.Proxy;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import javax.annotation.Nullable;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public abstract class Request<T extends Request<T>> {
protected HttpURLConnection connection;
private boolean connected;
protected String url;
private static final int DEFAULT_READ_TIMEOUT = 60000;
private static final int DEFAULT_CONNECT_TIMEOUT = 5000;
public Request(String pUrl, int pConnectTimeout, int pReadTimeout) {
try {
this.url = pUrl;
Proxy proxy = RealmsClientConfig.getProxy();
if (proxy != null) {
this.connection = (HttpURLConnection)(new URL(pUrl)).openConnection(proxy);
} else {
this.connection = (HttpURLConnection)(new URL(pUrl)).openConnection();
}
this.connection.setConnectTimeout(pConnectTimeout);
this.connection.setReadTimeout(pReadTimeout);
} catch (MalformedURLException malformedurlexception) {
throw new RealmsHttpException(malformedurlexception.getMessage(), malformedurlexception);
} catch (IOException ioexception) {
throw new RealmsHttpException(ioexception.getMessage(), ioexception);
}
}
public void cookie(String pKey, String pValue) {
cookie(this.connection, pKey, pValue);
}
public static void cookie(HttpURLConnection pConnection, String pKey, String pValue) {
String s = pConnection.getRequestProperty("Cookie");
if (s == null) {
pConnection.setRequestProperty("Cookie", pKey + "=" + pValue);
} else {
pConnection.setRequestProperty("Cookie", s + ";" + pKey + "=" + pValue);
}
}
public T header(String pException, String p_167287_) {
this.connection.addRequestProperty(pException, p_167287_);
return (T)this;
}
public int getRetryAfterHeader() {
return getRetryAfterHeader(this.connection);
}
public static int getRetryAfterHeader(HttpURLConnection pConnection) {
String s = pConnection.getHeaderField("Retry-After");
try {
return Integer.valueOf(s);
} catch (Exception exception) {
return 5;
}
}
public int responseCode() {
try {
this.connect();
return this.connection.getResponseCode();
} catch (Exception exception) {
throw new RealmsHttpException(exception.getMessage(), exception);
}
}
public String text() {
try {
this.connect();
String s;
if (this.responseCode() >= 400) {
s = this.read(this.connection.getErrorStream());
} else {
s = this.read(this.connection.getInputStream());
}
this.dispose();
return s;
} catch (IOException ioexception) {
throw new RealmsHttpException(ioexception.getMessage(), ioexception);
}
}
private String read(@Nullable InputStream p_87315_) throws IOException {
if (p_87315_ == null) {
return "";
} else {
InputStreamReader inputstreamreader = new InputStreamReader(p_87315_, StandardCharsets.UTF_8);
StringBuilder stringbuilder = new StringBuilder();
for(int i = inputstreamreader.read(); i != -1; i = inputstreamreader.read()) {
stringbuilder.append((char)i);
}
return stringbuilder.toString();
}
}
private void dispose() {
byte[] abyte = new byte[1024];
try {
InputStream inputstream = this.connection.getInputStream();
while(inputstream.read(abyte) > 0) {
}
inputstream.close();
return;
} catch (Exception exception) {
try {
InputStream inputstream1 = this.connection.getErrorStream();
if (inputstream1 != null) {
while(inputstream1.read(abyte) > 0) {
}
inputstream1.close();
return;
}
} catch (IOException ioexception) {
return;
}
} finally {
if (this.connection != null) {
this.connection.disconnect();
}
}
}
protected T connect() {
if (this.connected) {
return (T)this;
} else {
T t = this.doConnect();
this.connected = true;
return t;
}
}
protected abstract T doConnect();
public static Request<?> get(String pUrl) {
return new Request.Get(pUrl, 5000, 60000);
}
public static Request<?> get(String pUrl, int pConnectTimeout, int pReadTimeout) {
return new Request.Get(pUrl, pConnectTimeout, pReadTimeout);
}
public static Request<?> post(String pUrl, String pContent) {
return new Request.Post(pUrl, pContent, 5000, 60000);
}
public static Request<?> post(String pUrl, String pContent, int pConnectTimeout, int pReadTimeout) {
return new Request.Post(pUrl, pContent, pConnectTimeout, pReadTimeout);
}
public static Request<?> delete(String pUrl) {
return new Request.Delete(pUrl, 5000, 60000);
}
public static Request<?> put(String pUrl, String pContent) {
return new Request.Put(pUrl, pContent, 5000, 60000);
}
public static Request<?> put(String pUrl, String pContent, int pConnectTimeout, int pReadTimeout) {
return new Request.Put(pUrl, pContent, pConnectTimeout, pReadTimeout);
}
public String getHeader(String pName) {
return getHeader(this.connection, pName);
}
public static String getHeader(HttpURLConnection pConnection, String pName) {
try {
return pConnection.getHeaderField(pName);
} catch (Exception exception) {
return "";
}
}
@OnlyIn(Dist.CLIENT)
public static class Delete extends Request<Request.Delete> {
public Delete(String p_87359_, int p_87360_, int p_87361_) {
super(p_87359_, p_87360_, p_87361_);
}
public Request.Delete doConnect() {
try {
this.connection.setDoOutput(true);
this.connection.setRequestMethod("DELETE");
this.connection.connect();
return this;
} catch (Exception exception) {
throw new RealmsHttpException(exception.getMessage(), exception);
}
}
}
@OnlyIn(Dist.CLIENT)
public static class Get extends Request<Request.Get> {
public Get(String p_87365_, int p_87366_, int p_87367_) {
super(p_87365_, p_87366_, p_87367_);
}
public Request.Get doConnect() {
try {
this.connection.setDoInput(true);
this.connection.setDoOutput(true);
this.connection.setUseCaches(false);
this.connection.setRequestMethod("GET");
return this;
} catch (Exception exception) {
throw new RealmsHttpException(exception.getMessage(), exception);
}
}
}
@OnlyIn(Dist.CLIENT)
public static class Post extends Request<Request.Post> {
private final String content;
public Post(String pUrl, String pContent, int pConnectTimeout, int pReadTimeout) {
super(pUrl, pConnectTimeout, pReadTimeout);
this.content = pContent;
}
public Request.Post doConnect() {
try {
if (this.content != null) {
this.connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
}
this.connection.setDoInput(true);
this.connection.setDoOutput(true);
this.connection.setUseCaches(false);
this.connection.setRequestMethod("POST");
OutputStream outputstream = this.connection.getOutputStream();
OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream, "UTF-8");
outputstreamwriter.write(this.content);
outputstreamwriter.close();
outputstream.flush();
return this;
} catch (Exception exception) {
throw new RealmsHttpException(exception.getMessage(), exception);
}
}
}
@OnlyIn(Dist.CLIENT)
public static class Put extends Request<Request.Put> {
private final String content;
public Put(String pUrl, String pContent, int pConnectTimeout, int pReadTimeout) {
super(pUrl, pConnectTimeout, pReadTimeout);
this.content = pContent;
}
public Request.Put doConnect() {
try {
if (this.content != null) {
this.connection.setRequestProperty("Content-Type", "application/json; charset=utf-8");
}
this.connection.setDoOutput(true);
this.connection.setDoInput(true);
this.connection.setRequestMethod("PUT");
OutputStream outputstream = this.connection.getOutputStream();
OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream, "UTF-8");
outputstreamwriter.write(this.content);
outputstreamwriter.close();
outputstream.flush();
return this;
} catch (Exception exception) {
throw new RealmsHttpException(exception.getMessage(), exception);
}
}
}
}
Loaded 100 of 14134 files, more files were not shown because too many files have changed in this diff. Show more